/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.framework.internal;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.util.Iterator;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
import java.util.prefs.Preferences;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import org.eclipse.persistence.tools.workbench.framework.Application;
import org.eclipse.persistence.tools.workbench.framework.NodeManager;
import org.eclipse.persistence.tools.workbench.framework.action.ActionRepository;
import org.eclipse.persistence.tools.workbench.framework.app.NavigatorSelectionModel;
import org.eclipse.persistence.tools.workbench.framework.context.AbstractApplicationContext;
import org.eclipse.persistence.tools.workbench.framework.context.AbstractWorkbenchContext;
import org.eclipse.persistence.tools.workbench.framework.context.ApplicationContext;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContext;
import org.eclipse.persistence.tools.workbench.framework.help.HelpManager;
import org.eclipse.persistence.tools.workbench.framework.resources.ResourceRepository;
import org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog;
import org.eclipse.persistence.tools.workbench.framework.ui.dialog.TextAreaDialog;
import org.eclipse.persistence.tools.workbench.utility.iterators.SingleElementIterator;
/**
* Hacked up dialog for notifying the user of a SEVERE log entry,
* typically an unhandled exception.
*
* The main "hacking" occurs when we go searching for a workbench
* window to use as a "owner" window. Even then, an "owner" is not
* required.
*/
final class FrameworkLogHandlerDialog
extends AbstractDialog
{
/** the log record that triggered this dialog */
private LogRecord logRecord;
/** this will localize the log record's message */
private Formatter logFormatter;
// ********** static methods **********
/**
* Try to find a workbench window to use as a parent.
* This might return null....
*/
private static WorkbenchWindow findWindow() {
WorkbenchWindow anyWindow = null;
WorkbenchWindow focusWindow = null;
Frame[] frames = Frame.getFrames();
for (int i = 0; i < frames.length; i++) {
Frame frame = frames[i];
if (frame instanceof WorkbenchWindow) {
WorkbenchWindow ww = (WorkbenchWindow) frame;
if (ww.isFocusOwner()) {
focusWindow = ww;
break;
}
if (anyWindow == null) {
anyWindow = ww;
}
}
}
return (focusWindow == null) ? anyWindow : focusWindow;
}
/**
* Hack together a workbench context to pass to the dialog.
*/
private static WorkbenchContext buildContext(FrameworkApplication application) {
return new LocalWorkbenchContext(application, findWindow());
}
// ********** constructor **********
/**
* Construct a dialog for the specified log record.
*/
public FrameworkLogHandlerDialog(FrameworkApplication application, LogRecord logRecord) {
super(buildContext(application), application.getResourceRepository().getString("UNEXPECTED_ERROR"));
this.logRecord = logRecord;
this.logFormatter = new SimpleFormatter();
}
// ********** AbstractDialog implementation **********
/**
* The main panel merely consists of a label or two.
* @see org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog#buildMainPanel()
*/
protected Component buildMainPanel() {
JPanel mainPanel = new JPanel(new GridLayout(0, 1));
JLabel messageLabel = new JLabel();
messageLabel.setText(this.logFormatter.formatMessage(this.logRecord));
messageLabel.setIcon(this.resourceRepository().getIcon("error"));
messageLabel.setHorizontalAlignment(SwingConstants.CENTER);
mainPanel.add(messageLabel);
if (this.logRecord.getThrown() != null) {
JTextArea textArea = new JTextArea(this.logRecord.getThrown().toString());
textArea.setFont(messageLabel.getFont());
textArea.setTabSize(2);
mainPanel.add(new JScrollPane(textArea));
}
mainPanel.setPreferredSize(new Dimension(350, Math.min(mainPanel.getPreferredSize().height + 50, 150)));
return mainPanel;
}
/**
* @see org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog#helpTopicId()
*/
protected String helpTopicId() {
return "dialog.unexpectedError";
}
/**
* No need for a Cancel button.
* @see org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog#cancelButtonIsVisible()
*/
protected boolean cancelButtonIsVisible() {
return false;
}
/**
* Allow the user to see the stack trace, if appropriate.
* @see org.eclipse.persistence.tools.workbench.framework.ui.dialog.AbstractDialog#buildCustomActions()
*/
protected Iterator buildCustomActions() {
if (this.logRecord.getThrown() == null) {
return super.buildCustomActions();
}
Action stackTraceAction = this.buildStackTraceAction();
return new SingleElementIterator(stackTraceAction);
}
private Action buildStackTraceAction() {
return new AbstractAction(this.buildStackTraceText()) {
public void actionPerformed(ActionEvent e) {
FrameworkLogHandlerDialog.this.displayStackTrace();
}
};
}
protected String buildStackTraceText() {
return this.resourceRepository().getString("STACK_TRACE");
}
/**
* display the stack trace with a text area dialog
*/
protected void displayStackTrace() {
TextAreaDialog dialog =
new TextAreaDialog(
this.logRecord.getThrown(),
this.helpTopicId(),
this.getWorkbenchContext(),
this
);
dialog.setTitle(this.buildStackTraceText());
dialog.show();
}
/**
* Hack-o-rama: Since this dialog is instantiated outside the "normal"
* application context, we try to hack together a partial context.
*/
private static class LocalWorkbenchContext extends AbstractWorkbenchContext {
FrameworkApplication application;
private WorkbenchWindow window;
private ApplicationContext applicationContext;
LocalWorkbenchContext(FrameworkApplication application, WorkbenchWindow window) {
super();
this.application = application;
this.window = window;
this.applicationContext = buildApplicationContext();
}
private ApplicationContext buildApplicationContext() {
return new AbstractApplicationContext() {
public Application getApplication() {
return LocalWorkbenchContext.this.application;
}
public HelpManager getHelpManager() {
return LocalWorkbenchContext.this.application.getHelpManager();
}
public NodeManager getNodeManager() {
return LocalWorkbenchContext.this.application.getNodeManager();
}
public Preferences getPreferences() {
return LocalWorkbenchContext.this.application.getRootPreferences();
}
public ResourceRepository getResourceRepository() {
return LocalWorkbenchContext.this.application.getResourceRepository();
}
};
}
// ApplicationContext
public Application getApplication() {
return this.application;
}
public HelpManager getHelpManager() {
return this.application.getHelpManager();
}
public NodeManager getNodeManager() {
return this.application.getNodeManager();
}
public Preferences getPreferences() {
return this.application.getRootPreferences();
}
public ResourceRepository getResourceRepository() {
return this.application.getResourceRepository();
}
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
// WorkbenchContext
public ActionRepository getActionRepository() {
throw new UnsupportedOperationException();
}
public Window getCurrentWindow() {
// the window can be null...
return this.window;
}
public NavigatorSelectionModel getNavigatorSelectionModel() {
throw new UnsupportedOperationException();
}
public Component getPropertiesPage() {
throw new UnsupportedOperationException();
}
}
}