Revision: 8052
Author: [email protected]
Date: Wed May 5 10:04:19 2010
Log: Fix GWT logging in Devmode
Review at http://gwt-code-reviews.appspot.com/437801
Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=8052
Added:
/branches/2.1/dev/core/src/com/google/gwt/dev/shell/DevModeLogManager.java
/branches/2.1/dev/core/test/com/google/gwt/dev/DevModeBaseTest.java
/branches/2.1/dev/core/test/com/google/gwt/dev/shell/DevModeLogManagerTest.java
Modified:
/branches/2.1/dev/core/src/com/google/gwt/dev/DevModeBase.java
/branches/2.1/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
=======================================
--- /dev/null
+++
/branches/2.1/dev/core/src/com/google/gwt/dev/shell/DevModeLogManager.java
Wed May 5 10:04:19 2010
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.dev.shell;
+
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+/**
+ * A log manager which delegates to different instances for client
+ * code so that the client and server code do not share a root logger and
try
+ * to log to each other's handlers.
+ */
+public class DevModeLogManager extends LogManager {
+ static class LogManagerWithExposedConstructor extends LogManager {
+ public LogManagerWithExposedConstructor() {
+ super();
+ }
+ }
+
+ protected ThreadLocal<LogManager> clientLogManager =
+ new ThreadLocal<LogManager>() {
+ public LogManager initialValue() {
+ return new LogManagerWithExposedConstructor();
+ }
+ };
+
+ public DevModeLogManager() {
+ if (System.getProperty("java.util.logging.oldLogManager") != null) {
+ // TODO(unnurg): Instantiate the class stored in oldLogManager and
+ // delegate calls to there.
+ System.err.println(
+ "[WARN] ignoring user-specified value '" +
+ System.getProperty("java.util.logging.oldLogManager") +
+ "' for java.util.logging.manager");
+ }
+ }
+
+ @Override
+ public boolean addLogger(Logger logger) {
+ if (isClientCode()) {
+ return clientLogManager.get().addLogger(logger);
+ }
+ return super.addLogger(logger);
+ }
+
+ @Override
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ if (isClientCode()) {
+ clientLogManager.get().addPropertyChangeListener(l);
+ }
+ super.addPropertyChangeListener(l);
+ }
+
+ @Override
+ public void checkAccess() {
+ if (isClientCode()) {
+ clientLogManager.get().checkAccess();
+ }
+ super.checkAccess();
+ }
+
+ @Override
+ public Logger getLogger(String name) {
+ if (isClientCode()) {
+ return clientLogManager.get().getLogger(name);
+ }
+ return super.getLogger(name);
+ }
+
+ @Override
+ public Enumeration<String> getLoggerNames() {
+ if (isClientCode()) {
+ return clientLogManager.get().getLoggerNames();
+ }
+ return super.getLoggerNames();
+ }
+
+ @Override
+ public String getProperty(String name) {
+ if (isClientCode()) {
+ return clientLogManager.get().getProperty(name);
+ }
+ return super.getProperty(name);
+ }
+
+ @Override
+ public void readConfiguration() throws IOException, SecurityException {
+ if (isClientCode()) {
+ clientLogManager.get().readConfiguration();
+ }
+ super.readConfiguration();
+ }
+
+ @Override
+ public void readConfiguration(InputStream ins) throws IOException,
+ SecurityException {
+ if (isClientCode()) {
+ clientLogManager.get().readConfiguration(ins);
+ }
+ super.readConfiguration(ins);
+ }
+
+ @Override
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ if (isClientCode()) {
+ clientLogManager.get().removePropertyChangeListener(l);
+ }
+ super.removePropertyChangeListener(l);
+ }
+
+ @Override
+ public void reset() {
+ if (isClientCode()) {
+ clientLogManager.get().reset();
+ }
+ super.reset();
+ }
+
+ protected boolean isClientCode() {
+ return (Thread.currentThread() instanceof
+ BrowserChannelServer.CodeServerThread);
+ }
+}
=======================================
--- /dev/null
+++ /branches/2.1/dev/core/test/com/google/gwt/dev/DevModeBaseTest.java Wed
May 5 10:04:19 2010
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.dev;
+
+import junit.framework.TestCase;
+
+public class DevModeBaseTest extends TestCase {
+ static final String MANAGER_PROPERTY = "java.util.logging.manager";
+ static final String NEW_MANAGER
= "com.google.gwt.dev.shell.DevModeLogManager";
+ static final String OLD_MANAGER_PROPERTY
= "java.util.logging.oldLogManager";
+ static final String USERS_MANAGER = "UsersLogManager";
+
+ public void testSetLogManager() {
+ assertEquals(null, System.getProperty(MANAGER_PROPERTY));
+ assertEquals(null, System.getProperty(OLD_MANAGER_PROPERTY));
+
+ DevModeBase.setLogManager();
+ assertEquals(NEW_MANAGER, System.getProperty(MANAGER_PROPERTY));
+ assertEquals(null, System.getProperty(OLD_MANAGER_PROPERTY));
+
+ System.setProperty(MANAGER_PROPERTY, USERS_MANAGER);
+ DevModeBase.setLogManager();
+ assertEquals(NEW_MANAGER, System.getProperty(MANAGER_PROPERTY));
+ assertEquals(USERS_MANAGER, System.getProperty(OLD_MANAGER_PROPERTY));
+ }
+
+}
=======================================
--- /dev/null
+++
/branches/2.1/dev/core/test/com/google/gwt/dev/shell/DevModeLogManagerTest.java
Wed May 5 10:04:19 2010
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.dev.shell;
+
+import junit.framework.TestCase;
+
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+
+public class DevModeLogManagerTest extends TestCase {
+ private static String LOGGER_1_NAME = "Logger1";
+ private static String LOGGER_2_NAME = "Logger2";
+
+ /**
+ * Mocks out the detection of client code since I don't know how to
change
+ * Thread.currentThread to be an instance of CodeServerThread in a unit
test.
+ */
+ protected static class DevModeManagerMock extends DevModeLogManager {
+ private boolean isClientCode = false;
+
+ public void setIsClientCode(boolean value) {
+ isClientCode = value;
+ }
+
+ @Override
+ protected boolean isClientCode() {
+ return isClientCode;
+ }
+ }
+
+ public void testDelegation() {
+ Logger logger1 = Logger.getLogger(LOGGER_1_NAME);
+ Logger logger2 = Logger.getLogger(LOGGER_2_NAME);
+ DevModeManagerMock devManager = new DevModeManagerMock();
+ LogManager delegate = devManager.clientLogManager.get();
+ assertNull(devManager.getLogger(LOGGER_1_NAME));
+ assertNull(devManager.getLogger(LOGGER_2_NAME));
+ assertNull(delegate.getLogger(LOGGER_1_NAME));
+ assertNull(delegate.getLogger(LOGGER_2_NAME));
+
+ // devManager delegates to the delegate
+ devManager.setIsClientCode(false);
+ devManager.addLogger(logger1);
+ assertNotNull(devManager.getLogger(LOGGER_1_NAME));
+ assertNull(delegate.getLogger(LOGGER_1_NAME));
+
+ // devManager delegates to super
+ devManager.setIsClientCode(true);
+ devManager.addLogger(logger2);
+ assertNotNull(devManager.getLogger(LOGGER_2_NAME));
+ assertNotNull(delegate.getLogger(LOGGER_2_NAME));
+ }
+
+}
=======================================
--- /branches/2.1/dev/core/src/com/google/gwt/dev/DevModeBase.java Fri Apr
23 06:39:33 2010
+++ /branches/2.1/dev/core/src/com/google/gwt/dev/DevModeBase.java Wed May
5 10:04:19 2010
@@ -62,7 +62,7 @@
* The main executable class for the hosted mode shell. This class must
not have
* any GUI dependencies.
*/
-public abstract class DevModeBase implements DoneCallback {
+abstract class DevModeBase implements DoneCallback {
/**
* Implementation of BrowserWidgetHost that supports the abstract UI
@@ -165,9 +165,6 @@
* Handles the -blacklist command line argument.
*/
protected static class ArgHandlerBlacklist extends ArgHandlerString {
- public ArgHandlerBlacklist() {
- }
-
@Override
public String getPurpose() {
return "Prevents the user browsing URLs that match the specified
regexes (comma or space separated)";
@@ -346,9 +343,6 @@
}
}
- /**
- * Handles the -remoteUI command line flag.
- */
protected static class ArgHandlerRemoteUI extends ArgHandlerString {
private final HostedModeBaseOptions options;
@@ -413,9 +407,6 @@
* Handles the -whitelist command line flag.
*/
protected static class ArgHandlerWhitelist extends ArgHandlerString {
- public ArgHandlerWhitelist() {
- }
-
@Override
public String getPurpose() {
return "Allows the user to browse URLs that match the specified
regexes (comma or space separated)";
@@ -437,9 +428,6 @@
}
}
- /**
- * Base options for dev mode.
- */
protected interface HostedModeBaseOptions extends JJSOptions,
OptionLogDir,
OptionLogLevel, OptionGenDir, OptionNoServer, OptionPort,
OptionCodeServerPort, OptionStartupURLs, OptionRemoteUI,
@@ -560,9 +548,6 @@
}
}
- /**
- * Controls what local address to bind to.
- */
protected interface OptionBindAddress {
String getBindAddress();
@@ -573,9 +558,6 @@
void setConnectAddress(String connectAddress);
}
- /**
- * Controls what port the code server listens on.
- */
protected interface OptionCodeServerPort {
int getCodeServerPort();
@@ -644,10 +626,7 @@
List<String> getStartupURLs();
}
- /**
- * The base dev mode argument processor.
- */
- protected abstract static class ArgProcessor extends ArgProcessorBase {
+ abstract static class ArgProcessor extends ArgProcessorBase {
public ArgProcessor(HostedModeBaseOptions options, boolean
forceServer) {
if (!forceServer) {
registerHandler(new ArgHandlerNoServerFlag(options));
@@ -709,6 +688,19 @@
}
return buf.toString();
}
+
+ /**
+ * Set up the system to use a DevModeLogManager, which will delegate to
+ * different LogManager instances for client and server code.
+ */
+ protected static void setLogManager() {
+ String oldLogManager = System.getProperty("java.util.logging.manager");
+ if (oldLogManager != null) {
+ System.setProperty("java.util.logging.oldLogManager", oldLogManager);
+ }
+ System.setProperty("java.util.logging.manager",
+ "com.google.gwt.dev.shell.DevModeLogManager");
+ }
protected TreeLogger.Type baseLogLevelForUI = null;
@@ -785,6 +777,9 @@
// Eager AWT init for OS X to ensure safe coexistence with SWT.
BootStrapPlatform.initGui();
+ // Ensure that client and server logging does not share a root logger
+ setLogManager();
+
boolean success = startUp();
// The web server is running now, so launch browsers for startup
urls.
@@ -1133,7 +1128,7 @@
newlyGeneratedArtifacts);
produceOutput(linkLogger, linkerContext, artifacts, module, true);
}
-
+
/**
* Set the set of startup URLs. This is done before launching to allow
the UI
* to better present the options to the user, but note that the UI
should not
=======================================
---
/branches/2.1/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
Fri Feb 19 06:35:15 2010
+++
/branches/2.1/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
Wed May 5 10:04:19 2010
@@ -35,6 +35,16 @@
*/
public class BrowserChannelServer extends BrowserChannel
implements Runnable {
+
+ /**
+ * Does not extend the Thread functionality in any way. We use instanceof
+ * checks elsewhere in the code to check for this particular thread.
+ */
+ public static class CodeServerThread extends Thread {
+ private CodeServerThread(BrowserChannelServer browserChannelServer) {
+ super(browserChannelServer);
+ }
+ }
/**
* Hook interface for responding to messages from the client.
@@ -670,7 +680,7 @@
private void init(TreeLogger initialLogger) {
this.logger = initialLogger;
- Thread thread = new Thread(this);
+ Thread thread = new CodeServerThread(this);
thread.setDaemon(true);
thread.setName("Code server (initializing)");
thread.start();
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors