blob: bbc85d4d10cea3d07663a3d5bd72d39daba0e470 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.modules.gsf.testrunner.ui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import org.netbeans.modules.gsf.testrunner.ui.TestRunnerSettings.DividerSettings;
import org.netbeans.modules.gsf.testrunner.api.Report;
import org.netbeans.modules.gsf.testrunner.api.TestSession;
import org.netbeans.modules.gsf.testrunner.api.TestSuite;
import org.netbeans.modules.gsf.testrunner.ui.api.Manager;
import org.openide.ErrorManager;
import org.openide.util.Lookup;
import org.openide.windows.IOContainer;
import org.openide.windows.IOProvider;
import org.openide.windows.InputOutput;
import org.openide.windows.OutputWriter;
/**
*
* @author Marian Petras. Erno Mononen
*/
public final class ResultDisplayHandler {
private static final Logger LOGGER = Logger.getLogger(ResultDisplayHandler.class.getName());
/** */
private static java.util.ResourceBundle bundle = org.openide.util.NbBundle.getBundle(
ResultDisplayHandler.class);
/** */
private ResultPanelTree treePanel;
/** */
private JSplitPane displayComp;
private JComponent outputComponent;
private InputOutput inOut;
private final TestSession session;
private Lookup l;
private StatisticsPanel statisticsPanel;
/** Creates a new instance of ResultDisplayHandler */
public ResultDisplayHandler(TestSession session) {
this.session = session;
}
public JComponent getOutputComponent() {
if (outputComponent == null) {
outputComponent = new JPanel(new BorderLayout());
outputComponent.setBorder(
BorderFactory.createEmptyBorder(0, 10, 0, 0)); // #181873
}
return outputComponent;
}
public InputOutput createIO(IOContainer ioContainer) {
inOut = IOProvider.getDefault().getIO("test-results", null, ioContainer); //NOI18N
return inOut;
}
public TestSession getSession() {
return session;
}
/**
*/
public JSplitPane getDisplayComponent() {
if (displayComp == null) {
displayComp = createDisplayComp();
}
return displayComp;
}
/**
*/
private JSplitPane createDisplayComp() {
DividerSettings dividerSettings = TestRunnerSettings.getDefault().getDividerSettings(null);
statisticsPanel = new StatisticsPanel(this);
return createDisplayComp(statisticsPanel,
getOutputComponent(),
dividerSettings.getOrientation(),
dividerSettings.getLocation());
}
public int getTotalTests() {
return statisticsPanel.getTreePanel().getTotalTests();
}
private JSplitPane createDisplayComp(Component left, Component right, int orientation, final int location) {
final JSplitPane splitPane = new JSplitPane(orientation, true, left, right);
splitPane.setBorder(BorderFactory.createEmptyBorder());
splitPane.setDividerLocation(location);
splitPane.getAccessibleContext().setAccessibleName(bundle.getString("ACSN_ResultPanelTree"));
splitPane.getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_ResultPanelTree"));
splitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
DividerSettings dividerSettings = new DividerSettings(splitPane.getOrientation(), splitPane.getDividerLocation());
TestRunnerSettings.getDefault().setDividerSettings(dividerSettings);
}
});
splitPane.addPropertyChangeListener(JSplitPane.ORIENTATION_PROPERTY, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
DividerSettings dividerSettings = new DividerSettings(splitPane.getOrientation(), splitPane.getDividerLocation());
TestRunnerSettings.getDefault().setDividerSettings(dividerSettings);
}
});
splitPane.setToolTipText(session.getName());
return splitPane;
}
/**
*/
void displayShown() {
//
//PENDING
//
}
/**
*/
void displayHidden() {
//
//PENDING
//
}
//------------------ DISPLAYING OUTPUT ----------------------//
static final Object[] EMPTY_QUEUE = new Object[0];
private final Object queueLock = new Object();
private volatile Object[] outputQueue;
private volatile int outputQueueSize = 0;
/**
*/
Object getOutputQueueLock() {
return queueLock;
}
/**
*/
public void displayOutput(final String text, final boolean error) {
/* Called from the AntLogger's thread */
if (inOut != null) {
OutputWriter out = error ? inOut.getErr() : inOut.getOut();
Manager.getInstance().getOutputLineHandler().handleLine(out, text);
} else {
// log a warning - should rather throw an exception, but we're too close to release now
LOGGER.log(Level.WARNING, "Tried to display output before inOut was initialized. Output text: {0}", text);
}
}
/**
*/
Object[] consumeOutput() {
synchronized (queueLock) {
if (outputQueueSize == 0) {
return EMPTY_QUEUE;
}
Object[] passedQueue = outputQueue;
outputQueue = null;
outputQueueSize = 0;
return passedQueue;
}
}
//-----------------------------------------------------------//
//------------------- DISPLAYING TREE -----------------------//
/**
* name of the currently running suite - to be passed to the
* {@link #treePanel} once it is initialized
*/
private String runningSuite;
private final List<Report> reports = new ArrayList<Report>();
private String message;
boolean sessionFinished;
/**
*
* @param suiteName name of the running suite; or {@code null} in the case
* of anonymous suite
*/
public void displaySuiteRunning(String suiteName) {
synchronized (this) {
assert runningSuite == null;
suiteName = (suiteName != null) ? suiteName : TestSuite.ANONYMOUS_SUITE;
if (treePanel == null) {
runningSuite = suiteName;
return;
}
}
displayInDispatchThread(prepareMethod("displaySuiteRunning", String.class), suiteName); //NOI18N
}
/**
*
* @param suite name of the running suite
*/
public void displaySuiteRunning(TestSuite suite) {
synchronized (this) {
assert runningSuite == null;
suite = (suite != null) ? suite : TestSuite.ANONYMOUS_TEST_SUITE;
if (treePanel == null) {
runningSuite = suite.getName();
return;
}
}
displayInDispatchThread(prepareMethod("displaySuiteRunning", TestSuite.class), suite); //NOI18N
}
/**
*/
public void displayReport(final Report report) {
synchronized (this) {
if (treePanel == null) {
if (!reports.contains(report))
reports.add(report);
runningSuite = null;
return;
}
assert runningSuite == null;
}
displayInDispatchThread(prepareMethod("displayReport", Report.class), report); //NOI18N
}
/**
*/
public void displayMessage(final String msg) {
/* Called from the AntLogger's thread */
synchronized (this) {
if (treePanel == null) {
message = msg;
return;
}
}
displayInDispatchThread(prepareMethod("displayMsg", String.class), msg); //NOI18N
}
/**
*/
public void displayMessageSessionFinished(final String msg) {
/* Called from the AntLogger's thread */
synchronized (this) {
if (treePanel == null) {
message = msg;
return;
}
sessionFinished = true;
}
displayInDispatchThread(prepareMethod("displayMsgSessionFinished", String.class), msg); //NOI18N
}
/** */
private Map<String, Method> methodsMap = new HashMap<String, Method>();
/**
* Calls a given display-method of class {@code ResutlPanelTree}
* in the AWT event queue thread.
*
* @param methodName name of the {@code ResultPanelTree} method
* @param param argument to be passed to the method
*/
private void displayInDispatchThread(final Method method, final Object param) {
assert method != null;
final Method finalMethod = method;
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Invoking: {0} with param: {1}",
new Object[]{method.getName(), param});
}
finalMethod.invoke(treePanel, new Object[]{param});
} catch (InvocationTargetException ex) {
ErrorManager.getDefault().notify(ex.getTargetException());
} catch (Exception ex) {
ErrorManager.getDefault().notify(ErrorManager.ERROR, ex);
}
}
});
}
/**
*/
private synchronized Method prepareMethod(final String methodName, final Class paramType) {
Method method = methodsMap.get(methodName + "_" + paramType.getName()); //NOI18N
if (method == null) {
try {
method = ResultPanelTree.class.getDeclaredMethod(methodName, new Class[]{paramType});
} catch (Exception ex) {
method = null;
ErrorManager.getDefault().notify(ErrorManager.ERROR, ex);
}
methodsMap.put(methodName + "_" + paramType.getName(), method); //NOI18N
}
return method;
}
/**
*/
public synchronized void setTreePanel(final ResultPanelTree treePanel) {
assert EventQueue.isDispatchThread();
/* Called from the EventDispatch thread */
if (this.treePanel != null) {
return;
}
this.treePanel = treePanel;
if (message != null) {
treePanel.displayMsg(message);
message = null;
}
if (!reports.isEmpty()) {
treePanel.displayReports(reports);
reports.clear();
}
if (runningSuite != null) {
treePanel.displaySuiteRunning(runningSuite != TestSuite.ANONYMOUS_SUITE
? runningSuite
: null);
runningSuite = null;
}
if (sessionFinished) {
treePanel.displayMsgSessionFinished(message);
}
}
void setLookup(Lookup l) {
this.l = l;
}
Lookup getLookup() {
return l;
}
}