001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.geronimo.jaxws.builder; 018 019 import java.net.URI; 020 import java.net.URISyntaxException; 021 import java.util.HashMap; 022 import java.util.List; 023 import java.util.Map; 024 025 import javax.xml.namespace.QName; 026 import javax.xml.ws.Service; 027 import javax.xml.ws.handler.Handler; 028 029 import org.apache.commons.logging.Log; 030 import org.apache.commons.logging.LogFactory; 031 import org.apache.geronimo.common.DeploymentException; 032 import org.apache.geronimo.j2ee.deployment.Module; 033 import org.apache.geronimo.kernel.repository.Environment; 034 import org.apache.geronimo.naming.deployment.AbstractNamingBuilder; 035 import org.apache.geronimo.naming.deployment.ServiceRefBuilder; 036 import org.apache.geronimo.xbeans.geronimo.naming.GerServiceRefDocument; 037 import org.apache.geronimo.xbeans.geronimo.naming.GerServiceRefType; 038 import org.apache.geronimo.xbeans.javaee.PortComponentRefType; 039 import org.apache.geronimo.xbeans.javaee.ServiceRefHandlerChainType; 040 import org.apache.geronimo.xbeans.javaee.ServiceRefHandlerChainsType; 041 import org.apache.geronimo.xbeans.javaee.ServiceRefHandlerType; 042 import org.apache.geronimo.xbeans.javaee.ServiceRefType; 043 044 import org.apache.xmlbeans.QNameSet; 045 import org.apache.xmlbeans.XmlObject; 046 047 public abstract class JAXWSServiceRefBuilder extends AbstractNamingBuilder implements ServiceRefBuilder { 048 private static final Log log = LogFactory.getLog(JAXWSServiceRefBuilder.class); 049 050 private static final QName GER_SERVICE_REF_QNAME = 051 GerServiceRefDocument.type.getDocumentElementName(); 052 053 private static final QNameSet GER_SERVICE_REF_QNAME_SET = 054 QNameSet.singleton(GER_SERVICE_REF_QNAME); 055 056 private final QNameSet serviceRefQNameSet; 057 058 public JAXWSServiceRefBuilder(Environment defaultEnvironment, 059 String[] eeNamespaces) { 060 super(defaultEnvironment); 061 serviceRefQNameSet = buildQNameSet(eeNamespaces, "service-ref"); 062 } 063 064 protected boolean willMergeEnvironment(XmlObject specDD, XmlObject plan) { 065 return specDD.selectChildren(serviceRefQNameSet).length > 0; 066 } 067 068 public void buildNaming(XmlObject specDD, 069 XmlObject plan, 070 Module module, 071 Map componentContext) throws DeploymentException { 072 List<ServiceRefType> serviceRefsUntyped = convert(specDD.selectChildren(serviceRefQNameSet), JEE_CONVERTER, ServiceRefType.class, ServiceRefType.type); 073 XmlObject[] gerServiceRefsUntyped = plan == null ? NO_REFS : plan.selectChildren(GER_SERVICE_REF_QNAME_SET); 074 Map serviceRefMap = mapServiceRefs(gerServiceRefsUntyped); 075 076 for (ServiceRefType serviceRef : serviceRefsUntyped) { 077 String name = getStringValue(serviceRef.getServiceRefName()); 078 addInjections(name, serviceRef.getInjectionTargetArray(), componentContext); 079 GerServiceRefType serviceRefType = (GerServiceRefType) serviceRefMap.get(name); 080 serviceRefMap.remove(name); 081 buildNaming(serviceRef, serviceRefType, module, componentContext); 082 } 083 084 if (serviceRefMap.size() > 0) { 085 log.warn("Failed to build reference to service reference "+serviceRefMap.keySet()+" defined in plan file, reason - corresponding entry in deployment descriptor missing."); 086 } 087 } 088 089 private Class loadClass(String className, ClassLoader cl, String classDescription) throws DeploymentException { 090 try { 091 return cl.loadClass(className); 092 } catch (ClassNotFoundException e) { 093 throw new DeploymentException("Could not load " + classDescription + " class " + className, e); 094 } 095 } 096 097 public void buildNaming(XmlObject serviceRef, GerServiceRefType gerServiceRefType, Module module, Map componentContext) throws DeploymentException { 098 ServiceRefType serviceRefType = 099 (ServiceRefType)convert(serviceRef, JEE_CONVERTER, ServiceRefType.type); 100 buildNaming(serviceRefType, gerServiceRefType, module, componentContext); 101 } 102 103 public void buildNaming(ServiceRefType serviceRef, GerServiceRefType gerServiceRef, Module module, Map componentContext) throws DeploymentException { 104 ClassLoader cl = module.getEarContext().getClassLoader(); 105 String name = getStringValue(serviceRef.getServiceRefName()); 106 107 String serviceInterfaceName = getStringValue(serviceRef.getServiceInterface()); 108 Class serviceInterfaceClass = loadClass(serviceInterfaceName, cl, "service"); 109 if (!Service.class.isAssignableFrom(serviceInterfaceClass)) { 110 throw new DeploymentException(serviceInterfaceName + " service class does not extend " + Service.class.getName()); 111 } 112 113 QName serviceQName = null; 114 if (serviceRef.isSetServiceQname()) { 115 serviceQName = serviceRef.getServiceQname().getQNameValue(); 116 } 117 118 URI wsdlURI = null; 119 if (serviceRef.isSetWsdlFile()) { 120 String wsdlLocation = serviceRef.getWsdlFile().getStringValue().trim(); 121 try { 122 wsdlURI = new URI(wsdlLocation); 123 } catch (URISyntaxException e) { 124 throw new DeploymentException("Could not construct WSDL URI from " + wsdlLocation, e); 125 } 126 } 127 128 Class serviceReferenceType = null; 129 if (serviceRef.isSetServiceRefType()) { 130 String referenceClassName = getStringValue(serviceRef.getServiceRefType()); 131 serviceReferenceType = loadClass(referenceClassName, cl, "service reference"); 132 } 133 134 if (serviceRef.isSetHandlerChains()) { 135 ServiceRefHandlerChainsType handlerChains = serviceRef.getHandlerChains(); 136 for (ServiceRefHandlerChainType handlerChain : handlerChains.getHandlerChainArray()) { 137 for (ServiceRefHandlerType handler : handlerChain.getHandlerArray()) { 138 String handlerClassName = getStringValue(handler.getHandlerClass()); 139 Class handlerClass = loadClass(handlerClassName, cl, "handler"); 140 if (!Handler.class.isAssignableFrom(handlerClass)) { 141 throw new DeploymentException(handlerClassName + " handler class does not extend " + Handler.class.getName()); 142 } 143 } 144 } 145 } 146 147 Map<Class, PortComponentRefType> portComponentRefMap = new HashMap<Class, PortComponentRefType>(); 148 PortComponentRefType[] portComponentRefs = serviceRef.getPortComponentRefArray(); 149 if (portComponentRefs != null) { 150 for (int j = 0; j < portComponentRefs.length; j++) { 151 PortComponentRefType portComponentRef = portComponentRefs[j]; 152 String serviceEndpointInterfaceType = getStringValue(portComponentRef.getServiceEndpointInterface()); 153 Class serviceEndpointClass = loadClass(serviceEndpointInterfaceType, cl, "service endpoint"); 154 155 // TODO: check if it is annotated? 156 157 portComponentRefMap.put(serviceEndpointClass, portComponentRef); 158 } 159 } 160 161 Object ref = createService(serviceRef, gerServiceRef, module, cl, 162 serviceInterfaceClass, serviceQName, 163 wsdlURI, serviceReferenceType, portComponentRefMap); 164 getJndiContextMap(componentContext).put(ENV + name, ref); 165 } 166 167 public abstract Object createService(ServiceRefType serviceRef, GerServiceRefType gerServiceRef, 168 Module module, ClassLoader cl, Class serviceInterfaceClass, 169 QName serviceQName, URI wsdlURI, Class serviceReferenceType, 170 Map<Class, PortComponentRefType> portComponentRefMap) throws DeploymentException; 171 172 private static Map mapServiceRefs(XmlObject[] refs) { 173 Map refMap = new HashMap(); 174 if (refs != null) { 175 for (int i = 0; i < refs.length; i++) { 176 GerServiceRefType ref = (GerServiceRefType) refs[i].copy() 177 .changeType(GerServiceRefType.type); 178 String serviceRefName = ref.getServiceRefName().trim(); 179 refMap.put(serviceRefName, ref); 180 } 181 } 182 return refMap; 183 } 184 185 public QNameSet getSpecQNameSet() { 186 return serviceRefQNameSet; 187 } 188 189 public QNameSet getPlanQNameSet() { 190 return GER_SERVICE_REF_QNAME_SET; 191 } 192 193 }