001 /*
002 * The contents of this file are subject to the terms
003 * of the Common Development and Distribution License
004 * (the "License"). You may not use this file except
005 * in compliance with the License.
006 *
007 * You can obtain a copy of the license at
008 * http://www.opensource.org/licenses/cddl1.php
009 * See the License for the specific language governing
010 * permissions and limitations under the License.
011 */
012
013 /*
014 * Response.java
015 *
016 * Created on April 18, 2007, 9:00 AM
017 *
018 */
019
020 package javax.ws.rs.core;
021
022 import java.net.URI;
023 import java.util.Date;
024 import java.util.List;
025 import java.util.Locale;
026 import javax.ws.rs.ext.RuntimeDelegate;
027
028 /**
029 * Defines the contract between a returned instance and the runtime when
030 * an application needs to provide metadata to the runtime. An application
031 * class can extend this class directly or can use one of the static
032 * methods to create an instance using a ResponseBuilder.
033 *
034 * Several methods have parameters of type URI, {@link UriBuilder} provides
035 * convenient methods to create such values as does
036 * {@link <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/net/URI.html#create(java.lang.String)">URI.create()</a>}.
037 *
038 * @see Response.ResponseBuilder
039 */
040 public abstract class Response {
041
042 /**
043 * Protected constructor, use one of the static methods to obtain a
044 * {@link ResponseBuilder} instance and obtain a Response from that.
045 */
046 protected Response() {}
047
048
049 /**
050 * Return the response entity. The response will be serialized using a
051 * MessageBodyWriter for either the class of the entity or, in the case of
052 * {@link GenericEntity}, the value of {@link GenericEntity#getRawType()}.
053 * @return an object instance or null if there is no entity
054 * @see javax.ws.rs.ext.MessageBodyWriter
055 */
056 public abstract Object getEntity();
057
058 /**
059 * Get the status code associated with the response.
060 * @return the response status code or -1 if the status was not set.
061 */
062 public abstract int getStatus();
063
064 /**
065 * Get metadata associated with the response as a map. The returned map
066 * may be subsequently modified by the JAX-RS runtime. Values will be
067 * serialized using a {@link javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate}
068 * if one is available via
069 * {@link javax.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)}
070 * for the class of the value or using the values {@code toString} method if a
071 * header delegate is not available.
072 * @return response metadata as a map
073 */
074 public abstract MultivaluedMap<String, Object> getMetadata();
075
076 /**
077 * Create a new ResponseBuilder by performing a shallow copy of an
078 * existing Response. The returned builder has its own metadata map but
079 * entries are simply references to the keys and values contained in the
080 * supplied Response metadata map.
081 * @param response a Response from which the status code, entity and metadata
082 * will be copied
083 * @return a new ReponseBuilder
084 */
085 public static ResponseBuilder fromResponse(Response response) {
086 ResponseBuilder b = status(response.getStatus());
087 b.entity(response.getEntity());
088 for (String headerName: response.getMetadata().keySet()) {
089 List<Object> headerValues = response.getMetadata().get(headerName);
090 for (Object headerValue: headerValues) {
091 b.header(headerName, headerValue);
092 }
093 }
094 return b;
095 }
096
097 /**
098 * Create a new ResponseBuilder with the supplied status.
099 * @param status the response status
100 * @return a new ResponseBuilder
101 * @throws IllegalArgumentException if status is null
102 */
103 public static ResponseBuilder status(StatusType status) {
104 ResponseBuilder b = ResponseBuilder.newInstance();
105 b.status(status);
106 return b;
107 }
108
109 /**
110 * Create a new ResponseBuilder with the supplied status.
111 * @param status the response status
112 * @return a new ResponseBuilder
113 * @throws IllegalArgumentException if status is null
114 */
115 public static ResponseBuilder status(Status status) {
116 return status((StatusType)status);
117 }
118
119 /**
120 * Create a new ResponseBuilder with the supplied status.
121 * @param status the response status
122 * @return a new ResponseBuilder
123 * @throws IllegalArgumentException if status is less than 100 or greater
124 * than 599.
125 */
126 public static ResponseBuilder status(int status) {
127 ResponseBuilder b = ResponseBuilder.newInstance();
128 b.status(status);
129 return b;
130 }
131
132 /**
133 * Create a new ResponseBuilder with an OK status.
134 *
135 * @return a new ResponseBuilder
136 */
137 public static ResponseBuilder ok() {
138 ResponseBuilder b = status(Status.OK);
139 return b;
140 }
141
142 /**
143 * Create a new ResponseBuilder that contains a representation. It is the
144 * callers responsibility to wrap the actual entity with
145 * {@link GenericEntity} if preservation of its generic type is required.
146 *
147 * @param entity the representation entity data
148 * @return a new ResponseBuilder
149 */
150 public static ResponseBuilder ok(Object entity) {
151 ResponseBuilder b = ok();
152 b.entity(entity);
153 return b;
154 }
155
156 /**
157 * Create a new ResponseBuilder that contains a representation. It is the
158 * callers responsibility to wrap the actual entity with
159 * {@link GenericEntity} if preservation of its generic type is required.
160 *
161 * @param entity the representation entity data
162 * @param type the media type of the entity
163 * @return a new ResponseBuilder
164 */
165 public static ResponseBuilder ok(Object entity, MediaType type) {
166 ResponseBuilder b = ok();
167 b.entity(entity);
168 b.type(type);
169 return b;
170 }
171
172 /**
173 * Create a new ResponseBuilder that contains a representation. It is the
174 * callers responsibility to wrap the actual entity with
175 * {@link GenericEntity} if preservation of its generic type is required.
176 *
177 * @param entity the representation entity data
178 * @param type the media type of the entity
179 * @return a new ResponseBuilder
180 */
181 public static ResponseBuilder ok(Object entity, String type) {
182 ResponseBuilder b = ok();
183 b.entity(entity);
184 b.type(type);
185 return b;
186 }
187
188 /**
189 * Create a new ResponseBuilder that contains a representation. It is the
190 * callers responsibility to wrap the actual entity with
191 * {@link GenericEntity} if preservation of its generic type is required.
192 *
193 * @param entity the representation entity data
194 * @param variant representation metadata
195 * @return a new ResponseBuilder
196 */
197 public static ResponseBuilder ok(Object entity, Variant variant) {
198 ResponseBuilder b = ok();
199 b.entity(entity);
200 b.variant(variant);
201 return b;
202 }
203
204 /**
205 * Create a new ResponseBuilder with an server error status.
206 *
207 * @return a new ResponseBuilder
208 */
209 public static ResponseBuilder serverError() {
210 ResponseBuilder b = status(Status.INTERNAL_SERVER_ERROR);
211 return b;
212 }
213
214 /**
215 * Create a new ResponseBuilder for a created resource, set the location
216 * header using the supplied value.
217 *
218 * @param location the URI of the new resource. If a relative URI is
219 * supplied it will be converted into an absolute URI by resolving it
220 * relative to the request URI (see {@link UriInfo#getRequestUri}).
221 * @return a new ResponseBuilder
222 * @throws java.lang.IllegalArgumentException if location is null
223 */
224 public static ResponseBuilder created(URI location) {
225 ResponseBuilder b = status(Status.CREATED).location(location);
226 return b;
227 }
228
229 /**
230 * Create a new ResponseBuilder for an empty response.
231 *
232 * @return a new ResponseBuilder
233 */
234 public static ResponseBuilder noContent() {
235 ResponseBuilder b = status(Status.NO_CONTENT);
236 return b;
237 }
238
239 /**
240 * Create a new ResponseBuilder with a not-modified status.
241 *
242 * @return a new ResponseBuilder
243 */
244 public static ResponseBuilder notModified() {
245 ResponseBuilder b = status(Status.NOT_MODIFIED);
246 return b;
247 }
248
249 /**
250 * Create a new ResponseBuilder with a not-modified status.
251 *
252 * @param tag a tag for the unmodified entity
253 * @return a new ResponseBuilder
254 * @throws java.lang.IllegalArgumentException if tag is null
255 */
256 public static ResponseBuilder notModified(EntityTag tag) {
257 ResponseBuilder b = notModified();
258 b.tag(tag);
259 return b;
260 }
261
262 /**
263 * Create a new ResponseBuilder with a not-modified status
264 * and a strong entity tag. This is a shortcut
265 * for <code>notModified(new EntityTag(<i>value</i>))</code>.
266 *
267 * @param tag the string content of a strong entity tag. The JAX-RS
268 * runtime will quote the supplied value when creating the header.
269 * @return a new ResponseBuilder
270 * @throws java.lang.IllegalArgumentException if tag is null
271 */
272 public static ResponseBuilder notModified(String tag) {
273 ResponseBuilder b = notModified();
274 b.tag(tag);
275 return b;
276 }
277
278 /**
279 * Create a new ResponseBuilder for a redirection. Used in the
280 * redirect-after-POST (aka POST/redirect/GET) pattern.
281 *
282 * @param location the redirection URI. If a relative URI is
283 * supplied it will be converted into an absolute URI by resolving it
284 * relative to the base URI of the application (see
285 * {@link UriInfo#getBaseUri}).
286 * @return a new ResponseBuilder
287 * @throws java.lang.IllegalArgumentException if location is null
288 */
289 public static ResponseBuilder seeOther(URI location) {
290 ResponseBuilder b = status(Status.SEE_OTHER).location(location);
291 return b;
292 }
293
294 /**
295 * Create a new ResponseBuilder for a temporary redirection.
296 *
297 * @param location the redirection URI. If a relative URI is
298 * supplied it will be converted into an absolute URI by resolving it
299 * relative to the base URI of the application (see
300 * {@link UriInfo#getBaseUri}).
301 * @return a new ResponseBuilder
302 * @throws java.lang.IllegalArgumentException if location is null
303 */
304 public static ResponseBuilder temporaryRedirect(URI location) {
305 ResponseBuilder b = status(Status.TEMPORARY_REDIRECT).location(location);
306 return b;
307 }
308
309 /**
310 * Create a new ResponseBuilder for a not acceptable response.
311 *
312 * @param variants list of variants that were available, a null value is
313 * equivalent to an empty list.
314 * @return a new ResponseBuilder
315 */
316 public static ResponseBuilder notAcceptable(List<Variant> variants) {
317 ResponseBuilder b = status(Status.NOT_ACCEPTABLE).variants(variants);
318 return b;
319 }
320
321 /**
322 * A class used to build Response instances that contain metadata instead
323 * of or in addition to an entity. An initial instance may be obtained via
324 * static methods of the Response class, instance methods provide the
325 * ability to set metadata. E.g. to create a response that indicates the
326 * creation of a new resource:
327 * <pre>@POST
328 * Response addWidget(...) {
329 * Widget w = ...
330 * URI widgetId = UriBuilder.fromResource(Widget.class)...
331 * return Response.created(widgetId).build();
332 * }</pre>
333 *
334 * <p>Several methods have parameters of type URI, {@link UriBuilder} provides
335 * convenient methods to create such values as does <code>URI.create()</code>.</p>
336 *
337 * <p>Where multiple variants of the same method are provided, the type of
338 * the supplied parameter is retained in the metadata of the built
339 * {@code Response}.</p>
340 *
341 */
342 public static abstract class ResponseBuilder {
343
344 /**
345 * Protected constructor, use one of the static methods of
346 * <code>Response</code> to obtain an instance.
347 */
348 protected ResponseBuilder() {}
349
350 /**
351 * Create a new builder instance.
352 *
353 * @return a new ResponseBuilder
354 */
355 protected static ResponseBuilder newInstance() {
356 ResponseBuilder b = RuntimeDelegate.getInstance().createResponseBuilder();
357 return b;
358 }
359
360 /**
361 * Create a Response instance from the current ResponseBuilder. The builder
362 * is reset to a blank state equivalent to calling the ok method.
363 *
364 * @return a Response instance
365 */
366 public abstract Response build();
367
368 /**
369 * Create a copy of the ResponseBuilder preserving its state.
370 * @return a copy of the ResponseBuilder
371 */
372 @Override
373 public abstract ResponseBuilder clone();
374
375 /**
376 * Set the status on the ResponseBuilder.
377 *
378 * @param status the response status
379 * @return the updated ResponseBuilder
380 * @throws IllegalArgumentException if status is less than 100 or greater
381 * than 599.
382 */
383 public abstract ResponseBuilder status(int status);
384
385 /**
386 * Set the status on the ResponseBuilder.
387 *
388 * @param status the response status
389 * @return the updated ResponseBuilder
390 * @throws IllegalArgumentException if status is null
391 */
392 public ResponseBuilder status(StatusType status) {
393 if (status == null)
394 throw new IllegalArgumentException();
395 return status(status.getStatusCode());
396 };
397
398 /**
399 * Set the status on the ResponseBuilder.
400 *
401 * @param status the response status
402 * @return the updated ResponseBuilder
403 * @throws IllegalArgumentException if status is null
404 */
405 public ResponseBuilder status(Status status) {
406 return status((StatusType)status);
407 };
408
409 /**
410 * Set the entity on the ResponseBuilder. It is the
411 * callers responsibility to wrap the actual entity with
412 * {@link GenericEntity} if preservation of its generic type is required.
413 *
414 * @param entity the response entity
415 * @return the updated ResponseBuilder
416 */
417 public abstract ResponseBuilder entity(Object entity);
418
419 /**
420 * Set the response media type on the ResponseBuilder.
421 *
422 * @param type the media type of the response entity, if null any
423 * existing value for type will be removed
424 * @return the updated ResponseBuilder
425 */
426 public abstract ResponseBuilder type(MediaType type);
427
428 /**
429 * Set the response media type on the ResponseBuilder.
430 *
431 * @param type the media type of the response entity, if null any
432 * existing value for type will be removed
433 * @return the updated ResponseBuilder
434 * @throws IllegalArgumentException if type cannot be parsed
435 */
436 public abstract ResponseBuilder type(String type);
437
438 /**
439 * Set representation metadata on the ResponseBuilder. Equivalent to
440 * setting the values of content type, content language, and content
441 * encoding separately using the values of the variant properties.
442 *
443 * @param variant metadata of the response entity, a null value is
444 * equivalent to a variant with all null properties.
445 * @return the updated ResponseBuilder
446 */
447 public abstract ResponseBuilder variant(Variant variant);
448
449 /**
450 * Add a Vary header that lists the available variants.
451 *
452 * @param variants a list of available representation variants, a null
453 * value will remove an existing value for vary.
454 * @return the updated ResponseBuilder
455 */
456 public abstract ResponseBuilder variants(List<Variant> variants);
457
458 /**
459 * Set the language on the ResponseBuilder.
460 *
461 * @param language the language of the response entity, if null any
462 * existing value for language will be removed
463 * @return the updated ResponseBuilder
464 */
465 public abstract ResponseBuilder language(String language);
466
467 /**
468 * Set the language on the ResponseBuilder.
469 *
470 *
471 * @param language the language of the response entity, if null any
472 * existing value for type will be removed
473 * @return the updated ResponseBuilder
474 */
475 public abstract ResponseBuilder language(Locale language);
476
477 /**
478 * Set the location on the ResponseBuilder.
479 *
480 * @param location the location. If a relative URI is
481 * supplied it will be converted into an absolute URI by resolving it
482 * relative to the base URI of the application (see
483 * {@link UriInfo#getBaseUri}). If null any
484 * existing value for location will be removed.
485 * @return the updated ResponseBuilder
486 */
487 public abstract ResponseBuilder location(URI location);
488
489 /**
490 * Set the content location on the ResponseBuilder.
491 *
492 * @param location the content location. Relative or absolute URIs
493 * may be used for the value of content location. If null any
494 * existing value for content location will be removed.
495 * @return the updated ResponseBuilder
496 */
497 public abstract ResponseBuilder contentLocation(URI location);
498
499 /**
500 * Set an entity tag on the ResponseBuilder.
501 *
502 * @param tag the entity tag, if null any
503 * existing entity tag value will be removed.
504 * @return the updated ResponseBuilder
505 */
506 public abstract ResponseBuilder tag(EntityTag tag);
507
508 /**
509 * Set a strong entity tag on the ResponseBuilder. This is a shortcut
510 * for <code>tag(new EntityTag(<i>value</i>))</code>.
511 *
512 * @param tag the string content of a strong entity tag. The JAX-RS
513 * runtime will quote the supplied value when creating the header. If
514 * null any existing entity tag value will be removed.
515 * @return the updated ResponseBuilder
516 */
517 public abstract ResponseBuilder tag(String tag);
518
519 /**
520 * Set the last modified date on the ResponseBuilder.
521 *
522 * @param lastModified the last modified date, if null any existing
523 * last modified value will be removed.
524 * @return the updated ResponseBuilder
525 */
526 public abstract ResponseBuilder lastModified(Date lastModified);
527
528 /**
529 * Set the cache control data on the ResponseBuilder.
530 *
531 * @param cacheControl the cache control directives, if null removes any
532 * existing cache control directives.
533 * @return the updated ResponseBuilder
534 */
535 public abstract ResponseBuilder cacheControl(CacheControl cacheControl);
536
537 /**
538 * Set the expires date on the ResponseBuilder.
539 *
540 * @param expires the expiration date, if null removes any existing
541 * expires value.
542 * @return the updated ResponseBuilder
543 */
544 public abstract ResponseBuilder expires(Date expires);
545
546 /**
547 * Add a header to the ResponseBuilder.
548 *
549 * @param name the name of the header
550 * @param value the value of the header, the header will be serialized
551 * using a {@link javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate} if
552 * one is available via
553 * {@link javax.ws.rs.ext.RuntimeDelegate#createHeaderDelegate(java.lang.Class)}
554 * for the class of {@code value} or using its {@code toString} method if a
555 * header delegate is not available. If {@code value} is null then all
556 * current headers of the same name will be removed.
557 * @return the updated ResponseBuilder
558 */
559 public abstract ResponseBuilder header(String name, Object value);
560
561 /**
562 * Add cookies to the ResponseBuilder.
563 *
564 * @param cookies new cookies that will accompany the response. A null
565 * value will remove all cookies, including those added via the
566 * {@link #header(java.lang.String, java.lang.Object)} method.
567 * @return the updated ResponseBuilder
568 */
569 public abstract ResponseBuilder cookie(NewCookie... cookies);
570 }
571
572 /**
573 * Base interface for statuses used in responses.
574 */
575 public interface StatusType {
576 /**
577 * Get the associated status code
578 * @return the status code
579 */
580 public int getStatusCode();
581
582 /**
583 * Get the class of status code
584 * @return the class of status code
585 */
586 public Status.Family getFamily();
587
588 /**
589 * Get the reason phrase
590 * @return the reason phrase
591 */
592 public String getReasonPhrase();
593 }
594
595 /**
596 * Commonly used status codes defined by HTTP, see
597 * {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10">HTTP/1.1 documentation</a>}
598 * for the complete list. Additional status codes can be added by applications
599 * by creating an implementation of {@link StatusType}.
600 */
601 public enum Status implements StatusType {
602 /**
603 * 200 OK, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1">HTTP/1.1 documentation</a>}.
604 */
605 OK(200, "OK"),
606 /**
607 * 201 Created, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.2">HTTP/1.1 documentation</a>}.
608 */
609 CREATED(201, "Created"),
610 /**
611 * 202 Accepted, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3">HTTP/1.1 documentation</a>}.
612 */
613 ACCEPTED(202, "Accepted"),
614 /**
615 * 204 No Content, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5">HTTP/1.1 documentation</a>}.
616 */
617 NO_CONTENT(204, "No Content"),
618 /**
619 * 301 Moved Permanently, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2">HTTP/1.1 documentation</a>}.
620 */
621 MOVED_PERMANENTLY(301, "Moved Permanently"),
622 /**
623 * 303 See Other, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4">HTTP/1.1 documentation</a>}.
624 */
625 SEE_OTHER(303, "See Other"),
626 /**
627 * 304 Not Modified, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5">HTTP/1.1 documentation</a>}.
628 */
629 NOT_MODIFIED(304, "Not Modified"),
630 /**
631 * 307 Temporary Redirect, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.8">HTTP/1.1 documentation</a>}.
632 */
633 TEMPORARY_REDIRECT(307, "Temporary Redirect"),
634 /**
635 * 400 Bad Request, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1">HTTP/1.1 documentation</a>}.
636 */
637 BAD_REQUEST(400, "Bad Request"),
638 /**
639 * 401 Unauthorized, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">HTTP/1.1 documentation</a>}.
640 */
641 UNAUTHORIZED(401, "Unauthorized"),
642 /**
643 * 403 Forbidden, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4">HTTP/1.1 documentation</a>}.
644 */
645 FORBIDDEN(403, "Forbidden"),
646 /**
647 * 404 Not Found, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5">HTTP/1.1 documentation</a>}.
648 */
649 NOT_FOUND(404, "Not Found"),
650 /**
651 * 406 Not Acceptable, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.7">HTTP/1.1 documentation</a>}.
652 */
653 NOT_ACCEPTABLE(406, "Not Acceptable"),
654 /**
655 * 409 Conflict, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10">HTTP/1.1 documentation</a>}.
656 */
657 CONFLICT(409, "Conflict"),
658 /**
659 * 410 Gone, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11">HTTP/1.1 documentation</a>}.
660 */
661 GONE(410, "Gone"),
662 /**
663 * 412 Precondition Failed, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13">HTTP/1.1 documentation</a>}.
664 */
665 PRECONDITION_FAILED(412, "Precondition Failed"),
666 /**
667 * 415 Unsupported Media Type, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.16">HTTP/1.1 documentation</a>}.
668 */
669 UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
670 /**
671 * 500 Internal Server Error, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1">HTTP/1.1 documentation</a>}.
672 */
673 INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
674 /**
675 * 503 Service Unavailable, see {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4">HTTP/1.1 documentation</a>}.
676 */
677 SERVICE_UNAVAILABLE(503, "Service Unavailable");
678
679 private final int code;
680 private final String reason;
681 private Family family;
682
683 /**
684 * An enumeration representing the class of status code. Family is used
685 * here since class is overloaded in Java.
686 */
687 public enum Family {INFORMATIONAL, SUCCESSFUL, REDIRECTION, CLIENT_ERROR, SERVER_ERROR, OTHER};
688
689 Status(final int statusCode, final String reasonPhrase) {
690 this.code = statusCode;
691 this.reason = reasonPhrase;
692 switch(code/100) {
693 case 1: this.family = Family.INFORMATIONAL; break;
694 case 2: this.family = Family.SUCCESSFUL; break;
695 case 3: this.family = Family.REDIRECTION; break;
696 case 4: this.family = Family.CLIENT_ERROR; break;
697 case 5: this.family = Family.SERVER_ERROR; break;
698 default: this.family = Family.OTHER; break;
699 }
700 }
701
702 /**
703 * Get the class of status code
704 * @return the class of status code
705 */
706 public Family getFamily() {
707 return family;
708 }
709
710 /**
711 * Get the associated status code
712 * @return the status code
713 */
714 public int getStatusCode() {
715 return code;
716 }
717
718 /**
719 * Get the reason phrase
720 * @return the reason phrase
721 */
722 public String getReasonPhrase() {
723 return toString();
724 }
725
726 /**
727 * Get the reason phrase
728 * @return the reason phrase
729 */
730 @Override
731 public String toString() {
732 return reason;
733 }
734
735 /**
736 * Convert a numerical status code into the corresponding Status
737 * @param statusCode the numerical status code
738 * @return the matching Status or null is no matching Status is defined
739 */
740 public static Status fromStatusCode(final int statusCode) {
741 for (Status s : Status.values()) {
742 if (s.code == statusCode) {
743 return s;
744 }
745 }
746 return null;
747 }
748 }
749 }