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