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=43f8fe16a9a82bbdc127b42ab447aa17d07c786b;hb=c013d066971b9ac23b7b488bd1cc6193c83b6227;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..43f8fe16a 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,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 callService(String path, Map parameters) { + return (T)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,13 @@ public abstract class AbstractHttpServicesClient implements HttpServicesClient { @SuppressWarnings(value = { "unchecked" }) public T callServiceSafe(String path, Map parameters, Condition 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 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('?'); + 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; + } + }