Home | History | Annotate | Download | only in idegen
      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