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
018 package org.apache.geronimo.axis2;
019
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.net.MalformedURLException;
023 import java.net.URL;
024 import java.util.HashMap;
025 import java.util.Iterator;
026 import java.util.List;
027
028 import javax.wsdl.Binding;
029 import javax.wsdl.Definition;
030 import javax.wsdl.Port;
031 import javax.wsdl.Service;
032 import javax.wsdl.WSDLException;
033 import javax.wsdl.extensions.http.HTTPBinding;
034 import javax.wsdl.extensions.soap.SOAPBinding;
035 import javax.wsdl.extensions.soap12.SOAP12Binding;
036 import javax.wsdl.factory.WSDLFactory;
037 import javax.wsdl.xml.WSDLReader;
038 import javax.xml.namespace.QName;
039 import javax.xml.ws.WebServiceException;
040
041 import org.apache.axis2.Constants;
042 import org.apache.axis2.description.AxisOperation;
043 import org.apache.axis2.description.AxisService;
044 import org.apache.axis2.description.Parameter;
045 import org.apache.axis2.description.java2wsdl.Java2WSDLConstants;
046 import org.apache.axis2.engine.MessageReceiver;
047 import org.apache.axis2.jaxws.description.DescriptionFactory;
048 import org.apache.axis2.jaxws.description.EndpointDescription;
049 import org.apache.axis2.jaxws.description.ServiceDescription;
050 import org.apache.axis2.jaxws.description.builder.BindingTypeAnnot;
051 import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite;
052 import org.apache.axis2.jaxws.description.builder.MethodDescriptionComposite;
053 import org.apache.axis2.jaxws.description.builder.WebServiceAnnot;
054 import org.apache.axis2.jaxws.description.builder.WebServiceProviderAnnot;
055 import org.apache.axis2.jaxws.description.builder.WsdlComposite;
056 import org.apache.axis2.jaxws.description.builder.WsdlGenerator;
057 import org.apache.axis2.jaxws.description.builder.converter.JavaClassToDBCConverter;
058 import org.apache.axis2.jaxws.server.JAXWSMessageReceiver;
059 import org.apache.axis2.wsdl.WSDLUtil;
060 import org.apache.commons.logging.Log;
061 import org.apache.commons.logging.LogFactory;
062 import org.apache.geronimo.axis2.util.SimpleWSDLLocator;
063 import org.apache.geronimo.jaxws.JAXWSUtils;
064 import org.apache.geronimo.jaxws.PortInfo;
065 import org.apache.ws.commons.schema.utils.NamespaceMap;
066
067 /**
068 * @version $Rev$ $Date$
069 */
070 public class AxisServiceGenerator {
071 private static final Log log = LogFactory.getLog(AxisServiceGenerator.class);
072
073 private MessageReceiver messageReceiver;
074
075 public AxisServiceGenerator(){
076 this.messageReceiver = new JAXWSMessageReceiver();
077 }
078
079 public void setMessageReceiver(MessageReceiver messageReceiver) {
080 this.messageReceiver = messageReceiver;
081 }
082
083 public AxisService getServiceFromClass(Class endpointClass) throws Exception {
084 ServiceDescription serviceDescription =
085 DescriptionFactory.createServiceDescription(endpointClass);
086 EndpointDescription[] edArray = serviceDescription.getEndpointDescriptions();
087 AxisService service = edArray[0].getAxisService();
088
089 if (service.getNameSpacesMap() == null) {
090 NamespaceMap map = new NamespaceMap();
091 map.put(Java2WSDLConstants.AXIS2_NAMESPACE_PREFIX,
092 Java2WSDLConstants.AXIS2_XSD);
093 map.put(Java2WSDLConstants.DEFAULT_SCHEMA_NAMESPACE_PREFIX,
094 Java2WSDLConstants.URI_2001_SCHEMA_XSD);
095 service.setNameSpacesMap(map);
096 }
097
098 String endpointClassName = endpointClass.getName();
099 ClassLoader classLoader = endpointClass.getClassLoader();
100
101 service.addParameter(new Parameter(Constants.SERVICE_CLASS, endpointClassName));
102 service.setClassLoader(classLoader);
103
104 for(Iterator<AxisOperation> opIterator = service.getOperations() ; opIterator.hasNext() ;){
105 AxisOperation operation = opIterator.next();
106 operation.setMessageReceiver(this.messageReceiver);
107 }
108
109 Parameter serviceDescriptionParam =
110 new Parameter(EndpointDescription.AXIS_SERVICE_PARAMETER, edArray[0]);
111 service.addParameter(serviceDescriptionParam);
112
113 return service;
114 }
115
116 public AxisService getServiceFromWSDL(PortInfo portInfo, Class endpointClass, URL configurationBaseUrl) throws Exception {
117 String wsdlFile = portInfo.getWsdlFile();
118 if (wsdlFile == null || wsdlFile.equals("")) {
119 throw new Exception("WSDL file is required.");
120 }
121
122 String endpointClassName = endpointClass.getName();
123 ClassLoader classLoader = endpointClass.getClassLoader();
124
125 QName serviceQName = portInfo.getWsdlService();
126 if (serviceQName == null) {
127 serviceQName = JAXWSUtils.getServiceQName(endpointClass);
128 }
129
130 QName portQName = portInfo.getWsdlPort();
131 if (portQName == null) {
132 portQName = JAXWSUtils.getPortQName(endpointClass);
133 }
134
135 Definition wsdlDefinition = readWSDL(wsdlFile, configurationBaseUrl, classLoader);
136
137 Service wsdlService = wsdlDefinition.getService(serviceQName);
138 if (wsdlService == null) {
139 throw new Exception("Service '" + serviceQName + "' not found in WSDL");
140 }
141
142 Port port = wsdlService.getPort(portQName.getLocalPart());
143 if (port == null) {
144 throw new Exception("Port '" + portQName.getLocalPart() + "' not found in WSDL");
145 }
146
147 Binding binding = port.getBinding();
148 List extElements = binding.getExtensibilityElements();
149 Iterator extElementsIterator =extElements.iterator();
150 String bindingS = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING; //this is the default.
151 while (extElementsIterator.hasNext()) {
152 Object o = extElementsIterator.next();
153 if (o instanceof SOAPBinding) {
154 SOAPBinding sp = (SOAPBinding)o;
155 if (sp.getElementType().getNamespaceURI().equals("http://schemas.xmlsoap.org/wsdl/soap/")) {
156 //todo: how to we tell if it is MTOM or not.
157 bindingS = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING;
158 }
159 } else if (o instanceof SOAP12Binding) {
160 SOAP12Binding sp = (SOAP12Binding)o;
161 if (sp.getElementType().getNamespaceURI().equals("http://schemas.xmlsoap.org/wsdl/soap12/")) {
162 //todo: how to we tell if it is MTOM or not.
163 bindingS = javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING;
164 }
165 } else if (o instanceof HTTPBinding) {
166 HTTPBinding sp = (HTTPBinding)o;
167 if (sp.getElementType().getNamespaceURI().equals("http://www.w3.org/2004/08/wsdl/http")) {
168 bindingS = javax.xml.ws.http.HTTPBinding.HTTP_BINDING;
169 }
170 }
171 }
172
173 Class endPointClass = classLoader.loadClass(endpointClassName);
174 JavaClassToDBCConverter converter = new JavaClassToDBCConverter(endPointClass);
175 HashMap<String, DescriptionBuilderComposite> dbcMap = converter.produceDBC();
176
177 DescriptionBuilderComposite dbc = dbcMap.get(endpointClassName);
178 dbc.setClassLoader(classLoader);
179 dbc.setWsdlDefinition(wsdlDefinition);
180 dbc.setClassName(endpointClassName);
181 dbc.setCustomWsdlGenerator(new WSDLGeneratorImpl(wsdlDefinition));
182
183 if (dbc.getWebServiceAnnot() != null) { //information specified in .wsdl should overwrite annotation.
184 WebServiceAnnot serviceAnnot = dbc.getWebServiceAnnot();
185 serviceAnnot.setPortName(portQName.getLocalPart());
186 serviceAnnot.setServiceName(serviceQName.getLocalPart());
187 serviceAnnot.setTargetNamespace(serviceQName.getNamespaceURI());
188 if (dbc.getBindingTypeAnnot() !=null && bindingS != null && !bindingS.equals("")) {
189 BindingTypeAnnot bindingAnnot = dbc.getBindingTypeAnnot();
190 bindingAnnot.setValue(bindingS);
191 }
192 } else if (dbc.getWebServiceProviderAnnot() != null) {
193 WebServiceProviderAnnot serviceProviderAnnot = dbc.getWebServiceProviderAnnot();
194 serviceProviderAnnot.setPortName(portQName.getLocalPart());
195 serviceProviderAnnot.setServiceName(serviceQName.getLocalPart());
196 serviceProviderAnnot.setTargetNamespace(serviceQName.getNamespaceURI());
197 if (dbc.getBindingTypeAnnot() !=null && bindingS != null && !bindingS.equals("")) {
198 BindingTypeAnnot bindingAnnot = dbc.getBindingTypeAnnot();
199 bindingAnnot.setValue(bindingS);
200 }
201 }
202
203 AxisService service = getService(dbcMap);
204
205 service.setName(serviceQName.getLocalPart());
206 service.setEndpointName(portQName.getLocalPart());
207
208 for(Iterator<AxisOperation> opIterator = service.getOperations() ; opIterator.hasNext() ;){
209 AxisOperation operation = opIterator.next();
210 operation.setMessageReceiver(this.messageReceiver);
211 String MEP = operation.getMessageExchangePattern();
212 if (!WSDLUtil.isOutputPresentForMEP(MEP)) {
213 List<MethodDescriptionComposite> mdcList = dbc.getMethodDescriptionComposite(operation.getName().toString());
214 for(Iterator<MethodDescriptionComposite> mIterator = mdcList.iterator(); mIterator.hasNext();){
215 MethodDescriptionComposite mdc = mIterator.next();
216 //TODO: JAXWS spec says need to check Holder param exist before taking a method as OneWay
217 mdc.setOneWayAnnot(true);
218 }
219 }
220 }
221
222 return service;
223 }
224
225 private AxisService getService(HashMap<String, DescriptionBuilderComposite> dbcMap) {
226 return getEndpointDescription(dbcMap).getAxisService();
227 }
228
229 private EndpointDescription getEndpointDescription(HashMap<String, DescriptionBuilderComposite> dbcMap) {
230 List<ServiceDescription> serviceDescList = DescriptionFactory.createServiceDescriptionFromDBCMap(dbcMap);
231 if (serviceDescList == null || serviceDescList.isEmpty()) {
232 throw new RuntimeException("No service");
233 }
234 ServiceDescription serviceDescription = serviceDescList.get(0);
235 EndpointDescription[] edArray = serviceDescription.getEndpointDescriptions();
236 if (edArray == null || edArray.length == 0) {
237 throw new RuntimeException("No endpoint");
238 }
239 return edArray[0];
240 }
241
242 private class WSDLGeneratorImpl implements WsdlGenerator {
243 private Definition def;
244
245 public WSDLGeneratorImpl(Definition def) {
246 this.def = def;
247 }
248
249 public WsdlComposite generateWsdl(String implClass, String bindingType) throws WebServiceException {
250 // Need WSDL generation code
251 WsdlComposite composite = new WsdlComposite();
252 composite.setWsdlFileName(implClass);
253 HashMap<String, Definition> testMap = new HashMap<String, Definition>();
254 testMap.put(composite.getWsdlFileName(), def);
255 composite.setWsdlDefinition(testMap);
256 return composite;
257 }
258 }
259
260 protected Definition readWSDL(String wsdlLocation,
261 URL configurationBaseUrl,
262 ClassLoader classLoader)
263 throws IOException, WSDLException {
264 Definition wsdlDefinition = null;
265 URL wsdlURL = getWsdlURL(wsdlLocation, configurationBaseUrl, classLoader);
266 InputStream wsdlStream = null;
267 try {
268 wsdlStream = wsdlURL.openStream();
269 WSDLFactory factory = WSDLFactory.newInstance();
270 WSDLReader reader = factory.newWSDLReader();
271 reader.setFeature("javax.wsdl.importDocuments", true);
272 reader.setFeature("javax.wsdl.verbose", false);
273 SimpleWSDLLocator wsdlLocator = new SimpleWSDLLocator(wsdlURL.toString());
274 wsdlDefinition = reader.readWSDL(wsdlLocator);
275 } finally {
276 if (wsdlStream != null) {
277 wsdlStream.close();
278 }
279 }
280 return wsdlDefinition;
281 }
282
283 public static URL getWsdlURL(String wsdlFile, URL configurationBaseUrl, ClassLoader classLoader) {
284 URL wsdlURL = null;
285 if (wsdlFile != null) {
286 try {
287 wsdlURL = new URL(wsdlFile);
288 } catch (MalformedURLException e) {
289 // Not a URL, try as a resource
290 wsdlURL = classLoader.getResource(wsdlFile);
291
292 if (wsdlURL == null && configurationBaseUrl != null) {
293 // Cannot get it as a resource, try with
294 // configurationBaseUrl
295 try {
296 wsdlURL = new URL(configurationBaseUrl, wsdlFile);
297 } catch (MalformedURLException ee) {
298 // ignore
299 }
300 }
301 }
302 }
303 return wsdlURL;
304 }
305
306 public static EndpointDescription getEndpointDescription(AxisService service) {
307 Parameter param = service.getParameter(EndpointDescription.AXIS_SERVICE_PARAMETER);
308 return (param == null) ? null : (EndpointDescription) param.getValue();
309 }
310
311 }