/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.jbi.serviceengine.core;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.LinkedList;
import java.util.Collection;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.concurrent.ConcurrentHashMap;
import com.sun.enterprise.jbi.serviceengine.bridge.EndpointHelper;
import com.sun.enterprise.jbi.serviceengine.util.soap.StringTranslator;
import com.sun.enterprise.deployment.WebServiceEndpoint;
import com.sun.enterprise.deployment.BundleDescriptor;
import com.sun.enterprise.deployment.backend.DeployableObjectType;
import com.sun.enterprise.deployment.phasing.DeploymentServiceUtils;
import com.sun.enterprise.instance.BaseManager;
import com.sun.enterprise.webservice.WsUtil;
import com.sun.enterprise.util.Utility;
import com.sun.logging.LogDomains;
import com.sun.xml.ws.api.server.SDDocumentSource;
import com.sun.xml.ws.api.server.WSEndpoint;
import com.sun.xml.ws.api.WSBinding;
import com.sun.xml.ws.api.BindingID;
/**
* Class to manage enabling and disabling of endpoints in NMR. It uses
* EndpointHelper to manage the endpoints.
*
* @author Vikas Awasthi
*/
public class JBIEndpointManager {
private RegistryManager registryManager;
private final Logger logger = LogDomains.getLogger(LogDomains.SERVER_LOGGER);
private StringTranslator translator;
JBIEndpointManager() {
registryManager = new RegistryManager();
translator = new StringTranslator(this.getClass().getPackage().getName(),
this.getClass().getClassLoader());
}
/**
* Parse the jbi.xml file and read enpoint information. Store this
* information in the EndpointRegistry. JBIDescriptorReader is used to
* read jbi.xml. It creates a list of DescriptorEndpointInfo objects
* corresponding to the endpoints specified in the jbi.xml
*
* If there is any exception while parsing jbi.xml then deployment of the
* service unit will be stopped.
*/
void storeAllEndpoints(String appLocation, String su_Name) throws Exception {
InputStream jbi_xml = null;
try {
if(new File(appLocation).isDirectory()) {
jbi_xml = new FileInputStream(appLocation +
File.separator +
"META-INF" +
File.separator +
"jbi.xml");
} else {
ZipFile zipFile = new ZipFile(appLocation);
for (Enumeration e = zipFile.entries(); e.hasMoreElements();) {
ZipEntry zipEntry = (ZipEntry) e.nextElement();
if("META-INF/jbi.xml".equals(zipEntry.getName())) {
jbi_xml = zipFile.getInputStream(zipEntry);
break;
}
}
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(false);
Document doc = factory.newDocumentBuilder().parse(jbi_xml);
JBIDescriptorReader reader = new JBIDescriptorReader(su_Name);
reader.init(doc);
registryManager.addAllEndpointInfo(reader.getEndpoints());
registryManager.addServiceUnit(su_Name);
} catch (Exception e) {
String exceptionText =
translator.getString("serviceengine.jbixml_readerror",su_Name);
logger.log(Level.SEVERE,exceptionText,e);
throw new Exception(exceptionText, e);
} finally {
if(jbi_xml!=null)
jbi_xml.close();
}
}
/**
* Clear the registry. This will be called during service unit undeployment.
*/
void removeAllEndpoints(String su_Name) {
registryManager.removeAllConsumerEP(su_Name);
registryManager.removeAllProviderEP(su_Name);
registryManager.removeServiceUnit(su_Name);
}
/**
* Start all the endpoints specified in jbi.xml. In case of consumer just
* the state variable is set to started. For providers all the endpoints are
* activated in NMR.
*/
void startAllEndpoints(String su_Name) throws Exception {
EndpointHelper epHelper = EndpointHelper.getInstance();
for (DescriptorEndpointInfo ep : registryManager.getAllConsumerEP(su_Name))
ep.setStarted(true);
for (DescriptorEndpointInfo ep : registryManager.getAllProviderEP(su_Name)) {
if(registryManager.getSEEndpoint(ep)==null) {
WebServiceEndpoint endpoint = registryManager.getWSEndpoint(ep, su_Name);
if(endpoint == null)
throw new Exception(
translator.getString("serviceengine.endpoint_mismatch",
ep.getServiceName().getLocalPart(),
su_Name));
createEndpoint(endpoint, ep);
}
if (ep.isPrivate()) {
WebServiceEndpoint endpoint =
registryManager.getSEEndpoint(ep).getEndpointDesc();
endpoint.setJBIPrivate(true);
}
ep.setStarted(true);
// now activate the endpoint in NMR
epHelper.enableEndpoint(ep.getServiceName(), ep.getEndpointName());
}
}
/**
* Disable the endpoints enabled in during start
*/
void stopAllEndpoints(String su_Name) {
EndpointHelper epHelper = EndpointHelper.getInstance();
for (DescriptorEndpointInfo ep : registryManager.getAllConsumerEP(su_Name))
ep.setStarted(false);
for (DescriptorEndpointInfo ep : registryManager.getAllProviderEP(su_Name)) {
ep.setStarted(false);
// now de-activate the endpoint in NMR
epHelper.disableEndpoint(ep.getServiceName(), ep.getEndpointName());
}
}
/**
* Create a WSEndpoint and add it to the EndpointRegistry. The
* JBIAdapterBuilder will later use this endpoint to create a JBIAdapter.
* This code is copied from JAXWSServlet.registerEndpoint() with the
* following changes-
* --> Container is null as there is no need for security and
* monitoring pipes
* --> No ServletAdapter is created and only WSEndpoints are created
* --> No updates are made to JAXWSAdapterRegistry. A different registry
* specific to Java EE service engine is used.
* Related Issue: 6519371.
*/
private void createEndpoint(WebServiceEndpoint endpoint,
DescriptorEndpointInfo ep) throws Exception {
BundleDescriptor bundledesc = endpoint.getBundleDescriptor();
ClassLoader cl = bundledesc.getClassLoader();
// set the app classloader to be used while creating the WSEndpoint
ClassLoader origCl = Utility.setContextClassLoader(cl);
try {
WsUtil wsu = new WsUtil();
Class serviceEndpointClass =
Class.forName(endpoint.getServletImplClass(), true, cl);
// Get the proper binding using BindingID
String givenBinding = endpoint.getProtocolBinding();
// Get list of all wsdls and schema
SDDocumentSource primaryWsdl = null;
Collection docs = null;
if(endpoint.getWebService().hasWsdlFile()) {
BaseManager mgr;
if(bundledesc.getApplication().isVirtual()) {
mgr = DeploymentServiceUtils.getInstanceManager(DeployableObjectType.WEB);
} else {
mgr = DeploymentServiceUtils.getInstanceManager(DeployableObjectType.APP);
}
String deployedDir =
mgr.getLocation(bundledesc.getApplication().getRegistrationName());
File pkgedWsdl;
if(deployedDir != null) {
if(bundledesc.getApplication().isVirtual()) {
pkgedWsdl = new File(deployedDir+File.separator+
endpoint.getWebService().getWsdlFileUri());
} else {
pkgedWsdl = new File(deployedDir+File.separator+
bundledesc.getModuleDescriptor().getArchiveUri().replaceAll("\\.", "_") +
File.separator + endpoint.getWebService().getWsdlFileUri());
}
} else {
pkgedWsdl = new File(endpoint.getWebService().getWsdlFileUrl().getFile());
}
if(pkgedWsdl.exists()) {
primaryWsdl = SDDocumentSource.create(pkgedWsdl.toURL());
docs = wsu.getWsdlsAndSchemas(pkgedWsdl);
}
}
// Get catalog info
java.net.URL catalogURL = null;
File catalogFile = new File(bundledesc.getDeploymentDescriptorDir() +
File.separator + "jax-ws-catalog.xml");
if(catalogFile.exists()) {
catalogURL = catalogFile.toURL();
}
// Create Binding and set service side handlers on this binding
// MTOMFeature mtom = new MTOMFeature(wsu.setMtom(endpoint));
WSBinding binding = BindingID.parse(givenBinding).createBinding();
wsu.configureJAXWSServiceHandlers(endpoint, givenBinding, binding);
WSEndpoint wsep = WSEndpoint.create(
serviceEndpointClass, // The endpoint class
false, // we do not want JAXWS to process @HandlerChain
null, // the invoker interface
endpoint.getServiceName(), // the service QName
endpoint.getWsdlPort(), // the port
null, // Container is used to set custom security/monitoring pipe
binding, // Derive binding
primaryWsdl, // primary WSDL
docs, // Collection of imported WSDLs and schema
catalogURL
);
EndpointHelper epHelper = EndpointHelper.getInstance();
epHelper.registerEndpoint(endpoint);
registryManager.getSEEndpoint(ep).setWsep(wsep);
} finally {
Utility.setContextClassLoader(origCl);
}
}
/**
* Inner class to manage jbi endpoints in the registry. As this class is
* used within JBIEndpoint manager this is made Inner rather than a
* separate class.
*/
class RegistryManager {
RegistryManager() {
provider_endpoints = epRegistry.getProviders();
consumer_endpoints = epRegistry.getConsumers();
}
void addAllEndpointInfo(DescriptorEndpointInfo[] endpoints) {
for (DescriptorEndpointInfo ep : endpoints) {
if(ep.isProvider())
provider_endpoints.put(ep.getKey(), ep);
else
consumer_endpoints.put(ep.getKey(), ep);
}
}
void addServiceUnit(String su_Name) {
epRegistry.getCompApps().add(su_Name);
}
void removeServiceUnit(String su_Name) {
epRegistry.getCompApps().remove(su_Name);
}
void removeAllProviderEP(String su_Name) {
for (String key : provider_endpoints.keySet()) {
DescriptorEndpointInfo ep = provider_endpoints.get(key);
if(ep!=null && ep.getSu_Name().equals(su_Name))
provider_endpoints.remove(key);
}
}
void removeAllConsumerEP(String su_Name) {
for (String key : consumer_endpoints.keySet()) {
DescriptorEndpointInfo ep = consumer_endpoints.get(key);
if(ep!=null && ep.getSu_Name().equals(su_Name))
consumer_endpoints.remove(key);
}
}
List<DescriptorEndpointInfo> getAllProviderEP(String su_Name) {
List<DescriptorEndpointInfo> list =
new LinkedList<DescriptorEndpointInfo>();
for (String key : provider_endpoints.keySet()) {
DescriptorEndpointInfo ep = provider_endpoints.get(key);
if(ep!=null && ep.getSu_Name().equals(su_Name))
list.add(ep);
}
return list;
}
List<DescriptorEndpointInfo> getAllConsumerEP(String su_Name) {
List<DescriptorEndpointInfo> list =
new LinkedList<DescriptorEndpointInfo>();
for (String key : consumer_endpoints.keySet()) {
DescriptorEndpointInfo ep = consumer_endpoints.get(key);
if(ep!=null && ep.getSu_Name().equals(su_Name))
list.add(ep);
}
return list;
}
/** Return endpoint from the registry */
ServiceEngineEndpoint getSEEndpoint(DescriptorEndpointInfo ep) {
return epRegistry.get(ep.getServiceName(),ep.getEndpointName());
}
/** Get a WebServiceEndpoint descriptor that matches with the given
* DescriptorEndpointInfo */
private WebServiceEndpoint getWSEndpoint(DescriptorEndpointInfo ep, String appName) {
List<WebServiceEndpoint> endpoints = epRegistry.getWSEndpoints().get(appName);
if(endpoints == null)
return null;
for (WebServiceEndpoint endpoint : endpoints) {
String endpointName = endpoint.hasWsdlPort() ?
endpoint.getWsdlPort().getLocalPart() : endpoint.getEndpointName();
if(endpoint.getServiceName().equals(ep.getServiceName()) &&
endpointName.equals(ep.getEndpointName())) {
return endpoint;
}
}
return null;
}
// Using vectors here might be easier while updating but searching would
// be costlier. Searching in HashMap is faster.
// Since DescriptorEndpointInfo has serviceUnitName there is no need to
// have a data structure that maintains endpointInfo Vs su_Name
private ConcurrentHashMap<String, DescriptorEndpointInfo> provider_endpoints;
private ConcurrentHashMap<String, DescriptorEndpointInfo> consumer_endpoints;
private EndpointRegistry epRegistry = EndpointRegistry.getInstance();
}
}