adding a -logdir flag to hosted mode; no more taking screenshots of interesting stuff.
Review by: jat
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6105 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java b/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
index 5b47004..02f8348 100644
--- a/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
+++ b/dev/core/src/com/google/gwt/dev/CompileTaskRunner.java
@@ -46,7 +46,8 @@
if (options.isUseGuiLogger()) {
// Initialize a tree logger window.
DetachedTreeLoggerWindow loggerWindow = DetachedTreeLoggerWindow.getInstance(
- "Build Output for " + options.getModuleNames(), 800, 600, true);
+ "Build Output for " + options.getModuleNames(), 800, 600, true,
+ options.getLogLevel());
// Eager AWT initialization for OS X to ensure safe coexistence with SWT.
BootStrapPlatform.initGui();
diff --git a/dev/core/src/com/google/gwt/dev/HostedModeBase.java b/dev/core/src/com/google/gwt/dev/HostedModeBase.java
index 1496a6d..44fd711 100644
--- a/dev/core/src/com/google/gwt/dev/HostedModeBase.java
+++ b/dev/core/src/com/google/gwt/dev/HostedModeBase.java
@@ -86,6 +86,37 @@
}
/**
+ * Handles the -logdir command line option.
+ */
+ protected static class ArgHandlerLogDir extends ArgHandlerString {
+ private final OptionLogDir options;
+
+ public ArgHandlerLogDir(OptionLogDir options) {
+ this.options = options;
+ }
+
+ @Override
+ public String getPurpose() {
+ return "Logs to a file in the given directory, as well as graphically";
+ }
+
+ @Override
+ public String getTag() {
+ return "-logdir";
+ }
+ @Override
+ public String[] getTagArgs() {
+ return new String[] {"directory"};
+ }
+
+ @Override
+ public boolean setString(String value) {
+ options.setLogFile(value);
+ return true;
+ }
+ }
+
+ /**
* Handles the -noserver command line flag.
*/
protected static class ArgHandlerNoServerFlag extends ArgHandlerFlag {
@@ -232,8 +263,9 @@
}
}
- protected interface HostedModeBaseOptions extends JJSOptions, OptionLogLevel,
- OptionGenDir, OptionNoServer, OptionPort, OptionStartupURLs {
+ protected interface HostedModeBaseOptions extends JJSOptions, OptionLogDir,
+ OptionLogLevel, OptionGenDir, OptionNoServer, OptionPort,
+ OptionStartupURLs {
/**
* The base shell work directory.
@@ -248,6 +280,7 @@
PrecompileOptionsImpl implements HostedModeBaseOptions {
private boolean isNoServer;
+ private File logDir;
private int port;
private final List<String> startupURLs = new ArrayList<String>();
@@ -255,6 +288,20 @@
startupURLs.add(url);
}
+ public boolean alsoLogToFile() {
+ return logDir != null;
+ }
+
+ public File getLogDir() {
+ return logDir;
+ }
+ public File getLogFile(String sublog) {
+ if (logDir == null) {
+ return null;
+ }
+ return new File(logDir, sublog);
+ }
+
public int getPort() {
return port;
}
@@ -271,6 +318,10 @@
return isNoServer;
}
+ public void setLogFile(String filename) {
+ logDir = new File(filename);
+ }
+
public void setNoServer(boolean isNoServer) {
this.isNoServer = isNoServer;
}
@@ -281,6 +332,20 @@
}
/**
+ * Controls whether and where to log data to file.
+ *
+ */
+ protected interface OptionLogDir {
+ boolean alsoLogToFile();
+
+ File getLogDir();
+
+ File getLogFile(String subfile);
+
+ void setLogFile(String filename);
+ }
+
+ /**
* Controls whether to run a server or not.
*
*/
@@ -317,6 +382,7 @@
registerHandler(new ArgHandlerPort(options));
registerHandler(new ArgHandlerWhitelist());
registerHandler(new ArgHandlerBlacklist());
+ registerHandler(new ArgHandlerLogDir(options));
registerHandler(new ArgHandlerLogLevel(options));
registerHandler(new ArgHandlerGenDir(options));
registerHandler(new ArgHandlerScriptStyle(options));
@@ -480,7 +546,7 @@
// Initialize the logger.
//
initializeLogger();
-
+
// Check for updates
final TreeLogger logger = getTopLogger();
final CheckForUpdates updateChecker
diff --git a/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java b/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
index 1633bfe..38ee586 100644
--- a/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
+++ b/dev/core/src/com/google/gwt/dev/SwtHostedModeBase.java
@@ -285,7 +285,9 @@
shell.setImages(ShellMainWindow.getIcons());
mainWnd = new ShellMainWindow(this, shell, getTitleText(),
- options.isNoServer() ? 0 : getPort());
+ options.isNoServer() ? 0 : getPort(),
+ options.alsoLogToFile() ? options.getLogFile("hosted.log") : null,
+ options.getLogLevel());
shell.setSize(700, 600);
if (!isHeadless()) {
diff --git a/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java b/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java
index 2af6125..8a3bebc 100644
--- a/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java
+++ b/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.shell.BrowserWindowController.WebServerRestart;
import com.google.gwt.dev.shell.log.TreeLoggerWidget;
import com.google.gwt.dev.util.Util;
@@ -38,6 +39,8 @@
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolItem;
+import java.io.File;
+
/**
* Implements the GWTShell's main window control.
*/
@@ -201,7 +204,8 @@
private Toolbar toolbar;
public ShellMainWindow(BrowserWindowController browserWindowController,
- Shell parent, String titleText, int serverPort) {
+ Shell parent, String titleText, int serverPort, File logFile,
+ Type logLevel) {
super(parent, SWT.NONE);
this.browserWindowController = browserWindowController;
@@ -235,7 +239,7 @@
// Create the log pane.
{
- logPane = new TreeLoggerWidget(this);
+ logPane = new TreeLoggerWidget(this, logFile, logLevel);
GridData data = new GridData();
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = true;
diff --git a/dev/core/src/com/google/gwt/dev/shell/log/DetachedTreeLoggerWindow.java b/dev/core/src/com/google/gwt/dev/shell/log/DetachedTreeLoggerWindow.java
index 5a44b99..0aaf638 100644
--- a/dev/core/src/com/google/gwt/dev/shell/log/DetachedTreeLoggerWindow.java
+++ b/dev/core/src/com/google/gwt/dev/shell/log/DetachedTreeLoggerWindow.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.shell.log;
+import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.shell.LowLevel;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
@@ -42,10 +43,10 @@
*/
public static synchronized DetachedTreeLoggerWindow getInstance(
final String caption, final int width, final int height,
- final boolean autoScroll) {
+ final boolean autoScroll, Type logLevel) {
if (singleton == null) {
singleton = new DetachedTreeLoggerWindow(caption, width, height,
- autoScroll);
+ autoScroll, logLevel);
}
return singleton;
}
@@ -55,7 +56,7 @@
private boolean isRunning = false;
private DetachedTreeLoggerWindow(final String caption, final int width,
- final int height, final boolean autoScroll) {
+ final int height, final boolean autoScroll, Type logLevel) {
shell = new Shell(Display.getCurrent());
shell.setText(caption);
@@ -64,7 +65,8 @@
fillLayout.marginHeight = 0;
shell.setLayout(fillLayout);
- final TreeLoggerWidget treeLoggerWidget = new TreeLoggerWidget(shell);
+ final TreeLoggerWidget treeLoggerWidget = new TreeLoggerWidget(shell, null,
+ logLevel);
treeLoggerWidget.setAutoScroll(autoScroll);
logger = treeLoggerWidget.getLogger();
diff --git a/dev/core/src/com/google/gwt/dev/shell/log/TreeLoggerWidget.java b/dev/core/src/com/google/gwt/dev/shell/log/TreeLoggerWidget.java
index 47f80d0..2bfc484 100644
--- a/dev/core/src/com/google/gwt/dev/shell/log/TreeLoggerWidget.java
+++ b/dev/core/src/com/google/gwt/dev/shell/log/TreeLoggerWidget.java
@@ -15,10 +15,14 @@
*/
package com.google.gwt.dev.shell.log;
+import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.HelpInfo;
+import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.shell.BrowserWidget;
import com.google.gwt.dev.shell.log.TreeItemLogger.LogEvent;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
+import com.google.gwt.dev.util.log.CompositeTreeLogger;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
@@ -43,6 +47,8 @@
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
+import java.io.File;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
@@ -57,11 +63,19 @@
private final Text details;
- private final TreeItemLogger logger;
+ private final AbstractTreeLogger logger;
+
+ private final TreeItemLogger uiLogger;
private final Tree tree;
- public TreeLoggerWidget(Composite parent) {
+ /**
+ * Creates a graphical widget, and optionally logging to file as well.
+ *
+ * @param parent the graphical interface parent
+ * @param logFile the file to log to
+ */
+ public TreeLoggerWidget(Composite parent, File logFile, Type logLevel) {
super(parent, SWT.NONE);
setLayout(new FillLayout());
@@ -97,7 +111,21 @@
}
});
- logger = new TreeItemLogger();
+ uiLogger = new TreeItemLogger();
+ AbstractTreeLogger bestLogger = uiLogger;
+ if (logFile != null) {
+ try {
+ PrintWriterTreeLogger fileLogger = new PrintWriterTreeLogger(logFile);
+ bestLogger = new CompositeTreeLogger(uiLogger, fileLogger);
+ fileLogger.setMaxDetail(logLevel);
+ uiLogger.setMaxDetail(logLevel);
+ } catch (IOException ex) {
+ uiLogger.log(TreeLogger.ERROR, "Can't log to " +
+ logFile.getAbsolutePath(), ex);
+ }
+ }
+ logger = bestLogger;
+ logger.setMaxDetail(logLevel);
// The detail
details = new Text(sash, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY | SWT.BORDER
@@ -238,7 +266,7 @@
return;
}
- if (logger.uiFlush(tree)) {
+ if (uiLogger.uiFlush(tree)) {
// Sync to the end of the tree.
//
if (autoScroll) {
diff --git a/dev/core/src/com/google/gwt/dev/util/log/AbstractTreeLogger.java b/dev/core/src/com/google/gwt/dev/util/log/AbstractTreeLogger.java
index 2c7af4c..d128e8d 100644
--- a/dev/core/src/com/google/gwt/dev/util/log/AbstractTreeLogger.java
+++ b/dev/core/src/com/google/gwt/dev/util/log/AbstractTreeLogger.java
@@ -85,15 +85,15 @@
}
public int indexWithinMyParent;
+
+ protected TreeLogger.Type logLevel = TreeLogger.ALL;
- private TreeLogger.Type logLevel = TreeLogger.ALL;
+ protected AbstractTreeLogger parent;
private int nextChildIndex;
private final Object nextChildIndexLock = new Object();
- private AbstractTreeLogger parent;
-
private UncommittedBranchData uncommitted;
/**
@@ -226,6 +226,38 @@
return getLoggerId();
}
+ protected int allocateNextChildIndex() {
+ synchronized (nextChildIndexLock) {
+ // postincrement because we want indices to start at 0
+ return nextChildIndex++;
+ }
+ }
+
+ /**
+ * Commits the branch after ensuring that the parent logger (if there is one)
+ * has been committed first.
+ */
+ protected synchronized void commitMyBranchEntryInMyParentLogger() {
+ // (Only the root logger doesn't have a parent.)
+ //
+ if (parent != null) {
+ if (uncommitted != null) {
+ // Commit the parent first.
+ //
+ parent.commitMyBranchEntryInMyParentLogger();
+
+ // Let the subclass do its thing to commit this branch.
+ //
+ parent.doCommitBranch(this, uncommitted.type, uncommitted.message,
+ uncommitted.caught, uncommitted.helpInfo);
+
+ // Release the uncommitted state.
+ //
+ uncommitted = null;
+ }
+ }
+ }
+
/**
* Derived classes should override this method to return a branched logger.
*/
@@ -267,13 +299,6 @@
protected abstract void doLog(int indexOfLogEntryWithinParentLogger,
TreeLogger.Type type, String msg, Throwable caught, HelpInfo helpInfo);
- private int allocateNextChildIndex() {
- synchronized (nextChildIndexLock) {
- // postincrement because we want indices to start at 0
- return nextChildIndex++;
- }
- }
-
/**
* Scans <code>t</code> and its causes for {@link OutOfMemoryError}.
*
@@ -293,31 +318,6 @@
return false;
}
- /**
- * Commits the branch after ensuring that the parent logger (if there is one)
- * has been committed first.
- */
- private synchronized void commitMyBranchEntryInMyParentLogger() {
- // (Only the root logger doesn't have a parent.)
- //
- if (parent != null) {
- if (uncommitted != null) {
- // Commit the parent first.
- //
- parent.commitMyBranchEntryInMyParentLogger();
-
- // Let the subclass do its thing to commit this branch.
- //
- parent.doCommitBranch(this, uncommitted.type, uncommitted.message,
- uncommitted.caught, uncommitted.helpInfo);
-
- // Release the uncommitted state.
- //
- uncommitted = null;
- }
- }
- }
-
private String getLoggerId() {
if (parent != null) {
if (parent.parent == null) {
diff --git a/dev/core/src/com/google/gwt/dev/util/log/CompositeTreeLogger.java b/dev/core/src/com/google/gwt/dev/util/log/CompositeTreeLogger.java
new file mode 100644
index 0000000..c88f461
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/log/CompositeTreeLogger.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 2008 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.util.log;
+
+/**
+ * Forks logging over two child loggers. This provides the graphics + file
+ * logging of HostedModeBase's -logfile option.
+ */
+public class CompositeTreeLogger extends AbstractTreeLogger {
+
+ private AbstractTreeLogger[] loggers;
+
+ public CompositeTreeLogger(AbstractTreeLogger... loggers) {
+ this.loggers = loggers;
+ }
+
+ @Override
+ protected AbstractTreeLogger doBranch() {
+ AbstractTreeLogger children[] = new AbstractTreeLogger[loggers.length];
+ for (int i = 0; i < loggers.length; i++) {
+ children[i] = loggers[i].doBranch();
+ children[i].indexWithinMyParent = loggers[i].allocateNextChildIndex();
+ children[i].parent = loggers[i];
+ children[i].logLevel = loggers[i].logLevel;
+ }
+ return new CompositeTreeLogger(children);
+ }
+
+ @Override
+ protected void doCommitBranch(AbstractTreeLogger childBeingCommitted,
+ Type type, String msg, Throwable caught, HelpInfo helpInfo) {
+ CompositeTreeLogger child = (CompositeTreeLogger) childBeingCommitted;
+ assert loggers.length == child.loggers.length;
+ for (int i = 0; i < loggers.length; i++) {
+ loggers[i].doCommitBranch(child.loggers[i], type, msg, caught, helpInfo);
+ }
+ }
+
+ @Override
+ protected void doLog(int indexOfLogEntryWithinParentLogger, Type type,
+ String msg, Throwable caught, HelpInfo helpInfo) {
+ for (AbstractTreeLogger logger : loggers) {
+ logger.doLog(indexOfLogEntryWithinParentLogger, type, msg, caught,
+ helpInfo);
+ }
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/util/log/PrintWriterTreeLogger.java b/dev/core/src/com/google/gwt/dev/util/log/PrintWriterTreeLogger.java
index cdd7843..6b75ab9 100644
--- a/dev/core/src/com/google/gwt/dev/util/log/PrintWriterTreeLogger.java
+++ b/dev/core/src/com/google/gwt/dev/util/log/PrintWriterTreeLogger.java
@@ -15,6 +15,9 @@
*/
package com.google.gwt.dev.util.log;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
@@ -26,6 +29,8 @@
private final String indent;
private final PrintWriter out;
+
+ private final Object mutex = new Object();
public PrintWriterTreeLogger() {
this(new PrintWriter(System.out, true));
@@ -34,12 +39,22 @@
public PrintWriterTreeLogger(PrintWriter out) {
this(out, "");
}
+
+ public PrintWriterTreeLogger(File logFile) throws IOException {
+ boolean existing = logFile.exists();
+ this.out = new PrintWriter(new FileWriter(logFile, true), true);
+ this.indent = "";
+ if (existing) {
+ out.println(); // blank line to mark relaunch
+ }
+ }
protected PrintWriterTreeLogger(PrintWriter out, String indent) {
this.out = out;
this.indent = indent;
}
+ @Override
protected AbstractTreeLogger doBranch() {
return new PrintWriterTreeLogger(out, indent + " ");
}
@@ -53,23 +68,25 @@
@Override
protected void doLog(int indexOfLogEntryWithinParentLogger, Type type,
String msg, Throwable caught, HelpInfo helpInfo) {
- out.print(indent);
- if (type.needsAttention()) {
- out.print("[");
- out.print(type.getLabel());
- out.print("] ");
- }
-
- out.println(msg);
- if (helpInfo != null) {
- URL url = helpInfo.getURL();
- if (url != null) {
- out.print(indent);
- out.println("For additional info see: " + url.toString());
+ synchronized (mutex) { // ensure thread interleaving...
+ out.print(indent);
+ if (type.needsAttention()) {
+ out.print("[");
+ out.print(type.getLabel());
+ out.print("] ");
}
- }
- if (caught != null) {
- caught.printStackTrace(out);
+
+ out.println(msg);
+ if (helpInfo != null) {
+ URL url = helpInfo.getURL();
+ if (url != null) {
+ out.print(indent);
+ out.println("For additional info see: " + url.toString());
+ }
+ }
+ if (caught != null) {
+ caught.printStackTrace(out);
+ }
}
}
}
diff --git a/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java b/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java
index 6a94906..a58d5cf 100644
--- a/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java
+++ b/dev/oophm/overlay/com/google/gwt/dev/shell/ShellMainWindow.java
@@ -21,6 +21,7 @@
import java.awt.BorderLayout;
import java.awt.GridLayout;
+import java.io.File;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
@@ -33,7 +34,7 @@
private SwingLoggerPanel logWindow;
- public ShellMainWindow(TreeLogger.Type maxLevel) {
+ public ShellMainWindow(TreeLogger.Type maxLevel, File logFile) {
super(new BorderLayout());
// TODO(jat): add back when we have real options
if (false) {
@@ -49,7 +50,7 @@
panel.add(launchPanel);
add(panel, BorderLayout.NORTH);
}
- logWindow = new SwingLoggerPanel(maxLevel);
+ logWindow = new SwingLoggerPanel(maxLevel, logFile);
add(logWindow);
}
diff --git a/dev/oophm/src/com/google/gwt/dev/ModulePanel.java b/dev/oophm/src/com/google/gwt/dev/ModulePanel.java
index f20ec84..281dd76 100644
--- a/dev/oophm/src/com/google/gwt/dev/ModulePanel.java
+++ b/dev/oophm/src/com/google/gwt/dev/ModulePanel.java
@@ -24,6 +24,7 @@
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.File;
import javax.swing.JButton;
import javax.swing.JOptionPane;
@@ -41,7 +42,7 @@
private boolean disconnected;
public ModulePanel(Type maxLevel, String moduleName,
- Session session) {
+ Session session, File logFile) {
super(new BorderLayout());
this.session = session;
if (false) {
@@ -57,7 +58,7 @@
topPanel.add(compileButton);
add(topPanel, BorderLayout.NORTH);
}
- loggerPanel = new SwingLoggerPanel(maxLevel);
+ loggerPanel = new SwingLoggerPanel(maxLevel, logFile);
add(loggerPanel);
session.addModule(moduleName, this);
}
diff --git a/dev/oophm/src/com/google/gwt/dev/ModuleTabPanel.java b/dev/oophm/src/com/google/gwt/dev/ModuleTabPanel.java
index e6b3107..196fa1a 100644
--- a/dev/oophm/src/com/google/gwt/dev/ModuleTabPanel.java
+++ b/dev/oophm/src/com/google/gwt/dev/ModuleTabPanel.java
@@ -17,7 +17,7 @@
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.OophmHostedModeBase.TabPanelCollection;
-import com.google.gwt.dev.shell.Icons;
+import com.google.gwt.dev.util.BrowserInfo;
import java.awt.BorderLayout;
import java.awt.CardLayout;
@@ -26,6 +26,7 @@
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;
@@ -226,40 +227,6 @@
}
/**
- * Holds information about the browser used in the UI.
- */
- private static class BrowserInfo {
-
- private final ImageIcon icon;
- private final String shortName;
-
- /**
- * Create a BrowserInfo instance.
- *
- * @param icon
- * @param shortName
- */
- public BrowserInfo(ImageIcon icon, String shortName) {
- this.icon = icon;
- this.shortName = shortName;
- }
-
- /**
- * @return the icon used to identify this browser, or null if none.
- */
- public ImageIcon getIcon() {
- return icon;
- }
-
- /**
- * @return the short name used to identify this browser, or null if none.
- */
- public String getShortName() {
- return shortName;
- }
- }
-
- /**
* Renderer used to show entries in the module dropdown box.
*/
private static class SessionModuleRenderer extends BasicComboBoxRenderer {
@@ -384,7 +351,7 @@
cardLayout = new CardLayout();
deckPanel.setLayout(cardLayout);
add(deckPanel);
- BrowserInfo browserInfo = getBrowserInfo(userAgent);
+ BrowserInfo browserInfo = BrowserInfo.getBrowserInfo(userAgent);
// Construct the tab title and tooltip
String tabTitle = url;
@@ -426,10 +393,11 @@
public synchronized ModulePanel addModuleSession(Type maxLevel,
String moduleName,
- String sessionKey) {
+ String sessionKey,
+ File logFile) {
Session session = findOrCreateSession(sessionKey);
- ModulePanel panel = new ModulePanel(maxLevel, moduleName, session);
+ ModulePanel panel = new ModulePanel(maxLevel, moduleName, session, logFile);
return panel;
}
@@ -479,32 +447,6 @@
return session;
}
- /**
- * Choose an icon appropriate for this browser, or null if none.
- *
- * @param userAgent User-Agent string from browser
- * @return icon or null if none
- */
- private BrowserInfo getBrowserInfo(String userAgent) {
- ImageIcon browserIcon = null;
- String shortName = null;
- String lcAgent = userAgent.toLowerCase();
- if (lcAgent.contains("msie")) {
- browserIcon = Icons.getIE24();
- shortName = "IE";
- } else if (lcAgent.contains("chrome")) {
- browserIcon = Icons.getChrome24();
- shortName = "Chrome";
- } else if (lcAgent.contains("webkit") || lcAgent.contains("safari")) {
- browserIcon = Icons.getSafari24();
- shortName = "Safari";
- } else if (lcAgent.contains("firefox")) {
- browserIcon = Icons.getFirefox24();
- shortName = "FF";
- }
- return new BrowserInfo(browserIcon, shortName);
- }
-
private String getTabTitle(URL parsedUrl) {
String tabTitle = parsedUrl.getPath();
if (tabTitle.length() > 0) {
diff --git a/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java b/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java
index bc3f169..b8930dd 100644
--- a/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java
+++ b/dev/oophm/src/com/google/gwt/dev/OophmHostedModeBase.java
@@ -27,6 +27,7 @@
import com.google.gwt.dev.shell.OophmSessionHandler;
import com.google.gwt.dev.shell.ShellMainWindow;
import com.google.gwt.dev.shell.ShellModuleSpaceHost;
+import com.google.gwt.dev.util.BrowserInfo;
import com.google.gwt.dev.util.collect.HashMap;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
@@ -35,6 +36,7 @@
import java.awt.Cursor;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.io.File;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
@@ -185,7 +187,10 @@
if (!isHeadless()) {
tabPanel = findModuleTab(userAgent, remoteSocket, url, tabKey,
moduleName);
- tab = tabPanel.addModuleSession(maxLevel, moduleName, sessionKey);
+ String agentTag = BrowserInfo.getShortName(userAgent).toLowerCase();
+ tab = tabPanel.addModuleSession(maxLevel, moduleName, sessionKey,
+ options.getLogFile(String.format("%s-%s-%d.log", moduleName,
+ agentTag, getNextSessionCounter(options.getLogDir()))));
logger = tab.getLogger();
TreeLogger branch = logger.branch(TreeLogger.INFO, "Loading module "
+ moduleName);
@@ -276,6 +281,8 @@
private static final Random RNG = new Random();
+ private static int sessionCounter = 0;
+
/**
* Produce a random string that has low probability of collisions.
*
@@ -448,6 +455,23 @@
return browserHost;
}
+ protected int getNextSessionCounter(File logdir) {
+ if (sessionCounter == 0) {
+ // first time only, figure out the "last" session count already in use
+ for (String filename : logdir.list()) {
+ if (filename.matches("^[A-Za-z0-9_$]*-[a-z]*-[0-9]*.log$")) {
+ String substring = filename.substring(filename.lastIndexOf('-') + 1,
+ filename.length() - 4);
+ int number = Integer.parseInt(substring);
+ if (number > sessionCounter) {
+ sessionCounter = number;
+ }
+ }
+ }
+ }
+ return ++sessionCounter;
+ }
+
/**
* @return the icon to use for the web server tab
*/
@@ -498,10 +522,15 @@
ImageIcon gwtIcon = loadImageIcon("icon24.png");
frame = new JFrame("GWT Development Mode");
tabs = new JTabbedPane();
- mainWnd = new ShellMainWindow(options.getLogLevel());
+ if (options.alsoLogToFile()) {
+ options.getLogDir().mkdirs();
+ }
+ mainWnd = new ShellMainWindow(options.getLogLevel(),
+ options.getLogFile("main.log"));
tabs.addTab("Development Mode", gwtIcon, mainWnd, "GWT Development mode");
if (!options.isNoServer()) {
webServerLog = new WebServerPanel(getPort(), options.getLogLevel(),
+ options.getLogFile("webserver.log"),
new RestartAction() {
public void restartServer(TreeLogger logger) {
try {
diff --git a/dev/oophm/src/com/google/gwt/dev/WebServerPanel.java b/dev/oophm/src/com/google/gwt/dev/WebServerPanel.java
index 4c45873..4fb3986 100644
--- a/dev/oophm/src/com/google/gwt/dev/WebServerPanel.java
+++ b/dev/oophm/src/com/google/gwt/dev/WebServerPanel.java
@@ -21,6 +21,7 @@
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.File;
import javax.swing.JButton;
import javax.swing.JPanel;
@@ -38,14 +39,15 @@
private SwingLoggerPanel logWindow;
- public WebServerPanel(int serverPort, TreeLogger.Type maxLevel) {
- this(serverPort, maxLevel, null);
+ public WebServerPanel(int serverPort, TreeLogger.Type maxLevel,
+ File logFile) {
+ this(serverPort, maxLevel, logFile, null);
}
public WebServerPanel(int serverPort, TreeLogger.Type maxLevel,
- final RestartAction restartServerAction) {
+ File logFile, final RestartAction restartServerAction) {
super(new BorderLayout());
- logWindow = new SwingLoggerPanel(maxLevel);
+ logWindow = new SwingLoggerPanel(maxLevel, logFile);
if (restartServerAction != null) {
JPanel panel = new JPanel();
JButton restartButton = new JButton("Restart Server");
diff --git a/dev/oophm/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java b/dev/oophm/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java
index c24a316..f530a15 100644
--- a/dev/oophm/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java
+++ b/dev/oophm/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java
@@ -21,6 +21,8 @@
import com.google.gwt.dev.shell.CloseButton.Callback;
import com.google.gwt.dev.shell.log.SwingTreeLogger.LogEvent;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
+import com.google.gwt.dev.util.log.CompositeTreeLogger;
+import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import java.awt.BorderLayout;
import java.awt.Color;
@@ -35,6 +37,8 @@
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
@@ -264,7 +268,7 @@
private boolean disconnected = false;
- public SwingLoggerPanel(TreeLogger.Type maxLevel) {
+ public SwingLoggerPanel(TreeLogger.Type maxLevel, File logFile) {
super(new BorderLayout());
regexFilter = "";
levelFilter = maxLevel;
@@ -368,8 +372,22 @@
treeView.setMinimumSize(minSize);
splitter.setDividerLocation(0.80);
add(splitter);
- logger = new SwingTreeLogger(this);
- logger.setMaxDetail(maxLevel);
+
+ AbstractTreeLogger uiLogger = new SwingTreeLogger(this);
+ AbstractTreeLogger bestLogger = uiLogger;
+ if (logFile != null) {
+ try {
+ PrintWriterTreeLogger fileLogger = new PrintWriterTreeLogger(logFile);
+ bestLogger = new CompositeTreeLogger(bestLogger, fileLogger);
+ fileLogger.setMaxDetail(maxLevel);
+ uiLogger.setMaxDetail(maxLevel);
+ } catch (IOException ex) {
+ bestLogger.log(TreeLogger.ERROR, "Can't log to file "
+ + logFile.getAbsolutePath(), ex);
+ }
+ }
+ bestLogger.setMaxDetail(maxLevel);
+ logger = bestLogger;
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_F,
InputEvent.CTRL_DOWN_MASK);
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "find");
diff --git a/dev/oophm/src/com/google/gwt/dev/util/BrowserInfo.java b/dev/oophm/src/com/google/gwt/dev/util/BrowserInfo.java
new file mode 100644
index 0000000..8519f14
--- /dev/null
+++ b/dev/oophm/src/com/google/gwt/dev/util/BrowserInfo.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2009 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.util;
+
+import com.google.gwt.dev.shell.Icons;
+
+import javax.swing.ImageIcon;
+
+/**
+ * Holds information about the browser used in the UI.
+ */
+public class BrowserInfo {
+
+ private static final String UNKNOWN = "Unknown";
+ private static final String FIREFOX = "FF";
+ private static final String SAFARI = "Safari";
+ private static final String OPERA = "Opera";
+ private static final String CHROME = "Chrome";
+ private static final String IE = "IE";
+
+ /**
+ * Choose an icon and short name appropriate for this browser. The icon
+ * may be null.
+ *
+ * @param userAgent User-Agent string from browser
+ * @return icon or null if none
+ */
+ public static BrowserInfo getBrowserInfo(String userAgent) {
+ ImageIcon browserIcon = null;
+ String shortName = getShortName(userAgent);
+ if (shortName.equals(IE)) {
+ browserIcon = Icons.getIE24();
+ } else if (shortName.equals(CHROME)) {
+ browserIcon = Icons.getChrome24();
+ } else if (shortName.equals(OPERA)) {
+ browserIcon = Icons.getOpera24();
+ } else if (shortName.equals(SAFARI)) {
+ browserIcon = Icons.getSafari24();
+ } else if (shortName.equals(FIREFOX)) {
+ browserIcon = Icons.getFirefox24();
+ }
+ return new BrowserInfo(browserIcon, shortName);
+ }
+
+ public static String getShortName(String userAgent) {
+ String lcAgent = userAgent.toLowerCase();
+ if (lcAgent.contains("msie")) {
+ return IE;
+ } else if (lcAgent.contains("chrome")) {
+ return CHROME;
+ } else if (lcAgent.contains("opera")) {
+ return OPERA;
+ } else if (lcAgent.contains("webkit") || lcAgent.contains("safari")) {
+ return SAFARI;
+ } else if (lcAgent.contains("firefox")) {
+ return FIREFOX;
+ }
+ return UNKNOWN;
+ }
+ private final ImageIcon icon;
+ private final String shortName;
+
+ /**
+ * Create a BrowserInfo instance.
+ *
+ * @param icon
+ * @param shortName
+ */
+ private BrowserInfo(ImageIcon icon, String shortName) {
+ this.icon = icon;
+ this.shortName = shortName;
+ }
+
+ /**
+ * @return the icon used to identify this browser, or null if none.
+ */
+ public ImageIcon getIcon() {
+ return icon;
+ }
+
+ /**
+ * @return the short name used to identify this browser, or null if none.
+ */
+ public String getShortName() {
+ return shortName;
+ }
+}
\ No newline at end of file