Package ca.carleton.gcrc.couch.config

Source Code of ca.carleton.gcrc.couch.config.ConfigServlet

package ca.carleton.gcrc.couch.config;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import net.sf.json.JSONObject;
import net.sf.json.util.JSONTokener;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

import ca.carleton.gcrc.couch.app.JSONDirectoryBuilder;
import ca.carleton.gcrc.couch.client.CouchDb;
import ca.carleton.gcrc.couch.client.CouchDesignDocument;
import ca.carleton.gcrc.couch.client.CouchFactory;
import ca.carleton.gcrc.couch.client.CouchClient;
import ca.carleton.gcrc.couch.onUpload.UploadListener;
import ca.carleton.gcrc.couch.onUpload.UploadWorker;
import ca.carleton.gcrc.olkit.multimedia.utils.MultimediaConfiguration;
import ca.carleton.gcrc.upload.OnUploadedListenerSingleton;
import ca.carleton.gcrc.upload.UploadServlet;
import ca.carleton.gcrc.upload.UploadUtils;

@SuppressWarnings("serial")
public class ConfigServlet extends HttpServlet {

  final static public String DESIGN_DOC_NAME = "ss_upload";
  final static public String DESIGN_DOC_SIG_KEY = "signature";

  final protected Logger logger = Logger.getLogger(this.getClass());
 
  private CouchClient couchClient = null;
  private CouchDb couchDb = null;
  private CouchDesignDocument couchDd = null;
  private UploadWorker uploadWorker = null;
  private File mediaDir = null;
 
  public ConfigServlet() {
   
  }

  public void init(ServletConfig config) throws ServletException {
    super.init(config);
   
    // Instantiate CouchDb client
    try {
      initCouchDbClient(config);
    } catch(ServletException e) {
      logger.error("Error while initializing couch client",e);
      throw e;
    }
   
    // Upload design documents
    try {
      initCouchDesignDocument(config);
    } catch(ServletException e) {
      logger.error("Error while initializing design document",e);
      throw e;
    }
   
    // Configure multimedia
    try {
      initMultimedia(config);
    } catch(ServletException e) {
      logger.error("Error while initializing multimedia",e);
      throw e;
    }
   
    mediaDir = UploadUtils.getMediaDir(config.getServletContext());
   
    UploadListener uploadListener = new UploadListener();
    uploadListener.setCouchDb(couchDb);
    config.getServletContext().setAttribute(UploadServlet.OnUploadedListenerAttributeName, uploadListener);
    OnUploadedListenerSingleton.configure(uploadListener);
   
    try {
      uploadWorker = new UploadWorker();
      uploadWorker.setDesignDocument(couchDd);
      uploadWorker.setMediaDir(mediaDir);
      uploadWorker.start();
    } catch (Exception e) {
      logger.error("Error starting upload worker",e);
      throw new ServletException("Error starting upload worker",e);
    }
  }

  private void initCouchDbClient(ServletConfig config) throws ServletException {
    File rootFile = null;
    {
      ServletContext servletContext = config.getServletContext();
      if( null != servletContext ) {
        String realRoot = servletContext.getRealPath(".");
        if( null != realRoot ) {
          rootFile = new File(realRoot);
        }
      }
    }
   
    // Load up configuration information
    Properties props = new Properties();
    {
      File propFile = null;
      if( null != rootFile ) {
        propFile = new File(rootFile, "WEB-INF/couch.properties");
        if( false == propFile.exists() || false == propFile.isFile() ) {
          propFile = null;
        }
      }
      if( null != rootFile && null == propFile ) {
        propFile = new File(rootFile, "WEB-INF/couch.properties.default");
        if( false == propFile.exists() || false == propFile.isFile() ) {
          propFile = null;
        }
      }
      if( null == propFile ) {
        logger.info("Couch Client property file location can not be determined");
      } else {
        logger.info("Reading Couch Client properties from "+propFile.getAbsolutePath());
        FileInputStream fis = null;
        try {
          fis = new FileInputStream(propFile);
          props.load(fis);
        } catch (Exception e) {
          logger.error("Unable to read properties from "+propFile.getAbsolutePath(),e);
        } finally {
          if( null != fis ) {
            try {
              fis.close();
            } catch (Exception e) {
              // Ignore
            }
          }
        }
      }
    }
   
    // Create Couch Server from properties
    CouchFactory factory = new CouchFactory();
    try {
      couchClient = factory.getClient(props);
     
    } catch(Exception e) {
      logger.error("Unable to get Couch Server",e);
      throw new ServletException("Unable to get Couch Server",e);
    }
   
    // Create database
    try {
      if( props.containsKey("dbUrl") ) {
        couchDb = factory.getDb(couchClient, props.getProperty("dbUrl"));
      } else if( props.containsKey("dbName") ) {
        couchDb = couchClient.getDatabase(props.getProperty("dbName"));
      } else {
        throw new Exception("dbUrl or dbName must be provided");
      }
    } catch(Exception e) {
      logger.error("Unable to build Couch Database",e);
      throw new ServletException("Unable to build Couch Database",e);
    }
    logger.info("CouchDb configured: "+couchDb.getUrl());
  }

