Package maqetta.core.server

Source Code of maqetta.core.server.DavinciPageServlet

package maqetta.core.server;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

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

import org.davinci.ajaxLibrary.ILibraryManager;
import org.davinci.server.internal.Activator;
import org.davinci.server.user.IUser;
import org.davinci.server.user.IUserManager;
import org.davinci.server.user.UserException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.maqetta.server.IDavinciServerConstants;
import org.maqetta.server.IServerManager;
import org.maqetta.server.IVResource;
import org.maqetta.server.ServerManager;
import org.maqetta.server.VURL;
import org.maqetta.server.Validator;
import org.osgi.framework.Bundle;

public class DavinciPageServlet extends HttpServlet {

  static final private Logger theLogger = Logger.getLogger(DavinciPageServlet.class.getName());

  private static final long serialVersionUID = 1L;
  private static final String LAST_MODIFIED = "Last-Modified"; //$NON-NLS-1$
  private static final String IF_MODIFIED_SINCE = "If-Modified-Since"; //$NON-NLS-1$
  private static final String IF_NONE_MATCH = "If-None-Match"; //$NON-NLS-1$
  private static final String ETAG = "ETag"; //$NON-NLS-1$
  private static final String CACHE_CONTROL = "Cache-Control"; //$NON-NLS-1$
  private static final String PRAGMA = "Pragma"; //$NON-NLS-1$
  private static final String EXPIRES = "Expires"; //$NON-NLS-1$
  private static final long maxAge = 30*24*60*60; // 30 days

  private enum CacheHeaders {
    CACHE, NO_CACHE
  }

  protected IUserManager userManager;
  protected IServerManager serverManager;
  protected ILibraryManager libraryManager;

  public void initialize() {
    serverManager = ServerManager.getServerManager();
    userManager = serverManager.getUserManager();
    libraryManager = serverManager.getLibraryManager();
  }

  private void log(HttpServletRequest req, IUser user) {
    String log = "RequestURL: " + req.getRequestURL().toString();
    if (user != null) {
      log += "\nUser: uid=" + user.getUserID();
      String email = user.getPerson().getEmail();
      if (email != null) {
        log += " email=" + email;
      }
    }

    String query = req.getQueryString();
    if (query != null) {
      log += "\nQuery: " + query;
    }

    Enumeration<String> names = req.getHeaderNames();
    while (names.hasMoreElements()) {
      String name = names.nextElement();
      String header = req.getHeader(name);
      if (header != null) {
        log += "\n" + name + ": " + header;
      }
    }
    theLogger.info(log);
  }

  /*
   * Save file request from user. Saves files to workspace. (non-Javadoc)
   *
   * @see
   * javax.servlet.http.HttpServlet#doPut(javax.servlet.http.HttpServletRequest
   * , javax.servlet.http.HttpServletResponse)
   */
  @Override
  protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    IUser user = null;
    try {
      user = ServerManager.getServerManager().getUserManager().getUser(req);
      if(user==null){
        resp.sendError(HttpServletResponse.SC_FORBIDDEN);
        return;
      }
      String path = getPathInfo(req);
      if (path == null) {
        theLogger.warning("DavinciPageServlet:doPut getPathInfo returned Null for user: " + user.getUserID());
        resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        return;
      }
      boolean isWorkingCopy = (path.indexOf(IDavinciServerConstants.WORKING_COPY_EXTENSION) > -1);
      if ( isWorkingCopy ) {
        path = path.substring(0, path.indexOf(IDavinciServerConstants.WORKING_COPY_EXTENSION));
      }
      IVResource file = user.getResource(path);
      if (file == null) {
        theLogger.warning("DavinciPageServlet:doPut user.getResource("+path+") returned Null for user: " + user.getUserID());
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
      /* user is trying to save over a library path */
      if ( file.isVirtual() ) {
        file = user.createResource(path, file.isDirectory());
        if(file.isDirectory())
          file.mkdir();
        else
           file.createNewInstance();
      }
      if ( file.exists() ) {
        OutputStream os = file.getOutputStreem();
        transferStreams(req.getInputStream(), os, false);
        if ( !isWorkingCopy ) {
          // flush the working copy
          file.flushWorkingCopy();
        }
 
      } else {
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
      }
    } catch (RuntimeException re) {
      log(req, user);
      throw re;
    }
  }

