cleaned up some code - replaced a bunch of copy loops with calls to the new

IOUtil class methods, added some javadocs to IOUtil, StringUtil, and
AnyCharMatcher
This commit is contained in:
Eric J. Bowersox 2001-10-31 19:38:40 +00:00
parent f1584f3f4a
commit 597ebadf35
10 changed files with 391 additions and 98 deletions

View File

@ -17,6 +17,16 @@
*/
package com.silverwrist.util;
/**
* A class which performs the equivalent of <CODE>String.indexOf(char)</CODE>, but using
* multiple characters. It locates the first instance within a string of <EM>any</EM> of
* the specified characters.
*
* @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X
* @see java.lang.String#indexOf(char)
* @see java.lang.String#lastIndexOf(char)
*/
public final class AnyCharMatcher
{
/*--------------------------------------------------------------------------------
@ -32,6 +42,11 @@ public final class AnyCharMatcher
*--------------------------------------------------------------------------------
*/
/**
* Creates a new character matcher that matches the specified characters.
*
* @param charset The set of characters to be matched by this object, expressed as a character array.
*/
public AnyCharMatcher(char[] charset)
{
this.charset = charset;
@ -39,6 +54,11 @@ public final class AnyCharMatcher
} // end constructor
/**
* Creates a new character matcher that matches the specified characters.
*
* @param charset The set of characters to be matched by this object, expressed as a string.
*/
public AnyCharMatcher(String charset)
{
this.charset = charset.toCharArray();
@ -51,8 +71,20 @@ public final class AnyCharMatcher
*--------------------------------------------------------------------------------
*/
/**
* Returns the offset within the string of the first instance of any character in this
* character set.
*
* @param str The string to look through. If this parameter is <B><CODE>null</CODE></B>,
* the method returns -1.
* @return The 0-based index of the first instance of any character from this character
* matcher within <CODE>str</CODE>. If <CODE>str</CODE> contains no instances of
* any character from this character matcher, -1 is returned.
*/
public final int get(String str)
{
if (str==null)
return -1;
int numindexes = 0;
int i;
for (i=0; i<charset.length; i++)
@ -82,5 +114,50 @@ public final class AnyCharMatcher
} // end get
/**
* Returns the offset within the string of the last instance of any character in this
* character set.
*
* @param str The string to look through. If this parameter is <B><CODE>null</CODE></B>,
* the method returns -1.
* @return The 0-based index of the last instance of any character from this character
* matcher within <CODE>str</CODE>. If <CODE>str</CODE> contains no instances of
* any character from this character matcher, -1 is returned.
*/
public final int getLast(String str)
{
if (str==null)
return -1;
int numindexes = 0;
int i;
for (i=0; i<charset.length; i++)
{ // locate the index of the first HTML character
int tmp = str.lastIndexOf(charset[i]);
if (tmp>=0)
locs[numindexes++] = tmp;
} // end for
if (numindexes==0)
return -1; // no characters found
else if (numindexes==1)
return locs[0]; // only one found
int rc = locs[0];
int limit = str.length() - 1;
for (i=1; i<numindexes; i++)
{ // this loop determines the highest possible return value
if (rc==limit)
return limit; // can't get any higher!
if (locs[i]>rc)
rc = locs[i]; // this is now the highest
} // end for
return rc;
} // end getLast
} // end class AnyCharMatcher

View File

@ -19,8 +19,13 @@ package com.silverwrist.util;
import java.io.*;
/* Some concepts in here borrowed from Apache Jakarta Avalon Excalibur 4.0 */
/**
* A collection of IO-related static methods which are useful in various contexts.<P>
* Some of the concepts in this class have been borrowed from Apache Jakarta Avalon Excalibur 4.0.
*
* @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X
*/
public class IOUtil
{
/*--------------------------------------------------------------------------------
@ -28,6 +33,9 @@ public class IOUtil
*--------------------------------------------------------------------------------
*/
/**
* The default buffer size to use for copying, if none is specified.
*/
public static int DEFAULT_BUFSIZE = 4096;
/*--------------------------------------------------------------------------------
@ -35,6 +43,11 @@ public class IOUtil
*--------------------------------------------------------------------------------
*/
/**
* Closes an input stream cleanly, without throwing an exception.
*
* @param stm The stream to be closed.
*/
public static void shutdown(InputStream stm)
{
try
@ -48,6 +61,11 @@ public class IOUtil
} // end shutdown
/**
* Closes an output stream cleanly, without throwing an exception.
*
* @param stm The stream to be closed.
*/
public static void shutdown(OutputStream stm)
{
try
@ -61,6 +79,11 @@ public class IOUtil
} // end shutdown
/**
* Closes an input reader cleanly, without throwing an exception.
*
* @param stm The stream to be closed.
*/
public static void shutdown(Reader rdr)
{
try
@ -74,6 +97,11 @@ public class IOUtil
} // end shutdown
/**
* Closes an output reader cleanly, without throwing an exception.
*
* @param stm The stream to be closed.
*/
public static void shutdown(Writer wr)
{
try
@ -87,6 +115,14 @@ public class IOUtil
} // end shutdown
/**
* Copies the contents of the given input stream to the given output stream.
*
* @param input The stream to copy binary data from.
* @param output The stream to copy binary data to.
* @param bufsize The size of the buffer to allocate for copying.
* @exception java.io.IOException If an exception occurred while reading or writing data.
*/
public static void copy(InputStream input, OutputStream output, int bufsize) throws IOException
{
byte[] buffer = new byte[bufsize];
@ -101,12 +137,113 @@ public class IOUtil
} // end copy
/**
* Copies the contents of the given input stream to the given output stream. Uses a default
* buffer size.
*
* @param input The stream to copy binary data from.
* @param output The stream to copy binary data to.
* @exception java.io.IOException If an exception occurred while reading or writing data.
* @see #DEFAULT_BUFSIZE
* @see #copy(java.io.InputStream,java.io.OutputStream,int)
*/
public static void copy(InputStream input, OutputStream output) throws IOException
{
copy(input,output,DEFAULT_BUFSIZE);
} // end copy
/**
* Takes the contents of an input stream and returns it as an array of bytes.
*
* @param input The stream to load binary data from.
* @param bufsize The size of the buffer to allocate for copying.
* @return A new byte array containing the contents of the specified input stream.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #copy(java.io.InputStream,java.io.OutputStream,int)
*/
public static byte[] load(InputStream input, int bufsize) throws IOException
{
ByteArrayOutputStream stm = new ByteArrayOutputStream();
try
{ // copy the data to the input stream
copy(input,stm,bufsize);
return stm.toByteArray();
} // end try
finally
{ // close our byte array stream before we go
shutdown(stm);
} // end finally
} // end load
/**
* Takes the contents of an input stream and returns it as an array of bytes. Uses a default
* buffer size.
*
* @param input The stream to load binary data from.
* @return A new byte array containing the contents of the specified input stream.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #DEFAULT_BUFSIZE
* @see #load(java.io.InputStream,int)
*/
public static byte[] load(InputStream input) throws IOException
{
return load(input,DEFAULT_BUFSIZE);
} // end load
/**
* Takes the contents of a binary file and returns it as an array of bytes.
*
* @param file The file to load binary data from.
* @param bufsize The size of the buffer to allocate for copying.
* @return A new byte array containing the contents of the specified file.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #load(java.io.InputStream,int)
*/
public static byte[] loadBinary(File file, int bufsize) throws IOException
{
FileInputStream stm = new FileInputStream(file);
try
{ // now just load from the stream
return load(stm,bufsize);
} // end try
finally
{ // close the file before we leave
shutdown(stm);
} // end finally
} // end loadBinary
/**
* Takes the contents of a binary file and returns it as an array of bytes. Uses a default
* buffer size.
*
* @param file The file to load binary data from.
* @return A new byte array containing the contents of the specified file.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #DEFAULT_BUFSIZE
* @see #loadBinary(java.io.File,int)
*/
public static byte[] loadBinary(File file) throws IOException
{
return loadBinary(file,DEFAULT_BUFSIZE);
} // end loadBinary
/**
* Copies the contents of the given input reader to the given output writer.
*
* @param input The reader to copy character data from.
* @param output The writer to copy character data to.
* @param bufsize The size of the buffer to allocate for copying.
* @exception java.io.IOException If an exception occurred while reading or writing data.
*/
public static void copy(Reader input, Writer output, int bufsize) throws IOException
{
char[] buffer = new char[bufsize];
@ -121,12 +258,31 @@ public class IOUtil
} // end copy
/**
* Copies the contents of the given input reader to the given output writer. Uses a default
* buffer size.
*
* @param input The reader to copy character data from.
* @param output The writer to copy character data to.
* @exception java.io.IOException If an exception occurred while reading or writing data.
* @see #DEFAULT_BUFSIZE
* @see #copy(java.io.Reader,java.io.Writer,int)
*/
public static void copy(Reader input, Writer output) throws IOException
{
copy(input,output,DEFAULT_BUFSIZE);
} // end copy
/**
* Takes the contents of an input reader and returns it as a <CODE>StringBuffer</CODE>.
*
* @param input The reader to copy character data from.
* @param bufsize The size of the buffer to allocate for copying.
* @return A new <CODE>StringBuffer</CODE> containing the contents of the specified reader.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #copy(java.io.Reader,java.io.Writer,int)
*/
public static StringBuffer load(Reader input, int bufsize) throws IOException
{
StringWriter wr = new StringWriter();
@ -144,13 +300,32 @@ public class IOUtil
} // end load
/**
* Takes the contents of an input reader and returns it as a <CODE>StringBuffer</CODE>. Uses a
* default buffer size.
*
* @param input The reader to copy character data from.
* @return A new <CODE>StringBuffer</CODE> containing the contents of the specified reader.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #DEFAULT_BUFSIZE
* @see #load(java.io.Reader,int)
*/
public static StringBuffer load(Reader input) throws IOException
{
return load(input,DEFAULT_BUFSIZE);
} // end load
public static StringBuffer load(File file, int bufsize) throws IOException
/**
* Takes the contents of a text file and returns it as a <CODE>StringBuffer</CODE>.
*
* @param file The file to copy text from.
* @param bufsize The size of the buffer to allocate for copying.
* @return A new <CODE>StringBuffer</CODE> containing the contents of the specified text file.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #load(java.io.Reader,int)
*/
public static StringBuffer loadText(File file, int bufsize) throws IOException
{
FileReader rdr = new FileReader(file);
try
@ -166,9 +341,18 @@ public class IOUtil
} // end load
public static StringBuffer load(File file) throws IOException
/**
* Takes the contents of a text file and returns it as a <CODE>StringBuffer</CODE>.
*
* @param file The file to copy text from.
* @return A new <CODE>StringBuffer</CODE> containing the contents of the specified text file.
* @exception java.io.IOException If an exception occurred while reading data.
* @see #DEFAULT_BUFSIZE
* @see #loadText(java.io.File,int)
*/
public static StringBuffer loadText(File file) throws IOException
{
return load(file,DEFAULT_BUFSIZE);
return loadText(file,DEFAULT_BUFSIZE);
} // end load

View File

@ -84,8 +84,6 @@ public class ServletMultipartHandler
static class MultipartDataValue implements Blob
{
private static final int BLKSIZE = 4096;
private byte[] actual_data; // the actual data we contain
public MultipartDataValue(MimeBodyPart part) throws MessagingException, IOException
@ -93,26 +91,8 @@ public class ServletMultipartHandler
if (logger.isDebugEnabled())
logger.debug("creating new MultipartDataValue");
// set up the streams to copy between
InputStream in = part.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] copybuf = new byte[BLKSIZE];
// begin the copy loop
int ct = in.read(copybuf,0,BLKSIZE);
while (ct>=0)
{ // do a simple read and write
if (logger.isDebugEnabled())
logger.debug("read blksize = " + ct);
if (ct>0)
out.write(copybuf,0,ct);
ct = in.read(copybuf,0,BLKSIZE);
} // end while
in.close();
actual_data = out.toByteArray();
out.close();
// load actual data
actual_data = IOUtil.load(part.getInputStream());
if (logger.isDebugEnabled())
logger.debug("finished copying, " + actual_data.length + " bytes transferred");

View File

@ -19,6 +19,12 @@ package com.silverwrist.util;
import java.util.*;
/**
* A collection of string-related static methods which are useful in various contexts.
*
* @author Eric J. Bowersox &lt;erbo@silcom.com&gt;
* @version X
*/
public class StringUtil
{
/*--------------------------------------------------------------------------------
@ -35,10 +41,18 @@ public class StringUtil
*--------------------------------------------------------------------------------
*/
/**
* Performs SQL encoding of an arbitrary string. When a string is SQL-encoded, all single-quote
* characters are doubled, and all other characters are left untouched.
*
* @param str The string to be SQL-encoded. May be <B><CODE>null</CODE></B>.
* @return The SQL-encoded equivalent of <CODE>str</CODE>. If <CODE>str</CODE> is
* <B><CODE>null</CODE></B>, returns <B><CODE>null</CODE></B>.
*/
public static String encodeStringSQL(String str)
{
if (str==null)
return null;
return null; // safety feature
int ndx = str.indexOf('\'');
if (ndx<0)
return str;
@ -58,10 +72,19 @@ public class StringUtil
} // end encodeStringSQL
/**
* Performs HTML encoding of an arbitrary string. When a string is HTML encoded, the double-quote (&quot;),
* ampersand (&amp;), less-than (&lt;), and greater-than (&gt;) characters are transformed to their HTML
* entity equivalents; all other characters are left untouched.
*
* @param str The string to be HTML-encoded. May be <B><CODE>null</CODE></B>.
* @return The HTML-encoded equivalent of <CODE>str</CODE>. If <CODE>str</CODE> is
* <B><CODE>null</CODE></B>, returns <B><CODE>null</CODE></B>.
*/
public static String encodeHTML(String str)
{
if (str==null)
return null;
return null; // safety feature
AnyCharMatcher nhc = new AnyCharMatcher(HTML_ENCODE_CHARS);
int ndx = nhc.get(str);
if (ndx<0)
@ -103,46 +126,92 @@ public class StringUtil
} // end encodeHTML
/**
* Returns <B><CODE>true</CODE></B> if the given string is <B><CODE>null</CODE></B> or a string of
* length 0, <B><CODE>false</CODE></B> otherwise.
*
* @param s The string to be tested.
* @return <B><CODE>true</CODE></B> if the given string is <B><CODE>null</CODE></B> or a string of
* length 0, <B><CODE>false</CODE></B> otherwise.
*/
public static boolean isStringEmpty(String s)
{
return ((s==null) || (s.length()==0));
} // end isStringEmpty
/**
* Replaces all instances of a particular substring within a string with another substring.
* For example:<P>
* <CODE>replaceAllInstances(&quot;blahdeeblah&quot;,&quot;blah&quot;,&quot;hoo&quot;)</CODE>
* returns <CODE>&quot;hoodeehoo&quot;</CODE><BR>
* <CODE>replaceAllInstances(&quot;blahdeebleh&quot;,&quot;blah&quot;,&quot;hoo&quot;)</CODE>
* returns <CODE>&quot;hoodeebleh&quot;</CODE>
*
* @param base The string to be operated on. If this parameter is <B><CODE>null</CODE></B>, the
* method will return <B><CODE>null</CODE></B>.
* @param find The substring to find in the <CODE>base</CODE> string. If this parameter is
* <B><CODE>null</CODE></B> or an empty string, no replacing will be done.
* @param replace The substring to replace instances of the <CODE>find</CODE> string with in the
* <CODE>base</CODE> string. If this parameter is <B><CODE>null</CODE></B>, instances
* of the <CODE>find</CODE> string will be deleted.
* @return The <CODE>base</CODE> string with all replacements made as detailed above.
*/
public static String replaceAllInstances(String base, String find, String replace)
{
String work = base;
int ndx = work.indexOf(find);
if ((base==null) || isStringEmpty(find))
return base; // safety feature
int ndx = base.indexOf(find);
if (ndx<0)
return work; // trivial case
return base; // trivial case
StringBuffer b = new StringBuffer();
while (ndx>=0)
{ // break off the first part of the string, then insert the replacement
if (ndx>0)
b.append(work.substring(0,ndx));
b.append(base.substring(0,ndx));
if (replace!=null)
b.append(replace);
// break off the tail end
ndx += find.length();
if (ndx==work.length())
if (ndx==base.length())
return b.toString(); // entire string munched - we're done!
work = work.substring(ndx);
ndx = work.indexOf(find);
base = base.substring(ndx);
ndx = base.indexOf(find);
} // end while
// append the unmatched "tail" of the work string and then return result
b.append(work);
// append the unmatched "tail" of the string and then return result
b.append(base);
return b.toString();
} // end replaceAllInstances
/**
* Replaces variable substitutions in a string. Variable substitutions are strings of the form
* <CODE>${<EM>varname</EM>}</CODE>. The <EM>varname</EM> names are looked up in the supplied
* <CODE>Map</CODE>, and the values of variables in that map are substituted.<P>
* Only variable names that exist in the <CODE>Map</CODE> are replaced; other variable strings
* in the supplied string are left untouched. Variable substitution values may themselves contain
* variables; those variables are recursively replaced. (<B><EM>Caution:</EM></B> The code cannot
* detect variable substitutions that contain themselves, or two variables that contain each other.
* Avoid these situations.)
*
* @param base The string to be operated on. If this parameter is <B><CODE>null</CODE></B>, the
* method will return <B><CODE>null</CODE></B>.
* @param vars The mapping of variable name to value substitutions. If this parameter is
* <B><CODE>null</CODE></B> or an empty map, no substitutions will be performed on
* <CODE>base</CODE>.
* @return The <CODE>base</CODE> string with all variable substitutions made as detailed above.
*/
public static String replaceAllVariables(String base, Map vars)
{
String work = base;
boolean did_replace, retest;
if ((base==null) || (vars==null) || (vars.size()==0))
return base; // safety feature
retest = true;
String work = base;
boolean did_replace;
boolean retest = true;
do
{ // main loop for replacing all variables
did_replace = false;

View File

@ -0,0 +1,27 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!--
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
WARRANTY OF ANY KIND, either express or implied. See the License for the specific
language governing rights and limitations under the License.
The Original Code is the Venice Web Community System.
The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
Contributor(s):
-->
<html>
<body bgcolor="white">
Provides a number of &quot;utility&quot; functions used by various parts of the Venice code.
<!-- Put @see and @since tags down here. -->
</body>
</html>

View File

@ -21,6 +21,7 @@ import java.io.*;
import java.sql.*;
import java.util.*;
import org.apache.log4j.*;
import com.silverwrist.util.IOUtil;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.core.*;
@ -107,23 +108,8 @@ class ImageStore implements BinaryData
} // end if
// Since the InputStream we get from JDBC will probably go away when the connection is dropped, we
// need to make a temporary copy of it, to a ByteArrayOutputStream.
InputStream sqldata = rs.getBinaryStream(1);
ByteArrayOutputStream copy = new ByteArrayOutputStream(length);
byte[] buffer = new byte[4096];
int rd = sqldata.read(buffer);
while (rd>=0)
{ // write, then read again
if (rd>0)
copy.write(buffer,0,rd);
rd = sqldata.read(buffer);
} // end while
// Close both our streams, making sure we create the stream we need for the return value.
sqldata.close();
rc = new ByteArrayInputStream(copy.toByteArray());
copy.close();
// need to make a temporary copy of it.
rc = new ByteArrayInputStream(IOUtil.load(rs.getBinaryStream(1)));
} // end try
catch (SQLException e)

View File

@ -22,6 +22,7 @@ import java.sql.*;
import java.util.*;
import java.util.zip.*;
import org.apache.log4j.*;
import com.silverwrist.util.IOUtil;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.security.AuditRecord;
@ -432,21 +433,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext
} // end switch
ByteArrayOutputStream copy = new ByteArrayOutputStream(datalen);
byte[] buffer = new byte[4096];
int rd = real_input.read(buffer);
while (rd>=0)
{ // write, then read again
if (rd>0)
copy.write(buffer,0,rd);
rd = real_input.read(buffer);
} // end while
// Close both our streams, making sure we create the stream we need for the return value.
real_input.close();
rc = new ByteArrayInputStream(copy.toByteArray());
copy.close();
// Copy to a new stream.
rc = new ByteArrayInputStream(IOUtil.load(real_input));
} // end try
catch (SQLException e)

View File

@ -555,7 +555,7 @@ public class RenderConfig implements ColorSelectors
synchronized String loadStyleSheetData() throws IOException
{
// Load the stylesheet data.
StringBuffer raw_data = IOUtil.load(stylesheet);
StringBuffer raw_data = IOUtil.loadText(stylesheet);
stylesheet_time = stylesheet.lastModified();
// Set up the replacements map to replace the various parameters.

View File

@ -23,6 +23,7 @@ import java.text.DateFormat;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.*;
import com.silverwrist.util.IOUtil;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.DataException;
import com.silverwrist.venice.core.IDUtils;
@ -462,16 +463,7 @@ public class RenderData implements ColorSelectors
response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\";");
// Copy the contents of the "data" stream to the output.
ServletOutputStream stm = response.getOutputStream();
byte[] buffer = new byte[4096];
int rd = data.read(buffer);
while (rd>=0)
{ // simple read-write loop to shove data out the door
if (rd>0)
stm.write(buffer,0,rd);
rd = data.read(buffer);
} // end while
IOUtil.copy(data,response.getOutputStream());
} // end sendBinaryData

View File

@ -18,6 +18,7 @@
package com.silverwrist.venice.servlets.format;
import java.io.*;
import com.silverwrist.util.IOUtil;
import com.silverwrist.util.cachemap.CacheMap;
public class StaticRender implements ContentRender
@ -94,21 +95,10 @@ public class StaticRender implements ContentRender
} // end if
// Read in the whole thing.
StringBuffer raw_file = new StringBuffer();
StringBuffer raw_file;
try
{ // read in from the file
FileReader rdr = new FileReader(real_path);
char[] buffer = new char[4096];
int rd = rdr.read(buffer);
while (rd>=0)
{ // read in the raw characters
if (rd>0)
raw_file.append(buffer,0,rd);
rd = rdr.read(buffer);
} // end while
rdr.close();
raw_file = IOUtil.loadText(new File(real_path));
} // end try
catch (IOException ioe)