001: package com.xoetrope.service.http;
002:
003: import java.io.InputStream;
004: import java.io.InputStreamReader;
005: import java.io.OutputStream;
006: import java.net.HttpURLConnection;
007: import java.net.URL;
008: import java.net.URLConnection;
009: import java.util.Hashtable;
010:
011: import net.xoetrope.optional.service.ServiceProxy;
012: import net.xoetrope.optional.service.ServiceProxyArgs;
013: import net.xoetrope.optional.service.ServiceProxyException;
014: import java.net.URLEncoder;
015: import java.util.Enumeration;
016: import net.xoetrope.optional.service.ServiceContext;
017:
018: /**
019: * Makes a service call via the HTTP protocol. By default the arguments are
020: * URLEncoded and the response unencoded. Unlike the XHttpClientServiceProxy,
021: * this class is intended for use with standard http requests.
022: *
023: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
024: * the GNU Public License (GPL), please see license.txt for more details. If
025: * you make commercial use of this software you must purchase a commercial
026: * license from Xoetrope.</p>
027: * <p> $Revision: 1.2 $</p>
028: */
029: public class XHttpRequestProxy extends ServiceProxy {
030: private String sessionID;
031: private int responseCode;
032:
033: /**
034: * Error sent back in the case that a connection cannot be established.
035: */
036: public static final String ERR_CANNOT_CONNECT = "httprequestproxy:cannotconnect";
037: public static final String PARAM_AUTHORIZATION = "httprequestproxy:auth";
038: public static final String PARAM_BODY = "httprequestproxy:body";
039: public static final String REQUEST_METHOD = "httprequestproxy:request_method";
040:
041: protected String sessionKey = "jsessionid";
042: protected boolean useCookies = true;
043:
044: /*
045: * The original string from which the url is constructed.
046: */
047: protected String urlOrig;
048:
049: /*
050: * The url to be called.
051: */
052: protected URL url;
053:
054: /*
055: * Flag to indicate whether or not the url should be encoded.
056: */
057: protected boolean urlEncode = true;
058:
059: private String userName;
060: private String password;
061:
062: public XHttpRequestProxy() {
063: status = OK;
064: }
065:
066: public void setUrlEncoding(String encode) {
067: if (encode.compareTo("false") == 0)
068: urlEncode = false;
069: else
070: urlEncode = true;
071: }
072:
073: public void setUrl(String urlStr) {
074: urlOrig = urlStr;
075: }
076:
077: /**
078: * Makes a call to a server using the http protocol. The arguments are by
079: * default URLEncoded.
080: * @param method the method name to be invoked
081: * @param context the ServiceContext for this ServiceProxy call
082: * @return the response or result of the call
083: * @throws ServiceProxyException
084: */
085: public Object call(String method, ServiceContext context)
086: throws ServiceProxyException {
087: URLConnection conn = null;
088: HttpURLConnection httpConn = null;
089: responseCode = 0;
090:
091: try {
092: status = STARTED;
093: StringBuffer arguments = new StringBuffer();
094: ServiceProxyArgs args = context.getArgs();
095: Hashtable passArgs = context.getPassArgs();
096: Enumeration keys = passArgs.keys();
097: while (keys.hasMoreElements()) {
098: String name = (String) keys.nextElement();
099: if (name.equals(PARAM_AUTHORIZATION)
100: || name.equals(PARAM_BODY))
101: continue;
102: Object argObj = passArgs.get(name);
103: String argValue = (argObj == null) ? "" : argObj
104: .toString();
105: if (arguments.length() > 0)
106: arguments.append("&");
107: arguments.append(URLEncoder.encode(name, "UTF-8"));
108: argValue = (argValue == null ? "" : argValue);
109: arguments.append("="
110: + URLEncoder.encode(argValue, "UTF-8"));
111: }
112:
113: Object argUrl = args.getConfigParam("url");
114: String urlStr;
115: if (argUrl != null)
116: urlStr = argUrl.toString();
117: else
118: urlStr = urlOrig;
119:
120: // if ( arguments.length() > 0 )
121: // urlStr += "?" + arguments.toString();
122: url = new URL(urlStr);
123: conn = url.openConnection();
124: if (conn instanceof HttpURLConnection)
125: httpConn = (HttpURLConnection) conn;
126:
127: // Append the session id
128: setSessionID(conn, arguments);
129:
130: String authorization = (String) args
131: .getConfigParam(PARAM_AUTHORIZATION);
132: if (authorization != null)
133: conn.setRequestProperty("Authorization", "Basic "
134: + authorization);
135:
136: boolean doOutput = false;
137: if (httpConn != null) {
138: String requestMethod = (String) args
139: .getConfigParam(REQUEST_METHOD);
140: if (requestMethod != null) {
141: httpConn.setRequestMethod(requestMethod);
142: if (requestMethod.equals("PUT")
143: || requestMethod.equals("POST"))
144: doOutput = true;
145: }
146: }
147:
148: conn.setDefaultUseCaches(false);
149: conn.setDoOutput(doOutput);
150: conn.setIfModifiedSince(0);
151:
152: if (doOutput) {
153: OutputStream o = conn.getOutputStream();
154: if (arguments.length() > 0)
155: o.write(arguments.toString().getBytes());
156: byte[] bodyBytes = (byte[]) passArgs.get(PARAM_BODY);
157: if (bodyBytes != null) {
158: if (arguments.length() > 0)
159: o.write("\n".getBytes());
160: o.write(bodyBytes);
161: o.flush();
162: }
163: }
164:
165: status = PENDING;
166: conn.connect();
167: if (httpConn != null)
168: responseCode = httpConn.getResponseCode();
169:
170: if (responseCode >= 400)
171: return null;
172:
173: InputStream is = conn.getInputStream();
174:
175: InputStreamReader isr = new InputStreamReader(is);
176: char[] c = new char[4096];
177:
178: int i = 1;
179: String result = new String("");
180: while (i != -1) {
181: i = isr.read(c);
182: if (i > 0)
183: result += new String(c, 0, i);
184: }
185:
186: // Get the session ID
187: retrieveSessionID(conn);
188:
189: isr.close();
190: is.close();
191:
192: status = COMPLETE;
193: return result;
194: } catch (Exception e) {
195: status = FAILED;
196: context.addError(ERR_CANNOT_CONNECT);
197: throw (new ServiceProxyException("'" + method
198: + "' generated an exception : " + e.getMessage()));
199: }
200:
201: }
202:
203: /**
204: * Set the attributes for this service proxy. This class can set attributes
205: * for 'url' and 'urlEncode'.
206: * @param attribs The Hashtable of attributes as found in the XML declaration
207: */
208: public void setAttributes(Hashtable attribs) {
209: setUrl((String) attribs.get("url"));
210: String encode = (String) attribs.get("urlEncode");
211: setUrlEncoding((encode == null) ? "false" : encode);
212: }
213:
214: /**
215: * Set the session id header key. By default this is setup to deal with
216: * servlets and has a value of 'jsessionid'
217: * @param key the new key value
218: */
219: public void setSessionKey(String key) {
220: sessionKey = key;
221: }
222:
223: /**
224: * Setup the session id information.
225: * @param key the new key value
226: * @param id the new session id value
227: * @param state true to use cookies, otherwise URL rewriting is used
228: */
229: public void setupSession(boolean state, String key, String id) {
230: useCookies = state;
231: sessionKey = key;
232: sessionID = id;
233: }
234:
235: /**
236: * Get the response code for this request
237: */
238: public Integer getStatus() {
239: return new Integer(responseCode);
240: }
241:
242: /**
243: * Attempt to get the session ID
244: * @param conn the connection
245: */
246: protected void retrieveSessionID(URLConnection conn) {
247: if (sessionID == null)
248: useCookies = false;
249:
250: String key = "";
251: String id = "";
252: if (conn != null) {
253: for (int i = 1; (key = conn.getHeaderFieldKey(i)) != null; i++) {
254: if (key.equalsIgnoreCase("set-cookie")) {
255: id = conn.getHeaderField(key);
256: id = id.substring(0, id.indexOf(";"));
257: useCookies = true;
258: }
259: }
260: }
261:
262: sessionID = id;
263: if (!useCookies) {
264: // Retrieve the session ID.
265: sessionID = conn.getHeaderField(sessionKey);
266: useCookies = false;
267: }
268: }
269:
270: /**
271: * Attempt to get the session ID
272: * @param conn the connection
273: */
274: protected void setSessionID(URLConnection conn,
275: StringBuffer arguments) {
276: if (sessionID == null)
277: return;
278:
279: if (useCookies)
280: conn.setRequestProperty("Cookie", sessionID);
281: else {
282: if (sessionID != null) {
283: if (arguments.length() > 0)
284: arguments.append("&");
285: arguments.append(sessionKey + "=" + sessionID);
286: }
287: }
288: }
289: }
|