001: /*---------------- FILE HEADER ------------------------------------------
002: This file is part of adv ebrim project.
003: Copyright (C) 2007 by:
004:
005: Andreas Poth
006: lat/lon GmbH
007: Aennchenstr. 19
008: 53177 Bonn
009: Germany
010: E-Mail: poth@lat-lon.de
011:
012: ---------------------------------------------------------------------------*/
013:
014: package de.latlon.adv;
015:
016: import java.io.File;
017: import java.io.IOException;
018: import java.io.InputStream;
019: import java.io.OutputStream;
020: import java.net.MalformedURLException;
021: import java.util.Enumeration;
022: import java.util.HashMap;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Set;
026:
027: import javax.activation.DataSource;
028: import javax.mail.internet.ContentDisposition;
029: import javax.mail.internet.MimeBodyPart;
030: import javax.mail.internet.MimeMultipart;
031: import javax.mail.internet.MimeUtility;
032: import javax.servlet.ServletException;
033: import javax.servlet.http.HttpServletRequest;
034: import javax.servlet.http.HttpServletResponse;
035:
036: import org.apache.commons.httpclient.HttpClient;
037: import org.apache.commons.httpclient.HttpException;
038: import org.apache.commons.httpclient.methods.PostMethod;
039: import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
040: import org.apache.commons.httpclient.methods.multipart.Part;
041: import org.apache.commons.httpclient.methods.multipart.StringPart;
042: import org.deegree.enterprise.ServiceException;
043: import org.deegree.enterprise.servlet.OGCServletController;
044: import org.deegree.enterprise.servlet.ServiceLookup;
045: import org.deegree.framework.log.ILogger;
046: import org.deegree.framework.log.LoggerFactory;
047: import org.deegree.framework.util.CharsetUtils;
048: import org.deegree.framework.util.StringTools;
049: import org.deegree.framework.xml.XMLFragment;
050: import org.deegree.ogcbase.ExceptionCode;
051: import org.deegree.ogcwebservices.ExceptionReport;
052: import org.deegree.ogcwebservices.InvalidParameterValueException;
053: import org.deegree.ogcwebservices.OGCRequestFactory;
054: import org.deegree.ogcwebservices.OGCWebServiceException;
055: import org.deegree.ogcwebservices.OGCWebServiceRequest;
056: import org.deegree.ogcwebservices.csw.CSWExceptionCode;
057: import org.deegree.ogcwebservices.csw.CSWFactory;
058: import org.deegree.ogcwebservices.csw.CatalogueService;
059: import org.deegree.ogcwebservices.csw.capabilities.CatalogueCapabilities;
060: import org.deegree.ogcwebservices.csw.capabilities.CatalogueGetCapabilities;
061: import org.deegree.ogcwebservices.csw.discovery.DescribeRecord;
062: import org.deegree.ogcwebservices.csw.discovery.GetDomain;
063: import org.deegree.ogcwebservices.csw.discovery.GetRecordById;
064: import org.deegree.ogcwebservices.csw.discovery.GetRecords;
065: import org.deegree.ogcwebservices.csw.discovery.GetRepositoryItem;
066: import org.deegree.ogcwebservices.csw.manager.Harvest;
067: import org.deegree.ogcwebservices.csw.manager.Insert;
068: import org.deegree.ogcwebservices.csw.manager.Operation;
069: import org.deegree.ogcwebservices.csw.manager.Transaction;
070: import org.deegree.owscommon.XMLFactory;
071: import org.w3c.dom.Element;
072: import org.xml.sax.SAXException;
073:
074: /**
075: * Simple servlet facade for receiving csw/ebrim request and sending fake responses. This is not ususable anymore.
076: *
077: *
078: * @version $Revision: 1.6 $
079: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
080: * @author last edited by: $Author: bezema $
081: *
082: * @version 1.0. $Revision: 1.6 $, $Date: 2007-06-14 12:07:04 $
083: *
084: * @since 2.0
085: */
086: public class RIMServletHandler extends OGCServletController {
087:
088: /**
089: *
090: */
091: private static final long serialVersionUID = -4642387506442697837L;
092:
093: private final ILogger LOG = LoggerFactory
094: .getLogger(RIMServletHandler.class);
095:
096: private XMLFragment getRecordsByIdResponse;
097:
098: private XMLFragment getRecordsResponse;
099:
100: private XMLFragment transactionResponse;
101:
102: private XMLFragment getRepositoryItemResponse;
103:
104: /**
105: * A simple main, to check the multiparts sending (does not actually work :-)
106: * @param args not used
107: */
108: public static void main(String[] args) {
109:
110: // File transaction = new File( );
111: XMLFragment transaction = null;
112: XMLFragment extObj1 = null;
113: XMLFragment extObj2 = null;
114: try {
115: transaction = new XMLFragment(new File(
116: "resources/requests/insert1.xml"));
117: extObj1 = new XMLFragment(new File(
118: "resources/requests/urn_adv_crs_ETRS89_UTM32.xml"));
119: extObj2 = new XMLFragment(
120: new File(
121: "resources/requests/urn_adv_coordinateOperation_UTM32.xml"));
122: } catch (MalformedURLException e) {
123: // TODO Auto-generated catch block
124: e.printStackTrace();
125: } catch (IOException e) {
126: // TODO Auto-generated catch block
127: e.printStackTrace();
128: } catch (SAXException e) {
129: // TODO Auto-generated catch block
130: e.printStackTrace();
131: }
132:
133: PostMethod filePost = new PostMethod(
134: "http://localhost:8081/deegree/services");
135:
136: StringPart trans = new StringPart("Transaction", transaction
137: .getAsPrettyString(), "UTF-8");
138: trans.setContentType("application/xml");
139: trans.setName("Transaction");
140: System.out.println(transaction.getAsPrettyString());
141:
142: StringPart obj1 = new StringPart("urn:adv:crs:ETRS89_UTM32",
143: extObj1.getAsPrettyString(), "UTF-8");
144: obj1.setContentType("application/xml");
145: obj1.setName("urn:adv:crs:ETRS89_UTM32");
146:
147: StringPart obj2 = new StringPart(
148: "urn:adv:coordinateOperation:UTM32", extObj2
149: .getAsPrettyString(), "UTF-8");
150: obj2.setContentType("application/xml");
151: obj2.setName("urn:adv:coordinateOperation:UTM32");
152:
153: Part[] parts = { trans, obj1, obj2 };
154: filePost.setRequestEntity(new MultipartRequestEntity(parts,
155: filePost.getParams()));
156: HttpClient client = new HttpClient();
157: try {
158: int status = client.executeMethod(filePost);
159: System.out.println("status: " + status);
160: } catch (HttpException e) {
161: // TODO Auto-generated catch block
162: e.printStackTrace();
163: } catch (IOException e) {
164: // TODO Auto-generated catch block
165: e.printStackTrace();
166: }
167: }
168:
169: @Override
170: public void init() throws ServletException {
171: super .init();
172: }
173:
174: /**
175: *
176: *
177: * @param request
178: * @param response
179: * @throws ServiceException
180: * @TODO refactor and optimize code for initializing handler
181: */
182: @Override
183: public void doService(HttpServletRequest request,
184: HttpServletResponse response) throws ServiceException {
185: if (response.isCommitted()) {
186: LOG
187: .logWarning("The response object is already committed, cannot proceed!");
188: return;
189: }
190:
191: long startTime = System.currentTimeMillis();
192: address = request.getRequestURL().toString();
193:
194: try {
195: OGCWebServiceRequest ogcRequest = OGCRequestFactory
196: .create(request);
197:
198: LOG.logInfo(StringTools.concat(500, "Handling request '",
199: ogcRequest.getId(), "' from '", request
200: .getRemoteAddr(), "' to service: '",
201: ogcRequest.getServiceName(), "'"));
202:
203: // get service from request
204: String service = ogcRequest.getServiceName().toUpperCase();
205:
206: // get handler instance
207: ServiceLookup.getInstance().getHandler(service);
208:
209: // dispatch request to fake csw do service method
210: LOG.logDebug("Performing request: " + request.toString());
211: doCSWService(ogcRequest, response);
212: } catch (OGCWebServiceException e) {
213: e.printStackTrace();
214: LOG.logError(e.getMessage(), e);
215: sendException(response, e);
216: }
217: if (LOG.getLevel() == ILogger.LOG_DEBUG) {
218: LOG.logDebug("OGCServletController: request performed in "
219: + Long.toString(System.currentTimeMillis()
220: - startTime) + " milliseconds.");
221: }
222: }
223:
224: private void doCSWService(OGCWebServiceRequest request,
225: HttpServletResponse response) throws OGCWebServiceException {
226: File requestBaseDir = new File(getServletContext().getRealPath(
227: "/WEB-INF/conf/csw/"));
228: LOG.logDebug("basedir: " + requestBaseDir.toString());
229:
230: try {
231: if (request instanceof DescribeRecord) {
232: sendException(
233: response,
234: new OGCWebServiceException(
235: "Operation DescribeRecord is not implement yet",
236: ExceptionCode.OPERATIONNOTSUPPORTED));
237: } else if (request instanceof GetDomain) {
238: sendException(response, new OGCWebServiceException(
239: "Operation GetDomain is not implement yet",
240: ExceptionCode.OPERATIONNOTSUPPORTED));
241: } else if (request instanceof GetRecords) {
242: getRecordsResponse = new XMLFragment(new File(
243: requestBaseDir + "/getrecords_response1.xml")
244: .toURI().toURL());
245: sendFakeResponse(response, getRecordsResponse);
246: } else if (request instanceof GetRecordById) {
247: getRecordsByIdResponse = new XMLFragment(
248: new File(requestBaseDir
249: + "/getrecordbyid_response1.xml")
250: .toURI().toURL());
251:
252: sendFakeResponse(response, getRecordsByIdResponse);
253: } else if (request instanceof GetRepositoryItem) {
254: getRepositoryItemResponse = new XMLFragment(new File(
255: requestBaseDir
256: + "/getrepositoryitem_response1.xml")
257: .toURI().toURL());
258: sendFakeResponse(response, getRepositoryItemResponse);
259: } else if (request instanceof Transaction) {
260: transactionResponse = new XMLFragment(new File(
261: requestBaseDir + "/transaction_response1.xml")
262: .toURI().toURL());
263:
264: sendFakeResponse(response, transactionResponse);
265: } else if (request instanceof Harvest) {
266: sendException(response, new OGCWebServiceException(
267: "Operation Harvest is not implement yet",
268: ExceptionCode.OPERATIONNOTSUPPORTED));
269: } else if (request instanceof CatalogueGetCapabilities) {
270: LOG.logDebug("GetCapabilities for version:"
271: + request.getVersion(), request);
272: String[] acceptVersions = ((CatalogueGetCapabilities) request)
273: .getAcceptVersions();
274: boolean versionOk = false;
275: if (acceptVersions == null
276: || acceptVersions.length == 0) {
277: versionOk = true;
278: } else {
279: for (int i = 0; i < acceptVersions.length; i++) {
280: if ("2.0.0".equals(acceptVersions[i])
281: || "2.0.1".equals(acceptVersions[i])
282: || "2.0.2".equals(acceptVersions[i])) {
283: versionOk = true;
284: break;
285: }
286: }
287: }
288: if (versionOk) {
289: CatalogueService service = CSWFactory.getService();
290: CatalogueCapabilities requestResponse = (CatalogueCapabilities) service
291: .doService(request);
292: sendCapabilities(response,
293: (CatalogueGetCapabilities) request,
294: requestResponse);
295: } else {
296: throw new InvalidParameterValueException(
297: "Unsupported version requested, only version 2.0.0 is supported.");
298: }
299: } else {
300: sendException(response, new OGCWebServiceException(
301: "Invalid request type: '"
302: + request.getClass().getName() + "'."));
303:
304: }
305: } catch (MalformedURLException e) {
306: e.printStackTrace();
307: sendException(response, new OGCWebServiceException(e
308: .getMessage()));
309: } catch (IOException e) {
310: e.printStackTrace();
311: sendException(response, new OGCWebServiceException(e
312: .getMessage()));
313: } catch (SAXException e) {
314: e.printStackTrace();
315: sendException(response, new OGCWebServiceException(e
316: .getMessage()));
317: }
318: }
319:
320: /**
321: * Sends the passed <tt>CatalogCapabilities</tt> to the http client.
322: *
323: * @param response
324: * http connection to the client
325: * @param capabilities
326: * object to send
327: */
328: private void sendCapabilities(HttpServletResponse response,
329: CatalogueGetCapabilities getCapabilities,
330: CatalogueCapabilities capabilities) throws IOException {
331:
332: boolean xmlOk = false;
333: String[] formats = getCapabilities.getAcceptFormats();
334: if (formats == null || formats.length == 0) {
335: xmlOk = true;
336: } else {
337: for (int i = 0; i < formats.length; i++) {
338: if (formats[i].equals("text/xml")) {
339: xmlOk = true;
340: break;
341: }
342: }
343: }
344: if (!xmlOk) {
345: ExceptionCode code = ExceptionCode.INVALIDPARAMETERVALUE;
346: InvalidParameterValueException e = new InvalidParameterValueException(
347: this .getClass().getName(),
348: "OutputFormat must be 'text/xml'.", code);
349: sendException(response, e);
350: } else {
351:
352: XMLFragment doc = org.deegree.ogcwebservices.csw.XMLFactory
353: .export(capabilities, getCapabilities.getSections());
354: response.setContentType("text/xml; charset="
355: + CharsetUtils.getSystemCharset());
356: OutputStream os = response.getOutputStream();
357: doc.write(os);
358: os.close();
359: }
360: }
361:
362: @Override
363: public void doGet(HttpServletRequest request,
364: HttpServletResponse response) throws IOException,
365: ServletException {
366:
367: LOG.logDebug("query string ", request.getQueryString());
368: try {
369: this .doService(request, response);
370: } catch (ServiceException e) {
371: LOG.logError(e.getMessage(), e);
372: this .sendException(response, new OGCWebServiceException(e
373: .getLocalizedMessage()));
374: }
375: }
376:
377: @Override
378: public void doPost(HttpServletRequest req, HttpServletResponse res)
379: throws IOException, ServletException {
380: try {
381: if (req.getContentType().contains("multipart/form-data")) {
382: Transaction trans = handleMultiparts(req, res);
383: if (trans != null) {
384: sendFakeResponse(res, transactionResponse);
385: }
386: } else {
387: this .doService(req, res);
388: }
389: } catch (ServiceException e) {
390: LOG.logError(e.getMessage(), e);
391: e.printStackTrace();
392: this .sendException(res, new OGCWebServiceException(e
393: .getLocalizedMessage()));
394: }
395:
396: }
397:
398: private Transaction handleMultiparts(HttpServletRequest request,
399: HttpServletResponse response) {
400: Transaction trans = null;
401: try {
402: StreamDataSource sds = new StreamDataSource(request);
403: MimeMultipart multi = new MimeMultipart(sds);
404: Map<String, Operation> extrinsObjects = new HashMap<String, Operation>();
405: System.out.println("multi: " + multi.getCount());
406: for (int i = 0; i < multi.getCount(); i++) {
407: MimeBodyPart content = (MimeBodyPart) multi
408: .getBodyPart(i);
409: System.out.println("id: " + content.getContentID());
410: System.out.println("type: " + content.getContentType());
411: String contentType = content.getContentType();
412: if (!(contentType.contains("application/xml") || contentType
413: .contains("text/xml"))) {
414: throw new OGCWebServiceException(
415: "Other than xml-encoded data can not be handled in the multiparts",
416: CSWExceptionCode.WRS_INVALIDREQUEST);
417: }
418: Enumeration en = content.getAllHeaderLines();
419: while (en.hasMoreElements()) {
420: System.out.println((String) en.nextElement());
421: }
422: String[] names = content
423: .getHeader("Content-Disposition");
424: String nameID = null;
425: if (names != null) {
426: for (String name : names) {
427: ContentDisposition cd = new ContentDisposition(
428: name);
429: String nm = cd.getParameter("name");
430: if (nm != null) {
431: nameID = nm;
432: break;
433: }
434: }
435: }
436:
437: if (nameID == null) {
438: nameID = content.getContentID();
439: if (nameID == null) {
440: throw new OGCWebServiceException(
441: "Exactly one 'name' parameter must be set in the header.",
442: CSWExceptionCode.WRS_INVALIDREQUEST);
443: }
444: }
445: System.out.println("name:" + nameID);
446: if ("Transaction".equalsIgnoreCase(nameID)) {
447: XMLFragment doc = new XMLFragment();
448: System.out.println("lineCount: "
449: + content.getLineCount());
450:
451: System.out.println("string: " + content.toString());
452:
453: System.out.println("encoding: "
454: + content.getEncoding());
455: InputStream contentIS = null;
456: if (!"UTF-8"
457: .equalsIgnoreCase(content.getEncoding())) {
458: contentIS = MimeUtility.decode(content
459: .getInputStream(), content
460: .getEncoding());
461: } else {
462: contentIS = content.getInputStream();
463: }
464: doc.load(contentIS, XMLFragment.DEFAULT_URL);
465: // create the transaction
466: trans = Transaction.create("0", doc
467: .getRootElement());
468: List<Operation> ops = trans.getOperations();
469: // find all the ids which were referenced by the transaction.
470: for (Operation op : ops) {
471: if ("Insert".equalsIgnoreCase(op.getName())) {
472: Map<String, Element> objects = ((Insert) op)
473: .getExtrinsicObjects();
474: Set<String> keys = objects.keySet();
475: // set the keys to the operations they were referenced in.
476: for (String key : keys) {
477: if (extrinsObjects.containsKey(key)) {
478: throw new OGCWebServiceException(
479: "The following key is not unique, "
480: + key
481: + ", the transaction therefore failed.",
482: CSWExceptionCode.WRS_INVALIDREQUEST);
483: }
484: extrinsObjects.put(key, op);
485: }
486: }
487: }
488: } else {
489: if (extrinsObjects.size() > 0) {
490: if (extrinsObjects.containsKey(nameID)) {
491: // handleRIMObject( content );
492: // todo handle the object.
493: }
494: } else {
495: throw new OGCWebServiceException(
496: "Some parts remain, but there are no more referenced ids, something is wrong with the transaction",
497: CSWExceptionCode.WRS_INVALIDREQUEST);
498: }
499: }
500: }
501: } catch (OGCWebServiceException e) {
502: e.printStackTrace();
503: sendException(response, e);
504: } catch (Exception e) {
505: e.printStackTrace();
506: sendException(response, new OGCWebServiceException(e
507: .getMessage(),
508: CSWExceptionCode.WRS_TRANSACTIONFAILED));
509: }
510:
511: // finished so lets give back the transaction as a result.
512: return trans;
513: }
514:
515: /**
516: * Sends the passed <tt>OGCWebServiceException</tt> to the calling client.
517: *
518: * @param response
519: * @param e
520: */
521: private void sendException(HttpServletResponse response,
522: OGCWebServiceException e) {
523: LOG.logInfo("Sending OGCWebServiceException to client.");
524: ExceptionReport report = new ExceptionReport(
525: new OGCWebServiceException[] { e });
526:
527: try {
528: response.setContentType("application/vnd.ogc.se_xml");
529: XMLFragment doc = XMLFactory.export(report);
530: OutputStream os = response.getOutputStream();
531: doc.write(os);
532: os.close();
533: } catch (Exception ex) {
534: LOG.logError("ERROR: " + ex.getMessage(), ex);
535: }
536: }
537:
538: /**
539: *
540: * @param response
541: * @param getRecordResponse
542: * @throws IOException
543: * @throws SAXException
544: */
545: private void sendFakeResponse(HttpServletResponse response,
546: XMLFragment docResponse) throws IOException {
547: response.setContentType("text/xml; charset=UTF-8");
548: OutputStream os = response.getOutputStream();
549:
550: docResponse.write(os);
551: os.close();
552: }
553:
554: /**
555: * This class maps the request stream to the content parser that is able to pick files from it.
556: */
557: private class StreamDataSource implements DataSource {
558: private HttpServletRequest m_req;
559:
560: /**
561: * @param req
562: */
563: public StreamDataSource(HttpServletRequest req) {
564: m_req = req;
565: }
566:
567: /**
568: * @return the content type for the request stream.
569: */
570: public String getContentType() {
571: return m_req.getContentType();
572: }
573:
574: /**
575: * @return a stream from the request.
576: */
577: public InputStream getInputStream() throws IOException {
578: return m_req.getInputStream();
579: }
580:
581: /**
582: * Maps output to System.out. Do something more sensible here...
583: */
584: public OutputStream getOutputStream() {
585: return System.out;
586: }
587:
588: /*
589: * (non-Javadoc)
590: *
591: * @see javax.activation.DataSource#getName()
592: */
593: public String getName() {
594: // TODO Auto-generated method stub
595: return null;
596: }
597:
598: }
599:
600: }
|