1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.client.bindings.spi.http;
20
21 import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNotEmpty;
22
23 import java.io.BufferedOutputStream;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.math.BigInteger;
27 import java.net.HttpURLConnection;
28 import java.net.URL;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.zip.GZIPOutputStream;
32
33 import javax.net.ssl.HostnameVerifier;
34 import javax.net.ssl.HttpsURLConnection;
35 import javax.net.ssl.SSLSocketFactory;
36
37 import org.apache.chemistry.opencmis.client.bindings.impl.ClientVersion;
38 import org.apache.chemistry.opencmis.client.bindings.impl.CmisBindingsHelper;
39 import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
40 import org.apache.chemistry.opencmis.commons.SessionParameter;
41 import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
42 import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
43 import org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class DefaultHttpInvoker implements HttpInvoker {
48
49 private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpInvoker.class);
50
51 private static final int BUFFER_SIZE = 2 * 1024 * 1024;
52
53 public DefaultHttpInvoker() {
54 }
55
56 @Override
57 public Response invokeGET(UrlBuilder url, BindingSession session) {
58 return invoke(url, "GET", null, null, null, session, null, null);
59 }
60
61 @Override
62 public Response invokeGET(UrlBuilder url, BindingSession session, BigInteger offset, BigInteger length) {
63 return invoke(url, "GET", null, null, null, session, offset, length);
64 }
65
66 @Override
67 public Response invokePOST(UrlBuilder url, String contentType, Output writer, BindingSession session) {
68 return invoke(url, "POST", contentType, null, writer, session, null, null);
69 }
70
71 @Override
72 public Response invokePUT(UrlBuilder url, String contentType, Map<String, String> headers, Output writer,
73 BindingSession session) {
74 return invoke(url, "PUT", contentType, headers, writer, session, null, null);
75 }
76
77 @Override
78 public Response invokeDELETE(UrlBuilder url, BindingSession session) {
79 return invoke(url, "DELETE", null, null, null, session, null, null);
80 }
81
82 private Response invoke(UrlBuilder url, String method, String contentType, Map<String, String> headers,
83 Output writer, BindingSession session, BigInteger offset, BigInteger length) {
84 int respCode = -1;
85
86 try {
87
88 if (LOG.isDebugEnabled()) {
89 LOG.debug("Session {}: {} {}", session.getSessionId(), method, url);
90 }
91
92
93 HttpURLConnection conn = (HttpURLConnection) (new URL(url.toString())).openConnection();
94 conn.setRequestMethod(method);
95 conn.setDoInput(true);
96 conn.setDoOutput(writer != null);
97 conn.setAllowUserInteraction(false);
98 conn.setUseCaches(false);
99
100 conn.setRequestProperty("User-Agent",
101 (String) session.get(SessionParameter.USER_AGENT, ClientVersion.OPENCMIS_USER_AGENT));
102
103
104 int connectTimeout = session.get(SessionParameter.CONNECT_TIMEOUT, -1);
105 if (connectTimeout >= 0) {
106 conn.setConnectTimeout(connectTimeout);
107 }
108
109 int readTimeout = session.get(SessionParameter.READ_TIMEOUT, -1);
110 if (readTimeout >= 0) {
111 conn.setReadTimeout(readTimeout);
112 }
113
114
115 if (contentType != null) {
116 conn.setRequestProperty("Content-Type", contentType);
117 }
118
119 if (headers != null) {
120 for (Map.Entry<String, String> header : headers.entrySet()) {
121 conn.addRequestProperty(header.getKey(), header.getValue());
122 }
123 }
124
125
126 AuthenticationProvider authProvider = CmisBindingsHelper.getAuthenticationProvider(session);
127 if (authProvider != null) {
128 Map<String, List<String>> httpHeaders = authProvider.getHTTPHeaders(url.toString());
129 if (httpHeaders != null) {
130 for (Map.Entry<String, List<String>> header : httpHeaders.entrySet()) {
131 if (header.getKey() != null && isNotEmpty(header.getValue())) {
132 String key = header.getKey();
133 if (key.equalsIgnoreCase("user-agent")) {
134 conn.setRequestProperty("User-Agent", header.getValue().get(0));
135 } else {
136 for (String value : header.getValue()) {
137 if (value != null) {
138 conn.addRequestProperty(key, value);
139 }
140 }
141 }
142 }
143 }
144 }
145
146 if (conn instanceof HttpsURLConnection) {
147 SSLSocketFactory sf = authProvider.getSSLSocketFactory();
148 if (sf != null) {
149 ((HttpsURLConnection) conn).setSSLSocketFactory(sf);
150 }
151
152 HostnameVerifier hv = authProvider.getHostnameVerifier();
153 if (hv != null) {
154 ((HttpsURLConnection) conn).setHostnameVerifier(hv);
155 }
156 }
157 }
158
159
160 if (offset != null || length != null) {
161 StringBuilder sb = new StringBuilder("bytes=");
162
163 if ((offset == null) || (offset.signum() == -1)) {
164 offset = BigInteger.ZERO;
165 }
166
167 sb.append(offset.toString());
168 sb.append('-');
169
170 if (length != null && length.signum() == 1) {
171 sb.append(offset.add(length.subtract(BigInteger.ONE)).toString());
172 }
173
174 conn.setRequestProperty("Range", sb.toString());
175 }
176
177
178 Object compression = session.get(SessionParameter.COMPRESSION);
179 if (compression != null && Boolean.parseBoolean(compression.toString())) {
180 conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
181 }
182
183
184 if (session.get(CmisBindingsHelper.ACCEPT_LANGUAGE) instanceof String) {
185 conn.setRequestProperty("Accept-Language", session.get(CmisBindingsHelper.ACCEPT_LANGUAGE).toString());
186 }
187
188
189 if (writer != null) {
190 conn.setChunkedStreamingMode((64 * 1024) - 1);
191
192 OutputStream connOut = null;
193
194 Object clientCompression = session.get(SessionParameter.CLIENT_COMPRESSION);
195 if ((clientCompression != null) && Boolean.parseBoolean(clientCompression.toString())) {
196 conn.setRequestProperty("Content-Encoding", "gzip");
197 connOut = new GZIPOutputStream(conn.getOutputStream(), 4096);
198 } else {
199 connOut = conn.getOutputStream();
200 }
201
202 OutputStream out = new BufferedOutputStream(connOut, BUFFER_SIZE);
203 writer.write(out);
204 out.close();
205 }
206
207
208 conn.connect();
209
210
211 respCode = conn.getResponseCode();
212 InputStream inputStream = null;
213 if (respCode == 200 || respCode == 201 || respCode == 203 || respCode == 206) {
214 inputStream = conn.getInputStream();
215 }
216
217
218 if (LOG.isTraceEnabled()) {
219 LOG.trace("Session {}: {} {} > Headers: {}", session.getSessionId(), method, url,
220 conn.getHeaderFields().toString());
221 }
222
223
224 if (authProvider != null) {
225 authProvider.putResponseHeaders(url.toString(), respCode, conn.getHeaderFields());
226 }
227
228
229 return new Response(respCode, conn.getResponseMessage(), conn.getHeaderFields(), inputStream,
230 conn.getErrorStream());
231 } catch (Exception e) {
232 throw new CmisConnectionException(url.toString(), respCode, e);
233 }
234 }
235 }