/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.savara.scenario.simulator.cdm;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import org.pi4soa.cdl.CDLManager;
import org.pi4soa.cdl.Participant;
import org.pi4soa.cdl.ParticipantType;
import org.pi4soa.cdl.util.CDLTypeUtil;
import org.pi4soa.common.xml.XMLUtils;
import org.pi4soa.service.Channel;
import org.pi4soa.service.DefaultMessage;
import org.pi4soa.service.Message;
import org.pi4soa.service.ServiceException;
import org.pi4soa.service.behavior.MessageDefinition;
import org.pi4soa.service.behavior.Receive;
import org.pi4soa.service.behavior.Send;
import org.pi4soa.service.behavior.ServiceDescription;
import org.pi4soa.service.behavior.projection.BehaviorProjection;
import org.pi4soa.service.monitor.ServiceMonitor;
import org.pi4soa.service.monitor.ServiceMonitorFactory;
import org.pi4soa.service.monitor.XMLMonitorConfiguration;
import org.pi4soa.service.session.Session;
import org.pi4soa.service.tracker.ServiceTracker;
import org.savara.common.resources.ResourceLocator;
import org.savara.scenario.model.Event;
import org.savara.scenario.model.MessageEvent;
import org.savara.scenario.model.Role;
import org.savara.scenario.model.SendEvent;
import org.savara.scenario.simulation.RoleSimulator;
import org.savara.scenario.simulation.SimulationContext;
import org.savara.scenario.simulation.SimulationHandler;
import org.savara.scenario.simulation.SimulationModel;
/**
* This class provides the pi4soa CDM implementation of the Role Simulator interface.
*
*/
public class CDMRoleSimulator implements RoleSimulator {
private static final String WS_CDL_SIMULATOR = "WS-CDL simulator";
private static final String CDM_FILE_EXTENSION = ".cdm";
private static final Logger logger=Logger.getLogger(CDMRoleSimulator.class.getName());
/**
* This method returns the name of the role simulator.
*
* @return The name
*/
public String getName() {
return WS_CDL_SIMULATOR;
}
/**
* This method indicates whether the supplied model is supported.
*
* @param model The simulation model information
* @return Whether the model is supported by this role simulator
*/
public boolean isSupported(SimulationModel model) {
return(model.getName().endsWith(CDM_FILE_EXTENSION));
}
/**
* This method identifies whether the role simulator supports
* the model information, and if so, returns the specific model
* representation. If the model is not supported, then a null
* is returned.
*
* @param model The simulation model information
* @param locator The optional resource locator
* @return The supported model, or null if not handled
*/
public Object getModel(SimulationModel model, ResourceLocator locator) {
Object ret=null;
if (model.getName().endsWith(CDM_FILE_EXTENSION)) {
try {
ret = CDLManager.load(model.getContents());
} catch(Exception e) {
logger.log(Level.SEVERE, "Failed to load CDM model", e);
}
}
return(ret);
}
protected Role getRole(ParticipantType pt) {
String ns=CDLTypeUtil.getNamespace(pt.getName(), pt, true);
String lp=XMLUtils.getLocalname(pt.getName());
Role r=new Role();
r.setName(new QName(ns, lp).toString());
return(r);
}
protected Role getRole(Participant p) {
String ns=CDLTypeUtil.getNamespace(p.getName(), p, true);
String lp=XMLUtils.getLocalname(p.getName());
Role r=new Role();
r.setName(new QName(ns, lp).toString());
return(r);
}
/**
* This method returns the list of roles associated with the supplied
* model, if the model represents a global conversation type. If the
* model is a local conversation type, then an empty list will be
* returned.
*
* @param model The model
* @return The list of roles defined in the supplied model
*/
public List<Role> getModelRoles(Object model) {
java.util.List<Role> ret=new java.util.Vector<Role>();
if (model instanceof org.pi4soa.cdl.Package) {
java.util.List<ParticipantType> partTypes=((org.pi4soa.cdl.Package)model).getTypeDefinitions().getParticipantTypes();
for (ParticipantType pt : partTypes) {
ret.add(getRole(pt));
}
@SuppressWarnings("unchecked")
java.util.List<Participant> parts=((org.pi4soa.cdl.Package)model).getParticipants();
for (Participant p : parts) {
ret.add(getRole(p));
}
}
return(ret);
}
/**
* This method initializes the simulation context.
*
* @param context The simulation context
* @throws Exception Failed to initialize the context
*/
public void initialize(SimulationContext context) throws Exception {
if (context.getModel() instanceof org.pi4soa.service.behavior.ServiceDescription) {
XMLMonitorConfiguration config=
new XMLMonitorConfiguration();
SimulationHandlerProxy tracker=new SimulationHandlerProxy();
context.getProperties().put(SimulationHandlerProxy.class.getName(), tracker);
config.setServiceTracker(tracker);
config.setEvaluateState(true);
ServiceMonitor mon=ServiceMonitorFactory.getServiceMonitor(config);
mon.getConfiguration().getServiceRepository().
addServiceDescription((org.pi4soa.service.behavior.ServiceDescription)context.getModel());
context.getProperties().put(ServiceMonitor.class.getName(), mon);
} else {
throw new Exception("Model is not CDL");
}
}
/**
* This method returns the model, derived from the supplied model,
* that should be used for the specified role.
*
* @param model The model
* @param role The role
* @param locator The optional resource locator
* @return The simulation model
*/
public Object getModelForRole(Object model, Role role, ResourceLocator locator) {
Object ret=null;
if (model instanceof org.pi4soa.cdl.Package) {
org.pi4soa.cdl.Package cdlpack=(org.pi4soa.cdl.Package)model;
java.util.List<ParticipantType> participants=
cdlpack.getTypeDefinitions().getParticipantTypes();
java.util.Iterator<ParticipantType> iter=participants.iterator();
while (ret == null && iter.hasNext()) {
ParticipantType partType=iter.next();
Role r=getRole(partType);
if (r.getName().equals(role.getName())) {
try {
ret = BehaviorProjection.projectServiceDescription(cdlpack,
partType, null);
} catch(ServiceException se) {
logger.severe("Failed to project service " +
"description '"+partType.getName()+"'");
}
}
}
}
return(ret);
}
/**
* This method simulates the supplied event within the specified simulation
* context. The results are reported to the supplied handler.
*
* @param context The context
* @param event The event
* @param handler The handler
*/
public void onEvent(SimulationContext context, Event event,
SimulationHandler handler) {
ServiceMonitor mon=(ServiceMonitor)
context.getProperties().get(ServiceMonitor.class.getName());
SimulationHandlerProxy proxy=(SimulationHandlerProxy)
context.getProperties().get(SimulationHandlerProxy.class.getName());
if (mon != null && proxy != null) {
synchronized(mon) {
proxy.setEvent(event);
proxy.setSimulationHandler(handler);
if (event instanceof MessageEvent) {
MessageEvent me=(MessageEvent)event;
if (me.getParameter().size() == 1) {
String type=me.getParameter().get(0).getType();
String path=me.getParameter().get(0).getValue();
java.io.Serializable value=null;
if (path != null) {
try {
java.io.InputStream is=context.getResource(path);
byte[] b=new byte[is.available()];
is.read(b);
is.close();
// Assume value is text
value = new String(b);
} catch(Exception e) {
handler.error("Failed to obtain message value", event, e);
}
}
Message mesg=mon.createMessage(type,
null, null, value, null, null);
if (mesg instanceof DefaultMessage) {
// Not nice, but the factory method does not offer ability
// to set op/fault names on messgae - only req or resp
((DefaultMessage)mesg).setOperationName(me.getOperationName());
((DefaultMessage)mesg).setFaultName(me.getFaultName());
}
try {
if (event instanceof SendEvent) {
mon.messageSent(mesg);
} else {
mon.messageReceived(mesg);
}
} catch(org.pi4soa.service.OutOfSequenceMessageException oosme) {
// Ignore, as logged as unexpected messages with handler
} catch(Exception e) {
handler.error("Failed to simulate message", event, e);
}
} else {
handler.error("Cannot simulate event as does not have single parameter",
event, null);
}
}
}
} else {
handler.error("Service monitor not configured", event, null);
}
}
/**
* This method closes the role simulator.
*
* @param context The context
* @throws Exception Failed to close the role simulator
*/
public void close(SimulationContext context) throws Exception {
}
public static class SimulationHandlerProxy implements ServiceTracker {
private SimulationHandler m_handler=null;
private Event m_event=null;
public SimulationHandlerProxy() {
}
public void setSimulationHandler(SimulationHandler handler) {
m_handler = handler;
}
public void setEvent(Event event) {
m_event = event;
}
public void close() throws ServiceException {
}
public void error(Session arg0, String mesg, Throwable e) {
m_handler.error(mesg, m_event, e);
}
public void information(Session arg0, String arg1) {
}
public void initialize() throws ServiceException {
}
public void receivedMessage(MessageDefinition arg0, Message arg1) {
if (!m_event.isErrorExpected()) {
m_handler.processed(m_event);
} else {
m_handler.error("Error was expected but did not occur", m_event, null);
}
}
public void receivedMessage(Receive arg0, Session arg1, Channel arg2,
Message arg3) {
if (!m_event.isErrorExpected()) {
m_handler.processed(m_event);
} else {
m_handler.error("Error was expected but did not occur", m_event, null);
}
}
public void sentMessage(MessageDefinition arg0, Message arg1) {
if (!m_event.isErrorExpected()) {
m_handler.processed(m_event);
} else {
m_handler.error("Error was expected but did not occur", m_event, null);
}
}
public void sentMessage(Send arg0, Session arg1, Channel arg2,
Message arg3) {
if (!m_event.isErrorExpected()) {
m_handler.processed(m_event);
} else {
m_handler.error("Error was expected but did not occur", m_event, null);
}
}
public void serviceFinished(ServiceDescription arg0, Session arg1) {
}
public void serviceStarted(ServiceDescription arg0, Session arg1) {
}
public void subSessionFinished(Session arg0, Session arg1) {
}
public void subSessionStarted(Session arg0, Session arg1) {
}
public void unexpectedMessage(ServiceDescription arg0, Session arg1,
Message arg2, String arg3) {
if (!m_event.isErrorExpected()) {
m_handler.unexpected(m_event);
} else {
m_handler.processed(m_event);
}
}
public void unhandledException(Session arg0, String arg1) {
// TODO: Determine if this should be reported as unexpected or as an error?
m_handler.unexpected(m_event);
}
public void warning(Session arg0, String arg1, Throwable arg2) {
}
}
}