view software/eXist/mpdl-modules/src/de/mpg/mpiwg/berlin/mpdl/escidoc/ESciDocRESTServlet.java @ 0:408254cf2f1d

Erstellung
author Josef Willenborg <jwillenborg@mpiwg-berlin.mpg.de>
date Wed, 24 Nov 2010 17:24:23 +0100
parents
children
line wrap: on
line source

package de.mpg.mpiwg.berlin.mpdl.escidoc;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;

import de.mpg.mpiwg.berlin.mpdl.exception.ApplicationException;
import de.mpg.mpiwg.berlin.mpdl.general.MpdlConstants;
import de.mpg.mpiwg.berlin.mpdl.util.FileUtil;
import de.mpg.mpiwg.berlin.mpdl.util.XmlUtil;
import de.mpg.mpiwg.berlin.mpdl.xmlrpc.MpdlXmlRpcDocHandler;

public class ESciDocRESTServlet extends HttpServlet {
  private static final long serialVersionUID = -4889427839010526185L;
  private static int FILE_UPLOAD_MAX_MEMORY_SIZE = 100000;  // 100 KB
  private static String FILE_UPLOAD_TEMP_DIRECTORY = MpdlConstants.MPDL_EXIST_DATA_DIR + "/tmpUploadDir";
  
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    try {
      String escidocUrl = req.getParameter("escidocUrl");
      String query = req.getParameter("query");
      String queryPath = req.getParameter("queryPath");
      String parameters = req.getParameter("parameters");
      String startRecord = req.getParameter("startRecord");
      String maximumRecords = req.getParameter("maximumRecords");
      Cookie[] cookies = req.getCookies();
      String eScidDocCookie = getCookieValue(cookies, "escidocCookie");
      int startRecordInt = -1;
      if (startRecord != null && ! startRecord.equals(""))
        startRecordInt = Integer.parseInt(startRecord);
      int maximumRecordsInt = -1;
      if (maximumRecords != null && ! maximumRecords.equals(""))
        maximumRecordsInt = Integer.parseInt(maximumRecords);
      resp.setContentType("text/xml;charset=\"utf-8\"");  // important: otherwise the response is sent as iso-8859-1  
      PrintWriter out = resp.getWriter();
      // execute xquery script on eXist server
      if (escidocUrl != null && escidocUrl.startsWith("/exist:xquery/execute")) {
        if (query != null && ! query.equals("")) {
          String xqueryResult = xquery("string", query, null, startRecordInt, maximumRecordsInt);
          out.print(xqueryResult);
        } else if (queryPath != null && ! queryPath.equals("")) {
          String xqueryResult = xquery("uri", queryPath, parameters, startRecordInt, maximumRecordsInt);
          out.print(xqueryResult);
        }
      } else if (escidocUrl != null && escidocUrl.startsWith("/ir/item/") && escidocUrl.contains("/exist:xquery/execute")) {
        String existDocUrl = getExistDocUrl(eScidDocCookie, escidocUrl);
        String xQueryParamDocument = "<param name=\"document\">" + existDocUrl + "</param>";
        String params = "";
        if (parameters != null && ! parameters.equals("")) {
          int index = parameters.indexOf("</params>");
          params = parameters.substring(0, index) + xQueryParamDocument + parameters.substring(index);
        } else {
          params = "<params>" + xQueryParamDocument + "</params>";
        }
        if (query != null && ! query.equals("")) {
          String xqueryResult = xquery("string", query, params, startRecordInt, maximumRecordsInt);
          out.print(xqueryResult);
        } else if (queryPath != null && ! queryPath.equals("")) {
          String xqueryResult = xquery("uri", queryPath, params, startRecordInt, maximumRecordsInt);
          out.print(xqueryResult);
        }
      } else {
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println("<error>");
        out.print("EsciDoc does not support your URL: " + escidocUrl);
        out.print("</error>");
      }
    } catch (ApplicationException e) {
      throw new ServletException(e);
    }
  }
  
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    try {
      String escidocUrl = req.getParameter("escidocUrl");
      Cookie[] cookies = req.getCookies();
      String eScidDocCookie = getCookieValue(cookies, "escidocCookie");
      PrintWriter out = resp.getWriter();
      boolean isMultipart = ServletFileUpload.isMultipartContent(req);
      if (! isMultipart) { // if not multipartContent (e.g. set by client with setRequestBody or setRequestEntity)
        ServletInputStream is = req.getInputStream();
        File tmpUploadItemFile = File.createTempFile("item", ".xml", new File(FILE_UPLOAD_TEMP_DIRECTORY));
        String tmpUploadItemFileName = tmpUploadItemFile.getPath();
        FileUtil.getInstance().saveInputStreamToLocalFile(is, tmpUploadItemFileName);
        String containerId = getESciDocContainerId(escidocUrl);
        String newItemXmlStr = createItemInContainer(eScidDocCookie, containerId, tmpUploadItemFileName);  // create item and eXist document
        out.println(newItemXmlStr);
      } else {  // multipart content (each file item is uploaded) 
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(FILE_UPLOAD_MAX_MEMORY_SIZE);  // default is 100 KB
        File tmpFileUplaodDir = new File(FILE_UPLOAD_TEMP_DIRECTORY);
        factory.setRepository(tmpFileUplaodDir);  // for files which are bigger than the threshold; files are deleted, when they are garbage collected
        ServletFileUpload upload = new ServletFileUpload(factory);
        List<FileItem> items = upload.parseRequest(req);
        Iterator<FileItem> iter = items.iterator();
        while (iter.hasNext()) {
          /* fetch an item from the iterator above */
          FileItem item = iter.next();
          if (!item.isFormField()) {
            String fileName = item.getName(); 
            long sizeInBytes = item.getSize(); 
            File uploadedFile = new File(FILE_UPLOAD_TEMP_DIRECTORY + "/" + fileName); 
            item.write(uploadedFile); 
            out.println("<h1>File: " + uploadedFile.getAbsolutePath() + " (size: " + sizeInBytes + ") written</h1><br>");
          } 
        }
      }
    } catch (Exception e ) {
      throw new ServletException(e);
    }
  }

  protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter out = resp.getWriter();
    // TODO
    out.println("<html>");
    out.println("<body>");
    out.println("do put");
    out.println("</body>");
    out.println("</html>");
  }

  protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    try {
      String escidocUrl = req.getParameter("escidocUrl");
      Cookie[] cookies = req.getCookies();
      String cookieId = getCookieValue(cookies, "escidocCookie");
      PrintWriter out = resp.getWriter();
      if (escidocUrl != null && escidocUrl.startsWith("/ir/item/escidoc:")) {
        String existId = getExistDocUrl(cookieId, escidocUrl);
        ESciDocRestSession escidocRestSession = ESciDocRestSession.getInstance(cookieId);
        String itemId = escidocUrl;
        escidocRestSession.deleteItem(itemId);
        // delete eXist document
        MpdlXmlRpcDocHandler docHandler = MpdlXmlRpcDocHandler.getInstance();
        docHandler.deleteDocumentFile(existId);
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println("item: ");
        out.print(itemId);
        out.print(" sucessfully deleted in eSciDoc and eXist");
      } else {
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println("<error>");
        out.print("EsciDoc does not support your URL: " + escidocUrl);
        out.print("</error>");
      }
    } catch (ApplicationException e) {
      throw new ServletException(e);
    }
  }
  
  private void doDeleteOld(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    try {
      String escidocUrl = req.getParameter("escidocUrl");
      Cookie[] cookies = req.getCookies();
      String eScidDocCookie = getCookieValue(cookies, "escidocCookie");
      PrintWriter out = resp.getWriter();
      if (escidocUrl != null && escidocUrl.startsWith("/ir/item")) {
        String xQueryPath = "/mpdl/doc/rest-doc-operation.xql";
        String existDocUrl = getExistDocUrl(eScidDocCookie, escidocUrl);
        String strTmp = existDocUrl.substring(1);
        int index = strTmp.indexOf("/");
        String docBase = strTmp.substring(0, index);
        strTmp = strTmp.substring(index + 1);
        index = strTmp.indexOf("/");
        String language = strTmp.substring(0, index);
        String fileName = strTmp.substring(index + 1);
        String xQueryParamOperation = "<param name=\"operation\">delete</param>";
        String xQueryParamDocBase = "<param name=\"docBase\">" + docBase + "</param>";
        String xQueryParamLanguage = "<param name=\"language\">" + language + "</param>";
        String xQueryParamFileName = "<param name=\"fileName\">" + fileName + "</param>";
        String xQueryParams = "<params>" + xQueryParamOperation + xQueryParamDocBase + xQueryParamLanguage + xQueryParamFileName + "</params>";
        String xqueryResult = xqueryByPath(xQueryPath, xQueryParams, 1, 1);
        out.print(xqueryResult);
      } else {
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println("<error>");
        out.print("EsciDoc does not support your URL: " + escidocUrl);
        out.print("</error>");
      }
    } catch (ApplicationException e) {
      throw new ServletException(e);
    }
  }
  
  private String createItemInContainer(String cookieId, String containerId, String localFileName) throws ApplicationException {
    String retItemXmlStr = null;
    try {
      // create item in eSciDoc
      byte[] itemXmlBytes = FileUtil.getInstance().readBytes(localFileName);
      String itemXmlStr = new String(itemXmlBytes, "utf-8");
      ESciDocRestSession escidocRestSession = ESciDocRestSession.getInstance(cookieId);
      Item retItem = escidocRestSession.createItemInContainer(containerId, itemXmlStr);
      retItemXmlStr = retItem.toXmlString();
      // create/update eXist document
      MpdlXmlRpcDocHandler docHandler = MpdlXmlRpcDocHandler.getInstance();
      String existId = escidocRestSession.getFirstEXistId(itemXmlStr);
      String componentContentId = escidocRestSession.getFirstComponentId(retItemXmlStr);
      File tmpUploadExistFile = File.createTempFile("exist", ".xml", new File(FILE_UPLOAD_TEMP_DIRECTORY));
      String tmpUploadExistFileName = tmpUploadExistFile.getPath();
      escidocRestSession.saveComponentContentToLocalFile(componentContentId, tmpUploadExistFileName); 
      docHandler.saveDocumentFile(tmpUploadExistFileName, existId);
      FileUtil.getInstance().deleteFile(localFileName);
      FileUtil.getInstance().deleteFile(tmpUploadExistFileName);
    } catch (Exception e) {
      throw new ApplicationException(e);      
    }
    return retItemXmlStr;
  }
  
  private String getExistDocUrl(String cookieId, String escidocUrl) throws ApplicationException {
    ESciDocRestSession escidocRestSession = ESciDocRestSession.getInstance(cookieId);
    String itemId = getESciDocItemId(escidocUrl);
    String itemXmlStr = escidocRestSession.getItem(itemId);
    String existDocUrl = getEXistDocUrl(itemXmlStr);
    return existDocUrl;
  }
  
  private String xquery(String queryType, String xQuery, String xmlParameters, int startRecord, int maximumRecords) throws ApplicationException {
    String xQueryMethod = "/mpdl/interface/xquery.xql";
    String xQueryPath = "";
    String xqueryResult = null;
    if (queryType.equals("uri")) {
      xQueryPath = xQuery;
      xqueryResult = xqueryByPath(xQueryPath, xmlParameters, startRecord, maximumRecords);
    } else if (queryType.equals("string")) {
      xQueryPath = xQueryMethod;
      String paramXQuery = "<param name=\"xquery\">" + xQuery + "</param>";
      String params = "<params>" + paramXQuery + "</params>";
      if (xmlParameters != null) {
        int index = xmlParameters.indexOf("</params>");
        params = xmlParameters.substring(0, index) + paramXQuery + xmlParameters.substring(index);
      }
      xqueryResult = xqueryByPath(xQueryPath, params, startRecord, maximumRecords);
    }
    return xqueryResult;
  }
  
  private String xqueryByPath(String xQueryPath, String xmlParameters, int startRecord, int maximumRecords) throws ApplicationException {
    String requestName = xQueryPath;
    String parameters = getUrlStringByXmlParams(xmlParameters);
    if (parameters != null && ! parameters.equals("")) {
      if (startRecord != -1)
        parameters = parameters + "&startRecord=" + startRecord;
      if (maximumRecords != -1)
        parameters = parameters + "&maximumRecords=" + maximumRecords;
      requestName = requestName + "?" + parameters;
    } 
    String xqueryResult = performGetRequest(requestName, null);
    return xqueryResult;
  }
  
  private String getUrlStringByXmlParams(String xmlParameters) throws ApplicationException {
    String parameters = "";
    if (xmlParameters != null) {
      XmlUtil xmlUtil = XmlUtil.getInstance();
      ArrayList<String> paramNames = xmlUtil.evaluateToStringArray(xmlParameters, "//param/@name", null);
      ArrayList<String> paramValues = xmlUtil.evaluateToStringArray(xmlParameters, "//param", null);
      int size = paramValues.size();
      for (int i=0; i<size; i++) {
        String paramName = paramNames.get(i);
        String paramValue = paramValues.get(i);
        String paramValueEncoded = encode(paramValue);
        parameters = parameters + paramName + "=" + paramValueEncoded + "&";
      }
      parameters = parameters.substring(0, parameters.length() - 1); // without last "&"
    }
    return parameters;    
  }
  
  private String getEXistDocUrl(String itemXmlStr) throws ApplicationException {
    String retStr = null;
    if (itemXmlStr != null) {
      ESciDocRestSession escidocRestSession = ESciDocRestSession.getInstance(null);
      retStr = escidocRestSession.getFirstEXistId(itemXmlStr);
    }
    return retStr;    
  }
  
  private String getESciDocContainerId(String escidocUrl) {
    String retStr = null;
    int index = escidocUrl.indexOf("/ir/container/escidoc:");
    int indexNum = index + 22;
    int indexNext = escidocUrl.indexOf("/", indexNum);
    if (indexNext == -1)
      indexNext = escidocUrl.length();
    retStr = escidocUrl.substring(index, indexNext);
    return retStr;
  }
  
  private String getESciDocItemId(String escidocUrl) {
    String retStr = null;
    int index = escidocUrl.indexOf("/ir/item/escidoc:");
    int indexNum = index + 17;
    int indexNext = escidocUrl.indexOf("/", indexNum);
    if (indexNext == -1)
      indexNext = escidocUrl.length();
    retStr = escidocUrl.substring(index, indexNext);
    return retStr;
  }
  
  private String encode(String str) throws ApplicationException {
    String retStr = null;
    try {
      retStr = URLEncoder.encode(str, "utf-8");
    } catch (UnsupportedEncodingException e) {
      throw new ApplicationException(e);      
    }
    return retStr;    
  }

  private String getCookieValue(Cookie[] cookies, String name) {
    String value = null;
    for (int i=0; i<cookies.length; i++) {
      Cookie c = cookies[i];
      String n = c.getName();
      if (n.equals(name)) {
        value = c.getValue();
        break;
      }
    }
    return value;
  }
  
  private String performGetRequest(String requestName, String cookieId) throws ApplicationException {
    String resultStr = "";
    try {
      String urlStr = "http://" + MpdlConstants.MPDL_EXIST_HOST_NAME + ":" + MpdlConstants.MPDL_EXIST_PORT + requestName;
      GetMethod method = new GetMethod(urlStr);
      if (cookieId != null)
        method.setRequestHeader("Cookie", cookieId);
      HttpClient httpClient = new HttpClient();
      httpClient.executeMethod(method);
      byte[] responseBody = method.getResponseBody();
      resultStr = new String(responseBody, "utf-8");
      method.releaseConnection();
    } catch (HttpException e) {
      throw new ApplicationException(e);      
    } catch (IOException e) {
      throw new ApplicationException(e);      
    }
    return resultStr;
  } 
  
}