001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.transport.servlet;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.lang.ref.WeakReference;
023: import java.util.Hashtable;
024: import java.util.Map;
025: import java.util.logging.Level;
026: import java.util.logging.Logger;
027:
028: import javax.servlet.ServletConfig;
029: import javax.servlet.ServletContext;
030: import javax.servlet.ServletException;
031: import javax.servlet.http.HttpServlet;
032: import javax.servlet.http.HttpServletRequest;
033: import javax.servlet.http.HttpServletResponse;
034:
035: import org.apache.cxf.Bus;
036: import org.apache.cxf.BusException;
037: import org.apache.cxf.BusFactory;
038: import org.apache.cxf.bus.spring.SpringBusFactory;
039: import org.apache.cxf.common.classloader.ClassLoaderUtils;
040: import org.apache.cxf.common.logging.LogUtils;
041: import org.apache.cxf.resource.ResourceManager;
042: import org.apache.cxf.resource.URIResolver;
043: import org.apache.cxf.transport.DestinationFactory;
044: import org.apache.cxf.transport.DestinationFactoryManager;
045: import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
046: import org.springframework.context.ApplicationContext;
047: import org.springframework.context.support.GenericApplicationContext;
048: import org.springframework.core.io.InputStreamResource;
049:
050: /**
051: * A Servlet which supports loading of JAX-WS endpoints from an
052: * XML file and handling requests for endpoints created via other means
053: * such as Spring beans, or the Java API. All requests are passed on
054: * to the {@link ServletController}.
055: *
056: */
057: public class CXFServlet extends HttpServlet {
058: static final Map<String, WeakReference<Bus>> BUS_MAP = new Hashtable<String, WeakReference<Bus>>();
059: static final Logger LOG = LogUtils.getL7dLogger(CXFServlet.class);
060:
061: private Bus bus;
062: private ServletTransportFactory servletTransportFactory;
063: private ServletController controller;
064: private GenericApplicationContext childCtx;
065:
066: public ServletController createServletController() {
067: return new ServletController(servletTransportFactory, this );
068: }
069:
070: public ServletController getController() {
071: return controller;
072: }
073:
074: public Bus getBus() {
075: return bus;
076: }
077:
078: public void init(ServletConfig servletConfig)
079: throws ServletException {
080: super .init(servletConfig);
081:
082: try {
083: BusFactory.setThreadDefaultBus(null);
084:
085: String busid = servletConfig.getInitParameter("bus.id");
086: if (null != busid) {
087: WeakReference<Bus> ref = BUS_MAP.get(busid);
088: if (null != ref) {
089: bus = ref.get();
090: BusFactory.setThreadDefaultBus(bus);
091: }
092: }
093:
094: String springCls = "org.springframework.context.ApplicationContext";
095: try {
096: ClassLoaderUtils.loadClass(springCls, getClass());
097: loadSpringBus(servletConfig);
098: } catch (ClassNotFoundException e) {
099: loadBusNoConfig(servletConfig);
100: }
101:
102: if (null != busid) {
103: BUS_MAP.put(busid, new WeakReference<Bus>(bus));
104: }
105: } finally {
106: BusFactory.setThreadDefaultBus(null);
107: }
108: }
109:
110: private void loadBusNoConfig(ServletConfig servletConfig)
111: throws ServletException {
112:
113: if (bus == null) {
114: LOG.info("LOAD_BUS_WITHOUT_APPLICATION_CONTEXT");
115: bus = BusFactory.newInstance().createBus();
116: }
117: ResourceManager resourceManager = bus
118: .getExtension(ResourceManager.class);
119: resourceManager
120: .addResourceResolver(new ServletContextResourceResolver(
121: servletConfig.getServletContext()));
122:
123: // Set up the ServletController
124: controller = createServletController();
125:
126: replaceDestionFactory();
127:
128: }
129:
130: private void loadSpringBus(ServletConfig servletConfig)
131: throws ServletException {
132:
133: // try to pull an existing ApplicationContext out of the
134: // ServletContext
135: ServletContext svCtx = getServletContext();
136:
137: // Spring 1.x
138: ApplicationContext ctx = (ApplicationContext) svCtx
139: .getAttribute("interface org.springframework.web.context.WebApplicationContext.ROOT");
140:
141: // Spring 2.0
142: if (ctx == null) {
143: ctx = (ApplicationContext) svCtx
144: .getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
145: }
146:
147: // This constructor works whether there is a context or not
148: // If the ctx is null, we just start up the default bus
149: if (ctx == null) {
150: LOG.info("LOAD_BUS_WITHOUT_APPLICATION_CONTEXT");
151: bus = new SpringBusFactory().createBus();
152: } else {
153: LOG.info("LOAD_BUS_WITH_APPLICATION_CONTEXT");
154: bus = new SpringBusFactory(ctx).createBus();
155: }
156: ResourceManager resourceManager = bus
157: .getExtension(ResourceManager.class);
158: resourceManager
159: .addResourceResolver(new ServletContextResourceResolver(
160: servletConfig.getServletContext()));
161:
162: replaceDestionFactory();
163:
164: // Set up the ServletController
165: controller = createServletController();
166:
167: // build endpoints from the web.xml or a config file
168: loadAdditionalConfig(ctx, servletConfig);
169: }
170:
171: protected void loadAdditionalConfig(ApplicationContext ctx,
172: ServletConfig servletConfig) throws ServletException {
173: String location = servletConfig
174: .getInitParameter("config-location");
175: if (location == null) {
176: location = "/WEB-INF/cxf-servlet.xml";
177: }
178: InputStream is = null;
179: try {
180: is = servletConfig.getServletContext().getResourceAsStream(
181: location);
182:
183: if (is == null || is.available() == -1) {
184: URIResolver resolver = new URIResolver(location);
185:
186: if (resolver.isResolved()) {
187: is = resolver.getInputStream();
188: }
189: }
190: } catch (IOException e) {
191: //throw new ServletException(e);
192: }
193:
194: if (is != null) {
195: LOG.log(Level.INFO, "BUILD_ENDPOINTS_FROM_CONFIG_LOCATION",
196: new Object[] { location });
197: childCtx = new GenericApplicationContext(ctx);
198:
199: XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(
200: childCtx);
201: reader
202: .setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
203: reader.loadBeanDefinitions(new InputStreamResource(is,
204: location));
205:
206: childCtx.refresh();
207: }
208: }
209:
210: /**
211: * @return
212: */
213: protected DestinationFactory createServletTransportFactory() {
214: if (servletTransportFactory == null) {
215: servletTransportFactory = new ServletTransportFactory(bus);
216: }
217: return servletTransportFactory;
218: }
219:
220: private void registerTransport(DestinationFactory factory,
221: String namespace) {
222: bus.getExtension(DestinationFactoryManager.class)
223: .registerDestinationFactory(namespace, factory);
224: }
225:
226: private void replaceDestionFactory() throws ServletException {
227:
228: DestinationFactoryManager dfm = bus
229: .getExtension(DestinationFactoryManager.class);
230: try {
231: DestinationFactory df = dfm
232: .getDestinationFactory("http://cxf.apache.org/transports/http/configuration");
233: if (df instanceof ServletTransportFactory) {
234: servletTransportFactory = (ServletTransportFactory) df;
235: LOG.info("DESTIONFACTORY_ALREADY_REGISTERED");
236: return;
237: }
238: } catch (BusException e) {
239: // why are we throwing a busexception if the DF isn't found?
240: }
241:
242: DestinationFactory factory = createServletTransportFactory();
243:
244: for (String s : factory.getTransportIds()) {
245: registerTransport(factory, s);
246: }
247: LOG.info("REPLACED_HTTP_DESTIONFACTORY");
248: }
249:
250: public void destroy() {
251: if (childCtx != null) {
252: childCtx.destroy();
253: }
254:
255: String s = bus.getId();
256: BUS_MAP.remove(s);
257: bus.shutdown(true);
258: }
259:
260: protected void doPost(HttpServletRequest request,
261: HttpServletResponse response) throws ServletException {
262: invoke(request, response);
263: }
264:
265: protected void doGet(HttpServletRequest request,
266: HttpServletResponse response) throws ServletException {
267: invoke(request, response);
268: }
269:
270: @Override
271: protected void doDelete(HttpServletRequest request,
272: HttpServletResponse response) throws ServletException,
273: IOException {
274: invoke(request, response);
275: }
276:
277: @Override
278: protected void doPut(HttpServletRequest request,
279: HttpServletResponse response) throws ServletException,
280: IOException {
281: invoke(request, response);
282: }
283:
284: private void invoke(HttpServletRequest request,
285: HttpServletResponse response) throws ServletException {
286: try {
287: BusFactory.setThreadDefaultBus(getBus());
288: controller.invoke(request, response);
289: } finally {
290: BusFactory.setThreadDefaultBus(null);
291: }
292: }
293: }
|