]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java
@update:79; First end-to-end integration test
[gpl/argeo-slc.git] / runtime / org.argeo.slc.server / src / main / java / org / argeo / slc / server / client / impl / AbstractHttpServicesClient.java
index ba4e584efb242a9bc12d985a9bb4879cf546d798..410e8d9afe029d119425a8f0d565bf35750a1013 100644 (file)
@@ -1,11 +1,18 @@
 package org.argeo.slc.server.client.impl;
 
 import java.io.IOException;
-import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Iterator;
 import java.util.Map;
 
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
 import org.apache.commons.io.IOUtils;
@@ -14,6 +21,7 @@ import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.Condition;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.server.client.HttpServicesClient;
+import org.springframework.oxm.Marshaller;
 import org.springframework.oxm.Unmarshaller;
 import org.springframework.util.Assert;
 
@@ -21,13 +29,22 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        private final static Log log = LogFactory
                        .getLog(AbstractHttpServicesClient.class);
        private Unmarshaller unmarshaller;
+       private Marshaller marshaller;
        private String baseUrl;
+       private String encoding = "UTF-8";
 
        private Long retryPeriod = 1000l;
-       @SuppressWarnings(value = { "unchecked" })
+       private Long defaultTimeout = 30 * 1000l;
+
        public <T> T callService(String path, Map<String, String> parameters) {
+               return callService(path, parameters, null);
+       }
+
+       @SuppressWarnings(value = { "unchecked" })
+       public <T> T callService(String path, Map<String, String> parameters,
+                       Object body) {
                try {
-                       return (T) callServiceLowLevel(path, parameters);
+                       return (T) callServiceLowLevel(path, parameters, body);
                } catch (Exception e) {
                        throw new SlcException("Cannot call service " + path + " on "
                                        + baseUrl, e);
@@ -37,13 +54,16 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        @SuppressWarnings(value = { "unchecked" })
        public <T> T callServiceSafe(String path, Map<String, String> parameters,
                        Condition<T> condition, Long timeout) {
+               if (timeout == null)
+                       timeout = defaultTimeout;
+
                long begin = System.currentTimeMillis();
                try {
                        Object obj = null;
                        long duration = System.currentTimeMillis() - begin;
                        while (duration < timeout) {
                                try {
-                                       obj = callServiceLowLevel(path, parameters);
+                                       obj = callServiceLowLevel(path, parameters, null);
                                } catch (IOException e) {
                                        if (log.isTraceEnabled())
                                                log.trace("Exception when calling service " + path
@@ -83,27 +103,76 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        }
 
        protected Object callServiceLowLevel(String path,
-                       Map<String, String> parameters) throws IOException {
+                       Map<String, String> parameters, Object body) throws IOException {
                Assert.notNull(baseUrl, "base url");
-               InputStream in = null;
+               HttpURLConnection connection = null;
+               Writer writer = null;
+               Reader reader = null;
                try {
-                       URL url = new URL(baseUrl + path);
-                       HttpURLConnection connection = (HttpURLConnection) url
-                                       .openConnection();
-                       if (parameters != null) {
-                               for (String key : parameters.keySet()) {
-                                       connection.addRequestProperty(key, parameters.get(key));
-                               }
+                       URL url = createUrl(path, parameters);
+                       connection = (HttpURLConnection) url.openConnection();
+
+                       if (body != null) {
+                               connection.setRequestMethod("POST");
+                               connection.setDoOutput(true);
+                               connection.setDoInput(true);
+                               connection.setUseCaches(false);
+                               connection.setAllowUserInteraction(false);
+                               connection.setRequestProperty("Content-type",
+                                               "text/xml; charset=" + encoding);
                        }
 
+                       // Establish the connection
                        connection.connect();
 
-                       in = connection.getInputStream();
-                       StreamSource source = new StreamSource(in);
+                       if (body != null) {
+                               writer = new OutputStreamWriter(connection.getOutputStream(),
+                                               encoding);
+                               StreamResult result = new StreamResult(writer);
+                               marshaller.marshal(body, result);
+                               writer.flush();
+                               IOUtils.closeQuietly(writer);
+                       }
+
+                       // Read answer
+                       reader = new InputStreamReader(connection.getInputStream(),
+                                       encoding);
+                       Source source = new StreamSource(reader);
                        Object obj = unmarshaller.unmarshal(source);
                        return obj;
                } finally {
-                       IOUtils.closeQuietly(in);
+                       IOUtils.closeQuietly(reader);
+                       IOUtils.closeQuietly(writer);
+                       if (connection != null) {
+                               connection.disconnect();
+                       }
+               }
+       }
+
+       protected URL createUrl(String service, Map<String, String> parameters) {
+               // URL encoded with UTF-8, as recommended by W3C
+               final String urlEncoding = "UTF-8";
+
+               StringBuffer buf = new StringBuffer(baseUrl + service);
+               try {
+                       if (parameters != null && parameters.size() != 0) {
+                               buf.append('?');
+                               Iterator<String> it = parameters.keySet().iterator();
+                               String key = null;
+                               while (it.hasNext()) {
+                                       if (key != null)
+                                               buf.append('&');
+                                       key = it.next();
+                                       String keyEncoded = URLEncoder.encode(key, urlEncoding);
+                                       String valueEncoded = URLEncoder.encode(
+                                                       parameters.get(key), urlEncoding);
+                                       buf.append(keyEncoded).append('=').append(valueEncoded);
+                               }
+                       }
+
+                       return new URL(buf.toString());
+               } catch (Exception e) {
+                       throw new SlcException("Cannot create URL: " + buf, e);
                }
        }
 
@@ -123,4 +192,19 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        public void setRetryPeriod(Long retryPeriod) {
                this.retryPeriod = retryPeriod;
        }
+
+       public void setMarshaller(Marshaller marshaller) {
+               this.marshaller = marshaller;
+       }
+
+       /** Default is UTF-8. */
+       public void setEncoding(String encoding) {
+               this.encoding = encoding;
+       }
+
+       /** Default is 30s*/
+       public void setDefaultTimeout(Long defaultTimeout) {
+               this.defaultTimeout = defaultTimeout;
+       }
+
 }