  private void initCouchDesignDocument(ServletConfig config) throws ServletException {
    // Find root directory for design document
    File ddDir = null;
    {
      File rootFile = null;
      {
        ServletContext servletContext = config.getServletContext();
        if( null != servletContext ) {
          String realRoot = servletContext.getRealPath(".");
          if( null != realRoot ) {
            rootFile = new File(realRoot);
          }
        }
      }
      if( null != rootFile ) {
        ddDir = new File(rootFile, "WEB-INF/uploadDesignDoc");
        if( false == ddDir.exists() || false == ddDir.isDirectory() ) {
          ddDir = null;
        }
      }
      if( null == ddDir ) {
        throw new ServletException("Unable to find design document source for upload");
      }
    }
   
    // Load design document
    StringWriter ddWriter = new StringWriter();
    JSONObject designDoc = new JSONObject();
    try {
      JSONDirectoryBuilder builder = new JSONDirectoryBuilder(ddDir);
      builder.write(ddWriter);

      JSONTokener jsonTokener = new JSONTokener(ddWriter.toString());
      Object obj = jsonTokener.nextValue();
      if( obj instanceof JSONObject ) {
        designDoc = (JSONObject)obj;
      } else {
        throw new Exception("Unexpected returned object type: "+obj.getClass().getSimpleName());
      }
     
      designDoc.put("_id", "_design/"+DESIGN_DOC_NAME);
     
    } catch(Exception e) {
      throw new ServletException("Unable to load design document", e);
    }
   
    // Compute signature
    String signature = null;
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8");
      osw.write(ddWriter.toString());
      osw.flush();
     
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      md.update(baos.toByteArray());
      byte[] sigBytes = md.digest();

      // B64
      byte[] encoded = Base64.encodeBase64(sigBytes);
      ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
      InputStreamReader isr = new InputStreamReader(bais, "UTF-8");
      BufferedReader br = new BufferedReader(isr);
      signature = br.readLine();
     
      // Add signature to JSON doc
      designDoc.put(DESIGN_DOC_SIG_KEY, signature);
     
      logger.info("Design document signature: "+signature);

    } catch(Exception e) {
      throw new ServletException("Unable to compute signature on design document", e);
    }
   
    // Check if design doc exists
    boolean creationRequired = false;
    boolean updateNeeded = false;
    try {
      if( false == couchDb.documentExists("_design/"+DESIGN_DOC_NAME) ) {
        creationRequired = true;
      } else {
        // Check if it is the right signature
        JSONObject currentDesignDoc = couchDb.getDocument("_design/"+DESIGN_DOC_NAME);
        if( false == currentDesignDoc.containsKey(DESIGN_DOC_SIG_KEY) ) {
          updateNeeded = true;
        } else {
          String currentSignature = currentDesignDoc.getString(DESIGN_DOC_SIG_KEY);
          if( false == signature.equals(currentSignature) ) {
            updateNeeded = true;
          }
        }
       
        // Update revision
        designDoc.put("_rev", currentDesignDoc.get("_rev"));
      }
    } catch(Exception e) {
      throw new ServletException("Unable to access current design document", e);
    }
   
    // Upload, if required
    if( creationRequired ) {
      logger.info("Creating design document");
      try {
        couchDb.createDocument(designDoc);
      } catch (Exception e) {
        throw new ServletException("Unable to create design document", e);
      }
     
    } else if( updateNeeded ) {
      logger.info("Uploading design document");
      try {
        couchDb.updateDocument(designDoc);
      } catch (Exception e) {
        throw new ServletException("Unable to update design document", e);
      }
    }
   
    try {
      couchDd = couchDb.getDesignDocument(DESIGN_DOC_NAME);
    } catch (Exception e) {
      throw new ServletException("Unable to get design document", e);
    }
  }

  private void initMultimedia(ServletConfig config) throws ServletException {
    File rootFile = null;
    {
      ServletContext servletContext = config.getServletContext();
      if( null != servletContext ) {
        String realRoot = servletContext.getRealPath(".");
        if( null != realRoot ) {
          rootFile = new File(realRoot);
        }
      }
    }
   
    // Load up configuration information
    Properties props = new Properties();
    {
      File propFile = null;
      if( null != rootFile ) {
        propFile = new File(rootFile, "WEB-INF/multimedia.properties");
        if( false == propFile.exists() || false == propFile.isFile() ) {
          propFile = null;
        }
      }
      if( null != rootFile && null == propFile ) {
        propFile = new File(rootFile, "WEB-INF/multimedia.properties.default");
        if( false == propFile.exists() || false == propFile.isFile() ) {
          propFile = null;
        }
      }
      if( null == propFile ) {
        logger.info("Multimedia property file location can not be determined");
      } else {
        logger.info("Reading multimedia properties from "+propFile.getAbsolutePath());
        FileInputStream fis = null;
        try {
          fis = new FileInputStream(propFile);
          props.load(fis);
        } catch (Exception e) {
          logger.error("Unable to read properties from "+propFile.getAbsolutePath(),e);
        } finally {
          if( null != fis ) {
            try {
              fis.close();
            } catch (Exception e) {
              // Ignore
            }
          }
        }
      }
    }
   
    MultimediaConfiguration.configureFromProperties(props);
  }
 
  public void destroy() {
    try {
      uploadWorker.stopTimeoutMillis(5*1000); // 5 seconds
    } catch (Exception e) {
      logger.error("Unable to shutdown upload worker", e);
    }
  }
}
TOP

Related Classes of ca.carleton.gcrc.couch.config.ConfigServlet

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.