changeset 380:9798e4d83681

Services are now able to return more than just XML documents. artifacts/trunk@4188 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 03 Apr 2012 11:15:10 +0000
parents 95ff5a25a339
children bed51de8ae58
files ChangeLog artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultService.java artifact-database/src/main/java/de/intevation/artifactdatabase/XMLService.java artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ByteArrayRepresentation.java artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ServiceResource.java artifacts/src/main/java/de/intevation/artifacts/ArtifactDatabase.java artifacts/src/main/java/de/intevation/artifacts/Service.java
diffstat 8 files changed, 196 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Mar 30 07:21:29 2012 +0000
+++ b/ChangeLog	Tue Apr 03 11:15:10 2012 +0000
@@ -1,3 +1,28 @@
+2012-04-04	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	Modified services so that they are now able to return more than just
+	XML documents. Needed if you want to return e.g. a PNG image from a service.
+
+	* artifacts/src/main/java/de/intevation/artifacts/Service.java:
+	  A service now returns a tuple (data, MIME type).
+
+	* artifacts/src/main/java/de/intevation/artifacts/ArtifactDatabase.java,
+	  artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java:
+	  Adjusted calls.
+
+	* artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultService.java:
+	  Returns a DefaultService.Output by default.
+
+	* artifact-database/src/main/java/de/intevation/artifactdatabase/XMLService.java: New.
+	  Convenience sub class if DefaultService to produce XML documents. Old
+	  Services should derive from this class now to main compatibility.
+
+	* artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ServiceResource.java:
+	  Adjusted to handle the new Output tuples.
+
+	* artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ByteArrayRepresentation.java:
+	  New. Wraps a byte array as a Restlet representation.
+
 2012-03-30  Ingo Weinzierl <ingo@intevation.de>
 
 	* artifact-database/src/main/java/de/intevation/artifactdatabase/state/DefaultOutput.java:
--- a/artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java	Fri Mar 30 07:21:29 2012 +0000
+++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java	Tue Apr 03 11:15:10 2012 +0000
@@ -1162,7 +1162,7 @@
         return serviceNamesAndDescription;
     }
 
