• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ant;
18 
19 import com.android.annotations.NonNull;
20 import com.android.manifmerger.ICallback;
21 import com.android.manifmerger.ManifestMerger;
22 import com.android.manifmerger.MergerLog;
23 import com.android.sdklib.IAndroidTarget;
24 import com.android.sdklib.SdkManager;
25 import com.android.sdklib.io.FileOp;
26 import com.android.utils.StdLogger;
27 
28 import org.apache.tools.ant.BuildException;
29 import org.apache.tools.ant.types.Path;
30 
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 public class ManifestMergerTask extends SingleDependencyTask {
37 
38     private String mAppManifest;
39     private String mOutManifest;
40 
41     private ArrayList<Path> mLibraryPaths;
42     private boolean mEnabled = false;
43 
setAppManifest(Path appManifest)44     public void setAppManifest(Path appManifest) {
45         mAppManifest = TaskHelper.checkSinglePath("appManifest", appManifest);
46     }
47 
setOutManifest(Path outManifest)48     public void setOutManifest(Path outManifest) {
49         mOutManifest = TaskHelper.checkSinglePath("outManifest", outManifest);
50     }
51 
setEnabled(boolean enabled)52     public void setEnabled(boolean enabled) {
53         mEnabled  = enabled;
54     }
55 
56     /**
57      * Returns an object representing a nested <var>library</var> element.
58      */
createLibrary()59     public Object createLibrary() {
60         if (mLibraryPaths == null) {
61             mLibraryPaths = new ArrayList<Path>();
62         }
63 
64         Path path = new Path(getProject());
65         mLibraryPaths.add(path);
66 
67         return path;
68     }
69 
70     @Override
execute()71     public void execute() throws BuildException {
72         if (mAppManifest == null) {
73             throw new BuildException("Missing attribute appManifest");
74         }
75         if (mOutManifest == null) {
76             throw new BuildException("Missing attribute outManifest");
77         }
78 
79         // if we merge, then get the rest of the input paths.
80         List<File> libraries = new ArrayList<File>();
81         if (mLibraryPaths != null) {
82             for (Path pathList : mLibraryPaths) {
83                 for (String path : pathList.list()) {
84                     libraries.add(new File(path));
85                 }
86             }
87         }
88 
89         // prepare input files
90         ArrayList<File> allInputs = new ArrayList<File>(libraries.size() + 1);
91 
92         // always: the input manifest.
93         File appManifestFile = new File(mAppManifest);
94         allInputs.add(appManifestFile);
95 
96         // if enabled: add the libraries
97         if (mEnabled) {
98             allInputs.addAll(libraries);
99         }
100 
101         // figure out the path to the dependency file.
102         String depFile = mOutManifest + ".d";
103 
104         // get InputPath with no extension restrictions
105         List<InputPath> inputPaths = getInputPaths(allInputs, null /*extensionsToCheck*/,
106                 null /*factory*/);
107 
108         if (initDependencies(depFile, inputPaths) && dependenciesHaveChanged() == false) {
109             System.out.println(
110                     "No changes in the AndroidManifest files.");
111             return;
112         }
113 
114         System.out.println("Merging AndroidManifest files into one.");
115 
116         if (mEnabled == false || libraries.size() == 0) {
117             if (mEnabled == false) {
118                 System.out.println("Manifest merger disabled. Using project manifest only.");
119             } else {
120                 System.out.println("No libraries. Using project manifest only.");
121             }
122             // no merge (disabled or nothing to merge)? do a simple copy.
123             try {
124                 new FileOp().copyFile(appManifestFile, new File(mOutManifest));
125             } catch (IOException e) {
126                 throw new BuildException(e);
127             }
128         } else {
129             System.out.println(String.format("Merging manifests from project and %d libraries.",
130                     libraries.size()));
131             ManifestMerger merger = new ManifestMerger(
132                     MergerLog.wrapSdkLog(new StdLogger(StdLogger.Level.VERBOSE)),
133                     new ICallback() {
134                         SdkManager mManager;
135                         @Override
136                         public int queryCodenameApiLevel(@NonNull String codename) {
137                             if (mManager == null) {
138                                 File sdkDir = TaskHelper.getSdkLocation(getProject());
139                                 mManager = SdkManager.createManager(sdkDir.getPath(),
140                                         new StdLogger(StdLogger.Level.VERBOSE));
141                             }
142                             if (mManager != null) {
143                                 IAndroidTarget t = mManager.getTargetFromHashString(
144                                         IAndroidTarget.PLATFORM_HASH_PREFIX + codename);
145                                 if (t != null) {
146                                     return t.getVersion().getApiLevel();
147                                 }
148                             }
149                             return ICallback.UNKNOWN_CODENAME;
150                         }
151                     });
152             if (merger.process(
153                     new File(mOutManifest),
154                     appManifestFile,
155                     libraries.toArray(new File[libraries.size()])) == false) {
156                 throw new BuildException();
157             }
158         }
159 
160         // generate the dependency file.
161         generateDependencyFile(depFile, inputPaths, mOutManifest);
162     }
163 
164     @Override
getExecTaskName()165     protected String getExecTaskName() {
166         return "ManifestMerger";
167     }
168 }
169