Home | History | Annotate | Download | only in templates
      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 {
     45     TemplateManager() {
     46     }
     47 
     48     /** @return the root folder containing templates */
     49     @Nullable
     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
     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
    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
    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
    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      */
    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
    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