1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.execchain;
29
30 import java.io.Closeable;
31 import java.io.IOException;
32 import java.util.concurrent.TimeUnit;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.http.HttpClientConnection;
36 import org.apache.http.annotation.ThreadSafe;
37 import org.apache.http.concurrent.Cancellable;
38 import org.apache.http.conn.ConnectionReleaseTrigger;
39 import org.apache.http.conn.HttpClientConnectionManager;
40
41
42
43
44
45
46 @ThreadSafe
47 class ConnectionHolder implements ConnectionReleaseTrigger, Cancellable, Closeable {
48
49 private final Log log;
50
51 private final HttpClientConnectionManager manager;
52 private final HttpClientConnection managedConn;
53 private volatile boolean reusable;
54 private volatile Object state;
55 private volatile long validDuration;
56 private volatile TimeUnit tunit;
57
58 private volatile boolean released;
59
60 public ConnectionHolder(
61 final Log log,
62 final HttpClientConnectionManager manager,
63 final HttpClientConnection managedConn) {
64 super();
65 this.log = log;
66 this.manager = manager;
67 this.managedConn = managedConn;
68 }
69
70 public boolean isReusable() {
71 return this.reusable;
72 }
73
74 public void markReusable() {
75 this.reusable = true;
76 }
77
78 public void markNonReusable() {
79 this.reusable = false;
80 }
81
82 public void setState(final Object state) {
83 this.state = state;
84 }
85
86 public void setValidFor(final long duration, final TimeUnit tunit) {
87 synchronized (this.managedConn) {
88 this.validDuration = duration;
89 this.tunit = tunit;
90 }
91 }
92
93 public void releaseConnection() {
94 synchronized (this.managedConn) {
95 if (this.released) {
96 return;
97 }
98 this.released = true;
99 if (this.reusable) {
100 this.manager.releaseConnection(this.managedConn,
101 this.state, this.validDuration, this.tunit);
102 } else {
103 try {
104 this.managedConn.close();
105 log.debug("Connection discarded");
106 } catch (final IOException ex) {
107 if (this.log.isDebugEnabled()) {
108 this.log.debug(ex.getMessage(), ex);
109 }
110 } finally {
111 this.manager.releaseConnection(
112 this.managedConn, null, 0, TimeUnit.MILLISECONDS);
113 }
114 }
115 }
116 }
117
118 public void abortConnection() {
119 synchronized (this.managedConn) {
120 if (this.released) {
121 return;
122 }
123 this.released = true;
124 try {
125 this.managedConn.shutdown();
126 log.debug("Connection discarded");
127 } catch (final IOException ex) {
128 if (this.log.isDebugEnabled()) {
129 this.log.debug(ex.getMessage(), ex);
130 }
131 } finally {
132 this.manager.releaseConnection(
133 this.managedConn, null, 0, TimeUnit.MILLISECONDS);
134 }
135 }
136 }
137
138 public boolean cancel() {
139 final boolean alreadyReleased = this.released;
140 log.debug("Cancelling request execution");
141 abortConnection();
142 return !alreadyReleased;
143 }
144
145 public boolean isReleased() {
146 return this.released;
147 }
148
149 public void close() throws IOException {
150 abortConnection();
151 }
152
153 }