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 General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.wizard.components.actions;
038:
039: import java.io.File;
040: import java.io.FileFilter;
041: import java.util.ArrayList;
042: import java.util.Arrays;
043: import java.util.LinkedList;
044: import java.util.List;
045: import org.netbeans.installer.product.Registry;
046: import org.netbeans.installer.product.components.Product;
047: import org.netbeans.installer.utils.helper.ErrorLevel;
048: import org.netbeans.installer.utils.ErrorManager;
049: import org.netbeans.installer.utils.LogManager;
050: import org.netbeans.installer.utils.ResourceUtils;
051: import org.netbeans.installer.utils.StringUtils;
052: import org.netbeans.installer.utils.SystemUtils;
053: import org.netbeans.installer.utils.applications.JavaUtils;
054: import org.netbeans.installer.utils.applications.JavaUtils.JavaInfo;
055: import org.netbeans.installer.utils.exceptions.NativeException;
056: import org.netbeans.installer.utils.helper.Status;
057: import org.netbeans.installer.utils.helper.Version;
058: import org.netbeans.installer.utils.progress.Progress;
059: import org.netbeans.installer.utils.system.WindowsNativeUtils;
060: import org.netbeans.installer.utils.system.windows.WindowsRegistry;
061: import static org.netbeans.installer.utils.system.windows.WindowsRegistry.HKLM;
062: import static org.netbeans.installer.utils.system.windows.WindowsRegistry.HKCU;
063: import org.netbeans.installer.wizard.components.WizardAction;
064:
065: /**
066: *
067: * @author Kirill Sorokin
068: */
069: public class SearchForJavaAction extends WizardAction {
070: /////////////////////////////////////////////////////////////////////////////////
071: // Instance
072: private static List<File> javaLocations = new LinkedList<File>();
073: private static List<String> javaLabels = new LinkedList<String>();
074:
075: public SearchForJavaAction() {
076: setProperty(TITLE_PROPERTY, DEFAULT_TITLE);
077: setProperty(DESCRIPTION_PROPERTY, DEFAULT_DESCRIPTION);
078: }
079:
080: public void execute() {
081: execute(new Progress());
082: }
083:
084: public void execute(Progress progress) {
085: LogManager.logEntry("search for all java locations");
086: getWizardUi().setProgress(progress);
087: final List<File> locations = new LinkedList<File>();
088: progress.setTitle(SEARCH_INSTALLED_JAVAS);
089: progress.setDetail(StringUtils.EMPTY_STRING);
090: progress.setPercentage(Progress.START);
091:
092: SystemUtils.sleep(200);
093:
094: progress.setDetail(PREPARE_JAVA_LIST);
095: if (SystemUtils.isWindows()) {
096: fetchLocationsFromWindowsRegistry(locations);
097: }
098: fetchLocationsFromEnvironment(locations);
099: fetchLocationsFromFilesystem(locations);
100: fetchLocationsFromRegistry(locations);
101: getJavaLocationsInfo(locations, progress);
102:
103: sortJavaLocations();
104:
105: progress.setDetail(StringUtils.EMPTY_STRING);
106: progress.setPercentage(Progress.COMPLETE);
107:
108: SystemUtils.sleep(200);
109: LogManager.logExit("... end of search for all java locations");
110: }
111:
112: @Override
113: public boolean canExecuteForward() {
114: return javaLocations.size() == 0;
115: }
116:
117: // private //////////////////////////////////////////////////////////////////////
118: private static String getLabel(File javaHome) {
119: JavaInfo javaInfo = JavaUtils.getInfo(javaHome);
120:
121: return getLabel(javaHome, javaInfo);
122: }
123:
124: private static String getLabel(File javaHome, JavaInfo javaInfo) {
125: if (javaInfo.isNonFinal()) {
126: return StringUtils.format(JAVA_ENTRY_LABEL_NON_FINAL,
127: javaHome, javaInfo.getVersion().toJdkStyle(),
128: javaInfo.getVendor());
129: } else {
130: return StringUtils.format(JAVA_ENTRY_LABEL, javaHome,
131: javaInfo.getVersion().toJdkStyle(), javaInfo
132: .getVendor());
133: }
134: }
135:
136: private static String getLabel(File javaHome, Version version,
137: String vendor) {
138: return StringUtils.format(JAVA_ENTRY_LABEL, javaHome, version
139: .toJdkStyle(), vendor);
140: }
141:
142: private void getJavaLocationsInfo(List<File> locations,
143: Progress progress) {
144: for (int i = 0; i < locations.size(); i++) {
145: final File javaHome = locations.get(i).getAbsoluteFile();
146:
147: progress.setDetail(StringUtils.format(CHECKING, javaHome));
148:
149: if (isCanceled())
150: return; // check for cancel status
151:
152: LogManager.logIndent("investigating java home candidate: "
153: + javaHome);
154:
155: // check whether it is a java installation - the result will be null if
156: // it is not
157: final JavaInfo javaInfo = JavaUtils.getInfo(javaHome);
158:
159: if (javaInfo != null) {
160: LogManager.logUnindent("... parsed java: "
161: + javaInfo.getVersion() + " " + // NOI18N
162: "by " + javaInfo.getVendor() + "; " + // NOI18N
163: "final=" + !javaInfo.isNonFinal()); // NOI18N
164:
165: // filter out "private" jres
166: if (javaHome.getName().equals("jre")
167: && JavaUtils.isJdk(javaHome.getParentFile())) {
168: continue;
169: }
170:
171: // add the location to the list if it's not already there
172: if (!javaLocations.contains(javaHome)) {
173: javaLocations.add(javaHome);
174: javaLabels.add(getLabel(javaHome));
175: }
176: } else {
177: LogManager.unindent();
178: }
179: SystemUtils.sleep(5);
180: progress.setPercentage(Progress.COMPLETE * i
181: / locations.size());
182: }
183:
184: }
185:
186: public static void sortJavaLocations() {
187: // sort the found java installations:
188: // 1) by version descending
189: // 2) by path acending
190: // 3) by vendor descending (so Sun comes first, hehe)
191: for (int i = 0; i < javaLocations.size(); i++) {
192: for (int j = javaLocations.size() - 1; j > i; j--) {
193: File file1 = javaLocations.get(j);
194: File file2 = javaLocations.get(j - 1);
195:
196: String label1 = javaLabels.get(j);
197: String label2 = javaLabels.get(j - 1);
198:
199: JavaInfo info1 = JavaUtils
200: .getInfo(javaLocations.get(j));
201: JavaInfo info2 = JavaUtils.getInfo(javaLocations
202: .get(j - 1));
203:
204: if (info1.getVersion().equals(info2.getVersion())) {
205: if (file1.getPath().compareTo(file2.getPath()) == 0) {
206: if (info1.getVendor().compareTo(
207: info2.getVendor()) == 0) {
208: continue;
209: } else if (info1.getVendor().compareTo(
210: info2.getVendor()) < 0) {
211: javaLocations.set(j, file2);
212: javaLocations.set(j - 1, file1);
213:
214: javaLabels.set(j, label2);
215: javaLabels.set(j - 1, label1);
216: }
217: } else if (file1.getPath().length() < file2
218: .getPath().length()) {
219: javaLocations.set(j, file2);
220: javaLocations.set(j - 1, file1);
221:
222: javaLabels.set(j, label2);
223: javaLabels.set(j - 1, label1);
224: }
225: } else if (info1.getVersion().newerThan(
226: info2.getVersion())) {
227: javaLocations.set(j, file2);
228: javaLocations.set(j - 1, file1);
229:
230: javaLabels.set(j, label2);
231: javaLabels.set(j - 1, label1);
232: }
233: }
234: }
235: }
236:
237: public static void addJavaLocation(File location, Version version,
238: String vendor) {
239: if (!javaLocations.contains(location)) {
240: javaLocations.add(location);
241: javaLabels.add(getLabel(location, version, vendor));
242: JavaUtils.addJavaInfo(location, new JavaInfo(version,
243: vendor));
244: }
245: }
246:
247: public static void addJavaLocation(File location) {
248: if (!javaLocations.contains(location)) {
249: javaLocations.add(location);
250: javaLabels.add(getLabel(location));
251: }
252: }
253:
254: public static List<File> getJavaLocations() {
255: return javaLocations;
256: }
257:
258: public static List<String> getJavaLabels() {
259: return javaLabels;
260: }
261:
262: private void fetchLocationsFromFilesystem(final List<File> locations) {
263: final List<String> candidateLocations = new ArrayList<String>();
264:
265: for (String location : JAVA_FILESYSTEM_LOCATIONS_COMMON) {
266: candidateLocations.add(location);
267: }
268:
269: if (SystemUtils.isWindows()) {
270: candidateLocations.addAll(Arrays
271: .asList(JAVA_FILESYSTEM_LOCATIONS_WINDOWS));
272: } else if (SystemUtils.isMacOS()) {
273: candidateLocations.addAll(Arrays
274: .asList(JAVA_FILESYSTEM_LOCATIONS_MACOSX));
275: } else {
276: candidateLocations.addAll(Arrays
277: .asList(JAVA_FILESYSTEM_LOCATIONS_UNIX));
278: }
279: final File currentJava = SystemUtils.getCurrentJavaHome();
280: final File currentJavaParentDir = currentJava.getParentFile();
281: if (currentJavaParentDir != null) {
282: if (JavaUtils.isJavaHome(currentJava)
283: && JavaUtils.isJdk(currentJavaParentDir)) {
284: //installer runs on private JRE so perform search for
285: //all children of the parent directory of the corresponding JDK
286: String parentDir = currentJavaParentDir.getParent();
287: if (parentDir != null) {
288: if (!candidateLocations.contains(parentDir)) {
289: candidateLocations.add(parentDir);
290: }
291: }
292: }
293: }
294: for (String location : candidateLocations) {
295: final File parent = SystemUtils.resolvePath(location);
296:
297: if (parent.exists() && parent.isDirectory()) {
298: locations.add(parent);
299: final boolean isWindows = SystemUtils.isWindows();
300: final File[] children = parent
301: .listFiles(new FileFilter() {
302: public boolean accept(final File pathname) {
303: return pathname.isDirectory()
304: && (isWindows || !pathname
305: .getName().startsWith(
306: "."));
307: }
308: });
309:
310: if (children != null) {
311: for (File child : children) {
312: locations.add(child);
313: }
314: } else {
315: LogManager.log(ErrorLevel.DEBUG,
316: "Can`t get children of existing directory : "
317: + parent.getPath());
318: }
319: }
320: }
321: }
322:
323: private void fetchLocationsFromEnvironment(
324: final List<File> locations) {
325: LogManager
326: .logIndent("checking for possible java locations in environment");
327:
328: for (String name : JAVA_ENVIRONMENT_VARIABLES) {
329: final String value = System.getenv(name);
330:
331: if (value != null) {
332: LogManager.log("found: " + name + " = " + value); // NOI18N
333:
334: final File file = new File(value).getAbsoluteFile();
335: if (!locations.contains(file)) {
336: locations.add(file);
337: }
338: }
339: }
340:
341: LogManager.logUnindent("... finished");
342: }
343:
344: private void fetchLocationsFromWindowsRegistry(
345: final List<File> locations) {
346: LogManager
347: .logIndent("checking for possible java locations in windows registry");
348:
349: final WindowsNativeUtils nativeUtils = ((WindowsNativeUtils) SystemUtils
350: .getNativeUtils());
351: final WindowsRegistry registry = nativeUtils
352: .getWindowsRegistry();
353:
354: try {
355: for (int section : new int[] { HKLM, HKCU }) {
356: for (String path : JAVA_WINDOWS_REGISTRY_ENTRIES) {
357: // check whether current path exists in this section
358: if (!registry.keyExists(section, path)) {
359: continue;
360: }
361:
362: // get the names of all installed jdks
363: String[] keys = registry.getSubKeyNames(section,
364: path);
365:
366: // iterate over the list of jdks, checking their versions
367: // and taking actions appropriate to the current search
368: // mode
369: for (int i = 0; i < keys.length; i++) {
370: // get the name of the current examined jdk
371: String key = keys[i];
372:
373: // get the java home of the current jdk, if it exists
374: if (!registry.valueExists(section, path
375: + WindowsRegistry.SEPARATOR + key,
376: JavaUtils.JAVAHOME_VALUE)) {
377: continue;
378: }
379:
380: final String javaHome = registry
381: .getStringValue(section, path
382: + WindowsRegistry.SEPARATOR
383: + key,
384: JavaUtils.JAVAHOME_VALUE, false);
385:
386: LogManager
387: .log("found: "
388: + (section == HKLM ? "HKEY_LOCAL_MACHINE"
389: : "HKEY_CURRENT_USER")
390: + // NOI18N
391: "\\" + path + "\\" + key
392: + "\\"
393: + // NOI18N
394: JavaUtils.JAVAHOME_VALUE
395: + " = " + javaHome); // NOI18N
396:
397: // add java home to the list if it's not there already
398: final File file = new File(javaHome);
399: if (file.exists() && file.isDirectory()
400: && !locations.contains(file)) {
401: locations.add(file);
402: }
403: }
404: }
405: }
406: } catch (NativeException e) {
407: ErrorManager.notify(ErrorLevel.DEBUG,
408: "Failed to search in the windows registry", e);
409: }
410:
411: LogManager.logUnindent("... finished");
412: }
413:
414: private void fetchLocationsFromRegistry(final List<File> locations) {
415: for (Product jdk : Registry.getInstance().getProducts(
416: JDK_PRODUCT_UID)) {
417: if (jdk.getStatus() == Status.INSTALLED) {
418: if (!locations.contains(jdk.getInstallationLocation())) {
419: locations.add(jdk.getInstallationLocation());
420: }
421: }
422: }
423: }
424:
425: /////////////////////////////////////////////////////////////////////////////////
426: // Constants
427: public static final String DEFAULT_TITLE = ResourceUtils.getString(
428: SearchForJavaAction.class, "SFJA.title"); // NOI18N
429: public static final String DEFAULT_DESCRIPTION = ResourceUtils
430: .getString(SearchForJavaAction.class, "SFJA.description"); // NOI18N
431: public static final String PREPARE_JAVA_LIST = ResourceUtils
432: .getString(SearchForJavaAction.class, "SFJA.prepare.list"); //NOI18N
433: public static final String CHECKING = ResourceUtils.getString(
434: SearchForJavaAction.class, "SFJA.checking");//NOI18N
435: public static final String SEARCH_INSTALLED_JAVAS = ResourceUtils
436: .getString(SearchForJavaAction.class, "SFJA.search.java");//NOI18N
437: public static final String JAVA_ENTRY_LABEL = ResourceUtils
438: .getString(SearchForJavaAction.class, "SFJA.entry.label");//NOI18N
439: public static final String JAVA_ENTRY_LABEL_NON_FINAL = ResourceUtils
440: .getString(SearchForJavaAction.class,
441: "SFJA.entry.label.non.final");//NOI18N
442:
443: private static final String JDK_PRODUCT_UID = "jdk"; //NOI18N
444:
445: public static final String[] JAVA_WINDOWS_REGISTRY_ENTRIES = new String[] {
446: "SOFTWARE\\JavaSoft\\Java Development Kit", // NOI18N
447: "SOFTWARE\\JRockit\\Java Development Kit", // NOI18N
448: "SOFTWARE\\IBM\\Java Development Kit", // NOI18N
449: "SOFTWARE\\IBM\\Java2 Development Kit", // NOI18N
450:
451: "SOFTWARE\\JavaSoft\\Java Runtime Environment", // NOI18N
452: "SOFTWARE\\JRockit\\Java Runtime Environment", // NOI18N
453: "SOFTWARE\\IBM\\Java Runtime Environment", // NOI18N
454: "SOFTWARE\\IBM\\Java2 Runtime Environment" // NOI18N
455: };
456:
457: public static final String[] JAVA_ENVIRONMENT_VARIABLES = new String[] {
458: "JAVA_HOME", // NOI18N
459: "JAVAHOME", // NOI18N
460: "JAVA_PATH", // NOI18N
461: "JDK_HOME", // NOI18N
462: "JDKHOME", // NOI18N
463: "ANT_JAVA", // NOI18N
464: "JAVA", // NOI18N
465: "JDK" // NOI18N
466: };
467:
468: public static final String[] JAVA_FILESYSTEM_LOCATIONS_COMMON = new String[] {
469: "$S{java.home}", // NOI18N
470: "$S{java.home}/.." // NOI18N
471: };
472:
473: public static final String[] JAVA_FILESYSTEM_LOCATIONS_UNIX = new String[] {
474: "$N{home}", // NOI18N
475: "$N{home}/java", // NOI18N
476: "$N{home}/jdk", // NOI18N
477: "$N{home}/Java", // NOI18N
478:
479: "$N{install}", // NOI18N
480: "$N{install}/Java", // NOI18N
481:
482: "/usr", // NOI18N
483: "/usr/jdk", // NOI18N
484: "/usr/jdk/instances", // NOI18N
485: "/usr/java", // NOI18N
486: "/usr/java/jdk", // NOI18N
487: "/usr/j2se", // NOI18N
488: "/usr/j2sdk", // NOI18N
489:
490: "/usr/local", // NOI18N
491: "/usr/local/jdk", // NOI18N
492: "/usr/local/jdk/instances", // NOI18N
493: "/usr/local/java", // NOI18N
494: "/usr/local/j2se", // NOI18N
495: "/usr/local/j2sdk", // NOI18N
496:
497: "/export", // NOI18N
498: "/export/jdk", // NOI18N
499: "/export/jdk/instances", // NOI18N
500: "/export/java", // NOI18N
501: "/export/j2se", // NOI18N
502: "/export/j2sdk", // NOI18N
503:
504: "/opt", // NOI18N
505: "/opt/jdk", // NOI18N
506: "/opt/jdk/instances", // NOI18N
507: "/opt/java", // NOI18N
508: "/opt/j2se", // NOI18N
509: "/opt/j2sdk", // NOI18N
510:
511: "/usr/lib/jvm", // NOI18N
512: };
513:
514: public static final String[] JAVA_FILESYSTEM_LOCATIONS_MACOSX = new String[] {
515: "/Library/Java", // NOI18N
516: "/System/Library/Frameworks/JavaVM.framework/Versions/1.5", // NOI18N
517: "/System/Library/Frameworks/JavaVM.framework/Versions/1.5.0", // NOI18N
518: "/System/Library/Frameworks/JavaVM.framework/Versions/1.6", // NOI18N
519: "/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0", // NOI18N
520: "/System/Library/Frameworks/JavaVM.framework/Versions/1.7", // NOI18N
521: "/System/Library/Frameworks/JavaVM.framework/Versions/1.7.0" // NOI18N
522: };
523:
524: public static final String[] JAVA_FILESYSTEM_LOCATIONS_WINDOWS = new String[] {
525: "$N{install}", // NOI18N
526: "$N{install}/Java" // NOI18N
527: };
528: }
|