📄 abstractservice.java
字号:
doService(request, response, serviceRequest);
}
/**
* Sends the standard disabled service error message (a 503 error followed by an english description).
* @param response
* @throws IOException
*/
protected void sendDisabledServiceError(HttpServletResponse response)
throws IOException {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
getService() + " service is not enabled. " + "You can enable it in the web admin tool.");
}
/**
* Performs the post method. Simply passes itself on to the three argument
* doPost method, with null for the reader, because the
* request.getReader() will not have been used if this servlet is called
* directly.
*
* @param request DOCUMENT ME!
* @param response DOCUMENT ME!
*
* @throws ServletException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response, null);
}
/**
* Performs the post method. Gets the appropriate xml reader and
* determines the request from that, and then passes the request on to
* doService.
*
* @param request The request made.
* @param response The response to be returned.
* @param requestXml A reader of the xml to be read. This is only used by
* the dispatcher, everyone else should just pass in null. This is
* needed because afaik HttpServletRequest.getReader() can not be
* used twice. So in a dispatched case we write it to a temp file,
* which we can then read in twice.
*
* @throws ServletException DOCUMENT ME!
* @throws IOException DOCUMENT ME!
*/
public void doPost(HttpServletRequest request, HttpServletResponse response, Reader requestXml)
throws ServletException, IOException {
// this.curRequest = request;
Request serviceRequest = null;
//TODO: This isn't a proper ogc service response.
if (!isServiceEnabled(request)) {
sendDisabledServiceError(response);
return;
}
// implements the main request/response logic
try {
XmlRequestReader requestReader = getXmlRequestReader();
//JD: GEOS-323, adding support for character encoding detection
// Reader xml = (requestXml != null) ? requestXml : request.getReader();
Reader xml;
if (null != requestXml) {
xml = requestXml;
} else {
/*
* `getCharsetAwareReader` returns a reader which not support
* mark/reset. So it is a good idea to wrap it into BufferedReader.
* In this case the below debug output will work.
*/
xml = new BufferedReader(XmlCharsetDetector.getCharsetAwareReader(
request.getInputStream()));
}
//JD: GEOS-323
//DJB: add support for POST loggin
if (LOGGER.isLoggable(Level.FINE)) {
if (xml.markSupported()) {
// a little protection for large POSTs (ie. updates)
// for FINE, I assume people just want to see the "normal" ones - not the big ones
// for FINER, I assume they would want to see a bit more
// for FINEST, I assume they would want to see even more
int maxChars = 16000;
if (LOGGER.isLoggable(Level.FINER)) {
maxChars = 64000;
}
if (LOGGER.isLoggable(Level.FINEST)) {
maxChars = 640000; // Bill gates says 640k is good enough for anyone
}
xml.mark(maxChars + 1); // +1 so if you read the whole thing you can still reset()
char[] buffer = new char[maxChars];
int actualRead = xml.read(buffer);
xml.reset();
LOGGER.fine("------------XML POST START-----------\n"
+ new String(buffer, 0, actualRead)
+ "\n------------XML POST END-----------");
if (actualRead == maxChars) {
LOGGER.fine("------------XML POST REPORT WAS TRUNCATED AT " + maxChars
+ " CHARACTERS. RUN WITH HIGHER LOGGING LEVEL TO SEE MORE");
}
} else {
LOGGER.fine(
"ATTEMPTED TO LOG POST XML, BUT WAS PREVENTED BECAUSE markSupported() IS FALSE");
}
}
serviceRequest = requestReader.read(xml, request);
serviceRequest.setHttpServletRequest(request);
} catch (ServiceException se) {
sendError(request, response, se);
return;
} catch (Throwable e) {
sendError(request, response, e);
return;
}
doService(request, response, serviceRequest);
}
/**
* Peforms service according to ServiceStrategy.
*
* <p>
* This method has very strict requirements, please see the class
* description for the specifics.
* </p>
*
* <p>
* It has a lot of try/catch blocks, but they are fairly necessary to
* handle things correctly and to avoid as many ugly servlet responses, so
* that everything is wrapped correctly.
* </p>
*
* @param request The httpServlet of the request.
* @param response The response to be returned.
* @param serviceRequest The OGC request to service.
*
* @throws ServletException if the strategy can't be instantiated
*/
protected void doService(HttpServletRequest request, HttpServletResponse response,
Request serviceRequest) throws ServletException {
LOGGER.info("handling request: " + serviceRequest);
if (!isServiceEnabled(request)) {
try {
sendDisabledServiceError(response);
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Error writing service unavailable response", e);
}
return;
}
ServiceStrategy strategy = null;
Response serviceResponse = null;
try {
strategy = createServiceStrategy();
LOGGER.fine("strategy is: " + strategy.getId());
serviceResponse = getResponseHandler();
} catch (Throwable t) {
sendError(request, response, t);
return;
}
Map services = context.getBeansOfType(Service.class);
Service s = null;
for (Iterator itr = services.entrySet().iterator(); itr.hasNext();) {
Map.Entry entry = (Map.Entry) itr.next();
String id = (String) entry.getKey();
Service service = (Service) entry.getValue();
if (id.toLowerCase().startsWith(serviceRequest.getService().toLowerCase().trim())) {
s = service;
break;
}
}
if (s == null) {
String msg = "No service found matching: " + serviceRequest.getService();
sendError(request, response, new ServiceException(msg));
return;
}
try {
// execute request
LOGGER.finer("executing request");
serviceResponse.execute(serviceRequest);
LOGGER.finer("execution succeed");
} catch (ServiceException serviceException) {
LOGGER.warning("service exception while executing request: " + serviceRequest
+ "\ncause: " + serviceException.getMessage());
serviceResponse.abort(s);
sendError(request, response, serviceException);
return;
} catch (Throwable t) {
//we can safelly send errors here, since we have not touched response yet
serviceResponse.abort(s);
sendError(request, response, t);
return;
}
OutputStream strategyOuput = null;
//obtain the strategy output stream
try {
LOGGER.finest("getting strategy output");
strategyOuput = strategy.getDestination(response);
LOGGER.finer("strategy output is: " + strategyOuput.getClass().getName());
String mimeType = serviceResponse.getContentType(s.getGeoServer());
LOGGER.fine("mime type is: " + mimeType);
response.setContentType(mimeType);
String encoding = serviceResponse.getContentEncoding();
if (encoding != null) {
LOGGER.fine("content encoding is: " + encoding);
response.setHeader("Content-Encoding", encoding);
}
String disposition = serviceResponse.getContentDisposition();
if (disposition != null) {
LOGGER.fine("content encoding is: " + encoding);
response.setHeader("Content-Disposition", disposition);
}
} catch (SocketException socketException) {
LOGGER.fine("it seems that the user has closed the request stream: "
+ socketException.getMessage());
// It seems the user has closed the request stream
// Apparently this is a "cancel" and will quietly go away
//
// I will still give strategy and serviceResponse
// a chance to clean up
//
serviceResponse.abort(s);
strategy.abort();
return;
} catch (IOException ex) {
serviceResponse.abort(s);
strategy.abort();
sendError(request, response, ex);
return;
}
try {
// gather response
serviceResponse.writeTo(strategyOuput);
strategyOuput.flush();
strategy.flush(response);
} catch (java.net.SocketException sockEx) { // user cancel
LOGGER.info("Stream abruptly closed by client, response aborted");
serviceResponse.abort(s);
strategy.abort();
return;
} catch (IOException ioException) { // strategyOutput error
response.setHeader("Content-Disposition", ""); // reset it so we get a proper XML error returned
LOGGER.info("Stream abruptly closed by client, response aborted");
LOGGER.log(Level.FINE, "Error writing out " + ioException.getMessage(), ioException);
serviceResponse.abort(s);
strategy.abort();
return;
} catch (ServiceException writeToFailure) { // writeTo Failure
response.setHeader("Content-Disposition", ""); // reset it so we get a proper XML error returned
serviceResponse.abort(s);
strategy.abort();
sendError(request, response, writeToFailure);
return;
} catch (Throwable help) { // This is an unexpected error(!)
response.setHeader("Content-Disposition", ""); // reset it so we get a proper XML error returned
help.printStackTrace();
serviceResponse.abort(s);
strategy.abort();
sendError(request, response, help);
return;
}
// Finish Response
// I have moved closing the output stream out here, it was being
// done by a few of the ServiceStrategy
//
// By this time serviceResponse has finished successfully
// and strategy is also finished
//
try {
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (SocketException sockEx) { // user cancel
LOGGER.warning("Could not send completed response to user:" + sockEx);
return;
} catch (IOException ioException) {
// This is bad, the user did not get the completed response
LOGGER.warning("Could not send completed response to user:" + ioException);
return;
}
LOGGER.info("Service handled");
}
/**
* Gets the response class that should handle the request of this service.
* All subclasses must implement.
* <p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -