001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.geoserver.request;
006:
007: import org.geoserver.ows.util.EncodingInfo;
008: import org.geoserver.ows.util.XmlCharsetDetector;
009: import org.geoserver.platform.GeoServerExtensions;
010: import org.springframework.web.servlet.ModelAndView;
011: import org.springframework.web.servlet.mvc.AbstractController;
012: import org.vfny.geoserver.ServiceException;
013: import org.vfny.geoserver.global.GeoServer;
014: import org.vfny.geoserver.servlets.AbstractService;
015: import org.vfny.geoserver.util.requests.readers.DispatcherKvpReader;
016: import org.vfny.geoserver.util.requests.readers.DispatcherXmlReader;
017: import java.io.BufferedInputStream;
018: import java.io.BufferedOutputStream;
019: import java.io.BufferedReader;
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.FileOutputStream;
023: import java.io.IOException;
024: import java.io.InputStream;
025: import java.util.ArrayList;
026: import java.util.Date;
027: import java.util.Enumeration;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031: import java.util.Map.Entry;
032: import javax.servlet.ServletException;
033: import javax.servlet.http.HttpServletRequest;
034: import javax.servlet.http.HttpServletResponse;
035:
036: /**
037: * Root dispatcher which handles all incoming requests.
038: * <p>
039: *
040: * </p>
041: *
042: * @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
043: * @deprecated use {@link org.geoserver.ows.Dispatcher}.
044: */
045: public class Dispatcher extends AbstractController {
046: GeoServer geoServer;
047:
048: public Dispatcher(GeoServer geoServer) {
049: this .geoServer = geoServer;
050: }
051:
052: protected ModelAndView handleRequestInternal(
053: HttpServletRequest httpRequest,
054: HttpServletResponse httpResponse) throws Exception {
055: try {
056: try {
057: dispatch(httpRequest, httpResponse);
058: } catch (IOException e) {
059: throw new ServiceException(e);
060: } catch (ServletException e) {
061: throw new ServiceException(e);
062: }
063: } catch (ServiceException se) {
064: String tempResponse = se.getXmlResponse(geoServer
065: .isVerboseExceptions(), httpRequest, geoServer);
066:
067: httpResponse.setContentType(geoServer.getCharSet()
068: .toString());
069: httpResponse.getWriter().write(tempResponse);
070: }
071:
072: return null;
073: }
074:
075: AbstractService find(String service, String request)
076: throws ServiceException {
077: //map request parameters to a Request bean to handle it
078: List requests = GeoServerExtensions
079: .extensions(AbstractService.class);
080:
081: List matches = new ArrayList();
082:
083: for (Iterator itr = requests.iterator(); itr.hasNext();) {
084: AbstractService bean = (AbstractService) itr.next();
085: //we allow for a null service
086: if (service == null) {
087: if (bean.getRequest().toLowerCase().startsWith(
088: request.toLowerCase().trim())) {
089: //we have a winner
090: matches.add(bean);
091: }
092: } else {
093: if (bean.getService().toLowerCase().startsWith(
094: service.toLowerCase().trim())
095: && bean.getRequest().equalsIgnoreCase(
096: request.trim())) {
097: //we have a winner
098: matches.add(bean);
099: }
100: }
101: }
102:
103: if (matches.isEmpty()) {
104: return null;
105: }
106:
107: if (matches.size() > 1) {
108: String msg = "Multiple requests found capable of handling:"
109: + " (" + service + "," + request + ")";
110: throw new ServiceException(msg);
111: }
112:
113: return (AbstractService) matches.get(0);
114: }
115:
116: void dispatch(HttpServletRequest httpRequest,
117: HttpServletResponse httpResponse) throws ServiceException,
118: IOException, ServletException {
119: //mark as get request if it is indeed a get request, or a post request with content type
120: // == 'application/x-www-form-urlencoded'
121: boolean isGet = "GET".equalsIgnoreCase(httpRequest.getMethod())
122: || ((httpRequest.getContentType() != null) && httpRequest
123: .getContentType().startsWith(
124: "application/x-www-form-urlencoded"));
125:
126: String service = null;
127: String request = null;
128:
129: //look up service / request in key value pairs
130: for (Enumeration e = httpRequest.getParameterNames(); e
131: .hasMoreElements();) {
132: String key = (String) e.nextElement();
133:
134: if ("service".equalsIgnoreCase(key)) {
135: service = httpRequest.getParameter(key);
136: }
137:
138: if ("request".equalsIgnoreCase(key)) {
139: request = httpRequest.getParameter(key);
140: }
141: }
142:
143: if ((service == null) || (request == null)) {
144: //lookup in context path, (http://.../geoserver/service/request?)
145: String path = httpRequest.getContextPath();
146: StringBuffer uriBuf = new StringBuffer(httpRequest
147: .getRequestURI());
148:
149: while (uriBuf.indexOf("/") == 0) {
150: uriBuf.deleteCharAt(0);
151: }
152:
153: uriBuf.insert(0, "/");
154:
155: String uri;
156:
157: if (uriBuf.length() > path.length()) {
158: uri = uriBuf.substring(path.length() + 1);
159: } else {
160: uri = uriBuf.toString();
161: }
162:
163: int index = uri.indexOf('/');
164:
165: if (index != -1) {
166: //take everything before the slash to be the service and
167: // everything after to be the request
168: if (service == null) {
169: service = uri.substring(0, index);
170: }
171:
172: if (request == null) {
173: request = uri.substring(index + 1);
174: }
175: } else {
176: //just take the whole string to be the service
177: if (service == null) {
178: service = uri;
179: }
180: }
181: }
182:
183: /**
184: * ALFA: this is a HACK to let GeoServer do a getCapabilities request by default.
185: */
186:
187: /*request = (request == null ? "GetCapabilities" : request);*/
188: if ((service == null) || (request == null)) {
189: //check for a POST request specifying the request as the
190: if (!isGet) {
191: post(httpRequest, httpResponse);
192:
193: return;
194: }
195: }
196:
197: AbstractService target = find(service, request);
198:
199: if (target != null) {
200: //we have a servlet, do it
201: if (isGet) {
202: target.doGet(httpRequest, httpResponse);
203: } else {
204: target.doPost(httpRequest, httpResponse);
205: }
206: } else {
207: String msg = "Could not locate service mapping to: ("
208: + service + "," + request + ")";
209: throw new ServiceException(msg);
210: }
211: }
212:
213: //static int sequence = 0;
214: void post(HttpServletRequest httpRequest,
215: HttpServletResponse httpResponse) throws ServiceException,
216: IOException, ServletException {
217: File temp;
218:
219: InputStream is = new BufferedInputStream(httpRequest
220: .getInputStream());
221:
222: // REVISIT: Should do more than sequence here
223: // (In case we are running two GeoServers at once)
224: // - Could we use response.getHandle() in the filename?
225: // - ProcessID is traditional, I don't know how to find that in Java
226: long sequence = new Date().getTime();
227:
228: // test to see if we have permission to write, if not, throw an appropirate error
229: try {
230: temp = File.createTempFile("dispatch" + sequence, "tmp");
231:
232: if (!temp.canRead() || !temp.canWrite()) {
233: String errorMsg = "Temporary-file permission problem for location: "
234: + temp.getPath();
235: throw new IOException(errorMsg);
236: }
237: } catch (IOException e) {
238: String errorMsg = "Possible file permission problem. Root cause: \n"
239: + e.toString();
240: IOException newE = new IOException(errorMsg);
241: throw newE;
242: }
243:
244: FileOutputStream fos = new FileOutputStream(temp);
245: BufferedOutputStream out = new BufferedOutputStream(fos);
246:
247: int c;
248:
249: while (-1 != (c = is.read())) {
250: out.write(c);
251: }
252:
253: is.close();
254: out.flush();
255: out.close();
256:
257: //JD: GEOS-323, Adding char encoding support
258: EncodingInfo encInfo = new EncodingInfo();
259:
260: BufferedReader disReader;
261: BufferedReader requestReader;
262:
263: try {
264: disReader = new BufferedReader(XmlCharsetDetector
265: .getCharsetAwareReader(new FileInputStream(temp),
266: encInfo));
267:
268: requestReader = new BufferedReader(XmlCharsetDetector
269: .createReader(new FileInputStream(temp), encInfo));
270: } catch (Exception e) {
271: /*
272: * Any exception other than WfsException will "hang up" the
273: * process - no client output, no log entries, only "Internal
274: * server error". So this is a little trick to make detector's
275: * exceptions "visible".
276: */
277: throw new ServiceException(e);
278: }
279:
280: AbstractService target = null;
281:
282: //JD: GEOS-323, Adding char encoding support
283: boolean kvpRequestContent = false;
284:
285: if (disReader != null) {
286: try {
287: DispatcherXmlReader requestTypeAnalyzer = new DispatcherXmlReader();
288: requestTypeAnalyzer.read(disReader, httpRequest);
289:
290: target = find(requestTypeAnalyzer.getService(),
291: requestTypeAnalyzer.getRequest());
292: } catch (ServiceException e) {
293: DispatcherKvpReader requestTypeAnalyzer = new DispatcherKvpReader();
294: requestTypeAnalyzer.read(requestReader, httpRequest);
295:
296: target = find(requestTypeAnalyzer.getService(),
297: requestTypeAnalyzer.getRequest());
298: target.setKvpString(requestTypeAnalyzer
299: .getQueryString());
300: kvpRequestContent = true;
301: }
302: }
303:
304: if (target == null) {
305: String msg = "Could not locate service for request";
306: throw new ServiceException(msg);
307: }
308:
309: if (!kvpRequestContent) {
310: if (requestReader != null) {
311: target.doPost(httpRequest, httpResponse, requestReader);
312: } else {
313: target.doPost(httpRequest, httpResponse);
314: }
315: } else {
316: target.doGet(httpRequest, httpResponse);
317: }
318:
319: disReader.close();
320: requestReader.close();
321: temp.delete();
322: }
323: }
|