/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java

https://bitbucket.org/nbargnesi/idea · Java · 251 lines · 207 code · 26 blank · 18 comment · 35 complexity · 7ea121cc4e0993c6da72380261939200 MD5 · raw file

  1. /*
  2. * Copyright 2000-2010 JetBrains s.r.o.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.jetbrains.android.compiler;
  17. import com.intellij.openapi.application.ApplicationManager;
  18. import com.intellij.openapi.compiler.*;
  19. import com.intellij.openapi.compiler.ex.CompileContextEx;
  20. import com.intellij.openapi.module.Module;
  21. import com.intellij.openapi.module.ModuleManager;
  22. import com.intellij.openapi.util.Computable;
  23. import com.intellij.openapi.util.io.FileUtil;
  24. import com.intellij.openapi.vfs.LocalFileSystem;
  25. import com.intellij.openapi.vfs.VirtualFile;
  26. import org.jetbrains.android.compiler.tools.AndroidMavenExecutor;
  27. import org.jetbrains.android.dom.manifest.Manifest;
  28. import org.jetbrains.android.facet.AndroidFacet;
  29. import org.jetbrains.android.facet.AndroidRootUtil;
  30. import org.jetbrains.android.maven.AndroidMavenProvider;
  31. import org.jetbrains.android.maven.AndroidMavenUtil;
  32. import org.jetbrains.android.util.AndroidCommonUtils;
  33. import org.jetbrains.annotations.NotNull;
  34. import org.jetbrains.annotations.Nullable;
  35. import org.jetbrains.idea.maven.project.MavenProject;
  36. import org.jetbrains.idea.maven.project.MavenProjectsManager;
  37. import java.io.DataInput;
  38. import java.io.DataOutput;
  39. import java.io.File;
  40. import java.io.IOException;
  41. import java.util.ArrayList;
  42. import java.util.Arrays;
  43. import java.util.List;
  44. import java.util.Map;
  45. /**
  46. * @author Eugene.Kudelevsky
  47. */
  48. public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler {
  49. private static final GenerationItem[] EMPTY_GENERATION_ITEM_ARRAY = {};
  50. @Override
  51. public VirtualFile getPresentableFile(CompileContext context, Module module, VirtualFile outputRoot, VirtualFile generatedFile) {
  52. return null;
  53. }
  54. public GenerationItem[] getGenerationItems(CompileContext context) {
  55. return ApplicationManager.getApplication().runReadAction(new PrepareAction(context));
  56. }
  57. public GenerationItem[] generate(final CompileContext context, final GenerationItem[] items, VirtualFile outputRootDirectory) {
  58. if (items != null && items.length > 0) {
  59. context.getProgressIndicator().setText("Processing resources by Maven...");
  60. Computable<GenerationItem[]> computation = new Computable<GenerationItem[]>() {
  61. public GenerationItem[] compute() {
  62. if (context.getProject().isDisposed()) {
  63. return EMPTY_GENERATION_ITEM_ARRAY;
  64. }
  65. return doGenerate(context, items);
  66. }
  67. };
  68. GenerationItem[] generationItems = computation.compute();
  69. List<VirtualFile> generatedVFiles = new ArrayList<VirtualFile>();
  70. for (GenerationItem item : generationItems) {
  71. File generatedFile = ((MyGenerationItem)item).myGeneratedFile;
  72. if (generatedFile != null) {
  73. final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(generatedFile);
  74. if (vFile != null) {
  75. AndroidCompileUtil.markDirtyAndRefresh(vFile, false);
  76. generatedVFiles.add(vFile);
  77. }
  78. }
  79. }
  80. if (context instanceof CompileContextEx) {
  81. ((CompileContextEx)context).markGenerated(generatedVFiles);
  82. }
  83. return generationItems;
  84. }
  85. return EMPTY_GENERATION_ITEM_ARRAY;
  86. }
  87. private static GenerationItem[] doGenerate(final CompileContext context, GenerationItem[] items) {
  88. List<GenerationItem> results = new ArrayList<GenerationItem>(items.length);
  89. for (GenerationItem item : items) {
  90. if (item instanceof MyGenerationItem) {
  91. final MyGenerationItem genItem = (MyGenerationItem)item;
  92. if (!AndroidCompileUtil.isModuleAffected(context, genItem.myModule)) {
  93. continue;
  94. }
  95. Map<CompilerMessageCategory, List<String>> messages = AndroidMavenExecutor.generateResources(genItem.myModule);
  96. AndroidCompileUtil.addMessages(context, messages, genItem.myModule);
  97. if (messages.get(CompilerMessageCategory.ERROR).isEmpty()) {
  98. results.add(genItem);
  99. }
  100. if (genItem.myGeneratedFile.exists()) {
  101. ApplicationManager.getApplication().runReadAction(new Runnable() {
  102. public void run() {
  103. String className = FileUtil.getNameWithoutExtension(genItem.myGeneratedFile);
  104. AndroidCompileUtil.removeDuplicatingClasses(genItem.myModule, genItem.myPackage, className, genItem.myGeneratedFile,
  105. genItem.mySourceRootPath);
  106. }
  107. });
  108. }
  109. }
  110. }
  111. return results.toArray(new GenerationItem[results.size()]);
  112. }
  113. @NotNull
  114. public String getDescription() {
  115. return "Android Maven Resources Compiler";
  116. }
  117. public boolean validateConfiguration(CompileScope scope) {
  118. return true;
  119. }
  120. public ValidityState createValidityState(DataInput is) throws IOException {
  121. return new MyValidityState(is);
  122. }
  123. private final static class MyGenerationItem implements GenerationItem {
  124. final Module myModule;
  125. final String myPackage;
  126. final File myGeneratedFile;
  127. final String mySourceRootPath;
  128. private final MyValidityState myValidityState;
  129. private MyGenerationItem(@NotNull Module module, @NotNull String aPackage, @NotNull String sourceRootPath) {
  130. myModule = module;
  131. myPackage = aPackage;
  132. myGeneratedFile =
  133. new File(sourceRootPath, aPackage.replace('.', File.separatorChar) + File.separator + AndroidCommonUtils.R_JAVA_FILENAME);
  134. mySourceRootPath = sourceRootPath;
  135. myValidityState = new MyValidityState(myModule);
  136. }
  137. @Nullable
  138. public String getPath() {
  139. return myPackage.replace('.', '/') + '/' + AndroidCommonUtils.R_JAVA_FILENAME;
  140. }
  141. public ValidityState getValidityState() {
  142. return myValidityState;
  143. }
  144. public Module getModule() {
  145. return myModule;
  146. }
  147. public boolean isTestSource() {
  148. return false;
  149. }
  150. }
  151. private static class MyValidityState extends ResourceNamesValidityState {
  152. private final long[] myMavenArtifactsTimespamps;
  153. private MyValidityState(Module module) {
  154. super(module);
  155. AndroidMavenProvider mavenProvider = AndroidMavenUtil.getMavenProvider();
  156. assert mavenProvider != null;
  157. List<File> files = mavenProvider.getMavenDependencyArtifactFiles(module);
  158. myMavenArtifactsTimespamps = new long[files.size()];
  159. for (int i = 0, filesSize = files.size(); i < filesSize; i++) {
  160. myMavenArtifactsTimespamps[i] = files.get(i).lastModified();
  161. }
  162. }
  163. public MyValidityState(DataInput is) throws IOException {
  164. super(is);
  165. int c = is.readInt();
  166. myMavenArtifactsTimespamps = new long[c];
  167. for (int i = 0; i < c; i++) {
  168. myMavenArtifactsTimespamps[i] = is.readLong();
  169. }
  170. }
  171. @Override
  172. public boolean equalsTo(ValidityState otherState) {
  173. if (!super.equalsTo(otherState)) {
  174. return false;
  175. }
  176. if (!(otherState instanceof MyValidityState)) {
  177. return false;
  178. }
  179. return Arrays.equals(myMavenArtifactsTimespamps, ((MyValidityState)otherState).myMavenArtifactsTimespamps);
  180. }
  181. @Override
  182. public void save(DataOutput out) throws IOException {
  183. super.save(out);
  184. out.writeInt(myMavenArtifactsTimespamps.length);
  185. for (long timespamp : myMavenArtifactsTimespamps) {
  186. out.writeLong(timespamp);
  187. }
  188. }
  189. }
  190. private static final class PrepareAction implements Computable<GenerationItem[]> {
  191. private final CompileContext myContext;
  192. public PrepareAction(CompileContext context) {
  193. myContext = context;
  194. }
  195. public GenerationItem[] compute() {
  196. if (myContext.getProject().isDisposed()) {
  197. return EMPTY_GENERATION_ITEM_ARRAY;
  198. }
  199. Module[] modules = ModuleManager.getInstance(myContext.getProject()).getModules();
  200. List<GenerationItem> items = new ArrayList<GenerationItem>();
  201. for (Module module : modules) {
  202. MavenProjectsManager mavenProjectsManager = MavenProjectsManager.getInstance(myContext.getProject());
  203. if (mavenProjectsManager != null && mavenProjectsManager.isMavenizedModule(module)) {
  204. AndroidFacet facet = AndroidFacet.getInstance(module);
  205. if (facet != null && facet.getConfiguration().RUN_PROCESS_RESOURCES_MAVEN_TASK) {
  206. MavenProject mavenProject = mavenProjectsManager.findProject(module);
  207. if (mavenProject != null) {
  208. Manifest manifest = facet.getManifest();
  209. String aPackage = manifest != null ? manifest.getPackage().getValue() : null;
  210. if (aPackage == null) {
  211. VirtualFile manifestFile = AndroidRootUtil.getManifestFile(facet);
  212. myContext.addMessage(CompilerMessageCategory.ERROR,
  213. "Cannot find package value in AndroidManifest.xml for module " + module.getName(),
  214. manifestFile != null ? manifestFile.getUrl() : null, -1, -1);
  215. continue;
  216. }
  217. items.add(new MyGenerationItem(module, aPackage, mavenProject.getGeneratedSourcesDirectory(false) + "/r"));
  218. }
  219. }
  220. }
  221. }
  222. return items.toArray(new GenerationItem[items.size()]);
  223. }
  224. }
  225. }