1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package java.net; 18 19import java.util.ArrayList; 20import java.util.Collections; 21import java.util.HashMap; 22import java.util.Iterator; 23import java.util.List; 24import java.util.Map; 25 26/** 27 * An in-memory cookie store. 28 */ 29final class CookieStoreImpl implements CookieStore { 30 31 /** this map may have null keys! */ 32 private final Map<URI, List<HttpCookie>> map = new HashMap<URI, List<HttpCookie>>(); 33 34 public synchronized void add(URI uri, HttpCookie cookie) { 35 if (cookie == null) { 36 throw new NullPointerException("cookie == null"); 37 } 38 39 uri = cookiesUri(uri); 40 List<HttpCookie> cookies = map.get(uri); 41 if (cookies == null) { 42 cookies = new ArrayList<HttpCookie>(); 43 map.put(uri, cookies); 44 } else { 45 cookies.remove(cookie); 46 } 47 cookies.add(cookie); 48 } 49 50 private URI cookiesUri(URI uri) { 51 if (uri == null) { 52 return null; 53 } 54 try { 55 return new URI("http", uri.getHost(), null, null); 56 } catch (URISyntaxException e) { 57 return uri; // probably a URI with no host 58 } 59 } 60 61 public synchronized List<HttpCookie> get(URI uri) { 62 if (uri == null) { 63 throw new NullPointerException("uri == null"); 64 } 65 66 List<HttpCookie> result = new ArrayList<HttpCookie>(); 67 68 // get cookies associated with given URI. If none, returns an empty list 69 List<HttpCookie> cookiesForUri = map.get(uri); 70 if (cookiesForUri != null) { 71 for (Iterator<HttpCookie> i = cookiesForUri.iterator(); i.hasNext(); ) { 72 HttpCookie cookie = i.next(); 73 if (cookie.hasExpired()) { 74 i.remove(); // remove expired cookies 75 } else { 76 result.add(cookie); 77 } 78 } 79 } 80 81 // get all cookies that domain matches the URI 82 for (Map.Entry<URI, List<HttpCookie>> entry : map.entrySet()) { 83 if (uri.equals(entry.getKey())) { 84 continue; // skip the given URI; we've already handled it 85 } 86 87 List<HttpCookie> entryCookies = entry.getValue(); 88 for (Iterator<HttpCookie> i = entryCookies.iterator(); i.hasNext(); ) { 89 HttpCookie cookie = i.next(); 90 if (!HttpCookie.domainMatches(cookie.getDomain(), uri.getHost())) { 91 continue; 92 } 93 if (cookie.hasExpired()) { 94 i.remove(); // remove expired cookies 95 } else if (!result.contains(cookie)) { 96 result.add(cookie); 97 } 98 } 99 } 100 101 return Collections.unmodifiableList(result); 102 } 103 104 public synchronized List<HttpCookie> getCookies() { 105 List<HttpCookie> result = new ArrayList<HttpCookie>(); 106 for (List<HttpCookie> list : map.values()) { 107 for (Iterator<HttpCookie> i = list.iterator(); i.hasNext(); ) { 108 HttpCookie cookie = i.next(); 109 if (cookie.hasExpired()) { 110 i.remove(); // remove expired cookies 111 } else if (!result.contains(cookie)) { 112 result.add(cookie); 113 } 114 } 115 } 116 return Collections.unmodifiableList(result); 117 } 118 119 public synchronized List<URI> getURIs() { 120 List<URI> result = new ArrayList<URI>(map.keySet()); 121 result.remove(null); // sigh 122 return Collections.unmodifiableList(result); 123 } 124 125 public synchronized boolean remove(URI uri, HttpCookie cookie) { 126 if (cookie == null) { 127 throw new NullPointerException("cookie == null"); 128 } 129 130 List<HttpCookie> cookies = map.get(cookiesUri(uri)); 131 if (cookies != null) { 132 return cookies.remove(cookie); 133 } else { 134 return false; 135 } 136 } 137 138 public synchronized boolean removeAll() { 139 boolean result = !map.isEmpty(); 140 map.clear(); 141 return result; 142 } 143} 144