/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.server.csw.provider;
import com.esri.gpt.framework.context.BaseServlet;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.security.identity.NotAuthorizedException;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.server.csw.provider.components.IOriginalXmlProvider;
import com.esri.gpt.server.csw.provider.components.IProviderFactory;
import com.esri.gpt.server.csw.provider.components.OperationContext;
import com.esri.gpt.server.csw.provider.components.OperationResponse;
import com.esri.gpt.server.csw.provider.components.OwsException;
import com.esri.gpt.server.csw.provider.components.RequestHandler;
import com.esri.gpt.server.csw.provider.local.ProviderFactory;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* CSW provider servlet.
*/
@SuppressWarnings("serial")
public class CswServlet extends BaseServlet {
/** class variables ========================================================= */
/** The Logger. */
private static Logger LOGGER = Logger.getLogger(CswServlet.class.getName());
/** instance variables ====================================================== */
private boolean allowTransactions = true;
private String cswSubContextPath;
private String resourceFilePrefix;
/** methods ================================================================= */
/**
* Initializes the servlet.
* <br/>Reads the "cswSubContextPath" and "resourceFilePrefix".
* init params from the servlet configuration.
* @param config the servlet configuration
* @throws ServletException if an initialization exception occurs
*/
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.cswSubContextPath = config.getInitParameter("cswSubContextPath");
this.resourceFilePrefix = config.getInitParameter("resourceFilePrefix");
String s = Val.chkStr(config.getInitParameter("allowTransactions"));
this.allowTransactions = !s.equalsIgnoreCase("false");
}
/**
* Executes a request.
* @param request the HTTP servlet request
* @param response the HTTP servlet response
* @param context the request context
* @throws Exception if a processing exception occurs
*/
protected void execute(HttpServletRequest request,
HttpServletResponse response,
RequestContext context)
throws Exception {
// check for a request to return a full xml
String sGetXmlUuid = "";
String sParamsLC = Val.chkStr(request.getQueryString());
if (sParamsLC.indexOf("getxml=") != -1) {
sGetXmlUuid = Val.chkStr(request.getParameter("getxml"));
// try to decode uuids that have been mistakenly double encoded by an external client
if (sGetXmlUuid.startsWith("%7B")) {
try {
String s = java.net.URLDecoder.decode(sGetXmlUuid,"UTF-8");
sGetXmlUuid = Val.chkStr(s);
} catch (UnsupportedEncodingException ue) {}
}
}
// return the full xml if requested
if (sGetXmlUuid.length() > 0) {
LOGGER.finer("Retrieving document: "+sGetXmlUuid);
String xml = "";
try {
xml = readFullXml(request,response,context,sGetXmlUuid);
} catch (NotAuthorizedException nae) {
throw nae;
} catch (Throwable t) {
LOGGER.warning("\nError retrieving document: "+sGetXmlUuid+"\n "+t.toString());
}
this.writeXmlResponse(response,Val.chkStr(xml));
// execute a normal CSW request
} else {
executeCSW(request,response,context);
}
}
/**
* Executes a CSW request.
* @param request the HTTP servlet request
* @param response the HTTP servlet response
* @param context the request context
* @throws Exception if a processing exception occurs
*/
protected void executeCSW(HttpServletRequest request,
HttpServletResponse response,
RequestContext context)
throws Exception {
// process the request
LOGGER.fine("Executing CSW provider request....");
String cswResponse = "";
String mimeType = "application/xml";
RequestHandler handler = null;
OperationResponse opResponse = null;
try {
String cswRequest = readInputCharacters(request);
LOGGER.finer("cswRequest:\n"+cswRequest);
handler = this.makeRequestHandler(request,response,context);
if (cswRequest.length() > 0) {
opResponse = handler.handleXML(cswRequest);
} else {
opResponse = handler.handleGet(request);
}
if (opResponse != null) {
cswResponse = Val.chkStr(opResponse.getResponseXml());
String fmt = Val.chkStr(opResponse.getOutputFormat());
if (fmt.equalsIgnoreCase("text/xml")) {
mimeType = "text/xml";
}
}
} catch (Exception e) {
OperationContext opContext = null;
if (handler != null) {
opContext = handler.getOperationContext();
}
cswResponse = handleException(opContext,e);
}
// write the response
LOGGER.finer("cswResponse:\n"+cswResponse);
if (cswResponse.length() > 0) {
writeCharacterResponse(response,cswResponse,"UTF-8",mimeType+"; charset=UTF-8");
}
}
/**
* Creation an ExceptionReport response when an exception is encountered.
* @param e the exception
* @return the exception report string
* @throws throws Exception if an authorization related exception occurs
* @deprecated replaced by {@link #handleException(OperationContext,Exception)}
*/
protected String handleException(Exception e) throws Exception {
return this.handleException(null,e);
}
/**
* Creation an ExceptionReport response when an exception is encountered.
* @param context the operation context
* @param e the exception
* @return the exception report string
* @throws throws Exception if an authorization related exception occurs
*/
protected String handleException(OperationContext context, Exception e) throws Exception {
if (e instanceof NotAuthorizedException) {
throw e;
} else if (e instanceof OwsException) {
OwsException ows = (OwsException)e;
LOGGER.finer("Invalid CSW request: "+e.getMessage());
return ows.getReport(context);
} else {
OwsException ows = new OwsException(e);
LOGGER.log(Level.WARNING,e.toString(),e);
return ows.getReport(context);
}
}
/**
* Makes a handler for the CSW request.
* @param request the HTTP servlet request
* @param response the HTTP servlet response
* @param context the request context
* @return the request handler
*/
protected RequestHandler makeRequestHandler(HttpServletRequest request,
HttpServletResponse response,
RequestContext context) {
IProviderFactory factory = new ProviderFactory();
RequestHandler handler = factory.makeRequestHandler(
request,context,this.cswSubContextPath,this.resourceFilePrefix);
if (handler != null) {
handler.getOperationContext().getServiceProperties().setAllowTransactions(this.allowTransactions);
}
return handler;
}
/**
* Reads the full XML associated with a document UUID.
* @param request the HTTP servlet request
* @param response the HTTP servlet response
* @param context the request context
* @param id the document id
* @return the document XML
* @throws Exception if an exception occurs
*/
protected String readFullXml(HttpServletRequest request,
HttpServletResponse response,
RequestContext context,
String id)
throws Exception {
RequestHandler handler = this.makeRequestHandler(request,response,context);
OperationContext opContext = handler.getOperationContext();
IProviderFactory factory = opContext.getProviderFactory();
IOriginalXmlProvider oxp = factory.makeOriginalXmlProvider(opContext);
if (oxp == null) {
String msg = "The getxml parameter is not supported.";
String locator = "getxml";
throw new OwsException(OwsException.OWSCODE_InvalidParameterValue,locator,msg);
} else {
String xml = oxp.provideOriginalXml(opContext,id);
return xml;
}
}
}