1 /*
2  * Copyright (C) 2007 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 
17 package com.android.ide.eclipse.adt.internal;
18 
19 import com.android.SdkConstants;
20 import com.android.ide.eclipse.adt.AdtPlugin;
21 import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
22 import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
23 import com.android.ide.eclipse.adt.Messages;
24 import com.android.sdklib.repository.FullRevision;
25 import com.android.sdklib.repository.FullRevision.PreviewComparison;
26 import com.android.sdklib.repository.PkgProps;
27 
28 import org.osgi.framework.Constants;
29 import org.osgi.framework.Version;
30 
31 import java.io.BufferedReader;
32 import java.io.File;
33 import java.io.FileNotFoundException;
34 import java.io.FileReader;
35 import java.io.IOException;
36 import java.util.regex.Matcher;
37 import java.util.regex.Pattern;
38 
39 /**
40  * Class handling the version check for the plugin vs. the SDK.<br>
41  * The plugin must be able to support all version of the SDK.
42  *
43  * <p/>An SDK can require a new version of the plugin.
44  * <p/>The SDK contains a file with the minimum version for the plugin. This file is inside the
45  * <code>tools/lib</code> directory, and is called <code>plugin.prop</code>.<br>
46  * Inside that text file, there is a line in the format "plugin.version=#.#.#". This is checked
47  * against the current plugin version.<br>
48  *
49  */
50 public final class VersionCheck {
51     /**
52      * The minimum version of the SDK Tools that this version of ADT requires.
53      */
54     private final static FullRevision MIN_TOOLS_REV = new FullRevision(24, 0, 2, 0);
55 
56     /**
57      * Pattern to get the minimum plugin version supported by the SDK. This is read from
58      * the file <code>$SDK/tools/lib/plugin.prop</code>.
59      */
60     private final static Pattern sPluginVersionPattern = Pattern.compile(
61             "^plugin.version=(\\d+)\\.(\\d+)\\.(\\d+).*$"); //$NON-NLS-1$
62     private final static Pattern sSourcePropPattern = Pattern.compile(
63             "^" + PkgProps.PKG_REVISION + "=(.*)$"); //$NON-NLS-1$
64 
65     /**
66      * Checks the plugin and the SDK have compatible versions.
67      * @param osSdkPath The path to the SDK
68      * @return true if compatible.
69      */
checkVersion(String osSdkPath, CheckSdkErrorHandler errorHandler)70     public static boolean checkVersion(String osSdkPath, CheckSdkErrorHandler errorHandler) {
71         AdtPlugin plugin = AdtPlugin.getDefault();
72         String osLibs = osSdkPath + SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
73 
74         // get the plugin property file, and grab the minimum plugin version required
75         // to work with the sdk
76         int minMajorVersion = -1;
77         int minMinorVersion = -1;
78         int minMicroVersion = -1;
79         BufferedReader reader = null;
80         try {
81             reader = new BufferedReader(new FileReader(osLibs + SdkConstants.FN_PLUGIN_PROP));
82             String line;
83             while ((line = reader.readLine()) != null) {
84                 Matcher m = sPluginVersionPattern.matcher(line);
85                 if (m.matches()) {
86                     minMajorVersion = Integer.parseInt(m.group(1));
87                     minMinorVersion = Integer.parseInt(m.group(2));
88                     minMicroVersion = Integer.parseInt(m.group(3));
89                     break;
90                 }
91             }
92         } catch (FileNotFoundException e) {
93             // the build id will be null, and this is handled by the builders.
94         } catch (IOException e) {
95             // the build id will be null, and this is handled by the builders.
96         } finally {
97             if (reader != null) {
98                 try {
99                     reader.close();
100                 } catch (IOException e) {
101                 } finally {
102                     reader = null;
103                 }
104             }
105         }
106 
107         // Failed to get the min plugin version number?
108         if (minMajorVersion == -1 || minMinorVersion == -1 || minMicroVersion ==-1) {
109             return errorHandler.handleWarning(
110                     Solution.OPEN_SDK_MANAGER,
111                     Messages.VersionCheck_Plugin_Version_Failed);
112         }
113 
114         // Are the build tools installed? We can't query Sdk#getLatestBuildTool yet, since
115         // SDK initialization typically hasn't completed yet and Sdk.getCurrent() is null.
116         File buildToolsFolder = new File(osSdkPath, SdkConstants.FD_BUILD_TOOLS);
117         if (!buildToolsFolder.isDirectory()) {
118             return errorHandler.handleWarning(
119                     Solution.OPEN_SDK_MANAGER,
120                     Messages.VersionCheck_Build_Tool_Missing);
121         }
122 
123         // test the plugin number
124         String versionString = (String) plugin.getBundle().getHeaders().get(
125                 Constants.BUNDLE_VERSION);
126         Version version = new Version(versionString);
127 
128         boolean valid = true;
129         if (version.getMajor() < minMajorVersion) {
130             valid = false;
131         } else if (version.getMajor() == minMajorVersion) {
132             if (version.getMinor() < minMinorVersion) {
133                 valid = false;
134             } else if (version.getMinor() == minMinorVersion) {
135                 if (version.getMicro() < minMicroVersion) {
136                     valid = false;
137                 }
138             }
139         }
140 
141         if (valid == false) {
142             return errorHandler.handleError(
143                     Solution.OPEN_P2_UPDATE,
144                     String.format(Messages.VersionCheck_Plugin_Too_Old,
145                             minMajorVersion, minMinorVersion, minMicroVersion, versionString));
146         }
147 
148         // now check whether the tools are new enough.
149         String osTools = osSdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
150         FullRevision toolsRevision = new FullRevision(Integer.MAX_VALUE);
151         try {
152             reader = new BufferedReader(new FileReader(osTools + SdkConstants.FN_SOURCE_PROP));
153             String line;
154             while ((line = reader.readLine()) != null) {
155                 Matcher m = sSourcePropPattern.matcher(line);
156                 if (m.matches()) {
157                     try {
158                         toolsRevision = FullRevision.parseRevision(m.group(1));
159                     } catch (NumberFormatException ignore) {}
160                     break;
161                 }
162             }
163         } catch (FileNotFoundException e) {
164             // the build id will be null, and this is handled by the builders.
165         } catch (IOException e) {
166             // the build id will be null, and this is handled by the builders.
167         } finally {
168             if (reader != null) {
169                 try {
170                     reader.close();
171                 } catch (IOException e) {
172                 } finally {
173                     reader = null;
174                 }
175             }
176         }
177 
178         if (toolsRevision.compareTo(MIN_TOOLS_REV, PreviewComparison.IGNORE) < 0) {
179             // this is a warning only as we need to parse the SDK to allow updating
180             // of the tools!
181             return errorHandler.handleWarning(
182                     Solution.OPEN_SDK_MANAGER,
183                     String.format(Messages.VersionCheck_Tools_Too_Old,
184                             MIN_TOOLS_REV, toolsRevision));
185         }
186 
187         return true; // no error!
188     }
189 }
190