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