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.cxf.builder;
018
019 import java.io.FileNotFoundException;
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.io.StringWriter;
023 import java.net.URI;
024 import java.net.URL;
025 import java.util.Collections;
026 import java.util.HashMap;
027 import java.util.Map;
028 import java.util.jar.JarFile;
029
030 import javax.xml.bind.JAXBContext;
031 import javax.xml.bind.JAXBElement;
032 import javax.xml.bind.JAXBException;
033 import javax.xml.bind.Unmarshaller;
034 import javax.xml.namespace.QName;
035 import javax.xml.transform.stream.StreamSource;
036
037 import org.apache.commons.logging.Log;
038 import org.apache.commons.logging.LogFactory;
039 import org.apache.cxf.jaxws.javaee.HandlerChainsType;
040 import org.apache.cxf.jaxws.javaee.PortComponentType;
041 import org.apache.cxf.jaxws.javaee.ServiceImplBeanType;
042 import org.apache.cxf.jaxws.javaee.WebserviceDescriptionType;
043 import org.apache.cxf.jaxws.javaee.WebservicesType;
044 import org.apache.cxf.jaxws.support.JaxWsImplementorInfo;
045 import org.apache.geronimo.common.DeploymentException;
046 import org.apache.geronimo.cxf.client.CXFServiceReference;
047 import org.apache.geronimo.cxf.pojo.POJOWebServiceContainerFactoryGBean;
048 import org.apache.geronimo.gbean.GBeanData;
049 import org.apache.geronimo.gbean.GBeanInfo;
050 import org.apache.geronimo.gbean.GBeanInfoBuilder;
051 import org.apache.geronimo.j2ee.deployment.Module;
052 import org.apache.geronimo.j2ee.deployment.WebServiceBuilder;
053 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
054 import org.apache.geronimo.jaxws.JAXWSUtils;
055 import org.apache.geronimo.jaxws.PortInfo;
056 import org.apache.geronimo.jaxws.builder.EndpointInfoBuilder;
057 import org.apache.geronimo.jaxws.builder.JAXWSServiceBuilder;
058 import org.apache.geronimo.jaxws.builder.WsdlGenerator;
059 import org.apache.geronimo.jaxws.client.EndpointInfo;
060 import org.apache.geronimo.kernel.repository.Environment;
061 import org.apache.geronimo.xbeans.geronimo.naming.GerServiceRefType;
062 import org.apache.geronimo.xbeans.javaee.PortComponentRefType;
063 import org.apache.geronimo.xbeans.javaee.ServiceRefHandlerChainsType;
064 import org.apache.xmlbeans.XmlOptions;
065
066 public class CXFBuilder extends JAXWSServiceBuilder {
067 private static final Log LOG = LogFactory.getLog(CXFBuilder.class);
068
069 /**
070 * This property if enabled will cause the Sun wsgen tool to be used to
071 * generate the WSDL for servies without WSDL. By default CXF tooling
072 * will be used the generate the WSDL.
073 */
074 private static final String USE_WSGEN_PROPERTY =
075 "org.apache.geronimo.cxf.use.wsgen";
076
077 public CXFBuilder() {
078 this(null);
079 }
080
081 public CXFBuilder(Environment defaultEnvironment) {
082 super(defaultEnvironment);
083 }
084
085 protected GBeanInfo getContainerFactoryGBeanInfo() {
086 return POJOWebServiceContainerFactoryGBean.GBEAN_INFO;
087 }
088
089 protected Map<String, PortInfo> parseWebServiceDescriptor(InputStream in,
090 URL wsDDUrl,
091 JarFile moduleFile,
092 boolean isEJB,
093 Map correctedPortLocations)
094 throws DeploymentException {
095
096 LOG.debug("Parsing descriptor " + wsDDUrl);
097
098 Map<String, PortInfo> map = null;
099
100 try {
101 JAXBContext ctx = JAXBContext.newInstance(WebservicesType.class);
102 Unmarshaller unmarshaller = ctx.createUnmarshaller();
103 Object obj = unmarshaller.unmarshal(new StreamSource(in), WebservicesType.class);
104
105 if (obj instanceof JAXBElement) {
106 obj = ((JAXBElement) obj).getValue();
107 }
108
109 if (!(obj instanceof WebservicesType)) {
110 return map;
111 }
112 WebservicesType wst = (WebservicesType) obj;
113
114 for (WebserviceDescriptionType desc : wst.getWebserviceDescription()) {
115 String wsdlFile = null;
116 if (desc.getWsdlFile() != null) {
117 wsdlFile = getString(desc.getWsdlFile().getValue());
118 }
119
120 String serviceName = desc.getWebserviceDescriptionName().getValue();
121
122 for (PortComponentType port : desc.getPortComponent()) {
123
124 PortInfo portInfo = new PortInfo();
125
126 String serviceLink = null;
127 ServiceImplBeanType beanType = port.getServiceImplBean();
128 if (beanType.getEjbLink() != null) {
129 serviceLink = beanType.getEjbLink().getValue();
130 } else if (beanType.getServletLink().getValue() != null) {
131 serviceLink = beanType.getServletLink().getValue();
132 }
133 portInfo.setServiceLink(serviceLink);
134
135 if (port.getServiceEndpointInterface() != null) {
136 String sei = port.getServiceEndpointInterface().getValue();
137 portInfo.setServiceEndpointInterfaceName(sei);
138 }
139
140 String portName = port.getPortComponentName().getValue();
141 portInfo.setPortName(portName);
142
143 portInfo.setProtocolBinding(port.getProtocolBinding());
144 portInfo.setServiceName(serviceName);
145 portInfo.setWsdlFile(wsdlFile);
146
147 if (port.getEnableMtom() != null) {
148 portInfo.setEnableMTOM(port.getEnableMtom().isValue());
149 }
150
151 portInfo.setHandlers(HandlerChainsType.class, port.getHandlerChains());
152
153 if (port.getWsdlPort() != null) {
154 portInfo.setWsdlPort(port.getWsdlPort().getValue());
155 }
156
157 if (port.getWsdlService() != null) {
158 portInfo.setWsdlService(port.getWsdlService().getValue());
159 }
160
161 String location = (String) correctedPortLocations.get(serviceLink);
162 portInfo.setLocation(location);
163
164 if (map == null) {
165 map = new HashMap<String, PortInfo>();
166 }
167 map.put(serviceLink, portInfo);
168 }
169 }
170
171 return map;
172 } catch (FileNotFoundException e) {
173 return Collections.emptyMap();
174 } catch (IOException ex) {
175 throw new DeploymentException("Unable to read " + wsDDUrl, ex);
176 } catch (JAXBException ex) {
177 throw new DeploymentException("Unable to parse " + wsDDUrl, ex);
178 } catch (Exception ex) {
179 throw new DeploymentException("Unknown deployment error", ex);
180 } finally {
181 try {
182 in.close();
183 } catch (IOException e) {
184 // ignore
185 }
186 }
187 }
188
189 public Object createService(Class serviceInterface,
190 Class serviceReference,
191 URI wsdlURI,
192 QName serviceQName,
193 Map<Class, PortComponentRefType> portComponentRefMap,
194 ServiceRefHandlerChainsType handlerChains,
195 GerServiceRefType serviceRefType,
196 Module module,
197 ClassLoader cl) throws DeploymentException {
198 EndpointInfoBuilder builder = new EndpointInfoBuilder(serviceInterface,
199 serviceRefType, portComponentRefMap, module.getModuleFile(),
200 wsdlURI, serviceQName);
201 builder.build();
202
203 wsdlURI = builder.getWsdlURI();
204 serviceQName = builder.getServiceQName();
205 Map<Object, EndpointInfo> seiInfoMap = builder.getEndpointInfo();
206
207 String handlerChainsXML = null;
208 try {
209 handlerChainsXML = getHandlerChainAsString(handlerChains);
210 } catch (IOException e) {
211 // this should not happen
212 LOG.warn("Failed to serialize handler chains", e);
213 }
214
215 String serviceReferenceName = (serviceReference == null) ? null : serviceReference.getName();
216
217 return new CXFServiceReference(serviceInterface.getName(), serviceReferenceName, wsdlURI,
218 serviceQName, module.getModuleName(), handlerChainsXML, seiInfoMap);
219 }
220
221 private static String getHandlerChainAsString(ServiceRefHandlerChainsType handlerChains)
222 throws IOException {
223 String xml = null;
224 if (handlerChains != null) {
225 StringWriter w = new StringWriter();
226 XmlOptions options = new XmlOptions();
227 options.setSaveSyntheticDocumentElement(new QName("http://java.sun.com/xml/ns/javaee", "handler-chains"));
228 handlerChains.save(w, options);
229 xml = w.toString();
230 }
231 return xml;
232 }
233
234 private static String getString(String in) {
235 if (in != null) {
236 in = in.trim();
237 if (in.length() == 0) {
238 return null;
239 }
240 }
241 return in;
242 }
243
244 @Override
245 protected void initialize(GBeanData targetGBean, Class serviceClass, PortInfo portInfo, Module module)
246 throws DeploymentException {
247 if (Boolean.getBoolean(USE_WSGEN_PROPERTY)) {
248 generateWSDL(serviceClass, portInfo, module);
249 }
250 }
251
252 private void generateWSDL(Class serviceClass, PortInfo portInfo, Module module)
253 throws DeploymentException {
254 if (isWsdlSet(portInfo, serviceClass)) {
255 LOG.debug("Service " + portInfo.getServiceName() + " has WSDL.");
256 return;
257 }
258 LOG.debug("Service " + portInfo.getServiceName() + " does not have WSDL. Generating WSDL...");
259
260 WsdlGenerator generator = new WsdlGenerator();
261 generator.setSunSAAJ();
262
263 JaxWsImplementorInfo serviceInfo = new JaxWsImplementorInfo(serviceClass);
264
265 // set wsdl service
266 if (portInfo.getWsdlService() == null) {
267 generator.setWsdlService(serviceInfo.getServiceName());
268 } else {
269 generator.setWsdlService(portInfo.getWsdlService());
270 }
271
272 // set wsdl port
273 if (portInfo.getWsdlPort() != null) {
274 generator.setWsdlPort(portInfo.getWsdlPort());
275 }
276
277 String wsdlFile = generator.generateWsdl(module, serviceClass.getName(), module.getEarContext(), portInfo);
278 portInfo.setWsdlFile(wsdlFile);
279
280 LOG.debug("Generated " + wsdlFile + " for service " + portInfo.getServiceName());
281 }
282
283 private boolean isWsdlSet(PortInfo portInfo, Class serviceClass) {
284 return (portInfo.getWsdlFile() != null && !portInfo.getWsdlFile().trim().equals(""))
285 || JAXWSUtils.containsWsdlLocation(serviceClass, serviceClass.getClassLoader());
286 }
287
288 public static final GBeanInfo GBEAN_INFO;
289
290 static {
291 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(CXFBuilder.class, NameFactory.MODULE_BUILDER);
292 infoBuilder.addInterface(WebServiceBuilder.class);
293 infoBuilder.addAttribute("defaultEnvironment", Environment.class, true, true);
294
295 infoBuilder.setConstructor(new String[]{"defaultEnvironment"});
296
297 GBEAN_INFO = infoBuilder.getBeanInfo();
298 }
299
300 public static GBeanInfo getGBeanInfo() {
301 return GBEAN_INFO;
302 }
303
304 }