• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.sdklib.internal.repository;
18 
19 import com.android.sdklib.SdkConstants;
20 import com.android.sdklib.SdkManager;
21 import com.android.sdklib.internal.repository.Archive.Arch;
22 import com.android.sdklib.internal.repository.Archive.Os;
23 import com.android.sdklib.repository.SdkRepository;
24 
25 import org.w3c.dom.Node;
26 
27 import java.io.File;
28 import java.util.Map;
29 import java.util.Properties;
30 
31 /**
32  * Represents a extra XML node in an SDK repository.
33  */
34 public class ExtraPackage extends MinToolsPackage {
35 
36     private static final String PROP_PATH          = "Extra.Path";         //$NON-NLS-1$
37 
38     /**
39      * The install folder name. It must be a single-segment path.
40      * The paths "add-ons", "platforms", "tools" and "docs" are reserved and cannot be used.
41      * This limitation cannot be written in the XML Schema and must be enforced here by using
42      * the method {@link #isPathValid()} *before* installing the package.
43      */
44     private final String mPath;
45 
46     /**
47      * Creates a new tool package from the attributes and elements of the given XML node.
48      * <p/>
49      * This constructor should throw an exception if the package cannot be created.
50      */
ExtraPackage(RepoSource source, Node packageNode, Map<String,String> licenses)51     ExtraPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {
52         super(source, packageNode, licenses);
53 
54         mPath = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_PATH);
55     }
56 
57     /**
58      * Manually create a new package with one archive and the given attributes or properties.
59      * This is used to create packages from local directories in which case there must be
60      * one archive which URL is the actual target location.
61      * <p/>
62      * By design, this creates a package with one and only one archive.
63      */
ExtraPackage(RepoSource source, Properties props, String path, int revision, String license, String description, String descUrl, Os archiveOs, Arch archiveArch, String archiveOsPath)64     ExtraPackage(RepoSource source,
65             Properties props,
66             String path,
67             int revision,
68             String license,
69             String description,
70             String descUrl,
71             Os archiveOs,
72             Arch archiveArch,
73             String archiveOsPath) {
74         super(source,
75                 props,
76                 revision,
77                 license,
78                 description,
79                 descUrl,
80                 archiveOs,
81                 archiveArch,
82                 archiveOsPath);
83 
84         // The path argument comes before whatever could be in the properties
85         mPath = path != null ? path : getProperty(props, PROP_PATH, path);
86     }
87 
88     /**
89      * Save the properties of the current packages in the given {@link Properties} object.
90      * These properties will later be give the constructor that takes a {@link Properties} object.
91      */
92     @Override
saveProperties(Properties props)93     void saveProperties(Properties props) {
94         super.saveProperties(props);
95 
96         props.setProperty(PROP_PATH, mPath);
97 
98         if (getMinToolsRevision() != MIN_TOOLS_REV_NOT_SPECIFIED) {
99             props.setProperty(PROP_MIN_TOOLS_REV, Integer.toString(getMinToolsRevision()));
100         }
101     }
102 
103     /**
104      * Static helper to check if a given path is acceptable for an "extra" package.
105      */
isPathValid()106     public boolean isPathValid() {
107         if (SdkConstants.FD_ADDONS.equals(mPath) ||
108                 SdkConstants.FD_PLATFORMS.equals(mPath) ||
109                 SdkConstants.FD_TOOLS.equals(mPath) ||
110                 SdkConstants.FD_DOCS.equals(mPath)) {
111             return false;
112         }
113         return mPath != null && mPath.indexOf('/') == -1 && mPath.indexOf('\\') == -1;
114     }
115 
116     /**
117      * The install folder name. It must be a single-segment path.
118      * The paths "add-ons", "platforms", "tools" and "docs" are reserved and cannot be used.
119      * This limitation cannot be written in the XML Schema and must be enforced here by using
120      * the method {@link #isPathValid()} *before* installing the package.
121      */
getPath()122     public String getPath() {
123         return mPath;
124     }
125 
126     /** Returns a short description for an {@link IDescription}. */
127     @Override
getShortDescription()128     public String getShortDescription() {
129         String name = getPath();
130         if (name != null) {
131             // Uniformize all spaces in the name and upper case words.
132 
133             name = name.replaceAll("[ _\t\f-]+", " ");     //$NON-NLS-1$ //$NON-NLS-2$
134 
135             // Look at all lower case characters in range [1..n-1] and replace them by an upper
136             // case if they are preceded by a space. Also upper cases the first character of the
137             // string.
138             boolean changed = false;
139             char[] chars = name.toCharArray();
140             for (int n = chars.length - 1, i = 0; i < n; i++) {
141                 if (Character.isLowerCase(chars[i]) && (i == 0 || chars[i - 1] == ' ')) {
142                     chars[i] = Character.toUpperCase(chars[i]);
143                     changed = true;
144                 }
145             }
146             if (changed) {
147                 name = new String(chars);
148             }
149         }
150 
151         String s = String.format("%1$s package, revision %2$d",
152                 name,
153                 getRevision());
154 
155         return s;
156     }
157 
158     /**
159      * Returns a long description for an {@link IDescription}.
160      *
161      * The long description is whatever the XML contains for the &lt;description&gt; field,
162      * or the short description if the former is empty.
163      */
164     @Override
getLongDescription()165     public String getLongDescription() {
166         String s = getDescription();
167         if (s == null || s.length() == 0) {
168             s = String.format("Extra %1$s package", getPath());
169         }
170 
171         if (s.indexOf("revision") == -1) {
172             s += String.format("\nRevision %1$d", getRevision());
173         }
174 
175         if (getMinToolsRevision() != MIN_TOOLS_REV_NOT_SPECIFIED) {
176             s += String.format("\nRequires tools revision %1$d", getMinToolsRevision());
177         }
178 
179         return s;
180     }
181 
182     /**
183      * Computes a potential installation folder if an archive of this package were
184      * to be installed right away in the given SDK root.
185      * <p/>
186      * A "tool" package should always be located in SDK/tools.
187      *
188      * @param osSdkRoot The OS path of the SDK root folder.
189      * @param suggestedDir A suggestion for the installation folder name, based on the root
190      *                     folder used in the zip archive.
191      * @param sdkManager An existing SDK manager to list current platforms and addons.
192      * @return A new {@link File} corresponding to the directory to use to install this package.
193      */
194     @Override
getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager)195     public File getInstallFolder(String osSdkRoot, String suggestedDir, SdkManager sdkManager) {
196         return new File(osSdkRoot, getPath());
197     }
198 
199     @Override
sameItemAs(Package pkg)200     public boolean sameItemAs(Package pkg) {
201         // Extra packages are similar if they have the same path.
202         return pkg instanceof ExtraPackage && ((ExtraPackage)pkg).mPath.equals(mPath);
203     }
204 }
205