  public String getPathInfo(HttpServletRequest req){
    return req.getPathInfo();
  }
 
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    IUser user = null;
    try {
      if ( serverManager == null ) {
        initialize();
      }
      String previewParam = req.getParameter(IDavinciServerConstants.PREVIEW_PARAM);
 
      user = ServerManager.getServerManager().getUserManager().getUser(req);
      String pathInfo = getPathInfo(req);
      theLogger.finest("Page Servlet request: " + pathInfo + ", logged in=" + (user != null));

      if ( pathInfo == null ) {
        handleReview(req, resp);
        resp.sendRedirect("maqetta/");
      } else if ( pathInfo != null && (pathInfo.equals("") || pathInfo.equals("/")) && previewParam == null ) {
        if ( !ServerManager.LOCAL_INSTALL ) {
          if ( user == null ) {
            resp.sendRedirect("welcome");
          } else {
            writeMainPage(req, resp);
          }
        } else {
          writeMainPage(req, resp);
        }
      } else if ( pathInfo.equals("/welcome") ) {
        /* write the welcome page (may come from extension point) */
        writeWelcomePage(req, resp);
      } else if ( previewParam != null ) {
        handlePreview(req, resp);
      } else if ( pathInfo.startsWith(IDavinciServerConstants.USER_URL) ) {
        handleWSRequest(req, resp, user);
      } else {
        /* resource not found */
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
      }
    } catch (RuntimeException re) {
      log(req, user);
      throw re;
    }
  }
 
  /*
   * If review-related attributes are in the URL, set cookies so that
   * review gets opened on the client.
   */
  private void handleReview(HttpServletRequest req, HttpServletResponse resp) {
    String designerName = req.getParameter(IDavinciServerConstants.REVIEW_DESIGNER_ATTR);
    String reviewVersion = req.getParameter(IDavinciServerConstants.REVIEW_VERSION_ATTR);
    if (validateReviewParms(designerName, reviewVersion)) {
      //Fill in designer cookie
      Cookie designerCookie = new Cookie(IDavinciServerConstants.REVIEW_COOKIE_DESIGNER, designerName);
      /* have to set the path to delete it later from the client */
      designerCookie.setPath("/");
      resp.addCookie(designerCookie);

      //Fill in review version cookie
      if ( reviewVersion != null ) {
        Cookie versionCookie = new Cookie(IDavinciServerConstants.REVIEW_COOKIE_VERSION, reviewVersion);
        /* have to set the path to delete it later from the client */
        versionCookie.setPath("/");
        resp.addCookie(versionCookie);
      }
    }
  }
 
  /*
   * Make sure we have valid parms before putting back out into cookies. Putting
   * unsanitized/unvalidated parms straight into a cookie can open up the door for XSS attacks.
   */
  private boolean validateReviewParms(String designerName, String reviewVersion) {
    boolean returnVal = (designerName != null && reviewVersion != null);
    if (returnVal) {
      boolean validDesigner;
      try {
        validDesigner = ServerManager.getServerManager().getUserManager().isValidUser(designerName);
      } catch (IOException e) {
        throw new RuntimeException(e); //FIXME
      } catch (UserException e) {
        throw new RuntimeException(e); //FIXME
      }
      if (validDesigner) {
        returnVal = Validator.isValidISOTimeStamp(reviewVersion);
        if (!returnVal) {
          theLogger.warning("validateReviewParms: Poorly formatted reviewVersion = " + reviewVersion);
        }
      } else {
        theLogger.warning("validateReviewParms: Invalid review designer name = " + designerName);
        returnVal = false;
      }
    }
    return returnVal;
  }

  /*
   * Find a plugin with the given extension name and calculate winner based on
   * priority.
   *
   * @param extensionName the extension point name
   *
   * @return Bundle
   */
  protected URL getPageExtensionPath(String extensionPoint, String extensionName) {
    List extensions = serverManager.getExtensions(extensionPoint, extensionName);
    IConfigurationElement winner = null;
    int highest = -100000;
    for (int i = 0; i < extensions.size(); i++) {
      IConfigurationElement extension = (IConfigurationElement) extensions.get(i);
      int priority = Integer.parseInt(extension.getAttribute(IDavinciServerConstants.EP_ATTR_PAGE_PRIORITY));
      if ( priority > highest ) {
        winner = extension;
        highest = priority;
      }
    }
    String name = winner.getDeclaringExtension().getContributor().getName();
    Bundle bundle = Activator.getActivator().getOtherBundle(name);
    String path = winner.getAttribute(IDavinciServerConstants.EP_ATTR_PAGE_PATH);

    return bundle.getResource(path);
  }

  protected void writeWelcomePage(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
      IOException {
    URL welcomePage = getPageExtensionPath(IDavinciServerConstants.EXTENSION_POINT_WELCOME_PAGE,
        IDavinciServerConstants.EP_TAG_WELCOME_PAGE);
    VURL resourceURL = new VURL(welcomePage);
    this.writePage(req, resp, resourceURL, CacheHeaders.NO_CACHE);
  }

  protected void writeMainPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    URL welcomePage = getPageExtensionPath(IDavinciServerConstants.EXTENSION_POINT_MAIN_PAGE,
        IDavinciServerConstants.EP_TAG_MAIN_PAGE);
    VURL resourceURL = new VURL(welcomePage);
    this.writePage(req, resp, resourceURL, CacheHeaders.NO_CACHE);
  }

  /*
   * Used for previewing mobile pages.
   */
  protected void handlePreview(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
    URL previewPage = getPageExtensionPath(IDavinciServerConstants.EXTENSION_POINT_PREVIEW_PAGE,
        IDavinciServerConstants.EP_TAG_PREVIEW_PAGE);
    VURL resourceURL = new VURL(previewPage);
    this.writePage(req, resp, resourceURL, CacheHeaders.CACHE);
  }

  protected void handleWSRequest(HttpServletRequest req, HttpServletResponse resp, IUser user) throws IOException,
      ServletException {

    // System.out.println("enter ws request");
    String pathInfo =getPathInfo(req);
    // Code further down expects pathInfo==null if user goes to root of daVinci server
    IPath path = new Path(pathInfo);
    if ( path.hasTrailingSeparator() ) {
      path = path.removeTrailingSeparator();
    }

    path = path.removeFirstSegments(1);
    String userName = path.segment(0);
    if ( path.segmentCount() < 4 || !path.segment(1).equals("ws") || !path.segment(2).equals("workspace") ) {
      theLogger.warning("incorrectly formed workspace path: " + path);
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }
    path = path.removeFirstSegments(3);

    /* unlocking user directory to un-authenticated users */
    try {
      if ( user == null ) {
        user = ServerManager.getServerManager().getUserManager().getUser(userName);
      }
 
      if(user!=null && user.getUserID().compareTo(userName)!=0){
        user =  ServerManager.getServerManager().getUserManager().getUser(userName);
      }
    } catch (UserException e) {
      throw new RuntimeException(e);
    }
   
    if ( handleLibraryRequest(req, resp, path, user) ) {
      // System.out.println("was library");
      return;
    }

    if ( user == null ) {
      try {
        user = ServerManager.getServerManager().getUserManager().getUser(userName);
      } catch (UserException e) {
        throw new RuntimeException(e);
      }
      if ( user == null ) {
        theLogger.warning("user not found: " + userName);
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
    }

    IVResource userFile = user.getResource(path.toString());

    if ( userFile != null && !userFile.exists() ) {
      if ( path.getFileExtension() == null ) {
        userFile = user.getResource(path.addFileExtension("html").toString());
      }
      if ( !userFile.exists() ) {
        theLogger.warning("user file not found: " + path);
        resp.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }
    } else {
      resp.resetBuffer();
      resp.sendError(HttpServletResponse.SC_NOT_FOUND);
    }
  }

  protected boolean handleLibraryRequest(HttpServletRequest req, HttpServletResponse resp, IPath path, IUser user)
      throws ServletException, IOException {
    IVResource libraryURL = user.getResource(path.toString());
    if (libraryURL != null) {
      CacheHeaders caching = libraryURL.readOnly() ? CacheHeaders.CACHE : CacheHeaders.NO_CACHE;
      writePage(req, resp, libraryURL, caching);
      return true;
    }
    return false;
  }

  protected void writePage(HttpServletRequest req, HttpServletResponse resp, IVResource resourceURL,
      CacheHeaders doCache) throws ServletException, IOException {

    if ( resourceURL == null ) {
      theLogger.warning("resource URL not found: "+resourceURL);
      resp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }
   
    URLConnection connection = resourceURL.openConnection();
    InputStream is  = null;
    try {
      /*
       * #3897
       * Open the input stream here, if we open a URLConnection
       * and do not close a steam, some times we are unable to
       * delete the file latter. So by opening a stream and then
       * closing the stream we are able to process the file later.
       */
      is  = connection.getInputStream();
      long lastModified = connection.getLastModified();
      int contentLength = connection.getContentLength();
 
      String etag = null;
      if ( lastModified != -1 && contentLength != -1 ) {
        etag = "W/\"" + contentLength + "-" + lastModified + "\"";
      }
 
      // Check for cache revalidation.
      // We should prefer ETag validation as the guarantees are stronger and
      // all HTTP 1.1 clients should be using it
      String ifNoneMatch = req.getHeader(DavinciPageServlet.IF_NONE_MATCH);
      if (ifNoneMatch != null && etag != null && ifNoneMatch.compareTo(etag) == 0) {
        resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return; //#3897 free's up the file pointer/io stream in the finally
      }
 
      long ifModifiedSince = req.getDateHeader(DavinciPageServlet.IF_MODIFIED_SINCE);
      // for purposes of comparison we add 999 to ifModifiedSince since the fidelity
      // of the IMS header generally doesn't include milli-seconds
      if ( ifModifiedSince > -1 && lastModified > 0 && lastModified <= (ifModifiedSince + 999)) {
        resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return; //#3897 free's up the file pointer/io stream in the finally
      }
 
      // return the full contents regularly
      if ( contentLength != -1 ) {
        resp.setContentLength(contentLength);
      }
 
      String path = resourceURL.getPath();
      String contentType = req.getSession().getServletContext().getMimeType(path);
      if ( contentType != null ) {
        resp.setContentType(contentType);
      }
 
      if ( lastModified > 0 ) {
        resp.setDateHeader(DavinciPageServlet.LAST_MODIFIED, lastModified);
      }
 
      resp.setCharacterEncoding("UTF-8");
 
      if ( etag != null ) {
        resp.setHeader(DavinciPageServlet.ETAG, etag);
      }
 
      // Cache Headers
      if (doCache != CacheHeaders.NO_CACHE) {
        resp.setDateHeader(EXPIRES, System.currentTimeMillis() + maxAge * 1000);
        resp.setHeader(CACHE_CONTROL, "public, max-age=" + maxAge + ", must-revalidate"); //$NON-NLS-1$ //$NON-NLS-2$
      } else {
        resp.setDateHeader(EXPIRES, 0);
        resp.setHeader(CACHE_CONTROL, "no-cache"); // HTTP 1.1
        resp.setHeader(PRAGMA, "no-cache"); // HTTP 1.0
      }
 
   
      // write the resource
      try {
        OutputStream os = resp.getOutputStream();
        int writtenContentLength = writeResource(is, os);
        if ( contentLength == -1 || contentLength != writtenContentLength ) {
          resp.setContentLength(writtenContentLength);
        }
      } catch ( IllegalStateException e ) {
        // can occur if the response output is already open as a Writer
        Writer writer = resp.getWriter();
        writeResource(is, writer);
        // Since ContentLength is a measure of the number of bytes contained in the body
        // of a message when we use a Writer we lose control of the exact byte count and
        // defer the problem to the Servlet Engine's Writer implementation.
      }
    } catch ( FileNotFoundException e ) {
      // FileNotFoundException may indicate the following scenarios
      //     - url is a directory
      //     - url is not accessible
      theLogger.log(Level.WARNING, "writePage file not found: " + resourceURL, e);
      resp.reset();
      resp.sendError(HttpServletResponse.SC_FORBIDDEN);

    } catch ( SecurityException e ) {
      // SecurityException may indicate the following scenarios
      //     - url is not accessible
      theLogger.log(Level.WARNING, "writePage security exception: " + resourceURL, e);
      resp.reset();
      resp.sendError(HttpServletResponse.SC_FORBIDDEN);
    } finally {
      if (is != null ) {
        is.close(); //#3897 free up the file pointer
      }

    }
   
  }

//  protected void writeInternalPage(HttpServletRequest req, HttpServletResponse resp, Bundle bundle, String path)
//      throws ServletException, IOException {
//    VURL resourceURL = new VURL(bundle.getResource(path));
//    writePage(req, resp, resourceURL, CacheHeaders.CACHE);
//  }

  protected static int writeResource(InputStream is, OutputStream os) throws IOException {
    byte[] buffer = new byte[8192];
    int bytesRead = is.read(buffer);
    int writtenContentLength = 0;
    while ( bytesRead != -1 ) {
      os.write(buffer, 0, bytesRead);
      writtenContentLength += bytesRead;
      bytesRead = is.read(buffer);
    }
    return writtenContentLength;
  }

  protected static void writeResource(InputStream is, Writer writer) throws IOException {
    Reader reader = new InputStreamReader(is);
    try {
      char[] buffer = new char[8192];
      int charsRead = reader.read(buffer);
      while ( charsRead != -1 ) {
        writer.write(buffer, 0, charsRead);
        charsRead = reader.read(buffer);
      }
    } finally {
      if ( reader != null ) {
        reader.close(); // will also close input stream
      }
    }
  }

  protected static final void transferStreams(InputStream source, OutputStream destination, boolean closeInput)
      throws IOException {
    byte[] buffer = new byte[8192];
    try {
      synchronized ( buffer ) {
        while ( true ) {
          int bytesRead = -1;
          bytesRead = source.read(buffer);
          if ( bytesRead == -1 ) {
            break;
          }
          destination.write(buffer, 0, bytesRead);
        }
      }
    } finally {
      if ( closeInput ) {
        source.close();
      } else {
        destination.close();
      }
    }
  }
}
TOP

Related Classes of maqetta.core.server.DavinciPageServlet

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.