]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.launcher/src/main/java/org/argeo/slc/server/client/impl/AbstractHttpServicesClient.java
Adapt to changes in Argeo Commons
[gpl/argeo-slc.git] / runtime / org.argeo.slc.launcher / src / main / java / org / argeo / slc / server / client / impl / AbstractHttpServicesClient.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.slc.server.client.impl;
17
18 import java.io.IOException;
19 import java.io.InputStreamReader;
20 import java.io.OutputStreamWriter;
21 import java.io.Reader;
22 import java.io.Writer;
23 import java.net.Authenticator;
24 import java.net.HttpURLConnection;
25 import java.net.PasswordAuthentication;
26 import java.net.URL;
27 import java.net.URLEncoder;
28 import java.util.Map;
29
30 import javax.xml.transform.Source;
31 import javax.xml.transform.stream.StreamResult;
32 import javax.xml.transform.stream.StreamSource;
33
34 import org.apache.commons.io.IOUtils;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.argeo.slc.Condition;
38 import org.argeo.slc.SlcException;
39 import org.argeo.slc.server.client.HttpServicesClient;
40 import org.springframework.oxm.Marshaller;
41 import org.springframework.oxm.Unmarshaller;
42 import org.springframework.util.Assert;
43
44 public abstract class AbstractHttpServicesClient implements HttpServicesClient {
45 private final static Log log = LogFactory
46 .getLog(AbstractHttpServicesClient.class);
47
48 private String user;
49 private String password;
50
51 private Unmarshaller unmarshaller;
52 private Marshaller marshaller;
53 private String baseUrl;
54 private String encoding = "UTF-8";
55
56 private Long retryPeriod = 1000l;
57 private Long defaultTimeout = 30 * 1000l;
58
59 public void init() {
60 if (user != null && password != null)
61 Authenticator.setDefault(new Authenticator() {
62 protected PasswordAuthentication getPasswordAuthentication() {
63 return new PasswordAuthentication(user, password
64 .toCharArray());
65 }
66 });
67 }
68
69 @SuppressWarnings(value = { "unchecked" })
70 public <T> T callService(String path, Map<String, String> parameters) {
71 return (T) callService(path, parameters, null);
72 }
73
74 @SuppressWarnings(value = { "unchecked" })
75 public <T> T callService(String path, Map<String, String> parameters,
76 Object body) {
77 try {
78 return (T) callServiceLowLevel(path, parameters, body);
79 } catch (Exception e) {
80 throw new SlcException("Cannot call service " + path + " on "
81 + baseUrl, e);
82 }
83 }
84
85 @SuppressWarnings(value = { "unchecked" })
86 public <T> T callServiceSafe(String path, Map<String, String> parameters,
87 Condition<T> condition, Long timeout) {
88
89 long begin = System.currentTimeMillis();
90 try {
91 Object obj = null;
92 while (System.currentTimeMillis() - begin < timeout(timeout)) {
93 try {
94 obj = callServiceLowLevel(path, parameters, null);
95 } catch (IOException e) {
96 if (log.isTraceEnabled())
97 log.trace("Exception when calling service " + path
98 + " on " + baseUrl, e);
99 }
100
101 if (obj != null) {
102 if (condition == null)
103 break;
104 else {
105 if (condition.check((T) obj))
106 break;
107 }
108 }
109 // wait a bit
110 try {
111 Thread.sleep(retryPeriod);
112 } catch (InterruptedException e) {
113 // silent
114 }
115 }
116
117 if (obj == null)
118 throw new SlcException(
119 "Service "
120 + path
121 + " on "
122 + baseUrl
123 + " did not return an answer after calling it safely for "
124 + timeout(timeout) + " ms.");
125 return (T) obj;
126 } catch (Exception e) {
127 throw new SlcException(
128 "Unexpected exception when safely calling service " + path
129 + " on " + baseUrl, e);
130 }
131 }
132
133 protected Object callServiceLowLevel(String path,
134 Map<String, String> parameters, Object body) throws IOException {
135
136 Assert.notNull(baseUrl, "base url");
137 HttpURLConnection connection = null;
138 Writer writer = null;
139 Reader reader = null;
140 try {
141 URL url = createUrl(path, parameters);
142 connection = (HttpURLConnection) url.openConnection();
143
144 if (body != null) {
145 connection.setRequestMethod("POST");
146 connection.setDoOutput(true);
147 connection.setDoInput(true);
148 connection.setUseCaches(false);
149 connection.setAllowUserInteraction(false);
150 connection.setRequestProperty("Content-type",
151 "text/xml; charset=" + encoding);
152 }
153
154 // Establish the connection
155 connection.connect();
156
157 if (body != null) {
158 writer = new OutputStreamWriter(connection.getOutputStream(),
159 encoding);
160 StreamResult result = new StreamResult(writer);
161 marshaller.marshal(body, result);
162 writer.flush();
163 IOUtils.closeQuietly(writer);
164 }
165
166 // Read answer
167 reader = new InputStreamReader(connection.getInputStream(),
168 encoding);
169 Source source = new StreamSource(reader);
170 Object obj = unmarshaller.unmarshal(source);
171 return obj;
172 } finally {
173 IOUtils.closeQuietly(reader);
174 IOUtils.closeQuietly(writer);
175 if (connection != null) {
176 connection.disconnect();
177 }
178 }
179 }
180
181 protected URL createUrl(String service, Map<String, String> parameters) {
182 // URL encoded with UTF-8, as recommended by W3C
183 final String urlEncoding = "UTF-8";
184
185 StringBuffer buf = new StringBuffer(baseUrl + service);
186 try {
187 if (parameters != null && parameters.size() != 0) {
188 buf.append('?');
189 boolean first = true;
190 for (String key : parameters.keySet()) {
191 String value = parameters.get(key);
192 if (value != null) {
193 if (first)
194 first = false;
195 else
196 buf.append('&');
197 String keyEncoded = URLEncoder.encode(key, urlEncoding);
198 String valueEncoded = URLEncoder.encode(value,
199 urlEncoding);
200 buf.append(keyEncoded).append('=').append(valueEncoded);
201 }
202 }
203 }
204
205 return new URL(buf.toString());
206 } catch (Exception e) {
207 throw new SlcException("Cannot create URL: " + buf, e);
208 }
209 }
210
211 public Long timeout(Long timeout) {
212 if (timeout == null)
213 timeout = getDefaultTimeout();
214 return timeout;
215 }
216
217 public void setUnmarshaller(Unmarshaller unmarshaller) {
218 this.unmarshaller = unmarshaller;
219 }
220
221 public void setBaseUrl(String baseUrl) {
222 this.baseUrl = baseUrl;
223 }
224
225 public Long getRetryPeriod() {
226 return retryPeriod;
227 }
228
229 /** Retry period in ms when accessing service safely. Default is 1000 ms. */
230 public void setRetryPeriod(Long retryPeriod) {
231 this.retryPeriod = retryPeriod;
232 }
233
234 public void setMarshaller(Marshaller marshaller) {
235 this.marshaller = marshaller;
236 }
237
238 /** Default is UTF-8. */
239 public void setEncoding(String encoding) {
240 this.encoding = encoding;
241 }
242
243 /** Default is 30s */
244 public void setDefaultTimeout(Long defaultTimeout) {
245 this.defaultTimeout = defaultTimeout;
246 }
247
248 public Long getDefaultTimeout() {
249 return defaultTimeout;
250 }
251
252 public void setUser(String user) {
253 this.user = user;
254 }
255
256 public void setPassword(String password) {
257 this.password = password;
258 }
259
260 }