001: //=============================================================================
002: //=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
003: //=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
004: //=== and United Nations Environment Programme (UNEP)
005: //===
006: //=== This program is free software; you can redistribute it and/or modify
007: //=== it under the terms of the GNU General Public License as published by
008: //=== the Free Software Foundation; either version 2 of the License, or (at
009: //=== your option) any later version.
010: //===
011: //=== This program is distributed in the hope that it will be useful, but
012: //=== WITHOUT ANY WARRANTY; without even the implied warranty of
013: //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: //=== General Public License for more details.
015: //===
016: //=== You should have received a copy of the GNU General Public License
017: //=== along with this program; if not, write to the Free Software
018: //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
019: //===
020: //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
021: //=== Rome - Italy. email: geonetwork@osgeo.org
022: //==============================================================================
023:
024: package org.fao.geonet.kernel.csw;
025:
026: import java.io.File;
027: import java.io.IOException;
028: import java.io.StringReader;
029: import java.util.HashMap;
030: import java.util.List;
031: import java.util.Map;
032: import javax.xml.XMLConstants;
033: import javax.xml.parsers.DocumentBuilder;
034: import javax.xml.parsers.DocumentBuilderFactory;
035: import javax.xml.transform.Source;
036: import javax.xml.transform.dom.DOMSource;
037: import javax.xml.transform.stream.StreamSource;
038: import javax.xml.validation.Schema;
039: import javax.xml.validation.SchemaFactory;
040: import javax.xml.validation.Validator;
041: import jeeves.server.context.ServiceContext;
042: import jeeves.server.sources.ServiceRequest.InputMethod;
043: import jeeves.server.sources.ServiceRequest.OutputMethod;
044: import jeeves.utils.SOAPUtil;
045: import jeeves.utils.Util;
046: import jeeves.utils.Xml;
047: import org.fao.geonet.csw.common.exceptions.CatalogException;
048: import org.fao.geonet.csw.common.exceptions.MissingParameterValueEx;
049: import org.fao.geonet.csw.common.exceptions.NoApplicableCodeEx;
050: import org.fao.geonet.csw.common.exceptions.OperationNotSupportedEx;
051: import org.fao.geonet.kernel.csw.services.DescribeRecord;
052: import org.fao.geonet.kernel.csw.services.GetCapabilities;
053: import org.fao.geonet.kernel.csw.services.GetDomain;
054: import org.fao.geonet.kernel.csw.services.GetRecordById;
055: import org.fao.geonet.kernel.csw.services.GetRecords;
056: import org.fao.geonet.kernel.csw.services.Harvest;
057: import org.fao.geonet.kernel.csw.services.Transaction;
058: import org.jdom.Element;
059: import org.w3c.dom.Document;
060: import org.xml.sax.SAXException;
061:
062: import static org.fao.geonet.csw.common.Csw.*;
063:
064: //=============================================================================
065:
066: public class CatalogDispatcher {
067: private HashMap<String, CatalogService> hmServices = new HashMap<String, CatalogService>();
068:
069: //---------------------------------------------------------------------------
070: //---
071: //--- Constructor
072: //---
073: //---------------------------------------------------------------------------
074:
075: public CatalogDispatcher() {
076: register(new DescribeRecord());
077: register(new GetCapabilities());
078: register(new GetDomain());
079: register(new GetRecordById());
080: register(new GetRecords());
081: register(new Harvest());
082: register(new Transaction());
083: }
084:
085: //---------------------------------------------------------------------------
086:
087: private void register(CatalogService s) {
088: hmServices.put(s.getName(), s);
089: }
090:
091: //---------------------------------------------------------------------------
092: //---
093: //--- API methods
094: //---
095: //---------------------------------------------------------------------------
096:
097: public Element dispatch(Element request, ServiceContext context) {
098: context.info("Received:\n" + Xml.getString(request));
099:
100: InputMethod im = context.getInputMethod();
101: OutputMethod om = context.getOutputMethod();
102:
103: boolean inSOAP = (im == InputMethod.SOAP);
104: boolean outSOAP = (inSOAP || om == OutputMethod.SOAP);
105:
106: CatalogException exc;
107:
108: try {
109: if (inSOAP)
110: request = SOAPUtil.unembed(request);
111:
112: Element response = dispatchI(request, context);
113:
114: if (outSOAP)
115: response = SOAPUtil.embed(response);
116:
117: // validateResponse(context, response);
118:
119: return response;
120: }
121:
122: catch (CatalogException e) {
123: exc = e;
124: }
125:
126: catch (Exception e) {
127: context.info("Exception stack trace : \n"
128: + Util.getStackTrace(e));
129: exc = new NoApplicableCodeEx(e.toString());
130: }
131:
132: Element response = CatalogException.marshal(exc);
133: boolean sender = (exc instanceof NoApplicableCodeEx);
134:
135: if (outSOAP)
136: return SOAPUtil.embedExc(response, sender, exc.getCode(),
137: exc.toString());
138:
139: //TODO: need to set the status code
140:
141: return response;
142: }
143:
144: //---------------------------------------------------------------------------
145: //---
146: //--- Private method
147: //---
148: //---------------------------------------------------------------------------
149:
150: private Element dispatchI(Element request, ServiceContext context)
151: throws CatalogException {
152: InputMethod im = context.getInputMethod();
153:
154: if (im == InputMethod.XML || im == InputMethod.SOAP) {
155: String operation = request.getName();
156:
157: CatalogService cs = hmServices.get(operation);
158:
159: if (cs == null)
160: throw new OperationNotSupportedEx(operation);
161:
162: context.info("Dispatching operation : " + operation);
163:
164: return cs.execute(request, context);
165: }
166:
167: else //--- GET or POST/www-encoded request
168: {
169: Map<String, String> params = extractParams(request);
170:
171: String operation = params.get("request");
172:
173: if (operation == null)
174: throw new MissingParameterValueEx("request");
175:
176: CatalogService cs = hmServices.get(operation);
177:
178: if (cs == null)
179: throw new OperationNotSupportedEx(operation);
180:
181: request = cs.adaptGetRequest(params);
182:
183: context.debug("Adapted GET request is:\n"
184: + Xml.getString(request));
185: context.info("Dispatching operation : " + operation);
186:
187: return cs.execute(request, context);
188: }
189: }
190:
191: //---------------------------------------------------------------------------
192:
193: private Map<String, String> extractParams(Element request) {
194: HashMap<String, String> hm = new HashMap<String, String>();
195:
196: List params = request.getChildren();
197:
198: for (int i = 0; i < params.size(); i++) {
199: Element param = (Element) params.get(i);
200:
201: String name = param.getName().toLowerCase();
202: String value = param.getTextTrim();
203:
204: hm.put(name, value);
205: }
206:
207: return hm;
208: }
209:
210: //---------------------------------------------------------------------------
211:
212: private void validateResponse(ServiceContext context,
213: Element response) {
214: // String xml = Xml.getString(new org.jdom.Document(response));
215: // String path = context.getAppPath() +VALIDATE_PATH;
216: //
217: // byte
218: //
219: // DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
220: // Document doc = parser.parse(new StringReader(xml));
221: //
222: // // create a SchemaFactory capable of understanding WXS schemas
223: // SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
224: //
225: // // load a WXS schema, represented by a Schema instance
226: // Source schemaFile = new StreamSource(new File(path));
227: // Schema schema = factory.newSchema(schemaFile);
228: //
229: // // create a Validator instance, which can be used to validate an instance document
230: // Validator validator = schema.newValidator();
231: //
232: // // validate the DOM tree
233: //
234: // try
235: // {
236: // validator.validate(new DOMSource(doc));
237: // }
238: // catch (SAXException e)
239: // {
240: // // instance document is invalid!
241: // }
242: // catch (IOException e)
243: // {
244: // }
245: }
246:
247: //---------------------------------------------------------------------------
248:
249: private final static String VALIDATE_PATH = "web/xml/validation/csw/2.0.1/CSW-discovery.xsd";
250: }
251:
252: //=============================================================================
|