1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.http;
12
13 import org.mule.api.MuleEvent;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.expression.ExpressionManager;
16
17 import java.net.URI;
18 import java.net.URISyntaxException;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Map.Entry;
25
26 import org.apache.commons.httpclient.Cookie;
27 import org.apache.commons.httpclient.Header;
28 import org.apache.commons.httpclient.HttpClient;
29 import org.apache.commons.httpclient.cookie.CookiePolicy;
30 import org.apache.commons.httpclient.cookie.CookieSpec;
31 import org.apache.commons.httpclient.cookie.MalformedCookieException;
32 import org.apache.commons.httpclient.cookie.NetscapeDraftSpec;
33 import org.apache.commons.httpclient.cookie.RFC2109Spec;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.tomcat.util.http.Cookies;
37 import org.apache.tomcat.util.http.MimeHeaders;
38 import org.apache.tomcat.util.http.ServerCookie;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 public class CookieHelper
92 {
93
94
95
96
97
98
99 private static final String DEFAULT_URI_STRING = "http://localhost:80/";
100
101
102
103 protected static final Log logger = LogFactory.getLog(CookieHelper.class);
104
105
106
107
108 private CookieHelper()
109 {
110
111 }
112
113
114
115
116
117
118 public static CookieSpec getCookieSpec(String spec)
119 {
120 if (spec != null && spec.equalsIgnoreCase(HttpConnector.COOKIE_SPEC_NETSCAPE))
121 {
122 return new NetscapeDraftSpec();
123 }
124 else
125 {
126 return new RFC2109Spec();
127 }
128 }
129
130
131
132
133
134
135 public static String getCookiePolicy(String spec)
136 {
137 if (spec != null && spec.equalsIgnoreCase(HttpConnector.COOKIE_SPEC_NETSCAPE))
138 {
139 return CookiePolicy.NETSCAPE;
140 }
141 else
142 {
143 return CookiePolicy.RFC_2109;
144 }
145 }
146
147
148
149
150 public static Cookie[] parseCookiesAsAClient(Header cookieHeader, String spec)
151 throws MalformedCookieException
152 {
153 return parseCookiesAsAClient(cookieHeader.getValue(), spec, null);
154 }
155
156
157
158
159 public static Cookie[] parseCookiesAsAClient(String cookieHeaderValue, String spec)
160 throws MalformedCookieException
161 {
162 return parseCookiesAsAClient(cookieHeaderValue, spec, null);
163 }
164
165
166
167
168 public static Cookie[] parseCookiesAsAClient(Header cookieHeader, String spec, URI uri)
169 throws MalformedCookieException
170 {
171 return parseCookiesAsAClient(cookieHeader.getValue(), spec, uri);
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 public static Cookie[] parseCookiesAsAClient(String cookieHeaderValue, String spec, URI uri)
189 throws MalformedCookieException
190 {
191 if (uri == null)
192 {
193 try
194 {
195 uri = new URI(DEFAULT_URI_STRING);
196 }
197 catch (URISyntaxException e)
198 {
199 throw new RuntimeException("This should have not happened", e);
200 }
201 }
202 CookieSpec cookieSpec = getCookieSpec(spec);
203 boolean secure = uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("https");
204 String host = uri.getHost();
205 int port = getPortFromURI(uri);
206 String path = uri.getPath();
207
208 return cookieSpec.parse(host, port, path, secure, cookieHeaderValue);
209 }
210
211 private static int getPortFromURI(URI uri) throws MalformedCookieException
212 {
213 int port = uri.getPort();
214 if (port < 0)
215 {
216 String scheme = uri.getScheme();
217 if (scheme.equalsIgnoreCase("https"))
218 {
219 port = 443;
220 }
221 else if (scheme.equalsIgnoreCase("http"))
222 {
223 port = 80;
224 }
225 else
226 {
227 throw new MalformedCookieException(
228 "The uri ("
229 + uri
230 + ") does not specify a port and no default is available for its scheme ("
231 + scheme + ").");
232 }
233 }
234 return port;
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public static Cookie[] parseCookiesAsAServer(Header header, URI uri)
250 {
251 return parseCookiesAsAServer(header.getValue(), uri);
252 }
253
254
255
256
257
258
259
260
261
262
263
264 public static Cookie[] parseCookiesAsAServer(String headerValue, URI uri)
265 {
266 MimeHeaders mimeHeaders = new MimeHeaders();
267 mimeHeaders.addValue(HttpConstants.HEADER_COOKIE).setBytes(headerValue.getBytes(), 0,
268 headerValue.length());
269
270 Cookies cs = new Cookies(mimeHeaders);
271 Cookie[] cookies = new Cookie[cs.getCookieCount()];
272 for (int i = 0; i < cs.getCookieCount(); i++)
273 {
274 ServerCookie serverCookie = cs.getCookie(i);
275 cookies[i] = transformServerCookieToClientCookie(serverCookie);
276 if (uri != null)
277 {
278 cookies[i].setSecure(uri.getScheme() != null && uri.getScheme().equalsIgnoreCase("https"));
279 cookies[i].setDomain(uri.getHost());
280 cookies[i].setPath(uri.getPath());
281 }
282 }
283 return cookies;
284 }
285
286
287
288
289
290
291
292
293
294
295 protected static Cookie transformServerCookieToClientCookie(ServerCookie serverCookie)
296 {
297 Cookie clientCookie = new Cookie(serverCookie.getDomain().toString(), serverCookie.getName()
298 .toString(), serverCookie.getValue().toString(), serverCookie.getPath().toString(),
299 serverCookie.getMaxAge(), serverCookie.getSecure());
300 clientCookie.setComment(serverCookie.getComment().toString());
301 clientCookie.setVersion(serverCookie.getVersion());
302 return clientCookie;
303 }
304
305
306
307
308
309
310
311
312 public static String formatCookieForASetCookieHeader(Cookie cookie)
313 {
314 StringBuffer sb = new StringBuffer();
315 ServerCookie.appendCookieValue(sb, cookie.getVersion(), cookie.getName(), cookie.getValue(),
316 cookie.getPath(), cookie.getDomain(), cookie.getComment(), -1, cookie.getSecure());
317 String cookieForASetCookieHeader = sb.toString();
318 return cookieForASetCookieHeader;
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332
333 public static void addCookiesToClient(HttpClient client,
334 Object cookiesObject,
335 String policy,
336 MuleEvent event,
337 URI destinationUri)
338 {
339 CookieStorageType.resolveCookieStorageType(cookiesObject).addCookiesToClient(client, cookiesObject,
340 policy, event, destinationUri);
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359 public static Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue)
360 {
361 return CookieStorageType.resolveCookieStorageType(preExistentCookies).putAndMergeCookie(
362 preExistentCookies, cookieName, cookieValue);
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378 public static Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray)
379 {
380 return CookieStorageType.resolveCookieStorageType(preExistentCookies).putAndMergeCookie(
381 preExistentCookies, newCookiesArray);
382 }
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 public static Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap)
398 {
399 return CookieStorageType.resolveCookieStorageType(preExistentCookies).putAndMergeCookie(
400 preExistentCookies, newCookiesMap);
401 }
402
403
404
405
406
407
408
409
410
411 public static String getCookieValueFromCookies(Object cookiesObject, String cookieName)
412 {
413 return CookieStorageType.resolveCookieStorageType(cookiesObject).getCookieValueFromCookies(
414 cookiesObject, cookieName);
415 }
416
417
418
419
420
421
422
423 public static Cookie[] asArrayOfCookies(Object cookiesObject)
424 {
425 return CookieStorageType.resolveCookieStorageType(cookiesObject).asArrayOfCookies(cookiesObject);
426 }
427
428 }
429
430
431
432
433
434
435
436 enum CookieStorageType
437 {
438
439
440
441
442
443
444
445 ARRAY_OF_COOKIES
446 {
447 @Override
448 public Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue)
449 {
450 final Cookie[] preExistentCookiesArray = (Cookie[]) preExistentCookies;
451
452 final int sessionIndex = getCookieIndexFromCookiesArray(cookieName, preExistentCookiesArray);
453
454
455
456 final Cookie newSessionCookie = new Cookie(null, cookieName, cookieValue);
457 final Cookie[] mergedCookiesArray;
458 if (sessionIndex >= 0)
459 {
460 preExistentCookiesArray[sessionIndex] = newSessionCookie;
461 mergedCookiesArray = preExistentCookiesArray;
462 }
463 else
464 {
465 Cookie[] newSessionCookieArray = new Cookie[]{newSessionCookie};
466 mergedCookiesArray = concatenateCookies(preExistentCookiesArray, newSessionCookieArray);
467 }
468 return mergedCookiesArray;
469 }
470
471 protected Cookie[] concatenateCookies(Cookie[] cookies1, Cookie[] cookies2)
472 {
473 if (cookies1 == null)
474 {
475 return cookies2;
476 }
477 else if (cookies2 == null)
478 {
479 return null;
480 }
481 else
482 {
483 Cookie[] mergedCookies = new Cookie[cookies1.length + cookies2.length];
484 System.arraycopy(cookies1, 0, mergedCookies, 0, cookies1.length);
485 System.arraycopy(cookies2, 0, mergedCookies, cookies1.length, cookies2.length);
486 return mergedCookies;
487 }
488 }
489
490 protected int getCookieIndexFromCookiesArray(String cookieName, Cookie[] preExistentCookies)
491 {
492 if (preExistentCookies != null && cookieName != null)
493 {
494 for (int i = 0; i < preExistentCookies.length; i++)
495 {
496 if (cookieName.equals(preExistentCookies[i].getName()))
497 {
498 return i;
499 }
500 }
501 }
502 return -1;
503 }
504
505 @Override
506 public String getCookieValueFromCookies(Object cookiesObject, String cookieName)
507 {
508 Cookie[] cookies = (Cookie[]) cookiesObject;
509
510 int sessionIndex = getCookieIndexFromCookiesArray(cookieName, cookies);
511 if (sessionIndex >= 0)
512 {
513 return cookies[sessionIndex].getValue();
514 }
515 else
516 {
517 return null;
518 }
519 }
520
521 @Override
522 public void addCookiesToClient(HttpClient client,
523 Object cookiesObject,
524 String policy,
525 MuleEvent event,
526 URI destinationUri)
527 {
528 Cookie[] cookies = (Cookie[]) cookiesObject;
529
530 if (cookies != null && cookies.length > 0)
531 {
532 String host = destinationUri.getHost();
533 String path = destinationUri.getPath();
534 for (Cookie cookie : cookies)
535 {
536 client.getState().addCookie(
537 new Cookie(host, cookie.getName(), cookie.getValue(), path, cookie.getExpiryDate(),
538 cookie.getSecure()));
539 }
540 client.getParams().setCookiePolicy(CookieHelper.getCookiePolicy(policy));
541 }
542 }
543
544 @Override
545 public Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray)
546 {
547 if (newCookiesArray == null)
548 {
549 return preExistentCookies;
550 }
551 final List<Cookie> cookiesThatAreReallyNew = new ArrayList<Cookie>(newCookiesArray.length);
552 final Cookie[] preExistentCookiesArray = (Cookie[]) preExistentCookies;
553 for (Cookie newCookie : newCookiesArray)
554 {
555 int newCookieInPreExistentArrayIndex = getCookieIndexFromCookiesArray(newCookie.getName(),
556 preExistentCookiesArray);
557 if (newCookieInPreExistentArrayIndex >= 0)
558 {
559
560 preExistentCookiesArray[newCookieInPreExistentArrayIndex] = newCookie;
561 }
562 else
563 {
564
565 cookiesThatAreReallyNew.add(newCookie);
566 }
567 }
568
569 return concatenateCookies(preExistentCookiesArray,
570 cookiesThatAreReallyNew.toArray(new Cookie[cookiesThatAreReallyNew.size()]));
571 }
572
573 @Override
574 public Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap)
575 {
576 if (newCookiesMap == null)
577 {
578 return putAndMergeCookie(preExistentCookies, (Cookie[]) null);
579 }
580 else
581 {
582 Cookie[] cookiesArray = new Cookie[newCookiesMap.size()];
583 int i = 0;
584 for (Entry<String, String> cookieEntry : newCookiesMap.entrySet())
585 {
586 Cookie cookie = new Cookie();
587 cookie.setName(cookieEntry.getKey());
588 cookie.setValue(cookieEntry.getValue());
589 cookiesArray[i++] = cookie;
590 }
591 return putAndMergeCookie(preExistentCookies, cookiesArray);
592 }
593 }
594
595 @Override
596 public Cookie[] asArrayOfCookies(Object cookiesObject)
597 {
598 if (cookiesObject == null)
599 {
600 return ZERO_COOKIES;
601 }
602 else
603 {
604 return (Cookie[]) cookiesObject;
605 }
606 }
607
608 },
609
610
611
612
613
614
615
616
617
618 MAP_STRING_STRING
619 {
620 @Override
621 public Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue)
622 {
623 final Map<String, String> cookieMap = (Map<String, String>) preExistentCookies;
624
625 cookieMap.put(cookieName, cookieValue);
626 return cookieMap;
627 }
628
629 @Override
630 public String getCookieValueFromCookies(Object cookiesObject, String cookieName)
631 {
632 return ((Map<String, String>) cookiesObject).get(cookieName);
633 }
634
635 @Override
636 public void addCookiesToClient(HttpClient client,
637 Object cookiesObject,
638 String policy,
639 MuleEvent event,
640 URI destinationUri)
641 {
642 Map<String, String> cookieMap = (Map<String, String>) cookiesObject;
643
644 client.getParams().setCookiePolicy(CookieHelper.getCookiePolicy(policy));
645
646 String host = destinationUri.getHost();
647 String path = destinationUri.getPath();
648 Iterator<String> keyIter = cookieMap.keySet().iterator();
649 while (keyIter.hasNext())
650 {
651 String key = keyIter.next();
652 String cookieValue = cookieMap.get(key);
653
654 final String value;
655 if (event != null)
656 {
657 value = event.getMuleContext()
658 .getExpressionManager()
659 .parse(cookieValue, event.getMessage());
660 }
661 else
662 {
663 value = cookieValue;
664 }
665
666 Cookie cookie = new Cookie(host, key, value, path, null, false);
667 client.getState().addCookie(cookie);
668 }
669
670 }
671
672 @Override
673 public Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray)
674 {
675 if (newCookiesArray == null)
676 {
677 return preExistentCookies;
678 }
679 for (Cookie cookie : newCookiesArray)
680 {
681 preExistentCookies = putAndMergeCookie(preExistentCookies, cookie.getName(),
682 cookie.getValue());
683 }
684 return preExistentCookies;
685 }
686
687 @Override
688 public Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap)
689 {
690 if (newCookiesMap == null)
691 {
692 return preExistentCookies;
693 }
694 for (Entry<String, String> cookieEntry : newCookiesMap.entrySet())
695 {
696 preExistentCookies = putAndMergeCookie(preExistentCookies, cookieEntry.getKey(),
697 cookieEntry.getValue());
698 }
699 return preExistentCookies;
700 }
701
702 @Override
703 public Cookie[] asArrayOfCookies(Object cookiesObject)
704 {
705 Map<String, String> cookieMap = (Map<String, String>) cookiesObject;
706 Cookie[] arrayOfCookies = new Cookie[cookieMap.size()];
707 int i = 0;
708 for (Entry<String, String> cookieEntry : cookieMap.entrySet())
709 {
710 Cookie cookie = new Cookie();
711 cookie.setName(cookieEntry.getKey());
712 cookie.setValue(cookieEntry.getValue());
713 arrayOfCookies[i++] = cookie;
714 }
715 return arrayOfCookies;
716 }
717
718 };
719
720 private static final Cookie[] ZERO_COOKIES = new Cookie[0];
721
722
723
724
725
726
727
728 public static CookieStorageType resolveCookieStorageType(Object cookiesObject)
729 {
730 if (cookiesObject == null || cookiesObject instanceof Cookie[])
731 {
732 return CookieStorageType.ARRAY_OF_COOKIES;
733 }
734 else if (cookiesObject instanceof Map)
735 {
736 return CookieStorageType.MAP_STRING_STRING;
737 }
738 else
739 {
740 throw new IllegalArgumentException("Invalid cookiesObject. Only " + Cookie.class + "[] and "
741 + Map.class + " are supported: " + cookiesObject);
742 }
743 }
744
745
746
747
748 public abstract Object putAndMergeCookie(Object preExistentCookies, String cookieName, String cookieValue);
749
750
751
752
753 public abstract Object putAndMergeCookie(Object preExistentCookies, Cookie[] newCookiesArray);
754
755
756
757
758 public abstract Object putAndMergeCookie(Object preExistentCookies, Map<String, String> newCookiesMap);
759
760
761
762
763 public abstract String getCookieValueFromCookies(Object cookiesObject, String cookieName);
764
765
766
767
768
769 public abstract void addCookiesToClient(HttpClient client,
770 Object cookiesObject,
771 String policy,
772 MuleEvent event,
773 URI destinationUri);
774
775
776
777
778 public abstract Cookie[] asArrayOfCookies(Object cookiesObject);
779 }