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