• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 package com.android.ide.eclipse.adt.internal.wizards.templates;
17 
18 import static com.android.SdkConstants.FD_EXTRAS;
19 import static com.android.SdkConstants.FD_TEMPLATES;
20 import static com.android.SdkConstants.FD_TOOLS;
21 import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TEMPLATE_XML;
22 
23 import com.android.annotations.NonNull;
24 import com.android.annotations.Nullable;
25 import com.android.ide.eclipse.adt.AdtPlugin;
26 import com.android.ide.eclipse.adt.AdtUtils;
27 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
28 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
29 import com.google.common.base.Charsets;
30 import com.google.common.collect.Maps;
31 import com.google.common.io.Files;
32 
33 import org.w3c.dom.Document;
34 
35 import java.io.File;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.Comparator;
40 import java.util.List;
41 import java.util.Map;
42 
43 /** Handles locating templates and providing template metadata */
44 public class TemplateManager {
TemplateManager()45     TemplateManager() {
46     }
47 
48     /** @return the root folder containing templates */
49     @Nullable
getTemplateRootFolder()50     public static File getTemplateRootFolder() {
51         String location = AdtPrefs.getPrefs().getOsSdkFolder();
52         if (location != null) {
53             File folder = new File(location, FD_TOOLS + File.separator + FD_TEMPLATES);
54             if (folder.isDirectory()) {
55                 return folder;
56             }
57         }
58 
59         return null;
60     }
61 
62     /** @return the root folder containing extra templates */
63     @NonNull
getExtraTemplateRootFolders()64     public static List<File> getExtraTemplateRootFolders() {
65         List<File> folders = new ArrayList<File>();
66         String location = AdtPrefs.getPrefs().getOsSdkFolder();
67         if (location != null) {
68             File extras = new File(location, FD_EXTRAS);
69             if (extras.isDirectory()) {
70                 for (File vendor : AdtUtils.listFiles(extras)) {
71                     if (!vendor.isDirectory()) {
72                         continue;
73                     }
74                     for (File pkg : AdtUtils.listFiles(vendor)) {
75                         if (pkg.isDirectory()) {
76                             File folder = new File(pkg, FD_TEMPLATES);
77                             if (folder.isDirectory()) {
78                                 folders.add(folder);
79                             }
80                         }
81                     }
82                 }
83 
84                 // Legacy
85                 File folder = new File(extras, FD_TEMPLATES);
86                 if (folder.isDirectory()) {
87                     folders.add(folder);
88                 }
89             }
90         }
91 
92         return folders;
93     }
94 
95     /**
96      * Returns a template file under the given root, if it exists
97      *
98      * @param root the root folder
99      * @param relativePath the relative path
100      * @return a template file under the given root, if it exists
101      */
102     @Nullable
getTemplateLocation(@onNull File root, @NonNull String relativePath)103     public static File getTemplateLocation(@NonNull File root, @NonNull String relativePath) {
104         File templateRoot = getTemplateRootFolder();
105         if (templateRoot != null) {
106             String rootPath = root.getPath();
107             File templateFile = new File(templateRoot,
108                     rootPath.replace('/', File.separatorChar) + File.separator
109                     + relativePath.replace('/', File.separatorChar));
110             if (templateFile.exists()) {
111                 return templateFile;
112             }
113         }
114 
115         return null;
116     }
117 
118     /**
119      * Returns a template file under one of the available roots, if it exists
120      *
121      * @param relativePath the relative path
122      * @return a template file under one of the available roots, if it exists
123      */
124     @Nullable
getTemplateLocation(@onNull String relativePath)125     public static File getTemplateLocation(@NonNull String relativePath) {
126         File templateRoot = getTemplateRootFolder();
127         if (templateRoot != null) {
128             File templateFile = new File(templateRoot,
129                     relativePath.replace('/', File.separatorChar));
130             if (templateFile.exists()) {
131                 return templateFile;
132             }
133         }
134 
135         return null;
136 
137     }
138 
139     /**
140      * Returns all the templates with the given prefix
141      *
142      * @param folder the folder prefix
143      * @return the available templates
144      */
145     @NonNull
getTemplates(@onNull String folder)146     List<File> getTemplates(@NonNull String folder) {
147         List<File> templates = new ArrayList<File>();
148         Map<String, File> templateNames = Maps.newHashMap();
149         File root = getTemplateRootFolder();
150         if (root != null) {
151             File[] files = new File(root, folder).listFiles();
152             if (files != null) {
153                 for (File file : files) {
154                     if (file.isDirectory()) { // Avoid .DS_Store etc
155                         templates.add(file);
156                         templateNames.put(file.getName(), file);
157                     }
158                 }
159             }
160         }
161 
162         // Add in templates from extras/ as well.
163         for (File extra : getExtraTemplateRootFolders()) {
164             File[] files = new File(extra, folder).listFiles();
165             if (files != null) {
166                 for (File file : files) {
167                     if (file.isDirectory()) {
168                         File replaces = templateNames.get(file.getName());
169                         if (replaces != null) {
170                             int compare = compareTemplates(replaces, file);
171                             if (compare > 0) {
172                                 int index = templates.indexOf(replaces);
173                                 if (index != -1) {
174                                     templates.set(index, file);
175                                 } else {
176                                     templates.add(file);
177                                 }
178                             }
179                         } else {
180                             templates.add(file);
181                         }
182                     }
183                 }
184             }
185         }
186 
187         // Sort by file name (not path as is File's default)
188         if (templates.size() > 1) {
189             Collections.sort(templates, new Comparator<File>() {
190                 @Override
191                 public int compare(File file1, File file2) {
192                     return file1.getName().compareTo(file2.getName());
193                 }
194             });
195         }
196 
197         return templates;
198     }
199 
200     /**
201      * Compare two files, and return the one with the HIGHEST revision, and if
202      * the same, most recently modified
203      */
compareTemplates(File file1, File file2)204     private int compareTemplates(File file1, File file2) {
205         TemplateMetadata template1 = getTemplate(file1);
206         TemplateMetadata template2 = getTemplate(file2);
207 
208         if (template1 == null) {
209             return 1;
210         } else if (template2 == null) {
211             return -1;
212         } else {
213             int delta = template2.getRevision() - template1.getRevision();
214             if (delta == 0) {
215                 delta = (int) (file2.lastModified() - file1.lastModified());
216             }
217             return delta;
218         }
219     }
220 
221     /** Cache for {@link #getTemplate()} */
222     private Map<File, TemplateMetadata> mTemplateMap;
223 
224     @Nullable
getTemplate(File templateDir)225     TemplateMetadata getTemplate(File templateDir) {
226         if (mTemplateMap != null) {
227             TemplateMetadata metadata = mTemplateMap.get(templateDir);
228             if (metadata != null) {
229                 return metadata;
230             }
231         } else {
232             mTemplateMap = Maps.newHashMap();
233         }
234 
235         try {
236             File templateFile = new File(templateDir, TEMPLATE_XML);
237             if (templateFile.isFile()) {
238                 String xml = Files.toString(templateFile, Charsets.UTF_8);
239                 Document doc = DomUtilities.parseDocument(xml, true);
240                 if (doc != null && doc.getDocumentElement() != null) {
241                     TemplateMetadata metadata = new TemplateMetadata(doc);
242                     mTemplateMap.put(templateDir, metadata);
243                     return metadata;
244                 }
245             }
246         } catch (IOException e) {
247             AdtPlugin.log(e, null);
248         }
249 
250         return null;
251     }
252 }
253