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.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