You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by kr...@apache.org on 2010/07/28 14:32:06 UTC
svn commit: r980035 - in /db/derby/code/branches/10.6: ./
java/build/org/apache/derbyPreBuild/PropertySetter.java
Author: kristwaa
Date: Wed Jul 28 12:32:05 2010
New Revision: 980035
URL: http://svn.apache.org/viewvc?rev=980035&view=rev
Log:
DERBY-4694: Build breaks on Mac OS X due to JDK classpath issues
Merged fix from trunk (revisions 958555 and 963206).
Modified:
db/derby/code/branches/10.6/ (props changed)
db/derby/code/branches/10.6/java/build/org/apache/derbyPreBuild/PropertySetter.java
Propchange: db/derby/code/branches/10.6/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Jul 28 12:32:05 2010
@@ -1,2 +1,2 @@
-/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,942286,942476,942480,942587,944152,946794,948045,948069,951346,951366,952138,952237,952581,954344,954421,954544,954748,955001,955540,955634,956075,956234,956445,956569,956659,957260,958163,958522,958618,958939,959550,962716,963705,964115
+/db/derby/code/trunk:938547,938796,938959,939231,940462,940469,941627,942031,942286,942476,942480,942587,944152,946794,948045,948069,951346,951366,952138,952237,952581,954344,954421,954544,954748,955001,955540,955634,956075,956234,956445,956569,956659,957260,958163,958522,958555,958618,958939,959550,962716,963206,963705,964115
/db/derby/docs/trunk:954344
Modified: db/derby/code/branches/10.6/java/build/org/apache/derbyPreBuild/PropertySetter.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.6/java/build/org/apache/derbyPreBuild/PropertySetter.java?rev=980035&r1=980034&r2=980035&view=diff
==============================================================================
--- db/derby/code/branches/10.6/java/build/org/apache/derbyPreBuild/PropertySetter.java (original)
+++ db/derby/code/branches/10.6/java/build/org/apache/derbyPreBuild/PropertySetter.java Wed Jul 28 12:32:05 2010
@@ -23,7 +23,6 @@ package org.apache.derbyPreBuild;
import java.io.File;
import java.io.FileFilter;
-import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -124,11 +123,19 @@ public class PropertySetter extends Task
private static final String JDK_IBM = "IBM Corporation";
private static final String JDK_SUN = "Sun Microsystems Inc.";
- private static final String APPLE_JAVA_ROOT = "/System/Library/Frameworks/JavaVM.framework/Versions";
+ private static final String APPLE_CLASSES_DIR = "Classes";
+ private static final String APPLE_COMMANDS_DIR = "Commands";
+ private static final String APPLE_HOME_DIR = "Home";
+ private static final String APPLE_LIB_DIR = "Libraries";
+ private static final String APPLE_RESOURCES_DIR = "Resources";
private static final String JAVA_5 = "1.5";
private static final String PROPERTY_SETTER_DEBUG_FLAG = "printCompilerProperties";
+ /** Property controlling extra verbose debugging information. */
+ private static final String PROPERTY_SETTER_VERBOSE_DEBUG_FLAG =
+ "printCompilerPropertiesVerbose";
+ private static boolean VERBOSE_DEBUG_ENABLED;
/////////////////////////////////////////////////////////////////////////
//
@@ -350,9 +357,27 @@ public class PropertySetter extends Task
* </p>
*/
private void setForAppleJDKs()
- throws BuildException
+ throws Exception
{
- defaultSetter( APPLE_JAVA_ROOT + "/1.4/Classes", APPLE_JAVA_ROOT + "/1.5/Classes", APPLE_JAVA_ROOT + "/1.6/Classes" );
+ String default_j14lib = getProperty( J14LIB );
+ String default_j15lib = getProperty( J15LIB );
+ String default_j16lib = getProperty( J16LIB );
+
+ // Obtain a list of all JDKs available to us, then specify which one to
+ // use for the different versions we require.
+ List<JDKInfo> jdks = locateAppleJDKs(getJdkSearchPath());
+ debug("\nSelecting JDK candidates:");
+ if (default_j14lib == null) {
+ default_j14lib = getJreLib(jdks, "1.4", jdkVendor);
+ }
+ if (default_j15lib == null) {
+ default_j15lib = getJreLib(jdks, "1.5", jdkVendor);
+ }
+ if (default_j16lib == null) {
+ default_j16lib = getJreLib(jdks, "1.6", jdkVendor);
+ }
+
+ defaultSetter(default_j14lib, default_j15lib, default_j16lib);
}
/////////////////////////////////////////////////////////////////////////
@@ -413,7 +438,7 @@ public class PropertySetter extends Task
// Obtain a list of all JDKs available to us, then specify which one to
// use for the different versions we require.
- List<JDKInfo> jdks = locateJDKs(getJdkSearchPath());
+ List<JDKInfo> jdks = locateMostJDKs(getJdkSearchPath());
debug("\nSelecting JDK candidates:");
if (default_j14lib == null) {
default_j14lib = getJreLib(jdks, seed14, jdkVendor);
@@ -516,7 +541,8 @@ public class PropertySetter extends Task
{
echo( "JAVA_HOME directory '" + javaHome + "' does not have a grandparent directory sitting above all of the JDKs." );
}
-
+ verbose("jdkParent derived from '" + javaHome + "': '" +
+ ancestor.getPath() + "'");
return ancestor;
}
@@ -574,6 +600,77 @@ public class PropertySetter extends Task
}
// JDK heuristics based on inspecting JARs.
+ //
+ private List<JDKInfo> locateAppleJDKs(List<File> jdkParentDirectories) {
+ ArrayList<JDKInfo> jdks = new ArrayList<JDKInfo>();
+ if (jdkParentDirectories == null) {
+ debug("WARNING: No JDK parent directories specified.");
+ return jdks;
+ }
+
+ debug("\nLocating Apple JDKs:");
+
+ final FileFilter jdkFilter = new JDKRootFileFilter();
+ for (File jdkParentDirectory : jdkParentDirectories) {
+ verbose("locating JDKs in '" + jdkParentDirectory + "'");
+ // Limit the search to the directories in the parent directory.
+ // Don't descend into sub directories.
+ File[] possibleJdkRoots = jdkParentDirectory.listFiles(jdkFilter);
+ for (File f : possibleJdkRoots) {
+ verbose("checking root '" + f + "'");
+
+ File[] requiredDirs = new File[] {
+ new File(f, APPLE_CLASSES_DIR),
+ new File(f, APPLE_COMMANDS_DIR),
+ new File(f, APPLE_HOME_DIR),
+ new File(f, APPLE_LIB_DIR),
+ new File(f, APPLE_RESOURCES_DIR)
+ };
+
+ boolean dirsOK = true;
+ for (File reqDir : requiredDirs) {
+ if (!reqDir.exists()) {
+ debug("Missing JDK directory: " +
+ reqDir.getAbsolutePath());
+ dirsOK = false;
+ break;
+ }
+ }
+ if (!dirsOK) {
+ continue;
+ }
+
+ File rtArchive = new File(f,
+ new File(APPLE_CLASSES_DIR, "classes.jar").getPath());
+ if (!rtArchive.exists()) {
+ debug("Missing JAR: " + rtArchive);
+ // Bail out, we only understand JDKs that have a
+ // "Classes/classes.jar".
+ continue;
+ }
+ // Get implementation version from the manifest.
+ Manifest mf;
+ try {
+ JarFile rtJar = new JarFile(rtArchive);
+ mf = rtJar.getManifest();
+ } catch (IOException ioeIgnored) {
+ // Obtaining the manifest failed for some reason.
+ // If in debug mode, let the user know.
+ debug("Failed to obtain manifest for " +
+ rtArchive.getAbsolutePath() + ": " +
+ ioeIgnored.getMessage());
+ continue;
+ }
+ JDKInfo jdk = inspectJarManifest(mf, f);
+ if (jdk != null) {
+ jdks.add(jdk);
+ continue;
+ }
+ }
+ }
+ verbose("located " + jdks.size() + " JDKs in total");
+ return jdks;
+ }
/**
* Searches for JDKs in the specified directories.
@@ -582,7 +679,7 @@ public class PropertySetter extends Task
* @return A list containing information objects for JDKs found on the
* system. If no JDKs were found, the list will be empty.
*/
- private List<JDKInfo> locateJDKs(List<File> jdkParentDirectories) {
+ private List<JDKInfo> locateMostJDKs(List<File> jdkParentDirectories) {
ArrayList<JDKInfo> jdks = new ArrayList<JDKInfo>();
if (jdkParentDirectories == null) {
return jdks;
@@ -597,17 +694,11 @@ public class PropertySetter extends Task
// Default JAR file to look for, used be most JDKs.
new File(jreLibRel, "rt.jar").getPath(),
};
+ final FileFilter jdkFilter = new JDKRootFileFilter();
for (File jdkParentDirectory : jdkParentDirectories) {
// Limit the search to the directories in the parent directory.
// Don't descend into sub directories.
- File[] possibleJdkRoots = jdkParentDirectory.listFiles(
- new FileFilter() {
-
- /** Accepts only directories. */
- public boolean accept(File pathname) {
- return pathname.isDirectory();
- }
- });
+ File[] possibleJdkRoots = jdkParentDirectory.listFiles(jdkFilter);
for (File f : possibleJdkRoots) {
File rtArchive = new File(f, jreLibRel.getPath());
if (!rtArchive.exists()) {
@@ -662,6 +753,7 @@ public class PropertySetter extends Task
private JDKInfo inspectJarManifest(Manifest mf, File jdkHome) {
// The manifest may be null, as it is optional.
if (mf == null) {
+ verbose("no manifest found for JDK in '" + jdkHome + "'");
return null;
}
JDKInfo info = new JDKInfo(
@@ -669,23 +761,8 @@ public class PropertySetter extends Task
mf.getMainAttributes().getValue("Specification-Version"),
mf.getMainAttributes().getValue("Implementation-Version"),
jdkHome.getAbsolutePath());
- if (!info.implementationVersion.equals(JDKInfo.UNKNOWN)) {
- // Make sure we have javac
- File jdkBin = new File(jdkHome, "bin");
- File[] javac = jdkBin.listFiles(new FilenameFilter() {
-
- public boolean accept(File dir, String name) {
- return name.toLowerCase().startsWith("javac");
- }
- });
- if (javac == null || javac.length == 0) {
- return null;
- }
- //javac located, we're good to go.
- debug("found JDK: " + info);
- return info;
- }
- return null;
+ debug("found JDK: " + info);
+ return info;
}
/**
@@ -704,10 +781,10 @@ public class PropertySetter extends Task
private String getJreLib(List<JDKInfo> jdks,
String specificationVersion, String vendor) {
// If we have no candidate JDKs, just return null at once.
- if (jdks == null || jdks.size() == 0) {
+ if (jdks == null || jdks.isEmpty()) {
+ debug("No candidate JDKs (version '" + specificationVersion + "')");
return null;
}
- final String jreLib = new File("jre", "lib").getPath();
ArrayList<JDKInfo> candidates = new ArrayList<JDKInfo>();
ArrayList<String> versions = new ArrayList<String>();
// Get the JDKs with the requested specification version.
@@ -723,7 +800,7 @@ public class PropertySetter extends Task
}
}
// See if we found any suitable JDKs.
- if (candidates.size() == 0) {
+ if (candidates.isEmpty()) {
debug("INFO: No valid JDK with specification " +
"version '" + specificationVersion + "' found");
return null;
@@ -749,7 +826,7 @@ public class PropertySetter extends Task
(targetVendor == null ? "ignored"
: jdkVendor) +
"): " + jdk);
- return new File(jdk.path, jreLib).getAbsolutePath();
+ return constructJreLibPath(jdk).getAbsolutePath();
}
}
}
@@ -758,6 +835,22 @@ public class PropertySetter extends Task
}
/**
+ * Constructs the path to the JRE library directory for the given JDK.
+ *
+ * @param jdk the target JDK
+ * @return A <tt>File</tt> object pointing to the JRE library directory.
+ */
+ private static File constructJreLibPath(JDKInfo jdk) {
+ String relLib;
+ if (jdk.vendor.startsWith(JDK_APPLE)) {
+ relLib = new File(APPLE_CLASSES_DIR).getPath();
+ } else {
+ relLib = new File("jre", "lib").getPath();
+ }
+ return new File(jdk.path, relLib);
+ }
+
+ /**
* Tells if the specified implementation version is representing a valid JDK
* version and if it satisfies the specification version.
*
@@ -765,15 +858,18 @@ public class PropertySetter extends Task
* @param specVersion the specification version to satisfy
* @return {@code true} if a valid version, {@code false} if not.
*/
- private static boolean isValidVersion(String implVersion,
+ private boolean isValidVersion(String implVersion,
String specVersion) {
// Don't allow null as a version.
if (implVersion == null) {
+ debug("JDK ignored, no impl version found");
return false;
}
// Don't allow early access versions.
// This rule should at least match Sun EA versions.
if (implVersion.contains("ea")) {
+ debug("JDK with version '" + implVersion + "' ignored: " +
+ "early access");
return false;
}
@@ -820,10 +916,14 @@ public class PropertySetter extends Task
* @return A normalized vendor name suitable for vendor name matching.
*/
private static String normalizeVendorName(String vendorName) {
- // Currently we only replace commas with the empty string. The reason
- // for doing this is that the vendor name specified in the jar file
- // manifest differes from the one return by the JVM itself for the Sun
- // JDKs. For instance:
+ // Normalize the vendore names returned by Apple JDKs.
+ if (vendorName.equals("Apple Inc.")) {
+ // The running VM says "Apple Inc.", the JAR manifest says
+ // "Apple Computer, Inc.".
+ vendorName = "Apple Computer, Inc.";
+ }
+ // The vendor name specified in the jar file manifest differes from the
+ // one return by the JVM itself for the Sun JDKs. For instance:
// - from JAR: Sun Microsystems, Inc.
// - from running VM: Sun Microsystems Inc.
// (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6851869)
@@ -993,6 +1093,11 @@ public class PropertySetter extends Task
PropertyHelper helper = PropertyHelper.getPropertyHelper( getProject() );
_propertiesSnapshot = helper.getProperties();
+
+ // Set the verbose debugging flag, it is used by static methods.
+ VERBOSE_DEBUG_ENABLED = Boolean.valueOf((String)
+ _propertiesSnapshot.get(PROPERTY_SETTER_VERBOSE_DEBUG_FLAG)
+ ).booleanValue();
}
/**
@@ -1217,9 +1322,56 @@ public class PropertySetter extends Task
* @param msg the message to print
*/
private void debug(CharSequence msg) {
- if (isSet(PROPERTY_SETTER_DEBUG_FLAG)) {
+ if (isSet(PROPERTY_SETTER_DEBUG_FLAG) ||
+ VERBOSE_DEBUG_ENABLED) {
System.out.println(msg);
}
}
-}
+ /**
+ * Emits a debug message to the console if verbose debugging is enabled.
+ * <p>
+ * Verbose debugging is controlled by
+ * {@linkplain #PROPERTY_SETTER_VERBOSE_DEBUG_FLAG}.
+ *
+ * @param msg the message to print
+ */
+ private static void verbose(CharSequence msg) {
+ if (VERBOSE_DEBUG_ENABLED) {
+ System.out.println("[verbose] " + msg);
+ }
+ }
+
+ /**
+ * A custom filter that accepts only directories and which in addition tries
+ * to ignore duplicates (i.e. symbolic links pointing into the same
+ * directory).
+ */
+ private static class JDKRootFileFilter
+ implements FileFilter {
+
+ private List<String> canonicalRoots = new ArrayList<String>();
+
+ /** Accepts only directories. */
+ public boolean accept(File pathname) {
+ if (pathname.isDirectory()) {
+ // Avoid processing the same JDK multiple times if possible.
+ try {
+ String canonicalRoot = pathname.getCanonicalPath();
+ boolean accept = !canonicalRoots.contains(canonicalRoot);
+ if (accept) {
+ canonicalRoots.add(canonicalRoot);
+ }
+ verbose((accept ? "candidate" : "duplicate") + " '" +
+ pathname + "' -> '" + canonicalRoot + "'");
+ return accept;
+ } catch (IOException ioe) {
+ // Ignore exception, just accept the directory.
+ verbose("file operation failed: " + ioe.getMessage());
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}