/* * Copyright Technophobia Ltd 2012 * * This file is part of Substeps. * * Substeps is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Substeps is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Substeps. If not, see <http://www.gnu.org/licenses/>. */ package com.technophobia.substeps.jmx; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationListener; import com.technophobia.substeps.execution.ExecutionNodeResult; import com.technophobia.substeps.execution.ExecutionResult; import com.technophobia.substeps.execution.node.FeatureNode; import com.technophobia.substeps.model.exception.SubstepsConfigurationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.technophobia.substeps.execution.node.IExecutionNode; import com.technophobia.substeps.execution.node.RootNode; import com.technophobia.substeps.runner.ExecutionNodeRunner; import com.technophobia.substeps.runner.IExecutionListener; import com.technophobia.substeps.runner.SubstepExecutionFailure; import com.technophobia.substeps.runner.SubstepsExecutionConfig; /** * @author ian * */ public class SubstepsServer extends NotificationBroadcasterSupport implements SubstepsServerMBean, IExecutionListener { private final Logger log = LoggerFactory.getLogger(SubstepsServer.class); private ExecutionNodeRunner nodeRunner = null; private final CountDownLatch shutdownSignal; public byte[] prepareExecutionConfigAsBytes(final SubstepsExecutionConfig theConfig){ RootNode rtn = null; try { rtn = prepareExecutionConfig(theConfig); log.debug("execution config prepared"); } // catch (SubstepsConfigurationException e){ // // } catch(Exception e){ log.error("Error preparing ExecutionConfig", e); List<FeatureNode> empty = Collections.emptyList(); rtn = new RootNode("Substeps Test", empty); ExecutionNodeResult result = rtn.getResult(); result.setThrown(e); result.setResult(ExecutionResult.PARSE_FAILURE); } return getBytes(rtn); } private byte[] getBytes(Object rtn) { byte[] rtnBytes = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(rtn); rtnBytes = bos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally{ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } return rtnBytes; } public byte[] runAsBytes(){ RootNode rtn = run(); return getBytes(rtn); } /** * @param shutdownSignal */ public SubstepsServer(final CountDownLatch shutdownSignal) { this.shutdownSignal = shutdownSignal; // addNotificationListener(new NotificationListener(){ // //@Override // public void handleNotification(Notification notification, Object handback) { // // System.out.println("*** Handling new notification ***"); // // System.out.println("Message: " + notification.getMessage()); // // System.out.println("Seq: " + notification.getSequenceNumber()); // // System.out.println("*********************************"); // // } // // }, null, null); } public void shutdown() { this.shutdownSignal.countDown(); } /* * (non-Javadoc) * * @see * com.technopobia.substeps.jmx.SubstepsMBean#prepareExecutionConfig(com * .technophobia.substeps.runner.ExecutionConfig) */ public RootNode prepareExecutionConfig(final SubstepsExecutionConfig theConfig) { // TODO - synchronise around the init call ? this.nodeRunner = new ExecutionNodeRunner(); return this.nodeRunner.prepareExecutionConfig(theConfig); } /* * (non-Javadoc) * * @see com.technopobia.substeps.jmx.SubstepsMBean#run() */ public RootNode run() { // attach a result listener to broadcast this.nodeRunner.addNotifier(this); final RootNode rootNode; try { rootNode = this.nodeRunner.run(); } finally { // now send the final notification final Notification n = new Notification("ExecConfigComplete", SubstepsServerMBean.SUBSTEPS_JMX_MBEAN_NAME, this.notificationSequenceNumber); this.log.trace("sending complete notification sequence: " + this.notificationSequenceNumber); sendNotification(n); } return rootNode; } private long notificationSequenceNumber = 1; private void doNotification(final IExecutionNode node) { final Notification n = new Notification("ExNode", SubstepsServerMBean.SUBSTEPS_JMX_MBEAN_NAME, this.notificationSequenceNumber); this.notificationSequenceNumber++; n.setUserData(getBytes(node.getResult())); this.log.trace("sending notification for node id: " + node.getId() + " sequence: " + this.notificationSequenceNumber); sendNotification(n); } /* * (non-Javadoc) * * @see * com.technophobia.substeps.runner.INotifier#notifyNodeFailed(com.technophobia * .substeps.execution.ExecutionNode, java.lang.Throwable) */ public void onNodeFailed(final IExecutionNode node, final Throwable cause) { doNotification(node); } /* * (non-Javadoc) * * @see * com.technophobia.substeps.runner.INotifier#notifyNodeStarted(com.technophobia * .substeps.execution.ExecutionNode) */ public void onNodeStarted(final IExecutionNode node) { doNotification(node); } /* * (non-Javadoc) * * @see com.technophobia.substeps.runner.INotifier#notifyNodeFinished(com. * technophobia.substeps.execution.ExecutionNode) */ public void onNodeFinished(final IExecutionNode node) { doNotification(node); } /* * (non-Javadoc) * * @see * com.technophobia.substeps.runner.INotifier#notifyNodeIgnored(com.technophobia * .substeps.execution.ExecutionNode) */ public void onNodeIgnored(final IExecutionNode node) { doNotification(node); } public List<SubstepExecutionFailure> getFailures() { return this.nodeRunner.getFailures(); } public void addNotifier(final IExecutionListener notifier) { this.nodeRunner.addNotifier(notifier); } }