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.io.OutputStream;
023: import java.security.Principal;
024: import java.util.Collection;
025: import java.util.Set;
026: import java.util.logging.Level;
027: import java.util.logging.Logger;
028:
029: import javax.servlet.ServletException;
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.http.HttpServletResponse;
032:
033: import org.apache.cxf.Bus;
034: import org.apache.cxf.common.util.StringUtils;
035: import org.apache.cxf.message.ExchangeImpl;
036: import org.apache.cxf.message.Message;
037: import org.apache.cxf.message.MessageImpl;
038: import org.apache.cxf.security.SecurityContext;
039: import org.apache.cxf.service.model.EndpointInfo;
040: import org.apache.cxf.transport.http.AbstractHTTPDestination;
041: import org.apache.cxf.transport.http.HTTPSession;
042: import org.apache.cxf.transport.https.SSLUtils;
043: import org.apache.cxf.transports.http.QueryHandler;
044: import org.apache.cxf.transports.http.QueryHandlerRegistry;
045: import org.xmlsoap.schemas.wsdl.http.AddressType;
046:
047: public class ServletController {
048:
049: private static final Logger LOG = Logger
050: .getLogger(ServletController.class.getName());
051:
052: private ServletTransportFactory transport;
053: private CXFServlet cxfServlet;
054: private String lastBase = "";
055:
056: public ServletController(ServletTransportFactory df,
057: CXFServlet servlet) {
058: this .transport = df;
059: this .cxfServlet = servlet;
060: }
061:
062: private synchronized void updateDests(HttpServletRequest request) {
063: String base = getBaseURL(request);
064:
065: if (base.equals(lastBase)) {
066: return;
067: }
068: Set<String> paths = transport.getDestinationsPaths();
069: for (String path : paths) {
070: ServletDestination d2 = transport
071: .getDestinationForPath(path);
072: String ad = d2.getEndpointInfo().getAddress();
073: if (ad.equals(path) || ad.equals(lastBase + path)) {
074: d2.getEndpointInfo().setAddress(base + path);
075: if (d2.getEndpointInfo().getExtensor(AddressType.class) != null) {
076: d2.getEndpointInfo().getExtensor(AddressType.class)
077: .setLocation(base + path);
078: }
079: }
080: }
081: lastBase = base;
082: }
083:
084: public void invoke(HttpServletRequest request,
085: HttpServletResponse res) throws ServletException {
086: try {
087: EndpointInfo ei = new EndpointInfo();
088: String address = request.getPathInfo() == null ? ""
089: : request.getPathInfo();
090:
091: ei.setAddress(address);
092: ServletDestination d = (ServletDestination) transport
093: .getDestinationForPath(ei.getAddress());
094:
095: if (d == null) {
096: if (request.getRequestURI().endsWith("services")
097: || request.getRequestURI()
098: .endsWith("services/")
099: || StringUtils.isEmpty(request.getPathInfo())
100: || "/".equals(request.getPathInfo())) {
101: updateDests(request);
102: generateServiceList(request, res);
103: } else {
104: d = checkRestfulRequest(request);
105: if (d == null || d.getMessageObserver() == null) {
106: LOG.warning("Can't find the the request for "
107: + request.getRequestURL()
108: + "'s Observer ");
109: generateNotFound(request, res);
110: } else { // the request should be a restful service request
111: updateDests(request);
112: invokeDestination(request, res, d);
113: }
114: }
115: } else {
116: ei = d.getEndpointInfo();
117: Bus bus = cxfServlet.getBus();
118: if (null != request.getQueryString()
119: && request.getQueryString().length() > 0
120: && bus.getExtension(QueryHandlerRegistry.class) != null) {
121:
122: String ctxUri = request.getPathInfo();
123: String baseUri = request.getRequestURL().toString()
124: + "?" + request.getQueryString();
125: // update the EndPoint Address with request url
126: if ("GET".equals(request.getMethod())) {
127: updateDests(request);
128: }
129:
130: for (QueryHandler qh : bus.getExtension(
131: QueryHandlerRegistry.class).getHandlers()) {
132: if (qh.isRecognizedQuery(baseUri, ctxUri, ei)) {
133:
134: res.setContentType(qh
135: .getResponseContentType(baseUri,
136: ctxUri));
137: OutputStream out = res.getOutputStream();
138: try {
139: qh.writeResponse(baseUri, ctxUri, ei,
140: out);
141: out.flush();
142: return;
143: } catch (Exception e) {
144: throw new ServletException(e);
145: }
146: }
147: }
148: }
149:
150: invokeDestination(request, res, d);
151: }
152: } catch (IOException e) {
153: throw new ServletException(e);
154: }
155: }
156:
157: private ServletDestination checkRestfulRequest(
158: HttpServletRequest request) throws IOException {
159:
160: String address = request.getPathInfo() == null ? "" : request
161: .getPathInfo();
162:
163: for (String path : transport.getDestinationsPaths()) {
164: if (address.startsWith(path)) {
165: return transport.getDestinationForPath(path);
166: }
167: }
168: return null;
169: }
170:
171: private void generateServiceList(HttpServletRequest request,
172: HttpServletResponse response) throws IOException {
173: Collection<ServletDestination> destinations = transport
174: .getDestinations();
175: response.setContentType("text/html");
176: response.getWriter().write("<html><body>");
177:
178: if (destinations.size() > 0) {
179: for (ServletDestination sd : destinations) {
180: if (null != sd.getEndpointInfo().getName()) {
181: String address = sd.getEndpointInfo().getAddress();
182: response.getWriter().write(
183: "<p> <a href=\"" + address + "?wsdl\">");
184: response.getWriter().write(
185: sd.getEndpointInfo().getName()
186: + "</a> </p>");
187: }
188: }
189: } else {
190: response.getWriter().write("No service was found.");
191: }
192: response.getWriter().write("</body></html>");
193: }
194:
195: private String getBaseURL(HttpServletRequest request) {
196: String reqPerfix = request.getRequestURL().toString();
197: String pathInfo = request.getPathInfo() == null ? "" : request
198: .getPathInfo();
199: reqPerfix = reqPerfix.substring(0, reqPerfix.length()
200: - pathInfo.length());
201: return reqPerfix;
202: }
203:
204: protected void generateNotFound(HttpServletRequest request,
205: HttpServletResponse res) throws IOException {
206: res.setStatus(404);
207: res.setContentType("text/html");
208: res.getWriter().write(
209: "<html><body>No service was found.</body></html>");
210: }
211:
212: public void invokeDestination(final HttpServletRequest request,
213: HttpServletResponse response, ServletDestination d)
214: throws ServletException {
215: if (LOG.isLoggable(Level.FINE)) {
216: LOG.fine("Service http request on thread: "
217: + Thread.currentThread());
218: }
219:
220: try {
221: MessageImpl inMessage = new MessageImpl();
222: inMessage.setContent(InputStream.class, request
223: .getInputStream());
224: inMessage
225: .put(AbstractHTTPDestination.HTTP_REQUEST, request);
226: inMessage.put(AbstractHTTPDestination.HTTP_RESPONSE,
227: response);
228: inMessage.put(AbstractHTTPDestination.HTTP_CONTEXT,
229: cxfServlet.getServletContext());
230: inMessage.put(Message.HTTP_REQUEST_METHOD, request
231: .getMethod());
232: inMessage.put(Message.PATH_INFO, request.getPathInfo());
233: inMessage.put(Message.QUERY_STRING, request
234: .getQueryString());
235: inMessage.put(Message.CONTENT_TYPE, request
236: .getContentType());
237: inMessage.put(Message.BASE_PATH, d.getAddress()
238: .getAddress().getValue());
239: inMessage.put(SecurityContext.class, new SecurityContext() {
240: public Principal getUserPrincipal() {
241: return request.getUserPrincipal();
242: }
243:
244: public boolean isUserInRole(String role) {
245: return request.isUserInRole(role);
246: }
247: });
248:
249: // work around a bug with Jetty which results in the character
250: // encoding not being trimmed correctly.
251: String enc = request.getCharacterEncoding();
252: if (enc != null && enc.endsWith("\"")) {
253: enc = enc.substring(0, enc.length() - 1);
254: }
255:
256: inMessage.put(Message.ENCODING, enc);
257: SSLUtils.propogateSecureSession(request, inMessage);
258:
259: ExchangeImpl exchange = new ExchangeImpl();
260: exchange.setInMessage(inMessage);
261: exchange.setSession(new HTTPSession(request));
262:
263: d.doMessage(inMessage);
264: } catch (IOException e) {
265: throw new ServletException(e);
266: }
267:
268: }
269: }
|