1 /* 2 * Copyright (C) 2012 The Android Open Source Project 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 17 package com.android.idegen; 18 19 import com.google.common.base.Objects; 20 import com.google.common.collect.ImmutableList; 21 import com.google.common.collect.Sets; 22 import com.google.common.io.Files; 23 24 import java.io.File; 25 import java.io.IOException; 26 import java.util.List; 27 import java.util.Set; 28 import java.util.logging.Logger; 29 30 /** 31 * Super class for all modules. 32 */ 33 public abstract class Module { 34 35 private static final Logger logger = Logger.getLogger(Module.class.getName()); 36 37 /** 38 * All possible attributes for the make file. 39 */ 40 protected enum Key { 41 LOCAL_STATIC_JAVA_LIBRARIES, 42 LOCAL_JAVA_LIBRARIES, 43 LOCAL_SRC_FILES 44 } 45 46 ModuleCache moduleCache = ModuleCache.getInstance(); 47 private File imlFile; 48 private Set<String> allDependencies = Sets.newHashSet(); // direct + indirect 49 private Set<File> allDependentImlFiles = Sets.newHashSet(); 50 build()51 protected abstract void build() throws IOException; getName()52 protected abstract String getName(); getDir()53 protected abstract File getDir(); isAndroidModule()54 protected abstract boolean isAndroidModule(); getIntermediatesDirs()55 protected abstract List<File> getIntermediatesDirs(); getDirectDependencies()56 public abstract Set<String> getDirectDependencies(); getSourceDirs()57 protected abstract ImmutableList<File> getSourceDirs(); getExcludeDirs()58 protected abstract ImmutableList<File> getExcludeDirs(); getRepoRoot()59 public abstract File getRepoRoot(); 60 buildImlFile()61 public void buildImlFile() throws IOException { 62 String imlTemplate = Files.toString(new File(getRepoRoot(), Constants.REL_IML_TEMPLATE), 63 Constants.CHARSET); 64 65 String facetXml = ""; 66 if (isAndroidModule()) { 67 facetXml = buildAndroidFacet(); 68 } 69 imlTemplate = imlTemplate.replace("@FACETS@", facetXml); 70 71 String moduleDir = getDir().getAbsolutePath(); 72 73 StringBuilder sourceDirectories = new StringBuilder(); 74 sourceDirectories.append(" <content url=\"file://$MODULE_DIR$\">\n"); 75 ImmutableList<File> srcDirs = getSourceDirs(); 76 for (File src : srcDirs) { 77 String relative = src.getAbsolutePath().substring(moduleDir.length()); 78 sourceDirectories.append(" <sourceFolder url=\"file://$MODULE_DIR$") 79 .append(relative).append("\" isTestSource=\"false\" />\n"); 80 } 81 ImmutableList<File> excludeDirs = getExcludeDirs(); 82 for (File src : excludeDirs) { 83 String relative = src.getAbsolutePath().substring(moduleDir.length()); 84 sourceDirectories.append(" <excludeFolder url=\"file://$MODULE_DIR$") 85 .append(relative).append("\"/>\n"); 86 } 87 sourceDirectories.append(" </content>\n"); 88 89 // Intermediates. 90 sourceDirectories.append(buildIntermediates()); 91 92 imlTemplate = imlTemplate.replace("@SOURCES@", sourceDirectories.toString()); 93 94 StringBuilder moduleDependencies = new StringBuilder(); 95 for (String dependency : getDirectDependencies()) { 96 moduleDependencies.append(" <orderEntry type=\"module\" module-name=\"") 97 .append(dependency).append("\" />\n"); 98 } 99 imlTemplate = imlTemplate.replace("@MODULE_DEPENDENCIES@", moduleDependencies.toString()); 100 101 imlFile = new File(moduleDir, getName() + ".iml"); 102 logger.info("Creating " + imlFile.getAbsolutePath()); 103 Files.write(imlTemplate, imlFile, Constants.CHARSET); 104 } 105 buildIntermediates()106 protected String buildIntermediates() { 107 StringBuilder sb = new StringBuilder(); 108 for (File intermediatesDir : getIntermediatesDirs()) { 109 sb.append(" <content url=\"file://").append(intermediatesDir).append("\">\n"); 110 sb.append(" <sourceFolder url=\"file://") 111 .append(intermediatesDir.getAbsolutePath()) 112 .append("\" isTestSource=\"false\" />\n"); 113 sb.append(" </content>\n"); 114 } 115 return sb.toString(); 116 } 117 buildDependentModules()118 protected void buildDependentModules() throws IOException { 119 Set<String> directDependencies = getDirectDependencies(); 120 String[] copy = directDependencies.toArray(new String[directDependencies.size()]); 121 for (String dependency : copy) { 122 123 Module child = moduleCache.getAndCache(dependency); 124 if (child == null) { 125 directDependencies.remove(dependency); 126 } else { 127 addAllDependencies(dependency); 128 addAllDependencies(child.getAllDependencies()); 129 //logger.info("Adding iml " + child.getName() + " " + child.getImlFile()); 130 allDependentImlFiles.add(child.getImlFile()); 131 allDependentImlFiles.addAll(child.getAllDependentImlFiles()); 132 } 133 } 134 } 135 getImlFile()136 public File getImlFile() { 137 return imlFile; 138 } 139 getAllDependencies()140 public Set<String> getAllDependencies() { 141 return allDependencies; 142 } 143 addAllDependencies(String dependency)144 public void addAllDependencies(String dependency) { 145 this.allDependencies.add(dependency); 146 } 147 addAllDependencies(Set<String> dependencies)148 public void addAllDependencies(Set<String> dependencies) { 149 this.allDependencies.addAll(dependencies); 150 } 151 getAllDependentImlFiles()152 public Set<File> getAllDependentImlFiles() { 153 return allDependentImlFiles; 154 } 155 buildAndroidFacet()156 private String buildAndroidFacet() { 157 // Not sure how to handle android facet for multi-module since there could be more than 158 // one intermediates directory. 159 String dir = getIntermediatesDirs().get(0).getAbsolutePath(); 160 String xml = "" 161 + " <component name=\"FacetManager\">\n" 162 + " <facet type=\"android\" name=\"Android\">\n" 163 + " <configuration>\n" 164 + " <option name=\"GEN_FOLDER_RELATIVE_PATH_APT\" value=\"" + dir + "\" />\n" 165 + " <option name=\"GEN_FOLDER_RELATIVE_PATH_AIDL\" value=\"" + dir 166 + "\" />\n" 167 + " <option name=\"MANIFEST_FILE_RELATIVE_PATH\" value=\"" 168 + "/AndroidManifest.xml\" />\n" 169 + " <option name=\"RES_FOLDER_RELATIVE_PATH\" value=\"/res\" />\n" 170 + " <option name=\"ASSETS_FOLDER_RELATIVE_PATH\" value=\"/assets\" />\n" 171 + " <option name=\"LIBS_FOLDER_RELATIVE_PATH\" value=\"/libs\" />\n" 172 + " <option name=\"REGENERATE_R_JAVA\" value=\"true\" />\n" 173 + " <option name=\"REGENERATE_JAVA_BY_AIDL\" value=\"true\" />\n" 174 + " <option name=\"USE_CUSTOM_APK_RESOURCE_FOLDER\" value=\"false\" />\n" 175 + " <option name=\"CUSTOM_APK_RESOURCE_FOLDER\" value=\"\" />\n" 176 + " <option name=\"USE_CUSTOM_COMPILER_MANIFEST\" value=\"false\" />\n" 177 + " <option name=\"CUSTOM_COMPILER_MANIFEST\" value=\"\" />\n" 178 + " <option name=\"APK_PATH\" value=\"\" />\n" 179 + " <option name=\"LIBRARY_PROJECT\" value=\"false\" />\n" 180 + " <option name=\"RUN_PROCESS_RESOURCES_MAVEN_TASK\" value=\"true\" />\n" 181 + " <option name=\"GENERATE_UNSIGNED_APK\" value=\"false\" />\n" 182 + " </configuration>\n" 183 + " </facet>\n" 184 + " </component>\n"; 185 return xml; 186 } 187 188 @Override toString()189 public String toString() { 190 return Objects.toStringHelper(Module.class) 191 .add("name", getName()) 192 .add("allDependencies", allDependencies) 193 .add("iml files", allDependentImlFiles) 194 .add("imlFile", imlFile) 195 .toString(); 196 } 197 } 198 199