]> 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
Remote shutdown
[gpl/argeo-slc.git] / runtime / org.argeo.slc.server / src / main / java / org / argeo / slc / server / client / impl / AbstractHttpServicesClient.java
index ba4e584efb242a9bc12d985a9bb4879cf546d798..43f8fe16a9a82bbdc127b42ab447aa17d07c786b 100644 (file)
@@ -1,11 +1,17 @@
 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.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 +20,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 +28,23 @@ 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;
+       private Long defaultTimeout = 30 * 1000l;
+
        @SuppressWarnings(value = { "unchecked" })
        public <T> T callService(String path, Map<String, String> parameters) {
+               return (T)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,13 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
        @SuppressWarnings(value = { "unchecked" })
        public <T> T callServiceSafe(String path, Map<String, String> parameters,
                        Condition<T> condition, Long timeout) {
+
                long begin = System.currentTimeMillis();
                try {
                        Object obj = null;
-                       long duration = System.currentTimeMillis() - begin;
-                       while (duration < timeout) {
+                       while (System.currentTimeMillis() - begin < timeout(timeout)) {
                                try {
-                                       obj = callServiceLowLevel(path, parameters);
+                                       obj = callServiceLowLevel(path, parameters, null);
                                } catch (IOException e) {
                                        if (log.isTraceEnabled())
                                                log.trace("Exception when calling service " + path
@@ -73,7 +90,7 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient {
                                                                + " on "
                                                                + baseUrl
                                                                + " did not return an answer after calling it safely for "
-                                                               + duration + " ms.");
+                                                               + timeout(timeout) + " ms.");
                        return (T) obj;
                } catch (Exception e) {
                        throw new SlcException(
@@ -83,30 +100,88 @@ 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('?');
+                               boolean first = true;
+                               for (String key : parameters.keySet()) {
+                                       String value = parameters.get(key);
+                                       if (value != null) {
+                                               if (first)
+                                                       first = false;
+                                               else
+                                                       buf.append('&');
+                                               String keyEncoded = URLEncoder.encode(key, urlEncoding);
+                                               String valueEncoded = URLEncoder.encode(value,
+                                                               urlEncoding);
+                                               buf.append(keyEncoded).append('=').append(valueEncoded);
+                                       }
+                               }
+                       }
+
+                       return new URL(buf.toString());
+               } catch (Exception e) {
+                       throw new SlcException("Cannot create URL: " + buf, e);
+               }
+       }
+
+       public Long timeout(Long timeout) {
+               if (timeout == null)
+                       timeout = getDefaultTimeout();
+               return timeout;
+       }
+
        public void setUnmarshaller(Unmarshaller unmarshaller) {
                this.unmarshaller = unmarshaller;
        }
@@ -123,4 +198,23 @@ 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;
+       }
+
+       public Long getDefaultTimeout() {
+               return defaultTimeout;
+       }
+
 }