/*
* JBoss, Home of Professional Open Source.
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.bpel.runtime.ws;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.iapi.EndpointReference;
import org.apache.ode.bpel.iapi.ProcessConf;
import org.jboss.soa.bpel.deployer.BPELDeploymentUnit;
import org.jboss.soa.bpel.runtime.JBossDSPFactory;
import org.jboss.soa.bpel.runtime.engine.ode.BPELEngineImpl;
import org.jboss.soa.bpel.runtime.engine.ode.ExecutionEnvironment;
import org.jboss.soa.bpel.runtime.engine.ode.UDDIRegistration;
import org.jboss.soa.dsp.EndpointMetaData;
import org.jboss.soa.dsp.ServiceEndpointReference;
import org.jboss.soa.dsp.server.ServerConfig;
import org.jboss.soa.dsp.ws.BaseWebServiceEndpoint;
import org.jboss.soa.dsp.ws.DeploymentBuilder;
import org.jboss.soa.dsp.ws.WSDLParser;
import org.jboss.soa.dsp.ws.WSDLReference;
import org.jboss.soa.dsp.ws.WebServiceProviderGenerator;
import javax.xml.namespace.QName;
import java.io.File;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Manages creation and destroyal of web service endpoints and clients.
* This instance is stateful and retains references to both endpoints and clients.
* As such it should only exists once.
*
* @see org.jboss.soa.dsp.ws.BaseWebServiceEndpoint
* @see org.jboss.soa.bpel.runtime.ws.WebServiceClient
* @see org.jboss.soa.bpel.runtime.engine.ode.JAXWSBindingContext
*
* @author Heiko.Braun <heiko.braun@jboss.com>
*/
public class EndpointManager
{
protected final Log log = LogFactory.getLog(getClass());
private static final String BPEL_WS_STABLE_INTERFACE = "ws.stableInterface";
private Map<String, ServiceEndpointReference> endpointMapping = new ConcurrentHashMap<String, ServiceEndpointReference>();
private ServerConfig serverConfig;
private ExecutionEnvironment executionEnvironment;
private UDDIRegistration uddiRegistration;
private boolean stableInterface=false;
public EndpointManager(ExecutionEnvironment executionEnvironment)
{
this.executionEnvironment = executionEnvironment;
this.serverConfig = JBossDSPFactory.getServerConfig();
this.uddiRegistration = executionEnvironment.getUDDIRegistration();
stableInterface = executionEnvironment.getOdeConfig().getProperty(BPEL_WS_STABLE_INTERFACE,
"false").equalsIgnoreCase("true");
log.info("Use stable interface: "+stableInterface);
}
public boolean isStableInterface() {
return(stableInterface);
}
public EndpointReference createEndpoint(EndpointMetaData metaData, WSDLReference wsdlRef, final ClassLoader classLoader)
throws EndpointManagementException
{
try
{
File wsdlFile=new File(wsdlRef.getWsdlURL().toURI());
// Find deployment root folder
File root=wsdlFile.getParentFile();
while (root != null && !(new File(root,
BPELDeploymentUnit.DEPLOY_XML).exists() ||
new File(root, BPELDeploymentUnit.BPEL_DEPLOY_XML).exists())) {
root = root.getParentFile();
}
if (root == null) {
throw new EndpointManagementException("Failed to locate root folder of BPEL deployment unit");
}
// Check if a handler file has been specified
File handlerFile=new File(root, "jws_handlers.xml");
String handlerFilePath=null;
if (handlerFile.exists()) {
handlerFilePath = "/"+handlerFile.getName();
}
// generate provider impl
WebServiceProviderGenerator providerFactory = new WebServiceProviderGenerator();
BaseWebServiceEndpoint providerImpl =
providerFactory.createProvider(metaData, wsdlRef, classLoader,
handlerFilePath, ODEWebServiceFactory.class);
log.debug("Created dynamic endpoint class " + providerImpl.getClass().getName());
// create deployment structure (maybe replaced by shrinkwrap)
File warArchive = new DeploymentBuilder(serverConfig)
.setEndpoint(metaData.getEndpointId())
.setWSDL(wsdlFile, root)
.setProvider(providerImpl)
.process(new JBossWSCXFBuildProcessor(providerImpl))
.build();
if (!stableInterface) {
// Undeploy
try {
log.debug("Check if can remove existing service: "+metaData.getServiceName()+":"+metaData.getPortName());
removeEndpoint(metaData.getServiceName(), metaData.getPortName());
} catch(IllegalStateException ise) {
// Ignore for now - endpoint may not exist if first version
}
}
URL serviceUrl = new WSDLParser(wsdlRef.getDefinition()).getServiceLocationURL(metaData.getServiceName(), metaData.getPortName());
ServiceEndpointReference ref = JBossDSPFactory.getServiceDeployer().deploy(metaData, providerImpl.getClass(),
serviceUrl, classLoader, warArchive, serverConfig);
/*
//Deployment deployment = createInMemoryDeployment(endpointId);
Deployment deployment = createVFSDeployment(warArchive);
// Classloading
ClassLoaderFactory clf = new DelegatingClassLoaderFactory(classLoader);
// WebMetaData
URL serviceUrl = new WSDLParser(wsdlRef.getDefinition()).getServiceLocationURL(metaData.getServiceName(), metaData.getPortName());
String[] webContext = deriveWebContextFromServiceUrl(serviceUrl);
WebMetaDataFactory wmdFactory = new WebMetaDataFactory(
metaData.getEndpointId(), webContext[0], webContext[1], providerImpl.getClass().getName()
);
MutableAttachments mutableAttachments =
(MutableAttachments)deployment.getPredeterminedManagedObjects();
// Applies to in memory only. Not used with VFS underneath
//mutableAttachments.addAttachment(StructureMetaData.class, new StructureMetaDataImpl());
mutableAttachments.addAttachment(ClassLoaderFactory.class, clf);
mutableAttachments.addAttachment(JBossWebMetaData.class, wmdFactory.createWebMetaData(classLoader));
mutableAttachments.addAttachment(DeploymentUnitFilter.class, new RiftsawWSDeploymentUnitFilter());
if (!stableInterface) {
// Undeploy
try {
log.debug("Check if can remove existing service: "+metaData.getServiceName()+":"+metaData.getPortName());
removeEndpoint(metaData.getServiceName(), metaData.getPortName());
} catch(IllegalStateException ise) {
// Ignore for now - endpoint may not exist if first version
}
}
getMainDeployer().deploy(deployment);
ODEServiceEndpointReference ref = new ODEServiceEndpointReference(
metaData.getEndpointId(), serviceUrl.toExternalForm(), deployment.getName()
);
ref.setArchiveLocation(warArchive.getAbsolutePath());
*/
endpointMapping.put(
createEndpointKey(metaData.getServiceName(), metaData.getPortName()),
ref
);
if (uddiRegistration!=null) {
String processId = metaData.getProcessId().getLocalPart();
String version = processId.substring(processId.lastIndexOf("-")+1,processId.length());
uddiRegistration.registerBPELProcess(metaData.getServiceName(),
version, metaData.getPortName(), serviceUrl, wsdlRef.getWsdlURL(), wsdlRef.getDefinition());
}
return ODEServiceEndpointReference.toODE(ref);
}
catch (Exception e)
{
throw new EndpointManagementException("Failed to create endpoint", e);
}
}
private String createEndpointKey(QName service, String port)
{
return service.toString()+":"+port;
}
public void removeEndpoint(QName service, String port) throws EndpointManagementException
{
String key = createEndpointKey(service, port);
ServiceEndpointReference ref = endpointMapping.get(key);
if(null==ref)
throw new IllegalStateException("Unable to resolve ServiceEndpointReference for key: "+key);
if (log.isDebugEnabled()) {
log.debug("Remove endpoint service="+service+" port="+port+" deploymentName="+ref.getDeploymentName()+" ref="+ref);
}
try
{
JBossDSPFactory.getServiceDeployer().undeploy(ref, serverConfig);
// unregister
endpointMapping.remove(key);
if (log.isDebugEnabled()) {
log.debug("Undeployed web service with deploymentName="+ref.getDeploymentName());
}
// remove physical artifacts
File warArchive = new File(ref.getArchiveLocation());
if(warArchive.exists())
{
if(!deleteDirectory(warArchive)) log.warn(warArchive + " could no be deleted");
}
else
{
log.warn(ref.getArchiveLocation() + " cannot be removed (doesn't exist).");
}
if (uddiRegistration!=null) {
uddiRegistration.unRegisterBPELEPR(service, port, ref.getServiceUrl());
}
}
catch (Exception e)
{
throw new EndpointManagementException("Failed to undeploy "+ref.getDeploymentName(), e);
}
}
public EndpointReference maintains(QName service, String port)
{
String key = createEndpointKey(service, port);
return ODEServiceEndpointReference.toODE(endpointMapping.get(key));
}
public WebServiceClient createClient(
EndpointMetaData metaData, BPELEngineImpl server, ProcessConf pconf)
throws EndpointManagementException
{
try
{
WebServiceClient client =
new WebServiceClient(metaData, executionEnvironment, server, pconf);
return client;
}
catch (Exception e)
{
throw new EndpointManagementException("Failed to create endpoint", e);
}
}
static public boolean deleteDirectory(File path)
{
if( path.exists() ) {
File[] files = path.listFiles();
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
return( path.delete() );
}
}