From 5d6d27907dc89bd183db003513d9d90892281575 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Sun, 14 Oct 2012 13:54:08 +0000 Subject: [PATCH] * Console: Use non-nio connector for Java 5 and JamVM/gij (tickets #715 and #743) * SystemVersion: Centralize more methods here --- .../i2p/router/web/RouterConsoleRunner.java | 50 +++++++++++++++---- .../net/i2p/router/web/StatSummarizer.java | 8 ++- core/java/src/net/i2p/crypto/SHA1.java | 8 +-- .../net/i2p/util/ReusableGZIPInputStream.java | 2 +- .../i2p/util/ReusableGZIPOutputStream.java | 2 +- core/java/src/net/i2p/util/SystemVersion.java | 27 +++++++++- installer/resources/eepsite/jetty.xml | 4 +- 7 files changed, 76 insertions(+), 25 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java index e361df3ebb..488c5b655d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java @@ -34,11 +34,14 @@ import net.i2p.util.PortMapper; import net.i2p.util.SecureDirectory; import net.i2p.util.SecureFileOutputStream; import net.i2p.util.ShellCommand; +import net.i2p.util.SystemVersion; import net.i2p.util.VersionComparator; +import org.mortbay.jetty.AbstractConnector; import org.mortbay.jetty.Connector; import org.mortbay.jetty.NCSARequestLog; import org.mortbay.jetty.Server; +import org.mortbay.jetty.bio.SocketConnector; import org.mortbay.jetty.handler.ContextHandlerCollection; import org.mortbay.jetty.handler.DefaultHandler; import org.mortbay.jetty.handler.HandlerCollection; @@ -49,6 +52,7 @@ import org.mortbay.jetty.security.HashUserRealm; import org.mortbay.jetty.security.Constraint; import org.mortbay.jetty.security.ConstraintMapping; import org.mortbay.jetty.security.SecurityHandler; +import org.mortbay.jetty.security.SslSocketConnector; import org.mortbay.jetty.security.SslSelectChannelConnector; import org.mortbay.jetty.servlet.ServletHandler; import org.mortbay.jetty.servlet.ServletHolder; @@ -177,8 +181,7 @@ public class RouterConsoleRunner { try { //TODO: move away from routerconsole into a separate application. //ApplicationManager? - VersionComparator v = new VersionComparator(); - boolean recentJava = v.compare(System.getProperty("java.runtime.version"), "1.6") >= 0; + boolean recentJava = SystemVersion.isJava6(); // default false for now boolean desktopguiEnabled = I2PAppContext.getGlobalContext().getBooleanProperty("desktopgui.enabled"); if (recentJava && desktopguiEnabled) { @@ -334,12 +337,22 @@ public class RouterConsoleRunner { // _server.addListener('[' + host + "]:" + _listenPort); //else // _server.addListener(host + ':' + _listenPort); - SelectChannelConnector lsnr = new SelectChannelConnector(); + AbstractConnector lsnr; + if (SystemVersion.isJava6() && !SystemVersion.isGNU()) { + SelectChannelConnector slsnr = new SelectChannelConnector(); + slsnr.setUseDirectBuffers(false); // default true seems to be leaky + lsnr = slsnr; + } else { + // Jetty 6 and NIO on Java 5 don't get along that well + // Also: http://jira.codehaus.org/browse/JETTY-1238 + // "Do not use GCJ with Jetty, it will not work." + // Actually it does if you don't use NIO + lsnr = new SocketConnector(); + } lsnr.setHost(host); lsnr.setPort(lport); lsnr.setMaxIdleTime(90*1000); // default 10 sec lsnr.setName("ConsoleSocket"); // all with same name will use the same thread pool - lsnr.setUseDirectBuffers(false); // default true seems to be leaky //_server.addConnector(lsnr); connectors.add(lsnr); boundAddresses++; @@ -389,22 +402,37 @@ public class RouterConsoleRunner { } // TODO if class not found use SslChannelConnector // Sadly there's no common base class with the ssl methods in it - SslSelectChannelConnector ssll = new SslSelectChannelConnector(); - ssll.setHost(host); - ssll.setPort(sslPort); + AbstractConnector ssll; + if (SystemVersion.isJava6() && !SystemVersion.isGNU()) { + SslSelectChannelConnector sssll = new SslSelectChannelConnector(); + // the keystore path and password + sssll.setKeystore(keyStore.getAbsolutePath()); + sssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD)); + // the X.509 cert password (if not present, verifyKeyStore() returned false) + sssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork")); + sssll.setUseDirectBuffers(false); // default true seems to be leaky + ssll = sssll; + } else { + // Jetty 6 and NIO on Java 5 don't get along that well + SslSocketConnector sssll = new SslSocketConnector(); // the keystore path and password - ssll.setKeystore(keyStore.getAbsolutePath()); - ssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD)); + sssll.setKeystore(keyStore.getAbsolutePath()); + sssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD)); // the X.509 cert password (if not present, verifyKeyStore() returned false) - ssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork")); + sssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork")); + ssll = sssll; + } + ssll.setHost(host); + ssll.setPort(sslPort); ssll.setMaxIdleTime(90*1000); // default 10 sec ssll.setName("ConsoleSocket"); // all with same name will use the same thread pool - ssll.setUseDirectBuffers(false); // default true seems to be leaky //_server.addConnector(ssll); connectors.add(ssll); boundAddresses++; } catch (Exception e) { System.err.println("Unable to bind routerconsole to " + host + " port " + sslPort + " for SSL: " + e); + if (SystemVersion.isGNU()) + System.err.println("Probably because GNU classpath does not support Sun keystores"); System.err.println("You may ignore this warning if the console is still available at https://localhost:" + sslPort); } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java index 825133c0ee..199cf5e4e3 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java @@ -67,12 +67,10 @@ public class StatSummarizer implements Runnable { public void run() { // JRobin 1.5.9 crashes these JVMs - String vendor = System.getProperty("java.vendor"); - if (vendor.startsWith("Apache") || // Harmony - vendor.startsWith("GNU Classpath") || // JamVM - vendor.startsWith("Free Software Foundation")) { // gij + if (SystemVersion.isApache() || // Harmony + SystemVersion.isGNU()) { // JamVM or gij _log.logAlways(Log.WARN, "Graphing not supported with this JVM: " + - vendor + ' ' + + System.getProperty("java.vendor") + ' ' + System.getProperty("java.version") + " (" + System.getProperty("java.runtime.name") + ' ' + System.getProperty("java.runtime.version") + ')'); diff --git a/core/java/src/net/i2p/crypto/SHA1.java b/core/java/src/net/i2p/crypto/SHA1.java index 7ea68de562..bfe07630ca 100644 --- a/core/java/src/net/i2p/crypto/SHA1.java +++ b/core/java/src/net/i2p/crypto/SHA1.java @@ -20,6 +20,8 @@ import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import net.i2p.util.SystemVersion; + /** * NOTE: As of 0.8.7, use getInstance() instead of new SHA1(), which will * return the JVM's MessageDigest if it is faster. @@ -94,10 +96,8 @@ public final class SHA1 extends MessageDigest implements Cloneable { static { // oddly, Bitzi is faster than Oracle - see test results below boolean useBitzi = true; - String vendor = System.getProperty("java.vendor"); - if (vendor.startsWith("Apache") || // Harmony - vendor.startsWith("GNU Classpath") || // JamVM - vendor.startsWith("Free Software Foundation")) { // gij + if (SystemVersion.isApache() || // Harmony + SystemVersion.isGNU()) { // JamVM or gij try { MessageDigest.getInstance("SHA-1"); useBitzi = false; diff --git a/core/java/src/net/i2p/util/ReusableGZIPInputStream.java b/core/java/src/net/i2p/util/ReusableGZIPInputStream.java index f09c9711c3..5ef5b7801f 100644 --- a/core/java/src/net/i2p/util/ReusableGZIPInputStream.java +++ b/core/java/src/net/i2p/util/ReusableGZIPInputStream.java @@ -9,7 +9,7 @@ import java.util.concurrent.LinkedBlockingQueue; public class ReusableGZIPInputStream extends ResettableGZIPInputStream { // Apache Harmony 5.0M13 Deflater doesn't work after reset() // Neither does Android - private static final boolean ENABLE_CACHING = !(System.getProperty("java.vendor").startsWith("Apache") || + private static final boolean ENABLE_CACHING = !(SystemVersion.isApache() || SystemVersion.isAndroid()); private static final LinkedBlockingQueue<ReusableGZIPInputStream> _available; static { diff --git a/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java b/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java index fe686095e4..3cbf1dd335 100644 --- a/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java +++ b/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java @@ -20,7 +20,7 @@ import net.i2p.data.DataHelper; public class ReusableGZIPOutputStream extends ResettableGZIPOutputStream { // Apache Harmony 5.0M13 Deflater doesn't work after reset() // Neither does Android - private static final boolean ENABLE_CACHING = !(System.getProperty("java.vendor").startsWith("Apache") || + private static final boolean ENABLE_CACHING = !(SystemVersion.isApache() || SystemVersion.isAndroid()); private static final LinkedBlockingQueue<ReusableGZIPOutputStream> _available; static { diff --git a/core/java/src/net/i2p/util/SystemVersion.java b/core/java/src/net/i2p/util/SystemVersion.java index d43cddc898..484a293238 100644 --- a/core/java/src/net/i2p/util/SystemVersion.java +++ b/core/java/src/net/i2p/util/SystemVersion.java @@ -15,14 +15,23 @@ public abstract class SystemVersion { private static final boolean _isWin = System.getProperty("os.name").startsWith("Win"); private static final boolean _isMac = System.getProperty("os.name").startsWith("Mac"); - private static final boolean _isAndroid = System.getProperty("java.vendor").contains("Android"); + private static final boolean _isAndroid; + private static final boolean _isApache; + private static final boolean _isGNU; private static final boolean _is64 = "64".equals(System.getProperty("sun.arch.data.model")) || System.getProperty("os.arch").contains("64"); + private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null; private static final boolean _oneDotSix; private static final int _androidSDK; static { + String vendor = System.getProperty("java.vendor"); + _isAndroid = vendor.contains("Android"); + _isApache = vendor.startsWith("Apache"); + _isGNU = vendor.startsWith("GNU Classpath") || // JamVM + vendor.startsWith("Free Software Foundation"); // gij + int sdk = 0; if (_isAndroid) { try { @@ -52,6 +61,20 @@ public abstract class SystemVersion { return _isAndroid; } + /** + * Apache Harmony JVM, or Android + */ + public static boolean isApache() { + return _isApache || _isAndroid; + } + + /** + * gij or JamVM with GNU Classpath + */ + public static boolean isGNU() { + return _isGNU; + } + /** * Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0 * as it handles Android also, where java.version = "0". @@ -90,6 +113,6 @@ public abstract class SystemVersion { * Same as I2PAppContext.hasWrapper() */ public static boolean hasWrapper() { - return System.getProperty("wrapper.version") != null; + return _hasWrapper; } } diff --git a/installer/resources/eepsite/jetty.xml b/installer/resources/eepsite/jetty.xml index ba30a55ebd..0e873ca770 100644 --- a/installer/resources/eepsite/jetty.xml +++ b/installer/resources/eepsite/jetty.xml @@ -90,7 +90,9 @@ <!-- Use this connector for many frequently idle connections and for threadless continuations. - Not recommended on Java 5 - comment out and uncomment the + Not recommended on Java 5 - comment this out, and uncomment the + SocketConnector below. + Do not use for gij or JamVM - comment this out, and uncomment the SocketConnector below. --> <Call name="addConnector"> -- GitLab