/* * 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.apache.ode.jbi; import java.util.HashMap; import java.util.Map; import javax.jbi.component.ServiceUnitManager; import javax.jbi.management.DeploymentException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.apache.ode.utils.DOMUtils; import org.apache.ode.utils.XMLParserUtils; public class OdeSUManager implements ServiceUnitManager { private static final Log __log = LogFactory.getLog(OdeSUManager.class); private static final Messages __msgs = Messages.getMessages(Messages.class); private OdeContext _ode; /** All the service units that have been "init"ed. */ private Map<String, OdeServiceUnit> _serviceUnits = new HashMap<String, OdeServiceUnit>(); public OdeSUManager(OdeContext odeContext) { _ode = odeContext; } public synchronized String deploy(String serviceUnitID, String serviceUnitRootPath) throws DeploymentException { __log.trace("deploy: id=" + serviceUnitID + ", path=" + serviceUnitRootPath); OdeServiceUnit su = new OdeServiceUnit(_ode, serviceUnitID, serviceUnitRootPath); try { su.deploy(); } catch (Exception ex) { __log.error(__msgs.msgServiceUnitDeployFailed(serviceUnitID)); return makeStatusMessage("deploy", "FAILED"); } return makeStatusMessage("deploy", "SUCCESS"); } public synchronized void init(String serviceUnitID, String serviceUnitRootPath) throws DeploymentException { __log.trace("init called for " + serviceUnitID); if (_serviceUnits.containsKey(serviceUnitID)) { __log.debug("odd, init() called for su " + serviceUnitID + ", but it is already init()ed"); return; } try { OdeServiceUnit su = new OdeServiceUnit(_ode, serviceUnitID, serviceUnitRootPath); su.init(); _serviceUnits.put(serviceUnitID, su); } catch (Exception ex) { String errmsg = __msgs.msgServiceUnitInitFailed(serviceUnitID); __log.error(errmsg, ex); throw new DeploymentException(errmsg, ex); } } public synchronized void shutDown(String serviceUnitID) throws DeploymentException { __log.trace("shutDown called for " + serviceUnitID); OdeServiceUnit su = _serviceUnits.remove(serviceUnitID); if (su == null) return; try { su.shutdown(); } catch (Exception ex) { String errmsg = __msgs.msgServiceUnitShutdownFailed(serviceUnitID); __log.error(errmsg, ex); throw new DeploymentException(errmsg, ex); } } public synchronized void start(String serviceUnitID) throws DeploymentException { __log.trace("start called for " + serviceUnitID); OdeServiceUnit su = _serviceUnits.get(serviceUnitID); if (su == null) { // Should not really happen if JBI is working. String errmsg = "Unexpected state; start() called before init()"; IllegalStateException ex = new IllegalStateException(errmsg); __log.error(errmsg, ex); throw new DeploymentException(errmsg, ex); } try { su.start(); } catch (Exception ex) { String errmsg = __msgs.msgServiceUnitStartFailed(serviceUnitID); __log.error(errmsg, ex); throw new DeploymentException(errmsg, ex); } } /** * Stop the deployment. This causes the component to cease generating service * requests related to the deployment. This returns the deployment to a state * equivalent to after init() was called * * @param serviceUnitID * service unit ID * * @throws DeploymentException * deployment exception */ public synchronized void stop(String serviceUnitID) throws DeploymentException { __log.trace("stop called for " + serviceUnitID); OdeServiceUnit su = _serviceUnits.get(serviceUnitID); if (su == null) { // Should not really happen if JBI is working. String errmsg = "Unexpected state; stop() called before init()"; IllegalStateException ex = new IllegalStateException(errmsg); __log.error(errmsg, ex); throw new DeploymentException(errmsg, ex); } try { su.stop(); } catch (Exception ex) { String errmsg = __msgs.msgServiceUnitStopFailed(serviceUnitID); __log.error(errmsg, ex); throw new DeploymentException(errmsg, ex); } } /** * Cancel a Service Deployment. If the deployment is in use (has * dependencies), then will operation may fail. * * @param serviceUnitID - * ID of the Service Unit being undeployed * @param serviceUnitRootPath - * Full path to the Service Unit root. * * @return NOT YET DOCUMENTED * * @throws DeploymentException * deployment exception */ public synchronized String undeploy(String serviceUnitID, String serviceUnitRootPath) throws DeploymentException { __log.trace("undeploy: id=" + serviceUnitID + ", path=" + serviceUnitRootPath); OdeServiceUnit su = new OdeServiceUnit(_ode, serviceUnitID, serviceUnitRootPath); try { su.undeploy(); } catch (Exception ex) { __log.error(__msgs.msgServiceUnitDeployFailed(serviceUnitID)); return makeStatusMessage("undeploy", "FAILED"); } return makeStatusMessage("undeploy", "SUCCESS"); } /** * Generate those lame XML result strings that JBI requires. Oh did I mention * how lame this is? If not, let me remind the reader: this is just about the * lamest "clever idea" I have ever seen. * * @param task * the task that failed and must now generate a lame result string * @param status * the status code that will go into the lame result string. * @return a lame JBI result string */ private String makeStatusMessage(String task, String status) { /* * Cheat sheet: <component-task-result> <component-name>BC1</component-name> * <component-task-result-details * xmlns="http://java.sun.com/xml/ns/jbi/management- <task-result-details> * <task-id>deploy</task-id> <task-result>SUCCESS</task-result> * </task-result-details> </component-task-result-details> * </component-task-result> * */ // First of all, what is the logic why XML ? and if XML, why a String // and not a DOM ? But the 64k question is what is wrong with Exceptions? Document doc; try { // Note that we are using our own choice of factory (xerces), not the // one that is provided by the system. This is important, otherwise the // serialization routine won't work. DocumentBuilderFactory dbf = XMLParserUtils.getDocumentBuilderFactory(); DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.newDocument(); } catch (Exception ex) { throw new RuntimeException(ex); } Element elem = doc.createElement("component-task-result"); doc.appendChild(elem); Element compNameElem = doc.createElement("component-name"); elem.appendChild(compNameElem); Element compTaskRsltDtlsElem = doc.createElement("component-task-result-details"); elem.appendChild(compTaskRsltDtlsElem); Element taskRsltDtlsElem = doc.createElement("task-result-details"); compTaskRsltDtlsElem.appendChild(taskRsltDtlsElem); Element taskId = doc.createElement("task-id"); taskRsltDtlsElem.appendChild(taskId); Element taskResult = doc.createElement("task-result"); taskRsltDtlsElem.appendChild(taskResult); // Why do I have to tell this thing the component name? It /knows/ the // component name.... compNameElem.appendChild(doc.createTextNode(_ode.getContext().getComponentName())); // And why on earth do I have to tell my caller the method he just // called? taskId.appendChild(doc.createTextNode(task)); taskResult.appendChild(doc.createTextNode(status)); return DOMUtils.domToString(elem); } }