001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.projectopener;
043:
044: import java.io.BufferedReader;
045: import java.io.File;
046: import java.io.FileFilter;
047: import java.io.FileNotFoundException;
048: import java.io.FileReader;
049: import java.io.IOException;
050: import java.util.Collection;
051: import java.util.Comparator;
052: import java.util.Iterator;
053: import java.util.StringTokenizer;
054: import java.util.logging.Logger;
055: import java.util.regex.Matcher;
056: import java.util.regex.Pattern;
057:
058: /**
059: *
060: * @author Milan Kubec
061: */
062: public class NBInstallation {
063:
064: public static final Comparator VERSION_COMPARATOR = new VersionComparator();
065: public static final Comparator LAST_USED_COMPARATOR = new LastUsedComparator();
066:
067: private static Logger LOGGER = WSProjectOpener.LOGGER;
068:
069: // there are two versions of log file
070: private static final String searchStr1 = "Installation; User Dir.";
071: private static final String searchStr2 = "Installation";
072:
073: // regexp for matching nb cluster, e.g. nb5.5
074: private static final Pattern NB_CLUSTER_REGEX = Pattern
075: .compile("[/\\\\]nb(\\d*(\\.\\d+)*)$");
076: // regexp for matching start of windows path, e.g. e:\
077: private static final Pattern WIN_ROOT_REGEX = Pattern
078: .compile("^[a-zA-Z]:\\\\");
079:
080: private static final String[] NON_CLUSTER_DIRS = new String[] {
081: "etc", "bin", "harness" };
082:
083: private File userDir;
084: private File installDir;
085: private String ideVersion;
086:
087: private File logFile;
088: private File lockFile;
089:
090: private String versionParts[];
091:
092: /** Creates a new instance of NetBeansInstallation */
093: public NBInstallation(File userDir) {
094: this .userDir = userDir;
095: logFile = new File(new File(new File(userDir, "var"), "log"),
096: "messages.log");
097: ideVersion = findVersion();
098: try {
099: installDir = findInstallDir();
100: } catch (Exception ex) {
101: LOGGER.info("Exception during searching for install dir: "
102: + Utils.exc2String(ex));
103: }
104: versionParts = Utils.getVersionParts(ideVersion);
105: lockFile = new File(userDir, "lock");
106: }
107:
108: public boolean isLocked() {
109: if (lockFile.exists()) {
110: return true;
111: }
112: return false;
113: }
114:
115: public boolean isValid() {
116: if (isNBUserdir() && Utils.getVersionParts(ideVersion) != null
117: && installDir != null && installDir.exists()
118: && installDir.isDirectory()
119: && new File(installDir, "bin").exists()) {
120: return true;
121: }
122: return false;
123: }
124:
125: public File getInstallDir() {
126: return installDir;
127: }
128:
129: public File getExecDir() {
130: return new File(installDir, "bin");
131: }
132:
133: /**
134: * Tries to find important files for each project type in any cluster in installDir,
135: * XXX should be extended to look also in userDir!
136: */
137: public boolean canHandle(Collection c) {
138: int toBeFound = 0;
139: int foundFiles = 0;
140: for (Iterator iter = c.iterator(); iter.hasNext();) {
141: ProjectType pt = (ProjectType) iter.next();
142: String impFiles[] = pt.getImportantFiles();
143: toBeFound += impFiles.length;
144: String[] clusterPaths = getClusterDirPaths();
145: for (int i = 0; i < impFiles.length; i++) {
146: String iPath = impFiles[i].replace('/',
147: File.separatorChar);
148: for (int j = 0; j < clusterPaths.length; j++) {
149: String searchPath = clusterPaths[j]
150: + File.separator + iPath;
151: LOGGER.fine("Looking for: " + searchPath);
152: File f = new File(searchPath);
153: if (f.exists()) {
154: LOGGER.info("File: " + f.getAbsolutePath()
155: + " exists.");
156: foundFiles++;
157: }
158: }
159: }
160: }
161: if (foundFiles == toBeFound) {
162: return true;
163: }
164: return false;
165: }
166:
167: /**
168: * Returns all dirs under installDir that are not listed in
169: * NON_CLUSTER_DIRS, they are considered to be clusters
170: */
171: public File[] getClusterDirs() {
172: File[] dirs = installDir.listFiles(new FileFilter() {
173: public boolean accept(File f) {
174: if (f.isDirectory()) {
175: for (int i = 0; i < NON_CLUSTER_DIRS.length; i++) {
176: if (f.getName().equals(NON_CLUSTER_DIRS[i])) {
177: return false;
178: }
179: }
180: return true;
181: }
182: return false;
183: }
184: });
185: return dirs;
186: }
187:
188: private String[] getClusterDirPaths() {
189: File[] files = getClusterDirs();
190: String dirPaths[] = new String[files.length];
191: for (int i = 0; i < files.length; i++) {
192: dirPaths[i] = files[i].getAbsolutePath();
193: }
194: return dirPaths;
195: }
196:
197: public long lastUsed() {
198: if (logFile.exists()) {
199: return logFile.lastModified();
200: }
201: return 0L;
202: }
203:
204: // from 5.5.1beta2 => 5.5.1
205: public String numVersion() {
206: if (versionParts != null && !versionParts[0].equals("")) {
207: return versionParts[0];
208: }
209: // fallback to avoid problems when dev version
210: // userdir doesn't have a numeric version
211: return "1.0";
212: }
213:
214: // from 5.5.1beta2 => beta
215: public String releaseType() {
216: if (versionParts != null && !versionParts[1].equals("")) {
217: return versionParts[1];
218: }
219: return "";
220: }
221:
222: // from 5.5.1beta2 => 2
223: public String releaseVersion() {
224: if (versionParts != null && !versionParts[2].equals("")) {
225: return versionParts[2];
226: }
227: return "";
228: }
229:
230: public String toString() {
231: return userDir.getAbsolutePath();
232: }
233:
234: // ---
235:
236: public static class LastUsedComparator implements Comparator {
237:
238: public int compare(Object arg0, Object arg1) {
239: return signum(((NBInstallation) arg0).lastUsed()
240: - ((NBInstallation) arg1).lastUsed());
241: }
242:
243: private int signum(long diff) {
244: if (diff > 0)
245: return 1;
246: if (diff < 0)
247: return -1;
248: return 0;
249: }
250:
251: }
252:
253: public static class VersionComparator implements Comparator {
254:
255: public int compare(Object arg0, Object arg1) {
256: int retVal = 0;
257: String v0 = ((NBInstallation) arg0).numVersion();
258: String v1 = ((NBInstallation) arg1).numVersion();
259: // this is because dev version doesn't have any numbers,
260: // so 'dev' means lower version always
261: if (v0.equals("")) {
262: retVal = -1;
263: } else if (v1.equals("")) {
264: retVal = 1;
265: }
266: if (retVal == 0) {
267: retVal = Utils.compareVersions(v0, v1);
268: }
269: if (retVal == 0) {
270: v0 = ((NBInstallation) arg0).releaseType();
271: v1 = ((NBInstallation) arg1).releaseType();
272: retVal = Utils.compareReleaseTypes(v0, v1);
273: }
274: if (retVal == 0) {
275: v0 = ((NBInstallation) arg0).releaseVersion();
276: v1 = ((NBInstallation) arg1).releaseVersion();
277: retVal = Utils.compareVersions(v0, v1);
278: }
279: return retVal;
280: }
281:
282: }
283:
284: // ---
285:
286: private File findInstallDir() throws FileNotFoundException,
287: IOException {
288: String dirPath = null;
289: LOGGER.fine("Parsing file: " + logFile.getAbsolutePath());
290: BufferedReader logFileReader = new BufferedReader(
291: new FileReader(logFile));
292: String line = logFileReader.readLine();
293: boolean lineRead;
294:
295: while (line != null) {
296:
297: lineRead = false;
298: if (line.indexOf(searchStr1) != -1) { // old version of log file
299: LOGGER.fine("Found line: " + line);
300: int index1 = line.indexOf('=') + 2;
301: int index2 = line.indexOf("; ", index1);
302: String subStr = line.substring(index1, index2);
303: LOGGER.fine("Found substring: " + subStr);
304: StringTokenizer tokenizer = new StringTokenizer(subStr,
305: File.pathSeparator);
306: while (tokenizer.hasMoreTokens()) {
307: String instPart = tokenizer.nextToken();
308: LOGGER.fine("Testing token: " + instPart);
309: // regex matcher looking for nb cluster e.g. nb5.5
310: Matcher matcher = NB_CLUSTER_REGEX
311: .matcher(instPart);
312: if (matcher.find()) {
313: File f = new File(instPart).getParentFile();
314: LOGGER.fine("Found file: "
315: + f.getAbsolutePath());
316: if (f.exists()) {
317: dirPath = f.getAbsolutePath();
318: }
319: }
320: }
321: } else if (line.indexOf(searchStr2) != -1) { // new version of log file
322: LOGGER.fine("Found line: " + line);
323: int index = line.indexOf('=') + 2;
324: String tLine = line.substring(index).trim();
325: boolean matching;
326:
327: do {
328: matching = false;
329: // startsWith("/") OR startsWith("e:\")
330: if (tLine.startsWith("/") || matchWinRoot(tLine)) { // correct line matched
331: matching = true;
332: LOGGER.fine("Matching line: " + tLine);
333: Matcher matcher = NB_CLUSTER_REGEX
334: .matcher(tLine);
335: if (matcher.find()) { // nb cluster matched
336: File f = new File(tLine).getParentFile();
337: LOGGER.fine("Found file: "
338: + f.getAbsolutePath());
339: if (f.exists()) {
340: dirPath = f.getAbsolutePath();
341: }
342: }
343: line = logFileReader.readLine();
344: lineRead = true;
345: tLine = line.trim();
346: }
347: } while (matching);
348:
349: }
350:
351: if (!lineRead) {
352: line = logFileReader.readLine();
353: }
354:
355: }
356:
357: if (dirPath != null) {
358: return new File(dirPath);
359: } else {
360: return null;
361: }
362: }
363:
364: private boolean matchWinRoot(String line) {
365: Matcher matcher = WIN_ROOT_REGEX.matcher(line);
366: return matcher.find();
367: }
368:
369: // XXX the version might be read from log file
370: private String findVersion() {
371: return userDir.getName();
372: }
373:
374: // check if build.properties and var/log/messages.log files exist
375: private boolean isNBUserdir() {
376: File buildProps = new File(userDir, "build.properties");
377: if (buildProps.exists() && logFile.exists()) {
378: return true;
379: }
380: return false;
381: }
382:
383: // ---
384:
385: // will be used to validate folder as NB install dir
386: // after user selects some folder
387: public static boolean isNBInstallation(File f) {
388: if (new File(f, "bin").exists()) {
389: return true;
390: }
391: return false;
392: }
393:
394: }
|