This project has retired. For details please refer to its Attic page.
CmisCookieManager xref

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  /*
20   * This class has been taken from Apache Harmony (http://harmony.apache.org/) 
21   * and has been modified to work with OpenCMIS.
22   */
23  package org.apache.chemistry.opencmis.client.bindings.spi.cookies;
24  
25  import java.io.IOException;
26  import java.io.Serializable;
27  import java.net.URI;
28  import java.net.URISyntaxException;
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.concurrent.locks.ReentrantReadWriteLock;
35  
36  import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  /**
41   * Cookie Manager.
42   * 
43   * This implementation conforms to RFC 2965, section 3.3.
44   */
45  public class CmisCookieManager implements Serializable {
46      private static final long serialVersionUID = 1L;
47  
48      private static final Log LOG = LogFactory.getLog(CmisCookieManager.class.getName());
49  
50      private static final String VERSION_ZERO_HEADER = "Set-cookie";
51      private static final String VERSION_ONE_HEADER = "Set-cookie2";
52  
53      private final CmisCookieStoreImpl store;
54      private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
55  
56      /**
57       * Constructs a new cookie manager.
58       */
59      public CmisCookieManager() {
60          store = new CmisCookieStoreImpl();
61      }
62  
63      /**
64       * Searchs and gets all cookies in the cache by the specified uri in the
65       * request header.
66       * 
67       * @param uri
68       *            the specified uri to search for
69       * @param requestHeaders
70       *            a list of request headers
71       * @return a map that record all such cookies, the map is unchangeable
72       */
73      public Map<String, List<String>> get(String url, Map<String, List<String>> requestHeaders) {
74          if (url == null || requestHeaders == null) {
75              throw new IllegalArgumentException("URL or headers are null!");
76          }
77  
78          URI uri;
79          try {
80              uri = new URI(url);
81          } catch (URISyntaxException e) {
82              throw new CmisConnectionException(e.getMessage(), e);
83          }
84  
85          lock.writeLock().lock();
86          try {
87              List<CmisHttpCookie> cookies = store.get(uri);
88              for (int i = 0; i < cookies.size(); i++) {
89                  CmisHttpCookie cookie = cookies.get(i);
90                  String uriPath = uri.getPath();
91                  String cookiePath = cookie.getPath();
92                  // if the uri's path does not path-match cookie's path, remove
93                  // cookies from the list
94                  if (cookiePath == null || uriPath.length() == 0 || !uriPath.startsWith(cookiePath)) {
95                      cookies.remove(i);
96                  }
97              }
98  
99              Map<String, List<String>> map = getCookieMap(cookies, requestHeaders);
100 
101             if (LOG.isDebugEnabled()) {
102                 if (map != null && !map.isEmpty()) {
103                     LOG.debug("Setting cookies for URL " + url + ": " + map.get("Cookie"));
104                 }
105             }
106 
107             return map;
108         } finally {
109             lock.writeLock().unlock();
110         }
111     }
112 
113     private static Map<String, List<String>> getCookieMap(List<CmisHttpCookie> cookies,
114             Map<String, List<String>> requestHeaders) {
115         HashMap<String, List<String>> map = new HashMap<String, List<String>>();
116         ArrayList<String> cookieStr = new ArrayList<String>();
117         // If all cookies are version 1, add a "$Version="1"" header
118         boolean versionOne = true;
119         for (CmisHttpCookie cookie : cookies) {
120             if (cookie.getVersion() == 0) {
121                 versionOne = false;
122                 break;
123             }
124         }
125         if (versionOne && !cookies.isEmpty()) {
126             cookieStr.add("$Version=\"1\"");
127         }
128         // add every cookie's string representation into map
129         for (CmisHttpCookie cookie : cookies) {
130             cookieStr.add(cookie.toString());
131         }
132 
133         if (cookieStr.isEmpty()) {
134             return Collections.emptyMap();
135         }
136 
137         map.put("Cookie", cookieStr);
138         return map;
139     }
140 
141     /**
142      * Sets cookies according to uri and responseHeaders
143      * 
144      * @param uri
145      *            the specified uri
146      * @param responseHeaders
147      *            a list of request headers
148      * @throws IOException
149      *             if some error of I/O operation occurs
150      */
151     public void put(String url, Map<String, List<String>> responseHeaders) {
152         if (url == null || responseHeaders == null) {
153             throw new IllegalArgumentException("URL or headers are null!");
154         }
155 
156         URI uri;
157         try {
158             uri = new URI(url);
159         } catch (URISyntaxException e) {
160             throw new CmisConnectionException(e.getMessage(), e);
161         }
162 
163         lock.writeLock().lock();
164         try {
165             // parse and construct cookies according to the map
166             List<CmisHttpCookie> cookies = parseCookie(responseHeaders);
167             for (CmisHttpCookie cookie : cookies) {
168                 if (cookie.getDomain() == null) {
169                     cookie.setDomain(uri.getHost());
170                 }
171                 if (cookie.getPath() == null) {
172                     cookie.setPath("/");
173                 }
174                 store.add(uri, cookie);
175             }
176 
177             if (LOG.isDebugEnabled()) {
178                 if (!cookies.isEmpty()) {
179                     LOG.debug("Retrieved cookies for URL " + url + ": " + cookies);
180                 }
181             }
182         } finally {
183             lock.writeLock().unlock();
184         }
185     }
186 
187     private static List<CmisHttpCookie> parseCookie(Map<String, List<String>> responseHeaders) {
188         List<CmisHttpCookie> cookies = new ArrayList<CmisHttpCookie>();
189         for (Map.Entry<String, List<String>> entry : responseHeaders.entrySet()) {
190             String key = entry.getKey();
191             // Only "Set-cookie" and "Set-cookie2" pair will be parsed
192             if (key != null && (key.equalsIgnoreCase(VERSION_ZERO_HEADER) || key.equalsIgnoreCase(VERSION_ONE_HEADER))) {
193                 // parse list elements one by one
194                 for (String cookieStr : entry.getValue()) {
195                     try {
196                         for (CmisHttpCookie cookie : CmisHttpCookie.parse(cookieStr)) {
197                             cookies.add(cookie);
198                         }
199                     } catch (IllegalArgumentException e) {
200                         // this string is invalid, jump to the next one.
201                     }
202                 }
203             }
204         }
205 
206         return cookies;
207     }
208 
209     /**
210      * Gets current cookie store.
211      * 
212      * @return the cookie store currently used by cookie manager.
213      */
214     public CmisCookieStoreImpl getCookieStore() {
215         return store;
216     }
217 }