`
elicer
  • 浏览: 131183 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
收藏列表
标题 标签 来源
URLBuilder
/**
 * @author Elicer Zheng
 * @Time   2015 04:20:04
 * @Description
 */
public class URLBuilder {

    public static Builder getBuilder(){
    	return new Builder();
    }

	public static class Builder{
		/**
		 * This is the protocal info
		 *
		 * e.g. http/https
		 */
		private  String protocal;
		/**
		 * This is the host info
		 * e.g google.com
		 */
		private  String host;
		/**
		 * This is the port info
		 */
		private  String port;

		private  String pathInfo;
		/**
		 * This param list used for get request query parameter
		 * e.g.  http://samplehost:port/pathInfo?a=b&c+d
		 */

		private String URL_SEPARATER = "/";

		private String COLONO = ":";

		private String URL_PARAM_SEP = "?";

		private  List<BasicNameValuePair> paramList;

		Builder(){

		}

		public  Builder addParameter(String key, String value){
			if(StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value)){
			  this.getParamList().add(new BasicNameValuePair(key,value));

			}

			return this;
		}

		public  Builder setProtocal(String protocal) {
			this.protocal = protocal;
			return this;
		}

		public Builder setHost(String host) {
			this.host = host;
			return this;
		}

		public  Builder setPort(String port) {
			this.port = port;
			return this;
		}

		public  Builder setPathInfo(String pathInfo) {
			this.pathInfo = pathInfo;
			return this;
		}
		public  List<BasicNameValuePair> getParamList() {
			if(paramList == null){
				this.paramList =  new ArrayList<BasicNameValuePair>();
			}
			return paramList;
		}
		public  Builder setParamList(List<BasicNameValuePair> paramList) {
			this.paramList = paramList;
			return this;
		}

		private String encode(BasicNameValuePair keyValue) {
			StringBuffer param = new StringBuffer();
		    try {
		    	param.append(URLEncoder.encode(keyValue.getName(), "UTF-8"));
		    	param.append("=");
		    	param.append(URLEncoder.encode(keyValue.getValue(), "UTF-8"));


		    } catch (UnsupportedEncodingException ex) {
		      throw new RuntimeException("Broken VM does not support UTF-8");
		    }
		    return param.toString();
		  }
        public String build(){

		    StringBuffer urlBuilder = new StringBuffer();
            //Append http://host:port
		    if(StringUtils.isNotEmpty(this.protocal) && StringUtils.isNotEmpty(this.host) && StringUtils.isNotEmpty(this.port)){
		    	urlBuilder.append(this.protocal);
		    	urlBuilder.append(COLONO);
		    	urlBuilder.append(URL_SEPARATER);
		    	urlBuilder.append(URL_SEPARATER);

		    	urlBuilder.append(this.host);
		    	urlBuilder.append(COLONO);

		    	urlBuilder.append(this.port);
		    	urlBuilder.append(URL_SEPARATER);
		    }
		    //Append Path Info http://host:port/samplepathinfo
		    if(StringUtils.isNotEmpty(urlBuilder.toString())&& StringUtils.isNotEmpty(this.pathInfo)){
                //Remove the last "/" if available
		    	if(this.pathInfo.lastIndexOf(URL_SEPARATER) == (this.pathInfo.length()-1)){
		    		this.setPathInfo(this.pathInfo.substring(0,this.pathInfo.lastIndexOf(URL_SEPARATER)-1));
		    	}
		        if(this.pathInfo.startsWith(URL_SEPARATER)){
		        	urlBuilder.append(this.pathInfo.substring(1));
		        }else{

		        	urlBuilder.append(this.pathInfo);
		        }

		    }else if(StringUtils.isNotEmpty(this.pathInfo)){
                //Remove the last "/" if available
		    	if(this.pathInfo.lastIndexOf(URL_SEPARATER) == (this.pathInfo.length()-1)){
		    		this.setPathInfo(this.pathInfo.substring(0,this.pathInfo.lastIndexOf(URL_SEPARATER)-1));
		    	}

		        if(this.pathInfo.startsWith(URL_SEPARATER)){
		        	urlBuilder.append(this.pathInfo);
		        }else{
		        	urlBuilder.append(URL_SEPARATER);
		        	urlBuilder.append(this.pathInfo);
		        }
		    }

            //Addend parameter if avaialble http://host:port/samplepathinfo?a=b&d=g
		    if(StringUtils.isNotEmpty(urlBuilder.toString()) && paramList != null && paramList.size() > 0){

		    	urlBuilder.append(URL_PARAM_SEP);
		    	int i=0;
		    	for(BasicNameValuePair keyValue : paramList){
		    		i++;
		    		urlBuilder.append(encode(keyValue));
		    		if(i < paramList.size()){
		    			 urlBuilder.append("&");
		    		}
		    	}

		    }


	        return urlBuilder.toString();


        }


	}

	public static void main(String[] args){
		String urlPath = URLBuilder.getBuilder().setPathInfo("/test/test11/")
		 .addParameter("a", "b")
		 .addParameter("c", "d").build();

		System.out.println(urlPath+"\n");

		String urlPath1 = URLBuilder.getBuilder().setPathInfo("/test/test11/").setHost("sampleHost").setPort("samplePort").setProtocal("Http")
		 .addParameter("a1", "b1")
		 .addParameter("c1", "d1").build();

		System.out.println(urlPath1+"\n");


	}
}
Common Proxy for cross domain access
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;



/**
 * @Auther: Elicer Zheng
 * @Description  :
 * This class is responsible for a proxy http request.
 * It takes the incoming request and then it creates a new request to the target address and copies the response of that proxy request
 * to the response of the original request.
 * <p/>
 * This class uses the commons-httpclient classes from Apache.
 * <p/>
 *

 */
public class CommonProxyerImplTEST implements CommonProxyer {



	private static String[] paramKeyList ={"COM_PROXY_PROXY_SERVER","COM_PROXY_PROXY_PORT","COM_PROXY_TARGET_URL","COM_PROXY_PROXY_REQUIRED",
		"COM_PROXY_CREDNTIAL_REQUIRED","COM_PROXY_PROXY_USERNAME","COM_PROXY_PROXY_PASSWORD","COM_PRATURE_TOKEN","COM_PARATURE_PUBLISHED","COM_PARATURE_OUTPUT_FORMAT"};

	//private static String PROXY_HOST = "proxies.img.intranet";//"www.config.barclays.co.uk";//;

	//private static int PROXY_PORT = 8080;

	private static int CONNECTION_TIMEOUT = 8000;

	private static final int SUCCESS_RESPONSE = 200;

	private static final String PARATURE_SEARCH_FOLDER = "PARATURE_SEARCH_FOLDER";

	private static final String PARATURE_SEARCH_URL_SUFFIX = "parature/searchResult";

	private static final String FOLDER_ID_PARAM = "Folders_id_";

    private static HashMap<String, String> paramMap =new HashMap<String, String>();

    private static CommonProxyer commonProxyer = new CommonProxyerImplTEST();

    private static MCFELog log = MCFELogUtility.getLogger(CommonProxyerImplTEST.class);




    public static CommonProxyer getInstance(){

    	return commonProxyer;
    }

    private CommonProxyerImplTEST(){




    }



	@SuppressWarnings("rawtypes")
	private String addAdditionalParam(HttpServletRequest hsRequest, String sourceURL){
		String urlPath = sourceURL;

		if("GET".equals(hsRequest.getMethod())){
				HashMap requestMap = (HashMap)hsRequest.getParameterMap();
				Iterator request = requestMap.keySet().iterator();
				List<BasicNameValuePair> paramList = new ArrayList<BasicNameValuePair>();
				while(request.hasNext()){
					String key = (String)request.next();
					Object value = hsRequest.getParameterMap().get(key);


					if(value instanceof String){
						if(FOLDER_ID_PARAM.equals(key)){
							value = paramMap.get((String)value);
						}

						 paramList.add(new BasicNameValuePair(key, (String)value));
					}else if(value instanceof String[]){

						if(FOLDER_ID_PARAM.equals(key)){
							value = paramMap.get(((String[])value)[0]);
							paramList.add(new BasicNameValuePair(key, (String)value));
						}else{
							paramList.add(new BasicNameValuePair(key, ((String[])value)[0]));
						}

					}

				}



				if(hsRequest.getRequestURI().indexOf(PARATURE_SEARCH_URL_SUFFIX)!= -1){

                       paramList.add(new BasicNameValuePair("_output_", paramMap.get(paramKeyList[9])));
                       paramList.add(new BasicNameValuePair("_token_", paramMap.get(paramKeyList[7])));
                       paramList.add(new BasicNameValuePair("Published", paramMap.get(paramKeyList[8])));

				}

				urlPath = URLBuilder.getBuilder().setPathInfo(sourceURL).setParamList(paramList).build();

		}
		log.info("The target URL send out through proxy : " + urlPath);
		return urlPath;

    }
    /**
     * This method performs the proxying of the request to the target address.
     *
     *
     * @param hsRequest  The request data which should be send to the
     * @param hsResponse The response data which will contain the data returned by the proxied request to target.
     * @throws java.io.IOException Passed on from the connection logic.
     */
	public  void execute(final HttpServletRequest hsRequest, final HttpServletResponse hsResponse) throws IOException {

        String target = paramMap.get(paramKeyList[2]);

    	log.info("execute, target is " + target);
        log.info("response commit state: " + hsResponse.isCommitted());

        if (StringUtils.isBlank(target)) {
            log.error("The target address is not given. Please provide a target address.");
            return;
        }

        log.info("checking url");
        final URL url;
        try {
            url = new URL(target);
        } catch (MalformedURLException e) {
            log.error("The provided target url is not valid.");
            return;
        }


        CloseableHttpClient httpclient =  HttpClients.custom().build();;


        try {
        	RequestConfig config = RequestConfig.custom()
									            .setSocketTimeout(CONNECTION_TIMEOUT)
									            .setConnectTimeout(CONNECTION_TIMEOUT)
									            .build();;
            HttpHost targetHost = new HttpHost(url.getHost(), 443, url.getProtocol());
            //If proxy required
            if("Y".equals(paramMap.get(paramKeyList[3]))){
	            HttpHost proxy = new HttpHost(paramMap.get(paramKeyList[0]), Integer.valueOf(paramMap.get(paramKeyList[1])));

	            config = RequestConfig.custom()
								            .setProxy(proxy)
								            .setSocketTimeout(CONNECTION_TIMEOUT)
							                .setConnectTimeout(CONNECTION_TIMEOUT)
								            .build();

	            if("Y".equals(paramMap.get(paramKeyList[4]))){


	                CredentialsProvider credsProvider = new BasicCredentialsProvider();
	                credsProvider.setCredentials(
	                      new AuthScope(paramMap.get(paramKeyList[0]), Integer.valueOf(paramMap.get(paramKeyList[1]))),
	                      new UsernamePasswordCredentials(paramMap.get(paramKeyList[5]), paramMap.get(paramKeyList[6])));

	                httpclient = HttpClients.custom()
	                        .setDefaultCredentialsProvider(credsProvider).build();

	            }

            }

            HttpRequestBase httpMethod = setupProxyRequest(hsRequest, addAdditionalParam(hsRequest, url.getPath()));

            httpMethod.setConfig(config);


            CloseableHttpResponse response = httpclient.execute(targetHost, httpMethod);
            try{
	            HttpEntity entity = response.getEntity();


	            if(SUCCESS_RESPONSE == response.getStatusLine().getStatusCode()){

	                InputStream originalResponseStream = entity.getContent();
	                //the body might be null, i.e. for responses with cache-headers which leave out the body
	                if (originalResponseStream != null) {
	                    OutputStream responseStream = hsResponse.getOutputStream();
	                    copyStream(originalResponseStream, responseStream);
	                }

	            }
	            setupResponseHeaders(httpMethod, hsResponse);
	            hsResponse.setStatus(response.getStatusLine().getStatusCode());

            }finally{
            	response.close();
            }

        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.close();
        }



    }

    private  void copyStream(InputStream in, OutputStream out) throws IOException {
        byte[] buf = new byte[65536];
        int count;
        while ((count = in.read(buf)) != -1) {
            out.write(buf, 0, count);
        }
    }


	/**@Description this method used to set the input parameter for the post request
	 * @param httpServletRequest
	 * @return
	 */
	private  String getRequestBody(HttpServletRequest httpServletRequest){


		String responseData = null;
		try {
			if(httpServletRequest.getInputStream()!=null){
				InputStreamReader isr = new InputStreamReader(httpServletRequest.getInputStream(), "utf-8");
				BufferedReader br = new BufferedReader(isr);

				int b;
				StringBuilder buf = new StringBuilder(512);
				while ((b = br.read()) != -1) {
					buf.append((char) b);
				}
				responseData = buf.toString();
				br.close();
				isr.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return responseData;

	}

    @SuppressWarnings("rawtypes")
	private  HttpRequestBase setupProxyRequest(final HttpServletRequest hsRequest, final String targetUrl) throws IOException {
        final String methodName = hsRequest.getMethod();
        final HttpRequestBase method;
        if ("POST".equalsIgnoreCase(methodName)) {
            HttpPost postMethod = new HttpPost(targetUrl);
            HttpEntity bodyEntity = new StringEntity(getRequestBody(hsRequest));
            postMethod.setEntity(bodyEntity);
            method = postMethod;
        } else if ("GET".equalsIgnoreCase(methodName)) {
            method = new HttpGet(targetUrl);
        } else {
            //log.warn("Unsupported HTTP method requested: " + hsRequest.getMethod());
            return null;
        }

        Enumeration e = hsRequest.getHeaderNames();
        if (e != null) {
            while (e.hasMoreElements()) {
                String headerName = (String) e.nextElement();
                if ("host".equalsIgnoreCase(headerName)) {
                    //the host value is set by the http client
                    continue;
                } else if ("content-length".equalsIgnoreCase(headerName)) {
                    //the content-length is managed by the http client
                    continue;
                } else if ("accept-encoding".equalsIgnoreCase(headerName)) {
                    //the accepted encoding should only be those accepted by the http client.
                    //The response stream should (afaik) be deflated. If our http client does not support
                    //gzip then the response can not be unzipped and is delivered wrong.
                    continue;
                } else if (headerName.toLowerCase().startsWith("cookie")) {
                    //fixme : don't set any cookies in the proxied request, this needs a cleaner solution
                    continue;
                }

                Enumeration values = hsRequest.getHeaders(headerName);
                while (values.hasMoreElements()) {
                    String headerValue = (String) values.nextElement();
                    log.info("setting proxy request parameter:" + headerName + ", value: " + headerValue);
                    method.addHeader(headerName, headerValue);
                }
            }
        }

        return method;
    }

    private  void setupResponseHeaders(HttpRequestBase httpMethod, HttpServletResponse hsResponse) {


        //filter the headers, which are copied from the proxy response. The http lib handles those itself.
        //Filtered out: the content encoding, the content length and cookies
        for (int i = 0; i < httpMethod.getAllHeaders().length; i++) {
            Header h = httpMethod.getAllHeaders()[i];
            if ("content-encoding".equalsIgnoreCase(h.getName())) {
                continue;
            } else if ("content-length".equalsIgnoreCase(h.getName())) {
                continue;
            } else if ("transfer-encoding".equalsIgnoreCase(h.getName())) {
                continue;
            } else if (h.getName().toLowerCase().startsWith("cookie")) {
                //retrieving a cookie which sets the session id will change the calling session: bad! So we skip this header.
                continue;
            } else if (h.getName().toLowerCase().startsWith("set-cookie")) {
                //retrieving a cookie which sets the session id will change the calling session: bad! So we skip this header.
                continue;
            }

            hsResponse.addHeader(h.getName(), h.getValue());
            log.info("setting response parameter:" + h.getName() + ", value: " + h.getValue());
        }



    }

    /**
     * This method performs the proxying of the request to the target address.
     *
     * @param target     The target address. Has to be a fully qualified address. The request is send as-is to this address.
     * @param hsRequest  The request data which should be send to the
     * @param hsResponse The response data which will contain the data returned by the proxied request to target.
     * @throws java.io.IOException Passed on from the connection logic.
     */
    private  void testExecute(final String target) throws IOException {


    }

    public static void main(String[] args){

        CommonProxyerImplTEST   proxyer = new CommonProxyerImplTEST();
        try {
			proxyer.testExecute("Abe");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

    }

}

Http client access https through proxy
    public  void testExecute(final String target) throws IOException {

    	private static String targetURL = "https://s7.parature.com/api/v1/30120/30172/Article?_keywords_=credit+test&Published=true&_output_=json&_token_=sQp5HJVLpFSHGuBnHPP6ynmXSyl5mmgrguT7UHOIQTyREBgiGHsB7zUAMY/yJOFItdFQ5AB5u7ExewEfvxUdTQ==";


//
//        final HttpMethod targetRequest = setupProxyRequest(hsRequest, url);
//        if (targetRequest == null) {
//            log.error("Unsupported request method found: " + hsRequest.getMethod());
//            return;
//        }
		Protocol easyhttps = new Protocol("https",
				new EasySSLProtocolSocketFactory(), 443);
		Protocol.registerProtocol("https", easyhttps);
        //perform the reqeust to the target server
        HttpClient client = new HttpClient();
        //client.setTimeout(10000);
        client.getParams().setContentCharset("UTF-8");


        //HostConfiguration hostConfig = client.getHostConfiguration();
//        config.setProxy(PROXY_HOST, PROXY_PORT);
//
        String username = "clieng\\E20002258";
        String password = "Spring11";
//        Credentials credentials = new UsernamePasswordCredentials(username, password);
//        AuthScope authScope = new AuthScope(PROXY_HOST, PROXY_PORT);
		client.getHostConfiguration().setProxy(PROXY_HOST,
				Integer.valueOf(PROXY_PORT));

		//client.getParams().setAuthenticationPreemptive(true);

		client.getState().setProxyCredentials(
				new AuthScope(PROXY_HOST, Integer.valueOf(PROXY_PORT)),
				new NTCredentials(username,
						password, PROXY_HOST, "client"));

       // client.getState().setProxyCredentials(authScope, credentials);

        GetMethod getRequest = new GetMethod("https://www.google.co.uk");
         int result = 0;
        try{
             result = client.executeMethod(getRequest);

        }finally{


        	getRequest.releaseConnection();
        }



        //log.info("set up response, result code was " + result);
    }
WAVLoader.java
package marf.Storage.Loaders;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import marf.Storage.MARFAudioFileFormat;
import marf.Storage.Sample;
import marf.Storage.SampleLoader;
import marf.Storage.StorageException;
import marf.util.ByteUtils;
import marf.util.InvalidSampleFormatException;


/**
 * <p>Loads/stores samples if WAVE format.</p>
 *
 * $Id: WAVLoader.java,v 1.26 2006/08/06 15:27:08 mokhov Exp $
 *
 * @author Jimmy Nicolacopoulos
 * @author Serguei Mokhov
 *
 * @version $Revision: 1.26 $
 * @since 0.0.1
 */
public class WAVLoader
extends SampleLoader
{
	/*
	 * ----------------
	 * Methods
	 * ----------------
	 */

	/**
	 * WAVLoader Constructor.
	 * @throws InvalidSampleFormatException if the WAV file isn't really in WAV format
	 * or any other error took place.
	 */
	public WAVLoader()
	throws InvalidSampleFormatException
	{
		this.oSample = new Sample(MARFAudioFileFormat.WAV);
		AudioFormat.Encoding oEncoding = AudioFormat.Encoding.PCM_SIGNED;

		float fRate = DEFAULT_FREQUENCY;
		int iBitSampleSize = DEFAULT_SAMPLE_BIT_SIZE;
		int iChannels = DEFAULT_CHANNELS;

		this.oAudioFormat = new AudioFormat
		(
			oEncoding,
			fRate,
			iBitSampleSize,
			iChannels,
			(iBitSampleSize / 8) * iChannels,
			fRate,
			false
		);
	}

	/**
	 * Loads and decodes the WAV sample from the provided stream.
	 * @see marf.Storage.SampleLoader#loadSample(java.io.InputStream)
	 * @since 0.3.0.6
	 */
	public Sample loadSample(InputStream poAudioDataInputStream)
	throws StorageException
	{
		try
		{
			AudioInputStream oNewInputStream;

			// The parameter should not be null and should be a regular file.
			if(poAudioDataInputStream != null)
			{
				// Check the file format of the file
				AudioFileFormat oFileFormat = AudioSystem.getAudioFileFormat(poAudioDataInputStream);

				if(oFileFormat.getType().equals(AudioFileFormat.Type.WAVE) == false)
				{
					throw new InvalidSampleFormatException("Audio file type is not WAVE");
				}

				// Get input stream from the file
				oNewInputStream = AudioSystem.getAudioInputStream(poAudioDataInputStream);

				// Check internal audio format characteristics we require
				//validateAudioFormat(oNewInputStream.getFormat());
			}
			else
			{
				throw new FileNotFoundException("Filename is either null or is not a regular file.");
			}

			// Set the stream and fill out the sample's buffer with data
			this.oAudioInputStream = oNewInputStream;
			updateSample();

			return this.oSample;
		}

		// To avoid re-wrapping into StorageException again.
		catch(StorageException e)
		{
			throw e;
		}

		// Wrap all the other exceptions here.
		catch(Exception e)
		{
			throw new StorageException(e);
		}
	}

	/**
	 * Buffers out the contents of an audio buffer into the parameter.
	 * @param padAudioData data array to fill in
	 * @return the number of words of data read (a word is two bytes)
	 * @throws StorageException if there was a problem reading the audio data
	 */
	public final int readAudioData(double[] padAudioData)
	throws StorageException
	{
		try
		{
			byte[] atAudioBuffer = new byte[padAudioData.length * 2];
			int iNbrBytes = this.oAudioInputStream.read(atAudioBuffer);
			int iWordCount = (iNbrBytes / 2) + (iNbrBytes % 2);

			for(int i = 0; i < iWordCount; i++)
			{
				padAudioData[i] = (double)ByteUtils.byteArrayToShort
				(
					atAudioBuffer,
					2 * i,
					this.oAudioFormat.isBigEndian()
				) / 32768;
			}

			return iWordCount;
		}
		catch(IOException e)
		{
			throw new StorageException(e);
		}
	}

	/**
	 * Buffers the contents of padAudioData into atAudioBuffer.
	 * @param padAudioData array of data to be written
	 * @param piNbrWords number of words to be written
	 * @return the number of data written
	 * @throws StorageException if there was an error writing audio data
	 */
	public final int writeAudioData(final double[] padAudioData, final int piNbrWords)
	throws StorageException
	{
		int iWord = 0;

		byte[] atAudioBytes;
		byte[] atAudioBuffer = new byte[piNbrWords * 2];

		for(int i = 0; i < piNbrWords; i++)
		{
			iWord = (int)(padAudioData[i] * 32768);
			atAudioBuffer[2 * i] = (byte)(iWord & 255);
			atAudioBuffer[2 * i + 1] = (byte)(iWord >>> 8);
		}

		this.oByteArrayOutputStream.write(atAudioBuffer, 0, atAudioBuffer.length);
		atAudioBytes = oByteArrayOutputStream.toByteArray();

		ByteArrayInputStream oBais = new ByteArrayInputStream(atAudioBytes);

		this.oAudioInputStream = new AudioInputStream
		(
			oBais,
			this.oAudioFormat,
			atAudioBytes.length / this.oAudioFormat.getFrameSize()
		);

		return atAudioBuffer.length;
	}

	/**
	 * Saves the wave into a file for playback.
	 * @param poOutFile File object for output
	 * @throws StorageException if there was an error saving sample
	 */
	public final void saveSample(File poOutFile)
	throws StorageException
	{
		try
		{
			AudioSystem.write(this.oAudioInputStream, AudioFileFormat.Type.WAVE, poOutFile);
			reset();
		}
		catch(IOException e)
		{
			throw new StorageException(e);
		}
	}

	/**
	 * Resets the marker for the audio and byte-array streams.
	 * Used after writing audio data into the sample's audio stream.
	 * @throws StorageException if there was an error resetting the streams
	 * @since 0.3.0
	 */
	public void reset()
	throws StorageException
	{
		super.reset();
		this.oByteArrayOutputStream.reset();
	}

	/**
	 * Validates audio file stream format for WAVE files.
	 * Checks the format has the required bit size, number
	 * of channels, and required sampling frequency.
	 * @param poFormat the audio format to validate
	 * @throws UnsupportedAudioFileException if any of the three criteria are not met
	 * @since 0.3.0.5
	 */
	public void validateAudioFormat(final AudioFormat poFormat)
	throws UnsupportedAudioFileException
	{
		if(poFormat.getSampleSizeInBits() != this.iRequiredBitSize)
		{
			throw new UnsupportedAudioFileException
			(
				"Wave file not " + this.iRequiredBitSize + "-bit"
			);
		}

		if(poFormat.getChannels() != this.iRequiredChannels)
		{
			throw new UnsupportedAudioFileException("Wave file is not mono.");
		}

		if(poFormat.getFrameRate() != this.iRequiredFrequency)
		{
			throw new UnsupportedAudioFileException
			(
				"Wave file is not " + this.iRequiredFrequency + " Hz"
			);
		}
	}

	/**
	 * Returns source code revision information.
	 * @return revision string
	 * @since 0.3.0.2
	 */
	public static String getMARFSourceCodeRevision()
	{
		return "$Revision: 1.26 $";
	}
}

// EOF
SampleLoader.java
package marf.Storage;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;

import marf.util.NotImplementedException;


/**
 * <p>Abstract class that provides a generic sound-oriented implementation of the
 * sample loading interface. Must be overridden by a concrete sample loader.</p>
 *
 * $Id: SampleLoader.java,v 1.25 2006/08/06 05:35:34 mokhov Exp $
 *
 * @author Serguei Mokhov
 * @author Jimmy Nicolacopoulos
 *
 * @version $Revision: 1.25 $
 * @since 0.0.1
 */
public abstract class SampleLoader
implements ISampleLoader
{
	/*
	 * ----------------
	 * Data Members
	 * ----------------
	 */

	/**
	 * Current bit size of a sample.
	 */
	protected int iRequiredBitSize = DEFAULT_SAMPLE_BIT_SIZE;

	/**
	 * Current number of channels.
	 */
	protected int iRequiredChannels = DEFAULT_CHANNELS;

	/**
	 * Sample references of the sample to be loaded.
	 */
	protected Sample oSample = null;

	/**
	 * Properties of a sound sample.
	 */
	protected AudioFormat oAudioFormat = null;

	/**
	 * Stream representing sound sample.
	 */
	protected AudioInputStream oAudioInputStream = null;

	/**
	 * Output stream used for writing audio data.
	 */
	protected ByteArrayOutputStream oByteArrayOutputStream = null;

	/**
	 * Current frequency.
	 * @since 0.3.0
	 */
	protected float iRequiredFrequency = DEFAULT_FREQUENCY;

	/**
	 * Default constructor.
	 * Instantiates <code>ByteArrayOutputStream</code>.
	 */


	public SampleLoader()
	{
		this.oByteArrayOutputStream = new ByteArrayOutputStream();
	}

	public int getiRequiredBitSize() {
		return iRequiredBitSize;
	}

	public void setiRequiredBitSize(int iRequiredBitSize) {
		this.iRequiredBitSize = iRequiredBitSize;
	}

	public int getiRequiredChannels() {
		return iRequiredChannels;
	}

	public void setiRequiredChannels(int iRequiredChannels) {
		this.iRequiredChannels = iRequiredChannels;
	}

	public float getiRequiredFrequency() {
		return iRequiredFrequency;
	}

	public void setiRequiredFrequency(float iRequiredFrequency) {
		this.iRequiredFrequency = iRequiredFrequency;
	}

	/**
	 * Same as loadSample(File) but takes filename as an argument.
	 * @param pstrFilename filename of a sample to be read from
	 * @return Sample object reference
	 * @throws StorageException if there was an error loading the sample
	 */
	public Sample loadSample(final String pstrFilename)
	throws StorageException
	{
		return loadSample(new File(pstrFilename));
	}


	/**
	 * Loads sample data from a file. In a nutshell, converts the
	 * File into a buffered file input streams and passes it on
	 * the appropriate method.
	 *
	 * @param poInFile incoming sample File object
	 * @return Sample object
	 * @throws StorageException if there was a problem loading the sample
	 * @since 0.3.0.6
	 * @see #loadSample(InputStream)
	 */
	public Sample loadSample(File poInFile)
	throws StorageException
	{
		try
		{
			if(poInFile != null && poInFile.isFile())
			{
				return loadSample(new BufferedInputStream(new FileInputStream(poInFile)));
			}
			else
			{
				throw new FileNotFoundException("Filename is either null or is not a regular file.");
			}
		}

		// To avoid re-wrapping into StorageException again.
		catch(StorageException e)
		{
			throw e;
		}

		// Wrap all the other exceptions here.
		catch(Exception e)
		{
			throw new StorageException(e);
		}
	}

	/**
	 * Converts the byte array into a buffered byte array input stream
	 * and passes it on.
	 *
	 * @see marf.Storage.ISampleLoader#loadSample(byte[])
	 * @since 0.3.0.6
	 * @see #loadSample(InputStream)
	 */
	public Sample loadSample(byte[] patFileAudioData)
	throws StorageException
	{
		return loadSample(new BufferedInputStream(new ByteArrayInputStream(patFileAudioData)));
	}

	/**
	 * Not implemented. Must be overridden to work.
	 * @see marf.Storage.ISampleLoader#loadSample(java.io.InputStream)
	 * @since 0.3.0.6
	 * @throws NotImplementedException
	 */
	public Sample loadSample(InputStream poAudioDataInputStream)
	throws StorageException
	{
		throw new NotImplementedException();
	}

	/**
	 * Same as saveSample(File) but takes filename as an argument.
	 * @param pstrFilename filename of a sample to be saved to
	 * @throws StorageException if there was an error saving the sample
	 */
	public void saveSample(final String pstrFilename)
	throws StorageException
	{
		saveSample(new File(pstrFilename));
	}

	/**
	 * <p><code>updateSample()</code> is just used whenever the
	 * <code>AudioInputStream</code> is assigned to a new value (wave file).
	 * Then you would simply call this method to update the
	 * <code>Sample</code> member with the contents of the new <code>AudioInputStream</code>.</p>
	 * @throws StorageException if there was an error updating the sample data array
	 */
	public void updateSample()
	throws StorageException
	{
		double[] adSampleArray = new double[(int)getSampleSize()];
		readAudioData(adSampleArray);
		this.oSample.setSampleArray(adSampleArray);
	}

	/**
	 * Resets the marker for the audio stream. Used after writing audio data
	 * into the sample's audio stream.
	 * @throws StorageException if there was an error resetting the audio stream
	 */
	public void reset()
	throws StorageException
	{
		try
		{
			this.oAudioInputStream.reset();
		}
		catch(Exception e)
		{
			throw new StorageException(e);
		}
	}

	/**
	 * Retrieves the length of the sample (# of audio data in the audio stream).
	 * @return sample size, long
	 * @throws StorageException if there was an error getting sample size
	 */
	public long getSampleSize()
	throws StorageException
	{
		return this.oAudioInputStream.getFrameLength();
	}

	/**
	 * Returns internal reference to a Sample object.
	 * @return Sample reference
	 */
	public final Sample getSample()
	{
		return this.oSample;
	}

	/**
	 * Sets internal sample reference from outside.
	 * @param poSample Sample object
	 */
	public final void setSample(Sample poSample)
	{
		this.oSample = poSample;
	}

	/**
	 * Returns source code revision information.
	 * @return revision string
	 * @since 0.3.0.2
	 */
	public static String getMARFSourceCodeRevision()
	{
		return "$Revision: 1.25 $";
	}
}

// EOF
ResultSet.java
package marf.Storage;

import java.io.Serializable;
import java.util.Vector;

import marf.SpeakersIdentDb;
import marf.util.Arrays;
import marf.util.Debug;
import marf.util.SortComparator;
import marf.util.comparators.ResultComparator;


/**
 * <p>Class ResultSet represents classification result
 * set - IDs and some stats. May be sorted.
 * </p>
 *
 * $Id: ResultSet.java,v 1.21 2006/07/10 16:28:38 mokhov Exp $
 *
 * @author Serguei Mokhov
 * @version $Revision: 1.21 $
 * @since 0.3.0.2
 */
public class ResultSet
implements Serializable, Cloneable
{
	/**
	 * Indicates that this result set is unsorted.
	 * @since 0.3.0.4
	 */
	public static final int UNSORTED = -1;

	/**
	 * Distances from other samples and other stats or
	 * probabilities and likelyhood (growable and shrinkable).
	 */
	protected Vector oResultSet = null;

	/**
	 * References to the objects in the oResultSet
	 * in the sorted order.
	 */
	protected Result[] aoResultSetSorted = null;

	/**
	 * Used to remember in which direction sorting was performed,
	 * so some methods can work correctly. Default is UNSORTED.
	 * Otherwise, it is <code>SortComparator.ASCENDING</code>
	 * or <code>SortComparator.DESCENDING</code>. It is set by
	 * the <code>sort()</code> method only.
	 *
	 * @see #getSecondClosestID()
	 * @see #sort(int)
	 * @see SortComparator#ASCENDING
	 * @see SortComparator#DESCENDING
	 * @see #UNSORTED
	 *
	 * @since 0.3.0.3
	 */
	protected int iSortMode = UNSORTED;

	/**
	 * For serialization versioning.
	 * When adding new members or make other structural
	 * changes regenerate this number with the
	 * <code>serialver</code> tool that comes with JDK.
	 * @since 0.3.0.4
	 */
	private static final long serialVersionUID = -3133714664001380852L;

	/**
	 * Default constructor, which is
	 * equivalent to <code>ResultSet(new Vector())</code>.
	 */
	public ResultSet()
	{
		this(new Vector());
	}

	/**
	 * ID Vector ResultSet Constructor.
	 * @param poResultSet Vector of relevant data
	 * @throws IllegalArgumentException if the parameter is null
	 */
	public ResultSet(Vector poResultSet)
	{
		if(poResultSet == null)
		{
			throw new IllegalArgumentException("Result set Vector cannot be null.");
		}

		this.oResultSet = poResultSet;
	}

	/**
	 * Copy-constructor.
	 * @param poResultSet ResultSet object reference to make a copy of
	 * @since 0.3.0.5
	 */
	public ResultSet(final ResultSet poResultSet)
	{
		this.oResultSet = (Vector)poResultSet.oResultSet.clone();
		this.iSortMode = poResultSet.iSortMode;
		this.aoResultSetSorted = (Result[])poResultSet.aoResultSetSorted.clone();
	}

	/**
	 * Retrieves ID of a subject with minimum distance/probability.
	 * @return integer ID
	 * @throws ArrayIndexOutOfBoundsException if there are no results
	 */
	public final int getMininumID()
	{
		sort(SortComparator.ASCENDING);
		return this.aoResultSetSorted[0].getID();
	}

	public final Result getBestMatchValue(SpeakersIdentDb oDB){
		try{
			sort(SortComparator.ASCENDING);
			for(Result result:this.aoResultSetSorted){
				if(oDB.isValidResult(result.getID())){
					return result;
				}
			}
		}catch(Exception e){

		}
		return this.aoResultSetSorted[0];
	}
	public final Result getSecondMatchValue(){
		sort(SortComparator.ASCENDING);
		return this.aoResultSetSorted[1];
	}
	/**
	 * Retrieves ID of a subject with the distance/probability next
	 * to the minimum.
	 * @return integer ID
	 * @throws ArrayIndexOutOfBoundsException if there is only one
	 * or no result in the result set.
	 */
	public final int getSecondMininumID()
	{
		sort(SortComparator.ASCENDING);
		return this.aoResultSetSorted[1].getID();
	}

	/**
	 * Retrieves ID of a subject with maximum distance/probability.
	 * @return integer ID
	 * @throws ArrayIndexOutOfBoundsException if there are no results
	 */
	public final int getMaximumID()
	{
		sort(SortComparator.DESCENDING);
		return this.aoResultSetSorted[0].getID();
	}

	/**
	 * Retrieves ID of a subject with the distance/probability next
	 * to the maximum.
	 * @return integer ID
	 * @throws ArrayIndexOutOfBoundsException if there is only one
	 * or no result in the result set.
	 */
	public final int getSecondMaximumID()
	{
		sort(SortComparator.DESCENDING);
		return this.aoResultSetSorted[1].getID();
	}

	/**
	 * Returns second closest ID.
	 *
	 * @return ID of an entity (speaker, instrument, emotion, etc.); or -1
	 * if the first ID was not retrieved yet.
	 *
	 * @see #getSecondMininumID()
	 * @see #getSecondMaximumID()
	 */
	public final int getSecondClosestID()
	{
		switch(this.iSortMode)
		{
			case SortComparator.ASCENDING:
			{
				return getSecondMininumID();
			}

			case SortComparator.DESCENDING:
			{
				return getSecondMaximumID();
			}

			default:
			{
				Debug.debug(getClass(), "Call to getSecondClosestID() when not sorted.");
			}
		}

		return -1;
	}

	/**
	 * Retrieves ID of a subject with average distance/probability.
	 * @return integer ID
	 * @throws ArrayIndexOutOfBoundsException if there are no results
	 */
	public final int getAverageID()
	{
		sort(SortComparator.ASCENDING);
		return this.aoResultSetSorted[size() / 2].getID();
	}

	/**
	 * Retrieves a pseudo random ID of a subject.
	 * Used in the base-line testing.
	 * @return integer ID
	 * @throws ArrayIndexOutOfBoundsException if there are no results
	 */
	public final int getRandomID()
	{
		return ((Result)this.oResultSet.elementAt((int)(Math.random() * size()))).getID();
	}

	/**
	 * Perform sorting of the results in the result set.
	 * @param piMode sorting mode, either <code>SortComparator.ASCENDING</code> or
	 * <code>SortComparator.DESCENDING</code>.
	 *
	 * @see SortComparator#ASCENDING
	 * @see SortComparator#DESCENDING
	 *
	 * @throws IllegalArgumentException if the parameter is neither of the two modes
	 */
	public final void sort(final int piMode)
	{
		if(this.iSortMode != piMode)
		{
			this.iSortMode = piMode;
			this.aoResultSetSorted = (Result[])this.oResultSet.toArray(new Result[0]);
			Arrays.sort(this.aoResultSetSorted, new ResultComparator(this.iSortMode));
		}
	}

	/**
	 * Add result to the result set.
	 * @param piID subject ID recognized
	 * @param pdOutcome outcome of the recongnition distance or likelyhood
	 * @param pstrDescription textual description of the result
	 */
	public final void addResult(int piID, double pdOutcome, String pstrDescription)
	{
		this.oResultSet.add(new Result(piID, pdOutcome, pstrDescription));

		// Invalidate the sorted flag.
		this.iSortMode = UNSORTED;
	}

	/**
	 * Add result to the result set. Generates description based
	 * on the two parameters.
	 * @param piID subject ID recognized
	 * @param pdOutcome outcome of the recongnition distance or likelyhood
	 */
	public final void addResult(int piID, double pdOutcome)
	{
		addResult
		(
			piID,
			pdOutcome,
			new StringBuffer("ID=").append(piID).append(", outcome=").append(pdOutcome).toString()
		);
	}

	/**
	 * Add result to the result set based on already pre-constructed
	 * object.
	 * @param poResult Result object prepared ouside
	 * @throws IllegalArgumentException of the parameter is null
	 */
	public final void addResult(Result poResult)
	{
		if(poResult == null)
		{
			throw new IllegalArgumentException("Result parameter is null.");
		}

		this.oResultSet.add(poResult);
	}

	/**
	 * Retrieves the result from the result set with the
	 * minimum outcome value.
	 * @return corresponding Result object
	 */
	public Result getMinimumResult()
	{
		getMininumID();
		return this.aoResultSetSorted[0];
	}

	/**
	 * Retrieves the result from the result set with the
	 * average outcome value.
	 * @return corresponding Result object
	 */
	public Result getAverageResult()
	{
		getMininumID();
		return this.aoResultSetSorted[this.oResultSet.size() / 2];
	}

	/**
	 * Retrieves pseudo-random result object from the result set.
	 * Used in base-line testing.
	 * @return corresponding Result object
	 */
	public Result getRandomResult()
	{
		return (Result)this.oResultSet.elementAt((int)(Math.random() * size()));
	}

	/**
	 * Retrieves the result from the result set with the
	 * maximum outcome value.
	 * @return corresponding Result object
	 */
	public Result getMaximumResult()
	{
		sort(SortComparator.DESCENDING);

		// Debug
		if(Debug.isDebugOn())
		{
			for(int i = 0; i < aoResultSetSorted.length; i++)
			{
				Debug.debug("after.oResultSet=" + aoResultSetSorted[i]);
			}
		}

		return this.aoResultSetSorted[0];
	}

	/**
	 * Retrieves the underlying unsorted result collection.
	 * @return Vector of Results
	 */
	public Vector getResultSetVector()
	{
		/*
		 * Be pessimistic about what can be done with the
		 * retured result set vector reference outside of this.
		 * Thus, don't trust the client code anymore to keep
		 * the stuff unmodified (i.e. adding/deleting new records)
		 * and force a resorting internally in the sort() method.
		 */
		this.iSortMode = UNSORTED;

		return this.oResultSet;
	}

	/**
	 * Allows querying the current array of references to
	 * the contained Result objects sorted (if sorting was performed).
	 * The sorting is usually done when querying for minimum or
	 * maximum results.
	 * @return Returns the aoResultSetSorted.
	 * @since 0.3.0.5
	 */
	public Result[] getResultSetSorted()
	{
		return this.aoResultSetSorted;
	}

	/**
	 * Sets the underlying unsorted result collection.
	 * @param poResultSet the result set vector to set
	 * @since 0.3.0.6
	 */
	public void setResultSetVector(Vector poResultSet)
	{
		this.iSortMode = UNSORTED;
		this.oResultSet = poResultSet;
	}

	/**
	 * Allows setting the current array of sorted references to
	 * the contained Result objects if sorted outside.
	 * @param paoResultSetSorted the new collection of sorted references
	 * @since 0.3.0.6
	 */
	public void setResultSetSorted(Result[] paoResultSetSorted)
	{
		this.aoResultSetSorted = paoResultSetSorted;
	}

	/**
	 * Allows setting the sort mode the result set
	 * may be sorted next time in accordance with.
	 * @param piSortMode the sort mode to set
	 * @since 0.3.0.6
	 * @see #UNSORTED
	 * @see SortComparator#ASCENDING
	 * @see SortComparator#DESCENDING
	 * @see #iSortMode
	 */
	public void setSortMode(int piSortMode)
	{
		this.iSortMode = piSortMode;
	}

	/**
	 * Allows querying the sort mode the result set
	 * may be currently sorted in accordance with.
	 * @return the curren sort mode
	 * @since 0.3.0.5
	 * @see #UNSORTED
	 * @see SortComparator#ASCENDING
	 * @see SortComparator#DESCENDING
	 * @see #iSortMode
	 */
	public final int getSortMode()
	{
		return this.iSortMode;
	}

	/**
	 * Returns inner ResultSet data converted to string.
	 * @return String representation of a ResultSet object
	 */
	public String toString()
	{
		StringBuffer oSortedBuffer = new StringBuffer();

		if(this.aoResultSetSorted == null)
		{
			oSortedBuffer.append("N/A");
		}
		else
		{
			oSortedBuffer.append("(");

			for(int i = 0; i < this.aoResultSetSorted.length; i++)
			{
				if(i != 0)
				{
					oSortedBuffer.append(",");
				}

				oSortedBuffer.append(this.aoResultSetSorted[i]);
			}

			oSortedBuffer.append(")");
		}

		StringBuffer oBuffer = new StringBuffer();

		oBuffer
			.append("Raw ResultSet data:\n")
			.append(this.oResultSet).append("\n\n")
			.append("Sorted data:\n").append(oSortedBuffer);

		return oBuffer.toString();
	}

	/**
	 * Retrieves result count of the results in this result set.
	 * @return integer result count
	 */
	public int size()
	{
		return this.oResultSet.size();
	}

	/**
	 * Implements Cloneable interface for the ResultSet object.
	 * @see java.lang.Object#clone()
	 * @since 0.3.0.5
	 */
	public Object clone()
	{
		return new ResultSet(this);
	}

	/**
	 * Returns source code revision information.
	 * @return revision string
	 */
	public static String getMARFSourceCodeRevision()
	{
		return "$Revision: 1.21 $";
	}
}

// EOF
NeuralNetwork.java
package marf.Classification.NeuralNetwork;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Random;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import marf.MARF;
import marf.Classification.Classification;
import marf.Classification.ClassificationException;
import marf.FeatureExtraction.IFeatureExtraction;
import marf.Storage.Cluster;
import marf.Storage.Result;
import marf.Storage.StorageException;
import marf.util.Debug;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;


/**
 * <p>Artificial Neural Network-based Classifier.</p>
 *
 * $Id: NeuralNetwork.java,v 1.58 2006/07/31 14:33:47 mokhov Exp $
 *
 * @author Ian Clement
 * @author Serguei Mokhov
 *
 * @version $Revision: 1.58 $
 * @since 0.0.1
 */
public class NeuralNetwork
extends Classification
{
	/*
	 * ----------------------
	 * Enumeration
	 * ----------------------
	 */

	/**
	 * How many binary Neurons in the output layer.
	 * Presumably int (our ID) is 4 bytes, hence 4 * 8 = 32 bits, and so many outputs.
	 * @since 0.2.0
	 */
	public static final int DEFAULT_OUTPUT_NEURON_BITS = 32;

	/**
	 * Default training constant of <code>1</code> if none supplied.
	 * @since 0.2.0
	 */
	public static final double DEFAULT_TRAINING_CONSTANT = 1;

	/**
	 * Default number of epoch iterations of <code>64</code> if none supplied.
	 * @since 0.2.0
	 */
	public static final int DEFAULT_EPOCH_NUMBER = 64;

	/**
	 * Default minimum training error of <code>0.1</code> if none supplied.
	 * @since 0.2.0
	 */
	public static final double DEFAULT_MIN_ERROR = 0.1;


	/*
	 * ----------------------
	 * Data Members
	 * ----------------------
	 */

	/**
	 * Collection of layers.
	 */
	private ArrayList oLayers = new ArrayList();

	/**
	 * Current layer.
	 */
	private transient Layer oCurrentLayer;

	/**
	 * Current layer's #.
	 */
	private transient int iCurrenLayer = 0;

	/**
	 * Number of the buffered layer.
	 */
	private transient int iCurrLayerBuf = 0;

	/**
	 * Current Neuron.
	 */
	private transient Neuron oCurrNeuron;

	/**
	 * Neuron Type.
	 */
	private transient int iNeuronType = Neuron.UNDEF;

	/**
	 * Input layer.
	 */
	private Layer oInputs = new Layer();

	/**
	 * Output layer.
	 */
	private Layer oOutputs = new Layer();

	/* Constants used for JAXP 1.2 */

	/**
	 * All output will use this encoding.
	 */
	public static final String OUTPUT_ENCODING = "UTF-8";

	/**
	 * JAXP 1.2 Schema.
	 */
	public static final String JAXP_SCHEMA_LANGUAGE =
		"http://java.sun.com/xml/jaxp/properties/schemaLanguage";

	/**
	 * XML 2001 Schema.
	 */
	public static final String W3C_XML_SCHEMA =
		"http://www.w3.org/2001/XMLSchema";

	/**
	 * JAXP 1.2 Schema URL.
	 */
	public static final String JAXP_SCHEMA_SOURCE =
		"http://java.sun.com/xml/jaxp/properties/schemaSource";

	/**
	 * For serialization versioning.
	 * When adding new members or make other structural
	 * changes regenerate this number with the
	 * <code>serialver</code> tool that comes with JDK.
	 * @since 0.3.0.4
	 */
	private static final long serialVersionUID = 6116721242820120028L;


	/*
	 * ----------------------
	 * Methods
	 * ----------------------
	 */

	/**
	 * NeuralNetwork Constructor.
	 * @param poFeatureExtraction FeatureExtraction module reference
	 */
	public NeuralNetwork(IFeatureExtraction poFeatureExtraction)
	{
		super(poFeatureExtraction);
		//this.oObjectToSerialize = this;
//		this.iCurrentDumpMode = DUMP_XML;
		this.iCurrentDumpMode = DUMP_GZIP_BINARY;
//		this.iCurrentDumpMode = DUMP_BINARY;
		this.strFilename = getDefaultFilename();
	}

	/* Classification API */

	/**
	 * Implements training of Neural Net.
	 * @return <code>true</code> if training was successful
	 * @throws ClassificationException if there are any errors
	 * @throws NullPointerException if module parameters are incorrectly set
	 */
	public final boolean train()
	throws ClassificationException
	{
		return trainImplementation(null);
	}

	/**
	 * Implements training of Neural Net given the feature vector.
	 * @param padFeatureVector the feature vector to train on
	 * @return <code>true</code> if training was successful
	 * @throws ClassificationException if there are any errors
	 * @throws NullPointerException if module parameters are incorrectly set
	 * @since 0.3.0.6
	 */
	public final boolean train(double[] padFeatureVector)
	throws ClassificationException
	{
		return trainImplementation(padFeatureVector);
	}

	/**
	 * Implements training of Neural Net.
	 * @param padFeatureVector the feature vector to train on; if null pipelining mode is used
	 * @return <code>true</code> if training was successful
	 * @throws ClassificationException if there are any errors
	 * @throws NullPointerException if module parameters are incorrectly set
	 * @since 0.3.0.6
	 */
	private final boolean trainImplementation(double[] padFeatureVector)
	throws ClassificationException
	{
		Vector oTrainingSamples = null;
		Vector oParams = null;

		try
		{
			/*
			 * Get newly coming feature vector into the TrainingSet cluster
			 * in case it's not there.
			 */
			int iBackupDumpMode = this.iCurrentDumpMode;
//			this.iCurrentDumpMode = DUMP_BINARY;
			this.iCurrentDumpMode = DUMP_GZIP_BINARY;

			if(padFeatureVector == null)
			{
				super.train();
			}
			else
			{
				super.train(padFeatureVector);
			}

			this.iCurrentDumpMode = iBackupDumpMode;

			// Defaults
			double dTrainConst = DEFAULT_TRAINING_CONSTANT;
			int    iEpochNum   = DEFAULT_EPOCH_NUMBER;
			double dMinErr     = DEFAULT_MIN_ERROR;

			// Defaults can be overridden by an app
			if(MARF.getModuleParams() != null)
			{
				oParams = MARF.getModuleParams().getClassificationParams();

				if(oParams.size() > 1)
				{
					// May throw NullPointerException
					dTrainConst = ((Double)oParams.elementAt(1)).doubleValue();
					iEpochNum   = ((Integer)oParams.elementAt(2)).intValue();
					dMinErr     = ((Double)oParams.elementAt(3)).doubleValue();
				}
			}

			// Reload training data from the disk if there was any
			restore();

			// Get the Training set...
			oTrainingSamples = this.oTrainingSet.getClusters();

			// Set initial values to always enter the epoch training loop
			int    iLimit = 0;
			double dError = dMinErr + 1;

			// Epoch training
			while(dError > dMinErr && iLimit < iEpochNum)
			{
				// Execute the training for each training cluster of utterances
				for(int i = 0; i < oTrainingSamples.size(); i++)
				{
					Cluster oCluster = (Cluster)oTrainingSamples.get(i);
					train(oCluster.getMeanVector(), oCluster.getSubjectID(), dTrainConst);

					// Commit modified weight
					commit();
				}

				// Test new values and calc error...
				// TODO: Testing is done with the same training samples :-(
				int iCount = 0;
				dError = 0.0;

				for(iCount = 0; iCount < oTrainingSamples.size(); iCount++)
				{
					Cluster oCluster = (Cluster)oTrainingSamples.get(iCount);

					setInputs(oCluster.getMeanVector());
					runNNet();

					int iID = interpretAsBinary();

//					dError += Math.abs(oCluster.getSubjectID() - iID);
					dError += dMinErr * Math.abs(oCluster.getSubjectID() - iID);

					Debug.debug("Expected: " + oCluster.getSubjectID() + ", Got: " + iID + ", Error: " + dError);
				}

				if(iCount == 0)
				{
					throw new ClassificationException("NeuralNetwork.train() --- There are no training samples!");
				}

				dError /= iCount;
				iLimit++;

				Debug.debug("Epoch: error = " + dError + ", limit = " + iLimit);
			}

			dump();

			return true;
		}
		catch(StorageException e)
		{
			e.printStackTrace(System.err);

			throw new ClassificationException
			(
				"StorageException while dumping/restoring neural net: " +
				e.getMessage(), e
			);
		}
		catch(NullPointerException e)
		{
			e.printStackTrace(System.err);

			throw new ClassificationException
			(
				"NeuralNetwork.train(): Missing required ModuleParam (" + oParams +
				") or TrainingSample (" + oTrainingSamples + ")"
			);
		}
	}


	/**
	 * Neural Network implementation of classification routine.
	 * In 0.3.0.6 the generic pipelined verision of this API
	 * <code>classify()</code> was refactored into the
	 * <code>Classification</code>.
	 *
	 * @return <code>true</code> upon successful classification
	 *
	 * @throws ClassificationException when input feature vector
	 * length does not match the size of the input neuron layer or
	 * if there was a StorageException during dump/restore.
	 *
	 * @since 0.3.0.6
	 */
	public final boolean classify(double[] padFeatureVector)
	throws ClassificationException
	{
		try
		{
//			double[] adFeatures = this.oFeatureExtraction.getFeaturesArray();
			double[] adFeatures = padFeatureVector;

			// Reload trained net
			restore();

			if(adFeatures.length != this.oInputs.size())
			{
				throw new ClassificationException
				(
					"Input array size (" + adFeatures.length +
					") not consistent with input layer (" + this.oInputs.size() + ")"
				);
			}

			// Set the incoming features to the net's inputs
			for(int i = 0; i < adFeatures.length; i++)
			{
				this.oInputs.get(i).dResult = adFeatures[i];
			}

			// Execute the algorithm
			runNNet();

			// Make result...
			// TODO: fix second best kludge of adding the same thing twice
			this.oResultSet.addResult(new Result(interpretAsBinary()));
			this.oResultSet.addResult(new Result(interpretAsBinary() + 1));

			return true;
		}
		catch(StorageException e)
		{
			e.printStackTrace(System.err);
			throw new ClassificationException(e);
		}
	}

	/**
	 * Evaluates the entire neural network.
	 * @since 0.3.0.5
	 */
	public final void eval()
	{
		runNNet();
	}

	/**
	 * Evaluates the entire neural network.
	 */
	private final void runNNet()
	{
		for(int i = 0; i < this.oLayers.size(); i++)
		{
			Layer oTmpLayer = (Layer)this.oLayers.get(i);
			oTmpLayer.eval();
		}
	}

	//----------- Methods for Creating the NNet -----------------

	/**
	 * Parses XML and produces a neural network data structure.
	 * @param pstrFilename net's XML filename
	 * @param pbValidateDTD if true DTD will be validated
	 * @throws StorageException if there was an I/O or otherwise error
	 * during initialization of the net
	 */
	public final void initialize(final String pstrFilename, final boolean pbValidateDTD)
	throws StorageException
	{
		try
		{
			Debug.debug("Initializing XML parser...");

			DocumentBuilderFactory oDBF = DocumentBuilderFactory.newInstance();

			oDBF.setNamespaceAware(true);
			oDBF.setValidating(pbValidateDTD);

			DocumentBuilder oBuilder = oDBF.newDocumentBuilder();
			OutputStreamWriter oErrorWriter = new OutputStreamWriter(System.err, OUTPUT_ENCODING);

			oBuilder.setErrorHandler(new NeuralNetworkErrorHandler(new PrintWriter(oErrorWriter, true)));

			Debug.debug("Parsing XML file...");
			Document oDocument = oBuilder.parse(new File(pstrFilename));

			// Add input layer
			this.oLayers.add(this.oInputs);

			// Build NNet structure
			Debug.debug("Making the NNet structure...");
			buildNetwork(oDocument);

			// Add output layer
			this.oLayers.add(this.oOutputs);

			// Fix inputs/outputs
			Debug.debug("Setting the inputs and outputs for each Neuron...");
			this.iCurrenLayer = 0;
			createLinks(oDocument);
		}
		catch(FileNotFoundException e)
		{
			try
			{
				generate();
				dump();
			}
			catch(ClassificationException oClassificationException)
			{
				oClassificationException.printStackTrace(System.err);
				throw new StorageException(oClassificationException);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace(System.err);
			throw new StorageException(e);
		}
    }

	/**
	 * Generates the initial network at random with the default paramters.
	 * The defaults include the number of input neurons is the same as number of
	 * features <it>f</it>, the number of output layer neurons is the same as the
	 * number of bits in an integer <it>n</it>, and one middle (hidden) layer that has
	 * <it>h = |f - n| / 2</i>. If  <it>f = n</it>, then <it>h = f / 2</it>.
	 * @throws ClassificationException
	 * @since 0.3.0.6
	 * @see #DEFAULT_OUTPUT_NEURON_BITS
	 */
	public void generate()
	throws ClassificationException
	{
		Debug.debug("Generating new net...");

		int iFeaturesNum = this.oFeatureExtraction.getFeaturesArray().length;

		int iLastHiddenNeurons = Math.abs(iFeaturesNum - DEFAULT_OUTPUT_NEURON_BITS) / 2;

		if(iLastHiddenNeurons == 0)
		{
			iLastHiddenNeurons = iFeaturesNum / 2;
		}

		// Generate fully linked 3-layer neural net with random weights
		generate
		(
			// As many inputs as features
			iFeaturesNum,

			// "Middleware", from air
			new int[]
			{
				iFeaturesNum * 2,
				iFeaturesNum,
				iLastHiddenNeurons
			},

			// Output layer
			DEFAULT_OUTPUT_NEURON_BITS
		);

		Debug.debug("Dumping newly generated net...");
	}

	/**
	 * Performs DOM tree traversal to build neural network structure.
	 * @param poNode current root Node
	 */
	private final void buildNetwork(Node poNode)
	{
		String strName;
		int iType = poNode.getNodeType();

		if(iType == Node.ELEMENT_NODE)
		{
			strName = poNode.getNodeName();

			// TODO: not yet ;-)
			if(strName.equals("input") || strName.equals("output"))
			{
				return;
			}

			//Debug.debug("Making " + name + "...");

			NamedNodeMap oAtts = poNode.getAttributes();

			if(strName.equals("layer"))
			{
				for(int i = 0; i < oAtts.getLength(); i++)
				{
					Node oAttribute = oAtts.item(i);

					String strAttName = oAttribute.getNodeName();
					String strAttValue = oAttribute.getNodeValue();

					if(strAttName.equals("type"))
					{
						if(strAttValue.equals("input"))
						{
							this.oCurrentLayer = this.oInputs;
							this.iNeuronType = Neuron.INPUT;
						}
						else if(strAttValue.equals("output"))
						{
							this.oCurrentLayer = this.oOutputs;
							this.iNeuronType = Neuron.OUTPUT;
						}
						else
						{
							this.oCurrentLayer = new Layer();
							this.oLayers.add(this.oCurrentLayer);
							this.iNeuronType = Neuron.HIDDEN;
						}
					}
					else if(strAttName.equals("index"))
					{
						Debug.debug("Indexing layers currently not supported... Assumings written order.");
					}
					else
					{
						System.err.println("Unknown layer attribute: " + strAttName);
					}
				}
			}
			else if(strName.equals("neuron"))
			{
				String strNeuronName = new String();
				double dThreshold = 0.0;

				for(int i = 0; i < oAtts.getLength(); i++)
				{
					Node oAttribute = oAtts.item(i);

					String strAttName = oAttribute.getNodeName();
					String strAttValue = oAttribute.getNodeValue();

					if(strAttName.equals("index"))
					{
						//Debug.debug("Setting neuron name to " + strAttValue);
						strNeuronName = new String(strAttValue);
					}
					else if(strAttName.equals("thresh"))
					{
						try
						{
							dThreshold = Double.valueOf(strAttValue.trim()).doubleValue();
							//Debug.debug("Setting threshold to " + dThreshold + ".");
						}
						catch(NumberFormatException nfe)
						{
							// TODO: throw an exception maybe?
							System.err.println("NumberFormatException: " + nfe.getMessage());
							nfe.printStackTrace(System.err);
						}
					}
					else
					{
						System.err.println("Unknown layer attribute: " + strAttName);
					}
				}

				//Debug.debug("Making new neuron " + strNeuronName + " of type " + iType);

				Neuron oTmpNeuron = new Neuron(strNeuronName, this.iNeuronType);
				oTmpNeuron.dThreshold = dThreshold;
				this.oCurrentLayer.add(oTmpNeuron);
			}
		}

		// Recurse for children if any
		for
		(
			Node oChild = poNode.getFirstChild();
			oChild != null;
			oChild = oChild.getNextSibling()
		)
		{
			buildNetwork(oChild);
		}
	}

	/**
	 * DOM tree traversal -- create input and output links.
	 * @param poNode Node to create links to and from
	 * @throws ClassificationException if net's configuration is out order
	 */
	private final void createLinks(Node poNode)
	throws ClassificationException
	{
		int iType = poNode.getNodeType();

		String strName;

		if(iType == Node.ELEMENT_NODE)
		{
			strName = poNode.getNodeName();

			NamedNodeMap oAtts = poNode.getAttributes();

			if(strName.equals("layer"))
			{
				for(int i = 0; i < oAtts.getLength(); i++)
				{
					Node oAttribute = oAtts.item(i);

					String strAttName = oAttribute.getNodeName();
					String strAttValue = oAttribute.getNodeValue();

					if(strAttName.equals("type"))
					{
						if(strAttValue.equals("input"))
						{
							this.oCurrentLayer = this.oInputs;
							this.iCurrenLayer = 0;
						}
						else if(strAttValue.equals("output"))
						{
							this.oCurrentLayer = this.oOutputs;
							this.iCurrenLayer = this.oLayers.size() - 1;
						}
						else
						{
							this.iCurrenLayer = ++this.iCurrLayerBuf;
							this.oCurrentLayer = (Layer)this.oLayers.get(this.iCurrenLayer);
						}

						//Debug.debug("Moving to layer " + currLayer + " [currLayerBuf is " + currLayerBuf + "]");
					}
				}
			}

			else if(strName.equals("neuron"))
			{
				String strIndex = new String();

				for(int i = 0; i < oAtts.getLength(); i++)
				{
					Node oAttribute = oAtts.item(i);

					String strAttName = oAttribute.getNodeName();
					String strAttValue = oAttribute.getNodeValue();

					if(strAttName.equals("index"))
					{
						strIndex = new String(strAttValue);
					}
				}

				this.oCurrNeuron = this.oCurrentLayer.getNeuron(strIndex);
			}

			else if(strName.equals("input"))
			{
				String strIndex = null;
				double dWeight = -1.0;

				for(int i = 0; i < oAtts.getLength(); i++)
				{
					Node oAttribute = oAtts.item(i);

					String strAttName = oAttribute.getNodeName();
					String strAttValue = oAttribute.getNodeValue();

					if(strAttName.equals("ref"))
					{
						strIndex = new String(strAttValue);
					}
					else if(strAttName.equals("weight"))
					{
						try
						{
							dWeight = Double.valueOf(strAttValue.trim()).doubleValue();
						}
						catch(NumberFormatException nfe)
						{
							// TODO: should classification exception be thrown here??
							System.err.println("NumberFormatException: " + nfe.getMessage());
							nfe.printStackTrace(System.err);
						}
					}
				}

				//if(dWeight < 0.0) {
				//    throw new ClassificationException("Bad \'weight\' defined for neuron " + this.oCurrNeuron.name + " in layer " + this.oCurrentLayer);
				//}

				if(strIndex == null || strIndex.equals(""))
				{
					throw new ClassificationException
					(
						"No 'ref' value assigned for neuron " +
						this.oCurrNeuron.strName +
						" in layer " + this.iCurrenLayer
					);
				}

				//Debug.debug("Adding input " + strIndex + " with weight " + dWeight);

				if(this.iCurrenLayer > 0)
				{
					Neuron oNeuronToAdd = ((Layer)this.oLayers.get(this.iCurrenLayer - 1)).getNeuron(strIndex);

					if(oNeuronToAdd == null)
					{
						throw new ClassificationException
						(
							"Cannot find neuron " + strIndex
							+ " in layer " + (this.iCurrenLayer - 1)
						);
					}

					this.oCurrNeuron.addInput(oNeuronToAdd, dWeight);
				}
				else
				{
					throw new ClassificationException("Input element not allowed in input layer");
				}
			}

			else if(strName.equals("output"))
			{
				String strIndex = null;

				for(int i = 0; i < oAtts.getLength(); i++)
				{
					Node oAttribute = oAtts.item(i);

					String strAttName = oAttribute.getNodeName();
					String strAttValue = oAttribute.getNodeValue();

					if(strAttName.equals("ref"))
					{
						strIndex = new String(strAttValue);
					}
				}

				if(strIndex == null || strIndex.equals(""))
				{
					throw new ClassificationException
					(
						"No 'ref' value assigned for neuron " + this.oCurrNeuron.strName +
						" in layer " + this.iCurrenLayer
					);
				}

				//Debug.debug("Adding output " + strIndex);

				if(this.iCurrenLayer >= 0)
				{
					Neuron oNeuronToAdd = ((Layer)this.oLayers.get(this.iCurrenLayer + 1)).getNeuron(strIndex);

					if(oNeuronToAdd == null)
					{
						throw new ClassificationException
						(
							"Cannot find neuron " + strIndex
							+ " in layer " + (this.iCurrenLayer + 1)
						);
					}

					this.oCurrNeuron.addOutput(oNeuronToAdd);
				}
			}
		}

		// Recurse for children if any
		for
		(
			Node oChild = poNode.getFirstChild();
			oChild != null;
			oChild = oChild.getNextSibling()
		)
		{
			createLinks(oChild);
		}
    }

    //----------- Methods for Running the NNet -----------------

	/**
	 * Sets inputs.
	 * @param padInputs double array of input features
	 * @throws ClassificationException if the input array's length isn't
	 * equal to the size of the input layer
	 */
	public final void setInputs(final double[] padInputs)
	throws ClassificationException
	{
		if(padInputs.length != this.oInputs.size())
		{
			throw new ClassificationException
			(
				"Input array size not consistent with input layer."
			);
		}

		for(int i = 0; i < padInputs.length; i++)
		{
			this.oInputs.get(i).dResult = padInputs[i];
		}
	}

	/**
	 * Gets outputs of a neural network run.
	 * @return array of doubles read off the output layer's neurons
	 */
	public double[] getOutputResults()
	{
		double[] adRet = new double[this.oOutputs.size()];

		for(int i = 0; i < this.oOutputs.size(); i++)
		{
			adRet[i] = this.oOutputs.get(i).dResult;
		}

		return adRet;
	}

    //----------- Methods for Outputting the NNet -----------------

	/**
	 * Indents the output according to the requested tabulation
	 * for pretty indentation. TODO: move elsewhere to some
	 * utility module.
	 * @param poWriter Writer object to write tabs to.
	 * @param piTabsNum number of tabs
	 * @throws IOException if there is an error writing out the tabs
	 */
	public static final void indent(BufferedWriter poWriter, final int piTabsNum)
	throws IOException
	{
		for(int i = 0; i < piTabsNum; i++)
		{
			poWriter.write("\t");
		}
	}

	/**
	 * Dumps Neural Network as XML file.
	 * @param pstrFilename XML file name to write to
	 * @throws StorageException in case of an I/O error
	 */
	public final void dumpXML(final String pstrFilename)
	throws StorageException
	{
		try
		{
			BufferedWriter oWriter = new BufferedWriter(new FileWriter(pstrFilename));

			oWriter.write("<?xml version=\"1.0\"?>");
			oWriter.newLine();
			oWriter.write("<net>");
			oWriter.newLine();

			for(int i = 0; i < this.oLayers.size(); i++)
			{
				Layer oTmpLayer = (Layer)this.oLayers.get(i);

				indent(oWriter, 1);
				oWriter.write("<layer type=\"");

				if(i == 0)
				{
					oWriter.write("input");
				}
				else if(i == this.oLayers.size() - 1)
				{
					oWriter.write("output");
				}
				else
				{
					oWriter.write("hidden");
				}

				oWriter.write(new StringBuffer("\" index=\"").append(i).append("\">").toString());
				oWriter.newLine();

				for(int j = 0; j < oTmpLayer.size(); j++)
				{
					oTmpLayer.get(j).printXML(oWriter, 2);
				}

				indent(oWriter, 1);
				oWriter.write("</layer>");
				oWriter.newLine();
			}

			oWriter.write("</net>");
			oWriter.newLine();

			oWriter.close();
		}
        catch(Exception e)
        {
            throw new StorageException(e);
        }
	}

	/**
	 * Generates a virgin net at random.
	 * @param piNumOfInputs number of input Neurons in the input layer
	 * @param paiHiddenLayers arrays of numbers of Neurons in the hidden layers
	 * @param piNumOfOutputs number of output Neurons in the output layer
	 * @since 0.2.0, Serguei
	 * @throws ClassificationException if the hidden layers array has nothing or is null
	 */
	public final void generate(int piNumOfInputs, int[] paiHiddenLayers, int piNumOfOutputs)
	throws ClassificationException
	{
		if(paiHiddenLayers == null || paiHiddenLayers.length == 0)
		{
			throw new ClassificationException
			(
				"Number of hidden layers may not be null or of 0 length."
			);
		}

		for(int i = 1; i <= 1 + paiHiddenLayers.length + 1; i++)
		{
			// Add input layer
			if(i == 1)
			{
  				for(int j = 1; j <= piNumOfInputs; j++)
  				{
					Neuron oFreshAndJuicyNeuron = new Neuron("" + j, Neuron.INPUT);
					oFreshAndJuicyNeuron.dThreshold = 1.0;
					this.oInputs.add(oFreshAndJuicyNeuron);
				}

				this.oLayers.add(this.oInputs);

				continue;
			}

			// Add output layer
			if(i == 1 + paiHiddenLayers.length + 1)
			{
  				for(int j = 1; j <= piNumOfOutputs; j++)
  				{
					Neuron oFreshAndJuicyNeuron = new Neuron("" + j, Neuron.OUTPUT);
					oFreshAndJuicyNeuron.dThreshold = 1.0;
					this.oOutputs.add(oFreshAndJuicyNeuron);
				}

  				this.oLayers.add(this.oOutputs);

				continue;
			}

			Layer oHiddenLayer = new Layer();

			// Add hidden layers
			for(int j = 1; j <= paiHiddenLayers[i - 2]; j++)
			{
				Neuron oFreshAndJuicyNeuron = new Neuron("" + j, Neuron.HIDDEN);
				oFreshAndJuicyNeuron.dThreshold = 1.0;
				oHiddenLayer.add(oFreshAndJuicyNeuron);
			}

			this.oLayers.add(oHiddenLayer);
		}

		// Fix inputs / outputs
		Debug.debug("Setting the inputs and outputs for each Neuron...");

		for(int iCurrentLayer = 0; iCurrentLayer < this.oLayers.size() - 1; iCurrentLayer++)
		{
			Layer oTmpLayer = (Layer)this.oLayers.get(iCurrentLayer);

			for(int n = 0; n < oTmpLayer.size(); n++)
			{
				Neuron oCurrentNeuron = oTmpLayer.get(n);

				Layer oNextLayer = (Layer)this.oLayers.get(iCurrentLayer + 1);

				for(int k = 0; k < oNextLayer.size(); k++)
				{
					Neuron oNextLayerNeuron = oNextLayer.get(k);
					oCurrentNeuron.addOutput(oNextLayerNeuron);
					oNextLayerNeuron.addInput(oCurrentNeuron, new Random().nextDouble() * 2.0 - 1.0);
				}
			}
		}
	}

    //----------- Method for Training the NNet -----------------

	/**
	 * Performs Actual training of the net.
	 * @param padInput the input feature vector
	 * @param piExpectedLength expected length of the output layer
	 * @param pdTrainConst training constant to use for neurons
	 * @throws ClassificationException if the training constant less than zero or sizes
	 * of the inputs do not match or there is a problem evaluating the network
	 */
	public final void train(final double[] padInput, int piExpectedLength, final double pdTrainConst)
	throws ClassificationException
	{
		if(pdTrainConst <= 0.0)
		{
			throw new ClassificationException
			(
				"NeuralNetwork.train(): Training constant must be > 0.0, supplied: " +
				pdTrainConst
			);
		}

		if(padInput.length != this.oInputs.size())
		{
			throw new ClassificationException
			(
				"NeuralNetwork.train(): Input array size (" + padInput.length +
				") not consistent with input layer (" + this.oInputs.size() + ")"
			);
		}

		/*
		 * Setup NNet with training data.
		 */

		// Must setup the input data...
		setInputs(padInput);

		//if(piExpectedLength/*.length*/ != this.oOutputs.size())
		//    throw new ClassificationException("Expected array size not consistent with output layer.");

		// Run on training data. TODO: Must fix...
		runNNet();

		for(int k = this.oOutputs.size() - 1; k >= 0; k--)
		{
			int iCurrExpectedLength = piExpectedLength % 2;
			piExpectedLength /= 2;

			this.oOutputs.get(k).train(iCurrExpectedLength, pdTrainConst, 1.0);
		}

		for(int i = this.oLayers.size() - 2; i >= 0; i--)
		{
			Layer oLayer = (Layer)this.oLayers.get(i);
			oLayer.train(pdTrainConst);
		}
	}

	/**
	 * Applies changes made to neurons on every net's layer.
	 */
	public final void commit()
	{
		for(int i = 0; i < this.oLayers.size(); i++)
		{
			Layer oLayer = (Layer)this.oLayers.get(i);
			oLayer.commit();
		}
	}

	/**
	 * Interprets net's binary output as an ID for the final classification result.
	 * @return ID, integer
	 */
	private final int interpretAsBinary()
	{
		int iID = 0;

		for(int i = 0; i < this.oOutputs.size(); i++)
		{
			// Binary displacement happens to not have any
			// effect in the first iteration :-P
			iID *= 2;

			// Add 1 if the resulting weight is more than 0.5
			if(this.oOutputs.get(i).dResult > 0.5)
			{
				iID += 1;
			}

			Debug.debug(this.oOutputs.get(i).dResult + ",");
		}

		Debug.debug("Interpreted binary result (ID) = " + iID);

		return iID;
	}

    /* From Storage Manager */

	/**
	 * Dumps Neural Net to an XML or serialized file.
	 * @throws StorageException
	 */
	public void dump()
	throws StorageException
	{
		try
		{
			switch(this.iCurrentDumpMode)
			{
				case DUMP_GZIP_BINARY:
				case DUMP_BINARY:
				{
					// No initialization was done for binary mode
					if(this.oInputs.size() == 0)
					{
						generate();
					}

					Vector oNeuralNetLayersData = new Vector(3);
					oNeuralNetLayersData.add(this.oInputs);
					oNeuralNetLayersData.add(this.oLayers);
					oNeuralNetLayersData.add(this.oOutputs);

					this.oObjectToSerialize = oNeuralNetLayersData;
				}
			}
		}
		catch(ClassificationException e)
		{
			e.printStackTrace(System.err);
			throw new StorageException(e);
		}

		switch(this.iCurrentDumpMode)
		{
			case DUMP_GZIP_BINARY:
				dumpGzipBinary();
				break;

			case DUMP_BINARY:
				dumpBinary();
				break;

			default:
				super.dump();
		}
		//dumpXML();
	}

	/**
	 * Restores Neural Net from an XML or serialized file.
	 * @throws StorageException
	 */
	public void restore()
	throws StorageException
	{
		switch(this.iCurrentDumpMode)
		{
			case DUMP_GZIP_BINARY:
				restoreGzipBinary();
				break;

			case DUMP_BINARY:
				restoreBinary();
				break;

			default:
				super.restore();
		}
		//restoreXML();
	}

	/**
	 * Overrides the default implementation of <code>dumpXML()</code>.
	 * Merely calls <code>dumpXML(String)</code>.
	 * @see marf.Storage.IStorageManager#dumpXML()
	 * @see #dumpXML(String)
	 * @since 0.3.0.6
	 */
	public void dumpXML()
	throws StorageException
	{
		dumpXML(getDefaultFilename());
	}

	/**
	 * Overrides the default implementation of <code>restoreXML()</code>.
	 * Merely calls <code>initialize()</code>.
	 * @see marf.Storage.IStorageManager#restoreXML()
	 * @see #initialize(String, boolean)
	 * @since 0.3.0.6
	 */
	public void restoreXML()
	throws StorageException
	{
		initialize(getDefaultFilename(), false);
	}

	/**
	 * @see marf.Storage.StorageManager#backSynchronizeObject()
	 * @since 0.3.0.6
	 */
	public void backSynchronizeObject()
	{
		Vector oLoadedCopy = (Vector)this.oObjectToSerialize;

		this.oInputs = (Layer)oLoadedCopy.firstElement();
		this.oLayers = (ArrayList)oLoadedCopy.elementAt(1);
		this.oOutputs = (Layer)oLoadedCopy.lastElement();
	}

	/**
	 * Generates typical filename for dump/restore.
	 * @return canonical filename for dump/restore based on the current dump mode.
	 * @since 0.3.0.6
	 */
	protected String getDefaultFilename()
	{
		return new StringBuffer()
			.append(getClass().getName()).append(".")
			.append(MARF.getPreprocessingMethod()).append(".")
			.append(MARF.getFeatureExtractionMethod()).append(".")
			.append(getDefaultExtension())
			.toString();
	}

	/**
	 * Retrieves the minimum-error classification result.
	 * @return Result object
	 * @since 0.3.0.2
	 */
	public Result getResult()
	{
		return this.oResultSet.getMinimumResult();
	}

	/**
	 * Error handler to report errors and warnings.
	 * TODO: iclement: this may need revision.
	 * @author Ian Clement
	 */
	private static class NeuralNetworkErrorHandler
	implements ErrorHandler
	{
		/**
		 * Error handler output goes here.
		 */
		private PrintWriter oOut;

		/**
		 * Constructs our error handlier with the given writer.
		 * @param poOut writer to write errors to
		 */
		NeuralNetworkErrorHandler(PrintWriter poOut)
		{
			this.oOut = poOut;
		}

		/**
		 * Returns a string describing parse exception details.
		 * @param poParseException exception to get info from
		 * @return string representation of the info
		 */
		private String getParseExceptionInfo(SAXParseException poParseException)
		{
			String strSystemId = poParseException.getSystemId();

			if(strSystemId == null)
			{
				strSystemId = "null";
			}

			String strErrInfo =
				"URI=" + strSystemId +
				" Line=" + poParseException.getLineNumber() +
				": " + poParseException.getMessage();

			return strErrInfo;
		}

		// The following methods are standard SAX ErrorHandler methods.
		// See SAX documentation for more info.

		/**
		 * Issues a SAX warning.
		 * @param poParseException the parse exception to warn about
		 * @throws SAXException
		 */
		public void warning(SAXParseException poParseException)
		throws SAXException
		{
			this.oOut.println
			(
				"WARNING: "
				+ getParseExceptionInfo(poParseException)
			);
		}

		/**
		 * Issues a SAX error.
		 * @param poParseException the source of the error information
		 * @throws SAXException the error based on the parse exception
		 */
		public void error(SAXParseException poParseException)
		throws SAXException
		{
			String strMessage = "ERROR: " + getParseExceptionInfo(poParseException);
			throw new SAXException(strMessage);
		}

		/**
		 * Issues a SAX fatal error.
		 * @param poParseException the source of the error information
		 * @throws SAXException the error based on the parse exception
		 */
		public void fatalError(SAXParseException poParseException)
		throws SAXException
		{
			String strMessage = "FATAL: " + getParseExceptionInfo(poParseException);
			throw new SAXException(strMessage);
		}
	}

	/**
	 * Retrieves class' revision.
	 * @return revision string
	 * @since 0.3.0.2
	 */
	public static String getMARFSourceCodeRevision()
	{
		return "$Revision: 1.58 $";
	}
}

// EOF
Classification.java
package marf.Classification;

import java.util.Vector;

import marf.MARF;
import marf.FeatureExtraction.IFeatureExtraction;
import marf.Storage.ResultSet;
import marf.Storage.StorageException;
import marf.Storage.StorageManager;
import marf.Storage.TrainingSet;


/**
 * <p>Abstract Classification Module.
 * A generic implementation of the <code>IClassification</code> interface.
 * The derivatives must inherit from this class, and if they cannot,
 * they should implement <code>IClassification</code> themselves.
 * </p>
 *
 * $Id: Classification.java,v 1.46 2006/09/03 18:19:22 mokhov Exp $
 *
 * @author Serguei Mokhov
 * @version $Revision: 1.46 $
 * @since 0.0.1
 */
public abstract class Classification
extends StorageManager
implements IClassification
{
	/* Data Members */

	/**
	 * Reference to the enclosed FeatureExtraction object.
	 */
	protected IFeatureExtraction oFeatureExtraction = null;

	/**
	 * TrainingSet Container.
	 */
	protected TrainingSet oTrainingSet = null;

	/**
	 * Local reference to the array of features, either obtained
	 * from the feature extraction module or passed directly to
	 * train() or classify.
	 * Used in prevention of NullPointerException, bug #1539695.
	 * @since 0.3.0.6
	 * @see #train(double[])
	 * @see IClassification#classify(double[])
	 */
	protected double[] adFeatureVector = null;

	/**
	 * Classification result set. May contain
	 * one or more results (in case of similarity).
	 *
	 * @since 0.3.0.2
	 */
	protected ResultSet oResultSet = new ResultSet();

	/**
	 * For serialization versioning.
	 * When adding new members or make other structural
	 * changes regenerate this number with the
	 * <code>serialver</code> tool that comes with JDK.
	 * @since 0.3.0.5
	 */
	private static final long serialVersionUID = 7933249658173204609L;

	/* Constructors */

	/**
	 * Generic Classification Constructor.
	 * @param poFeatureExtraction FeatureExtraction module reference
	 */
	protected Classification(IFeatureExtraction poFeatureExtraction)
	{
		// TODO: null validation?
		this.oFeatureExtraction = poFeatureExtraction;

		// See if there is a request for dump format
		if(MARF.getModuleParams() != null)
		{
			Vector oParams = MARF.getModuleParams().getClassificationParams();

			// TODO: Must be validated of what's coming in
			if(oParams != null && oParams.size() > 0)
			{
				this.iCurrentDumpMode = ((Integer)oParams.elementAt(0)).intValue();
			}
		}
	}

	/* Classification API */

	/**
	 * Generic training routine for building/updating
	 * mean vectors in the training set. Assumes presence
	 * of a non-null feature extraction module for pipelining.
	 * Can be overridden, and if the overriding classifier is using
	 * <code>TrainingSet</code>, it should call <code>super.train();</code>
	 *
	 * @return <code>true</code> if training was successful
	 * (i.e. mean vector was updated); <code>false</code> otherwise
	 * @throws ClassificationException if there was a problem while training
	 * @see TrainingSet
	 */
	public boolean train()
	throws ClassificationException
	{
		return train(this.oFeatureExtraction.getFeaturesArray());
	}

	/**
	 * Generic training routine for building/updating
	 * mean vectors in the training set.
	 * Can be overridden, and if the overriding classifier is using
	 * <code>TrainingSet</code>, it should call <code>super.train();</code>
	 *
	 * @param padFeatureVector feature vector to train on
	 * @return <code>true</code> if training was successful
	 * (i.e. mean vector was updated); <code>false</code> otherwise
	 * @throws ClassificationException if there was a problem while training
	 * @see TrainingSet
	 * @since 0.3.0.6
	 */
	public boolean train(double[] padFeatureVector)
	throws ClassificationException
	{
		// For exception handling
		String strPhase = "[start]";

		// Bug #1539695
		this.adFeatureVector = padFeatureVector;

		/*
		 * It is important to use saveTrainingSet() and loadTrainingSet()
		 * throughout this method, as the dump() and restore() may easily
		 * (and likely) to be overridden by the derivatives.
		 */
		try
		{
			if(this.oTrainingSet != null)
			{
				// Wrong global cluster loaded, reload the correct one.
				if
				(
					(this.oTrainingSet.getPreprocessingMethod() != MARF.getPreprocessingMethod())
					||
					(this.oTrainingSet.getFeatureExtractionMethod() != MARF.getFeatureExtractionMethod())
				)
				{
					strPhase = "[dumping previous cluster]";

					saveTrainingSet();
					this.oTrainingSet = null;
				}
			}

			strPhase = "[restoring training set]";
			loadTrainingSet();

			// Add the new feature vector.
			strPhase = "[adding feature vector]";

			boolean bVectorAdded = this.oTrainingSet.addFeatureVector
			(
				this.adFeatureVector,
				MARF.getSampleFile(),
				MARF.getCurrentSubject(),
				MARF.getPreprocessingMethod(),
				MARF.getFeatureExtractionMethod()
			);

			// No point of doing I/O if we didn't add anything.
			if(bVectorAdded == true)
			{
				strPhase = "[dumping updated training set]";
				saveTrainingSet();
			}

			return true;
		}
		catch(NullPointerException e)
		{
			e.printStackTrace(System.err);

			throw new ClassificationException
			(
				new StringBuffer()
					.append("NullPointerException in Classification.train(): oTrainingSet = ")
					.append(this.oTrainingSet)
					.append(", oFeatureExtraction = ").append(this.oFeatureExtraction)
					.append(", FeaturesArray = ").append(this.adFeatureVector)
					.append(", phase: ").append(strPhase)
					.toString()
			);
		}
		catch(Exception e)
		{
			e.printStackTrace(System.err);
			throw new ClassificationException("Phase: " + strPhase, e);
		}
	}

	/**
	 * Generic classification routine that assumes a presence of
	 * a valid non-null feature extraction module for pipeline operation.
	 * @see marf.Classification.IClassification#classify()
	 * @since 0.3.0.6
	 */
	public boolean classify()
	throws ClassificationException
	{
		return classify(this.oFeatureExtraction.getFeaturesArray());
	}

	/* From Storage Manager */

	/**
	 * Generic implementation of dump() to dump the TrainingSet.
	 * @since 0.2.0
	 * @throws StorageException if there's a problem saving training set to disk
	 */
	public void dump()
	throws StorageException
	{
		switch(this.iCurrentDumpMode)
		{
			case DUMP_GZIP_BINARY:
			case DUMP_BINARY:
				saveTrainingSet();
				break;

			default:
				super.dump();
		}
	}

	/**
	 * Generic implementation of restore() for TrainingSet.
	 * @since 0.2.0
	 * @throws StorageException if there is a problem loading the training set from disk
	 */
	public void restore()
	throws StorageException
	{
		switch(this.iCurrentDumpMode)
		{
			case DUMP_GZIP_BINARY:
			case DUMP_BINARY:
				loadTrainingSet();
				break;

			default:
				super.restore();
		}
	}

	/**
	 * Saves TrainingSet to a file. Called by <code>dump()</code>.
	 * @since 0.2.0
	 * @throws StorageException if there's a problem saving training set to disk
	 * @see #dump()
	 * @see TrainingSet
	 */
	private final void saveTrainingSet()
	throws StorageException
	{
		try
		{
			// Dump stuff is there's anything to dump
			if(this.oTrainingSet != null)
			{
				this.oTrainingSet.setDumpMode(this.iCurrentDumpMode);
				this.oTrainingSet.setFilename(getTrainingSetFilename());
				this.oTrainingSet.dump();
			}

			// TODO: if TrainingSet is null
			else
			{
				// [SM, 2003-05-02] Should here be something? Like a debug() call or
				// more severe things?
				System.err.println
				(
					"WARNING: Classification.saveTrainingSet() -- TrainingSet is null.\n" +
					"         No TrainingSet is saved."
				);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace(System.err);
			throw new StorageException(e);
		}
	}

	/**
	 * Loads TrainingSet from a file. Called by <code>restore()</code>.
	 * @since 0.2.0
	 * @throws StorageException if there is a problem loading the training set from disk
	 * @see #restore()
	 */
	private final void loadTrainingSet()
	throws StorageException
	{
		try
		{
			if(this.oTrainingSet == null)
			{
				this.oTrainingSet = new TrainingSet();
				this.oTrainingSet.setDumpMode(this.iCurrentDumpMode);
				this.oTrainingSet.setFilename(getTrainingSetFilename());
				this.oTrainingSet.restore();
			}

			//TODO: if TrainingSet is not null
			else
			{
				// [SM, 2003-05-02] Should here be something? Like a debug() call or
				// more severe things?
				System.err.println
				(
					"WARNING: Classification.loadTrainingSet() -- TrainingSet is not null.\n" +
					"         No TrainingSet is loaded."
				);
			}
		}
		catch(Exception e)
		{
			e.printStackTrace(System.err);
			throw new StorageException(e);
		}
	}

	/**
	 * Retrieves the enclosed result set.
	 * @return the enclosed ResultSet object
	 * @since 0.3.0.2
	 */
	public ResultSet getResultSet()
	{
		return this.oResultSet;
	}

	/**
	 * Constructs a global cluster file name for the TrainingSet.
	 *
	 * <p>Filename is constructed using fully-qualified class of
	 * either TrainingSet or a classifier name with global
	 * clustering info such as preprocessing and feature
	 * extraction methods, so that ony that cluster can be reloaded
	 * after.</p>
	 *
	 * May be overridden by the drivatives when necessary.
	 *
	 * @return String, filename
	 * @since 0.2.0
	 */
	protected String getTrainingSetFilename()
	{
		// Prevents NullPointerException, bug #1539695
		int iFeaturesCount = this.oFeatureExtraction == null
			? (this.adFeatureVector == null ? 0 : this.adFeatureVector.length)
			: this.oFeatureExtraction.getFeaturesArray().length;

		// For comparison, distinguish samples with or without
		// noise and silence removed
		int iNoiseRemoved = 0;
		int iSilenceRemoved = 0;

		if(MARF.getModuleParams() != null)
		{
			Vector oPreprocessingParams = MARF.getModuleParams().getPreprocessingParams();

			if(oPreprocessingParams != null)
			{
				switch(oPreprocessingParams.size())
				{
					case 0:
						break;

					case 1:
					{
						if(oPreprocessingParams.firstElement() instanceof Boolean)
						{
							iNoiseRemoved = ((Boolean)oPreprocessingParams.firstElement()).booleanValue() == true ? 1 : 0;
						}

						break;
					}

					default:
					{
						if(oPreprocessingParams.firstElement() instanceof Boolean)
						{
							iNoiseRemoved = ((Boolean)oPreprocessingParams.firstElement()).booleanValue() == true ? 1 : 0;
						}

						if(oPreprocessingParams.elementAt(1) instanceof Boolean)
						{
							iSilenceRemoved = ((Boolean)oPreprocessingParams.elementAt(1)).booleanValue() == true ? 1 : 0;
						}

						break;
					}
				}
			}
		}

		return new StringBuffer()
			// Fully-qualified class name
			.append(this.oTrainingSet.getClass().getName()).append(".")

			// Distinguish between samples with removed noise or silence
			// or both or none
			.append(iNoiseRemoved).append(".")
			.append(iSilenceRemoved).append(".")

			// Global cluster: <PR>.<FE>.<FVS>
			// For the same FE method we may have different feature vector sizes
			.append(MARF.getPreprocessingMethod()).append(".")
			.append(MARF.getFeatureExtractionMethod()).append(".")
			.append(iFeaturesCount).append(".")

			// Extension depending on the dump type
			.append(getDefaultExtension())
			.toString();
	}

	/**
	 * Retrieves the features source.
	 * @return returns the FeatureExtraction reference
	 * @since 0.3.0.4
	 */
	public IFeatureExtraction getFeatureExtraction()
	{
		return this.oFeatureExtraction;
	}

	/**
	 * Allows setting the features surce.
	 * @param poFeatureExtraction the FeatureExtraction object to set
	 * @since 0.3.0.4
	 */
	public void setFeatureExtraction(IFeatureExtraction poFeatureExtraction)
	{
		this.oFeatureExtraction = poFeatureExtraction;
	}

	/**
	 * Implementes Cloneable interface for the Classification object.
	 * The contained FeatureExtraction isn't cloned at this point,
	 * and is just assigned to the clone.
	 * @see java.lang.Object#clone()
	 * @since 0.3.0.5
	 */
	public Object clone()
	{
		Classification oClone = (Classification)super.clone();
		oClone.oResultSet = (ResultSet)this.oResultSet.clone();
		oClone.oTrainingSet = (TrainingSet)this.oTrainingSet.clone();
		oClone.oFeatureExtraction = this.oFeatureExtraction;
		return oClone;
	}

	/**
	 * Retrieves class' revision.
	 * @return revision string
	 * @since 0.3.0.2
	 */
	public static String getMARFSourceCodeRevision()
	{
		return "$Revision: 1.46 $";
	}
}

// EOF
SpeakersIdentDb.java
package marf;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.DecimalFormat;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import marf.Storage.Database;
import marf.Storage.StorageException;
import marf.util.Arrays;
import marf.util.Debug;


/**
 * <p>Class SpeakersIdentDb manages database of speakers on the application level.</p>
 * <p>XXX: Move stats collection over to MARF.</p>
 *
 * <p>$Id: SpeakersIdentDb.java,v 1.24 2006/01/08 14:47:43 mokhov Exp $</p>
 *
 * @author Serguei Mokhov
 * @version $Revision: 1.24 $
 * @since 0.0.1
 */
public class SpeakersIdentDb
extends Database
{
	/**
	 * Hashes "config string" -> Vector(FirstMatchPoint(XSuccesses, YFailures),
	 * SecondMatchPoint(XSuccesses, YFailures)).
	 */
	private Hashtable oStatsPerConfig = null;

	/**
	 * Array of sorted stats refs.
	 */
	private Vector[] aoSortedStatsRefs = null;

	/**
	 * A vector of vectors of speakers info pre-loded on <code>connect()</code>.
	 * @see #connect()
	 */
	private Hashtable oDB = null;

	/**
	 * "Database connection".
	 */
	private BufferedReader oConnection = null;

	/**
	 * For serialization versioning.
	 * @since 0.3.0.5
	 */
	private static final long serialVersionUID = -7185805363856188810L;

	/**
	 * Constructor.
	 * @param pstrFileName filename of a CSV file with IDs and names of speakers
	 */
	public SpeakersIdentDb(final String pstrFileName)
	{
		this.strFilename = pstrFileName;
		this.oDB = new Hashtable();
		this.oStatsPerConfig = new Hashtable();
	}

	/**
	 * Retrieves Speaker's ID by a sample filename.
	 * @param pstrFileName Name of a .wav file for which ID must be returned
	 * @param pbTraining indicates whether the filename is a training (<code>true</code>) sample or testing (<code>false</code>)
	 * @return int ID
	 * @throws StorageException in case of an error in any I/O operation
	 */
	public final int getIDByFilename(final String pstrFileName, final boolean pbTraining)
	throws StorageException
	{
		String strFilenameToLookup;

		// Extract actual file name without preceeding path (if any)
		if(pstrFileName.lastIndexOf('/') >= 0)
		{
			strFilenameToLookup = pstrFileName.substring(pstrFileName.lastIndexOf('/') + 1, pstrFileName.length());
		}
		else if(pstrFileName.lastIndexOf('\\') >= 0)
		{
			strFilenameToLookup = pstrFileName.substring(pstrFileName.lastIndexOf('\\') + 1, pstrFileName.length());
		}
		else
		{
			strFilenameToLookup = pstrFileName;
		}

		Enumeration oIDs = this.oDB.keys();

		// Traverse all the info vectors looking for sample filename
		while(oIDs.hasMoreElements())
		{
			Integer oID = (Integer)oIDs.nextElement();

			Debug.debug("File: " + pstrFileName + ", id = " + oID.intValue());

			Vector oSpeakerInfo = (Vector)this.oDB.get(oID);
			Vector oFilenames;

			if(pbTraining == true)
			{
				oFilenames = (Vector)oSpeakerInfo.elementAt(1);
			}
			else
			{
				oFilenames = (Vector)oSpeakerInfo.elementAt(2);
			}

			// Start from 1 because 0 is speaker's name
			for(int i = 0; i < oFilenames.size(); i++)
			{
				String strCurrentFilename = (String)oFilenames.elementAt(i);

				if(strCurrentFilename.equals(strFilenameToLookup))
				{
					return oID.intValue();
				}
			}
		}

		return -1;
	}

	/**
	 * Retrieves speaker's name by their ID.
	 * @param piID ID of a person in the DB to return a name for
	 * @return name string
	 * @throws StorageException
	 */
	public final String getName(final int piID)
	throws StorageException
	{
		//Debug.debug("getName() - ID = " + piID + ", db size: " + oDB.size());
		String strName;

		Vector oDBEntry = (Vector)this.oDB.get(new Integer(piID));

		if(oDBEntry == null)
		{
			strName = "Unknown Speaker (" + piID + ")";
		}
		else
		{
			strName = (String)oDBEntry.elementAt(0);
		}

		return strName;
	}
	public final boolean isValidResult(final int piID)
	throws StorageException
	{


		Vector oDBEntry = (Vector)this.oDB.get(new Integer(piID));

		if(oDBEntry == null)
		{
			return false;
		}


		return true;
	}
	/**
	 * Connects to the "database" of speakers (opens the text file :-)).
	 * @throws StorageException in case of any I/O error
	 */
	public void connect()
	throws StorageException
	{
		// That's where we should establish file linkage and keep it until closed
		try
		{
			this.oConnection = new BufferedReader(new FileReader(this.strFilename));
			this.bConnected = true;
		}
		catch(IOException e)
		{
			throw new StorageException
			(
				"Error opening speaker DB: \"" + this.strFilename + "\": " +
				e.getMessage() + "."
			);
		}
	}

	/**
	 * Retrieves speaker's data from the text file and populates
	 * internal data structures. Uses StringTokenizer to parse
	 * data read from the file.
	 * @throws StorageException in case of any I/O error
	 */
	public void query()
	throws StorageException
	{
		// That's where we should load db results into internal data structure

		String strLine;
		int iID = -1;

		try
		{
			strLine = this.oConnection.readLine();

			while(strLine != null)
			{
				StringTokenizer oTokenizer = new StringTokenizer(strLine, ",");
				Vector oSpeakerInfo = new Vector();

				// get ID
				if(oTokenizer.hasMoreTokens())
				{
					iID = Integer.parseInt(oTokenizer.nextToken());
				}

				// speaker's name
				if(oTokenizer.hasMoreTokens())
				{
					strLine = oTokenizer.nextToken();
					oSpeakerInfo.add(strLine);
				}

				// training file names
				Vector oTrainingFilenames = new Vector();

				if(oTokenizer.hasMoreTokens())
				{
					StringTokenizer oSTK = new StringTokenizer(oTokenizer.nextToken(), "|");

					while(oSTK.hasMoreTokens())
					{
						strLine = oSTK.nextToken();
						oTrainingFilenames.add(strLine);
					}
				}

				oSpeakerInfo.add(oTrainingFilenames);

				// testing file names
				Vector oTestingFilenames = new Vector();

				if(oTokenizer.hasMoreTokens())
				{
					StringTokenizer oSTK = new StringTokenizer(oTokenizer.nextToken(), "|");

					while(oSTK.hasMoreTokens())
					{
						strLine = oSTK.nextToken();
						oTestingFilenames.add(strLine);
					}
				}

				oSpeakerInfo.add(oTestingFilenames);

				Debug.debug("Putting ID=" + iID + " along with info vector of size " + oSpeakerInfo.size());

				this.oDB.put(new Integer(iID), oSpeakerInfo);

				strLine = this.oConnection.readLine();
			}
		}
		catch(IOException e)
		{
			throw new StorageException
			(
				"Error reading from speaker DB: \"" + this.strFilename +
				"\": " + e.getMessage() + "."
			);
		}
	}

	/**
	 * Closes (file) database connection.
	 * @throws StorageException if not connected or fails to close inner reader
	 */
	public void close()
	throws StorageException
	{
		// Close file
		if(this.bConnected == false)
		{
			throw new StorageException("SpeakersIdentDb.close() - not connected");
		}

		try
		{
			this.oConnection.close();
			this.bConnected = false;
		}
		catch(IOException e)
		{
			throw new StorageException(e.getMessage());
		}
	}

	/**
	 * Adds one more classification statics entry.
	 * @param pstrConfig String representation of the configuration the stats are for
	 * @param pbSuccess <code>true</code> if classification was successful; <code>false</code> otherwise
	 */
	public final void addStats(final String pstrConfig, final boolean pbSuccess)
	{
		addStats(pstrConfig, pbSuccess, false);
	}

	/**
	 * Adds one more classification statics entry and accounts for the second best choice.
	 * @param pstrConfig String representation of the configuration the stats are for
	 * @param pbSuccess <code>true</code> if classification was successful; <code>false</code> otherwise
	 * @param pbSecondBest <code>true</code> if classification was successful; <code>false</code> otherwise
	 */
	public final void addStats(final String pstrConfig, final boolean pbSuccess, final boolean pbSecondBest)
	{
		Vector oMatches = (Vector)this.oStatsPerConfig.get(pstrConfig);
		Point oPoint = null;

		if(oMatches == null)
		{
			oMatches = new Vector(2);
			oMatches.add(new Point());
			oMatches.add(new Point());
			oMatches.add(pstrConfig);
		}
		else
		{
			if(pbSecondBest == false)
			{
				// First match
				oPoint = (Point)oMatches.elementAt(0);
			}
			else
			{
				// Second best match
				oPoint = (Point)oMatches.elementAt(1);
			}
		}

		int iSuccesses = 0; // # of successes
		int iFailures = 0; // # of failures

		if(oPoint == null) // Didn't exist yet; create new
		{
			if(pbSuccess == true)
			{
				iSuccesses = 1;
			}
			else
			{
				iFailures = 1;
			}

			oPoint = new Point(iSuccesses, iFailures);

			if(oPoint == null)
			{
				System.err.println("SpeakersIdentDb.addStats() - oPoint null! Out of memory?");
				System.exit(-1);
			}

			if(oMatches == null)
			{
				System.err.println("SpeakersIdentDb.addStats() - oMatches null! Out of memory?");
				System.exit(-1);
			}

			if(oMatches.size() == 0)
			{
				System.err.println("SpeakersIdentDb.addStats() - oMatches.size = 0");
				System.exit(-1);
			}

			if(pbSecondBest == false)
			{
				oMatches.setElementAt(oPoint, 0);
			}
			else
			{
				oMatches.setElementAt(oPoint, 1);
			}

			this.oStatsPerConfig.put(pstrConfig, oMatches);
		}

		else // There is an entry for this config; update
		{
			if(pbSuccess == true)
			{
				oPoint.x++;
			}
			else
			{
				oPoint.y++;
			}
		}
	}

	/**
	 * Dumps all collected statistics to STDOUT.
	 * @throws Exception
	 */
	public final void printStats()
	throws Exception
	{
		printStats(false);
	}

	/**
	 * Dumps collected statistics to STDOUT.
	 * @param pbBestOnly <code>true</code> - print out only the best score number; <code>false</code> - all stats
	 * @throws Exception
	 */
	public final void printStats(boolean pbBestOnly)
	throws Exception
	{
		if(this.oStatsPerConfig.size() == 0)
		{
			System.err.println("SpeakerIdentDb: no statistics available. Did you run the recognizer yet?");
			return;
		}

		// First row is for the identified results, 2nd is for 2nd best ones.
		String[][] astrResults = new String[2][this.oStatsPerConfig.size()];

		this.aoSortedStatsRefs = (Vector[])oStatsPerConfig.values().toArray(new Vector[0]);
		Arrays.sort(this.aoSortedStatsRefs, new StatsPercentComparator(StatsPercentComparator.DESCENDING));

		int iResultNum = 0;

		System.out.println("guess,run,config,good,bad,%");

		for(int i = 0; i < this.aoSortedStatsRefs.length; i++)
		{
			String strConfig = (String)(this.aoSortedStatsRefs[i]).elementAt(2);

			for(int j = 0; j < 2; j++)
			{
				Point oGoodBadPoint = (Point)(this.aoSortedStatsRefs[i]).elementAt(j);
				String strGuess = (j == 0) ? "1st" : "2nd";
				String strRun = (iResultNum + 1) + "";
				DecimalFormat oFormat = new DecimalFormat("#,##0.00;(#,##0.00)");
				double dRate = ((double)oGoodBadPoint.x / (double)(oGoodBadPoint.x + oGoodBadPoint.y)) * 100;

				if(pbBestOnly == true)
				{
					System.out.print(oFormat.format(dRate));
					return;
				}

				astrResults[j][iResultNum] =
					strGuess + "," +
					strRun + "," +
					strConfig + "," +
					oGoodBadPoint.x + "," + // Good
					oGoodBadPoint.y + "," + // Bad
					oFormat.format(dRate);
			}

			iResultNum++;
		}

		// Print all of the 1st match
		for(int i = 0; i < astrResults[0].length; i++)
		{
			System.out.println(astrResults[0][i]);
		}

		// Print all of the 2nd match
		for(int i = 0; i < astrResults[1].length; i++)
		{
			System.out.println(astrResults[1][i]);
		}
	}

	/**
	 * Resets in-memory and on-disk statistics.
	 * @throws StorageException
	 */
	public final void resetStats()
	throws StorageException
	{
		this.oStatsPerConfig.clear();
		dump();
	}

	/**
	 * Dumps statistic's Hashtable object as gzipped binary to disk.
	 * @throws StorageException
	 */
	public void dump()
	throws StorageException
	{
		try
		{
			FileOutputStream oFOS = new FileOutputStream(this.strFilename + ".stats");
			GZIPOutputStream oGZOS = new GZIPOutputStream(oFOS);
			ObjectOutputStream oOOS = new ObjectOutputStream(oGZOS);

			oOOS.writeObject(this.oStatsPerConfig);
			oOOS.flush();
			oOOS.close();
		}
		catch(Exception e)
		{
			throw new StorageException(e);
		}
	}

	public void cleanSerializeFile(){
		try {
			super.dump();
		} catch (StorageException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * Reloads statistic's Hashtable object from disk.
	 * If the file did not exist, it creates a new one.
	 * @throws StorageException
	 */
	public void restore()
	throws StorageException
	{
		try
		{
			FileInputStream oFIS = new FileInputStream(this.strFilename + ".stats");
			GZIPInputStream oGZIS = new GZIPInputStream(oFIS);
			ObjectInputStream oOIS = new ObjectInputStream(oGZIS);

			this.oStatsPerConfig = (Hashtable)oOIS.readObject();
			oOIS.close();
		}
		catch(FileNotFoundException e)
		{
			System.out.println
			(
				"NOTICE: File " + this.strFilename +
				".stats does not seem to exist. Creating a new one...."
			);

			resetStats();
		}
		catch(ClassNotFoundException e)
		{
			throw new StorageException
			(
				"SpeakerIdentDb.retore() - ClassNotFoundException: " +
				e.getMessage()
			);
		}
		catch(Exception e)
		{
			throw new StorageException(e);
		}
	}
}

/**
 * <p>Used in sorting by percentage of the stats entries
 * in either ascending or descending order.</p>
 *
 * <p>TODO: To be moved to Stats.</p>
 *
 * @author Serguei Mokhov
 * @version $Revision: 1.24 $
 * @since 0.0.1 of MARF
 */
class StatsPercentComparator
extends marf.util.SortComparator
{
	/**
	 * For serialization versioning.
	 * @since 0.3.0.5
	 */
	private static final long serialVersionUID = -7185805363856188810L;

	/**
	 * Mimics parent's constructor.
	 */
	public StatsPercentComparator()
	{
		super();
	}

	/**
	 * Mimics parent's constructor.
	 * @param piSortMode either DESCENDING or ASCENDING sort mode
	 */
	public StatsPercentComparator(final int piSortMode)
	{
		super(piSortMode);
	}

	/**
	 * Implementation of the Comparator interface for the stats objects.
	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
	 */
	public int compare(Object poStats1, Object poStats2)
	{
		Vector oStats1 = (Vector)poStats1;
		Vector oStats2 = (Vector)poStats2;

		Point oGoodBadPoint1 = (Point)(oStats1.elementAt(0));
		Point oGoodBadPoint2 = (Point)(oStats2.elementAt(0));

		double dRate1 = ((double)oGoodBadPoint1.x / (double)(oGoodBadPoint1.x + oGoodBadPoint1.y)) * 100;
		double dRate2 = ((double)oGoodBadPoint2.x / (double)(oGoodBadPoint2.x + oGoodBadPoint2.y)) * 100;

		switch(this.iSortMode)
		{
			case DESCENDING:
			{
				return (int)((dRate2 - dRate1) * 100);
			}

			case ASCENDING:
			default:
			{
				return (int)((dRate1 - dRate2) * 100);
			}
		}
	}

	public void cleanDB(){

	}
}

// EOF
MarfUtils.java
package marf;
import java.io.File;
import java.util.Date;

import marf.Storage.ModuleParams;
import marf.Storage.Result;
import marf.Storage.StorageException;
import marf.Storage.TrainingSet;
import marf.util.Debug;
import marf.util.MARFException;
import marf.util.OptionProcessor;


/**
 * <p>Indentfies a speaker independently of text, based on the MARF framework,
 * <a href="http://marf.sf.net">http://marf.sf.net</a>.
 * </p>
 *
 * <p>$Id: SpeakerIdentApp.java,v 1.56 2006/01/23 00:03:34 mokhov Exp $</p>
 *
 * @author Serguei Mokhov
 * @author Stephen Sinclair
 * @author Ian Clement
 * @author Dimitrios Nicolacopoulos
 * @author The MARF Research and Development Group
 *
 * @version 0.3.0, $Revision: 1.56 $
 * @since 0.0.1
 */
public class MarfUtils
{
	/*
	 * ----------------
	 * Apps. Versioning
	 * ----------------
	 */

	/**
	 * Current major version of the application.
	 */
	public static final int MAJOR_VERSION = 0;

	/**
	 * Current minor version of the application.
	 */
	public static final int MINOR_VERSION = 3;

	/**
	 * Current revision of the application.
	 */
	public static final int REVISION      = 0;


	/*
	 * ----------------------------------
	 * Major and Misc Options Enumeration
	 * ----------------------------------
	 */

	/**
	 * Numeric equivalent of the option <code>--train</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_TRAIN = 0;

	/**
	 * Numeric equivalent of the option <code>--ident</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_IDENT = 1;

	/**
	 * Numeric equivalent of the option <code>--stats</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_STATS = 2;

	/**
	 * Numeric equivalent of the option <code>--reset</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_RESET = 3;

	/**
	 * Numeric equivalent of the option <code>--version</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_VERSION = 4;

	/**
	 * Numeric equivalent of the option <code>--help</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_HELP_LONG = 5;

	/**
	 * Numeric equivalent of the option <code>-h</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_HELP_SHORT = 6;

	/**
	 * Numeric equivalent of the option <code>-debug</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_DEBUG = 7;

	/**
	 * Numeric equivalent of the option <code>-graph</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_GRAPH = 8;

	/**
	 * Numeric equivalent of the option <code>-spectrogram</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_SPECTROGRAM = 9;

	/**
	 * Numeric equivalent of the option <code><speaker ID></code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_EXPECTED_SPEAKER_ID = 10;

	/**
	 * Numeric equivalent of the option <code>--batch-ident</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_BATCH_IDENT = 11;

	/**
	 * Numeric equivalent of the option <code>--single-train</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_SINGLE_TRAIN = 12;

	/**
	 * Numeric equivalent of the option <code><sample-file-or-directory-name></code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_DIR_OR_FILE = 13;

	/**
	 * Numeric equivalent of the option <code>--best-score</code>.
	 * @since 0.3.0.5
	 */
	public static final int OPT_BEST_SCORE = 14;

	/*
	 * ---------------------
	 * State Data Structures
	 * ---------------------
	 */

	/**
	 * Instance of the database of speakers.
	 * @since 0.3.0.5
	 */
	protected static SpeakersIdentDb soDB = null;

	/**
	 * Intance of the option processing utility.
	 * @since 0.3.0.5
	 */
	protected static OptionProcessor soGetOpt = new OptionProcessor();

	/*
	 * -----------------
	 * Static State Init
	 * -----------------
	 */

	static
	{
		// Main options
		soGetOpt.addValidOption(OPT_TRAIN, "--train");
		soGetOpt.addValidOption(OPT_SINGLE_TRAIN, "--single-train");
		soGetOpt.addValidOption(OPT_IDENT, "--ident");
		soGetOpt.addValidOption(OPT_BATCH_IDENT, "--batch-ident");
		soGetOpt.addValidOption(OPT_STATS, "--stats");
		soGetOpt.addValidOption(OPT_BEST_SCORE, "--best-score");
		soGetOpt.addValidOption(OPT_RESET, "--reset");
		soGetOpt.addValidOption(OPT_VERSION, "--version");
		soGetOpt.addValidOption(OPT_HELP_LONG, "--help");
		soGetOpt.addValidOption(OPT_HELP_SHORT, "-h");
		soGetOpt.addValidOption(OPT_DIR_OR_FILE, "--dir");

		// Preprocessing
		soGetOpt.addValidOption(MARF.DUMMY, "-norm");
		soGetOpt.addValidOption(MARF.HIGH_FREQUENCY_BOOST_FFT_FILTER, "-boost");
		soGetOpt.addValidOption(MARF.HIGH_PASS_FFT_FILTER, "-high");
		soGetOpt.addValidOption(MARF.LOW_PASS_FFT_FILTER, "-low");
		soGetOpt.addValidOption(MARF.BANDPASS_FFT_FILTER, "-band");
		soGetOpt.addValidOption(MARF.HIGH_PASS_BOOST_FILTER, "-highpassboost");
		soGetOpt.addValidOption(MARF.RAW, "-raw");
		soGetOpt.addValidOption(MARF.ENDPOINT, "-endp");

		// Feature extraction
		soGetOpt.addValidOption(MARF.FFT, "-fft");
		soGetOpt.addValidOption(MARF.LPC, "-lpc");
		soGetOpt.addValidOption(MARF.RANDOM_FEATURE_EXTRACTION, "-randfe");
		soGetOpt.addValidOption(MARF.MIN_MAX_AMPLITUDES, "-minmax");
		soGetOpt.addValidOption(MARF.FEATURE_EXTRACTION_AGGREGATOR, "-aggr");

		// Classification
		soGetOpt.addValidOption(MARF.NEURAL_NETWORK, "-nn");
		soGetOpt.addValidOption(MARF.EUCLIDEAN_DISTANCE, "-eucl");
		soGetOpt.addValidOption(MARF.CHEBYSHEV_DISTANCE, "-cheb");
		soGetOpt.addValidOption(MARF.MINKOWSKI_DISTANCE, "-mink");
		soGetOpt.addValidOption(MARF.MAHALANOBIS_DISTANCE, "-mah");
		soGetOpt.addValidOption(MARF.RANDOM_CLASSIFICATION, "-randcl");


		// Misc
		soGetOpt.addValidOption(OPT_SPECTROGRAM, "-spectrogram");
		soGetOpt.addValidOption(OPT_DEBUG, "-debug");
		soGetOpt.addValidOption(OPT_GRAPH, "-graph");
	}
   public static void main(String[] args){

	   MarfUtils.initialize("speakers116.txt");
	   MarfUtils.training("D:\\music");

	   MarfUtils.recongnize("D:\\music\\audio_31.wav");



   }
   public static final void initialize(String trainingFileFolder){

		/*
		 * Load the speakers database
		 */
		try {
			soDB = new SpeakersIdentDb(trainingFileFolder);

			soDB.connect();
			soDB.query();


			setDefaultConfig();
		} catch (StorageException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MARFException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

   }

   public static final void training(String trainingPath){
		try
		{
			// Dir contents
			File[] aoFiles = new File(trainingPath).listFiles();

			Debug.debug("Files array: " + aoFiles);

			if(Debug.isDebugOn())
			{
				System.getProperties().list(System.err);
			}

			String strFileName = "";

			// XXX: this loop has to be in MARF
			for(int i = 0; i < aoFiles.length; i++)
			{
				strFileName = aoFiles[i].getPath();

				if(aoFiles[i].isFile() && strFileName.toLowerCase().endsWith(".wav"))
				{
					train(strFileName);
				}
			}
		}
		catch(NullPointerException e)
		{
			System.err.println("Folder \"" + soGetOpt.getOption(OPT_DIR_OR_FILE) + "\" not found.");
			e.printStackTrace(System.err);
			System.exit(-1);
		} catch (MARFException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try{
				   soDB.close();
				}catch(Exception e){
				   e.printStackTrace();
				}
			}

		System.out.println("Done training on folder" + trainingPath);


   }
   public static final boolean recongnize(String sourceFile){

	   try {
		 return ident(getConfigString(null), sourceFile, -1);
	} catch (MARFException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}finally{
		try{
		   //soDB.close();
		}catch(Exception e){
		   e.printStackTrace();
		}
	}
	return false;
   }

	/**
	 * Indetifies a speaker using MARF given configuration,
	 * wave filename, and possibly expected speaker ID.
	 *
	 * @param pstrConfig configuration string for stats
	 * @param pstrFilename name of the wave file with voice sample to identify
	 * @param piExpectedID expected speaker ID; if -1 then no stats is kept
	 *
	 * @throws MARFException in case of any error while processing is in MARF
	 * @since 0.3.0.5
	 */
	public static final boolean ident(String pstrConfig, String pstrFilename, int piExpectedID)
	throws MARFException
	{
		/*
		 * If no expected speaker present on the command line,
		 * attempt to fetch it from the database by filename.
		 */
		if(piExpectedID < 0)
		{
			piExpectedID = soDB.getIDByFilename(pstrFilename, false);
		}

		MARF.setSampleFile(pstrFilename);
		MARF.recognize();

		// First guess
		//int iIdentifiedID = MARF.queryResultID();
		Result bestMatchValueSet = MARF.getResultSet().getBestMatchValue(soDB);
		//Result secondMatchValueSet = MARF.getResultSet().getSecondMatchValue();
		// Second best
		//int iSecondClosestID = MARF.getResultSet().getSecondClosestID();

		if(bestMatchValueSet.getOutcome() > 1500){
			System.out.println("Can not find the matched value:");
			System.out.println("   Best Match Disance: " + bestMatchValueSet.getOutcome()+"\n Exceed the threshold value 1500");
		    return false;
		}else{

			System.out.println("                 File: " + pstrFilename);
			System.out.println("               Config: " + pstrConfig);
			System.out.println("         Speaker's ID: " + bestMatchValueSet.getID());
			System.out.println("   Speaker identified: " + soDB.getName(bestMatchValueSet.getID()));
			System.out.println("   Best Match Disance: " + bestMatchValueSet.getOutcome());
            return true;
		}

		/*
		 * Only collect stats if we have expected speaker
		 */
//		if(piExpectedID > 0)
//		{
//			System.out.println("Expected Speaker's ID: " + piExpectedID);
//			System.out.println("     Expected Speaker: " + soDB.getName(piExpectedID));
//
//			soDB.restore();
//			{
//				// 1st match
//				soDB.addStats(pstrConfig, (iIdentifiedID == piExpectedID));
//				soDB.addStats(soDB.getName(iIdentifiedID), (iIdentifiedID == piExpectedID));
//
//				// 2nd best: must be true if either 1st true or second true (or both :))
//				boolean bSecondBest =
//					iIdentifiedID == piExpectedID
//					||
//					iSecondClosestID == piExpectedID;
//
//				soDB.addStats(pstrConfig, bSecondBest, true);
//				soDB.addStats(soDB.getName(iIdentifiedID), bSecondBest, true);
//			}
//			soDB.dump();
//		}
//
//		System.out.println("       Second Best ID: " + iSecondClosestID);
//		System.out.println("     Second Best Name: " + soDB.getName(iSecondClosestID));
//		System.out.println("            Date/time: " + new Date());
//		System.out.println("   Second Match Disance: " + secondMatchValueSet.getOutcome());
//		System.out.println("----------------------------8<------------------------------");
	}

	/**
	 * Updates training set with a new sample from a given file.
	 *
	 * @param pstrFilename name of the wave file with voice sample train the system on
	 *
	 * @throws MARFException in case of any error while processing is in MARF
	 * @since 0.3.0.5
	 */
	public static final void train(String pstrFilename)
	throws MARFException
	{
		MARF.setSampleFile(pstrFilename);

		int iID = soDB.getIDByFilename(pstrFilename, true);

		if(iID == -1)
		{
			System.out.println("No speaker found for \"" + pstrFilename + "\" for training.");
		}
		else
		{
			MARF.setCurrentSubject(iID);
			MARF.train();
		}
	}

	/**
	 * Displays application's usage information and exits.
	 */
	private static final void usage()
	{
		System.out.println
		(
			"Usage:\n" +
			"  java SpeakerIdentApp --train <samples-dir> [options]        -- train mode\n" +
			"                       --single-train <sample> [options]      -- add a single sample to the training set\n" +
			"                       --ident <sample> [options]             -- identification mode\n" +
			"                       --batch-ident <samples-dir> [options]  -- batch identification mode\n" +
			"                       --stats                                -- display stats\n" +
			"                       --best-score                           -- display best classification result\n" +
			"                       --reset                                -- reset stats\n" +
			"                       --version                              -- display version info\n" +
			"                       --help | -h                            -- display this help and exit\n\n" +

			"Options (one or more of the following):\n\n" +

			"Preprocessing:\n\n" +
			"  -raw          - no preprocessing\n" +
			"  -norm         - use just normalization, no filtering\n" +
			"  -low          - use low-pass filter\n" +
			"  -high         - use high-pass filter\n" +
			"  -boost        - use high-frequency-boost preprocessor\n" +
			"  -band         - use band-pass filter\n" +
			"  -endp         - use endpointing\n" +
			"\n" +

			"Feature Extraction:\n\n" +
			"  -lpc          - use LPC\n" +
			"  -fft          - use FFT\n" +
			"  -minmax       - use Min/Max Amplitudes\n" +
			"  -randfe       - use random feature extraction\n" +
			"  -aggr         - use aggregated FFT+LPC feature extraction\n" +
			"\n" +

			"Classification:\n\n" +
			"  -nn           - use Neural Network\n" +
			"  -cheb         - use Chebyshev Distance\n" +
			"  -eucl         - use Euclidean Distance\n" +
			"  -mink         - use Minkowski Distance\n" +
			"  -diff         - use Diff-Distance\n" +
			"  -randcl       - use random classification\n" +
			"\n" +

			"Misc:\n\n" +
			"  -debug        - include verbose debug output\n" +
			"  -spectrogram  - dump spectrogram image after feature extraction\n" +
			"  -graph        - dump wave graph before preprocessing and after feature extraction\n" +
			"  <integer>     - expected speaker ID\n" +
			"\n"
		);

		System.exit(0);
	}

	/**
	 * Retrieves String representation of the application's version.
	 * @return version String
	 */
	public static final String getVersion()
	{
		return MAJOR_VERSION + "." + MINOR_VERSION + "." + REVISION;
	}

	/**
	 * Retrieves integer representation of the application's version.
	 * @return integer version
	 */
	public static final int getIntVersion()
	{
		return MAJOR_VERSION * 100 + MINOR_VERSION * 10 + REVISION;
	}

	/**
	 * Makes sure the applications isn't run against older MARF version.
	 * Exits with 1 if the MARF version is too old.
	 */
	public static final void validateVersions()
	{
		if(MARF.getDoubleVersion() < (0 * 100 + 3 * 10 + 0 + .5))
		{
			System.err.println
			(
				"Your MARF version (" + MARF.getVersion() +
				") is too old. This application requires 0.3.0.5 or above."
			);

			System.exit(1);
		}
	}

	/**
	 * Composes the current configuration of in a string form.
	 *
	 * @param pstrArgv set of configuration options passed through the command line;
	 * can be null or empty. If latter is the case, MARF itself is queried for its
	 * numerical set up inside.
	 *
	 * @return the current configuration setup
	 */
	public static final String getConfigString(String[] pstrArgv)
	{
		// Store config and error/successes for that config
		String strConfig = "";

		if(pstrArgv != null && pstrArgv.length > 2)
		{
			// Get config from the command line
			for(int i = 2; i < pstrArgv.length; i++)
			{
				strConfig += pstrArgv[i] + " ";
			}
		}
		else
		{
			// Query MARF for it's current config
			strConfig = MARF.getConfig();
		}

		return strConfig;
	}

	/**
	 * Sets default MARF configuration parameters as normalization
	 * for preprocessing, FFT for feature extraction, Eucludean
	 * distance for training and classification with no spectrogram
	 * dumps and no debug information, assuming WAVE file format.
	 *
	 * @throws MARFException
	 * @since 0.3.0.5
	 */
	public static final void setDefaultConfig()
	throws MARFException
	{
		/*
		 * Default MARF setup
		 */
		//MARF.setPreprocessingMethod(MARF.HIGH_FREQUENCY_BOOST_FFT_FILTER);
		MARF.setPreprocessingMethod(MARF.DUMMY);
		//MARF.setFeatureExtractionMethod(MARF.LPC);

		MARF.setFeatureExtractionMethod(MARF.FFT);
		//MARF.setClassificationMethod(MARF.CHEBYSHEV_DISTANCE);

		MARF.setClassificationMethod(MARF.EUCLIDEAN_DISTANCE);
		MARF.setDumpSpectrogram(false);
		MARF.setSampleFormat(MARF.WAV);

		Debug.enableDebug(true);
	}

	/**
	 * Customizes MARF's configuration based on the options.
	 * @throws MARFException if some options are out of range
	 * @since 0.3.0.5
	 */
	public static final void setCustomConfig()
	throws MARFException
	{
		ModuleParams oParams = new ModuleParams();

		for
		(
			int iPreprocessingMethod = MARF.MIN_PREPROCESSING_METHOD;
			iPreprocessingMethod <= MARF.MAX_PREPROCESSING_METHOD;
			iPreprocessingMethod++
		)
		{
			if(soGetOpt.isActiveOption(iPreprocessingMethod))
			{
				MARF.setPreprocessingMethod(iPreprocessingMethod);

				switch(iPreprocessingMethod)
				{
					case MARF.DUMMY:
					case MARF.HIGH_FREQUENCY_BOOST_FFT_FILTER:
					case MARF.HIGH_PASS_FFT_FILTER:
					case MARF.LOW_PASS_FFT_FILTER:
					case MARF.BANDPASS_FFT_FILTER:
					case MARF.HIGH_PASS_BOOST_FILTER:
					case MARF.RAW:
					case MARF.ENDPOINT:
						// For now do nothing; customize when these methods
						// become parametrizable.
						break;

					default:
						assert false;
				} // switch

				break;
			}
		}

		for
		(
			int iFeatureExtractionMethod = MARF.MIN_FEATUREEXTRACTION_METHOD;
			iFeatureExtractionMethod <= MARF.MAX_FEATUREEXTRACTION_METHOD;
			iFeatureExtractionMethod++
		)
		{
			if(soGetOpt.isActiveOption(iFeatureExtractionMethod))
			{
				MARF.setFeatureExtractionMethod(iFeatureExtractionMethod);

				switch(iFeatureExtractionMethod)
				{
					case MARF.FFT:
					case MARF.LPC:
					case MARF.RANDOM_FEATURE_EXTRACTION:
					case MARF.MIN_MAX_AMPLITUDES:
						// For now do nothing; customize when these methods
						// become parametrizable.
						break;

					case MARF.FEATURE_EXTRACTION_AGGREGATOR:
					{
						// For now aggregate FFT followed by LPC until
						// it becomes customizable
						oParams.addFeatureExtractionParam(new Integer(MARF.FFT));
						oParams.addFeatureExtractionParam(null);
						oParams.addFeatureExtractionParam(new Integer(MARF.LPC));
						oParams.addFeatureExtractionParam(null);
						break;
					}

					default:
						assert false;
				} // switch

				break;
			}
		}

		for
		(
			int iClassificationMethod = MARF.MIN_CLASSIFICATION_METHOD;
			iClassificationMethod <= MARF.MAX_CLASSIFICATION_METHOD;
			iClassificationMethod++
		)
		{
			if(soGetOpt.isActiveOption(iClassificationMethod))
			{
				MARF.setClassificationMethod(iClassificationMethod);

				switch(iClassificationMethod)
				{
					case MARF.NEURAL_NETWORK:
					{
						// Dump/Restore Format of the TrainingSet
						oParams.addClassificationParam(new Integer(TrainingSet.DUMP_GZIP_BINARY));

						// Training Constant
						oParams.addClassificationParam(new Double(0.5));

						// Epoch number
						oParams.addClassificationParam(new Integer(20));

						// Min. error
						oParams.addClassificationParam(new Double(0.1));

						break;
					}

					case MARF.MINKOWSKI_DISTANCE:
					{
						// Dump/Restore Format
						oParams.addClassificationParam(new Integer(TrainingSet.DUMP_GZIP_BINARY));

						// Minkowski Factor
						oParams.addClassificationParam(new Double(6.0));

						break;
					}

					case MARF.EUCLIDEAN_DISTANCE:
					case MARF.CHEBYSHEV_DISTANCE:
					case MARF.MAHALANOBIS_DISTANCE:
					case MARF.RANDOM_CLASSIFICATION:
					case MARF.DIFF_DISTANCE:
						// For now do nothing; customize when these methods
						// become parametrizable.
						break;

					default:
						assert false;
				} // switch

				// Method is found, break out of the look up loop
				break;
			}
		}

		// Assign meaningful params only
		if(oParams.size() > 0)
		{
			MARF.setModuleParams(oParams);
		}
	}
}

// EOF
MappingController.java
package org.springframework.samples.mvc.mapping;

import java.io.FileOutputStream;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.math.RandomUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.samples.mvc.utils.VoiceRecogHandler;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MappingController {

	@Autowired
	private VoiceRecogHandler voiceRecogHandler;


	public VoiceRecogHandler getVoiceRecogHandler() {
		return voiceRecogHandler;
	}

	public void setVoiceRecogHandler(VoiceRecogHandler voiceRecogHandler) {
		this.voiceRecogHandler = voiceRecogHandler;
	}
	public static final String VERIFY_FILE_KEY = "VERIFY_FILE_KEY";

	@RequestMapping("/mapping/path")
	public @ResponseBody String byPath() {
		return "Mapped by path!";
	}

	@RequestMapping(value="/mapping/path/*", method=RequestMethod.GET)
	public @ResponseBody String byPathPattern(HttpServletRequest request) {
		return "Mapped by path pattern ('" + request.getRequestURI() + "')";
	}

	@RequestMapping(value="/mapping/method", method=RequestMethod.GET)
	public @ResponseBody String byMethod() {
		return "Mapped by path + method";
	}

	@RequestMapping(value="/mapping/parameter", method=RequestMethod.GET, params="foo")
	public @ResponseBody String byParameter() {
		return "Mapped by path + method + presence of query parameter!";
	}

	@RequestMapping(value="/mapping/parameter", method=RequestMethod.GET, params="!foo")
	public @ResponseBody String byParameterNegation() {
		return "Mapped by path + method + not presence of query parameter!";
	}

	@RequestMapping(value="/mapping/header", method=RequestMethod.GET, headers="FooHeader=foo")
	public @ResponseBody String byHeader() {
		return "Mapped by path + method + presence of header!";
	}

	@RequestMapping(value="/mapping/header", method=RequestMethod.GET, headers="!FooHeader")
	public @ResponseBody String byHeaderNegation() {
		return "Mapped by path + method + absence of header!";
	}

	@RequestMapping(value="/mapping/consumes", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody String byConsumes(@RequestBody JavaBean javaBean) {
		return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')";
	}

	@RequestMapping(value="/mapping/produces", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody JavaBean byProducesJson() {
		return new JavaBean();
	}

	@RequestMapping(value="/mapping/produces", method=RequestMethod.GET, produces=MediaType.APPLICATION_XML_VALUE)
	public @ResponseBody JavaBean byProducesXml() {
		return new JavaBean();
	}
	@RequestMapping(value="/mapping/saveAudio", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody String saveAudio(@RequestBody JavaBean javaBean,HttpServletRequest request) {
        this.voiceRecogHandler.training(javaBean, request);
 		return "Training process was done";
	}

	@RequestMapping(value="/mapping/verifyAudio", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody String verifyAudio(@RequestBody JavaBean javaBean) {
        //this.voiceRecogHandler.recognize(javaBean);
 		return this.voiceRecogHandler.recognize(javaBean)?"Recognize was successful":"Recognize was failure";
	}

	@RequestMapping(value="/mapping/saveImage", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody JavaBean saveImage(@RequestBody JavaBean javaBean) {

//		    FileOutputStream fs = null;
//		    //ByteArrayOutputStream outStr = null;
//			try {
//				fs = new FileOutputStream("d:\\image.png", false);
//
//			    //outStr = new ByteArrayOutputStream();
//
//			    byte[] data =Base64.decode(javaBean.getImageData().getBytes());
//			    //outStr.write(data);
//			    fs.write(data);
//
//			    //outStr.close();
//			    fs.close();
//			} catch (IOException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			} catch(Exception e){
//				e.printStackTrace();
//			}
//			finally{
//				try{
//				    if(fs != null){
//					fs.close();
//
//				    }
//				}catch(IOException e){
//					e.printStackTrace();
//				}
//			}


			 ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
		        try
		        {
		            //try to read the jason string into the Account Object
		        	javaBean.setFoo("FOO");
		        	javaBean.setFruit("Banana");
		          // return mapper.writeValueAsString(javaBean);


			    }catch(Exception e){
			    	e.printStackTrace();
			    }


			//return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')";
		        return javaBean;
		}
}
VoiceRecognize.java
package org.springframework.samples.mvc.mapping;

import java.util.ArrayList;

public class VoiceRecognize {
	private static final String separater = ",";
	private int serialID;
	private String name;
	private ArrayList<String> fileList;

	public int getSerialID() {
		return serialID;
	}

	public void setSerialID(int serialID) {
		this.serialID = serialID;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public ArrayList<String> getFileList() {
		return fileList;
	}

	public void setFileList(ArrayList<String> fileList) {
		this.fileList = fileList;
	}

	public void AddFileName(String fileName){
		if(getFileList() == null){
			this.fileList = new ArrayList();
		}
		this.fileList.add(fileName);
	}

	public String toString(){
		StringBuffer trainingFileList = new StringBuffer();
		for(int i= 0; i<this.fileList.size();i++){
			trainingFileList.append(fileList.get(i));
			if(i<(fileList.size()-1)){
				trainingFileList.append("|");
			}
		}
		return new StringBuffer().append(this.getSerialID())+separater+this.getName()+separater+trainingFileList.toString();
	}

}
JavaBean.java
package org.springframework.samples.mvc.mapping;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class JavaBean {

	private String name;

	private String age;

	private String foo;

	private String fruit;

	private String imageData;


	private String audioData;


	public String getAudioData() {
		return audioData;
	}

	public void setAudioData(String audioData) {
		this.audioData = audioData;
	}

	public String getImageData() {
		return imageData;
	}

	public void setImageData(String imageData) {
		this.imageData = imageData;
	}

	public String getFoo() {
		return foo;
	}

	public void setFoo(String foo) {
		this.foo = foo;
	}

	public String getFruit() {
		return fruit;
	}

	public void setFruit(String fruit) {
		this.fruit = fruit;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "JavaBean {foo=[" + foo + "], fruit=[" + fruit + "]}" + "Age:" + age+"Name:"+name;
	}

}
VoiceRecogHandler .java
package org.springframework.samples.mvc.utils;

import javax.servlet.http.HttpServletRequest;

import org.springframework.samples.mvc.mapping.JavaBean;

public interface VoiceRecogHandler {
     public void training(JavaBean javaBean,HttpServletRequest request);
     public boolean recognize(JavaBean javeBean);
}
VoiceRecogHandlerImpl.java
package org.springframework.samples.mvc.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import marf.MarfUtils;

import org.apache.commons.lang.math.RandomUtils;
import org.springframework.samples.mvc.mapping.JavaBean;
import org.springframework.samples.mvc.mapping.VoiceRecognize;
import org.springframework.security.crypto.codec.Base64;

public class VoiceRecogHandlerImpl implements VoiceRecogHandler {
    private static final String RECOGNIZE_BEAN_KEY = "RECOGNIZE_BEAN_KEY";
    private static final String TRAINING_FOLDER = "d:\\music";

    private void writeToFile(String fileContent, String filePath, boolean isBase64){
    	FileOutputStream fs = null;
		try {
			fs = new FileOutputStream(filePath, false);
		    //outStr = new ByteArrayOutputStream();

		    byte[] data =null;
		   if(isBase64){
			   data = Base64.decode(fileContent.getBytes());
		   }else{
			   data = fileContent.getBytes();
		   }
		    //outStr.write(data);
		    fs.write(data);

		    //outStr.close();
		    fs.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{


				try {
					if(fs != null){
					   fs.close();
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

		}


    }
	@Override
	public void training(JavaBean javaBean, HttpServletRequest request) {
		// TODO Auto-generated method stub
	       HttpSession session = request.getSession();
		    //ByteArrayOutputStream outStr = null;
		    String fileName = new StringBuffer().append("audio_").append(RandomUtils.nextInt(100)).append(".wav").toString();
			try {
				String fullPath= "d:\\music\\"+fileName;
				writeToFile(javaBean.getAudioData(),fullPath,true);

		        VoiceRecognize recognizeBean = null;
		        if(session.getAttribute(RECOGNIZE_BEAN_KEY) != null){
		        	recognizeBean = (VoiceRecognize)session.getAttribute(RECOGNIZE_BEAN_KEY);
		        	recognizeBean.AddFileName(fileName);
		        }else{
		        	recognizeBean = new VoiceRecognize();
		        	recognizeBean.setSerialID(RandomUtils.nextInt(100));
		        	recognizeBean.setName("Customer"+recognizeBean.getSerialID());
		        	recognizeBean.AddFileName(fileName);
		        	session.setAttribute(RECOGNIZE_BEAN_KEY, recognizeBean);
		        }

		        //Check if all the three round been reached, then start the training process
		        if(recognizeBean.getFileList().size() == 3){
		        	String preLoadFileName = "d:\\music\\speakers"+RandomUtils.nextInt(200)+".txt";
		        	writeToFile(recognizeBean.toString(),preLoadFileName,false);
		            //Training the recorded wav File
		        	MarfUtils.initialize(preLoadFileName);
		        	MarfUtils.training(TRAINING_FOLDER);
		        	//Removed the training data in session
		        	session.removeAttribute(RECOGNIZE_BEAN_KEY);
		        }


			} catch(Exception e){
				e.printStackTrace();
			}

	}

	@Override
	public boolean recognize(JavaBean javeBean) {
		// TODO Auto-generated method stub

		String fileName = new StringBuffer().append(TRAINING_FOLDER).append("\\audio_").append(RandomUtils.nextInt(100)).append(".wav").toString();
		writeToFile(javeBean.getAudioData(), fileName,true);

		if(MarfUtils.recongnize(fileName)){
			File file = new File(fileName);
			file.delete();
			return true;
		}
		File file = new File(fileName);
		file.delete();
		return false;

	}

}
script.js
// variables
var leftchannel = [];
var rightchannel = [];
var recorder = null;
var recording = false;
var recordingLength = 0;
var volume = null;
var audioInput = null;
var sampleRate = 44100;
var audioContext = null;
var context = null;
var outputElement = document.getElementById('output');
var outputString;
var progressBarValue = 0;
var progressBarIndex = null;
var trainingURL = "/spring-mvc-showcase/mapping/saveAudio";
var verifyURL = "/spring-mvc-showcase/mapping/verifyAudio";


// feature detection
	if (!navigator.getUserMedia)
	    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
	                  navigator.mozGetUserMedia || navigator.msGetUserMedia;

	if (navigator.getUserMedia){
	    navigator.getUserMedia({audio:true}, success, function(e) {
	    alert('Error capturing audio.');
	    });
	} else
	  {
		alert('getUserMedia not supported in this browser.');
	  }



//Show the error mesasge after start clicking
function showInfoMessage(message){
    recording = true;
    // reset the buffers for the new recording
    leftchannel.length = rightchannel.length = 0;
    recordingLength = 0;
    outputElement.innerHTML = message;
}
//Show the progress bar value
function diplayProgressBarValue(sourceComp){
	progressBarValue++;
	sourceComp.html("<progress value=\""+progressBarValue+"\" max=\"10\">");
	//alert(sourceComp.innerHTML);
	if(progressBarValue == 10){
		 clearInterval(progressBarIndex);
	}
}
//Reset the start value of progress bar
function resetProgressBarValue(){
	progressBarValue= 0;
}
//Start progress bar
function startProgressBar(sourceComp){
	progressBarValue= 0;
	progressBarIndex = setInterval(function(){diplayProgressBarValue(sourceComp)}, 1000);
}
// when key is down
$("#start1").click(function(){
	    startProgressBar($("#progress1"));
	    //alert($("#progress1"));
	    showInfoMessage("Start Training.......");
    }

);
//when key is down
$("#start2").click(function(){
	 startProgressBar($("#progress2"));
	    showInfoMessage("Start Training.......");
    }
);

//when key is down
$("#start3").click(function(){
	 startProgressBar($("#progress3"));
	    showInfoMessage("Start Training.......");
    }
);
//when key is down
$("#verifyStart").click(function(){
	 startProgressBar($("#progressVerify"));
	    showInfoMessage("Start Verifying......");
    }
);
$("#stop1").click(function(){

	sendAudioData(trainingURL);
	 clearInterval(progressBarIndex);
}
);
$("#stop2").click(function(){

	sendAudioData(trainingURL);
	 clearInterval(progressBarIndex);
}
);
$("#stop3").click(function(){

	sendAudioData(trainingURL);
	 clearInterval(progressBarIndex);
}
);

$("#verifyStop").click(function(){

	sendAudioData(verifyURL);
	 clearInterval(progressBarIndex);
}
);

//Capture the recorded audio
function sendAudioData(actionUrl){
    // we stop recording
    recording = false;

    outputElement.innerHTML = 'Building wav file...';

    // we flat the left and right channels down
    var leftBuffer = mergeBuffers ( leftchannel, recordingLength );
    var rightBuffer = mergeBuffers ( rightchannel, recordingLength );
    // we interleave both channels together
    var interleaved = interleave ( leftBuffer, rightBuffer );
    //alert("TEST11");
    // we create our wav file
    var buffer = new ArrayBuffer(44 + interleaved.length * 2);
    var view = new DataView(buffer);
    //alert("TEST12");
    // RIFF chunk descriptor
    writeUTFBytes(view, 0, 'RIFF');
    view.setUint32(4, 44 + interleaved.length * 2, true);
    writeUTFBytes(view, 8, 'WAVE');
    //alert("TEST13");
    // FMT sub-chunk
    writeUTFBytes(view, 12, 'fmt ');
    view.setUint32(16, 16, true);
    view.setUint16(20, 1, true);
    //alert("TEST14");
    // stereo (2 channels)
    view.setUint16(22, 2, true);
    view.setUint32(24, sampleRate, true);
    view.setUint32(28, sampleRate * 4, true);
    view.setUint16(32, 4, true);
    view.setUint16(34, 16, true);
    //alert("TEST15");
    // data sub-chunk
    writeUTFBytes(view, 36, 'data');
    view.setUint32(40, interleaved.length * 2, true);

    // write the PCM samples
    var lng = interleaved.length;
    var index = 44;
    var volume = 1;
    for (var i = 0; i < lng; i++){
        view.setInt16(index, interleaved[i] * (0x7FFF * volume), true);
        index += 2;
    }

    // our final binary blob
    var blob = new Blob ( [ view ], { type : 'audio/wav' } );
    //alert("bold **"+blob);
    //var audioRawData = blob.replace('data:audio/wav;base64,', '');

    var base64Data = null;
    var reader = new window.FileReader();
    reader.readAsDataURL(blob);
    reader.onloadend = function() {
        base64Data = reader.result;
        base64Data = base64Data.replace('data:audio/wav;base64,', '');
        //alert("Inside onloaded"+ base64Data);
	    //alert("RawData **"+base64Data);
	    // let's save it locally
	    outputElement.innerHTML = 'Handing off and training the voice now...';
		    $.ajax({
	        type: 'POST',
	        url: actionUrl,
	        data: '{ "audioData" : "' + base64Data + '" }',
	        contentType: 'application/json; charset=utf-8',
	        dataType: 'text',
	        success: function (msg) {

           MvcUtil.showSuccessResponse(msg,$('#output'));
	        },
	        error: function(xhr) {
	        	MvcUtil.showErrorResponse(xhr.responseText, $('#output'));
	            alert("Error"+xhr.responseText);
	        }
	    });
    };

}

function interleave(leftChannel, rightChannel){
  var length = leftChannel.length + rightChannel.length;
  var result = new Float32Array(length);

  var inputIndex = 0;

  for (var index = 0; index < length; ){
    result[index++] = leftChannel[inputIndex];
    result[index++] = rightChannel[inputIndex];
    inputIndex++;
  }
  return result;
}

function mergeBuffers(channelBuffer, recordingLength){
  var result = new Float32Array(recordingLength);
  var offset = 0;
  var lng = channelBuffer.length;
  for (var i = 0; i < lng; i++){
    var buffer = channelBuffer[i];
    result.set(buffer, offset);
    offset += buffer.length;
  }
  return result;
}

function writeUTFBytes(view, offset, string){
  var lng = string.length;
  for (var i = 0; i < lng; i++){
    view.setUint8(offset + i, string.charCodeAt(i));
  }
}

function success(e){
    // creates the audio context
    audioContext = window.AudioContext || window.webkitAudioContext;
    context = new audioContext();

    console.log('succcess');

    // creates a gain node
    volume = context.createGain();

    // creates an audio node from the microphone incoming stream
    audioInput = context.createMediaStreamSource(e);

    // connect the stream to the gain node
    audioInput.connect(volume);

    /* From the spec: This value controls how frequently the audioprocess event is
    dispatched and how many sample-frames need to be processed each call.
    Lower values for buffer size will result in a lower (better) latency.
    Higher values will be necessary to avoid audio breakup and glitches */
    var bufferSize = 2048;
    recorder = context.createScriptProcessor(bufferSize, 2, 2);

    recorder.onaudioprocess = function(e){
        if (!recording) return;
        var left = e.inputBuffer.getChannelData (0);
        var right = e.inputBuffer.getChannelData (1);
        // we clone the samples
        leftchannel.push (new Float32Array (left));
        rightchannel.push (new Float32Array (right));
        recordingLength += bufferSize;
        console.log('recording');
    }

    // we connect the recorder
    volume.connect (recorder);
    recorder.connect (context.destination);

    //Start Progerss Bar
    var int=self.setInterval("clock()",50);
}
home.jsp
<!DOCTYPE HTML>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html manifest="/spring-mvc-showcase/resources/cache.manifest">
<head>
	<title>spring-mvc-showcase</title>
	<link href="<c:url value="/resources/form.css" />" rel="stylesheet"  type="text/css" />
	<link href="<c:url value="/resources/jqueryui/1.8/themes/base/jquery.ui.all.css" />" rel="stylesheet" type="text/css"/>

	<!--
		Used for including CSRF token in JSON requests
		Also see bottom of this file for adding CSRF token to JQuery AJAX requests
	-->
	<meta name="_csrf" content="${_csrf.token}"/>
	<meta name="_csrf_header" content="${_csrf.headerName}"/>
</head>
<body>
<h1><a href="<c:url value="/" />">spring-mvc-showcase</a></h1>
<p>Recommended: Using a Web Developer tool such a Firebug to inspect the client/server interaction</p>
<div id="tabs">
	<ul>
		<li><a href="#simple">Simple</a></li>
		<li><a href="#mapping">Request Mapping</a></li>
		<li><a href="#data">Request Data</a></li>
		<li><a href="#responses">Response Writing</a></li>
		<li><a href="#messageconverters">Message Converters</a></li>
		<li><a href="#views">View Rendering</a></li>
		<li><a href="#convert">Type Conversion</a></li>
		<li><a href="#validation">Validation</a></li>
		<li><a href="<c:url value="/form" />" title="forms">Forms</a></li>
		<li><a href="<c:url value="/fileupload" />" title="fileupload">File Upload</a></li>
		<li><a href="#exceptions">Exception Handling</a></li>
		<li><a href="#redirect">Redirecting</a></li>
        <li><a href="#async">Async Requests</a></li>
         <li><a href="#Camera">Camere</a></li>
          <li><a href="#Audio">Audio</a></li>
    </ul>
    <div id="simple">
		<h2>Simple</h2>
		<p>
			See the <code>org.springframework.samples.mvc.simple</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="simpleLink" class="textLink" href="<c:url value="/simple" />">GET /simple</a>
			</li>
			<li>
				<a id="simpleRevisited" class="textLink" href="<c:url value="/simple/revisited" />">GET /simple/revisited</a>
			</li>
		</ul>
	</div>
	<div id="mapping">
		<h2>Request Mapping</h2>
		<p>
			See the <code>org.springframework.samples.mvc.mapping</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="byPath" class="textLink" href="<c:url value="/mapping/path" />">By path</a>
			</li>
			<li>
				<a id="byPathPattern" class="textLink" href="<c:url value="/mapping/path/wildcard" />">By path pattern</a>
			</li>
			<li>
				<a id="byMethod" class="textLink" href="<c:url value="/mapping/method" />">By path and method</a>
			</li>
			<li>
				<a id="byParameter" class="textLink" href="<c:url value="/mapping/parameter?foo=bar" />">By path, method, and presence of parameter</a>
			</li>
			<li>
				<a id="byNotParameter" class="textLink" href="<c:url value="/mapping/parameter" />">By path, method, and not presence of parameter</a>
			</li>
			<li>
				<a id="byHeader" href="<c:url value="/mapping/header" />">By presence of header</a>
			</li>
			<li>
				<a id="byHeaderNegation" class="textLink" href="<c:url value="/mapping/header" />">By absence of header</a>
			</li>
			<li>
				<form id="byConsumes" class="readJsonForm" action="<c:url value="/mapping/consumes" />" method="post">
					<input id="byConsumesSubmit" type="submit" value="By consumes" />
				</form>
			</li>
			<li>
				<a id="byProducesAcceptJson" class="writeJsonLink" href="<c:url value="/mapping/produces" />">By produces via Accept=application/json</a>
			</li>
            <li>
                <a id="byProducesAcceptXml" class="writeXmlLink" href="<c:url value="/mapping/produces" />">By produces via Accept=appilcation/xml</a>
            </li>
            <li>
              <a id="byProducesJsonExt" class="writeJsonLink" href="<c:url value="/mapping/produces.json" />">By produces via ".json"</a>
            </li>
            <li>
                <a id="byProducesXmlExt" class="writeXmlLink" href="<c:url value="/mapping/produces.xml" />">By produces via ".xml"</a>
            </li>
		</ul>
	</div>
	<div id="data">
		<h2>Request Data</h2>
		<p>
			See the <code>org.springframework.samples.mvc.data</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="param" class="textLink" href="<c:url value="/data/param?foo=bar" />">Query parameter</a>
			</li>
			<li>
				<a id="group" class="textLink" href="<c:url value="/data/group?param1=foo¶m2=bar¶m3=baz" />">Group of query parameters</a>
			</li>
			<li>
				<a id="var" class="textLink" href="<c:url value="/data/path/foo" />">Path variable</a>
			</li>
			<li>
				<a id="matrixVar" class="textLink" href="<c:url value="/data/matrixvars;foo=bar/simple" />">Matrix variable</a>
			</li>
			<li>
				<a id="matrixVarMultiple" class="textLink" href="<c:url value="/data/matrixvars;foo=bar1/multiple;foo=bar2" />">Matrix variables (multiple)</a>
			</li>
			<li>
				<a id="header" class="textLink" href="<c:url value="/data/header" />">Header</a>
			</li>
			<li>
				<form id="requestBody" class="textForm" action="<c:url value="/data/body" />" method="post">
					<input id="requestBodySubmit" type="submit" value="Request Body" />
				</form>
			</li>
			<li>
				<form id="requestBodyAndHeaders" class="textForm" action="<c:url value="/data/entity" />" method="post">
					<input id="requestBodyAndHeadersSubmit" type="submit" value="Request Body and Headers" />
				</form>
			</li>
		</ul>
		<div id="standardArgs">
			<h3>Standard Resolvable Web Arguments</h3>
			<ul>
				<li>
					<a id="request" class="textLink" href="<c:url value="/data/standard/request" />">Request arguments</a>
				</li>
				<li>
					<form id="requestReader" class="textForm" action="<c:url value="/data/standard/request/reader" />" method="post">
						<input id="requestReaderSubmit" type="submit" value="Request Reader" />
					</form>
				</li>
				<li>
					<form id="requestIs" class="textForm" action="<c:url value="/data/standard/request/is" />" method="post">
						<input id="requestIsSubmit" type="submit" value="Request InputStream" />
					</form>
				</li>
				<li>
					<a id="response" class="textLink" href="<c:url value="/data/standard/response" />">Response arguments</a>
				</li>
				<li>
					<a id="writer" class="textLink" href="<c:url value="/data/standard/response/writer" />">Response Writer</a>
				</li>
				<li>
					<a id="os" class="textLink" href="<c:url value="/data/standard/response/os" />">Response OutputStream</a>
				</li>
				<li>
					<a id="session" class="textLink" href="<c:url value="/data/standard/session" />">Session</a>
				</li>
			</ul>
		</div>
		<div id="customArgs">
			<h3>Custom Resolvable Web Arguments</h3>
			<ul>
				<li>
					<a id="customArg" class="textLink" href="<c:url value="/data/custom" />">Custom</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="responses">
		<h2>Response Writing</h2>
		<p>
			See the <code>org.springframework.samples.mvc.response</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="responseBody" class="textLink" href="<c:url value="/response/annotation" />">@ResponseBody</a>
			</li>
			<li>
				<a id="responseCharsetAccept" class="utf8TextLink" href="<c:url value="/response/charset/accept" />">@ResponseBody (UTF-8 charset requested)</a>
			</li>
			<li>
				<a id="responseCharsetProduce" class="textLink" href="<c:url value="/response/charset/produce" />">@ResponseBody (UTF-8 charset produced)</a>
			</li>
			<li>
				<a id="responseEntityStatus" class="textLink" href="<c:url value="/response/entity/status" />">ResponseEntity (custom status)</a>
			</li>
			<li>
				<a id="responseEntityHeaders" class="textLink" href="<c:url value="/response/entity/headers" />">ResponseEntity (custom headers)</a>
			</li>
		</ul>
	</div>
	<div id="messageconverters">
		<h2>Http Message Converters</h2>
		<p>
			See the <code>org.springframework.samples.mvc.messageconverters</code> package for the @Controller code
		</p>
		<div id="stringMessageConverter">
			<h3>StringHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readString" class="textForm" action="<c:url value="/messageconverters/string" />" method="post">
						<input id="readStringSubmit" type="submit" value="Read a String" />
					</form>
				</li>
				<li>
					<a id="writeString" class="textLink" href="<c:url value="/messageconverters/string" />">Write a String</a>
				</li>
			</ul>
			<h3>FormHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readForm" action="<c:url value="/messageconverters/form" />" method="post">
						<input id="readFormSubmit" type="submit" value="Read Form Data" />
					</form>
				</li>
				<li>
					<a id="writeForm" href="<c:url value="/messageconverters/form" />">Write Form Data</a>
				</li>
			</ul>
			<h3>Jaxb2RootElementHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readXml" class="readXmlForm" action="<c:url value="/messageconverters/xml" />" method="post">
						<input id="readXmlSubmit" type="submit" value="Read XML" />
					</form>
				</li>
				<li>
					<a id="writeXmlAccept" class="writeXmlLink" href="<c:url value="/messageconverters/xml" />">Write XML via Accept=application/xml</a>
				</li>
                <li>
                    <a id="writeXmlExt" class="writeXmlLink" href="<c:url value="/messageconverters/xml.xml" />">Write XML via ".xml"</a>
                </li>
			</ul>
			<h3>MappingJacksonHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readJson" class="readJsonForm" action="<c:url value="/messageconverters/json" />" method="post">
						<input id="readJsonSubmit" type="submit" value="Read JSON" />
					</form>
				</li>
				<li>
					<form id="readJsonInvalid" class="readJsonForm invalid" action="<c:url value="/messageconverters/json" />" method="post">
						<input id="readInvalidJsonSubmit" type="submit" value="Read invalid JSON (400 response code)" />
					</form>
				</li>
				<li>
					<a id="writeJsonAccept" class="writeJsonLink" href="<c:url value="/messageconverters/json" />">Write JSON via Accept=application/json</a>
				</li>
                <li>
                    <a id="writeJsonExt" class="writeJsonLink" href="<c:url value="/messageconverters/json.json" />">Write JSON via ".json"</a>
                </li>
			</ul>
			<h3>AtomFeedHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readAtom" action="<c:url value="/messageconverters/atom" />" method="post">
						<input id="readAtomSubmit" type="submit" value="Read Atom" />
					</form>
				</li>
				<li>
					<a id="writeAtom" href="<c:url value="/messageconverters/atom" />">Write Atom</a>
				</li>
			</ul>
			<h3>RssChannelHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readRss" action="<c:url value="/messageconverters/rss" />" method="post">
						<input id="readRssSubmit" type="submit" value="Read Rss" />
					</form>
				</li>
				<li>
					<a id="writeRss" href="<c:url value="/messageconverters/rss" />">Write Rss</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="views">
		<h2>View Rendering</h2>
		<p>
			See the <code>org.springframework.samples.mvc.views</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a href="<c:url value="/views/html" />">HTML generated by JSP template</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/viewName" />">DefaultRequestToViewNameTranslator convention</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/pathVariables/bar/apple" />">Using path variables in a view template</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/dataBinding/bar/apple" />">Data binding with URI variables</a>
			</li>
		</ul>
	</div>
	<div id="convert">
		<h2>Type Conversion</h2>
		<p>
			See the <code>org.springframework.samples.mvc.convert</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="primitive" class="textLink" href="<c:url value="/convert/primitive?value=3" />">Primitive</a>
			</li>
			<li>
				<a id="date" class="textLink" href="<c:url value="/convert/date/2010-07-04" />">Date</a>
			</li>
			<li>
				<a id="collection" class="textLink" href="<c:url value="/convert/collection?values=1&values=2&values=3&values=4&values=5" />">Collection 1 (multi-value parameter)</a>
			</li>
			<li>
				<a id="collection2" class="textLink" href="<c:url value="/convert/collection?values=1,2,3,4,5" />">Collection 2 (single comma-delimited parameter value)</a>
			</li>
			<li>
				<a id="formattedCollection" class="textLink" href="<c:url value="/convert/formattedCollection?values=2010-07-04,2011-07-04" />">@Formatted Collection</a>
			</li>
			<li>
				<a id="valueObject" class="textLink" href="<c:url value="/convert/value?value=123456789" />">Custom Value Object</a>
			</li>
			<li>
				<a id="customConverter" class="textLink" href="<c:url value="/convert/custom?value=123-45-6789" />">Custom Converter</a>
			</li>
		</ul>
		<div id="convert-bean">
			<h3>JavaBean Property Binding</h3>
			<ul>
				<li>
					<a id="primitiveProp" class="textLink" href="<c:url value="/convert/bean?primitive=3" />">Primitive</a>
				</li>
				<li>
					<a id="dateProp" class="textLink" href="<c:url value="/convert/bean?date=2010-07-04" />">Date</a>
				</li>
				<li>
					<a id="maskedProp" class="textLink" href="<c:url value="/convert/bean?masked=(205) 333-3333" />">Masked</a>
				</li>
				<li>
					<a id="listProp" class="textLink" href="<c:url value="/convert/bean?list[0]=1&list[1]=2&list[2]=3" />">List Elements</a>
				</li>
				<li>
					<a id="formattedListProp" class="textLink" href="<c:url value="/convert/bean?formattedList[0]=2010-07-04&formattedList[1]=2011-07-04" />">@Formatted List Elements</a>
				</li>
				<li>
					<a id="mapProp" class="textLink" href="<c:url value="/convert/bean?map[0]=apple&map[1]=pear" />">Map Elements</a>
				</li>
				<li>
					<a id="nestedProp" class="textLink" href="<c:url value="/convert/bean?nested.foo=bar&nested.list[0].foo=baz&nested.map[key].list[0].foo=bip" />">Nested</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="validation">
		<h2>Validation</h2>
		<p>
			See the <code>org.springframework.samples.mvc.validation</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="validateNoErrors" class="textLink" href="<c:url value="/validate?number=3&date=2029-07-04" />">Validate, no errors</a>
			</li>
			<li>
				<a id="validateErrors" class="textLink" href="<c:url value="/validate?number=3&date=2010-07-01" />">Validate, errors</a>
			</li>
		</ul>
	</div>
	<div id="exceptions">
		<h2>Exception Handling</h2>
		<p>
			See the <code>org.springframework.samples.mvc.exceptions</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="exception" class="textLink" href="<c:url value="/exception" />">@ExceptionHandler in Controller</a>
			</li>
			<li>
				<a id="globalException" class="textLink" href="<c:url value="/global-exception" />">Global @ExceptionHandler</a>
			</li>
		</ul>
	</div>
	<div id="redirect">
		<h2>Redirecting</h2>
		<p>
			See the <code>org.springframework.samples.mvc.redirect</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a href="<c:url value="/redirect/uriTemplate" />">URI Template String</a>
			</li>
			<li>
				<a href="<c:url value="/redirect/uriComponentsBuilder" />">UriComponentsBuilder</a>
			</li>
		</ul>
	</div>
	<div id="async">
		<h2>Async Requests</h2>
		<p>
			<em>Note: Links may take 2-3 seconds to complete.</em>
		</p>
		<p>
		  See the <code>org.springframework.samples.mvc.async</code> package for the @Controller code.
		</p>
		<ul>
		<li>
			<a id="callableResponseBodyLink" class="textLink"
				href="<c:url value="/async/callable/response-body" />">GET /async/callable/response-body</a>
		</li>
		<li>
			<a id="callableViewLink" class="textLink"
				href="<c:url value="/async/callable/view" />">GET /async/callable/view</a>
		</li>
		<li>
			<a id="callableExceptionLink" class="textLink"
				href="<c:url value="/async/callable/exception" />">GET /async/callable/exception</a>
		</li>
		<li>
			<a id="callableUnhandledExceptionLink" class="textLink"
				href="<c:url value="/async/callable/exception?handled=false" />">GET /async/callable/exception?handled=false</a>
				(500 Error expected)
		</li>
		<li>
			<a id="callableCustomTimeoutLink" class="textLink"
				href="<c:url value="/async/callable/custom-timeout-handling" />">GET /async/callable/custom-timeout-handling</a>
		</li>
		<li>
			<a id="deferredResultSuccessLink" class="textLink"
				href="<c:url value="/async/deferred-result/response-body" />">GET /async/deferred-result/response-body</a>
		</li>
		<li>
			<a id="deferredResultModelAndViewLink" class="textLink"
				href="<c:url value="/async/deferred-result/model-and-view" />">GET /async/deferred-result/model-and-view</a>
		</li>
		<li>
			<a id="deferredResultErrorLink" class="textLink"
				href="<c:url value="/async/deferred-result/exception" />">GET /async/deferred-result/exception</a>
		</li>
		<li>
			<a id="deferredResultTimeoutValueLink" class="textLink"
				href="<c:url value="/async/deferred-result/timeout-value" />">GET /async/deferred-result/timeout-value</a>
		</li>
		</ul>
	</div>


		<div id="Camera">
		<h2>Camera Take Photos</h2>

		<p>
		     <form id="byConsumes" class="saveImageForm" action="/spring-mvc-showcase/mapping/saveImage" method="post">

	             <p>
						<video id="video" width="400" height="400" controls="controls" autoplay="autoplay">

						 <source src="/spring-mvc-showcase/resources/img/movie.ogg" type="video/ogg"/>
						 </video>
						 <canvas id="canvas" width="300" height="300"></canvas>
                 </p>
				 <p>
					 <button id="snap">TakePhoto</button>
	            <input id="byConsumesSubmit" type="submit" value="SaveImages" />
<!-- 					  <button id="sendBtn">SavePhoto</button> -->
			     </p>
				</form>


		<div id="saveStatus">

		</div>


	</div>

	<div id="Audio">
	  <section>
	  <h1>Training Section</h1>
	  <p>
	     Note:Please record at least 10 seconds!
	  </p>
	  <table border="1" with="100%">
	    <thead>
	        <tr>
	           <th>Step</th>
	           <th>Start Action</th>
	           <th>End Action</th>
	           <th>Progress</th>
	        </tr>
	    </thead>
	     <tr>
	          <td width="10%">1</td>
	          <td width="30%"> <button id="start1">Start Training</button></td>
	          <td width="30%"> <button id="stop1">Stop Training</button></td>
	          <td width="30%" id="progress1"><progress value="0" max="10"></progress></td>
	     </tr>
	     <tr>
	          <td width="10%">2</td>
	          <td width="45%"> <button id="start2">Start Training</button></td>
	          <td width="45%"> <button id="stop2">Stop Training</button></td>
	          <td width="30%" id="progress2"><progress  value="0" max="10"></progress></td>
	     </tr>

	     <tr>
	          <td width="10%">3</td>
	          <td width="45%"> <button id="start3">Start Training</button></td>
	          <td width="45%"> <button id="stop3">Stop Training</button></td>
	          <td width="30%" id="progress3"><progress  value="0" max="10"></progress></td>
	     </tr>
	  </table>
	  </section>

	  <section>
	  <h1>Verify Section</h1>

	  <table border="1" with="100%">
	  	    <thead>
	        <tr>

	           <th>Start Verify</th>
	           <th>End Verify</th>
	           <th>Progress</th>
	        </tr>
	    </thead>
	     <tr>
	          <td width = "30%"> <button id="verifyStart">Start Verify</button></td>
	          <td width = "30%"> <button id="verifyStop">End Vefiry</button></td>
	          <td width="30%" id="progressVerify"><progress  value="0" max="10"></progress></td>
	     </tr>

	  </table>
	  </section>
	  <section>
	  <h1>Action Status</h1>
	  <div id="output">

	   </div>
      </section>

	</div>
</div>
<script type="text/javascript" src="<c:url value="/resources/jquery/1.6/jquery.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryform/2.8/jquery.form.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.core.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.widget.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.tabs.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/json2.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/js/script.js" />"></script>
<script>
	MvcUtil = {};
	MvcUtil.showSuccessResponse = function (text, element) {
		MvcUtil.showResponse("success", text, element);
	};
	MvcUtil.showErrorResponse = function showErrorResponse(text, element) {
		MvcUtil.showResponse("error", text, element);
	};
	MvcUtil.showResponse = function(type, text, element) {
		var responseElementId = element.attr("id") + "Response";
		var responseElement = $("#" + responseElementId);
		if (responseElement.length == 0) {
			responseElement = $('<span id="' + responseElementId + '" class="' + type + '" style="display:none">' + text + '</span>').insertAfter(element);
		} else {
			responseElement.replaceWith('<span id="' + responseElementId + '" class="' + type + '" style="display:none">' + text + '</span>');
			responseElement = $("#" + responseElementId);
		}
		responseElement.fadeIn("slow");
	};
	MvcUtil.xmlencode = function(xml) {
		//for IE
		var text;
		if (window.ActiveXObject) {
		    text = xml.xml;
		 }
		// for Mozilla, Firefox, Opera, etc.
		else {
		   text = (new XMLSerializer()).serializeToString(xml);
		}
		    return text.replace(/\&/g,'&'+'amp;').replace(/</g,'&'+'lt;')
	        .replace(/>/g,'&'+'gt;').replace(/\'/g,'&'+'apos;').replace(/\"/g,'&'+'quot;');
	};
</script>
<script type="text/javascript">
$(document).ready(function() {
	$("#tabs").tabs();

	// Append '#' to the window location so "Back" returns to the selected tab
	// after a redirect or a full page refresh (e.g. Views tab).

	// However, note this general disclaimer about going back to previous tabs:
	// http://docs.jquery.com/UI/API/1.8/Tabs#Back_button_and_bookmarking

	$("#tabs").bind("tabsselect", function(event, ui) { window.location.hash = ui.tab.hash; });


	$("a.textLink").click(function(){
		var link = $(this);
		$.ajax({ url: link.attr("href"), dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("a.utf8TextLink").click(function(){
		var link = $(this);
		$.ajax({ url: link.attr("href"), dataType: "text", beforeSend: function(req) { req.setRequestHeader("Accept", "text/plain;charset=UTF-8"); }, success: function(text) { MvcUtil.showSuccessResponse(text, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("form.textForm").submit(function(event) {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "foo", contentType: "text/plain", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#readForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "foo=bar&fruit=apple", contentType: "application/x-www-form-urlencoded", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeForm").click(function() {
		var link = $(this);
		$.ajax({ url: this.href, dataType: "text", beforeSend: function(req) { req.setRequestHeader("Accept", "application/x-www-form-urlencoded"); }, success: function(form) { MvcUtil.showSuccessResponse(form, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("form.readXmlForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><javaBean><foo>bar</foo><fruit>apple</fruit></javaBean>", contentType: "application/xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("a.writeXmlLink").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				if (!this.url.match(/\.xml$/)) {
					req.setRequestHeader("Accept", "application/xml");
				}
			},
			success: function(xml) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(xml), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("form.readJsonForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		var data = form.hasClass("invalid") ?
				"{ \"foo\": \"bar\" }" :
				"{ \"foo\": \"bar\", \"fruit\": \"apple\" }";
		$.ajax({ type: "POST", url: form.attr("action"), data: data, contentType: "application/json", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("a.writeJsonLink").click(function() {
		var link = $(this);
		$.ajax({ url: this.href,
			beforeSend: function(req) {
				if (!this.url.match(/\.json$/)) {
					req.setRequestHeader("Accept", "application/json");
				}
			},
			success: function(json) {
				MvcUtil.showSuccessResponse(JSON.stringify(json), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}});
		return false;
	});

	$("#readAtom").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: '<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"><title>My Atom feed</title></feed>', contentType: "application/atom+xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeAtom").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				req.setRequestHeader("Accept", "application/atom+xml");
			},
			success: function(feed) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(feed), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("#readRss").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: '<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"><channel><title>My RSS feed</title></channel></rss>', contentType: "application/rss+xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeRss").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				req.setRequestHeader("Accept", "application/rss+xml");
			},
			success: function(feed) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(feed), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("#byHeader").click(function(){
		var link = $(this);
		$.ajax({ url: this.href, dataType: "text", beforeSend: function(req) { req.setRequestHeader("FooHeader", "foo"); }, success: function(form) { MvcUtil.showSuccessResponse(form, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

		window.addEventListener("DOMContentLoaded", function() {

 			// Grab elements, create settings, etc.
 			var canvas = document.getElementById("canvas"),
 				context = canvas.getContext("2d"),
 				video = document.getElementById("video"),
 				videoObj = { "video": true },
 				errBack = function(error) {
 					console.log("Video capture error: ", error.code);
 				};
		 		document.getElementById("snap").addEventListener("click", function() {

		 			context.drawImage(video, 0, 0, 300, 300);


		 		});

				$("form.saveImageForm").submit(function() {
					var form = $(this);
				    var image = canvas.toDataURL("image/png");
				    image = image.replace('data:image/png;base64,', '');
					$.ajax({ type: "POST", url: form.attr("action"), data: '{ "imageData" : "' + image + '" }', contentType: "application/json", dataType: "json", success: function(text) { alert(text.foo+text.fruit);MvcUtil.showSuccessResponse(text, $('#saveStatus')); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, $('#saveStatus')); }});
					return false;
				});

// 				$('#sendBtn').live('click', function () {
// 				    var image = canvas.toDataURL("image/png");
// 				    image = image.replace('data:image/png;base64,', '');
//                     alert("ImageValue"+image);
// 				    $.ajax({
// 				        type: 'POST',
// 				        url: '/spring-mvc-showcase/mapping/saveImage',
// 				        data: '{ "imageData" : "' + image + '" }',
// 				        contentType: 'application/json; charset=utf-8',
// 				        dataType: 'json',
// 				        success: function (msg) {
// 				            alert(msg);
//				           MvcUtil.showSuccessResponse("Saved Successfully",$('#saveStatus'));
// 				        },
// 				        error: function(xhr) {
// 				        	MvcUtil.showErrorResponse(xhr.responseText, $('#saveStatus'));
// 				            alert("Error"+xhr.responseText);
// 				        }
// 				    });
// 				});


 		}, false);



	// Include CSRF token as header in JQuery AJAX requests
	// See http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#csrf-include-csrf-token-ajax
	var token = $("meta[name='_csrf']").attr("content");
	var header = $("meta[name='_csrf_header']").attr("content");
	$(document).ajaxSend(function(e, xhr, options) {
		xhr.setRequestHeader(header, token);
	});

});
</script>
</body>
</html>
HTML5UpdateWithForm
<!DOCTYPE HTML>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html manifest="/spring-mvc-showcase/resources/cache.manifest">
<head>
	<title>spring-mvc-showcase</title>
	<link href="<c:url value="/resources/form.css" />" rel="stylesheet"  type="text/css" />
	<link href="<c:url value="/resources/jqueryui/1.8/themes/base/jquery.ui.all.css" />" rel="stylesheet" type="text/css"/>

	<!--
		Used for including CSRF token in JSON requests
		Also see bottom of this file for adding CSRF token to JQuery AJAX requests
	-->
	<meta name="_csrf" content="${_csrf.token}"/>
	<meta name="_csrf_header" content="${_csrf.headerName}"/>
</head>
<body>
<h1><a href="<c:url value="/" />">spring-mvc-showcase</a></h1>
<p>Recommended: Using a Web Developer tool such a Firebug to inspect the client/server interaction</p>
<div id="tabs">
	<ul>
		<li><a href="#simple">Simple</a></li>
		<li><a href="#mapping">Request Mapping</a></li>
		<li><a href="#data">Request Data</a></li>
		<li><a href="#responses">Response Writing</a></li>
		<li><a href="#messageconverters">Message Converters</a></li>
		<li><a href="#views">View Rendering</a></li>
		<li><a href="#convert">Type Conversion</a></li>
		<li><a href="#validation">Validation</a></li>
		<li><a href="<c:url value="/form" />" title="forms">Forms</a></li>
		<li><a href="<c:url value="/fileupload" />" title="fileupload">File Upload</a></li>
		<li><a href="#exceptions">Exception Handling</a></li>
		<li><a href="#redirect">Redirecting</a></li>
        <li><a href="#async">Async Requests</a></li>
         <li><a href="#Camera">Camere</a></li>
    </ul>
    <div id="simple">
		<h2>Simple</h2>
		<p>
			See the <code>org.springframework.samples.mvc.simple</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="simpleLink" class="textLink" href="<c:url value="/simple" />">GET /simple</a>
			</li>
			<li>
				<a id="simpleRevisited" class="textLink" href="<c:url value="/simple/revisited" />">GET /simple/revisited</a>
			</li>
		</ul>
	</div>
	<div id="mapping">
		<h2>Request Mapping</h2>
		<p>
			See the <code>org.springframework.samples.mvc.mapping</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="byPath" class="textLink" href="<c:url value="/mapping/path" />">By path</a>
			</li>
			<li>
				<a id="byPathPattern" class="textLink" href="<c:url value="/mapping/path/wildcard" />">By path pattern</a>
			</li>
			<li>
				<a id="byMethod" class="textLink" href="<c:url value="/mapping/method" />">By path and method</a>
			</li>
			<li>
				<a id="byParameter" class="textLink" href="<c:url value="/mapping/parameter?foo=bar" />">By path, method, and presence of parameter</a>
			</li>
			<li>
				<a id="byNotParameter" class="textLink" href="<c:url value="/mapping/parameter" />">By path, method, and not presence of parameter</a>
			</li>
			<li>
				<a id="byHeader" href="<c:url value="/mapping/header" />">By presence of header</a>
			</li>
			<li>
				<a id="byHeaderNegation" class="textLink" href="<c:url value="/mapping/header" />">By absence of header</a>
			</li>
			<li>
				<form id="byConsumes" class="readJsonForm" action="<c:url value="/mapping/consumes" />" method="post">
					<input id="byConsumesSubmit" type="submit" value="By consumes" />
				</form>
			</li>
			<li>
				<a id="byProducesAcceptJson" class="writeJsonLink" href="<c:url value="/mapping/produces" />">By produces via Accept=application/json</a>
			</li>
            <li>
                <a id="byProducesAcceptXml" class="writeXmlLink" href="<c:url value="/mapping/produces" />">By produces via Accept=appilcation/xml</a>
            </li>
            <li>
              <a id="byProducesJsonExt" class="writeJsonLink" href="<c:url value="/mapping/produces.json" />">By produces via ".json"</a>
            </li>
            <li>
                <a id="byProducesXmlExt" class="writeXmlLink" href="<c:url value="/mapping/produces.xml" />">By produces via ".xml"</a>
            </li>
		</ul>
	</div>
	<div id="data">
		<h2>Request Data</h2>
		<p>
			See the <code>org.springframework.samples.mvc.data</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="param" class="textLink" href="<c:url value="/data/param?foo=bar" />">Query parameter</a>
			</li>
			<li>
				<a id="group" class="textLink" href="<c:url value="/data/group?param1=foo¶m2=bar¶m3=baz" />">Group of query parameters</a>
			</li>
			<li>
				<a id="var" class="textLink" href="<c:url value="/data/path/foo" />">Path variable</a>
			</li>
			<li>
				<a id="matrixVar" class="textLink" href="<c:url value="/data/matrixvars;foo=bar/simple" />">Matrix variable</a>
			</li>
			<li>
				<a id="matrixVarMultiple" class="textLink" href="<c:url value="/data/matrixvars;foo=bar1/multiple;foo=bar2" />">Matrix variables (multiple)</a>
			</li>
			<li>
				<a id="header" class="textLink" href="<c:url value="/data/header" />">Header</a>
			</li>
			<li>
				<form id="requestBody" class="textForm" action="<c:url value="/data/body" />" method="post">
					<input id="requestBodySubmit" type="submit" value="Request Body" />
				</form>
			</li>
			<li>
				<form id="requestBodyAndHeaders" class="textForm" action="<c:url value="/data/entity" />" method="post">
					<input id="requestBodyAndHeadersSubmit" type="submit" value="Request Body and Headers" />
				</form>
			</li>
		</ul>
		<div id="standardArgs">
			<h3>Standard Resolvable Web Arguments</h3>
			<ul>
				<li>
					<a id="request" class="textLink" href="<c:url value="/data/standard/request" />">Request arguments</a>
				</li>
				<li>
					<form id="requestReader" class="textForm" action="<c:url value="/data/standard/request/reader" />" method="post">
						<input id="requestReaderSubmit" type="submit" value="Request Reader" />
					</form>
				</li>
				<li>
					<form id="requestIs" class="textForm" action="<c:url value="/data/standard/request/is" />" method="post">
						<input id="requestIsSubmit" type="submit" value="Request InputStream" />
					</form>
				</li>
				<li>
					<a id="response" class="textLink" href="<c:url value="/data/standard/response" />">Response arguments</a>
				</li>
				<li>
					<a id="writer" class="textLink" href="<c:url value="/data/standard/response/writer" />">Response Writer</a>
				</li>
				<li>
					<a id="os" class="textLink" href="<c:url value="/data/standard/response/os" />">Response OutputStream</a>
				</li>
				<li>
					<a id="session" class="textLink" href="<c:url value="/data/standard/session" />">Session</a>
				</li>
			</ul>
		</div>
		<div id="customArgs">
			<h3>Custom Resolvable Web Arguments</h3>
			<ul>
				<li>
					<a id="customArg" class="textLink" href="<c:url value="/data/custom" />">Custom</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="responses">
		<h2>Response Writing</h2>
		<p>
			See the <code>org.springframework.samples.mvc.response</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="responseBody" class="textLink" href="<c:url value="/response/annotation" />">@ResponseBody</a>
			</li>
			<li>
				<a id="responseCharsetAccept" class="utf8TextLink" href="<c:url value="/response/charset/accept" />">@ResponseBody (UTF-8 charset requested)</a>
			</li>
			<li>
				<a id="responseCharsetProduce" class="textLink" href="<c:url value="/response/charset/produce" />">@ResponseBody (UTF-8 charset produced)</a>
			</li>
			<li>
				<a id="responseEntityStatus" class="textLink" href="<c:url value="/response/entity/status" />">ResponseEntity (custom status)</a>
			</li>
			<li>
				<a id="responseEntityHeaders" class="textLink" href="<c:url value="/response/entity/headers" />">ResponseEntity (custom headers)</a>
			</li>
		</ul>
	</div>
	<div id="messageconverters">
		<h2>Http Message Converters</h2>
		<p>
			See the <code>org.springframework.samples.mvc.messageconverters</code> package for the @Controller code
		</p>
		<div id="stringMessageConverter">
			<h3>StringHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readString" class="textForm" action="<c:url value="/messageconverters/string" />" method="post">
						<input id="readStringSubmit" type="submit" value="Read a String" />
					</form>
				</li>
				<li>
					<a id="writeString" class="textLink" href="<c:url value="/messageconverters/string" />">Write a String</a>
				</li>
			</ul>
			<h3>FormHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readForm" action="<c:url value="/messageconverters/form" />" method="post">
						<input id="readFormSubmit" type="submit" value="Read Form Data" />
					</form>
				</li>
				<li>
					<a id="writeForm" href="<c:url value="/messageconverters/form" />">Write Form Data</a>
				</li>
			</ul>
			<h3>Jaxb2RootElementHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readXml" class="readXmlForm" action="<c:url value="/messageconverters/xml" />" method="post">
						<input id="readXmlSubmit" type="submit" value="Read XML" />
					</form>
				</li>
				<li>
					<a id="writeXmlAccept" class="writeXmlLink" href="<c:url value="/messageconverters/xml" />">Write XML via Accept=application/xml</a>
				</li>
                <li>
                    <a id="writeXmlExt" class="writeXmlLink" href="<c:url value="/messageconverters/xml.xml" />">Write XML via ".xml"</a>
                </li>
			</ul>
			<h3>MappingJacksonHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readJson" class="readJsonForm" action="<c:url value="/messageconverters/json" />" method="post">
						<input id="readJsonSubmit" type="submit" value="Read JSON" />
					</form>
				</li>
				<li>
					<form id="readJsonInvalid" class="readJsonForm invalid" action="<c:url value="/messageconverters/json" />" method="post">
						<input id="readInvalidJsonSubmit" type="submit" value="Read invalid JSON (400 response code)" />
					</form>
				</li>
				<li>
					<a id="writeJsonAccept" class="writeJsonLink" href="<c:url value="/messageconverters/json" />">Write JSON via Accept=application/json</a>
				</li>
                <li>
                    <a id="writeJsonExt" class="writeJsonLink" href="<c:url value="/messageconverters/json.json" />">Write JSON via ".json"</a>
                </li>
			</ul>
			<h3>AtomFeedHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readAtom" action="<c:url value="/messageconverters/atom" />" method="post">
						<input id="readAtomSubmit" type="submit" value="Read Atom" />
					</form>
				</li>
				<li>
					<a id="writeAtom" href="<c:url value="/messageconverters/atom" />">Write Atom</a>
				</li>
			</ul>
			<h3>RssChannelHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readRss" action="<c:url value="/messageconverters/rss" />" method="post">
						<input id="readRssSubmit" type="submit" value="Read Rss" />
					</form>
				</li>
				<li>
					<a id="writeRss" href="<c:url value="/messageconverters/rss" />">Write Rss</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="views">
		<h2>View Rendering</h2>
		<p>
			See the <code>org.springframework.samples.mvc.views</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a href="<c:url value="/views/html" />">HTML generated by JSP template</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/viewName" />">DefaultRequestToViewNameTranslator convention</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/pathVariables/bar/apple" />">Using path variables in a view template</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/dataBinding/bar/apple" />">Data binding with URI variables</a>
			</li>
		</ul>
	</div>
	<div id="convert">
		<h2>Type Conversion</h2>
		<p>
			See the <code>org.springframework.samples.mvc.convert</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="primitive" class="textLink" href="<c:url value="/convert/primitive?value=3" />">Primitive</a>
			</li>
			<li>
				<a id="date" class="textLink" href="<c:url value="/convert/date/2010-07-04" />">Date</a>
			</li>
			<li>
				<a id="collection" class="textLink" href="<c:url value="/convert/collection?values=1&values=2&values=3&values=4&values=5" />">Collection 1 (multi-value parameter)</a>
			</li>
			<li>
				<a id="collection2" class="textLink" href="<c:url value="/convert/collection?values=1,2,3,4,5" />">Collection 2 (single comma-delimited parameter value)</a>
			</li>
			<li>
				<a id="formattedCollection" class="textLink" href="<c:url value="/convert/formattedCollection?values=2010-07-04,2011-07-04" />">@Formatted Collection</a>
			</li>
			<li>
				<a id="valueObject" class="textLink" href="<c:url value="/convert/value?value=123456789" />">Custom Value Object</a>
			</li>
			<li>
				<a id="customConverter" class="textLink" href="<c:url value="/convert/custom?value=123-45-6789" />">Custom Converter</a>
			</li>
		</ul>
		<div id="convert-bean">
			<h3>JavaBean Property Binding</h3>
			<ul>
				<li>
					<a id="primitiveProp" class="textLink" href="<c:url value="/convert/bean?primitive=3" />">Primitive</a>
				</li>
				<li>
					<a id="dateProp" class="textLink" href="<c:url value="/convert/bean?date=2010-07-04" />">Date</a>
				</li>
				<li>
					<a id="maskedProp" class="textLink" href="<c:url value="/convert/bean?masked=(205) 333-3333" />">Masked</a>
				</li>
				<li>
					<a id="listProp" class="textLink" href="<c:url value="/convert/bean?list[0]=1&list[1]=2&list[2]=3" />">List Elements</a>
				</li>
				<li>
					<a id="formattedListProp" class="textLink" href="<c:url value="/convert/bean?formattedList[0]=2010-07-04&formattedList[1]=2011-07-04" />">@Formatted List Elements</a>
				</li>
				<li>
					<a id="mapProp" class="textLink" href="<c:url value="/convert/bean?map[0]=apple&map[1]=pear" />">Map Elements</a>
				</li>
				<li>
					<a id="nestedProp" class="textLink" href="<c:url value="/convert/bean?nested.foo=bar&nested.list[0].foo=baz&nested.map[key].list[0].foo=bip" />">Nested</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="validation">
		<h2>Validation</h2>
		<p>
			See the <code>org.springframework.samples.mvc.validation</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="validateNoErrors" class="textLink" href="<c:url value="/validate?number=3&date=2029-07-04" />">Validate, no errors</a>
			</li>
			<li>
				<a id="validateErrors" class="textLink" href="<c:url value="/validate?number=3&date=2010-07-01" />">Validate, errors</a>
			</li>
		</ul>
	</div>
	<div id="exceptions">
		<h2>Exception Handling</h2>
		<p>
			See the <code>org.springframework.samples.mvc.exceptions</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="exception" class="textLink" href="<c:url value="/exception" />">@ExceptionHandler in Controller</a>
			</li>
			<li>
				<a id="globalException" class="textLink" href="<c:url value="/global-exception" />">Global @ExceptionHandler</a>
			</li>
		</ul>
	</div>
	<div id="redirect">
		<h2>Redirecting</h2>
		<p>
			See the <code>org.springframework.samples.mvc.redirect</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a href="<c:url value="/redirect/uriTemplate" />">URI Template String</a>
			</li>
			<li>
				<a href="<c:url value="/redirect/uriComponentsBuilder" />">UriComponentsBuilder</a>
			</li>
		</ul>
	</div>
	<div id="async">
		<h2>Async Requests</h2>
		<p>
			<em>Note: Links may take 2-3 seconds to complete.</em>
		</p>
		<p>
		  See the <code>org.springframework.samples.mvc.async</code> package for the @Controller code.
		</p>
		<ul>
		<li>
			<a id="callableResponseBodyLink" class="textLink"
				href="<c:url value="/async/callable/response-body" />">GET /async/callable/response-body</a>
		</li>
		<li>
			<a id="callableViewLink" class="textLink"
				href="<c:url value="/async/callable/view" />">GET /async/callable/view</a>
		</li>
		<li>
			<a id="callableExceptionLink" class="textLink"
				href="<c:url value="/async/callable/exception" />">GET /async/callable/exception</a>
		</li>
		<li>
			<a id="callableUnhandledExceptionLink" class="textLink"
				href="<c:url value="/async/callable/exception?handled=false" />">GET /async/callable/exception?handled=false</a>
				(500 Error expected)
		</li>
		<li>
			<a id="callableCustomTimeoutLink" class="textLink"
				href="<c:url value="/async/callable/custom-timeout-handling" />">GET /async/callable/custom-timeout-handling</a>
		</li>
		<li>
			<a id="deferredResultSuccessLink" class="textLink"
				href="<c:url value="/async/deferred-result/response-body" />">GET /async/deferred-result/response-body</a>
		</li>
		<li>
			<a id="deferredResultModelAndViewLink" class="textLink"
				href="<c:url value="/async/deferred-result/model-and-view" />">GET /async/deferred-result/model-and-view</a>
		</li>
		<li>
			<a id="deferredResultErrorLink" class="textLink"
				href="<c:url value="/async/deferred-result/exception" />">GET /async/deferred-result/exception</a>
		</li>
		<li>
			<a id="deferredResultTimeoutValueLink" class="textLink"
				href="<c:url value="/async/deferred-result/timeout-value" />">GET /async/deferred-result/timeout-value</a>
		</li>
		</ul>
	</div>


		<div id="Camera">
		<h2>Camera Take Photos</h2>

		<p>
		     <form id="byConsumes" class="saveImageForm" action="/spring-mvc-showcase/mapping/saveImage" method="post">

	             <p>
						<video id="video" width="400" height="400" controls="controls" autoplay="autoplay">

						 <source src="/spring-mvc-showcase/resources/img/mov_bbb.ogg" type="video/ogg"/>
						 </video>
						 <canvas id="canvas" width="300" height="300"></canvas>
                 </p>
				 <p>
					 <button id="snap">TakePhoto</button>
	            <input id="byConsumesSubmit" type="submit" value="SaveImages" />
<!-- 					  <button id="sendBtn">SavePhoto</button> -->
			     </p>
				</form>


		<div id="saveStatus">

		</div>
	</div>
</div>
<script type="text/javascript" src="<c:url value="/resources/jquery/1.6/jquery.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryform/2.8/jquery.form.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.core.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.widget.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.tabs.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/json2.js" />"></script>
<script>
	MvcUtil = {};
	MvcUtil.showSuccessResponse = function (text, element) {
		MvcUtil.showResponse("success", text, element);
	};
	MvcUtil.showErrorResponse = function showErrorResponse(text, element) {
		MvcUtil.showResponse("error", text, element);
	};
	MvcUtil.showResponse = function(type, text, element) {
		var responseElementId = element.attr("id") + "Response";
		var responseElement = $("#" + responseElementId);
		if (responseElement.length == 0) {
			responseElement = $('<span id="' + responseElementId + '" class="' + type + '" style="display:none">' + text + '</span>').insertAfter(element);
		} else {
			responseElement.replaceWith('<span id="' + responseElementId + '" class="' + type + '" style="display:none">' + text + '</span>');
			responseElement = $("#" + responseElementId);
		}
		responseElement.fadeIn("slow");
	};
	MvcUtil.xmlencode = function(xml) {
		//for IE
		var text;
		if (window.ActiveXObject) {
		    text = xml.xml;
		 }
		// for Mozilla, Firefox, Opera, etc.
		else {
		   text = (new XMLSerializer()).serializeToString(xml);
		}
		    return text.replace(/\&/g,'&'+'amp;').replace(/</g,'&'+'lt;')
	        .replace(/>/g,'&'+'gt;').replace(/\'/g,'&'+'apos;').replace(/\"/g,'&'+'quot;');
	};
</script>
<script type="text/javascript">
$(document).ready(function() {
	$("#tabs").tabs();

	// Append '#' to the window location so "Back" returns to the selected tab
	// after a redirect or a full page refresh (e.g. Views tab).

	// However, note this general disclaimer about going back to previous tabs:
	// http://docs.jquery.com/UI/API/1.8/Tabs#Back_button_and_bookmarking

	$("#tabs").bind("tabsselect", function(event, ui) { window.location.hash = ui.tab.hash; });


	$("a.textLink").click(function(){
		var link = $(this);
		$.ajax({ url: link.attr("href"), dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("a.utf8TextLink").click(function(){
		var link = $(this);
		$.ajax({ url: link.attr("href"), dataType: "text", beforeSend: function(req) { req.setRequestHeader("Accept", "text/plain;charset=UTF-8"); }, success: function(text) { MvcUtil.showSuccessResponse(text, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("form.textForm").submit(function(event) {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "foo", contentType: "text/plain", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#readForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "foo=bar&fruit=apple", contentType: "application/x-www-form-urlencoded", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeForm").click(function() {
		var link = $(this);
		$.ajax({ url: this.href, dataType: "text", beforeSend: function(req) { req.setRequestHeader("Accept", "application/x-www-form-urlencoded"); }, success: function(form) { MvcUtil.showSuccessResponse(form, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("form.readXmlForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><javaBean><foo>bar</foo><fruit>apple</fruit></javaBean>", contentType: "application/xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("a.writeXmlLink").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				if (!this.url.match(/\.xml$/)) {
					req.setRequestHeader("Accept", "application/xml");
				}
			},
			success: function(xml) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(xml), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("form.readJsonForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		var data = form.hasClass("invalid") ?
				"{ \"foo\": \"bar\" }" :
				"{ \"foo\": \"bar\", \"fruit\": \"apple\" }";
		$.ajax({ type: "POST", url: form.attr("action"), data: data, contentType: "application/json", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("a.writeJsonLink").click(function() {
		var link = $(this);
		$.ajax({ url: this.href,
			beforeSend: function(req) {
				if (!this.url.match(/\.json$/)) {
					req.setRequestHeader("Accept", "application/json");
				}
			},
			success: function(json) {
				MvcUtil.showSuccessResponse(JSON.stringify(json), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}});
		return false;
	});

	$("#readAtom").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: '<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"><title>My Atom feed</title></feed>', contentType: "application/atom+xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeAtom").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				req.setRequestHeader("Accept", "application/atom+xml");
			},
			success: function(feed) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(feed), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("#readRss").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: '<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"><channel><title>My RSS feed</title></channel></rss>', contentType: "application/rss+xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeRss").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				req.setRequestHeader("Accept", "application/rss+xml");
			},
			success: function(feed) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(feed), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("#byHeader").click(function(){
		var link = $(this);
		$.ajax({ url: this.href, dataType: "text", beforeSend: function(req) { req.setRequestHeader("FooHeader", "foo"); }, success: function(form) { MvcUtil.showSuccessResponse(form, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

		window.addEventListener("DOMContentLoaded", function() {

 			// Grab elements, create settings, etc.
 			var canvas = document.getElementById("canvas"),
 				context = canvas.getContext("2d"),
 				video = document.getElementById("video"),
 				videoObj = { "video": true },
 				errBack = function(error) {
 					console.log("Video capture error: ", error.code);
 				};
		 		document.getElementById("snap").addEventListener("click", function() {

		 			context.drawImage(video, 0, 0, 300, 300);


		 		});

				$("form.saveImageForm").submit(function() {
					var form = $(this);
				    var image = canvas.toDataURL("image/png");
				    image = image.replace('data:image/png;base64,', '');
					$.ajax({ type: "POST", url: form.attr("action"), data: '{ "imageData" : "' + image + '" }', contentType: "application/json", dataType: "json", success: function(text) { MvcUtil.showSuccessResponse(text, $('#saveStatus')); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, $('#saveStatus')); }});
					return false;
				});

// 				$('#sendBtn').live('click', function () {
// 				    var image = canvas.toDataURL("image/png");
// 				    image = image.replace('data:image/png;base64,', '');
//                     alert("ImageValue"+image);
// 				    $.ajax({
// 				        type: 'POST',
// 				        url: '/spring-mvc-showcase/mapping/saveImage',
// 				        data: '{ "imageData" : "' + image + '" }',
// 				        contentType: 'application/json; charset=utf-8',
// 				        dataType: 'json',
// 				        success: function (msg) {
// 				            alert(msg);
//				           MvcUtil.showSuccessResponse("Saved Successfully",$('#saveStatus'));
// 				        },
// 				        error: function(xhr) {
// 				        	MvcUtil.showErrorResponse(xhr.responseText, $('#saveStatus'));
// 				            alert("Error"+xhr.responseText);
// 				        }
// 				    });
// 				});


 		}, false);



	// Include CSRF token as header in JQuery AJAX requests
	// See http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#csrf-include-csrf-token-ajax
	var token = $("meta[name='_csrf']").attr("content");
	var header = $("meta[name='_csrf_header']").attr("content");
	$(document).ajaxSend(function(e, xhr, options) {
		xhr.setRequestHeader(header, token);
	});

});
</script>
</body>
</html>
HTML5 CameraPage
<!DOCTYPE HTML>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html manifest="/spring-mvc-showcase/resources/cache.manifest">
<head>
	<title>spring-mvc-showcase</title>
	<link href="<c:url value="/resources/form.css" />" rel="stylesheet"  type="text/css" />
	<link href="<c:url value="/resources/jqueryui/1.8/themes/base/jquery.ui.all.css" />" rel="stylesheet" type="text/css"/>

	<!--
		Used for including CSRF token in JSON requests
		Also see bottom of this file for adding CSRF token to JQuery AJAX requests
	-->
	<meta name="_csrf" content="${_csrf.token}"/>
	<meta name="_csrf_header" content="${_csrf.headerName}"/>
</head>
<body>
<h1><a href="<c:url value="/" />">spring-mvc-showcase</a></h1>
<p>Recommended: Using a Web Developer tool such a Firebug to inspect the client/server interaction</p>
<div id="tabs">
	<ul>
		<li><a href="#simple">Simple</a></li>
		<li><a href="#mapping">Request Mapping</a></li>
		<li><a href="#data">Request Data</a></li>
		<li><a href="#responses">Response Writing</a></li>
		<li><a href="#messageconverters">Message Converters</a></li>
		<li><a href="#views">View Rendering</a></li>
		<li><a href="#convert">Type Conversion</a></li>
		<li><a href="#validation">Validation</a></li>
		<li><a href="<c:url value="/form" />" title="forms">Forms</a></li>
		<li><a href="<c:url value="/fileupload" />" title="fileupload">File Upload</a></li>
		<li><a href="#exceptions">Exception Handling</a></li>
		<li><a href="#redirect">Redirecting</a></li>
        <li><a href="#async">Async Requests</a></li>
         <li><a href="#Camera">Camere</a></li>
    </ul>
    <div id="simple">
		<h2>Simple</h2>
		<p>
			See the <code>org.springframework.samples.mvc.simple</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="simpleLink" class="textLink" href="<c:url value="/simple" />">GET /simple</a>
			</li>
			<li>
				<a id="simpleRevisited" class="textLink" href="<c:url value="/simple/revisited" />">GET /simple/revisited</a>
			</li>
		</ul>
	</div>
	<div id="mapping">
		<h2>Request Mapping</h2>
		<p>
			See the <code>org.springframework.samples.mvc.mapping</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="byPath" class="textLink" href="<c:url value="/mapping/path" />">By path</a>
			</li>
			<li>
				<a id="byPathPattern" class="textLink" href="<c:url value="/mapping/path/wildcard" />">By path pattern</a>
			</li>
			<li>
				<a id="byMethod" class="textLink" href="<c:url value="/mapping/method" />">By path and method</a>
			</li>
			<li>
				<a id="byParameter" class="textLink" href="<c:url value="/mapping/parameter?foo=bar" />">By path, method, and presence of parameter</a>
			</li>
			<li>
				<a id="byNotParameter" class="textLink" href="<c:url value="/mapping/parameter" />">By path, method, and not presence of parameter</a>
			</li>
			<li>
				<a id="byHeader" href="<c:url value="/mapping/header" />">By presence of header</a>
			</li>
			<li>
				<a id="byHeaderNegation" class="textLink" href="<c:url value="/mapping/header" />">By absence of header</a>
			</li>
			<li>
				<form id="byConsumes" class="readJsonForm" action="<c:url value="/mapping/consumes" />" method="post">
					<input id="byConsumesSubmit" type="submit" value="By consumes" />
				</form>
			</li>
			<li>
				<a id="byProducesAcceptJson" class="writeJsonLink" href="<c:url value="/mapping/produces" />">By produces via Accept=application/json</a>
			</li>
            <li>
                <a id="byProducesAcceptXml" class="writeXmlLink" href="<c:url value="/mapping/produces" />">By produces via Accept=appilcation/xml</a>
            </li>
            <li>
              <a id="byProducesJsonExt" class="writeJsonLink" href="<c:url value="/mapping/produces.json" />">By produces via ".json"</a>
            </li>
            <li>
                <a id="byProducesXmlExt" class="writeXmlLink" href="<c:url value="/mapping/produces.xml" />">By produces via ".xml"</a>
            </li>
		</ul>
	</div>
	<div id="data">
		<h2>Request Data</h2>
		<p>
			See the <code>org.springframework.samples.mvc.data</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="param" class="textLink" href="<c:url value="/data/param?foo=bar" />">Query parameter</a>
			</li>
			<li>
				<a id="group" class="textLink" href="<c:url value="/data/group?param1=foo¶m2=bar¶m3=baz" />">Group of query parameters</a>
			</li>
			<li>
				<a id="var" class="textLink" href="<c:url value="/data/path/foo" />">Path variable</a>
			</li>
			<li>
				<a id="matrixVar" class="textLink" href="<c:url value="/data/matrixvars;foo=bar/simple" />">Matrix variable</a>
			</li>
			<li>
				<a id="matrixVarMultiple" class="textLink" href="<c:url value="/data/matrixvars;foo=bar1/multiple;foo=bar2" />">Matrix variables (multiple)</a>
			</li>
			<li>
				<a id="header" class="textLink" href="<c:url value="/data/header" />">Header</a>
			</li>
			<li>
				<form id="requestBody" class="textForm" action="<c:url value="/data/body" />" method="post">
					<input id="requestBodySubmit" type="submit" value="Request Body" />
				</form>
			</li>
			<li>
				<form id="requestBodyAndHeaders" class="textForm" action="<c:url value="/data/entity" />" method="post">
					<input id="requestBodyAndHeadersSubmit" type="submit" value="Request Body and Headers" />
				</form>
			</li>
		</ul>
		<div id="standardArgs">
			<h3>Standard Resolvable Web Arguments</h3>
			<ul>
				<li>
					<a id="request" class="textLink" href="<c:url value="/data/standard/request" />">Request arguments</a>
				</li>
				<li>
					<form id="requestReader" class="textForm" action="<c:url value="/data/standard/request/reader" />" method="post">
						<input id="requestReaderSubmit" type="submit" value="Request Reader" />
					</form>
				</li>
				<li>
					<form id="requestIs" class="textForm" action="<c:url value="/data/standard/request/is" />" method="post">
						<input id="requestIsSubmit" type="submit" value="Request InputStream" />
					</form>
				</li>
				<li>
					<a id="response" class="textLink" href="<c:url value="/data/standard/response" />">Response arguments</a>
				</li>
				<li>
					<a id="writer" class="textLink" href="<c:url value="/data/standard/response/writer" />">Response Writer</a>
				</li>
				<li>
					<a id="os" class="textLink" href="<c:url value="/data/standard/response/os" />">Response OutputStream</a>
				</li>
				<li>
					<a id="session" class="textLink" href="<c:url value="/data/standard/session" />">Session</a>
				</li>
			</ul>
		</div>
		<div id="customArgs">
			<h3>Custom Resolvable Web Arguments</h3>
			<ul>
				<li>
					<a id="customArg" class="textLink" href="<c:url value="/data/custom" />">Custom</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="responses">
		<h2>Response Writing</h2>
		<p>
			See the <code>org.springframework.samples.mvc.response</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="responseBody" class="textLink" href="<c:url value="/response/annotation" />">@ResponseBody</a>
			</li>
			<li>
				<a id="responseCharsetAccept" class="utf8TextLink" href="<c:url value="/response/charset/accept" />">@ResponseBody (UTF-8 charset requested)</a>
			</li>
			<li>
				<a id="responseCharsetProduce" class="textLink" href="<c:url value="/response/charset/produce" />">@ResponseBody (UTF-8 charset produced)</a>
			</li>
			<li>
				<a id="responseEntityStatus" class="textLink" href="<c:url value="/response/entity/status" />">ResponseEntity (custom status)</a>
			</li>
			<li>
				<a id="responseEntityHeaders" class="textLink" href="<c:url value="/response/entity/headers" />">ResponseEntity (custom headers)</a>
			</li>
		</ul>
	</div>
	<div id="messageconverters">
		<h2>Http Message Converters</h2>
		<p>
			See the <code>org.springframework.samples.mvc.messageconverters</code> package for the @Controller code
		</p>
		<div id="stringMessageConverter">
			<h3>StringHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readString" class="textForm" action="<c:url value="/messageconverters/string" />" method="post">
						<input id="readStringSubmit" type="submit" value="Read a String" />
					</form>
				</li>
				<li>
					<a id="writeString" class="textLink" href="<c:url value="/messageconverters/string" />">Write a String</a>
				</li>
			</ul>
			<h3>FormHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readForm" action="<c:url value="/messageconverters/form" />" method="post">
						<input id="readFormSubmit" type="submit" value="Read Form Data" />
					</form>
				</li>
				<li>
					<a id="writeForm" href="<c:url value="/messageconverters/form" />">Write Form Data</a>
				</li>
			</ul>
			<h3>Jaxb2RootElementHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readXml" class="readXmlForm" action="<c:url value="/messageconverters/xml" />" method="post">
						<input id="readXmlSubmit" type="submit" value="Read XML" />
					</form>
				</li>
				<li>
					<a id="writeXmlAccept" class="writeXmlLink" href="<c:url value="/messageconverters/xml" />">Write XML via Accept=application/xml</a>
				</li>
                <li>
                    <a id="writeXmlExt" class="writeXmlLink" href="<c:url value="/messageconverters/xml.xml" />">Write XML via ".xml"</a>
                </li>
			</ul>
			<h3>MappingJacksonHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readJson" class="readJsonForm" action="<c:url value="/messageconverters/json" />" method="post">
						<input id="readJsonSubmit" type="submit" value="Read JSON" />
					</form>
				</li>
				<li>
					<form id="readJsonInvalid" class="readJsonForm invalid" action="<c:url value="/messageconverters/json" />" method="post">
						<input id="readInvalidJsonSubmit" type="submit" value="Read invalid JSON (400 response code)" />
					</form>
				</li>
				<li>
					<a id="writeJsonAccept" class="writeJsonLink" href="<c:url value="/messageconverters/json" />">Write JSON via Accept=application/json</a>
				</li>
                <li>
                    <a id="writeJsonExt" class="writeJsonLink" href="<c:url value="/messageconverters/json.json" />">Write JSON via ".json"</a>
                </li>
			</ul>
			<h3>AtomFeedHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readAtom" action="<c:url value="/messageconverters/atom" />" method="post">
						<input id="readAtomSubmit" type="submit" value="Read Atom" />
					</form>
				</li>
				<li>
					<a id="writeAtom" href="<c:url value="/messageconverters/atom" />">Write Atom</a>
				</li>
			</ul>
			<h3>RssChannelHttpMessageConverter</h3>
			<ul>
				<li>
					<form id="readRss" action="<c:url value="/messageconverters/rss" />" method="post">
						<input id="readRssSubmit" type="submit" value="Read Rss" />
					</form>
				</li>
				<li>
					<a id="writeRss" href="<c:url value="/messageconverters/rss" />">Write Rss</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="views">
		<h2>View Rendering</h2>
		<p>
			See the <code>org.springframework.samples.mvc.views</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a href="<c:url value="/views/html" />">HTML generated by JSP template</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/viewName" />">DefaultRequestToViewNameTranslator convention</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/pathVariables/bar/apple" />">Using path variables in a view template</a>
			</li>
		</ul>
		<ul>
			<li>
				<a href="<c:url value="/views/dataBinding/bar/apple" />">Data binding with URI variables</a>
			</li>
		</ul>
	</div>
	<div id="convert">
		<h2>Type Conversion</h2>
		<p>
			See the <code>org.springframework.samples.mvc.convert</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="primitive" class="textLink" href="<c:url value="/convert/primitive?value=3" />">Primitive</a>
			</li>
			<li>
				<a id="date" class="textLink" href="<c:url value="/convert/date/2010-07-04" />">Date</a>
			</li>
			<li>
				<a id="collection" class="textLink" href="<c:url value="/convert/collection?values=1&values=2&values=3&values=4&values=5" />">Collection 1 (multi-value parameter)</a>
			</li>
			<li>
				<a id="collection2" class="textLink" href="<c:url value="/convert/collection?values=1,2,3,4,5" />">Collection 2 (single comma-delimited parameter value)</a>
			</li>
			<li>
				<a id="formattedCollection" class="textLink" href="<c:url value="/convert/formattedCollection?values=2010-07-04,2011-07-04" />">@Formatted Collection</a>
			</li>
			<li>
				<a id="valueObject" class="textLink" href="<c:url value="/convert/value?value=123456789" />">Custom Value Object</a>
			</li>
			<li>
				<a id="customConverter" class="textLink" href="<c:url value="/convert/custom?value=123-45-6789" />">Custom Converter</a>
			</li>
		</ul>
		<div id="convert-bean">
			<h3>JavaBean Property Binding</h3>
			<ul>
				<li>
					<a id="primitiveProp" class="textLink" href="<c:url value="/convert/bean?primitive=3" />">Primitive</a>
				</li>
				<li>
					<a id="dateProp" class="textLink" href="<c:url value="/convert/bean?date=2010-07-04" />">Date</a>
				</li>
				<li>
					<a id="maskedProp" class="textLink" href="<c:url value="/convert/bean?masked=(205) 333-3333" />">Masked</a>
				</li>
				<li>
					<a id="listProp" class="textLink" href="<c:url value="/convert/bean?list[0]=1&list[1]=2&list[2]=3" />">List Elements</a>
				</li>
				<li>
					<a id="formattedListProp" class="textLink" href="<c:url value="/convert/bean?formattedList[0]=2010-07-04&formattedList[1]=2011-07-04" />">@Formatted List Elements</a>
				</li>
				<li>
					<a id="mapProp" class="textLink" href="<c:url value="/convert/bean?map[0]=apple&map[1]=pear" />">Map Elements</a>
				</li>
				<li>
					<a id="nestedProp" class="textLink" href="<c:url value="/convert/bean?nested.foo=bar&nested.list[0].foo=baz&nested.map[key].list[0].foo=bip" />">Nested</a>
				</li>
			</ul>
		</div>
	</div>
	<div id="validation">
		<h2>Validation</h2>
		<p>
			See the <code>org.springframework.samples.mvc.validation</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="validateNoErrors" class="textLink" href="<c:url value="/validate?number=3&date=2029-07-04" />">Validate, no errors</a>
			</li>
			<li>
				<a id="validateErrors" class="textLink" href="<c:url value="/validate?number=3&date=2010-07-01" />">Validate, errors</a>
			</li>
		</ul>
	</div>
	<div id="exceptions">
		<h2>Exception Handling</h2>
		<p>
			See the <code>org.springframework.samples.mvc.exceptions</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a id="exception" class="textLink" href="<c:url value="/exception" />">@ExceptionHandler in Controller</a>
			</li>
			<li>
				<a id="globalException" class="textLink" href="<c:url value="/global-exception" />">Global @ExceptionHandler</a>
			</li>
		</ul>
	</div>
	<div id="redirect">
		<h2>Redirecting</h2>
		<p>
			See the <code>org.springframework.samples.mvc.redirect</code> package for the @Controller code
		</p>
		<ul>
			<li>
				<a href="<c:url value="/redirect/uriTemplate" />">URI Template String</a>
			</li>
			<li>
				<a href="<c:url value="/redirect/uriComponentsBuilder" />">UriComponentsBuilder</a>
			</li>
		</ul>
	</div>
	<div id="async">
		<h2>Async Requests</h2>
		<p>
			<em>Note: Links may take 2-3 seconds to complete.</em>
		</p>
		<p>
		  See the <code>org.springframework.samples.mvc.async</code> package for the @Controller code.
		</p>
		<ul>
		<li>
			<a id="callableResponseBodyLink" class="textLink"
				href="<c:url value="/async/callable/response-body" />">GET /async/callable/response-body</a>
		</li>
		<li>
			<a id="callableViewLink" class="textLink"
				href="<c:url value="/async/callable/view" />">GET /async/callable/view</a>
		</li>
		<li>
			<a id="callableExceptionLink" class="textLink"
				href="<c:url value="/async/callable/exception" />">GET /async/callable/exception</a>
		</li>
		<li>
			<a id="callableUnhandledExceptionLink" class="textLink"
				href="<c:url value="/async/callable/exception?handled=false" />">GET /async/callable/exception?handled=false</a>
				(500 Error expected)
		</li>
		<li>
			<a id="callableCustomTimeoutLink" class="textLink"
				href="<c:url value="/async/callable/custom-timeout-handling" />">GET /async/callable/custom-timeout-handling</a>
		</li>
		<li>
			<a id="deferredResultSuccessLink" class="textLink"
				href="<c:url value="/async/deferred-result/response-body" />">GET /async/deferred-result/response-body</a>
		</li>
		<li>
			<a id="deferredResultModelAndViewLink" class="textLink"
				href="<c:url value="/async/deferred-result/model-and-view" />">GET /async/deferred-result/model-and-view</a>
		</li>
		<li>
			<a id="deferredResultErrorLink" class="textLink"
				href="<c:url value="/async/deferred-result/exception" />">GET /async/deferred-result/exception</a>
		</li>
		<li>
			<a id="deferredResultTimeoutValueLink" class="textLink"
				href="<c:url value="/async/deferred-result/timeout-value" />">GET /async/deferred-result/timeout-value</a>
		</li>
		</ul>
	</div>


		<div id="Camera">
		<h2>Camera Take Photos</h2>
		<p>

		</p>
		<p>
			<video id="video" width="400" height="400" controls="controls" autoplay="autoplay">

			  <source src="/spring-mvc-showcase/resources/img/mov_bbb.ogg" type="video/ogg"/>
			</video>
			  <canvas id="canvas" width="300" height="300"></canvas>
       </p>
		<p>
		    <button id="snap">TakePhoto</button>
		    <button id="sendBtn">SavePhoto</button>

		</p>
		<div id="saveStatus">

		</div>
	</div>
</div>
<script type="text/javascript" src="<c:url value="/resources/jquery/1.6/jquery.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryform/2.8/jquery.form.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.core.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.widget.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/jqueryui/1.8/jquery.ui.tabs.js" />"></script>
<script type="text/javascript" src="<c:url value="/resources/json2.js" />"></script>
<script>
	MvcUtil = {};
	MvcUtil.showSuccessResponse = function (text, element) {
		MvcUtil.showResponse("success", text, element);
	};
	MvcUtil.showErrorResponse = function showErrorResponse(text, element) {
		MvcUtil.showResponse("error", text, element);
	};
	MvcUtil.showResponse = function(type, text, element) {
		var responseElementId = element.attr("id") + "Response";
		var responseElement = $("#" + responseElementId);
		if (responseElement.length == 0) {
			responseElement = $('<span id="' + responseElementId + '" class="' + type + '" style="display:none">' + text + '</span>').insertAfter(element);
		} else {
			responseElement.replaceWith('<span id="' + responseElementId + '" class="' + type + '" style="display:none">' + text + '</span>');
			responseElement = $("#" + responseElementId);
		}
		responseElement.fadeIn("slow");
	};
	MvcUtil.xmlencode = function(xml) {
		//for IE
		var text;
		if (window.ActiveXObject) {
		    text = xml.xml;
		 }
		// for Mozilla, Firefox, Opera, etc.
		else {
		   text = (new XMLSerializer()).serializeToString(xml);
		}
		    return text.replace(/\&/g,'&'+'amp;').replace(/</g,'&'+'lt;')
	        .replace(/>/g,'&'+'gt;').replace(/\'/g,'&'+'apos;').replace(/\"/g,'&'+'quot;');
	};
</script>
<script type="text/javascript">
$(document).ready(function() {
	$("#tabs").tabs();

	// Append '#' to the window location so "Back" returns to the selected tab
	// after a redirect or a full page refresh (e.g. Views tab).

	// However, note this general disclaimer about going back to previous tabs:
	// http://docs.jquery.com/UI/API/1.8/Tabs#Back_button_and_bookmarking

	$("#tabs").bind("tabsselect", function(event, ui) { window.location.hash = ui.tab.hash; });


	$("a.textLink").click(function(){
		var link = $(this);
		$.ajax({ url: link.attr("href"), dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("a.utf8TextLink").click(function(){
		var link = $(this);
		$.ajax({ url: link.attr("href"), dataType: "text", beforeSend: function(req) { req.setRequestHeader("Accept", "text/plain;charset=UTF-8"); }, success: function(text) { MvcUtil.showSuccessResponse(text, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("form.textForm").submit(function(event) {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "foo", contentType: "text/plain", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#readForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "foo=bar&fruit=apple", contentType: "application/x-www-form-urlencoded", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeForm").click(function() {
		var link = $(this);
		$.ajax({ url: this.href, dataType: "text", beforeSend: function(req) { req.setRequestHeader("Accept", "application/x-www-form-urlencoded"); }, success: function(form) { MvcUtil.showSuccessResponse(form, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

	$("form.readXmlForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><javaBean><foo>bar</foo><fruit>apple</fruit></javaBean>", contentType: "application/xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("a.writeXmlLink").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				if (!this.url.match(/\.xml$/)) {
					req.setRequestHeader("Accept", "application/xml");
				}
			},
			success: function(xml) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(xml), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("form.readJsonForm").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		var data = form.hasClass("invalid") ?
				"{ \"foo\": \"bar\" }" :
				"{ \"foo\": \"bar\", \"fruit\": \"apple\" }";
		$.ajax({ type: "POST", url: form.attr("action"), data: data, contentType: "application/json", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("a.writeJsonLink").click(function() {
		var link = $(this);
		$.ajax({ url: this.href,
			beforeSend: function(req) {
				if (!this.url.match(/\.json$/)) {
					req.setRequestHeader("Accept", "application/json");
				}
			},
			success: function(json) {
				MvcUtil.showSuccessResponse(JSON.stringify(json), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}});
		return false;
	});

	$("#readAtom").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: '<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom"><title>My Atom feed</title></feed>', contentType: "application/atom+xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeAtom").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				req.setRequestHeader("Accept", "application/atom+xml");
			},
			success: function(feed) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(feed), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("#readRss").submit(function() {
		var form = $(this);
		var button = form.children(":first");
		$.ajax({ type: "POST", url: form.attr("action"), data: '<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"><channel><title>My RSS feed</title></channel></rss>', contentType: "application/rss+xml", dataType: "text", success: function(text) { MvcUtil.showSuccessResponse(text, button); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, button); }});
		return false;
	});

	$("#writeRss").click(function() {
		var link = $(this);
		$.ajax({ url: link.attr("href"),
			beforeSend: function(req) {
				req.setRequestHeader("Accept", "application/rss+xml");
			},
			success: function(feed) {
				MvcUtil.showSuccessResponse(MvcUtil.xmlencode(feed), link);
			},
			error: function(xhr) {
				MvcUtil.showErrorResponse(xhr.responseText, link);
			}
		});
		return false;
	});

	$("#byHeader").click(function(){
		var link = $(this);
		$.ajax({ url: this.href, dataType: "text", beforeSend: function(req) { req.setRequestHeader("FooHeader", "foo"); }, success: function(form) { MvcUtil.showSuccessResponse(form, link); }, error: function(xhr) { MvcUtil.showErrorResponse(xhr.responseText, link); }});
		return false;
	});

		window.addEventListener("DOMContentLoaded", function() {

 			// Grab elements, create settings, etc.
 			var canvas = document.getElementById("canvas"),
 				context = canvas.getContext("2d"),
 				video = document.getElementById("video"),
 				videoObj = { "video": true },
 				errBack = function(error) {
 					console.log("Video capture error: ", error.code);
 				};
		 		document.getElementById("snap").addEventListener("click", function() {

		 			context.drawImage(video, 0, 0, 300, 300);


		 		});
				$('#sendBtn').live('click', function () {
				    var image = canvas.toDataURL("image/png");
				    image = image.replace('data:image/png;base64,', '');
                    alert("ImageValue"+image);
				    $.ajax({
				        type: 'POST',
				        url: '/spring-mvc-showcase//mapping/saveImage',
				        data: '{ "imageData" : "' + image + '" }',
				        contentType: 'application/json; charset=utf-8',
				        dataType: 'json',
				        success: function (msg) {
				            alert('Image sent!');
				            MvcUtil.showSuccessResponse("Saved Successfully",$('#saveStatus'));
				        }
				    });
				});


 		}, false);



	// Include CSRF token as header in JQuery AJAX requests
	// See http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#csrf-include-csrf-token-ajax
	var token = $("meta[name='_csrf']").attr("content");
	var header = $("meta[name='_csrf_header']").attr("content");
	$(document).ajaxSend(function(e, xhr, options) {
		xhr.setRequestHeader(header, token);
	});

});
</script>
</body>
</html>
HTML5 Camera
Java:
	@RequestMapping(value="/mapping/saveImage", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
	public @ResponseBody String saveImage(@RequestBody JavaBean javaBean) {

	    FileOutputStream fs = null;
	    //ByteArrayOutputStream outStr = null;
		try {
			fs = new FileOutputStream("C:\\image.png", true);

		    //outStr = new ByteArrayOutputStream();

		    byte[] data = org.apache.tomcat.util.codec.binary.Base64.decodeBase64(javaBean.getImageData());
		    //outStr.write(data);
		    fs.write(data);

		    //outStr.close();
		    fs.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch(Exception e){
			e.printStackTrace();
		}
		finally{
			try{
			     fs.close();
			}catch(IOException e){
				e.printStackTrace();
			}
		}

		return "Mapped by path + method + consumable media type (javaBean '" + javaBean + "')";
	}
MD5 SHA256,SHA512 with random salt
MD5  SHA256,SHA512   with random salt   to encrypt the password
Global site tag (gtag.js) - Google Analytics