Source Code Cross Referenced for CookieJar.java in  » Testing » HttpUnit » com » meterware » httpunit » cookies » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » HttpUnit » com.meterware.httpunit.cookies 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.meterware.httpunit.cookies;
002:
003:        /********************************************************************************************************************
004:         * $Id: CookieJar.java,v 1.11 2004/09/29 17:15:26 russgold Exp $
005:         *
006:         * Copyright (c) 2002-2004, Russell Gold
007:         *
008:         * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
009:         * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
010:         * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
011:         * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
012:         *
013:         * The above copyright notice and this permission notice shall be included in all copies or substantial portions
014:         * of the Software.
015:         *
016:         * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
017:         * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018:         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
019:         * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020:         * DEALINGS IN THE SOFTWARE.
021:         *
022:         *******************************************************************************************************************/
023:        import java.io.IOException;
024:        import java.io.StreamTokenizer;
025:        import java.io.StringReader;
026:        import java.net.URL;
027:        import java.util.*;
028:
029:        /**
030:         * A collection of HTTP cookies, which can interact with cookie and set-cookie header values.
031:         *
032:         * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
033:         * @author <a href="mailto:drew.varner@oracle.com">Drew Varner</a>
034:         **/
035:        public class CookieJar {
036:
037:            private static final int DEFAULT_HEADER_SIZE = 80;
038:
039:            private ArrayList _cookies = new ArrayList();
040:            private ArrayList _globalCookies = new ArrayList();
041:            private CookiePress _press;
042:
043:            /**
044:             * Creates an empty cookie jar.
045:             */
046:            public CookieJar() {
047:                _press = new CookiePress(null);
048:            }
049:
050:            /**
051:             * Creates a cookie jar which is initially populated with cookies parsed from the <code>Set-Cookie</code> and
052:             * <code>Set-Cookie2</code> header fields.
053:             * <p>
054:             * Note that the parsing does not strictly follow the specifications, but
055:             * attempts to imitate the behavior of popular browsers. Specifically,
056:             * it allows cookie values to contain commas, which the
057:             * Netscape standard does not allow for, but which is required by some servers.
058:             * </p>
059:             */
060:            public CookieJar(CookieSource source) {
061:                _press = new CookiePress(source.getURL());
062:                findCookies(source.getHeaderFields("Set-Cookie"),
063:                        new RFC2109CookieRecipe());
064:                findCookies(source.getHeaderFields("Set-Cookie2"),
065:                        new RFC2965CookieRecipe());
066:            }
067:
068:            private void findCookies(String cookieHeader[], CookieRecipe recipe) {
069:                for (int i = 0; i < cookieHeader.length; i++) {
070:                    recipe.findCookies(cookieHeader[i]);
071:                }
072:            }
073:
074:            /**
075:             * Empties this cookie jar of all contents.
076:             */
077:            public void clear() {
078:                _cookies.clear();
079:                _globalCookies.clear();
080:            }
081:
082:            /**
083:             * Defines a cookie to be sent to the server on every request. This bypasses the normal mechanism by which only
084:             * certain cookies are sent based on their host and path.
085:             * @deprecated as of 1.6, use #putCookie
086:             **/
087:            public void addCookie(String name, String value) {
088:                _globalCookies.add(new Cookie(name, value));
089:            }
090:
091:            /**
092:             * Defines a cookie to be sent to the server on every request. This bypasses the normal mechanism by which only
093:             * certain cookies are sent based on their host and path.
094:             * @since 1.6
095:             **/
096:            public void putCookie(String name, String value) {
097:                for (Iterator iterator = _globalCookies.iterator(); iterator
098:                        .hasNext();) {
099:                    Cookie cookie = (Cookie) iterator.next();
100:                    if (name.equals(cookie.getName()))
101:                        iterator.remove();
102:                }
103:                _globalCookies.add(new Cookie(name, value));
104:            }
105:
106:            /**
107:             * Returns the name of all the active cookies in this cookie jar.
108:             **/
109:            public String[] getCookieNames() {
110:                final int numGlobalCookies = _globalCookies.size();
111:                String[] names = new String[_cookies.size() + numGlobalCookies];
112:                for (int i = 0; i < numGlobalCookies; i++) {
113:                    names[i] = ((Cookie) _globalCookies.get(i)).getName();
114:                }
115:                for (int i = numGlobalCookies; i < names.length; i++) {
116:                    names[i] = ((Cookie) _cookies.get(i - numGlobalCookies))
117:                            .getName();
118:                }
119:                return names;
120:            }
121:
122:            /**
123:             * Returns a collection containing all of the cookies in this jar.
124:             */
125:            public Collection getCookies() {
126:                final Collection collection = (Collection) _cookies.clone();
127:                collection.addAll(_globalCookies);
128:                return collection;
129:            }
130:
131:            /**
132:             * Returns the value of the specified cookie.
133:             **/
134:            public String getCookieValue(String name) {
135:                Cookie cookie = getCookie(name);
136:                return cookie == null ? null : cookie.getValue();
137:            }
138:
139:            /**
140:             * Returns the value of the specified cookie.
141:             **/
142:            public Cookie getCookie(String name) {
143:                if (name == null)
144:                    throw new IllegalArgumentException(
145:                            "getCookieValue: no name specified");
146:                for (Iterator iterator = _cookies.iterator(); iterator
147:                        .hasNext();) {
148:                    Cookie cookie = (Cookie) iterator.next();
149:                    if (name.equals(cookie.getName()))
150:                        return cookie;
151:                }
152:                for (Iterator iterator = _globalCookies.iterator(); iterator
153:                        .hasNext();) {
154:                    Cookie cookie = (Cookie) iterator.next();
155:                    if (name.equals(cookie.getName()))
156:                        return cookie;
157:                }
158:                return null;
159:            }
160:
161:            /**
162:             * Returns the value of the cookie header to be sent to the specified URL.
163:             * Will return null if no compatible cookie is defined.
164:             **/
165:            public String getCookieHeaderField(URL targetURL) {
166:                if (_cookies.isEmpty() && _globalCookies.isEmpty())
167:                    return null;
168:                StringBuffer sb = new StringBuffer(DEFAULT_HEADER_SIZE);
169:                HashSet restrictedCookies = new HashSet();
170:                for (Iterator i = _cookies.iterator(); i.hasNext();) {
171:                    Cookie cookie = (Cookie) i.next();
172:                    if (!cookie.mayBeSentTo(targetURL))
173:                        continue;
174:                    restrictedCookies.add(cookie.getName());
175:                    if (sb.length() != 0)
176:                        sb.append("; ");
177:                    sb.append(cookie.getName()).append('=').append(
178:                            cookie.getValue());
179:                }
180:                for (Iterator i = _globalCookies.iterator(); i.hasNext();) {
181:                    Cookie cookie = (Cookie) i.next();
182:                    if (restrictedCookies.contains(cookie.getName()))
183:                        continue;
184:                    if (sb.length() != 0)
185:                        sb.append("; ");
186:                    sb.append(cookie.getName()).append('=').append(
187:                            cookie.getValue());
188:                }
189:                return sb.length() == 0 ? null : sb.toString();
190:            }
191:
192:            /**
193:             * Updates the cookies maintained in this cookie jar with those in another cookie jar. Any duplicate cookies in
194:             * the new jar will replace those in this jar.
195:             **/
196:            public void updateCookies(CookieJar newJar) {
197:                for (Iterator i = newJar._cookies.iterator(); i.hasNext();) {
198:                    addUniqueCookie((Cookie) i.next());
199:                }
200:            }
201:
202:            /**
203:             * Add the cookie to this jar, replacing any previous matching cookie.
204:             */
205:            void addUniqueCookie(Cookie cookie) {
206:                _cookies.remove(cookie);
207:                _cookies.add(cookie);
208:            }
209:
210:            abstract class CookieRecipe {
211:
212:                /**
213:                 * Extracts cookies from a cookie header. Works in conjunction with a cookie press class, which actually creates
214:                 * the cookies and adds them to the jar as appropriate.
215:                 *
216:                 * 1. Parse the header into tokens, separated by ',' and ';' (respecting single and double quotes)
217:                 * 2. Process tokens from the end:
218:                 *    a. if the token contains an '=' we have a name/value pair. Add them to the cookie press, which
219:                 *       will decide if it is a cookie name or an attribute name.
220:                 *    b. if the token is a reserved word, flush the cookie press and continue.
221:                 *    c. otherwise, add the token to the cookie press, passing along the last character of the previous token.
222:                 */
223:                void findCookies(String cookieHeader) {
224:                    Vector tokens = getCookieTokens(cookieHeader);
225:
226:                    for (int i = tokens.size() - 1; i >= 0; i--) {
227:                        String token = (String) tokens.elementAt(i);
228:
229:                        int equalsIndex = getEqualsIndex(token);
230:                        if (equalsIndex != -1) {
231:                            _press.addTokenWithEqualsSign(this , token,
232:                                    equalsIndex);
233:                        } else if (isCookieReservedWord(token)) {
234:                            _press.clear();
235:                        } else {
236:                            _press.addToken(token, lastCharOf((i == 0) ? ""
237:                                    : (String) tokens.elementAt(i - 1)));
238:                        }
239:                    }
240:                }
241:
242:                private char lastCharOf(String string) {
243:                    return (string.length() == 0) ? ' ' : string.charAt(string
244:                            .length() - 1);
245:                }
246:
247:                /**
248:                 * Returns the index (if any) of the equals sign separating a cookie name from the its value.
249:                 * Equals signs at the end of the token are ignored in this calculation, since they may be
250:                 * part of a Base64-encoded value.
251:                 */
252:                private int getEqualsIndex(String token) {
253:                    if (!token.endsWith("==")) {
254:                        return token.indexOf('=');
255:                    } else {
256:                        return getEqualsIndex(token.substring(0,
257:                                token.length() - 2));
258:                    }
259:                }
260:
261:                /**
262:                 * Tokenizes a cookie header and returns the tokens in a
263:                 * <code>Vector</code>.
264:                 **/
265:                private Vector getCookieTokens(String cookieHeader) {
266:                    StringReader sr = new StringReader(cookieHeader);
267:                    StreamTokenizer st = new StreamTokenizer(sr);
268:                    Vector tokens = new Vector();
269:
270:                    // clear syntax tables of the StreamTokenizer
271:                    st.resetSyntax();
272:
273:                    // set all characters as word characters
274:                    st.wordChars(0, Character.MAX_VALUE);
275:
276:                    // set up characters for quoting
277:                    st.quoteChar('"'); //double quotes
278:                    st.quoteChar('\''); //single quotes
279:
280:                    // set up characters to separate tokens
281:                    st.whitespaceChars(59, 59); //semicolon
282:                    st.whitespaceChars(44, 44); //comma
283:
284:                    try {
285:                        while (st.nextToken() != StreamTokenizer.TT_EOF) {
286:                            tokens.addElement(st.sval.trim());
287:                        }
288:                    } catch (IOException ioe) {
289:                        // this will never happen with a StringReader
290:                    }
291:                    sr.close();
292:                    return tokens;
293:                }
294:
295:                abstract protected boolean isCookieAttribute(
296:                        String stringLowercase);
297:
298:                abstract protected boolean isCookieReservedWord(String token);
299:
300:            }
301:
302:            class CookiePress {
303:
304:                private StringBuffer _value = new StringBuffer();
305:                private HashMap _attributes = new HashMap();
306:                private URL _sourceURL;
307:
308:                public CookiePress(URL sourceURL) {
309:                    _sourceURL = sourceURL;
310:                }
311:
312:                void clear() {
313:                    _value.setLength(0);
314:                    _attributes.clear();
315:                }
316:
317:                void addToken(String token, char lastChar) {
318:                    _value.insert(0, token);
319:                    if (lastChar != '=')
320:                        _value.insert(0, ',');
321:                }
322:
323:                void addTokenWithEqualsSign(CookieRecipe recipe, String token,
324:                        int equalsIndex) {
325:                    String name = token.substring(0, equalsIndex).trim();
326:                    _value.insert(0, token.substring(equalsIndex + 1).trim());
327:                    if (recipe.isCookieAttribute(name.toLowerCase())) {
328:                        _attributes.put(name.toLowerCase(), _value.toString());
329:                    } else {
330:                        addCookieIfValid(new Cookie(name, _value.toString(),
331:                                _attributes));
332:                        _attributes.clear();
333:                    }
334:                    _value.setLength(0);
335:                }
336:
337:                private void addCookieIfValid(Cookie cookie) {
338:                    if (acceptCookie(cookie))
339:                        addUniqueCookie(cookie);
340:                }
341:
342:                private boolean acceptCookie(Cookie cookie) {
343:                    if (cookie.getPath() == null) {
344:                        cookie.setPath(getParentPath(_sourceURL.getPath()));
345:                    } else {
346:                        int status = getPathAttributeStatus(cookie.getPath(),
347:                                _sourceURL.getPath());
348:                        if (status != CookieListener.ACCEPTED) {
349:                            reportCookieRejected(status, cookie.getPath(),
350:                                    cookie.getName());
351:                            return false;
352:                        }
353:                    }
354:
355:                    if (cookie.getDomain() == null) {
356:                        cookie.setDomain(_sourceURL.getHost());
357:                    } else if (!CookieProperties.isDomainMatchingStrict()
358:                            && cookie.getDomain().equalsIgnoreCase(
359:                                    _sourceURL.getHost())) {
360:                        cookie.setDomain(_sourceURL.getHost());
361:                    } else {
362:                        int status = getDomainAttributeStatus(cookie
363:                                .getDomain(), _sourceURL.getHost());
364:                        if (status != CookieListener.ACCEPTED) {
365:                            reportCookieRejected(status, cookie.getDomain(),
366:                                    cookie.getName());
367:                            return false;
368:                        }
369:                    }
370:
371:                    return true;
372:                }
373:
374:                private String getParentPath(String path) {
375:                    int rightmostSlashIndex = path.lastIndexOf('/');
376:                    return rightmostSlashIndex < 0 ? "/" : path.substring(0,
377:                            rightmostSlashIndex);
378:                }
379:
380:                private int getPathAttributeStatus(String pathAttribute,
381:                        String sourcePath) {
382:                    if (!CookieProperties.isPathMatchingStrict()
383:                            || sourcePath.length() == 0
384:                            || sourcePath.startsWith(pathAttribute)) {
385:                        return CookieListener.ACCEPTED;
386:                    } else {
387:                        return CookieListener.PATH_NOT_PREFIX;
388:                    }
389:                }
390:
391:                private int getDomainAttributeStatus(String domainAttribute,
392:                        String sourceHost) {
393:                    if (!domainAttribute.startsWith("."))
394:                        domainAttribute = '.' + domainAttribute;
395:
396:                    if (domainAttribute.lastIndexOf('.') == 0) {
397:                        return CookieListener.DOMAIN_ONE_DOT;
398:                    } else if (!sourceHost.endsWith(domainAttribute)) {
399:                        return CookieListener.DOMAIN_NOT_SOURCE_SUFFIX;
400:                    } else if (CookieProperties.isDomainMatchingStrict()
401:                            && sourceHost.lastIndexOf(domainAttribute) > sourceHost
402:                                    .indexOf('.')) {
403:                        return CookieListener.DOMAIN_TOO_MANY_LEVELS;
404:                    } else {
405:                        return CookieListener.ACCEPTED;
406:                    }
407:                }
408:
409:                private boolean reportCookieRejected(int reason,
410:                        String attribute, String source) {
411:                    CookieProperties.reportCookieRejected(reason, attribute,
412:                            source);
413:                    return false;
414:                }
415:
416:            }
417:
418:            /**
419:             * Parses cookies according to
420:             * <a href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a>
421:             *
422:             * <br />
423:             * These cookies come from the <code>Set-Cookie:</code> header
424:             **/
425:            class RFC2109CookieRecipe extends CookieRecipe {
426:
427:                protected boolean isCookieAttribute(String stringLowercase) {
428:                    return stringLowercase.equals("path")
429:                            || stringLowercase.equals("domain")
430:                            || stringLowercase.equals("expires")
431:                            || stringLowercase.equals("comment")
432:                            || stringLowercase.equals("max-age")
433:                            || stringLowercase.equals("version");
434:                }
435:
436:                protected boolean isCookieReservedWord(String token) {
437:                    return token.equalsIgnoreCase("secure");
438:                }
439:            }
440:
441:            /**
442:             * Parses cookies according to
443:             * <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>
444:             *
445:             * <br />
446:             * These cookies come from the <code>Set-Cookie2:</code> header
447:             **/
448:            class RFC2965CookieRecipe extends CookieRecipe {
449:
450:                protected boolean isCookieAttribute(String stringLowercase) {
451:                    return stringLowercase.equals("path")
452:                            || stringLowercase.equals("domain")
453:                            || stringLowercase.equals("comment")
454:                            || stringLowercase.equals("commenturl")
455:                            || stringLowercase.equals("max-age")
456:                            || stringLowercase.equals("version")
457:                            || stringLowercase.equals("$version")
458:                            || stringLowercase.equals("port");
459:                }
460:
461:                protected boolean isCookieReservedWord(String token) {
462:                    return token.equalsIgnoreCase("discard")
463:                            || token.equalsIgnoreCase("secure");
464:                }
465:            }
466:
467:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.