javaxt.http.servlet.FormValue Maven / Gradle / Ivy
package javaxt.http.servlet;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
//******************************************************************************
//** FormValue
//******************************************************************************
/**
* Used to retrieve the value associated with a form input found in the body of
* an http request. Form values are retrieved on-demand.
*
******************************************************************************/
public class FormValue {
private FormInput input;
private byte[] value = null;
private final static byte[] CRLF = new byte[] { '\r', '\n' };
private FormInputStream formInputStream;
// **************************************************************************
// ** Constructor
// **************************************************************************
/** Creates a new instance of Value. */
protected FormValue(FormInput input) {
this.input = input;
formInputStream = new FormInputStream();
}
// **************************************************************************
// ** toInteger
// **************************************************************************
/**
* Returns the value as an integer. Returns a null if there was a problem
* converting the value to an integer or if the value is null.
*/
public Integer toInteger() {
if (isNull())
return null;
try {
return Integer.valueOf(this.toString());
} catch (Exception e) {
return null;
}
}
// **************************************************************************
// ** toShort
// **************************************************************************
/**
* Returns the value as a short. Returns a null if there was a problem
* converting the value to a short or if the value is null.
*/
public Short toShort() {
if (isNull())
return null;
try {
return Short.valueOf(this.toString());
} catch (Exception e) {
return null;
}
}
// **************************************************************************
// ** toDouble
// **************************************************************************
/**
* Returns the value as a double. Returns a null if there was a problem
* converting the value to a double or if the value is null.
*/
public Double toDouble() {
if (isNull())
return null;
try {
return Double.valueOf(this.toString());
} catch (Exception e) {
return null;
}
}
// **************************************************************************
// ** toLong
// **************************************************************************
/**
* Returns the value as a long. Returns a null if there was a problem
* converting the value to a long or if the value is null.
*/
public Long toLong() {
if (isNull())
return null;
try {
return Long.valueOf(this.toString());
} catch (Exception e) {
return null;
}
}
// **************************************************************************
// ** toBigDecimal
// **************************************************************************
/**
* Returns the value as a BigDecimal. Returns a null if there was a problem
* converting the value to a BigDecimal or if the value is null.
*/
public java.math.BigDecimal toBigDecimal() {
if (isNull())
return null;
try {
return java.math.BigDecimal.valueOf(toDouble());
} catch (Exception e) {
return null;
}
}
// **************************************************************************
// ** toByteArray
// **************************************************************************
/**
* Returns the value as a byte array.
*/
public byte[] toByteArray() {
return getByteArray();
}
// **************************************************************************
// ** toBoolean
// **************************************************************************
/**
* Returns the value as a boolean. Performs a case insensitive comparison
* between string values representing known booleans (e.g. "true", "false",
* "yes", "no", "t", "f", "y", "n", "1", "0").
*/
public Boolean toBoolean() {
if (isNull())
return null;
String value = this.toString().toLowerCase().trim();
if (value.equals("true"))
return true;
if (value.equals("false"))
return false;
if (value.equals("yes"))
return true;
if (value.equals("no"))
return false;
if (value.equals("y"))
return true;
if (value.equals("n"))
return false;
if (value.equals("t"))
return true;
if (value.equals("f"))
return false;
if (value.equals("1"))
return true;
if (value.equals("0"))
return false;
return null;
}
// **************************************************************************
// ** isNumeric
// **************************************************************************
/** Used to determine if the value is numeric. */
public boolean isNumeric() {
if (isNull())
return false;
if (toDouble() == null)
return false;
else
return true;
}
// **************************************************************************
// ** isNull
// **************************************************************************
/** Used to determine whether the value is null. */
public boolean isNull() {
return getByteArray().length < 1;
}
// **************************************************************************
// ** toString
// **************************************************************************
/**
* Returns the value as a string. Automatically decodes the data if it is
* url encoded.
*/
@Override
public String toString() {
String value = new String(getByteArray());
if (input.getBoundary().equals("&")) {
// Decode the value
try {
value = java.net.URLDecoder.decode(value, "UTF-8");
} catch (Exception e) {
// Try to decode the string manually
String find[] = new String[] { "%2C", "%2F", "%3A" };
String replace[] = new String[] { ",", "/", ":" };
for (int i = 0; i < find.length; i++) {
value = value.replace(find[i], replace[i]);
}
}
}
return value;
}
// **************************************************************************
// ** toFile
// **************************************************************************
/**
* Used to save a form value to a file. This is particularly useful when
* processing large binary data (e.g. uploaded file).
*/
public boolean toFile(java.io.File file) {
try {
if (value == null) {
int bufferSize = 2048;
if (!file.getParentFile().exists())
file.getParentFile().mkdirs();
FileOutputStream output = new FileOutputStream(file);
final ReadableByteChannel inputChannel = Channels.newChannel(getInputStream());
final WritableByteChannel outputChannel = Channels.newChannel(output);
final java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocateDirect(bufferSize);
while (inputChannel.read(buffer) != -1) {
buffer.flip();
outputChannel.write(buffer);
buffer.compact();
}
buffer.flip();
while (buffer.hasRemaining()) {
outputChannel.write(buffer);
}
inputChannel.close();
outputChannel.close();
// file.setLastModified(File.lastModified());
return true;
} else {
FileOutputStream output = new FileOutputStream(file);
output.write(value);
output.close();
return true;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
// **************************************************************************
// ** getInputStream
// **************************************************************************
/**
* Returns a java.io.InputStream used to read raw bytes associated with the
* form value. This is particularly useful when processing large values
* (e.g. uploaded file).
*/
public java.io.InputStream getInputStream() {
return formInputStream;
}
// **************************************************************************
// ** readFully
// **************************************************************************
/**
* Reads any remaining bytes associated with this input. This is extremely
* important if we're going to give users access to the raw InputStream.
*/
protected void readFully() {
if (value != null)
return;
try {
java.io.InputStream inputStream = this.getInputStream();
while (inputStream.read() != -1) {
}
} catch (Exception e) {
}
}
// **************************************************************************
// ** getByteArray
// **************************************************************************
/**
* Used to read data from the client into a byte array. The byte array is
* then persisted as a class variable.
*/
private byte[] getByteArray() {
if (value == null) {
ByteArrayOutputStream bas = new ByteArrayOutputStream();
java.io.InputStream inputStream = this.getInputStream();
try {
int x = 0;
while ((x = inputStream.read()) != -1) {
bas.write(x);
}
value = bas.toByteArray();
} catch (Exception e) {
e.printStackTrace();
value = new byte[0]; // <-- is this a good idea??
}
}
return value;
}
// **************************************************************************
// ** FormInputStream
// **************************************************************************
/**
* Simple implementation of a java.io.InputStream used to read bytes
* associated with a form value.
*/
private class FormInputStream extends java.io.InputStream {
private byte[] cache;
private String boundary;
private ServletInputStream is;
public FormInputStream() {
boundary = input.getBoundary();
is = input.getInputStream();
cache = new byte[0];
}
@Override
public int read() throws IOException {
if (input.isFullyRead())
return -1;
if (boundary.equals("&")) { // Content-Type:
// application/x-www-form-urlencoded
int a = getNextByte();
if (a == '&' || a == -1) {
input.setReadFully();
return -1;
} else
return a;
} else { // Content-Type: multipart/form-data
int a = getNextByte();
if (a == -1)
return -1;
if (a == '\r') {
int b = getNextByte();
if (b == -1)
return -1;
if (b == '\n') {
byte[] arr = new byte[boundary.length() + 2];
read(arr);
String str = new String(arr);
if (str.equals("--" + boundary)) {
// Read next few bytes: either "\r\n" or "--\r\n" or
// EOS
while (true) {
arr = new byte[2];
if (read(arr) < 0)
break;
if (java.util.Arrays.equals(arr, CRLF))
break;
}
input.setReadFully();
return -1;
} else {
for (int i = arr.length - 1; i > -1; i--) {
updateCache(arr[i]);
}
updateCache((byte) b);
return a;
}
} else {
updateCache((byte) b);
return a;
}
} else {
return a;
}
}
// return -1;
}
@Override
public int read(byte[] b) throws IOException {
int totalBytesRead = 0;
for (int i = 0; i < b.length; i++) {
int x = getNextByte();
if (x == -1) {
totalBytesRead = -1; // <-- This violates the java spec...
break;
} else {
b[i] = (byte) x;
totalBytesRead++;
}
}
return totalBytesRead;
}
/** Prepends a byte to the cache */
private void updateCache(byte b) {
byte[] temp = new byte[cache.length + 1];
temp[0] = b;
int i = 1;
for (byte _byte : cache) {
temp[i] = _byte;
i++;
}
cache = temp;
temp = null;
}
/**
* Returns the next available byte from the cache. If the cache is
* empty, returns the next available byte from the socket channel.
*/
private int getNextByte() throws IOException {
if (cache.length > 0) {
byte b = cache[0];
byte[] a = new byte[cache.length - 1];
System.arraycopy(cache, 1, a, 0, a.length);
cache = a;
return b & 0xFF; // convert unsigned Byte to Int
// return b;
} else {
return is.read();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy