📄 abstractservice.java
字号:
* This method is not abstract to support subclasses that use the
* request-response mechanism.
* </p>
*
* @return The response that the request read by this servlet should be
* passed to.
*/
protected Response getResponseHandler() {
return null;
}
/**
* This method was added in order to adapt the old style servlet services
* to the new ows dispatching interface, without having to modify the
* services themselves.
*
* @return A call to {@link #getResponseHandler()}.
*/
public final Response getResponse() {
return getResponseHandler();
}
/**
* Gets a reader that will figure out the correct Key Vaule Pairs for this
* service.
* <p>
* Subclasses should override to supply a specific kvp reader. Default
* implementation returns <code>null</code>
* </p>
* @param params A map of the kvp pairs.
*
* @return An initialized KVP reader to decode the request.
*/
protected KvpRequestReader getKvpReader(Map params) {
return null;
}
/**
* Gets a reader that will handle a posted xml request for this servlet.
* <p>
* Subclasses should override to supply a specific xml reader. Default
* implementation returns <code>null</code>
* </p>
* @return An XmlRequestReader appropriate to this service.
*/
protected XmlRequestReader getXmlRequestReader() {
return null;
}
/**
* Gets the exception handler for this service.
*
* @return The correct ExceptionHandler
*/
protected abstract ExceptionHandler getExceptionHandler();
/**
* Gets the strategy for outputting the response. This method gets the
* strategy from the serviceStrategy param in the web.xml file. This is
* sort of odd behavior, as all other such parameters are set in the
* services and catalog xml files, and this param may move there. But as
* it is much more of a programmer configuration than a user
* configuration there is no rush to move it.
*
* <p>
* Subclasses may choose to override this method in order to get a strategy
* more suited to their response. Currently only Transaction will do
* this, since the commit is only called after writeTo, and it often
* messes up, so we want to be able to see the error message (SPEED writes
* the output directly, so errors in writeTo do not show up.)
* </p>
*
* <p>
* Most subclasses should not override, this method will most always return
* the SPEED strategy, since it is the fastest response and should work
* fine if everything is well tested. FILE and BUFFER should be used when
* there are errors in writeTo methods of child classes, set by the
* programmer in the web.xml file.
* </p>
*
* @return The service strategy found in the web.xml serviceStrategy
* parameter. The code that finds this is in the init method
*
* @throws ServiceException If the service strategy set in #init() is not
* valid.
*
* @see #init() for the code that sets the serviceStrategy.
*/
protected ServiceStrategy createServiceStrategy() throws ServiceException {
// If verbose exceptions is on then lets make sure they actually get the
// exception by using the file strategy.
ServiceStrategy theStrategy = null;
if (geoServer.isVerboseExceptions()) {
theStrategy = (ServiceStrategy) context.getBean("fileServiceStrategy");
} else {
if (serviceStrategy == null) {
// none set, look up in web applicatino context
serviceStrategy = getServletContext().getInitParameter("serviceStrategy");
}
// do a lookup
if (serviceStrategy != null) {
Map strategies = context.getBeansOfType(ServiceStrategy.class);
for (Iterator itr = strategies.values().iterator(); itr.hasNext();) {
ServiceStrategy bean = (ServiceStrategy) itr.next();
if (bean.getId().equals(serviceStrategy)) {
theStrategy = bean;
break;
}
}
}
}
if (theStrategy == null) {
// default to buffer
theStrategy = (ServiceStrategy) context.getBean("bufferServiceStrategy");
}
// clone the strategy since at the moment the strategies are marked as singletons
// in the web.xml file.
try {
theStrategy = (ServiceStrategy) theStrategy.clone();
} catch (CloneNotSupportedException e) {
LOGGER.log(Level.SEVERE,
"Programming error found, service strategies should be cloneable, " + e, e);
throw new RuntimeException("Found a strategy that does not support cloning...", e);
}
// TODO: this hack should be removed once modules have their own config
if (theStrategy instanceof PartialBufferStrategy2) {
if (partialBufferSize == 0) {
String size = getServletContext().getInitParameter("PARTIAL_BUFFER_STRATEGY_SIZE");
if (size != null) {
try {
partialBufferSize = Integer.valueOf(size).intValue();
if (partialBufferSize <= 0) {
LOGGER.warning("Invalid partial buffer size, defaulting to "
+ PartialBufferedOutputStream2.DEFAULT_BUFFER_SIZE + " (was "
+ partialBufferSize + ")");
partialBufferSize = 0;
}
} catch (NumberFormatException nfe) {
LOGGER.warning("Invalid partial buffer size, defaulting to "
+ PartialBufferedOutputStream2.DEFAULT_BUFFER_SIZE + " (was "
+ partialBufferSize + ")");
partialBufferSize = 0;
}
}
}
((PartialBufferStrategy2) theStrategy).setBufferSize(partialBufferSize);
}
return theStrategy;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected String getMimeType() {
ServletContext servContext = getServletContext();
try {
return ((GeoServer) servContext.getAttribute("GeoServer")).getMimeType();
} catch (NullPointerException e) {
return "text/xml; charset=" + Charset.forName("UTF-8").displayName();
}
}
/**
* DOCUMENT ME!
*
* @param response DOCUMENT ME!
* @param content DOCUMENT ME!
*/
protected void send(HttpServletResponse response, CharSequence content) {
send(response, content, getMimeType());
}
/**
* DOCUMENT ME!
*
* @param response DOCUMENT ME!
* @param content DOCUMENT ME!
* @param mimeType DOCUMENT ME!
*/
protected void send(HttpServletResponse response, CharSequence content, String mimeType) {
try {
response.setContentType(mimeType);
response.getWriter().write(content.toString());
} catch (IOException ex) { //stream closed by client, do nothing
LOGGER.info("Stream abruptly closed by client, response aborted");
LOGGER.fine(ex.getMessage());
} catch (IllegalStateException ex) { //stream closed by client, do nothing
LOGGER.info("Stream abruptly closed by client, response aborted");
LOGGER.fine(ex.getMessage());
}
}
/**
* Send error produced during getService opperation.
*
* <p>
* Some errors know how to write themselves out WfsTransactionException for
* instance. It looks like this might be is handled by
* getExceptionHandler().newServiceException( t, pre, null ). I still
* would not mind seeing a check for ServiceConfig Exception here.
* </p>
*
* <p>
* This code says that it deals with UNCAUGHT EXCEPTIONS, so I think it
* would be wise to explicitly catch ServiceExceptions.
* </p>
*
* @param response DOCUMENT ME!
* @param t DOCUMENT ME!
*/
protected void sendError(HttpServletRequest request, HttpServletResponse response, Throwable t) {
if (t instanceof ServiceException) {
sendError(request, response, (ServiceException) t);
return;
}
LOGGER.info("Had an undefined error: " + t.getMessage());
//TODO: put the stack trace in the logger.
//t.printStackTrace();
//String pre = "UNCAUGHT EXCEPTION";
ExceptionHandler exHandler = getExceptionHandler();
ServiceException se = exHandler.newServiceException(t);
sendError(request, response, se);
//GeoServer geoServer = (GeoServer) this.getServletConfig()
// .getServletContext().getAttribute(GeoServer.WEB_CONTAINER_KEY);
//send(response, se.getXmlResponse(geoServer.isVerboseExceptions()));
}
/**
* Send a serviceException produced during getService opperation.
*
* @param response DOCUMENT ME!
* @param se DOCUMENT ME!
*/
protected void sendError(HttpServletRequest request, HttpServletResponse response,
ServiceException se) {
// first log the exception
LOGGER.log(Level.SEVERE, "Service exception occurred", se);
String mimeType = se.getMimeType(geoServer);
send(response, se.getXmlResponse(geoServer.isVerboseExceptions(), request, geoServer),
mimeType);
}
/**
* DOCUMENT ME!
*
* @param response DOCUMENT ME!
* @param result DOCUMENT ME!
*/
protected void send(HttpServletRequest httpRequest, HttpServletResponse response,
Response result) {
OutputStream responseOut = null;
try {
responseOut = response.getOutputStream();
} catch (IOException ex) { //stream closed, do nothing.
LOGGER.info("apparently client has closed stream: " + ex.getMessage());
}
OutputStream out = new BufferedOutputStream(responseOut);
ServletContext servContext = getServletContext();
response.setContentType(result.getContentType(
(GeoServer) servContext.getAttribute("GeoServer")));
try {
result.writeTo(out);
out.flush();
responseOut.flush();
} catch (IOException ioe) {
//user just closed the socket stream, do nothing
LOGGER.fine("connection closed by user: " + ioe.getMessage());
} catch (ServiceException ex) {
sendError(httpRequest, response, ex);
}
}
/**
* Checks if the client requests supports gzipped responses by quering it's
* 'accept-encoding' header.
*
* @param request the request to query the HTTP header from
*
* @return true if 'gzip' if one of the supported content encodings of
* <code>request</code>, false otherwise.
*/
protected boolean requestSupportsGzip(HttpServletRequest request) {
boolean supportsGzip = false;
String header = request.getHeader("accept-encoding");
if ((header != null) && (header.indexOf("gzip") > -1)) {
supportsGzip = true;
}
if (LOGGER.isLoggable(Level.CONFIG)) {
LOGGER.config("user-agent=" + request.getHeader("user-agent"));
LOGGER.config("accept=" + request.getHeader("accept"));
LOGGER.config("accept-encoding=" + request.getHeader("accept-encoding"));
}
return supportsGzip;
}
public String getKvpString() {
return kvpString;
}
public void setKvpString(String kvpString) {
this.kvpString = kvpString;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -