com.esri.gpt.control.rest.ManageDocumentServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.esri.gpt.control.rest.ManageDocumentServlet.java

Source

/* 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.control.rest;

import com.esri.gpt.catalog.arcims.ImsMetadataAdminDao;
import com.esri.gpt.catalog.arcims.ImsServiceException;
import com.esri.gpt.catalog.context.CatalogIndexException;
import com.esri.gpt.catalog.harvest.protocols.HarvestProtocol.ProtocolType;
import com.esri.gpt.catalog.harvest.repository.HrAssertUrlException;
import com.esri.gpt.catalog.harvest.repository.HrCompleteUpdateRequest;
import com.esri.gpt.catalog.harvest.repository.HrRecord;
import com.esri.gpt.catalog.harvest.repository.HrRecord.HarvestFrequency;
import com.esri.gpt.catalog.management.MmdActionCriteria;
import com.esri.gpt.catalog.management.MmdActionRequest;
import com.esri.gpt.catalog.management.MmdCriteria;
import com.esri.gpt.catalog.management.MmdEnums;
import com.esri.gpt.catalog.management.MmdResult;
import com.esri.gpt.catalog.publication.PublicationRecord;
import com.esri.gpt.catalog.publication.PublicationRequest;
import com.esri.gpt.catalog.publication.ValidationRequest;
import com.esri.gpt.catalog.schema.MetadataDocument;
import com.esri.gpt.catalog.schema.SchemaException;
import com.esri.gpt.catalog.schema.ValidationException;
import com.esri.gpt.control.webharvest.client.arcgis.ArcGISProtocol;
import com.esri.gpt.control.webharvest.protocol.ProtocolFactory;
import com.esri.gpt.control.webharvest.protocol.ProtocolInvoker;
import com.esri.gpt.framework.collection.StringAttribute;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.ApplicationConfiguration;
import com.esri.gpt.framework.context.ApplicationContext;
import com.esri.gpt.framework.context.BaseServlet;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.jsf.FacesContextBroker;
import com.esri.gpt.framework.jsf.MessageBroker;
import com.esri.gpt.framework.security.credentials.Credentials;
import com.esri.gpt.framework.security.credentials.CredentialsDeniedException;
import com.esri.gpt.framework.security.identity.IdentityException;
import com.esri.gpt.framework.security.identity.NotAuthorizedException;
import com.esri.gpt.framework.security.principal.Publisher;
import com.esri.gpt.framework.util.EnumerationAdapter;
import com.esri.gpt.framework.util.UuidUtil;
import com.esri.gpt.framework.util.Val;

import de.tudresden.gis.db.McpPublish;
import de.tudresden.gis.manage.http.HttpHelperMethods;
import de.tudresden.gis.manage.xml.Constant;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import org.apache.commons.io.IOUtils;
import org.n52.movingcode.runtime.codepackage.MovingCodePackage;

/**
 * Provides an HTTP REST interface for the management of an XML based metadata document.
 * <p/>
 * The URL pattern for this end-point is:<br/>
 * <i>http://host:port/application/</i><b>rest&#47;manage&#47;document</b> 
 * <p/>
 * Four HTTP methods are supported:
 * <ul>
 *   <li>GET - gets an XML document from the catalog
 *     <ul>
 *       <li>the subject document must be specified within the URL</li>
 *       <li>the XML is returned within the body of the HTTP response</li>
 *     </ul>
 *   <li>PUT - publishes an XML document to the catalog
 *     <ul>
 *       <li>the XML must be supplied within the body of the HTTP request.</li>
 *       <li>URL parameter publicationMethod is accepted, values are upload,editor,other</li>
 *       <li>URL parameter asDraft=true is accepted</li>
 *       <li>if no document provided, that means this is resource registration request.</li>
 *       <li>returns HTTP 200 when a document is replaced</li>
 *       <li>returns HTTP 201 when a document is created</li>
 *     </ul>
 *   <li>POST - same as PUT</li>
 *   <li>DELETE - deletes a document from the catalog
 *     <ul>
 *       <li>the subject document must be specified within the URL</li>
 *       <li>returns HTTP 200 when a document is deleted</li>
 *     </ul>
 * </ul>
 * The subject document can be specified within the URL as follows:
 * <ul>
 *   <li>.../rest/manage/document/<b>identifier</b></li>
 *   <li>.../rest/manage/document<b>?id=identifier</b></li>
 *   <li><b>identifier</b> can be the catalog's UUID for the document, 
 *         or the file identifier internal to the XML document</li>
 *   <li><b>identifier</b> must be properly URL encoded</li>
 * </ul>
 * Attributes applicable for resource registration:
 * <ul>
 *    <li>url - resource URL (required)</li>
 *    <li>uuid - UUID of the resource (optional). If provided this is an update of the already existing resource</li>
 *    <li>name - resource name/title (optional)</li>
 *    <li>protocol - protocol type (optional: res,arcgis,arcims,csw,oai,waf). Default: res</li>
 *    <li>frequency - frequency (optional: Monthly, BiWeekly, Weekly, Dayly, Hourly, Once, Skip). Default: Skip</li>
 *    <li>sendNotification - to send notification (optional: true,false). Default: false</li>
 *    <li>updateContent - to harvest content during synchronization (optional: true,false). Default: true</li>
 *    <li>updateDefinition - to update definition during synchronization (optional: true,false). Default: true</li>
 *    <li>autoApprove - to automatically approve newly acquired metadata (optional: true,false). Default: true</li>
 *    <li>findable - to make this resource findable when searching for metadata (optional: true, false), Default: true</li>
 *    <li>searchable - to make this resource to act as distributed search endpoint (only if csw) (optional: true, false), Default: true</li>
 *    <li>synchronizable - to make this resource synchronizable (optional: true, false), Default: true</li>
 *    <li>username - user name required to access protected resource (optional)</li>
 *    <li>password - password required to access protected resource (optional)</li>
 *    <li>soapurl - (ARCGIS only) resource SOAP URL</li>
 *    <li>profile - (CSW only) profile</li>
 *    <li>set - (OAI only) set</li>
 *    <li>prefix - (OAI only) prefix</li>
 *    <li>service - (ARCIMS only) service</li>
 *    <li>port - (ARCIMS only) port</li>
 *    <li>rootFolder - (ARCIMS only) root folder</li>
 * </ul>
 * Exceptions applicable to all methods:
 * <ul>
 *   <li>HTTP 401 Unauthorized 
 *       - indicates that valid credentials must be supplied to access this URL</li>
 *   <li>HTTP 403 The document is owned by another user. 
 *       - when an attempt is made to access a document owned by another user</li>
 * </ul>
 * Exceptions applicable to GET/DETETE:
 * <ul>
 *   <li>HTTP 404 Document not found.. 
 *       - when the document specified within the request URL could not be located 
 *         within the catalog</li>
 * </ul>
 * Exceptions applicable to PUT/POST:
 * <ul>
 *   <li>HTTP 400 IOException while reading request body. 
 *       - when characters could not be read from the request body</li>
 *   <li>HTTP 409 Document was empty. 
 *       - when the request body was empty</li>   
 *   <li>HTTP 409 Unable to parse document as XML. 
 *       - when the content of the request body cannot be parsed as XML</li> 
 *   <li>HTTP 409 Unrecognized metadata schema. 
 *       - when the supplied XML does not match a configured XML standard for the catalog</li>
 *   <li>HTTP 409 Document failed to validate.. 
 *       - when the supplied XML is invalid with respect to the configured validation rules 
 *         for the catalog</li> 
 *   <li>HTTP 409 XSD violation. 
 *       - when the supplied XML is invalid with respect to it's XSD</li> 
 *   <li>HTTP 409 Duplicated resource URL.
 *       - when registering new resource with URL as another already registered resource</li>
 * </ul>
 * 
 */
