package eu.play_project.play_platformservices; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.jws.WebService; import javax.xml.ws.Endpoint; import org.objectweb.fractal.api.NoSuchInterfaceException; import org.objectweb.fractal.api.control.BindingController; import org.objectweb.fractal.api.control.IllegalBindingException; import org.objectweb.fractal.api.control.IllegalLifeCycleException; import org.objectweb.proactive.Body; import org.objectweb.proactive.core.component.body.ComponentEndActive; import org.objectweb.proactive.core.component.body.ComponentInitActive; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.hp.hpl.jena.query.Query; import com.hp.hpl.jena.query.QueryException; import com.hp.hpl.jena.query.QueryFactory; import com.hp.hpl.jena.query.Syntax; import com.hp.hpl.jena.sparql.serializer.PlaySerializer; import eu.play_platform.platformservices.bdpl.syntax.windows.visitor.ElementWindowVisitor; import eu.play_project.dcep.api.DcepManagementException; import eu.play_project.dcep.api.DcepManagmentApi; import eu.play_project.play_commons.constants.Constants; import eu.play_project.play_platformservices.api.BdplQuery; import eu.play_project.play_platformservices.api.QueryDetails; import eu.play_project.play_platformservices.api.QueryDispatchApi; import eu.play_project.play_platformservices.api.QueryDispatchException; import eu.play_project.play_platformservices_querydispatcher.api.EleGenerator; import eu.play_project.play_platformservices_querydispatcher.bdpl.code_generator.realtime.EleGeneratorForConstructQuery; import eu.play_project.play_platformservices_querydispatcher.bdpl.visitor.historic.QueryTemplateGenerator; import eu.play_project.play_platformservices_querydispatcher.bdpl.visitor.realtime.ComplexTypeFinder; import eu.play_project.play_platformservices_querydispatcher.bdpl.visitor.realtime.StreamIdCollector; import eu.play_project.play_platformservices_querydispatcher.bdpl.visitor.realtime.WindowVisitor; /** * The PLAY SOAP Web Service to manage event patterns. See * {@linkplain PlayPlatformservicesRest} for the corresponding RESTful service. * * @author Roland Stühmer */ @WebService( serviceName = "QueryDispatchApi", portName = "QueryDispatchApiPort", endpointInterface = "eu.play_project.play_platformservices.api.QueryDispatchApi") public class PlayPlatformservices implements QueryDispatchApi, ComponentInitActive, ComponentEndActive, BindingController, Serializable { private static final long serialVersionUID = 100L; private EleGenerator eleGenerator; private DcepManagmentApi dcepManagmentApi; private boolean init = false; private final Logger logger = LoggerFactory.getLogger(PlayPlatformservices.class); private Endpoint soapServer; private PlayPlatformservicesRest restServer; @Override public String[] listFc() { return new String[] { DcepManagmentApi.class.getSimpleName() }; } @Override public Object lookupFc(String clientItfName) throws NoSuchInterfaceException { if (DcepManagmentApi.class.getSimpleName().equals(clientItfName)) { return dcepManagmentApi; } else { throw new NoSuchInterfaceException(DcepManagmentApi.class.getSimpleName()); } } @Override public void bindFc(String clientItfName, Object serverItf) throws NoSuchInterfaceException, IllegalBindingException, IllegalLifeCycleException { if (clientItfName.equals(DcepManagmentApi.class.getSimpleName())) { dcepManagmentApi = (DcepManagmentApi) serverItf; } else { throw new NoSuchInterfaceException(String.format("Interface '%s' not available at '%s'.", clientItfName, this.getClass().getSimpleName())); } } @Override public void unbindFc(String clientItfName) throws NoSuchInterfaceException, IllegalBindingException, IllegalLifeCycleException { if (clientItfName.equals(DcepManagmentApi.class.getSimpleName())) { // do nothing, currently } else { throw new NoSuchInterfaceException(String.format("Interface '%s' not available at '%s'.", clientItfName, this.getClass().getSimpleName())); } } @Override public synchronized void initComponentActivity(Body body) { if (!init) { logger.info("Initialising {} component.", this.getClass().getSimpleName()); eleGenerator = new EleGeneratorForConstructQuery(); /* * Provide QueryDispatchApi as SOAP Webservice */ try { String address = Constants.getProperties().getProperty("platfomservices.querydispatchapi.endpoint"); soapServer = Endpoint.publish(address, this); logger.info("QueryDispatch SOAP service started at {}.", address); } catch (Exception e) { logger.error("Exception while publishing QueryDispatch SOAP Service", e); } /* * Provide QueryDispatchApi as REST Webservice */ try { restServer = new PlayPlatformservicesRest(this); logger.info(String.format("QueryDispatch REST service started at %s with WADL remotely available at " + "%s/application.wadl\n", PlayPlatformservicesRest.BASE_URI, Constants.getProperties().getProperty("platfomservices.querydispatchapi.rest"))); } catch (Exception e) { logger.error("Exception while publishing QueryDispatch REST Service", e); } this.init = true; } } @Override public synchronized void endComponentActivity(Body arg0) { logger.info("Terminating {} component.", this.getClass().getSimpleName()); this.init = false; if (this.soapServer != null) { this.soapServer.stop(); } if (this.restServer != null) { this.restServer.destroy(); } } @Override public synchronized String registerQuery(String queryId, String query) throws QueryDispatchException { if (!init) { throw new IllegalStateException("Component not initialized: " + this.getClass().getSimpleName()); } logger.info("Registering query with ID '{}'", queryId); BdplQuery epQuery = createCepQuery(queryId, query); try { dcepManagmentApi.registerEventPattern(epQuery); } catch (Exception e) { String msg = String.format("Error while registering query '%s': %s: %s", queryId, e.getClass().getSimpleName(), e.getMessage()); logger.error(msg); throw new QueryDispatchException(msg); } return queryId; } private BdplQuery createCepQuery(String queryId, String query) throws QueryDispatchException { // Parse query Query q; try { q = QueryFactory.create(query, Syntax.syntaxBDPL); } catch (com.hp.hpl.jena.query.QueryException e) { throw new QueryDispatchException(e.getMessage()); } // Generate CEP-language eleGenerator.setPatternId(queryId); eleGenerator.generateQuery(q); // Add queryDetails QueryDetails qd = this.createQueryDetails(queryId, q); qd.setRdfDbQueries(eleGenerator.getRdfDbQueries()); BdplQuery bdpl = BdplQuery.builder() .details(qd) .ele(eleGenerator.getEle()) .historicalQueries(PlaySerializer.serializeToMultipleSelectQueries(q)) .constructTemplate(new QueryTemplateGenerator().createQueryTemplate(q)) .bdpl(query) .build(); return bdpl; } @Override public void unregisterQuery(String queryId) { if (!init) { throw new IllegalStateException("Component not initialized: " + this.getClass().getSimpleName()); } logger.info("Unregistering query " + queryId); this.dcepManagmentApi.unregisterEventPattern(queryId); } @Override public QueryDetails analyseQuery(String queryId, String query) throws QueryDispatchException { if (!init) { throw new IllegalStateException("Component not initialized: " + this.getClass().getSimpleName()); } // Parse query try { Query q = QueryFactory.create(query, com.hp.hpl.jena.query.Syntax.syntaxBDPL); return createQueryDetails(queryId, q); } catch (QueryException e) { throw new QueryDispatchException(e.getMessage()); } } private QueryDetails createQueryDetails(String queryId, Query query) throws QueryDispatchException { if (!init) { throw new IllegalStateException("Component not initialized: " + this.getClass().getSimpleName()); } logger.info("Analysing query with ID " + queryId); QueryDetails qd = new QueryDetails(queryId); // Set properties for windows in QueryDetails ElementWindowVisitor windowVisitor = new WindowVisitor(qd); query.getWindow().accept(windowVisitor); // Check if id is alredy used. if (dcepManagmentApi != null && dcepManagmentApi.getRegisteredEventPatterns().containsKey(queryId)) { throw new QueryDispatchException("Query ID is already used: " + queryId); } // Set stream ids in QueryDetails. StreamIdCollector streamIdCollector = new StreamIdCollector(); streamIdCollector.getStreamIds(query, qd); // Set complex event type. qd.setComplexType((new ComplexTypeFinder()).visit(query.getConstructTemplate())); return qd; } @Override public eu.play_project.play_platformservices.jaxb.Query getRegisteredQuery(String queryId) throws QueryDispatchException { if (!init) { throw new IllegalStateException("Component not initialized: " + this.getClass().getSimpleName()); } try { return new eu.play_project.play_platformservices.jaxb.Query( this.dcepManagmentApi.getRegisteredEventPattern(queryId)); } catch (DcepManagementException e) { throw new QueryDispatchException(e.getMessage()); } } @Override public List<eu.play_project.play_platformservices.jaxb.Query> getRegisteredQueries() { if (!init) { throw new IllegalStateException("Component not initialized: " + this.getClass().getSimpleName()); } List<eu.play_project.play_platformservices.jaxb.Query> results = new ArrayList<eu.play_project.play_platformservices.jaxb.Query>(); Map<String, BdplQuery> queries = dcepManagmentApi .getRegisteredEventPatterns(); for (String queryId : queries.keySet()) { results.add(new eu.play_project.play_platformservices.jaxb.Query(queries.get(queryId))); } return results; } }