Package javango.contrib.servlet

Source Code of javango.contrib.servlet.Servlet

package javango.contrib.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javango.api.Settings;
import javango.core.AnonymousUser;
import javango.core.JavangoLifecycleListener;
import javango.core.servers.RequestProcessor;
import javango.http.Http404;
import javango.http.HttpException;
import javango.http.HttpRequest;
import javango.http.HttpResponse;
import javango.http.SimpleHttpResponse;

import javax.servlet.ServletException;
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.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.inject.Binder;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Named;

public class Servlet extends HttpServlet implements Module, javango.core.JavangoLifecycle {
 
  public static final String BROKEN_LINK_LOG_LEVEL = "BROKEN_LINK_LOG_LEVEL";

  /**
   *
   */
  private static final long serialVersionUID = 4173911300243443940L;

  private final static Log log = LogFactory.getLog(Servlet.class);
 
  Injector injector;
 
  // TODO Should Guice provide this giving the developer the flexability to create a new one or use a singleton
  // therefore getting rid of this property?
  @Inject
  RequestProcessor requestProcessor;
 
  @Inject(optional=true)
  @Named("javango.characterEncoding")
  String characterEncoding;
 
  List<JavangoLifecycleListener> listeners = new ArrayList<JavangoLifecycleListener>();
 
  protected Injector getInjector() throws ServletException {
    if (injector != null) {
      return injector;
    }
    try {

            String guiceModule = this.getServletConfig().getInitParameter("GuiceModules");
            String settings = this.getServletConfig().getInitParameter("Settings");

            List<Module> moduleList = new ArrayList<Module>();
            moduleList.add(this);

            if (!StringUtils.isBlank(guiceModule)) {
              for (String moduleName : guiceModule.split(";")) {
                moduleList.add((Module)Class.forName(moduleName.trim()).newInstance());
              }
            return  com.google.inject.Guice.createInjector(moduleList);
            } else if (!StringUtils.isBlank(settings)) {
               return ((Settings)Class.forName(settings.trim()).newInstance()).createInjector(moduleList);
            } else {
              throw new ServletException("You must provide GuiceModules or Settings as a parameter to the servlet");
            }
           
    } catch (Exception e) {
      // TODO Instead of throwing servletexception add a single url (^.*$) to the list that shows the error message and stack.
      log.error(e,e);
      throw new ServletException(e);
    }
  }
 
  @Override
  public void init() throws ServletException {
    log.debug("Entering Servlet.init");
    super.init();
    injector = getInjector();
    injector.injectMembers(this);

//        requestProcessor = injector.getInstance(RequestProcessor.class);     
//        String charEncode = injector.getInstance(arg0)
       
        for(JavangoLifecycleListener listener: listeners) {
          listener.start();
        }
  }

 
  public void configure(Binder binder) {
    binder.bind(Servlet.class).toInstance(this);
//    binder.bind(RegUrlFactory.class).toProvider(FactoryProvider.newFactory(RegUrlFactory.class, RegUrl.class));
  }

  public void addListener(JavangoLifecycleListener listener) {
    this.listeners.add(listener);   
  }

  @Override
  public void destroy() {
    requestProcessor.stop();
   
        for(JavangoLifecycleListener listener: listeners) {
          listener.stop();
        }
       
    LogFactory.releaseAll();
    super.destroy();
  }