@MultipartConfig
public class ManageDocumentServlet extends BaseServlet {

    /** class variables ========================================================= */

    /** The logger.*/
    private static final Logger LOGGER = Logger.getLogger(ManageDocumentServlet.class.getName());

    /** methods ================================================================= */

    /**
     * Determines the source uri for a publication request.
     * @param request the servlet request
     * @param context the request context
     * @param publisher the publisher
     * @throws SQLException if an exception occurs while communicating with the database
     * @throws ServletException 
     */
    private void determineSourceUri(HttpServletRequest request, RequestContext context,
            PublicationRequest publicationRequest) throws SQLException, ServletException {
        String uuid = this.determineUuid(request, context, false);
        if ((uuid != null) && (uuid.length() > 0)) {
            publicationRequest.getPublicationRecord().setSourceFileName(uuid + ".xml");
            //sourceUri = uuid;
        } else {
            String pathInfo = Val.chkStr(request.getPathInfo());
            String queryString = Val.chkStr(request.getQueryString());
            if (pathInfo.startsWith("/"))
                pathInfo = pathInfo.substring(1);
            if (queryString.length() > 0) {
                pathInfo = pathInfo + "?" + queryString;
            }
            if (pathInfo.length() > 0) {
                //sourceUri = "userid:"+pubRequest.getPublisher().getLocalID()+"/"+pathInfo;
            }
        }
    }

