001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package com.noelios.restlet;
020:
021: import java.util.logging.Level;
022:
023: import org.restlet.Context;
024: import org.restlet.Filter;
025: import org.restlet.data.MediaType;
026: import org.restlet.data.Request;
027: import org.restlet.data.Response;
028: import org.restlet.data.Status;
029: import org.restlet.resource.Representation;
030: import org.restlet.resource.StringRepresentation;
031:
032: /**
033: * Filter associating a response entity based on the status. In order to
034: * customize the default representation, just subclass this class and override
035: * the "getRepresentation" method.<br/> If any exception occurs during the call
036: * handling, a "server internal error" status is automatically associated to the
037: * call. Of course, you can personalize the representation of this error. Also,
038: * if no status is set (null), then the "success ok" status is assumed.<br/>
039: *
040: * @see <a href="http://www.restlet.org/documentation/1.0/tutorial#part08">Tutorial: Displaying
041: * error pages</a>
042: * @author Jerome Louvel (contact@noelios.com)
043: */
044: public class StatusFilter extends Filter {
045: /** Indicates whether an existing representation should be overwritten. */
046: private boolean overwrite;
047:
048: /** Email address of the administrator to contact in case of error. */
049: private String email;
050:
051: /** The home URI to propose in case of error. */
052: private String homeURI;
053:
054: /**
055: * Constructor.
056: *
057: * @param context
058: * The context.
059: * @param overwrite
060: * Indicates whether an existing representation should be
061: * overwritten.
062: * @param email
063: * Email address of the administrator to contact in case of
064: * error.
065: * @param homeUri
066: * The home URI to propose in case of error.
067: */
068: public StatusFilter(Context context, boolean overwrite,
069: String email, String homeUri) {
070: super (context);
071: this .overwrite = overwrite;
072: this .email = email;
073: this .homeURI = homeUri;
074: }
075:
076: /**
077: * Handles the call by distributing it to the next Restlet.
078: *
079: * @param request
080: * The request to handle.
081: * @param response
082: * The response to update.
083: */
084: public void doHandle(Request request, Response response) {
085: // Normally handle the call
086: try {
087: super .doHandle(request, response);
088: } catch (Throwable t) {
089: response.setStatus(getStatus(t, request, response));
090: }
091: }
092:
093: /**
094: * Allows filtering after its handling by the target Restlet. Does nothing
095: * by default.
096: *
097: * @param request
098: * The request to handle.
099: * @param response
100: * The response to update.
101: */
102: public void afterHandle(Request request, Response response) {
103: // If no status is set, then the "success ok" status is assumed.
104: if (response.getStatus() == null) {
105: response.setStatus(Status.SUCCESS_OK);
106: }
107:
108: // Do we need to get a representation for the current status?
109: if (response.getStatus().isError()
110: && ((response.getEntity() == null) || overwrite)) {
111: response.setEntity(getRepresentation(response.getStatus(),
112: request, response));
113: }
114: }
115:
116: /**
117: * Returns a representation for the given status.<br/> In order to
118: * customize the default representation, this method can be overriden.
119: *
120: * @param status
121: * The status to represent.
122: * @param request
123: * The request handled.
124: * @param response
125: * The response updated.
126: * @return The representation of the given status.
127: */
128: public Representation getRepresentation(Status status,
129: Request request, Response response) {
130: StringBuilder sb = new StringBuilder();
131: sb.append("<html>\n");
132: sb.append("<head>\n");
133: sb.append(" <title>Status page</title>\n");
134: sb.append("</head>\n");
135: sb.append("<body>\n");
136:
137: sb.append("<h3>");
138: if (status.getDescription() != null) {
139: sb.append(status.getDescription());
140: } else {
141: sb
142: .append("No description available for this result status");
143: }
144: sb.append("</h3>");
145: sb.append("<p>You can get technical details <a href=\"");
146: sb.append(status.getUri());
147: sb.append("\">here</a>.<br/>\n");
148:
149: if (email != null) {
150: sb
151: .append("For further assistance, you can contact the <a href=\"mailto:");
152: sb.append(email);
153: sb.append("\">administrator</a>.<br/>\n");
154: }
155:
156: if (homeURI != null) {
157: sb.append("Please continue your visit at our <a href=\"");
158: sb.append(homeURI);
159: sb.append("\">home page</a>.\n");
160: }
161:
162: sb.append("</p>\n");
163: sb.append("</body>\n");
164: sb.append("</html>\n");
165:
166: return new StringRepresentation(sb.toString(),
167: MediaType.TEXT_HTML);
168: }
169:
170: /**
171: * Returns a status for a given exception or error. By default it returns an
172: * {@link Status#SERVER_ERROR_INTERNAL} status and logs a severe message.<br/>
173: * In order to customize the default behavior, this method can be overriden.
174: *
175: * @param throwable
176: * The exception or error caught.
177: * @param request
178: * The request handled.
179: * @param response
180: * The response updated.
181: * @return The representation of the given status.
182: */
183: public Status getStatus(Throwable throwable, Request request,
184: Response response) {
185: getLogger().log(Level.SEVERE,
186: "Unhandled exception or error intercepted", throwable);
187: return Status.SERVER_ERROR_INTERNAL;
188: }
189: }
|