2
* Copyright 2005-2012 Restlet S.A.S.
4
* The contents of this file are subject to the terms of one of the following
5
* open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
6
* 1.0 (the "Licenses"). You can select the license that you prefer but you may
7
* not use this file except in compliance with one of these Licenses.
9
* You can obtain a copy of the Apache 2.0 license at
10
* http://www.opensource.org/licenses/apache-2.0
12
* You can obtain a copy of the LGPL 3.0 license at
13
* http://www.opensource.org/licenses/lgpl-3.0
15
* You can obtain a copy of the LGPL 2.1 license at
16
* http://www.opensource.org/licenses/lgpl-2.1
18
* You can obtain a copy of the CDDL 1.0 license at
19
* http://www.opensource.org/licenses/cddl1
21
* You can obtain a copy of the EPL 1.0 license at
22
* http://www.opensource.org/licenses/eclipse-1.0
24
* See the Licenses for the specific language governing permissions and
25
* limitations under the Licenses.
27
* Alternatively, you can obtain a royalty free commercial license with less
28
* limitations, transferable or non-transferable, directly at
29
* http://www.restlet.com/products/restlet-framework
31
* Restlet is a registered trademark of Restlet S.A.S.
36
import java.util.Date;
37
import java.util.List;
39
import java.util.concurrent.CopyOnWriteArrayList;
40
import java.util.concurrent.CopyOnWriteArraySet;
42
import org.restlet.data.AuthenticationInfo;
43
import org.restlet.data.ChallengeRequest;
44
import org.restlet.data.CookieSetting;
45
import org.restlet.data.Dimension;
46
import org.restlet.data.Method;
47
import org.restlet.data.Reference;
48
import org.restlet.data.ServerInfo;
49
import org.restlet.data.Status;
50
import org.restlet.engine.util.CookieSettingSeries;
51
import org.restlet.util.Series;
54
* Generic response sent by server connectors. It is then received by client
55
* connectors. Responses are uniform across all types of connectors, protocols
58
* @see org.restlet.Request
59
* @see org.restlet.Uniform
60
* @author Jerome Louvel
62
public class Response extends Message {
63
private static final ThreadLocal<Response> CURRENT = new ThreadLocal<Response>();
66
* Returns the response associated to the current thread.
68
* Warning: this method should only be used under duress. You should by
69
* default prefer obtaining the current context using methods such as
70
* {@link org.restlet.resource.Resource#getResponse()}.
72
* This variable is stored internally as a thread local variable and updated
73
* each time a call is handled by a Restlet via the
74
* {@link Restlet#handle(org.restlet.Request, org.restlet.Response)} method.
76
* @return The current context.
78
public static Response getCurrent() {
83
* Sets the response associated with the current thread.
86
* The thread's response.
88
public static void setCurrent(Response response) {
89
CURRENT.set(response);
93
* Estimated amount of time since a response was generated or revalidated by
96
private volatile int age;
98
/** The set of methods allowed on the requested resource. */
99
private volatile Set<Method> allowedMethods;
102
* The authentication information sent by an origin server to a client in
103
* the case of a successful authentication attempt.
105
private volatile AuthenticationInfo authenticationInfo;
107
/** Indicates if the response should be automatically committed. */
108
private volatile boolean autoCommitting;
110
/** The authentication requests sent by an origin server to a client. */
111
private volatile List<ChallengeRequest> challengeRequests;
113
/** Indicates if the response has been committed. */
114
private volatile boolean committed;
116
/** The cookie settings provided by the server. */
117
private volatile Series<CookieSetting> cookieSettings;
119
/** The set of dimensions on which the response entity may vary. */
120
private volatile Set<Dimension> dimensions;
122
/** The reference used for redirections or creations. */
123
private volatile Reference locationRef;
125
/** The authentication requests sent by a proxy to a client. */
126
private volatile List<ChallengeRequest> proxyChallengeRequests;
128
/** The associated request. */
129
private volatile Request request;
132
* Indicates how long the service is expected to be unavailable to the
135
private volatile Date retryAfter;
137
/** The server-specific information. */
138
private volatile ServerInfo serverInfo;
141
private volatile Status status;
147
* The request associated to this response.
149
public Response(Request request) {
151
this.allowedMethods = null;
152
this.autoCommitting = true;
153
this.challengeRequests = null;
154
this.cookieSettings = null;
155
this.committed = false;
156
this.dimensions = null;
157
this.locationRef = null;
158
this.proxyChallengeRequests = null;
159
this.request = request;
160
this.retryAfter = null;
161
this.serverInfo = null;
162
this.status = Status.SUCCESS_OK;
166
* Ask the connector to abort the related network connection, for example
167
* immediately closing the socket.
169
public void abort() {
170
getRequest().abort();
174
* Asks the server connector to immediately commit the given response,
175
* making it ready to be sent back to the client. Note that all server
176
* connectors don't necessarily support this feature.
178
public void commit() {
179
getRequest().commit(this);
183
* Returns the estimated amount of time since a response was generated or
184
* revalidated by the origin server. Origin servers should leave the 0
185
* default value. Only caches are expected to set this property.<br>
187
* Note that when used with HTTP connectors, this property maps to the "Age"
190
* @return The response age.
192
public int getAge() {
197
* Returns the modifiable set of methods allowed on the requested resource.
198
* This property only has to be updated when a status
199
* CLIENT_ERROR_METHOD_NOT_ALLOWED is set. Creates a new instance if no one
202
* Note that when used with HTTP connectors, this property maps to the
205
* @return The set of allowed methods.
207
public Set<Method> getAllowedMethods() {
208
// Lazy initialization with double-check.
209
Set<Method> a = this.allowedMethods;
211
synchronized (this) {
212
a = this.allowedMethods;
214
this.allowedMethods = a = new CopyOnWriteArraySet<Method>();
222
* Returns information sent by an origin server related to an successful
223
* authentication attempt. If none is available, null is returned.<br>
225
* Note that when used with HTTP connectors, this property maps to the
226
* "Authentication-Info" header.
228
* @return The authentication information provided by the server.
230
public AuthenticationInfo getAuthenticationInfo() {
231
return this.authenticationInfo;
235
* Returns the list of authentication requests sent by an origin server to a
236
* client. If none is available, an empty list is returned.<br>
238
* Note that when used with HTTP connectors, this property maps to the
239
* "WWW-Authenticate" header.
241
* @return The list of authentication requests.
243
public List<ChallengeRequest> getChallengeRequests() {
244
// Lazy initialization with double-check.
245
List<ChallengeRequest> cr = this.challengeRequests;
247
synchronized (this) {
248
cr = this.challengeRequests;
250
this.challengeRequests = cr = new CopyOnWriteArrayList<ChallengeRequest>();
258
* Returns the modifiable series of cookie settings provided by the server.
259
* Creates a new instance if no one has been set.<br>
261
* Note that when used with HTTP connectors, this property maps to the
262
* "Set-Cookie" and "Set-Cookie2" headers.
264
* @return The cookie settings provided by the server.
266
public Series<CookieSetting> getCookieSettings() {
267
// Lazy initialization with double-check.
268
Series<CookieSetting> c = this.cookieSettings;
270
synchronized (this) {
271
c = this.cookieSettings;
273
this.cookieSettings = c = new CookieSettingSeries();
281
* Returns the modifiable set of selecting dimensions on which the response
282
* entity may vary. If some server-side content negotiation is done, this
283
* set should be properly updated, other it can be left empty. Creates a new
284
* instance if no one has been set.<br>
286
* Note that when used with HTTP connectors, this property maps to the
289
* @return The set of dimensions on which the response entity may vary.
291
public Set<Dimension> getDimensions() {
292
if (this.dimensions == null) {
293
this.dimensions = new CopyOnWriteArraySet<Dimension>();
295
return this.dimensions;
299
* Returns the location reference. This is the reference that the client
300
* should follow for redirections or resource creations.<br>
302
* Note that when used with HTTP connectors, this property maps to the
305
* @return The redirection reference.
307
public Reference getLocationRef() {
308
return this.locationRef;
312
* Returns the list of authentication requests sent by an origin server to a
313
* client. If none is available, an empty list is returned.<br>
315
* Note that when used with HTTP connectors, this property maps to the
316
* "Proxy-Authenticate" header.
318
* @return The list of authentication requests.
320
public List<ChallengeRequest> getProxyChallengeRequests() {
321
// Lazy initialization with double-check.
322
List<ChallengeRequest> cr = this.proxyChallengeRequests;
324
synchronized (this) {
325
cr = this.proxyChallengeRequests;
327
this.proxyChallengeRequests = cr = new CopyOnWriteArrayList<ChallengeRequest>();
335
* Returns the associated request
337
* @return The associated request
339
public Request getRequest() {
344
* Indicates how long the service is expected to be unavailable to the
345
* requesting client. Default value is null.<br>
347
* Note that when used with HTTP connectors, this property maps to the
348
* "Retry-After" header.
350
* @return Date after with a retry attempt could occur.
352
public Date getRetryAfter() {
357
* Returns the server-specific information. Creates a new instance if no one
360
* @return The server-specific information.
362
public ServerInfo getServerInfo() {
363
// Lazy initialization with double-check.
364
ServerInfo s = this.serverInfo;
366
synchronized (this) {
369
this.serverInfo = s = new ServerInfo();
377
* Returns the status.
379
* @return The status.
381
public Status getStatus() {
386
* Indicates if the response should be automatically committed. When
387
* processing a request on the server-side, setting this property to 'false'
388
* let you ask to the server connector to wait before sending the response
389
* back to the client when the initial calling thread returns. This will let
390
* you do further updates to the response and manually calling
391
* {@link #commit()} later on, using another thread.
393
* @return True if the response should be automatically committed.
395
public boolean isAutoCommitting() {
396
return autoCommitting;
400
* Indicates if the response has already been committed.
402
* @return True if the response has already been committed.
404
public boolean isCommitted() {
409
public boolean isConfidential() {
410
return getRequest().isConfidential();
414
* Permanently redirects the client to a target URI. The client is expected
415
* to reuse the same method for the new request.
418
* The target URI reference.
420
public void redirectPermanent(Reference targetRef) {
421
setLocationRef(targetRef);
422
setStatus(Status.REDIRECTION_PERMANENT);
426
* Permanently redirects the client to a target URI. The client is expected
427
* to reuse the same method for the new request.<br>
429
* If you pass a relative target URI, it will be resolved with the current
430
* base reference of the request's resource reference (see
431
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
436
public void redirectPermanent(String targetUri) {
437
setLocationRef(targetUri);
438
setStatus(Status.REDIRECTION_PERMANENT);
442
* Redirects the client to a different URI that SHOULD be retrieved using a
443
* GET method on that resource. This method exists primarily to allow the
444
* output of a POST-activated script to redirect the user agent to a
445
* selected resource. The new URI is not a substitute reference for the
446
* originally requested resource.
449
* The target reference.
451
public void redirectSeeOther(Reference targetRef) {
452
setLocationRef(targetRef);
453
setStatus(Status.REDIRECTION_SEE_OTHER);
457
* Redirects the client to a different URI that SHOULD be retrieved using a
458
* GET method on that resource. This method exists primarily to allow the
459
* output of a POST-activated script to redirect the user agent to a
460
* selected resource. The new URI is not a substitute reference for the
461
* originally requested resource.<br>
463
* If you pass a relative target URI, it will be resolved with the current
464
* base reference of the request's resource reference (see
465
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
470
public void redirectSeeOther(String targetUri) {
471
setLocationRef(targetUri);
472
setStatus(Status.REDIRECTION_SEE_OTHER);
476
* Temporarily redirects the client to a target URI. The client is expected
477
* to reuse the same method for the new request.
480
* The target reference.
482
public void redirectTemporary(Reference targetRef) {
483
setLocationRef(targetRef);
484
setStatus(Status.REDIRECTION_TEMPORARY);
488
* Temporarily redirects the client to a target URI. The client is expected
489
* to reuse the same method for the new request.<br>
491
* If you pass a relative target URI, it will be resolved with the current
492
* base reference of the request's resource reference (see
493
* {@link Request#getResourceRef()} and {@link Reference#getBaseRef()}.
498
public void redirectTemporary(String targetUri) {
499
setLocationRef(targetUri);
500
setStatus(Status.REDIRECTION_TEMPORARY);
504
* Sets the estimated amount of time since a response was generated or
505
* revalidated by the origin server. Origin servers should leave the 0
506
* default value. Only caches are expected to set this property.<br>
508
* Note that when used with HTTP connectors, this property maps to the "Age"
514
public void setAge(int age) {
519
* Sets the set of methods allowed on the requested resource. The set
520
* instance set must be thread-safe (use {@link CopyOnWriteArraySet} for
523
* Note that when used with HTTP connectors, this property maps to the
526
* @param allowedMethods
527
* The set of methods allowed on the requested resource.
529
public void setAllowedMethods(Set<Method> allowedMethods) {
530
synchronized (getAllowedMethods()) {
531
if (allowedMethods != this.allowedMethods) {
532
this.allowedMethods.clear();
534
if (allowedMethods != null) {
535
this.allowedMethods.addAll(allowedMethods);
542
* Sets the authentication information sent by an origin server to a client
543
* after a successful authentication attempt.<br>
545
* Note that when used with HTTP connectors, this property maps to the
546
* "Authentication-Info" header.
548
* @param authenticationInfo
549
* The data returned by the server in response to successful
552
public void setAuthenticationInfo(AuthenticationInfo authenticationInfo) {
553
this.authenticationInfo = authenticationInfo;
557
* Indicates if the response should be automatically committed.
559
* @param autoCommitting
560
* True if the response should be automatically committed
562
public void setAutoCommitting(boolean autoCommitting) {
563
this.autoCommitting = autoCommitting;
567
* Sets the authentication request sent by an origin server to a client.
570
* The authentication request sent by an origin server to a
572
* @deprecated Add request to {@link #getChallengeRequests()} method result
573
* instead or use {@link #setChallengeRequests(List)}.
576
public void setChallengeRequest(ChallengeRequest request) {
577
final List<ChallengeRequest> requests = new CopyOnWriteArrayList<ChallengeRequest>();
578
requests.add(request);
579
setChallengeRequests(requests);
583
* Sets the list of authentication requests sent by an origin server to a
584
* client. Note that when used with HTTP connectors, this property maps to
585
* the "WWW-Authenticate" header. This method clears the current list and
586
* adds all entries in the parameter list.
588
* @param challengeRequests
589
* A list of authentication requests sent by an origin server to
592
public void setChallengeRequests(List<ChallengeRequest> challengeRequests) {
593
synchronized (getChallengeRequests()) {
594
if (challengeRequests != getChallengeRequests()) {
595
getChallengeRequests().clear();
597
if (challengeRequests != null) {
598
getChallengeRequests().addAll(challengeRequests);
605
* Indicates if the response has already been committed.
608
* True if the response has already been committed.
610
public void setCommitted(boolean committed) {
611
this.committed = committed;
615
* Sets the modifiable series of cookie settings provided by the server.
616
* Note that when used with HTTP connectors, this property maps to the
617
* "Set-Cookie" and "Set-Cookie2" headers. This method clears the current
618
* series and adds all entries in the parameter series.
620
* @param cookieSettings
621
* A series of cookie settings provided by the server.
623
public void setCookieSettings(Series<CookieSetting> cookieSettings) {
624
synchronized (getCookieSettings()) {
625
if (cookieSettings != getCookieSettings()) {
626
getCookieSettings().clear();
628
if (cookieSettings != null) {
629
getCookieSettings().addAll(cookieSettings);
636
* Sets the set of dimensions on which the response entity may vary. Note
637
* that when used with HTTP connectors, this property maps to the "Vary"
638
* header. This method clears the current set and adds all entries in the
642
* The set of dimensions on which the response entity may vary.
644
public void setDimensions(Set<Dimension> dimensions) {
645
synchronized (getDimensions()) {
646
if (dimensions != getDimensions()) {
647
getDimensions().clear();
649
if (dimensions != null) {
650
getDimensions().addAll(dimensions);
657
* Sets the reference that the client should follow for redirections or
658
* resource creations. Note that when used with HTTP connectors, this
659
* property maps to the "Location" header.
662
* The reference to set.
664
public void setLocationRef(Reference locationRef) {
665
this.locationRef = locationRef;
669
* Sets the reference that the client should follow for redirections or
670
* resource creations. If you pass a relative location URI, it will be
671
* resolved with the current base reference of the request's resource
672
* reference (see {@link Request#getResourceRef()} and
673
* {@link Reference#getBaseRef()}.<br>
675
* Note that when used with HTTP connectors, this property maps to the
680
* @see #setLocationRef(Reference)
682
public void setLocationRef(String locationUri) {
683
Reference baseRef = null;
685
if (getRequest().getResourceRef() != null) {
686
if (getRequest().getResourceRef().getBaseRef() != null) {
687
baseRef = getRequest().getResourceRef().getBaseRef();
689
baseRef = getRequest().getResourceRef();
693
setLocationRef(new Reference(baseRef, locationUri).getTargetRef());
697
* Sets the modifiable list of authentication requests sent by a proxy to a
698
* client. The list instance set must be thread-safe (use
699
* {@link CopyOnWriteArrayList} for example. Note that when used with HTTP
700
* connectors, this property maps to the "Proxy-Authenticate" header. This
701
* method clears the current list and adds all entries in the parameter
704
* @param proxyChallengeRequests
705
* A list of authentication requests sent by a proxy to a client.
707
public void setProxyChallengeRequests(
708
List<ChallengeRequest> proxyChallengeRequests) {
709
synchronized (getProxyChallengeRequests()) {
710
if (proxyChallengeRequests != getProxyChallengeRequests()) {
711
getProxyChallengeRequests().clear();
713
if (proxyChallengeRequests != null) {
714
getProxyChallengeRequests().addAll(proxyChallengeRequests);
721
* Sets the associated request.
724
* The associated request
726
public void setRequest(Request request) {
727
this.request = request;
731
* Indicates how long the service is expected to be unavailable to the
732
* requesting client. Default value is null.<br>
734
* Note that when used with HTTP connectors, this property maps to the
735
* "Retry-After" header.
738
* Date after with a retry attempt could occur.
740
public void setRetryAfter(Date retryAfter) {
741
this.retryAfter = retryAfter;
745
* Sets the server-specific information.
748
* The server-specific information.
750
public void setServerInfo(ServerInfo serverInfo) {
751
this.serverInfo = serverInfo;
760
public void setStatus(Status status) {
761
this.status = status;
770
* The status message.
772
public void setStatus(Status status, String message) {
773
setStatus(new Status(status, message));
782
* The related error or exception.
784
public void setStatus(Status status, Throwable throwable) {
785
setStatus(new Status(status, throwable));
794
* The related error or exception.
796
* The status message.
798
public void setStatus(Status status, Throwable throwable, String message) {
799
setStatus(new Status(status, throwable, message));
803
* Displays a synthesis of the response like an HTTP status line.
805
* @return A synthesis of the response like an HTTP status line.
807
public String toString() {
808
return getRequest().getProtocol() + " - " + getStatus();