    /**
     * Determines the specified document UIID from the HTTP request URL.
     * @param request the servlet request
     * @param context the request context
     * @param force if true, throw a ServletException if the document UUID is undetermined
     * @return the document UUID
     * @throws SQLException if an exception occurs while communicating with the database
     * @throws ServletException if the document UUID is undetermined (force=true only)
     */
    private String determineUuid(HttpServletRequest request, RequestContext context, boolean force)
            throws SQLException, ServletException {
        String uuid = "";
        String id = Val.chkStr(request.getParameter("id"));
        if (id.length() == 0) {
            String tmp = Val.chkStr(request.getPathInfo()).replaceAll("^/", "");
            try {
                id = Val.chkStr(URLDecoder.decode(tmp, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                // will never happen
            }
        }

        // determine the document uuid (the supplied id could be a gpt uuid or file identifier)
        if (id.length() > 0) {
            ImsMetadataAdminDao dao = new ImsMetadataAdminDao(context);
            uuid = dao.findUuid(id);
            if (!force && ((uuid == null) || (uuid.length() == 0))) {
                String tmpId = UuidUtil.addCurlies(id);
                if (tmpId.length() == 38) {
                    uuid = tmpId;
                }
            }
        }

        // throw an exception if the document uuid was not located
        if (force && ((uuid == null) || (uuid.length() == 0))) {
            throw new ServletException("404: Document not found.");
        }
        return uuid;
    }

    /**
     * Deletes a document from the catalog.
     * <br/>An HTTP 200 response code is set when a document is successfully deleted.
     * @param request the servlet request
     * @param response the servlet response
     * @throws ServletException if the request cannot be handled
     * @throws IOException if an I/O error occurs while handling the request 
     */
    @Override
    protected void doDelete(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.execute(request, response, "DELETE");
    }

    /**
     * Gets an XML document from the catalog.
     * <br/>The XML is returned within the body of the HTTP response.
     * @param request the servlet request
     * @param response the servlet response
     * @throws ServletException if the request cannot be handled
     * @throws IOException if an I/O error occurs while handling the request 
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.execute(request, response, "GET");
    }

    /**
     * Handles a POST request.
     * <br/>Same as doPut().
     * @param request the servlet request
     * @param response the servlet response
     * @throws ServletException if the request cannot be handled
     * @throws IOException if an I/O error occurs while handling the request 
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.execute(request, response, "POST");
    }

    /**
     * Publishes an XML document to the catalog.
     * <br/>The XML must be supplied within the body of the HTTP request.
     * <br/>An HTTP 200 response code is set when a document is successfully replaced.
     * <br/>An HTTP 201 response code is set when a document is successfully created.
     * @param request the servlet request
     * @param response the servlet response
     * @throws ServletException if the request cannot be handled
     * @throws IOException if an I/O error occurs while handling the request 
     */
    @Override
    protected void doPut(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.execute(request, response, "PUT");
    }

    /**
     * Provides a concrete executeUpdate() method to fulfill the sub-class requirement of the parent
     * BaseServlet class. 
     * This method is never invoked, all work is handled through 
     * doGet(), doPut(), doPost() and doDelete().
     */
    @Override
    protected void execute(HttpServletRequest request, HttpServletResponse response, RequestContext context)
            throws Exception {
    }

    /**
     * Processes the HTTP request.
     * @param request the HTTP request
     * @param response HTTP response
     * @param context request context
     * @param method the method to executeUpdate GET|PUT|POST|DELETE
     * @throws ServletException if the request cannot be handled
     * @throws IOException if an I/O error occurs while handling the request 
     */
    private void execute(HttpServletRequest request, HttpServletResponse response, String method)
            throws ServletException, IOException {

        RequestContext context = null;
        try {
            String msg = "HTTP " + method + ", " + request.getRequestURL().toString();
            if ((request.getQueryString() != null) && (request.getQueryString().length() > 0)) {
                msg += "?" + request.getQueryString();
            }
            getLogger().fine(msg);

            String sEncoding = request.getCharacterEncoding();
            if ((sEncoding == null) || (sEncoding.trim().length() == 0)) {
                request.setCharacterEncoding("UTF-8");
            }
            context = RequestContext.extract(request);

            //redirect to new method for list parameter without any authentication
            if (method.equals("GET") && request.getParameter("list") != null) {
                this.executeGetList(request, response, context);
                return;
            }
            if (method.equals("GET") && request.getParameter("download") != null) {
                this.executeGetPackage(request, response, context);
                return;
            }

            /// estabish the publisher
            StringAttributeMap params = context.getCatalogConfiguration().getParameters();
            String autoAuthenticate = Val.chkStr(params.getValue("BaseServlet.autoAuthenticate"));
            if (!autoAuthenticate.equalsIgnoreCase("false")) {
                Credentials credentials = getCredentials(request);
                if (credentials != null) {
                    this.authenticate(context, credentials);
                }
            }
            Publisher publisher = new Publisher(context);

            // executeUpdate the appropriate action
            if (method.equals("GET")) {
                this.executeGet(request, response, context, publisher);
            } else if (method.equals("POST")) {
                this.executePost(request, response, context, publisher);
            } else if (method.equals("PUT")) {
                this.executePut(request, response, context, publisher);
            } else if (method.equals("DELETE")) {
                this.executeDelete(request, response, context, publisher);
            }

        } catch (CredentialsDeniedException e) {
            String sRealm = this.getRealm(context);
            response.setHeader("WWW-Authenticate", "Basic realm=\"" + sRealm + "\"");
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } catch (NotAuthorizedException e) {
            String sRealm = this.getRealm(context);
            response.setHeader("WWW-Authenticate", "Basic realm=\"" + sRealm + "\"");
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } catch (ValidationException e) {
            String sMsg = e.toString();
            if (sMsg.contains("XSD violation.")) {
                sMsg = "XSD violation.";
            } else if (sMsg.contains("Invalid metadata document.")) {
                sMsg = "Invalid metadata document.";
            } else {
                sMsg = "Invalid metadata document.";
            }
            String json = Val.chkStr(request.getParameter("errorsAsJson"));
            if (json.length() > 0) {
                json = Val.escapeXmlForBrowser(json);
                FacesContextBroker fcb = new FacesContextBroker(request, response);
                MessageBroker msgBroker = fcb.extractMessageBroker();

                ArrayList<String> validationMessages = new ArrayList<String>();
                e.getValidationErrors().buildMessages(msgBroker, validationMessages, true);

                StringBuilder sb = new StringBuilder();
                sb.append(json).append(" = {\r\n");
                sb.append("message: \"").append(Val.escapeStrForJson(sMsg)).append("\",\r\n");
                sb.append("code: 409,\r\n");
                sb.append("errors: [\r\n");
                for (int i = 0; i < validationMessages.size(); i++) {
                    if (i > 0) {
                        sb.append(",\r\n");
                    }
                    sb.append("\"").append(Val.escapeStrForJson(validationMessages.get(i))).append("\"");
                }
                if (validationMessages.size() > 0) {
                    sb.append("\r\n");
                }
                sb.append("]}");

                LOGGER.log(Level.SEVERE, sb.toString());
                response.getWriter().print(sb.toString());
            } else {
                response.sendError(409, sMsg);
            }
        } catch (ServletException e) {
            String sMsg = e.getMessage();
            int nCode = Val.chkInt(sMsg.substring(0, 3), 500);
            sMsg = Val.chkStr(sMsg.substring(4));
            String json = Val.chkStr(request.getParameter("errorsAsJson"));
            if (json.length() > 0) {
                json = Val.escapeXmlForBrowser(json);
                StringBuilder sb = new StringBuilder();
                sb.append(json).append(" = {\r\n");
                sb.append("message: \"").append(Val.escapeStrForJson(sMsg)).append("\",\r\n");
                sb.append("code: ").append(nCode).append(",\r\n");
                sb.append("errors: [\r\n");
                sb.append("\"").append(Val.escapeStrForJson(sMsg)).append("\"");
                sb.append("]}");

                LOGGER.log(Level.SEVERE, sb.toString());
                response.getWriter().print(sb.toString());
            } else {
                response.sendError(nCode, sMsg);
            }
        } catch (Throwable t) {
            String sMsg = t.toString();
            String json = Val.chkStr(request.getParameter("errorsAsJson"));
            if (json.length() > 0) {
                json = Val.escapeXmlForBrowser(json);
                StringBuilder sb = new StringBuilder();
                sb.append(json).append(" = {\r\n");
                sb.append("message: \"").append(Val.escapeStrForJson(sMsg)).append("\",\r\n");
                sb.append("code: ").append(500).append(",\r\n");
                sb.append("errors: [\r\n");
                sb.append("\"").append(Val.escapeStrForJson(sMsg)).append("\"");
                sb.append("]}");

                LOGGER.log(Level.SEVERE, sb.toString());
                response.getWriter().print(sb.toString());
            } else if (sMsg.contains("The document is owned by another user:")) {
                response.sendError(HttpServletResponse.SC_FORBIDDEN, "The document is owned by another user.");
            } else {
                //String sErr = "Exception occured while processing servlet request.";
                //getLogger().log(Level.SEVERE,sErr,t);
                //response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                //    sMsg + sErr);
            }
        } finally {
            if (context != null)
                context.onExecutionPhaseCompleted();
        }
    }

    /**
     * Deletes the metadata document specified within the URL.
     * @param request the servlet request
     * @param response the servlet response
     * @param context the request context
     * @param publisher the publisher
     * @throws Exception if an exception occurs
     */
    private void executeDelete(HttpServletRequest request, HttpServletResponse response, RequestContext context,
            Publisher publisher) throws Exception {
        String uuid = this.determineUuid(request, context, true);
        MmdActionCriteria actionCriteria = new MmdActionCriteria();
        actionCriteria.setActionKey("delete");
        actionCriteria.getSelectedRecordIdSet().add(uuid);
        MmdResult result = new MmdResult();
        MmdCriteria criteria = new MmdCriteria();
        criteria.setActionCriteria(actionCriteria);
        MmdActionRequest actionRequest = new MmdActionRequest(context, publisher, criteria, result);
        actionRequest.execute();
        LOGGER.finer(result.getActionResult().getNumberOfRecordsModified() + " document(s) deleted.");
    }

    /**
     * Gets the XML string associated with the metadata document specified within the URL.
     * @param request the servlet request
     * @param response the servlet response
     * @param context the request context
     * @param publisher the publisher
      * @throws Exception if an exception occurs
     */
    private void executeGet(HttpServletRequest request, HttpServletResponse response, RequestContext context,
            Publisher publisher) throws Exception {
        String uuid = this.determineUuid(request, context, true);
        MetadataDocument mdDoc = new MetadataDocument();
        String xml = Val.chkStr(mdDoc.prepareForDownload(context, publisher, uuid));
        if (xml.length() > 0) {
            this.writeXmlResponse(response, xml);
        }
    }

    /**
     * Publishes the XML metadata document supplied within the request body.
     * <br/>this method is a pass-turu to executePut().
     * @param request the servlet request
     * @param response the servlet response
     * @param context the request context
     * @param publisher the publisher
     * @throws Exception if an exception occurs
     */
    private void executePost(HttpServletRequest request, HttpServletResponse response, RequestContext context,
            Publisher publisher) throws Exception {
        this.executePut(request, response, context, publisher);
    }

    /**
     * Publishes the XML metadata document supplied within the request body.
     * @param request the servlet request
     * @param response the servlet response
     * @param context the request context
     * @param publisher the publisher
     * @throws Exception if an exception occurs
     */
    private void executePut(HttpServletRequest request, HttpServletResponse response, RequestContext context,
            Publisher publisher) throws Exception {
        String xml = null;
        HrRecord record = extractRegistrationInfo(request);
        //get multipart request for xml creating + upload
        try {
            //create mode - xml and zip are sended via parts 
            if (request.getParts().size() > 0) {
                createAndUpload(request, response, context, publisher);
                return;
            }
        } catch (Exception e) {
        }
        //else normal - edit mode (no parts, no zip file - only xml change)
        if (record == null) {
            try {
                xml = this.readInputCharacters(request);
            } catch (IOException e) {
                throw new ServletException("400: IOException while reading request body.");
            }
            xml = Val.chkStr(Val.removeBOM(xml));
            if (xml.length() > 0) {
                PublicationRequest pubRequest = new PublicationRequest(context, publisher, xml);
                PublicationRecord pubRecord = pubRequest.getPublicationRecord();

                pubRecord.setPublicationMethod(MmdEnums.PublicationMethod.upload.toString());
                String pubMethod = Val.chkStr(request.getParameter("publicationMethod"));
                if (pubMethod.length() > 0) {
                    try {
                        pubMethod = MmdEnums.PublicationMethod.valueOf(Val.chkStr(pubMethod)).toString();
                        pubRecord.setPublicationMethod(pubMethod);
                    } catch (IllegalArgumentException ex) {
                    }
                }

                String asDraft = Val.chkStr(request.getParameter("asDraft"));
                if (asDraft.equals("true")) {
                    pubRecord.setApprovalStatus(MmdEnums.ApprovalStatus.draft.toString());
                }

                this.determineSourceUri(request, context, pubRequest);
                try {
                    pubRequest.publish();
                    //SAVE XML TO ZIP ARCHIVE
                    saveXml2Package(xml, pubRecord.getUuid());

                    if (!pubRecord.getWasDocumentReplaced()) {
                        response.setStatus(HttpServletResponse.SC_CREATED);
                    }
                    //Validation error triggert via pubRequest.publish /ValidationRequest
                } catch (ValidationException e) {
                    String sMsg = e.toString();
                    if (sMsg.contains("XSD violation.")) {
                        throw new ServletException("409: XSD violation.");
                    } else if (sMsg.contains("Invalid metadata document.")) {
                        throw new ServletException("409: Document failed to validate.");
                    } else {
                        throw new ServletException("409: Document failed to validate.");
                    }
                } catch (SchemaException e) {
                    String sMsg = e.toString();
                    if (sMsg.contains("Unrecognized metadata schema.")) {
                        throw new ServletException("409: Unrecognized metadata schema.");
                    } else if (sMsg.contains("Unable to parse document.")) {
                        throw new ServletException("409: Unable to parse document as XML.");
                    } else {
                        throw e;
                    }
                }
            } else {
                throw new ServletException("409: Document was empty.");
            }
        } else {
            try {
                HrCompleteUpdateRequest req = new HrCompleteUpdateRequest(context, record);
                req.execute();
                response.setStatus(HttpServletResponse.SC_CREATED);
            } catch (HrAssertUrlException e) {
                throw new ServletException("409: Duplicated resource URL.");
            } catch (ValidationException e) {
                String sMsg = e.toString();
                if (sMsg.contains("XSD violation.")) {
                    throw new ServletException("409: XSD violation.");
                } else if (sMsg.contains("Invalid metadata document.")) {
                    throw new ServletException("409: Document failed to validate.");
                } else {
                    throw new ServletException("409: Document failed to validate.");
                }
            } catch (SchemaException e) {
                String sMsg = e.toString();
                if (sMsg.contains("Unrecognized metadata schema.")) {
                    throw new ServletException("409: Unrecognized metadata schema.");
                } else if (sMsg.contains("Unable to parse document.")) {
                    throw new ServletException("409: Unable to parse document as XML.");
                } else {
                    throw e;
                }
            } catch (Exception ex) {
                throw new ServletException("409: Unable to register resource.");
            }
        }
    }

    /**
     * Extracts registration info.
     * @param request HTTP request
     * @return registration info or <code>null</code> if unable to extract registration info
     */
    private HrRecord extractRegistrationInfo(HttpServletRequest request) {
        ApplicationContext appCtx = ApplicationContext.getInstance();
        ApplicationConfiguration appCfg = appCtx.getConfiguration();

        HrRecord record = new HrRecord();
        StringAttributeMap attributes = new StringAttributeMap();
        boolean updateContent = true;
        boolean updateDefinition = true;
        boolean autoApprove = true;

        for (String paramName : new EnumerationAdapter<String>(request.getParameterNames())) {
            String paramValue = request.getParameter(paramName);
            if (paramName.equalsIgnoreCase("uuid")) {
                record.setUuid(paramValue);
            }
            if (paramName.equalsIgnoreCase("name")) {
                record.setName(paramValue);
            } else if (paramName.equalsIgnoreCase("url")) {
                record.setHostUrl(paramValue);
            } else if (paramName.equalsIgnoreCase("soapurl")) {
                attributes.add(new StringAttribute(ArcGISProtocol.SOAP_URL, paramValue));
            } else if (paramName.equalsIgnoreCase("protocol")) {
                ProtocolFactory factory = appCfg.getProtocolFactories().get(paramValue);
                if (factory != null) {
                    record.setProtocol(factory.newProtocol());
                }
            } else if (paramName.equalsIgnoreCase("frequency")) {
                record.setHarvestFrequency(HarvestFrequency.checkValueOf(paramValue));
            } else if (paramName.equalsIgnoreCase("sendNotification")) {
                record.setSendNotification(Val.chkBool(paramValue, false));
            } else if (paramName.equalsIgnoreCase("updateContent")) {
                updateContent = Val.chkBool(paramValue, true);
            } else if (paramName.equalsIgnoreCase("updateDefinition")) {
                updateDefinition = Val.chkBool(paramValue, true);
            } else if (paramName.equalsIgnoreCase("autoApprove")) {
                autoApprove = Val.chkBool(paramValue, true);
            } else if (paramName.equalsIgnoreCase("findable")) {
                record.setFindable(Val.chkBool(paramValue, true));
            } else if (paramName.equalsIgnoreCase("searchable")) {
                record.setSearchable(Val.chkBool(paramValue, true));
            } else if (paramName.equalsIgnoreCase("synchronizable")) {
                record.setSynchronizable(Val.chkBool(paramValue, true));
            } else {
                attributes.add(new StringAttribute(paramName, paramValue));
            }
        }

        if (record.getProtocol() == null
                || record.getProtocol().getKind().equalsIgnoreCase(ProtocolType.None.name())) {
            ProtocolFactory factory = appCfg.getProtocolFactories().get(ProtocolType.RES.name());
            if (factory != null) {
                record.setProtocol(factory.newProtocol());
            }
        }

        if (record.getProtocol() != null) {
            record.getProtocol().setAttributeMap(attributes);
            ProtocolInvoker.setUpdateDefinition(record.getProtocol(), updateDefinition);
            ProtocolInvoker.setUpdateContent(record.getProtocol(), updateContent);
            ProtocolInvoker.setAutoApprove(record.getProtocol(), autoApprove);
        }

        record = record.getName().length() > 0 && record.getHostUrl().length() > 0 && record.getProtocol() != null
                ? record
                : null;

        return record;
    }

    private boolean saveXml2Package(String xml, String uuid) throws IOException {
        uuid = UuidUtil.removeCurlies(uuid);
        //xml file
        String folder = Constant.UPLOAD_FOLDER;

        File temp = new File(folder + File.separator + uuid + File.separator + Constant.XML_OUTPUT_FILE_NAME);
        InputStream in = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
        //InputStream in = doc.newInputStream();
        Path a = temp.toPath();
        Files.copy(in, a, java.nio.file.StandardCopyOption.REPLACE_EXISTING);

        //copy xml file into zip file
        Map<String, String> env = new HashMap<>();
        env.put("create", "true");
        Path path = null;
        path = Paths.get(folder + File.separator + uuid + File.separator + Constant.XML_OUTPUT_ZIP_NAME);
        URI uri = URI.create("jar:" + path.toUri());

        try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
            Files.copy(Paths.get(folder + File.separator + uuid + File.separator + Constant.XML_OUTPUT_FILE_NAME),
                    fs.getPath(Constant.XML_OUTPUT_FILE_NAME), StandardCopyOption.REPLACE_EXISTING);
        }

        return true;
    }

    private void createAndUpload(HttpServletRequest request, HttpServletResponse response, RequestContext context,
            Publisher publisher) throws IOException, IllegalStateException, ServletException, SchemaException,
            CatalogIndexException, ImsServiceException, SQLException, NotAuthorizedException, IdentityException {

        //XML
        InputStream xmlStream = request.getPart("xml").getInputStream();
        String xml = IOUtils.toString(xmlStream, "UTF-8");
        xml = Val.chkStr(Val.removeBOM(xml));

        //read file
        OutputStream out = null;
        InputStream filecontent = request.getPart("file").getInputStream();

        //ID
        InputStream idStream = request.getPart("id").getInputStream();
        String id = IOUtils.toString(idStream, "UTF-8");
        /**Collection<Part> x = request.getParts();
        Part[] array = x.toArray (new Part[x.size ()]);
        for(int f=0; f<array.length;f++){
           System.out.println(array[f].getName() + " " + array[f].getSize());
        }*/

        //verify - throw servlet exception
        ValidationRequest vRequest = new ValidationRequest(context, "id", xml);
        // in case of schema problems verify method would throw exception
        try {
            vRequest.verify();
        } catch (ValidationException e) {
            System.out.println("valid error: " + e);
            throw new ServletException("409: Document failed to validate.");
        }

        //Save Zip file
        String webDataPath = Constant.UPLOAD_FOLDER, folder = id;
        new File(webDataPath + File.separator + folder).mkdir();
        try {
            //initiate output stream
            out = new FileOutputStream(new File(
                    webDataPath + File.separator + folder + File.separator + Constant.XML_OUTPUT_ZIP_NAME));
            int read = 0;
            final byte[] bytes = new byte[1024];
            while ((read = filecontent.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
        } finally {
            //close all open streams if necessary
            if (out != null) {
                out.close();
            }
            if (filecontent != null) {
                filecontent.close();
            }
        }

        //save xml in mcp
        saveXml2Package(xml, id);

        //save xml in db
        if (xml.length() > 0) {
            //PublicationRequest pubRequest = new PublicationRequest(context,publisher,xml);
            //PublicationRecord pubRecord = pubRequest.getPublicationRecord();
            //pubRecord.setPublicationMethod("editor");
            //pubRequest.publish();
            MovingCodePackage mvp = new MovingCodePackage(new File(
                    webDataPath + File.separator + folder + File.separator + Constant.XML_OUTPUT_ZIP_NAME));
            McpPublish mcpP = new McpPublish(mvp,
                    webDataPath + File.separator + folder + File.separator + Constant.XML_OUTPUT_ZIP_NAME, id,
                    context);
            if (mcpP.publish(false))
                System.out.println("publishing successfully");
        }

        response.setStatus(HttpServletResponse.SC_CREATED);
    }

    private void executeGetList(HttpServletRequest request, HttpServletResponse response, RequestContext context)
            throws Exception {

        String list = request.getParameter("list");
        int count = 3;
        if (request.getParameter("count") != null) {
            count = Integer.parseInt(request.getParameter("count"));
        }
        if (list.equals("recent")) {
            String json = HttpHelperMethods.getRecent(count);
            response.setContentType("application/json");
            PrintWriter out = response.getWriter();
            out.print(json);
            out.flush();
        }
        if (list.equals("top")) {
            String json = HttpHelperMethods.getTopRated(count);
            response.setContentType("application/json");
            PrintWriter out = response.getWriter();
            out.print(json);
            out.flush();
        }
        if (list.contains("id:")) {
            String json = HttpHelperMethods.getEntryWithID(list.replace("id:", ""));
            response.setContentType("application/json");
            PrintWriter out = response.getWriter();
            out.print(json);
            out.flush();
        }

    }

    private void executeGetPackage(HttpServletRequest request, HttpServletResponse response, RequestContext context)
            throws Exception {

        String id = request.getParameter("download");
        String value = UuidUtil.removeCurlies(id);
        String path = Constant.UPLOAD_FOLDER + File.separator + value + File.separator
                + Constant.XML_OUTPUT_ZIP_NAME;
        File file = new File(path);
        InputStream fis = new FileInputStream(file);

        //HttpServletResponse response =
        //         (HttpServletResponse) FacesContext.getCurrentInstance()
        //        .getExternalContext().getResponse();
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename=package.zip");
        OutputStream responseOutput = response.getOutputStream();

        byte[] buf = new byte[2048];
        int bytesRead;
        while ((bytesRead = fis.read(buf)) > 0) {
            responseOutput.write(buf, 0, bytesRead);
        }
        responseOutput.flush();
        fis.close();
        responseOutput.close();
        FacesContext.getCurrentInstance().responseComplete();

    }

}