001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.wsrp.handler;
023:
024: import org.apache.commons.httpclient.Cookie;
025: import org.apache.commons.httpclient.cookie.MalformedCookieException;
026: import org.apache.commons.httpclient.cookie.RFC2109Spec;
027: import org.jboss.portal.wsrp.consumer.ProducerSessionInformation;
028:
029: import javax.xml.namespace.QName;
030: import javax.xml.rpc.Stub;
031: import javax.xml.rpc.handler.GenericHandler;
032: import javax.xml.rpc.handler.MessageContext;
033: import javax.xml.rpc.handler.soap.SOAPMessageContext;
034: import javax.xml.soap.MimeHeaders;
035: import javax.xml.soap.SOAPMessage;
036: import java.net.MalformedURLException;
037: import java.net.URL;
038:
039: /**
040: * A request handler that uses a thread local to setup cookies on the wire.
041: *
042: * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
043: * @author <a href="mailto:chris.laprun@jboss.com?subject=org.jboss.portal.wsrp.handler.RequestHeaderClientHandler">Chris
044: * Laprun</a>
045: */
046: public class RequestHeaderClientHandler extends GenericHandler {
047: private static final ThreadLocal local = new ThreadLocal();
048: private static final RFC2109Spec cookieParser = new RFC2109Spec();
049:
050: public QName[] getHeaders() {
051: return null;
052: }
053:
054: public boolean handleRequest(MessageContext msgContext) {
055: CurrentInfo info = getCurrentInfo(false);
056: if (info == null) {
057: return super .handleRequest(msgContext);
058: }
059:
060: ProducerSessionInformation sessionInfo = info.sessionInfo;
061: if (sessionInfo == null) {
062: return super .handleRequest(msgContext);
063: }
064:
065: SOAPMessageContext smc = (SOAPMessageContext) msgContext;
066: SOAPMessage message = smc.getMessage();
067: MimeHeaders mimeHeaders = message.getMimeHeaders();
068: StringBuffer cookie = new StringBuffer(64);
069: if (sessionInfo.isPerGroupCookies()) {
070: if (info.groupId == null) {
071: throw new IllegalStateException(
072: "Was expecting a current group Id...");
073: }
074:
075: String groupCookie = sessionInfo
076: .getGroupCookieFor(info.groupId);
077: if (groupCookie != null) {
078: cookie.append(groupCookie);
079: }
080: }
081:
082: String userCookie = sessionInfo.getUserCookie();
083: if (userCookie != null) {
084: if (cookie.length() != 0) {
085: cookie.append(";");
086: }
087: cookie.append(userCookie);
088: }
089:
090: if (cookie.length() != 0) {
091: mimeHeaders.setHeader("Cookie", cookie.toString());
092: }
093:
094: return super .handleRequest(msgContext);
095: }
096:
097: public boolean handleResponse(MessageContext msgContext) {
098: SOAPMessageContext smc = (SOAPMessageContext) msgContext;
099: SOAPMessage message = smc.getMessage();
100: MimeHeaders mimeHeaders = message.getMimeHeaders();
101: String[] cookieValues = mimeHeaders.getHeader("Set-Cookie");
102:
103: if (cookieValues != null) {
104: if (cookieValues.length > 1) {
105: StringBuffer sb = new StringBuffer(128);
106: sb.append("Cookie headers:\n");
107: for (int i = 0; i < cookieValues.length; i++) {
108: sb.append("\t").append(i).append(":\t").append(
109: cookieValues[i]).append("\n");
110:
111: }
112: throw new IllegalArgumentException(
113: "Too many cookie headers!\n" + sb.toString());
114: }
115:
116: Cookie[] cookies = extractCookies((String) msgContext
117: .getProperty(Stub.ENDPOINT_ADDRESS_PROPERTY),
118: cookieValues);
119:
120: CurrentInfo info = getCurrentInfo(true);
121: ProducerSessionInformation sessionInfo = info.sessionInfo;
122:
123: if (sessionInfo.isPerGroupCookies()) {
124: if (info.groupId == null) {
125: throw new IllegalStateException(
126: "Was expecting a current group Id...");
127: }
128:
129: sessionInfo.setGroupCookieFor(info.groupId, cookies);
130: } else {
131: sessionInfo.setUserCookie(cookies);
132: }
133: }
134:
135: return super .handleResponse(msgContext);
136: }
137:
138: private Cookie[] extractCookies(String endpointAddress,
139: String[] cookieValues) {
140: if (endpointAddress == null) {
141: throw new NullPointerException(
142: "Was expecting an endpoint address but none was provided in the MessageContext");
143: }
144:
145: URL hostURL;
146: try {
147: hostURL = new URL(endpointAddress);
148: } catch (MalformedURLException e) {
149: // should not happen
150: throw new IllegalArgumentException(endpointAddress
151: + " is not a valid URL for the endpoint address.");
152: }
153:
154: String cookie = cookieValues[0];
155: Cookie[] cookies;
156: try {
157: String host = hostURL.getHost();
158: int port = hostURL.getPort();
159: if (port == -1) {
160: port = 80; // if the port is not set in the endpoint address, assume it's 80.
161: }
162: String path = hostURL.getPath();
163: boolean secure = hostURL.getProtocol().endsWith("s"); // todo: is that correct?
164:
165: cookies = cookieParser.parse(host, port, path, secure,
166: cookie);
167:
168: for (int i = 0; i < cookies.length; i++) {
169: cookieParser.validate(host, port, path, secure,
170: cookies[i]);
171: }
172: } catch (MalformedCookieException e) {
173: throw new IllegalArgumentException("Malformed cookie: "
174: + cookie);
175: }
176: return cookies;
177: }
178:
179: public static void setCurrentInfo(String groupId,
180: ProducerSessionInformation sessionInformation) {
181: local.set(new CurrentInfo(groupId, sessionInformation));
182: }
183:
184: public static void resetCurrentInfo() {
185: local.set(null);
186: }
187:
188: public static ProducerSessionInformation getCurrentProducerSessionInformation() {
189: CurrentInfo info = getCurrentInfo(false);
190:
191: if (info != null) {
192: return info.sessionInfo;
193: }
194:
195: return null;
196: }
197:
198: public static String getCurrentGroupId() {
199: CurrentInfo info = getCurrentInfo(false);
200: if (info != null) {
201: return info.groupId;
202: }
203: return null;
204: }
205:
206: public static void setCurrentGroupId(String groupId) {
207: CurrentInfo currentInfo = (CurrentInfo) local.get();
208: if (currentInfo == null) {
209: throw new IllegalStateException(
210: "Cannot set current group id when the current info hasn't been initialized.");
211: }
212: currentInfo.groupId = groupId;
213: }
214:
215: private static CurrentInfo getCurrentInfo(boolean createIfNeeded) {
216: CurrentInfo info = (CurrentInfo) local.get();
217: if (info == null && createIfNeeded) {
218: info = new CurrentInfo(null,
219: new ProducerSessionInformation());
220: local.set(info);
221: }
222: return info;
223: }
224:
225: static class CurrentInfo {
226: public CurrentInfo(String groupId,
227: ProducerSessionInformation sessionInfo) {
228: this .groupId = groupId;
229: this .sessionInfo = sessionInfo;
230: }
231:
232: String groupId;
233: ProducerSessionInformation sessionInfo;
234: }
235: }
|