blob: 7e6dfefb31968e7fcdc9272aca5eb3df422f624d [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.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.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 Logger __log = LoggerFactory.getLogger(OdeSUManager.class);
private static final Messages __msgs = Messages.getMessages(Messages.class);
private static final String XMLNS_JBI_MGMT = "http://java.sun.com/xml/ns/jbi/management-message";
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);
}
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
su.start();
} catch (Exception ex) {
String errmsg = __msgs.msgServiceUnitStartFailed(serviceUnitID);
__log.error(errmsg, ex);
throw new DeploymentException(errmsg, ex);
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
}
/**
* 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.createElementNS(XMLNS_JBI_MGMT, "component-task-result");
doc.appendChild(elem);
Element compNameElem = doc.createElementNS(XMLNS_JBI_MGMT, "component-name");
elem.appendChild(compNameElem);
Element compTaskRsltDtlsElem = doc.createElementNS(XMLNS_JBI_MGMT, "component-task-result-details");
elem.appendChild(compTaskRsltDtlsElem);
Element taskRsltDtlsElem = doc.createElementNS(XMLNS_JBI_MGMT, "task-result-details");
compTaskRsltDtlsElem.appendChild(taskRsltDtlsElem);
Element taskId = doc.createElementNS(XMLNS_JBI_MGMT, "task-id");
taskRsltDtlsElem.appendChild(taskId);
Element taskResult = doc.createElementNS(XMLNS_JBI_MGMT, "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);
}
}