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.Preconditions; 20 import com.google.common.collect.Sets; 21 import com.google.common.io.Files; 22 23 import java.io.File; 24 import java.io.IOException; 25 import java.nio.charset.Charset; 26 import java.util.Arrays; 27 import java.util.Set; 28 import java.util.logging.Logger; 29 30 /** 31 * Build Intellij projects. 32 */ 33 public class IntellijProject { 34 35 public static final String FRAMEWORK_MODULE = "framework"; 36 public static final Charset CHARSET = Charset.forName("UTF-8"); 37 38 private static final Logger logger = Logger.getLogger(IntellijProject.class.getName()); 39 40 private static final String MODULES_TEMPLATE_FILE_NAME = "modules.xml"; 41 private static final String VCS_TEMPLATE_FILE_NAME = "vcs.xml"; 42 43 ModuleCache cache = ModuleCache.getInstance(); 44 45 File indexFile; 46 File repoRoot; 47 File projectIdeaDir; 48 String moduleName; 49 50 public IntellijProject(String indexFile, String moduleName) { 51 this.indexFile = new File(Preconditions.checkNotNull(indexFile)); 52 this.moduleName = Preconditions.checkNotNull(moduleName); 53 } 54 55 private void init() throws IOException { 56 repoRoot = DirectorySearch.findRepoRoot(indexFile); 57 cache.init(indexFile); 58 } 59 60 public void build() throws IOException { 61 init(); 62 buildFrameWorkModule(); 63 64 // First pass, find all dependencies and cache them. 65 Module module = cache.getAndCache(moduleName); 66 if (module == null) { 67 logger.info("Module '" + moduleName + "' not found." + 68 " Module names are case senstive."); 69 return; 70 } 71 projectIdeaDir = new File(module.getDir(), ".idea"); 72 projectIdeaDir.mkdir(); 73 copyTemplates(); 74 75 // Second phase, build aggregate modules. 76 Set<String> deps = module.getAllDependencies(); 77 for (String dep : deps) { 78 cache.buildAndCacheAggregatedModule(dep); 79 } 80 81 // Third phase, replace individual modules with aggregated modules 82 Iterable<Module> modules = cache.getModules(); 83 for (Module mod : modules) { 84 replaceWithAggregate(mod); 85 } 86 87 // Finally create iml files for dependencies 88 for (Module mod : modules) { 89 mod.buildImlFile(); 90 } 91 92 createModulesFile(module); 93 createVcsFile(module); 94 createNameFile(moduleName); 95 } 96 97 private void replaceWithAggregate(Module module) { 98 replaceWithAggregate(module.getDirectDependencies(), module.getName()); 99 replaceWithAggregate(module.getAllDependencies(), module.getName()); 100 101 } 102 103 private void replaceWithAggregate(Set<String> deps, String moduleName) { 104 for (String dep : Sets.newHashSet(deps)) { 105 String replacement = cache.getAggregateReplacementName(dep); 106 if (replacement != null) { 107 108 deps.remove(dep); 109 // There could be dependencies on self due to aggregation. 110 // Only add if the replacement is not self. 111 if (!replacement.equals(moduleName)) { 112 deps.add(replacement); 113 } 114 } 115 } 116 } 117 118 /** 119 * Framework module needs special handling due to one off resource path: 120 * frameworks/base/Android.mk 121 */ 122 private void buildFrameWorkModule() throws IOException { 123 String makeFile = cache.getMakeFile(FRAMEWORK_MODULE); 124 if (makeFile == null) { 125 logger.warning("Unable to find framework module: " + FRAMEWORK_MODULE + 126 ". Skipping."); 127 } else { 128 logger.info("makefile: " + makeFile); 129 StandardModule frameworkModule = new FrameworkModule(FRAMEWORK_MODULE, 130 makeFile); 131 frameworkModule.build(); 132 cache.put(frameworkModule); 133 } 134 } 135 136 private void createModulesFile(Module module) throws IOException { 137 String modulesContent = Files.toString( 138 new File(DirectorySearch.findTemplateDir(), 139 "idea" + File.separator + MODULES_TEMPLATE_FILE_NAME), 140 CHARSET); 141 StringBuilder sb = new StringBuilder(); 142 File moduleIml = module.getImlFile(); 143 sb.append(" <module fileurl=\"file://").append(moduleIml.getAbsolutePath()) 144 .append("\" filepath=\"").append(moduleIml.getAbsolutePath()).append("\" />\n"); 145 for (String name : module.getAllDependencies()) { 146 Module mod = cache.getAndCache(name); 147 File iml = mod.getImlFile(); 148 sb.append(" <module fileurl=\"file://").append(iml.getAbsolutePath()) 149 .append("\" filepath=\"").append(iml.getAbsolutePath()).append("\" />\n"); 150 } 151 modulesContent = modulesContent.replace("@MODULES@", sb.toString()); 152 153 File out = new File(projectIdeaDir, "modules.xml"); 154 logger.info("Creating " + out.getAbsolutePath()); 155 Files.write(modulesContent, out, CHARSET); 156 } 157 158 private void createVcsFile(Module module) throws IOException { 159 String vcsTemplate = Files.toString( 160 new File(DirectorySearch.findTemplateDir(), 161 "idea" + File.separator + VCS_TEMPLATE_FILE_NAME), 162 CHARSET); 163 164 StringBuilder sb = new StringBuilder(); 165 for (String name : module.getAllDependencies()) { 166 Module mod = cache.getAndCache(name); 167 File dir = mod.getDir(); 168 File gitRoot = new File(dir, ".git"); 169 if (gitRoot.exists()) { 170 sb.append(" <mapping directory=\"").append(dir.getAbsolutePath()) 171 .append("\" vcs=\"Git\" />\n"); 172 } 173 } 174 vcsTemplate = vcsTemplate.replace("@VCS@", sb.toString()); 175 Files.write(vcsTemplate, new File(projectIdeaDir, "vcs.xml"), CHARSET); 176 } 177 178 private void createNameFile(String name) throws IOException { 179 File out = new File(projectIdeaDir, ".name"); 180 Files.write(name, out, CHARSET); 181 } 182 183 private void copyTemplates() throws IOException { 184 File templateDir = DirectorySearch.findTemplateDir(); 185 copyTemplates(new File(templateDir, "idea"), projectIdeaDir); 186 } 187 188 private void copyTemplates(File fromDir, File toDir) throws IOException { 189 toDir.mkdir(); 190 File[] files = fromDir.listFiles(); 191 for (File file : files) { 192 if (file.isDirectory()) { 193 File destDir = new File(toDir, file.getName()); 194 copyTemplates(file, destDir); 195 } else { 196 File toFile = new File(toDir, file.getName()); 197 logger.info("copying " + file.getAbsolutePath() + " to " + 198 toFile.getAbsolutePath()); 199 Files.copy(file, toFile); 200 } 201 } 202 } 203 204 public static void main(String[] args) { 205 logger.info("Args: " + Arrays.toString(args)); 206 207 String indexFile = args[0]; 208 String module = args[1]; 209 210 IntellijProject intellij = new IntellijProject(indexFile, module); 211 try { 212 intellij.build(); 213 } catch (IOException e) { 214 e.printStackTrace(); 215 } 216 } 217 } 218