-    public Document process(
+    public Service.Output process(
         String   serviceName,
         Document input,
         CallMeta callMeta
--- a/artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultService.java	Fri Mar 30 07:21:29 2012 +0000
+++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/DefaultService.java	Tue Apr 03 11:15:10 2012 +0000
@@ -8,8 +8,6 @@
 
 package de.intevation.artifactdatabase;
 
-import de.intevation.artifacts.common.utils.XMLUtils;
-
 import de.intevation.artifacts.CallMeta;
 import de.intevation.artifacts.Service;
 import de.intevation.artifacts.GlobalContext;
@@ -30,14 +28,38 @@
 {
     private static Logger logger = Logger.getLogger(DefaultService.class);
 
+    public static class Output implements Service.Output {
+
+        protected Object data;
+        protected String mimeType;
+
+        public Output() {
+        }
+
+        public Output(Object data, String mimeType) {
+            this.data     = data;
+            this.mimeType = mimeType;
+        }
+
+        @Override
+        public Object getData() {
+            return data;
+        }
+
+        @Override
+        public String getMIMEType() {
+            return mimeType;
+        }
+    } // class Output
+
     @Override
-    public Document process(
+    public Service.Output process(
         Document      data,
         GlobalContext globalContext,
         CallMeta      callMeta
     ) {
         logger.debug("Service.process");
-        return XMLUtils.newDocument();
+        return new Output(new byte[0], "application/octet-stream");
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/XMLService.java	Tue Apr 03 11:15:10 2012 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 by Intevation GmbH
+ *
+ * This program is free software under the LGPL (>=v2.1)
+ * Read the file LGPL.txt coming with the software for details
+ * or visit http://www.gnu.org/licenses/ if it does not exist.
+ */
+
+package de.intevation.artifactdatabase;
+
+import de.intevation.artifacts.CallMeta;
+import de.intevation.artifacts.Service;
+import de.intevation.artifacts.GlobalContext;
+
+import de.intevation.artifacts.common.utils.XMLUtils;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+
+/**
+ * Trivial implementation of an artifact database service. Useful to
+ * be subclassed.
+ *
+ * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
+ */
+public class XMLService
+extends      DefaultService
+{
+    private static Logger logger = Logger.getLogger(XMLService.class);
+
+    @Override
+    public Service.Output process(
+        Document      data,
+        GlobalContext globalContext,
+        CallMeta      callMeta
+    ) {
+        return new Output(
+            processXML(data, globalContext, callMeta),
+            "application/xml");
+    }
+
+    public Document processXML(
+        Document      data,
+        GlobalContext globalContext,
+        CallMeta      callMeta
+    ) {
+        return XMLUtils.newDocument();
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ByteArrayRepresentation.java	Tue Apr 03 11:15:10 2012 +0000
@@ -0,0 +1,65 @@
+package de.intevation.artifactdatabase.rest;
+
+import org.restlet.representation.Representation;
+
+import java.io.Reader;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.Writer;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.ByteArrayInputStream;
+
+import java.nio.ByteBuffer;
+
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+
+import org.restlet.data.MediaType;
+
+public class ByteArrayRepresentation
+extends      Representation
+{
+    protected byte [] data;
+
+    public ByteArrayRepresentation(MediaType mediaType, byte [] data) {
+        super(mediaType);
+        this.data = data;
+    }
+
+    @Override
+    public long getSize() {
+        return data.length;
+    }
+
+    @Override
+    public ReadableByteChannel getChannel() throws IOException {
+        return null;
+    }
+
+    @Override
+    public Reader getReader() throws IOException {
+        return new InputStreamReader(getStream());
+    }
+
+    @Override
+    public InputStream getStream() throws IOException {
+        return new ByteArrayInputStream(data);
+    }
+
+    @Override
+    public void write(Writer writer) throws IOException {
+        writer.append(ByteBuffer.wrap(data).asCharBuffer());
+    }
+
+    @Override
+    public void write(WritableByteChannel writableChannel) throws IOException {
+        writableChannel.write(ByteBuffer.wrap(data));
+    }
+
+    @Override
+    public void write(OutputStream outputStream) throws IOException {
+        outputStream.write(data);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ServiceResource.java	Fri Mar 30 07:21:29 2012 +0000
+++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/rest/ServiceResource.java	Tue Apr 03 11:15:10 2012 +0000
@@ -27,6 +27,8 @@
 
 import org.w3c.dom.Document;
 
+import de.intevation.artifacts.Service;
+
 /**
  * Resource to process incoming XML documents with a given service.
  *
@@ -72,8 +74,7 @@
             .getAttributes().get("database");
 
         try {
-            return new DomRepresentation(
-                MediaType.APPLICATION_XML,
+            return guessRepresentation(
                 db.process(service, inputDocument, getCallMeta()));
         }
         catch (ArtifactDatabaseException adbe) {
@@ -84,5 +85,21 @@
             return new EmptyRepresentation();
         }
     }
+
+    protected static Representation guessRepresentation(Service.Output output) {
+
+        MediaType mediaType = new MediaType(output.getMIMEType());
+        Object    data      = output.getData();
+
+        if (data instanceof Document) {
+            return new DomRepresentation(mediaType, (Document)data);
+        }
+
+        if (data instanceof byte []) {
+            return new ByteArrayRepresentation(mediaType, (byte [])data);
+        }
+
+        return new EmptyRepresentation();
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/de/intevation/artifacts/ArtifactDatabase.java	Fri Mar 30 07:21:29 2012 +0000
+++ b/artifacts/src/main/java/de/intevation/artifacts/ArtifactDatabase.java	Tue Apr 03 11:15:10 2012 +0000
@@ -207,7 +207,7 @@
      * @throws ArtifactDatabaseException Thrown if someting went wrong during
      * the service processing.
      */
-    Document process(String service, Document input, CallMeta callMeta)
+    Service.Output process(String service, Document input, CallMeta callMeta)
         throws ArtifactDatabaseException;
 
     // User API
--- a/artifacts/src/main/java/de/intevation/artifacts/Service.java	Fri Mar 30 07:21:29 2012 +0000
+++ b/artifacts/src/main/java/de/intevation/artifacts/Service.java	Tue Apr 03 11:15:10 2012 +0000
@@ -20,14 +20,20 @@
 public interface Service
 extends          Serializable
 {
+    interface Output {
+        Object getData();
+
+        String getMIMEType();
+    } // interface Output
+
     /**
      * Processes some input XML document
      * @param data The input data
      * @param globalContext The global context of the artifact database.
      * @param callMeta The call meta contex, e.g. preferred languages.
-     * @return The result output XML document.
+     * @return The result.
      */
-    Document process(Document data, GlobalContext globalContext, CallMeta callMeta);
+    Output process(Document data, GlobalContext globalContext, CallMeta callMeta);
 
     /**
      * Setup the concrete processing service. This is done at startup time

http://dive4elements.wald.intevation.org