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
|