/* 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.catalog.management.MmdEnums;
import com.esri.gpt.catalog.publication.PublicationRecord;
import com.esri.gpt.catalog.publication.PublicationRequest;
import com.esri.gpt.catalog.schema.UnrecognizedSchemaException;
import com.esri.gpt.catalog.schema.ValidationException;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.security.principal.Publisher;
import com.esri.gpt.framework.util.Val;
import com.esri.gpt.framework.xml.XmlIoUtil;
import com.esri.gpt.server.csw.provider.components.IOperationProvider;
import com.esri.gpt.server.csw.provider.components.IProviderFactory;
import com.esri.gpt.server.csw.provider.components.IResponseGenerator;
import com.esri.gpt.server.csw.provider.components.OperationContext;
import com.esri.gpt.server.csw.provider.components.OwsException;
import com.esri.gpt.server.csw.provider.components.TransactionOptions;
import com.esri.gpt.server.csw.provider.components.TransactionSummary;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Provides the CSW Transaction/Insert operation.
*/
public class InsertProvider implements IOperationProvider {
/** class variables ========================================================= */
/** The Logger. */
private static Logger LOGGER = Logger.getLogger(InsertProvider.class.getName());
/** constructors ============================================================ */
/** Default constructor */
public InsertProvider() {
super();
}
/** methods ================================================================= */
/**
* Generates the response.
* @param context the operation context
* @throws Exception if a processing exception occurs
*/
public void generateResponse(OperationContext context) throws Exception {
IProviderFactory factory = context.getProviderFactory();
IResponseGenerator generator = factory.makeResponseGenerator(context);
if (generator == null) {
String msg = "IProviderFactory.makeResponseGenerator: instantiation failed.";
LOGGER.log(Level.SEVERE,msg);
throw new OwsException(msg);
} else {
generator.generateResponse(context);
}
}
/**
* Handles a URL based request (HTTP GET).
* @param context the operation context
* @param request the HTTP request
* @throws Exception if a processing exception occurs
*/
public void handleGet(OperationContext context, HttpServletRequest request)
throws Exception {
// initialize
LOGGER.finer("Handling csw:Transaction/csw:Insert request URL...");
throw new OwsException("HTTP Get is not supported for this operation.");
/*
// initialize
LOGGER.finer("Handling ccsw:Transaction/csw:Insert request URL...");
Publisher publisher = new Publisher(context.getRequestContext());
ParseHelper pHelper = new ParseHelper();
ValidationHelper vHelper = new ValidationHelper();
String locator;
String[] parsed;
// type name and handle
String typeName = null;
String handle = null;
// XML document(s) to insert
//String[] parameterNames = new String[]{"xml,record,metadata,md_metadata"};
String[] parameterNames = new String[]{"xml"};
for (String parameterName: parameterNames) {
parsed = pHelper.getParameterValues(request,parameterName);
if (parsed != null) {
for (String xml: parsed) {
this.publishDocument(context,publisher,typeName,handle,xml);
}
}
}
// generate the response
this.generateResponse(context);
*/
}
/**
* Handles an XML based request (normally HTTP POST).
* @param context the operation context
* @param root the root node
* @param xpath an XPath to enable queries (properly configured with name spaces)
* @throws Exception if a processing exception occurs
*/
public void handleXML(OperationContext context, Node root, XPath xpath)
throws Exception {
// initialize
LOGGER.finer("Handling csw:Transaction/csw:Insert request XML...");
Publisher publisher = new Publisher(context.getRequestContext());
// find all the Insert nodes
String locator = "csw:Insert";
NodeList nlActions = (NodeList)xpath.evaluate(locator,root,XPathConstants.NODESET);
if (nlActions != null) {
for (int i=0;i<nlActions.getLength();i++) {
Node ndAction = nlActions.item(i);
String typeName = xpath.evaluate("@typeName",ndAction);
String handle = xpath.evaluate("@handle",ndAction);
// publish all XML documents contained
NodeList nlXmls = ndAction.getChildNodes();
this.processDocumentNodes(context,publisher,typeName,handle,nlXmls);
}
}
// generate the response
this.generateResponse(context);
}
/**
* Processes and publishes the XML document child nodes associated with
* the parent action.
* @param context the operation context
* @param publisher the authenticated publisher
* @param typeName the CSW collection type
* @param handle a client supplied name (can be echoed within the response)
* @param xmlNodes a list of child nodes containing XML's to publish
* @throws Exception if a processing exception occurs
*/
public void processDocumentNodes(OperationContext context,
Publisher publisher,
String typeName,
String handle,
NodeList xmlNodes)
throws Exception {
int nElementNodes = 0;
for (int i=0;i<xmlNodes.getLength();i++) {
Node ndXml = xmlNodes.item(i);
if (ndXml.getNodeType() == Node.ELEMENT_NODE) {
nElementNodes++;
StringWriter result = new StringWriter();
XmlIoUtil.transform(new DOMSource(ndXml),new StreamResult(result),true) ;
String xmlInsert = result.toString();
//Document domInsert = DomUtil.newDocument();
//Node ndAdopted = domInsert.adoptNode(ndXml);
//domInsert.appendChild(ndAdopted);
//String xmlInsert = XmlIoUtil.domToString(domInsert);
xmlInsert = Val.chkStr(Val.removeBOM(xmlInsert));
this.publishDocument(context,publisher,typeName,handle,xmlInsert);
}
}
if (nElementNodes == 0) {
String locator = "csw:Insert/*";
if (this instanceof UpdateProvider) {
locator = "csw:Update/*";
}
String msg = "No child documents were included for publication.";
throw new OwsException(OwsException.OWSCODE_MissingParameterValue,locator,msg);
}
}
/**
* Publishes a document to the catalog.
* @param context the operation context
* @param publisher the authenticated publisher
* @param typeName the CSW collection type
* @param handle a client supplied name (can be echoed within the response)
* @param xml the document XML to publish
* @throws Exception if a processing exception occurs
*/
public void publishDocument(OperationContext context,
Publisher publisher,
String typeName,
String handle,
String xml)
throws Exception {
handle = Val.chkStr(handle);
xml = Val.chkStr(Val.removeBOM(xml));
TransactionOptions tOptions = context.getRequestOptions().getTransactionOptions();
TransactionSummary tSummary = tOptions.getSummary();
PublicationRequest pubRequest = new PublicationRequest(
context.getRequestContext(),publisher,xml);
PublicationRecord pubRecord = pubRequest.getPublicationRecord();
pubRecord.setPublicationMethod(MmdEnums.PublicationMethod.upload.toString());
if (tOptions.getAutoApprove()) {
pubRecord.setAutoApprove(true);
}
if ((tOptions.getApprovalStatus() != null) && (tOptions.getApprovalStatus().length() > 0)) {
pubRecord.setApprovalStatus(MmdEnums.ApprovalStatus.valueOf(tOptions.getApprovalStatus()).toString());
}
if ((tOptions.getPublicationMethod() != null) && (tOptions.getPublicationMethod().length() > 0)) {
pubRecord.setPublicationMethod(MmdEnums.PublicationMethod.valueOf(tOptions.getPublicationMethod()).toString());
}
// TODO: need a sourceUri
//this.determineSourceUri(request,context,pubRequest);
try {
pubRequest.publish();
if (pubRecord.getWasDocumentUnchanged()) {
} else if (pubRecord.getWasDocumentReplaced()) {
tSummary.setTotalUpdated(tSummary.getTotalUpdated() + 1);
} else {
tSummary.setTotalInserted(tSummary.getTotalInserted() + 1);
}
} catch (ValidationException e) {
MessageBroker msgBroker = new MessageBroker();
msgBroker.setBundleBaseName(MessageBroker.DEFAULT_BUNDLE_BASE_NAME);
ArrayList<String> messages = new ArrayList<String>();
e.getValidationErrors().buildMessages(msgBroker,messages,true);
StringBuilder sb = new StringBuilder();
sb.append("<![CDATA[");
sb.append("\r\nMetadata Validation Exception");
if (handle.length() > 0) {
sb.append("\r\nhandle=").append(handle);
sb.append(", sk=").append(e.getKey());
} else {
sb.append("\r\nsk=").append(e.getKey());
}
String id = Val.chkStr(pubRecord.getUuid());
if (id.length() > 0) {
sb.append(", id=").append(id);
}
for (String msg : messages) {
sb.append("\r\n").append(msg);
}
sb.append("\r\n]]>");
throw new OwsException(sb.toString());
} catch (UnrecognizedSchemaException e) {
StringBuilder sb = new StringBuilder();
sb.append("<![CDATA[");
sb.append("\r\n").append(e.getMessage());
if (handle.length() > 0) {
sb.append("\r\nhandle=").append(handle);
}
sb.append("\r\n]]>");
throw new OwsException(sb.toString());
}
}
}