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