1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
27 package org.apache.http.pool;
28
29 import java.util.concurrent.TimeUnit;
30
31 import org.apache.http.annotation.GuardedBy;
32 import org.apache.http.annotation.ThreadSafe;
33
34 /**
35 * Pool entry containing a pool connection object along with its route.
36 * <p/>
37 * The connection contained by the pool entry may have an expiration time which
38 * can be either set upon construction time or updated with
39 * the {@link #updateExpiry(long, TimeUnit)}.
40 * <p/>
41 * Pool entry may also have an object associated with it that represents
42 * a connection state (usually a security principal or a unique token identifying
43 * the user whose credentials have been used while establishing the connection).
44 *
45 * @param <T> the route type that represents the opposite endpoint of a pooled
46 * connection.
47 * @param <C> the connection type.
48 * @since 4.2
49 */
50 @ThreadSafe
51 public abstract class PoolEntry<T, C> {
52
53 private final String id;
54 private final T route;
55 private final C conn;
56 private final long created;
57 private final long validUnit;
58
59 @GuardedBy("this")
60 private long updated;
61
62 @GuardedBy("this")
63 private long expiry;
64
65 private volatile Object state;
66
67 /**
68 * Creates new <tt>PoolEntry</tt> instance.
69 *
70 * @param id unique identifier of the pool entry. May be <code>null</code>.
71 * @param route route to the opposite endpoint.
72 * @param conn the connection.
73 * @param timeToLive maximum time to live. May be zero if the connection
74 * does not have an expiry deadline.
75 * @param tunit time unit.
76 */
77 public PoolEntry(final String id, final T route, final C conn,
78 final long timeToLive, final TimeUnit tunit) {
79 super();
80 if (route == null) {
81 throw new IllegalArgumentException("Route may not be null");
82 }
83 if (conn == null) {
84 throw new IllegalArgumentException("Connection may not be null");
85 }
86 if (tunit == null) {
87 throw new IllegalArgumentException("Time unit may not be null");
88 }
89 this.id = id;
90 this.route = route;
91 this.conn = conn;
92 this.created = System.currentTimeMillis();
93 if (timeToLive > 0) {
94 this.validUnit = this.created + tunit.toMillis(timeToLive);
95 } else {
96 this.validUnit = Long.MAX_VALUE;
97 }
98 this.expiry = this.validUnit;
99 }
100
101 /**
102 * Creates new <tt>PoolEntry</tt> instance without an expiry deadline.
103 *
104 * @param id unique identifier of the pool entry. May be <code>null</code>.
105 * @param route route to the opposite endpoint.
106 * @param conn the connection.
107 */
108 public PoolEntry(final String id, final T route, final C conn) {
109 this(id, route, conn, 0, TimeUnit.MILLISECONDS);
110 }
111
112 public String getId() {
113 return this.id;
114 }
115
116 public T getRoute() {
117 return this.route;
118 }
119
120 public C getConnection() {
121 return this.conn;
122 }
123
124 public long getCreated() {
125 return this.created;
126 }
127
128 public long getValidUnit() {
129 return this.validUnit;
130 }
131
132 public Object getState() {
133 return this.state;
134 }
135
136 public void setState(final Object state) {
137 this.state = state;
138 }
139
140 public synchronized long getUpdated() {
141 return this.updated;
142 }
143
144 public synchronized long getExpiry() {
145 return this.expiry;
146 }
147
148 public synchronized void updateExpiry(final long time, final TimeUnit tunit) {
149 if (tunit == null) {
150 throw new IllegalArgumentException("Time unit may not be null");
151 }
152 this.updated = System.currentTimeMillis();
153 long newExpiry;
154 if (time > 0) {
155 newExpiry = this.updated + tunit.toMillis(time);
156 } else {
157 newExpiry = Long.MAX_VALUE;
158 }
159 this.expiry = Math.min(newExpiry, this.validUnit);
160 }
161
162 public synchronized boolean isExpired(final long now) {
163 return now >= this.expiry;
164 }
165
166 /**
167 * Invalidates the pool entry and closes the pooled connection associated
168 * with it.
169 */
170 public abstract void close();
171
172 /**
173 * Returns <code>true</code> if the pool entry has been invalidated.
174 */
175 public abstract boolean isClosed();
176
177 @Override
178 public String toString() {
179 StringBuilder buffer = new StringBuilder();
180 buffer.append("[id:");
181 buffer.append(this.id);
182 buffer.append("][route:");
183 buffer.append(this.route);
184 buffer.append("][state:");
185 buffer.append(this.state);
186 buffer.append("]");
187 return buffer.toString();
188 }
189
190 }