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 }