  public void service(final HttpServletRequest servletRequest, final HttpServletResponse servletResponse) throws IOException, ServletException {
    if (characterEncoding != null) {
      servletRequest.setCharacterEncoding(characterEncoding);
      servletResponse.setCharacterEncoding(characterEncoding);
    }
    HttpRequest request = injector.getInstance(HttpRequest.class);
   
    String context = StringUtils.trimToEmpty(servletRequest.getContextPath());
    String path = StringUtils.trimToEmpty(servletRequest.getRequestURI());

    try {     
      // TODO context should always end in a trailing slash and path should always start without a slash.
     
      path = path.substring(context.length()+1); // +1 to gobble up the trailing slash
      request.setPath(path);
      request.setContext(context);
      request.setMethod(servletRequest.getMethod());
      request.setSession(new HttpServletSession(servletRequest));
     
      // Check that we have a file upload request
      boolean isMultipart = ServletFileUpload.isMultipartContent(servletRequest);
      if (isMultipart) {
        Map<String, FileItem> files = new HashMap<String, FileItem>();
        Map<String, String[]> parameters = new HashMap<String, String[]>();
       
        // Create a factory for disk-based file items
        FileItemFactory factory = new DiskFileItemFactory();

        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);

        // Parse the request
        List<FileItem> items = upload.parseRequest(servletRequest);

        // Process the uploaded items
        Iterator<FileItem> iter = items.iterator();
        while (iter.hasNext()) {
            FileItem item = (FileItem) iter.next();

            if (item.isFormField()) {
                parameters.put(item.getFieldName(), new String[] {item.getString()}); // TODO Allow multiple values,  check to see if parameters already has a value with this name and append.
            } else {
                files.put(item.getFieldName(), item);
            }
        }
        request.setFiles(files);
        request.setParameterMap(parameters);

      } else {
        request.setParameterMap(servletRequest.getParameterMap());
        request.setFiles(null);
      }
     
      if (servletRequest.getUserPrincipal() == null) {
        // TODO this user should not necessarly change from request to request (maybe).  only works if the user has cookies,  see how django handles.
        request.setUser(new AnonymousUser());
      } else {
        request.setUser(new PrincipalUser(servletRequest));
      }
     
      HttpResponse response = requestProcessor.service(request);
      response.render(servletRequest, servletResponse);
     
      // tell the request that we are done so it can notify any listeners.  good place to close database sessions, etc.
      request.close();
    } catch (Http404 e) {
      String level = injector.getInstance(Settings.class).get(BROKEN_LINK_LOG_LEVEL);
      if (level != null) {
        if ("trace".equalsIgnoreCase(level)) {
          log.trace(e,e);
        } else if ("debug".equalsIgnoreCase(level)) {
          log.debug(e,e);
        } else if ("info".equalsIgnoreCase(level)) {
          log.info(e,e);
        } else if ("warn".equalsIgnoreCase(level)) {
          log.warn(e,e);
        } else if ("error".equalsIgnoreCase(level)) {
          log.error(e,e);
        } else if ("fatal".equalsIgnoreCase(level)) {
          log.fatal(e,e);
        }
      }
      if (!injector.getInstance(Settings.class).isDebug()) {
        // TODO ability to specify 404 handler
        SimpleHttpResponse response = new SimpleHttpResponse("Page not found");
        response.setStatusCode(404);
        try {
          response.render(servletRequest, servletResponse);
        } catch (HttpException e2) {
          log.error(e2,e2);
          throw new ServletException(e);
        }
      } else {
        throw new ServletException(e);
      }
    } catch (FileUploadException e) {
      log.error(e,e);
      try {
        request.close();
      } catch (HttpException e1) {
        log.error(e1,e1);
      }
      // TODO Pretty print the exception and stack trace,  request information, etc
      if (!injector.getInstance(Settings.class).isDebug()) {
        HttpResponse response = new SimpleHttpResponse("Unrecoverable error processing uploaded files, please contact support");
        try {
          response.render(servletRequest, servletResponse);
        } catch (HttpException e2) {
          log.error(e2,e2);
          throw new ServletException(e);
        }
      }
    } catch (HttpException e) {
      log.error(String.format("HttpException while processing for user '%s' %s:%s", request.getUser(), context, path));
      log.error(e,e);
      try {
        request.close();
      } catch (HttpException e1) {
        log.error(e1,e1);
      }
      // TODO Pretty print the exception and stack trace,  request information, etc
      // TODO can this exception be handled by middleware?  middleware is not really avaliable here as it is handled in the requestProcessor...
      if (!injector.getInstance(Settings.class).isDebug()) {
        HttpResponse response = new SimpleHttpResponse("Unrecoverable error, please contact support");
        try {
          response.render(servletRequest, servletResponse);
        } catch (HttpException e2) {
          log.error(e2,e2);
          throw new ServletException(e);
        }
      } else {
        throw new ServletException(e);
      }
    }
  }
 
}
TOP

Related Classes of javango.contrib.servlet.Servlet

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.