001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.geoserver.ows;
006:
007: import org.geoserver.ows.util.ResponseUtils;
008: import org.geoserver.platform.Service;
009: import org.geoserver.platform.ServiceException;
010: import org.vfny.geoserver.global.GeoServer;
011:
012: import java.io.ByteArrayOutputStream;
013: import java.io.IOException;
014: import java.io.PrintStream;
015: import java.util.List;
016: import java.util.logging.Level;
017:
018: import javax.servlet.http.HttpServletRequest;
019: import javax.servlet.http.HttpServletResponse;
020:
021: /**
022: * An implementation of {@link ServiceExceptionHandler} which outputs
023: * as service exception in a <code>ServiceExceptionReport</code> document.
024: * <p>
025: * This handler is referred to as "legacy" as newer services move to the ows
026: * style exception report. See {@link DefaultServiceExceptionHandler}.
027: * </p>
028: * <p>
029: * <h3>Version</h3>
030: * By default this exception handler will output a <code>ServiceExceptionReport</code>
031: * which is of version <code>1.2.0</code>. This may be overriden with
032: * {@link #setVersion(String)}.
033: * </p>
034: * <p>
035: * <h3>DTD and Schema</h3>
036: * By default, no DTD or XML Schema reference will be included in the document.
037: * The methods {@link #setDTDLocation(String)} and {@link #setSchemaLocation(String)}
038: * can be used to override this behaviour. Only one of these methods should be
039: * set per instance of this class.
040: *
041: * The supplied value should be relative, and will be appended to the result
042: * of {@link OWS#getSchemaBaseURL()}.
043: * </p>
044: * <p>
045: * <h3>Content Type</h3>
046: * The default content type for the created document is <code>text/xml</code>,
047: * this can be overridden with {@link #setContentType(String)}.
048: * </p>
049: *
050: * @author Justin Deoliveira, The Open Planning Project
051: *
052: */
053: public class LegacyServiceExceptionHandler extends
054: ServiceExceptionHandler {
055: /**
056: * The configuration of hte service.
057: */
058: OWS ows;
059:
060: /**
061: * the version of the service exceptoin report.
062: */
063: String version = "1.2.0";
064:
065: /**
066: * Location of document type defintion for document
067: */
068: String dtdLocation = null;
069:
070: /**
071: * Location of schema for document.
072: */
073: String schemaLocation = null;
074:
075: /**
076: * The content type of the produced document
077: */
078: String contentType = "text/xml";
079:
080: /**
081: * The central configuration, used to decide whether to dump a verbose stack trace, or not
082: */
083: GeoServer geoServer;
084:
085: public LegacyServiceExceptionHandler(List services, OWS ows,
086: GeoServer geoServer) {
087: super (services);
088: this .ows = ows;
089: this .geoServer = geoServer;
090: }
091:
092: public LegacyServiceExceptionHandler(Service service, OWS ows,
093: GeoServer geoServer) {
094: super (service);
095: this .ows = ows;
096: this .geoServer = geoServer;
097: }
098:
099: public void setVersion(String version) {
100: this .version = version;
101: }
102:
103: public void setDTDLocation(String dtd) {
104: this .dtdLocation = dtd;
105: }
106:
107: public void setSchemaLocation(String schemaLocation) {
108: this .schemaLocation = schemaLocation;
109: }
110:
111: public void setContentType(String contentType) {
112: this .contentType = contentType;
113: }
114:
115: public void handleServiceException(ServiceException exception,
116: Service service, HttpServletRequest request,
117: HttpServletResponse response) {
118: String tab = " ";
119: StringBuffer sb = new StringBuffer();
120:
121: //xml header TODO: should the encoding the server default?
122: sb.append("<?xml version=\"1.0\"");
123: sb.append(" encoding=\"UTF-8\"");
124:
125: if (dtdLocation != null) {
126: sb.append(" standalone=\"no\"");
127: }
128:
129: sb.append("?>");
130:
131: //dtd location
132: if (dtdLocation != null) {
133: String fullDtdLocation = ResponseUtils.appendPath(ows
134: .getSchemaBaseURL(), dtdLocation);
135: sb.append("<!DOCTYPE ServiceExceptionReport SYSTEM \""
136: + fullDtdLocation + "\"> ");
137: }
138:
139: //root element
140: sb.append("<ServiceExceptionReport version=\"" + version
141: + "\" ");
142:
143: //xml schema location
144: if ((schemaLocation != null) && (dtdLocation == null)) {
145: String fullSchemaLocation = ResponseUtils.appendPath(ows
146: .getSchemaBaseURL(), schemaLocation);
147:
148: sb.append("xmlns=\"http://www.opengis.net/ogc\" ");
149: sb
150: .append("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
151: sb
152: .append("xsi:schemaLocation=\"http://www.opengis.net/ogc "
153: + fullSchemaLocation + "\"");
154: }
155:
156: sb.append(">");
157:
158: //write out the service exception
159: sb.append(tab + "<ServiceException");
160:
161: //exception code
162: if ((exception.getCode() != null)
163: && !exception.getCode().equals("")) {
164: sb.append(" code=\"" + exception.getCode() + "\"");
165: }
166:
167: //exception locator
168: if ((exception.getLocator() != null)
169: && !exception.getLocator().equals("")) {
170: sb.append(" locator=\"" + exception.getLocator() + "\"");
171: }
172:
173: sb.append(">");
174:
175: //message
176: if ((exception.getMessage() != null)) {
177: sb.append("\n" + tab + tab);
178: dumpExceptionMessages(exception, sb);
179:
180: if (geoServer.isVerboseExceptions()) {
181: ByteArrayOutputStream stackTrace = new ByteArrayOutputStream();
182: exception.printStackTrace(new PrintStream(stackTrace));
183:
184: sb.append("\nDetails:\n");
185: sb.append(ResponseUtils.encodeXML(new String(stackTrace
186: .toByteArray())));
187: }
188: }
189:
190: sb.append("\n</ServiceException>");
191: sb.append("</ServiceExceptionReport>");
192:
193: response.setContentType(contentType);
194:
195: //TODO: server encoding?
196: response.setCharacterEncoding("UTF-8");
197:
198: try {
199: response.getOutputStream().write(sb.toString().getBytes());
200: response.getOutputStream().flush();
201: } catch (IOException e) {
202: //throw new RuntimeException(e);
203: // Hmm, not much we can do here. I guess log the fact that we couldn't write out the exception and be done with it...
204: LOGGER
205: .log(
206: Level.INFO,
207: "Problem writing exception information back to calling client:",
208: e);
209: }
210: }
211: }
|