view src/HumanEchoServlet.java @ 60:b3f3b42b9933

Cache generated files. The files are now generated into distinct subdirectories and moved into the main directory before being returned to the client.
author Chris Cannam
date Thu, 27 Mar 2014 17:35:18 +0000
parents b27106b380d8
children 21bab43ae2c1
line wrap: on
line source
/*
 * HumanEchoServlet
 *
 * Version information
 *
 * 3 December 2013
 *
 * Copyright notice
 */

import java.util.Properties;
import java.io.IOException;

import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.File;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

import org.apache.log4j.Logger;

import javax.servlet.*;
import javax.servlet.http.*;

import com.mathworks.toolbox.javabuilder.MWJavaObjectRef;
import com.mathworks.toolbox.javabuilder.MWNumericArray;
import com.mathworks.toolbox.javabuilder.MWStructArray;
import com.mathworks.toolbox.javabuilder.MWException;
import com.mathworks.toolbox.javabuilder.internal.MCRConfiguration;

import uk.ac.soton.isvr.*;

public class HumanEchoServlet extends HttpServlet {

    private HumanEcho echo;
    private static Logger logger = Logger.getLogger(HumanEchoServlet.class);

    private String outdir = "";
    private String indir = "";

    private static Integer dirId = 0;

    public void init(ServletConfig config) throws ServletException {
        super.init(config);

	logger.info("In init");

	logger.info("java.library.path is " + 
		     System.getProperty("java.library.path"));

        try {
            Properties properties = new Properties();
            properties.load
		(Thread.currentThread().getContextClassLoader().
		 getResourceAsStream("HumanEcho.properties"));

            outdir = properties.getProperty("outdir");
            indir = properties.getProperty("indir");

	    logger.info("WAV file directory is " + outdir);

        } catch (Exception e) {
	    logger.error("Failed to load app properties: " + e.getMessage());
            e.printStackTrace();
        }

        try {
	    // Test that we can construct one of the MATLAB objects
	    
	    long before = System.currentTimeMillis();
            echo = new HumanEcho();
	    long after = System.currentTimeMillis();
	    logger.info("Created a HumanEcho object: it took " + (after - before) + " ms");
        } catch (MWException e) {
	    logger.error("Failed to construct HumanEcho object: " + e.getMessage());
            e.printStackTrace();
        }

	logger.info("Init completed");
    }

    public void destroy() {
        super.destroy();

        if (echo != null) {
            echo.dispose();
        }
    }

    protected synchronized String getDirToken() {
	dirId = dirId + 1;
	return dirId.toString();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	logger.info("In doGet");

        logger.info("Distance (as string) is: " + request.getParameter("dist"));

        // todo: validate/normalise distance
        Double dist = Double.parseDouble(request.getParameter("dist"));
	Double azim = Double.parseDouble(request.getParameter("azim"));
	String orientation = request.getParameter("orient");
	Double dirweight = Double.parseDouble(request.getParameter("dirweight"));

	logger.info("Got parameters");

        MWStructArray Input = null;

        String outputfname = new String();

	// this needs to be distinct for the parameters
	StringBuilder sb = new StringBuilder();

	sb.append("e_d");
	sb.append(dist);
	sb.append("_a");
	sb.append(azim);

	if (orientation.equals("horz")) {
	    sb.append("_H");
	} else if (orientation.equals("angled")) {
	    sb.append("_A");
	}

	sb.append("_w");
	sb.append(dirweight);

	outputfname = sb.toString();

	String target = outdir + "/" + outputfname + ".wav";
	File targetFile = new File(target);
	targetFile.deleteOnExit();

	if (!targetFile.exists()) {

	    try {
		logger.info("Property catalina.base is " + System.getProperty("catalina.base"));

		String tempDir = outdir + "/" + getDirToken();
		File tempDirFilePath = new File(tempDir);
		tempDirFilePath.mkdirs();

		// Matlab structure:
		// 
		// Input = struct('dist', 0.9, 'azim', 0, 'orient',
		// 'horz', 'dirweight', 0.2, 'outdir', '/tmp/wav',
		// 'outname', 'foo.wav', 'indir', '/path/to/hrir')

		String[] InputStructFields = {
		    "dist", "azim", "orient", "dirweight",
		    "outdir", "outname", "indir" 
		};

		Input = new MWStructArray(1, 1, InputStructFields);
		Input.set("dist", 1, Double.valueOf(dist));
		Input.set("azim", 1, Double.valueOf(azim));
		Input.set("orient", 1, orientation);
		Input.set("dirweight", 1, Double.valueOf(dirweight));
		Input.set("outdir", 1, tempDir);
		Input.set("indir", 1, indir);

		Input.set("outname", 1, outputfname);

		Object[] result = echo.simulateBinauralSignals(Input);

		File createdFile = new File(tempDir + "/" + outputfname + ".wav");
		if (!createdFile.exists()) {
		    String err = "The simulateBinauralSignals call failed to create expected output file \"" + createdFile + "\"";
		    logger.error(err);
		    throw new ServletException(err);
		}

		Files.move(createdFile.toPath(),
			   targetFile.toPath(),
			   StandardCopyOption.ATOMIC_MOVE);

		tempDirFilePath.delete();

	    } catch (MWException e) {
		logger.error("Failed to calculate simulateBinauralSignals: " + e.getMessage());
		e.printStackTrace();
		throw new ServletException(e.getMessage());
	    }
	}

        // Creating the stream
        ServletOutputStream stream = null;
        BufferedInputStream buf = null;

        try{
            stream = response.getOutputStream();

	    logger.info("About to read WAV data from \"" + target + "\"");

            //set response headers
            response.setContentType("audio/x-wav");
            response.addHeader("Content-Disposition","attachment; filename=" + outputfname );
            response.setContentLength( (int) targetFile.length( ) );

            FileInputStream input = new FileInputStream(targetFile);
            buf = new BufferedInputStream(input);

            int b = 0;
	    int total = 0;

            // read from the file; write to the ServletOutputStream
            while ((b = buf.read()) != -1) {
                stream.write(b);
		total += 1;
	    }

	    logger.info("Successfully wrote " + total + " byte(s) to client");

        } catch (IOException ioe){
	    logger.error("Failed to read wav data: " + ioe.getMessage());
            throw new ServletException(ioe.getMessage( ));
        } finally {
            if (stream != null) stream.close();
            if (buf != null) buf.close();
	}
    }
}