001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/enterprise/servlet/OGCServletController.java $
002: // $Id: OGCServletController.java 10393 2008-03-04 16:15:57Z rbezema $
003: /*---------------- FILE HEADER ------------------------------------------
004:
005: This file is part of deegree.
006: Copyright (C) 2001-2008 by:
007: EXSE, Department of Geography, University of Bonn
008: http://www.giub.uni-bonn.de/deegree/
009: lat/lon GmbH
010: http://www.lat-lon.de
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: License as published by the Free Software Foundation; either
015: version 2.1 of the License, or (at your option) any later version.
016:
017: This library is distributed in the hope that it will be useful,
018: but WITHOUT ANY WARRANTY; without even the implied warranty of
019: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
020: Lesser General Public License for more details.
021:
022: You should have received a copy of the GNU Lesser General Public
023: License along with this library; if not, write to the Free Software
024: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
025:
026: Contact:
027:
028: Andreas Poth
029: lat/lon GmbH
030: Aennchenstr. 19
031: 53115 Bonn
032: Germany
033: E-Mail: poth@lat-lon.de
034:
035: Prof. Dr. Klaus Greve
036: Department of Geography
037: University of Bonn
038: Meckenheimer Allee 166
039: 53115 Bonn
040: Germany
041: E-Mail: greve@giub.uni-bonn.de
042:
043:
044: ---------------------------------------------------------------------------*/
045:
046: package org.deegree.enterprise.servlet;
047:
048: import java.io.IOException;
049: import java.io.OutputStream;
050: import java.io.PrintWriter;
051: import java.lang.reflect.InvocationTargetException;
052: import java.lang.reflect.Method;
053: import java.net.InetAddress;
054: import java.net.URL;
055: import java.nio.charset.Charset;
056: import java.text.MessageFormat;
057: import java.util.HashMap;
058: import java.util.Iterator;
059: import java.util.Map;
060:
061: import javax.servlet.ServletContext;
062: import javax.servlet.ServletException;
063: import javax.servlet.http.HttpServletRequest;
064: import javax.servlet.http.HttpServletResponse;
065:
066: import org.deegree.enterprise.AbstractOGCServlet;
067: import org.deegree.enterprise.ServiceException;
068: import org.deegree.framework.log.ILogger;
069: import org.deegree.framework.log.LoggerFactory;
070: import org.deegree.framework.util.CharsetUtils;
071: import org.deegree.framework.util.KVP2Map;
072: import org.deegree.framework.util.StringTools;
073: import org.deegree.framework.util.WebappResourceResolver;
074: import org.deegree.framework.version.Version;
075: import org.deegree.framework.xml.XMLFragment;
076: import org.deegree.ogcwebservices.ExceptionReport;
077: import org.deegree.ogcwebservices.OGCRequestFactory;
078: import org.deegree.ogcwebservices.OGCWebServiceException;
079: import org.deegree.ogcwebservices.OGCWebServiceRequest;
080: import org.deegree.ogcwebservices.wmps.configuration.WMPSConfigurationDocument;
081: import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument;
082: import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationDocument_1_3_0;
083: import org.deegree.owscommon.XMLFactory;
084: import org.xml.sax.SAXException;
085:
086: /**
087: * An <code>OGCServletController</code> handles all incoming requests. The controller for all OGC service requests.
088: * Dispatcher to specific handler for WMS, WFS and other.
089: *
090: * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a>
091: *
092: * @author last edited by: $Author: rbezema $
093: *
094: * @see <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html">Front controller </a>
095: */
096: public class OGCServletController extends AbstractOGCServlet {
097:
098: /**
099: * address is the url of the client which requests.
100: */
101: public static String address = null;
102:
103: private static final long serialVersionUID = -4461759017823581221L;
104:
105: private static final ILogger LOG = LoggerFactory
106: .getLogger(OGCServletController.class);
107:
108: private static final String SERVICE = "services";
109:
110: private static final String HANDLER_CLASS = ".handler";
111:
112: private static final String HANDLER_CONF = ".config";
113:
114: private static final Map<Class<?>, String> SERVICE_FACTORIES_MAPPINGS = new HashMap<Class<?>, String>();
115:
116: private static final String ERR_MSG = "Can't set configuration for {0}";
117:
118: /**
119: *
120: *
121: * @param request
122: * @param response
123: * @TODO refactor and optimize code for initializing handler
124: */
125: public void doService(HttpServletRequest request,
126: HttpServletResponse response) {
127: if (response.isCommitted()) {
128: LOG
129: .logWarning("The response object is already committed, cannot proceed!");
130: return;
131: }
132:
133: long startTime = System.currentTimeMillis();
134: address = request.getRequestURL().toString();
135:
136: String service = null;
137: try {
138: OGCWebServiceRequest ogcRequest = OGCRequestFactory
139: .create(request);
140:
141: LOG.logInfo(StringTools.concat(500, "Handling request '",
142: ogcRequest.getId(), "' from '", request
143: .getRemoteAddr(), "' to service: '",
144: ogcRequest.getServiceName(), "'"));
145:
146: // get service from request
147: service = ogcRequest.getServiceName().toUpperCase();
148:
149: // get handler instance
150: ServiceDispatcher handler = ServiceLookup.getInstance()
151: .getHandler(service, request.getRemoteAddr());
152: // dispatch request to specific handler
153: handler.perform(ogcRequest, response);
154: } catch (OGCWebServiceException e) {
155: LOG.logError(e.getMessage(), e);
156: sendException(response, e, request, service);
157: } catch (ServiceException e) {
158: if (e.getNestedException() instanceof OGCWebServiceException) {
159: sendException(response, (OGCWebServiceException) e
160: .getNestedException(), request, service);
161: } else {
162: sendException(response, new OGCWebServiceException(this
163: .getClass().getName(), e.getMessage()),
164: request, service);
165: }
166: LOG.logError(e.getMessage(), e);
167: } catch (Exception e) {
168: sendException(response, new OGCWebServiceException(this
169: .getClass().getName(), e.getMessage()), request,
170: service);
171: LOG.logError(e.getMessage(), e);
172: }
173: if (LOG.isDebug()) {
174: LOG.logDebug("OGCServletController: request performed in "
175: + Long.toString(System.currentTimeMillis()
176: - startTime) + " milliseconds.");
177: }
178: }
179:
180: /**
181: * Sends the passed <code>OGCWebServiceException</code> to the calling client.
182: *
183: * @param response
184: * @param e
185: */
186: @SuppressWarnings("unchecked")
187: // for castthe map
188: private void sendException(HttpServletResponse response,
189: OGCWebServiceException e, HttpServletRequest request,
190: String service) {
191: LOG.logInfo("Sending OGCWebServiceException to client.");
192:
193: // according to Sun's JavaDoc, the map always has this type
194: Map<String, String[]> map = request.getParameterMap();
195:
196: boolean isWMS130 = false, isCSW = false, isWCTS = false;
197:
198: if (service != null) {
199: if ("wms".equalsIgnoreCase(service)) {
200: for (String str : map.keySet()) {
201: if (str.equalsIgnoreCase("version")) {
202: String[] version = map.get(str);
203: if (version != null && version.length > 0
204: && version[0].equals("1.3.0")) {
205: isWMS130 = true;
206: }
207: }
208: }
209: }
210:
211: isCSW = "csw".equalsIgnoreCase(service);
212: isWCTS = "wcts".equalsIgnoreCase(service);
213: } else {
214: // could clash with other services!
215: for (String str : map.keySet()) {
216: if (str.equalsIgnoreCase("version")) {
217: String[] version = map.get(str);
218: if (version != null && version.length > 0
219: && version[0].equals("1.3.0")) {
220: isWMS130 = true;
221: }
222: }
223: }
224:
225: for (String str : map.keySet()) {
226: if (str.equalsIgnoreCase("service")) {
227: isCSW = map.get(str)[0].equalsIgnoreCase("csw");
228: isWCTS = "wcts".equalsIgnoreCase(map.get(str)[0]);
229: break;
230: }
231: }
232:
233: try {
234: XMLFragment doc = new XMLFragment(request.getReader(),
235: XMLFragment.DEFAULT_URL);
236: service = OGCRequestFactory.getTargetService("", "",
237: doc.getRootElement().getOwnerDocument());
238: isCSW = "csw".equalsIgnoreCase(service);
239: isWCTS = "wcts".equalsIgnoreCase(service);
240: } catch (SAXException e1) {
241: // ignore
242: } catch (IOException e1) {
243: // ignore
244: }
245: }
246:
247: try {
248: XMLFragment doc;
249: String contentType = "text/xml";
250: if (isWMS130 || "wcs".equalsIgnoreCase(e.getLocator())) {
251: doc = XMLFactory.exportNS(new ExceptionReport(
252: new OGCWebServiceException[] { e }));
253: } else if (isCSW) {
254: doc = XMLFactory
255: .exportExceptionReport(new ExceptionReport(
256: new OGCWebServiceException[] { e }));
257: } else if (isWCTS) {
258: doc = org.deegree.owscommon_1_1_0.XMLFactory
259: .exportException(e);
260: } else {
261: contentType = "application/vnd.ogc.se_xml";
262: doc = XMLFactory.export(new ExceptionReport(
263: new OGCWebServiceException[] { e }));
264: }
265: response.setContentType(contentType);
266: OutputStream os = response.getOutputStream();
267: doc.write(os);
268: os.close();
269: } catch (Exception ex) {
270: LOG.logError("ERROR: " + ex.getMessage(), ex);
271: }
272: }
273:
274: /**
275: *
276: * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
277: * javax.servlet.http.HttpServletResponse)
278: */
279: @Override
280: protected void doGet(HttpServletRequest request,
281: HttpServletResponse response) throws ServletException,
282: IOException {
283:
284: LOG.logDebug("query string ", request.getQueryString());
285: if (request.getParameter("RELOADDEEGREE") != null) {
286: reloadServices(request, response);
287: } else {
288: this .doService(request, response);
289: }
290: }
291:
292: /**
293: *
294: * @param request
295: * @param response
296: * @throws ServletException
297: * @throws IOException
298: */
299: private void reloadServices(HttpServletRequest request,
300: HttpServletResponse response) throws ServletException,
301: IOException {
302: Map<?, ?> map = KVP2Map.toMap(request);
303: String user = (String) map.get("USER");
304: String password = (String) map.get("PASSWORD");
305: String message = null;
306: if (getInitParameter("USER") != null
307: && getInitParameter("PASSWORD") != null
308: && getInitParameter("USER").equals(user)
309: && getInitParameter("PASSWORD").equals(password)) {
310: initServices(getServletContext());
311: ctDestroyed();
312: message = Messages
313: .getString("OGCServletController.reloadsuccess");
314: } else {
315: message = Messages
316: .getString("OGCServletController.reloadfailed");
317: }
318: PrintWriter pw = response.getWriter();
319: pw.print(message);
320: pw.flush();
321: pw.close();
322: }
323:
324: /*
325: * (non-Javadoc)
326: *
327: * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
328: * javax.servlet.http.HttpServletResponse)
329: */
330: @Override
331: protected void doPost(HttpServletRequest request,
332: HttpServletResponse response) throws ServletException,
333: IOException {
334: this .doService(request, response);
335: }
336:
337: /**
338: * @see javax.servlet.GenericServlet#init()
339: */
340: @Override
341: public void init() throws ServletException {
342: super .init();
343:
344: LOG.logDebug("Logger for " + this .getClass().getName()
345: + " initialized.");
346:
347: SERVICE_FACTORIES_MAPPINGS.put(CSWHandler.class,
348: "org.deegree.ogcwebservices.csw.CSWFactory");
349: SERVICE_FACTORIES_MAPPINGS.put(WFSHandler.class,
350: "org.deegree.ogcwebservices.wfs.WFServiceFactory");
351: SERVICE_FACTORIES_MAPPINGS.put(WCSHandler.class,
352: "org.deegree.ogcwebservices.wcs.WCServiceFactory");
353: SERVICE_FACTORIES_MAPPINGS.put(WMSHandler.class,
354: "org.deegree.ogcwebservices.wms.WMServiceFactory");
355: SERVICE_FACTORIES_MAPPINGS.put(SOSHandler.class,
356: "org.deegree.ogcwebservices.sos.SOServiceFactory");
357: SERVICE_FACTORIES_MAPPINGS.put(WPVSHandler.class,
358: "org.deegree.ogcwebservices.wpvs.WPVServiceFactory");
359: SERVICE_FACTORIES_MAPPINGS.put(WMPSHandler.class,
360: "org.deegree.ogcwebservices.wmps.WMPServiceFactory");
361: SERVICE_FACTORIES_MAPPINGS.put(WPSHandler.class,
362: "org.deegree.ogcwebservices.wps.WPServiceFactory");
363: SERVICE_FACTORIES_MAPPINGS
364: .put(WASSHandler.class,
365: "org.deegree.ogcwebservices.wass.common.WASServiceFactory");
366: SERVICE_FACTORIES_MAPPINGS.put(WCTSHandler.class,
367: "org.deegree.ogcwebservices.wcts.WCTServiceFactory");
368:
369: LOG
370: .logInfo("-------------------------------------------------------------------------------");
371: LOG.logInfo("Starting deegree version " + Version.getVersion());
372: LOG.logInfo("- context : "
373: + this .getServletContext().getServletContextName());
374: LOG.logInfo("- real path : "
375: + this .getServletContext().getRealPath("/"));
376: LOG.logInfo("- java version : "
377: + System.getProperty("java.version") + "");
378: LOG.logInfo("- system charset : "
379: + CharsetUtils.getSystemCharset());
380: LOG.logInfo("- default charset: " + Charset.defaultCharset());
381: LOG.logInfo("- server info : "
382: + this .getServletContext().getServerInfo());
383: try {
384: LOG.logInfo("- ip : "
385: + InetAddress.getLocalHost().getHostAddress());
386: LOG.logInfo("- host name : "
387: + InetAddress.getLocalHost().getHostName());
388: LOG
389: .logInfo("- domain name : "
390: + InetAddress.getLocalHost()
391: .getCanonicalHostName());
392: } catch (Exception e) {
393: LOG.logError(e.getMessage(), e);
394: }
395: LOG
396: .logInfo("-------------------------------------------------------------------------------");
397: this .initServices(getServletContext());
398: LOG
399: .logInfo("-------------------------------------------------------------------------------");
400: String tmpServiceList = this .getServiceList();
401: if (tmpServiceList != null
402: && !("".equals(tmpServiceList.trim()))) {
403: LOG.logInfo("Initialized successfully (context '"
404: + this .getServletContext().getServletContextName()
405: + "'):");
406: String[] tmpServices = tmpServiceList.split(",");
407: for (String service : tmpServices) {
408: LOG.logInfo("- " + service);
409: }
410: } else {
411: LOG
412: .logError("An Error occured while initializing context '"
413: + this .getServletContext()
414: .getServletContextName()
415: + "', no services are available.");
416: }
417:
418: LOG
419: .logInfo("-------------------------------------------------------------------------------");
420: // Sets the attributes for tomcat -> application.getAttribute(); in jsp sites
421: this .getServletContext().setAttribute("deegree_ogc_services",
422: this .getServiceList());
423: }
424:
425: private void initServices(ServletContext context)
426: throws ServletException {
427:
428: // get list of OGC services
429: String serviceList = this .getRequiredInitParameter(SERVICE);
430:
431: String[] serviceNames = StringTools.toArray(serviceList, ",",
432: false);
433:
434: ServiceLookup lookup = ServiceLookup.getInstance();
435: for (int i = 0; i < serviceNames.length; i++) {
436: LOG.logInfo(StringTools.concat(100, "---- Initializing ",
437: serviceNames[i].toUpperCase(), " ----"));
438: try {
439: String className = this
440: .getRequiredInitParameter(serviceNames[i]
441: + HANDLER_CLASS);
442: Class<?> handlerClzz = Class.forName(className);
443:
444: // initialize each service factory
445: String s = this
446: .getRequiredInitParameter(serviceNames[i]
447: + HANDLER_CONF);
448: URL serviceConfigurationURL = WebappResourceResolver
449: .resolveFileLocation(s, context, LOG);
450:
451: // set configuration
452: LOG.logInfo(StringTools.concat(300,
453: "Reading configuration for ", serviceNames[i]
454: .toUpperCase(), " from URL: '",
455: serviceConfigurationURL, "'."));
456:
457: String factoryClassName = SERVICE_FACTORIES_MAPPINGS
458: .get(handlerClzz);
459:
460: Class<?> factory = Class.forName(factoryClassName);
461: Method method = factory.getMethod("setConfiguration",
462: new Class[] { URL.class });
463: method.invoke(factory,
464: new Object[] { serviceConfigurationURL });
465:
466: // put handler to available service list
467: lookup.addService(serviceNames[i].toUpperCase(),
468: handlerClzz);
469:
470: LOG.logInfo(StringTools.concat(300, serviceNames[i]
471: .toUpperCase(), " successfully initialized."));
472: } catch (ServletException e) {
473: LOG.logError(e.getMessage(), e);
474: } catch (InvocationTargetException e) {
475: e.getTargetException().printStackTrace();
476: LOG.logError(this .produceMessage(ERR_MSG,
477: new Object[] { serviceNames[i] }), e);
478: } catch (Exception e) {
479: LOG.logError("Can't initialize OGC service:"
480: + serviceNames[i], e);
481: }
482: }
483: }
484:
485: private String getRequiredInitParameter(String name)
486: throws ServletException {
487: String paramValue = getInitParameter(name);
488: if (paramValue == null) {
489:
490: String msg = "Required init parameter '" + name
491: + "' missing in web.xml";
492: LOG.logError(msg);
493: throw new ServletException(msg);
494: }
495: return paramValue;
496: }
497:
498: /**
499: * @return the services, separated by ","
500: */
501: private String getServiceList() {
502:
503: StringBuffer buf = new StringBuffer();
504: ServiceLookup lookup = ServiceLookup.getInstance();
505: for (Iterator<?> iter = lookup.getIterator(); iter.hasNext();) {
506: String serviceName = (String) iter.next();
507: buf.append(serviceName);
508: if (iter.hasNext()) {
509: buf.append(',');
510: }
511: }
512: return buf.toString();
513: }
514:
515: /**
516: * Formats the provided string and the args array into a String using MessageFormat.
517: *
518: * @param pattern
519: * @param args
520: * @return the message to present the client.
521: */
522: private String produceMessage(String pattern, Object[] args) {
523: return new MessageFormat(pattern).format(args);
524: }
525:
526: /**
527: * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
528: */
529: public void ctDestroyed() {
530: LOG.logInfo("Stopping context: ");
531:
532: WMSConfigurationDocument.resetCapabilitiesCache();
533: WMSConfigurationDocument_1_3_0.resetCapabilitiesCache();
534: WMPSConfigurationDocument.resetCapabilitiesCache();
535:
536: ServiceLookup lookup = ServiceLookup.getInstance();
537: for (Iterator<?> iter = lookup.getIterator(); iter.hasNext();) {
538: String serviceName = (String) iter.next();
539: LOG.logInfo("Stopping service " + serviceName);
540:
541: try {
542: String s = SERVICE_FACTORIES_MAPPINGS.get(lookup
543: .getService(serviceName));
544: Class<?> clzz = Class.forName(s);
545: // TODO stop and reset all service instances
546: Method[] methods = clzz.getMethods();
547: for (int j = 0; j < methods.length; j++) {
548: if (methods[j].getName().equals("reset")) {
549: Object[] args = new Object[0];
550: methods[j].invoke(clzz.newInstance(), args);
551: }
552: }
553: } catch (Exception e) {
554: LOG.logError(e.getMessage(), e);
555: }
556: }
557: }
558:
559: @Override
560: public void destroy() {
561: super.destroy();
562: }
563: }
|