/*
* @author : Pushkala
* @Version : 1.0
*
* Development Environment : Oracle9i JDeveloper
* Name of the File : FileUploadUtils.java
* Creation/Modification History :
*
* Pushkala 03-Feb-2003 Created
*
*/
package oracle.otnsamples.cmsxdb.useraction;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.sql.SQLException;
import java.sql.Connection;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import oracle.sql.CLOB;
import oracle.sql.BLOB;
import oracle.otnsamples.cmsxdb.exception.CMSAccessException;
/**
* This class parses the request and gathers the request parameters. When
* content type of request is of multipart/form-data, the request must be
* parsed based on boundary to gather parameters and file content.
*
* If the input file is an XML or XSL file, the data is stored in a CLOB, else
* a BLOB is used.
*/
public class FileUploadUtils {
// The multipart request
private HttpServletRequest req;
private ServletInputStream in = null;
// Name of the file being uploaded currently
private String fileName;
// The boundary
private String boundary = "--";
// Name of the form field
private String paramName;
// Content disposition
private String contentDisp;
// Holds parameter name,value pair
private Hashtable hash = null;
// Database connection to create a temporary LOB
private Connection connection = null;
// Temporary LOB
private CLOB dataClob = null;
private BLOB dataBlob = null;
/**
* Constructs a new object with the specified request and connection.
*
* @param req The original request
* @param connection Database connection to create a temporary LOB
*
* @exception CMSAccessException if parsing request fails
*/
public FileUploadUtils( HttpServletRequest req, Connection connection)
throws CMSAccessException {
try {
this.req = req;
hash = new Hashtable();
this.connection = connection;
this.in = req.getInputStream();
// Gather request parameters
this.processFileRequest(req);
} catch (IOException ioe) {
throw new CMSAccessException ( "IOException in FileUploadUitls" +
ioe.toString());
}
}
/**
* This method reads a line of data from servlet request.
*
* @return line read
*
* @exception IOException if reading from servlet request fails
*/
private String readLine() throws IOException {
int len = 0;
byte[] buff = new byte[4*1024];
String line = null;
// Read until buffer is full or newline char is reached
len= in.readLine(buff,0,buff.length);
if (len<0) return null;
line = new String(buff,0,len, "ISO-8859-1");
return line;
}
/**
* Parse request and gather parameters.
*
* @param req HttpServletRequest to be parsed
* @exception IOException if parsing request fails
*
*/
private void processFileRequest(HttpServletRequest req)
throws IOException {
// Set the boundary string
this.setBoundary();
int len = 0;
// the first line is the boundary , ignore it
String line = readLine();
while((line= readLine())!=null) {
// set disposition, param name and filename
setHeaders(line);
// skip next line
line=readLine();
// if there is a content-type specified, its the file content
if(line.toLowerCase().startsWith("content-type")){
// Handle resource , write it to a CLOB or BLOB
this.handleResource();
} else {
// its a form field, add to Hashtable
String paramvalue = null;
StringBuffer buf = new StringBuffer();
while (!(paramvalue = readLine()).startsWith(boundary)) {
if (paramvalue.endsWith("\n")) {
// Ignore the \n character
paramvalue = paramvalue.substring(0, paramvalue.indexOf("\n"));
// Ignore the \r character
paramvalue = paramvalue.substring(0, paramvalue.indexOf("\r"));
buf.append(paramvalue);
} else if (paramvalue.endsWith("\r")) {
// Ignore the \r character
paramvalue = paramvalue.substring(0, paramvalue.indexOf("\r"));
// Ignore the \n character
paramvalue = paramvalue.substring(0, paramvalue.indexOf("\n"));
buf.append(paramvalue);
} else {
buf.append(paramvalue);
}
}
paramvalue = buf.toString();
hash.put(paramName, paramvalue);
}
}
}
/**
* Read file contents and populate into LOB.
*
* @exception IOException if reading file content fails
*/
private void handleResource() throws IOException {
// Ignore this line
String line=readLine();
int len;
OutputStream out = null;
try {
// If XML, XSL, XSD or RDF, write to CLOB
if ( fileName.toLowerCase().endsWith(".xml") ||
fileName.toLowerCase().endsWith(".xsl") ||
fileName.toLowerCase().endsWith(".xsd") ||
fileName.toLowerCase().endsWith(".rdf") ) {
// Initialize temporary CLOB
dataClob = CLOB.createTemporary(connection, true, CLOB.DURATION_SESSION);
// Open the temporary CLOB in read-write mode to enable writing
dataClob.open(CLOB.MODE_READWRITE);
out = dataClob.getAsciiOutputStream();
} else { // Binary data
// Initialize temporary CLOB
dataBlob = BLOB.createTemporary(connection, true, BLOB.DURATION_SESSION);
// Open the temporary BLOB in read-write mode to enable writing
dataBlob.open(BLOB.MODE_READWRITE);
out = dataBlob.getBinaryOutputStream();
}
} catch (SQLException sqlex) {
System.out.println("SQLException in Handle resource");
throw new IOException(sqlex.toString());
}
boolean writeCR = false;
byte[] buff = new byte[4*1024]; //4K buffer
// Read file contents and write to LOB
while( (len=in.readLine(buff,0,buff.length )) >-1 ) {
line = new String(buff,0,len);
// if end of content, break
if (line.startsWith(boundary)) break;
// If newline character has to be written
if(writeCR){
writeCR=false;
out.write("\r".getBytes());
out.write("\n".getBytes());
}
// Postpone writing newline char because end of file will have newline appended
if(len>2 && buff[len-2]=='\r' && buff[len-1]=='\n') {
writeCR=true;
out.write(buff,0,len-2);
} else {
out.write(buff,0,len);
}
out.flush();
}
out.close();
}
/**
* Sets the boundary string for this request.
*
* @exception IOException if reading from request fails
*/
private void setBoundary()throws IOException{
String temp = req.getContentType();
int index = temp.indexOf("boundary=");
boundary += temp.substring(index+9,temp.length());
}
/**
* Sets the content disposition, param name and file name fields.
*
* @param line the content-disposition line
*/
public void setHeaders(String line) {
StringTokenizer tokens = new StringTokenizer(line,";",false);
String token = tokens.nextToken();
String temp = token.toLowerCase();
// Set content disposition
int index = temp.indexOf("content-disposition=");
contentDisp = token.substring(index+21,token.length());
token = tokens.nextToken();
temp = token.toLowerCase();
// Get parameter name
index = token.indexOf("name=");
paramName = token.substring(index+6,token.lastIndexOf('"'));
fileName = null;
// Get filename
if (tokens.hasMoreTokens()) {
token = tokens.nextToken();
temp = token.toLowerCase();
index = token.indexOf("filename=");
fileName = token.substring(index+10,token.length());
index = fileName.lastIndexOf('/');
if(index<0) {
index = fileName.lastIndexOf('\\');
}
if(index <0) {
fileName = fileName.substring(0,fileName.lastIndexOf('"'));
} else {
fileName = fileName.substring(index+1,fileName.lastIndexOf('"'));
}
}
if (fileName != null) {
hash.put("filename", fileName);
}
}
/**
* Returns the value of the specified parameter.
*
* @param name parameter name
*
* @return parameter value, null-if parameter does not exist
*/
public String getParameter( String name ) {
String ret = null;
if (hash != null) {
ret = (String) hash.get(name);
}
return ret;
}
/**
* Returns the temporary CLOB.
*
* @return temporary CLOB containing file content, if file is an XML or XSL or XSD.
*/
public CLOB getClobVal() {
return dataClob;
}
/**
* Returns the temporary BLOB.
*
* @return temporary BLOB containing file content, if file is not an XML or XSL or XSD.
*/
public BLOB getBlobVal() {
return dataBlob;
}
}