X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.server%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fserver%2Fclient%2Fimpl%2FAbstractHttpServicesClient.java;h=44444f6f13c6c78a3399410f4d0626cbc9332253;hb=b0c2c01573db47690afdf723e49fb7fa39561e8e;hp=ba4e584efb242a9bc12d985a9bb4879cf546d798;hpb=4f2c9778c7f5559bec3d9480de011181962ad105;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java index ba4e584ef..44444f6f1 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java @@ -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 = 10 * 1000l; + public T callService(String path, Map parameters) { + return callService(path, parameters, null); + } + + @SuppressWarnings(value = { "unchecked" }) + public T callService(String path, Map 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 callServiceSafe(String path, Map parameters, Condition 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 parameters) throws IOException { + Map 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 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 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; + } + }