diff --git a/src/Acme/Fmt.java b/src/Acme/Fmt.java deleted file mode 100644 index cba4bf2e..00000000 --- a/src/Acme/Fmt.java +++ /dev/null @@ -1,613 +0,0 @@ -// Fmt - some simple single-arg sprintf-like routines -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme; - -/// Some simple single-arg sprintf-like routines. -//

-// It is apparently impossible to declare a Java method that accepts -// variable numbers of any type of argument. You can declare it to take -// Objects, but numeric variables and constants are not in fact Objects. -//

-// However, using the built-in string concatenation, it's almost as -// convenient to make a series of single-argument formatting routines. -//

-// Fmt can format the following types: -//

-// byte short int long float double char String Object -//
-// For each type there is a set of overloaded methods, each returning -// a formatted String. There's the plain formatting version: -//
-// Fmt.fmt( x )
-// 
-// There's a version specifying a minimum field width: -//
-// Fmt.fmt( x, minWidth )
-// 
-// And there's a version that takes flags: -//
-// Fmt.fmt( x, minWidth, flags )
-// 
-// Currently available flags are: -//
-// Fmt.ZF - zero-fill
-// Fmt.LJ - left justify
-// Fmt.HX - hexadecimal
-// Fmt.OC - octal
-// 
-// The HX and OC flags imply unsigned output. -//

-// For doubles and floats, there's a significant-figures parameter before -// the flags: -//

-// Fmt.fmt( d )
-// Fmt.fmt( d, minWidth )
-// Fmt.fmt( d, minWidth, sigFigs )
-// Fmt.fmt( d, minWidth, sigFigs, flags )
-// 
-//

-// Fetch the software.
-// Fetch the entire Acme package. -//


-// Similar classes: -// - -public class Fmt - { - - // Flags. - /// Zero-fill. - public static final int ZF = 1; - /// Left justify. - public static final int LJ = 2; - /// Hexadecimal. - public static final int HX = 4; - /// Octal. - public static final int OC = 8; - // Was a number - internal use. - private static final int WN = 16; - - // byte - public static String fmt( byte b ) - { - return fmt( b, 0, 0 ); - } - public static String fmt( byte b, int minWidth ) - { - return fmt( b, minWidth, 0 ); - } - public static String fmt( byte b, int minWidth, int flags ) - { - boolean hexadecimal = ( ( flags & HX ) != 0 ); - boolean octal = ( ( flags & OC ) != 0 ); - if ( hexadecimal ) - return fmt( Integer.toString( b & 0xff, 16 ), minWidth, flags|WN ); - else if ( octal ) - return fmt( Integer.toString( b & 0xff, 8 ), minWidth, flags|WN ); - else - return fmt( Integer.toString( b & 0xff ), minWidth, flags|WN ); - } - - // short - public static String fmt( short s ) - { - return fmt( s, 0, 0 ); - } - public static String fmt( short s, int minWidth ) - { - return fmt( s, minWidth, 0 ); - } - public static String fmt( short s, int minWidth, int flags ) - { - boolean hexadecimal = ( ( flags & HX ) != 0 ); - boolean octal = ( ( flags & OC ) != 0 ); - if ( hexadecimal ) - return fmt( - Integer.toString( s & 0xffff, 16 ), minWidth, flags|WN ); - else if ( octal ) - return fmt( - Integer.toString( s & 0xffff, 8 ), minWidth, flags|WN ); - else - return fmt( Integer.toString( s ), minWidth, flags|WN ); - } - - // int - public static String fmt( int i ) - { - return fmt( i, 0, 0 ); - } - public static String fmt( int i, int minWidth ) - { - return fmt( i, minWidth, 0 ); - } - public static String fmt( int i, int minWidth, int flags ) - { - boolean hexadecimal = ( ( flags & HX ) != 0 ); - boolean octal = ( ( flags & OC ) != 0 ); - if ( hexadecimal ) - return fmt( - Long.toString( i & 0xffffffffL, 16 ), minWidth, flags|WN ); - else if ( octal ) - return fmt( - Long.toString( i & 0xffffffffL, 8 ), minWidth, flags|WN ); - else - return fmt( Integer.toString( i ), minWidth, flags|WN ); - } - - // long - public static String fmt( long l ) - { - return fmt( l, 0, 0 ); - } - public static String fmt( long l, int minWidth ) - { - return fmt( l, minWidth, 0 ); - } - public static String fmt( long l, int minWidth, int flags ) - { - boolean hexadecimal = ( ( flags & HX ) != 0 ); - boolean octal = ( ( flags & OC ) != 0 ); - if ( hexadecimal ) - { - if ( ( l & 0xf000000000000000L ) != 0 ) - return fmt( - Long.toString( l >>> 60, 16 ) + - fmt( l & 0x0fffffffffffffffL, 15, HX|ZF ), - minWidth, flags|WN ); - else - return fmt( Long.toString( l, 16 ), minWidth, flags|WN ); - } - else if ( octal ) - { - if ( ( l & 0x8000000000000000L ) != 0 ) - return fmt( - Long.toString( l >>> 63, 8 ) + - fmt( l & 0x7fffffffffffffffL, 21, OC|ZF ), - minWidth, flags|WN ); - else - return fmt( Long.toString( l, 8 ), minWidth, flags|WN ); - } - else - return fmt( Long.toString( l ), minWidth, flags|WN ); - } - - // float - public static String fmt( float f ) - { - return fmt( f, 0, 0, 0 ); - } - public static String fmt( float f, int minWidth ) - { - return fmt( f, minWidth, 0, 0 ); - } - public static String fmt( float f, int minWidth, int sigFigs ) - { - return fmt( f, minWidth, sigFigs, 0 ); - } - public static String fmt( float f, int minWidth, int sigFigs, int flags ) - { - if ( sigFigs != 0 ) - return fmt( - sigFigFix( Float.toString( f ), sigFigs ), minWidth, - flags|WN ); - else - return fmt( Float.toString( f ), minWidth, flags|WN ); - } - - // double - public static String fmt( double d ) - { - return fmt( d, 0, 0, 0 ); - } - public static String fmt( double d, int minWidth ) - { - return fmt( d, minWidth, 0, 0 ); - } - public static String fmt( double d, int minWidth, int sigFigs ) - { - return fmt( d, minWidth, sigFigs, 0 ); - } - public static String fmt( double d, int minWidth, int sigFigs, int flags ) - { - if ( sigFigs != 0 ) - return fmt( - sigFigFix( doubleToString( d ), sigFigs ), minWidth, - flags|WN ); - else - return fmt( doubleToString( d ), minWidth, flags|WN ); - } - - // char - public static String fmt( char c ) - { - return fmt( c, 0, 0 ); - } - public static String fmt( char c, int minWidth ) - { - return fmt( c, minWidth, 0 ); - } - public static String fmt( char c, int minWidth, int flags ) - { - // return fmt( Character.toString( c ), minWidth, flags ); - // Character currently lacks a static toString method. Workaround - // is to make a temporary instance and use the instance toString. - return fmt( new Character( c ).toString(), minWidth, flags ); - } - - // Object - public static String fmt( Object o ) - { - return fmt( o, 0, 0 ); - } - public static String fmt( Object o, int minWidth ) - { - return fmt( o, minWidth, 0 ); - } - public static String fmt( Object o, int minWidth, int flags ) - { - return fmt( o.toString(), minWidth, flags ); - } - - // String - public static String fmt( String s ) - { - return fmt( s, 0, 0 ); - } - public static String fmt( String s, int minWidth ) - { - return fmt( s, minWidth, 0 ); - } - public static String fmt( String s, int minWidth, int flags ) - { - int len = s.length(); - boolean zeroFill = ( ( flags & ZF ) != 0 ); - boolean leftJustify = ( ( flags & LJ ) != 0 ); - boolean hexadecimal = ( ( flags & HX ) != 0 ); - boolean octal = ( ( flags & OC ) != 0 ); - boolean wasNumber = ( ( flags & WN ) != 0 ); - if ( ( hexadecimal || octal || zeroFill ) && ! wasNumber ) - throw new InternalError( "Acme.Fmt: number flag on a non-number" ); - if ( zeroFill && leftJustify ) - throw new InternalError( "Acme.Fmt: zero-fill left-justify is silly" ); - if ( hexadecimal && octal ) - throw new InternalError( "Acme.Fmt: can't do both hex and octal" ); - if ( len >= minWidth ) - return s; - int fillWidth = minWidth - len; - StringBuffer fill = new StringBuffer( fillWidth ); - for ( int i = 0; i < fillWidth; ++i ) - if ( zeroFill ) - fill.append( '0' ); - else - fill.append( ' ' ); - if ( leftJustify ) - return s + fill; - else if ( zeroFill && s.startsWith( "-" ) ) - return "-" + fill + s.substring( 1 ); - else - return fill + s; - } - - - // Internal routines. - - private static String sigFigFix( String s, int sigFigs ) - { - // First dissect the floating-point number string into sign, - // integer part, fraction part, and exponent. - String sign; - String unsigned; - if ( s.startsWith( "-" ) || s.startsWith( "+" ) ) - { - sign = s.substring( 0, 1 ); - unsigned = s.substring( 1 ); - } - else - { - sign = ""; - unsigned = s; - } - String mantissa; - String exponent; - int eInd = unsigned.indexOf( 'e' ); - if ( eInd == -1 ) // it may be 'e' or 'E' - eInd = unsigned.indexOf( 'E' ); - if ( eInd == -1 ) - { - mantissa = unsigned; - exponent = ""; - } - else - { - mantissa = unsigned.substring( 0, eInd ); - exponent = unsigned.substring( eInd ); - } - StringBuffer number, fraction; - int dotInd = mantissa.indexOf( '.' ); - if ( dotInd == -1 ) - { - number = new StringBuffer( mantissa ); - fraction = new StringBuffer( "" ); - } - else - { - number = new StringBuffer( mantissa.substring( 0, dotInd ) ); - fraction = new StringBuffer( mantissa.substring( dotInd + 1 ) ); - } - - int numFigs = number.length(); - int fracFigs = fraction.length(); - if ( ( numFigs == 0 || number.equals( "0" ) ) && fracFigs > 0 ) - { - // Don't count leading zeros in the fraction. - numFigs = 0; - for ( int i = 0; i < fraction.length(); ++i ) - { - if ( fraction.charAt( i ) != '0' ) - break; - --fracFigs; - } - } - int mantFigs = numFigs + fracFigs; - if ( sigFigs > mantFigs ) - { - // We want more figures; just append zeros to the fraction. - for ( int i = mantFigs; i < sigFigs; ++i ) - fraction.append( '0' ); - } - else if ( sigFigs < mantFigs && sigFigs >= numFigs ) - { - // Want fewer figures in the fraction; chop. - fraction.setLength( - fraction.length() - ( fracFigs - ( sigFigs - numFigs ) ) ); - // Round? - } - else if ( sigFigs < numFigs ) - { - // Want fewer figures in the number; turn them to zeros. - fraction.setLength( 0 ); // should already be zero, but make sure - for ( int i = sigFigs; i < numFigs; ++i ) - number.setCharAt( i, '0' ); - // Round? - } - // Else sigFigs == mantFigs, which is fine. - - if ( fraction.length() == 0 ) - return sign + number + exponent; - else - return sign + number + "." + fraction + exponent; - } - - - /// Improved version of Double.toString(), returns more decimal places. - //

- // The JDK 1.0.2 version of Double.toString() returns only six decimal - // places on some systems. In JDK 1.1 full precision is returned on - // all platforms. - // @deprecated - // @see java.lang.Double#toString - public static String doubleToString( double d ) - { - // Handle special numbers first, to avoid complications. - if ( Double.isNaN( d ) ) - return "NaN"; - if ( d == Double.NEGATIVE_INFINITY ) - return "-Inf"; - if ( d == Double.POSITIVE_INFINITY ) - return "Inf"; - - // Grab the sign, and then make the number positive for simplicity. - boolean negative = false; - if ( d < 0.0D ) - { - negative = true; - d = -d; - } - - // Get the native version of the unsigned value, as a template. - String unsStr = Double.toString( d ); - - // Dissect out the exponent. - String mantStr, expStr; - int exp; - int eInd = unsStr.indexOf( 'e' ); - if ( eInd == -1 ) // it may be 'e' or 'E' - eInd = unsStr.indexOf( 'E' ); - if ( eInd == -1 ) - { - mantStr = unsStr; - expStr = ""; - exp = 0; - } - else - { - mantStr = unsStr.substring( 0, eInd ); - expStr = unsStr.substring( eInd + 1 ); - if ( expStr.startsWith( "+" ) ) - exp = Integer.parseInt( expStr.substring( 1 ) ); - else - exp = Integer.parseInt( expStr ); - } - - // Dissect out the number part. - String numStr; - int dotInd = mantStr.indexOf( '.' ); - if ( dotInd == -1 ) - numStr = mantStr; - else - numStr = mantStr.substring( 0, dotInd ); - long num; - if ( numStr.length() == 0 ) - num = 0; - else - num = Integer.parseInt( numStr ); - - // Build the new mantissa. - StringBuffer newMantBuf = new StringBuffer( numStr + "." ); - double p = Math.pow( 10, exp ); - double frac = d - num * p; - String digits = "0123456789"; - int nDigits = 16 - numStr.length(); // about 16 digits in a double - for ( int i = 0; i < nDigits; ++i ) - { - p /= 10.0D; - int dig = (int) ( frac / p ); - if ( dig < 0 ) dig = 0; - if ( dig > 9 ) dig = 9; - newMantBuf.append( digits.charAt( dig ) ); - frac -= dig * p; - } - - if ( (int) ( frac / p + 0.5D ) == 1 ) - { - // Round up. - boolean roundMore = true; - for ( int i = newMantBuf.length() - 1; i >= 0; --i ) - { - int dig = digits.indexOf( newMantBuf.charAt( i ) ); - if ( dig == -1 ) - continue; - ++dig; - if ( dig == 10 ) - { - newMantBuf.setCharAt( i, '0' ); - continue; - } - newMantBuf.setCharAt( i, digits.charAt( dig ) ); - roundMore = false; - break; - } - if ( roundMore ) - { - // If this happens, we need to prepend a 1. But I haven't - // found a test case yet, so I'm leaving it out for now. - // But if you get this message, please let me know! - newMantBuf.append( "ROUNDMORE" ); - } - } - - // Chop any trailing zeros. - int len = newMantBuf.length(); - while ( newMantBuf.charAt( len - 1 ) == '0' ) - newMantBuf.setLength( --len ); - // And chop a trailing dot, if any. - if ( newMantBuf.charAt( len - 1 ) == '.' ) - newMantBuf.setLength( --len ); - - // Done. - return ( negative ? "-" : "" ) + - newMantBuf + - ( expStr.length() != 0 ? ( "e" + expStr ) : "" ); - } - - -/****************************************************************************** - /// Test program. - public static void main( String[] args ) - { - System.out.println( "Starting tests." ); - show( Fmt.fmt( "Hello there." ) ); - show( Fmt.fmt( 123 ) ); - show( Fmt.fmt( 123, 10 ) ); - show( Fmt.fmt( 123, 10, Fmt.ZF ) ); - show( Fmt.fmt( 123, 10, Fmt.LJ ) ); - show( Fmt.fmt( -123 ) ); - show( Fmt.fmt( -123, 10 ) ); - show( Fmt.fmt( -123, 10, Fmt.ZF ) ); - show( Fmt.fmt( -123, 10, Fmt.LJ ) ); - show( Fmt.fmt( (byte) 0xbe, 22, Fmt.OC ) ); - show( Fmt.fmt( (short) 0xbabe, 22, Fmt.OC ) ); - show( Fmt.fmt( 0xcafebabe, 22, Fmt.OC ) ); - show( Fmt.fmt( 0xdeadbeefcafebabeL, 22, Fmt.OC ) ); - show( Fmt.fmt( 0x8000000000000000L, 22, Fmt.OC ) ); - show( Fmt.fmt( (byte) 0xbe, 16, Fmt.HX ) ); - show( Fmt.fmt( (short) 0xbabe, 16, Fmt.HX ) ); - show( Fmt.fmt( 0xcafebabe, 16, Fmt.HX ) ); - show( Fmt.fmt( 0xdeadbeefcafebabeL, 16, Fmt.HX ) ); - show( Fmt.fmt( 0x8000000000000000L, 16, Fmt.HX ) ); - show( Fmt.fmt( 'c' ) ); - show( Fmt.fmt( new java.util.Date() ) ); - show( Fmt.fmt( 123.456F ) ); - show( Fmt.fmt( 123456000000000000.0F ) ); - show( Fmt.fmt( 123.456F, 0, 8 ) ); - show( Fmt.fmt( 123.456F, 0, 7 ) ); - show( Fmt.fmt( 123.456F, 0, 6 ) ); - show( Fmt.fmt( 123.456F, 0, 5 ) ); - show( Fmt.fmt( 123.456F, 0, 4 ) ); - show( Fmt.fmt( 123.456F, 0, 3 ) ); - show( Fmt.fmt( 123.456F, 0, 2 ) ); - show( Fmt.fmt( 123.456F, 0, 1 ) ); - show( Fmt.fmt( 123456000000000000.0F, 0, 4 ) ); - show( Fmt.fmt( -123.456F, 0, 4 ) ); - show( Fmt.fmt( -123456000000000000.0F, 0, 4 ) ); - show( Fmt.fmt( 123.0F ) ); - show( Fmt.fmt( 123.0D ) ); - show( Fmt.fmt( 1.234567890123456789F ) ); - show( Fmt.fmt( 1.234567890123456789D ) ); - show( Fmt.fmt( 1234567890123456789F ) ); - show( Fmt.fmt( 1234567890123456789D ) ); - show( Fmt.fmt( 0.000000000000000000001234567890123456789F ) ); - show( Fmt.fmt( 0.000000000000000000001234567890123456789D ) ); - show( Fmt.fmt( 12300.0F ) ); - show( Fmt.fmt( 12300.0D ) ); - show( Fmt.fmt( 123000.0F ) ); - show( Fmt.fmt( 123000.0D ) ); - show( Fmt.fmt( 1230000.0F ) ); - show( Fmt.fmt( 1230000.0D ) ); - show( Fmt.fmt( 12300000.0F ) ); - show( Fmt.fmt( 12300000.0D ) ); - show( Fmt.fmt( Float.NaN ) ); - show( Fmt.fmt( Float.POSITIVE_INFINITY ) ); - show( Fmt.fmt( Float.NEGATIVE_INFINITY ) ); - show( Fmt.fmt( Double.NaN ) ); - show( Fmt.fmt( Double.POSITIVE_INFINITY ) ); - show( Fmt.fmt( Double.NEGATIVE_INFINITY ) ); - show( Fmt.fmt( 1.0F / 8.0F ) ); - show( Fmt.fmt( 1.0D / 8.0D ) ); - System.out.println( "Done with tests." ); - } - - private static void show( String str ) - { - System.out.println( "#" + str + "#" ); - } -******************************************************************************/ - - } diff --git a/src/Acme/JPM/Decoders/ImageDecoder.java b/src/Acme/JPM/Decoders/ImageDecoder.java deleted file mode 100644 index 01dec95c..00000000 --- a/src/Acme/JPM/Decoders/ImageDecoder.java +++ /dev/null @@ -1,314 +0,0 @@ -// ImageDecoder - abstract class for reading in an image -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Decoders; - -import java.util.*; -import java.io.*; -import java.awt.image.*; - -/// Abstract class for reading in an image. -//

-// A framework for classes that read in and decode an image in -// a particular file format. -//

-// This provides a very simplified rendition of the ImageProducer interface. -// It requires the decoder to read the image a row at a time. It requires -// use of the RGBdefault color model. -// If you want more flexibility you can always implement ImageProducer -// directly. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see PpmDecoder -// @see Acme.JPM.Encoders.ImageEncoder - -public abstract class ImageDecoder implements ImageProducer - { - - private InputStream in; - private int width, height; - private boolean[] rowsRead; - private int[][] rgbPixels; - private boolean startedRead = false; - private boolean gotSize = false; - private boolean err = false; - private boolean producing = false; - private Vector consumers = new Vector(); - private static final ColorModel model = ColorModel.getRGBdefault(); - - - /// Constructor. - // @param in The stream to read the bytes from. - public ImageDecoder( InputStream in ) - { - this.in = in; - } - - - // Methods that subclasses implement. - - /// Subclasses implement this to read in enough of the image stream - // to figure out the width and height. - abstract void readHeader( InputStream in ) throws IOException; - - /// Subclasses implement this to return the width, or -1 if not known. - abstract int getWidth(); - - /// Subclasses implement this to return the height, or -1 if not known. - abstract int getHeight(); - - /// Subclasses implement this to read pixel data into the rgbRow - // array, an int[width]. One int per pixel, no offsets or padding, - // RGBdefault (AARRGGBB) color model. - abstract void readRow( InputStream in, int row, int[] rgbRow ) throws IOException; - - - // Our own methods. - - void readImage() - { - try - { - readHeader( in ); - width = getWidth(); - height = getHeight(); - if ( width == -1 || height == -1 ) - err = true; - else - { - rowsRead = new boolean[height]; - for ( int row = 0; row < height; ++row ) - rowsRead[row] = false; - gotSize = true; - notifyThem(); - rgbPixels = new int[height][width]; - for ( int row = 0; row < height; ++row ) - { - readRow( in, row, rgbPixels[row] ); - rowsRead[row] = true; - notifyThem(); - } - } - } - catch ( IOException e ) - { - err = true; - width = -1; - height = -1; - rowsRead = null; - rgbPixels = null; - } - } - - private synchronized void notifyThem() - { - notifyAll(); - } - - void sendImage() - { - // Grab the list of consumers, in case it changes while we're sending. - ImageConsumer[] c = new ImageConsumer[consumers.size()]; - int i; - for ( i = 0; i < c.length; ++i ) - c[i] = (ImageConsumer) consumers.elementAt( i ); - // Try to be as parallel as possible. - waitForSize(); - for ( i = 0; i < c.length; ++i ) - sendHead( c[i] ); - for ( int row = 0; row < height; ++row ) - for ( i = 0; i < c.length; ++i ) - sendPixelRow( c[i], row ); - for ( i = 0; i < c.length; ++i ) - sendTail( c[i] ); - producing = false; - } - - private synchronized void waitForSize() - { - while ( ( ! err ) && ( ! gotSize )) - { - try - { - wait(); - } - catch ( InterruptedException ignore ) {} - } - } - - private synchronized void waitForRow( int row ) - { - while ( ( ! err ) && ( ! rowsRead[row] ) ) - { - try - { - wait(); - } - catch ( InterruptedException ignore ) {} - } - } - - private void sendHead( ImageConsumer ic ) - { - if ( err ) - return; - ic.setDimensions( width, height ); - ic.setColorModel( model ); - ic.setHints( - ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.COMPLETESCANLINES | - ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME ); - } - - private void sendPixelRow( ImageConsumer ic, int row ) - { - if ( err ) - return; - waitForRow( row ); - if ( err ) - return; - ic.setPixels( 0, row, width, 1, model, rgbPixels[row], 0, width ); - } - - private void sendTail( ImageConsumer ic ) - { - if ( err ) - ic.imageComplete( ImageConsumer.IMAGEERROR ); - else - ic.imageComplete( ImageConsumer.STATICIMAGEDONE ); - - } - - - // Methods from ImageProducer. - - /// This method is used to register an ImageConsumer with the - // ImageProducer for access to the image data during a later - // reconstruction of the Image. The ImageProducer may, at its - // discretion, start delivering the image data to the consumer - // using the ImageConsumer interface immediately, or when the - // next available image reconstruction is triggered by a call - // to the startProduction method. - // @see #startProduction - public void addConsumer( ImageConsumer ic ) - { - if ( ic != null && ! isConsumer( ic ) ) - consumers.addElement( ic ); - } - - /// This method determines if a given ImageConsumer object - // is currently registered with this ImageProducer as one - // of its consumers. - public boolean isConsumer( ImageConsumer ic ) - { - return consumers.contains( ic ); - } - - /// This method removes the given ImageConsumer object - // from the list of consumers currently registered to - // receive image data. It is not considered an error - // to remove a consumer that is not currently registered. - // The ImageProducer should stop sending data to this - // consumer as soon as is feasible. - public void removeConsumer( ImageConsumer ic ) - { - consumers.removeElement( ic ); - } - - /// This method both registers the given ImageConsumer object - // as a consumer and starts an immediate reconstruction of - // the image data which will then be delivered to this - // consumer and any other consumer which may have already - // been registered with the producer. This method differs - // from the addConsumer method in that a reproduction of - // the image data should be triggered as soon as possible. - // @see #addConsumer - public void startProduction( ImageConsumer ic ) - { - addConsumer( ic ); - if ( ! startedRead ) - { - startedRead = true; - new ImageDecoderRead( this ); - } - if ( ! producing ) - { - producing = true; - sendImage(); - } - } - - /// This method is used by an ImageConsumer to request that - // the ImageProducer attempt to resend the image data one - // more time in TOPDOWNLEFTRIGHT order so that higher - // quality conversion algorithms which depend on receiving - // pixels in order can be used to produce a better output - // version of the image. The ImageProducer is free to - // ignore this call if it cannot resend the data in that - // order. If the data can be resent, then the ImageProducer - // should respond by executing the following minimum set of - // ImageConsumer method calls: - //

-    //     ic.setHints( TOPDOWNLEFTRIGHT | [otherhints] );
-    //     ic.setPixels( [...] );    // as many times as needed
-    //     ic.imageComplete( [status] );
-    // 
- // @see ImageConsumer#setHints - public void requestTopDownLeftRightResend( ImageConsumer ic ) - { - addConsumer( ic ); - waitForSize(); - sendHead( ic ); - for ( int row = 0; row < height; ++row ) - sendPixelRow( ic, row ); - sendTail( ic ); - } - - } - - -class ImageDecoderRead extends Thread - { - - private ImageDecoder parent; - - public ImageDecoderRead( ImageDecoder parent ) - { - this.parent = parent; - start(); - } - - // Methods from Runnable. - - public void run() - { - parent.readImage(); - } - - } diff --git a/src/Acme/JPM/Decoders/PpmDecoder.java b/src/Acme/JPM/Decoders/PpmDecoder.java deleted file mode 100644 index 8c39f9ce..00000000 --- a/src/Acme/JPM/Decoders/PpmDecoder.java +++ /dev/null @@ -1,267 +0,0 @@ -// PpmDecoder - read in a PPM image -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Decoders; - -import java.io.*; -import java.awt.image.*; - -/// Read in a PPM image. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see Acme.JPM.Encoders.PpmEncoder - -public class PpmDecoder extends ImageDecoder - { - - /// Constructor. - // @param in The stream to read the bytes from. - public PpmDecoder( InputStream in ) - { - super( in ); - } - - - private int type; - private static final int PBM_ASCII = 1; - private static final int PGM_ASCII = 2; - private static final int PPM_ASCII = 3; - private static final int PBM_RAW = 4; - private static final int PGM_RAW = 5; - private static final int PPM_RAW = 6; - - private int width = -1, height = -1; - private int maxval; - - /// Subclasses implement this to read in enough of the image stream - // to figure out the width and height. - void readHeader( InputStream in ) throws IOException - { - char c1, c2; - - c1 = (char) readByte( in ); - c2 = (char) readByte( in ); - - if ( c1 != 'P' ) - throw new IOException( "not a PBM/PGM/PPM file" ); - switch ( c2 ) - { - case '1': - type = PBM_ASCII; - break; - case '2': - type = PGM_ASCII; - break; - case '3': - type = PPM_ASCII; - break; - case '4': - type = PBM_RAW; - break; - case '5': - type = PGM_RAW; - break; - case '6': - type = PPM_RAW; - break; - default: - throw new IOException( "not a standard PBM/PGM/PPM file" ); - } - width = readInt( in ); - height = readInt( in ); - if ( type != PBM_ASCII && type != PBM_RAW ) - maxval = readInt( in ); - } - - /// Subclasses implement this to return the width, or -1 if not known. - int getWidth() - { - return width; - } - - /// Subclasses implement this to return the height, or -1 if not known. - int getHeight() - { - return height; - } - - /// Subclasses implement this to read pixel data into the rgbRow - // array, an int[width]. One int per pixel, no offsets or padding, - // RGBdefault (AARRGGBB) color model - void readRow( InputStream in, int row, int[] rgbRow ) throws IOException - { - int col, r, g, b; - int rgb = 0; - char c; - - for ( col = 0; col < width; ++col ) - { - switch ( type ) - { - case PBM_ASCII: - c = readChar( in ); - if ( c == '1' ) - rgb = 0xff000000; - else if ( c == '0' ) - rgb = 0xffffffff; - else - throw new IOException( "illegal PBM bit" ); - break; - case PGM_ASCII: - g = readInt( in ); - rgb = makeRgb( g, g, g ); - break; - case PPM_ASCII: - r = readInt( in ); - g = readInt( in ); - b = readInt( in ); - rgb = makeRgb( r, g, b ); - break; - case PBM_RAW: - if ( readBit( in ) ) - rgb = 0xff000000; - else - rgb = 0xffffffff; - break; - case PGM_RAW: - g = readByte( in ); - if ( maxval != 255 ) - g = fixDepth( g ); - rgb = makeRgb( g, g, g ); - break; - case PPM_RAW: - r = readByte( in ); - g = readByte( in ); - b = readByte( in ); - if ( maxval != 255 ) - { - r = fixDepth( r ); - g = fixDepth( g ); - b = fixDepth( b ); - } - rgb = makeRgb( r, g, b ); - break; - } - rgbRow[col] = rgb; - } - } - - /// Utility routine to read a byte. Instead of returning -1 on - // EOF, it throws an exception. - private static int readByte( InputStream in ) throws IOException - { - int b = in.read(); - if ( b == -1 ) - throw new EOFException(); - return b; - } - - private int bitshift = -1; - private int bits; - - /// Utility routine to read a bit, packed eight to a byte, big-endian. - private boolean readBit( InputStream in ) throws IOException - { - if ( bitshift == -1 ) - { - bits = readByte( in ); - bitshift = 7; - } - boolean bit = ( ( ( bits >> bitshift ) & 1 ) != 0 ); - --bitshift; - return bit; - } - - /// Utility routine to read a character, ignoring comments. - private static char readChar( InputStream in ) throws IOException - { - char c; - - c = (char) readByte( in ); - if ( c == '#' ) - { - do - { - c = (char) readByte( in ); - } - while ( c != '\n' && c != '\r' ); - } - - return c; - } - - /// Utility routine to read the first non-whitespace character. - private static char readNonwhiteChar( InputStream in ) throws IOException - { - char c; - - do - { - c = readChar( in ); - } - while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' ); - - return c; - } - - /// Utility routine to read an ASCII integer, ignoring comments. - private static int readInt( InputStream in ) throws IOException - { - char c; - int i; - - c = readNonwhiteChar( in ); - if ( c < '0' || c > '9' ) - throw new IOException( "junk in file where integer should be" ); - - i = 0; - do - { - i = i * 10 + c - '0'; - c = readChar( in ); - } - while ( c >= '0' && c <= '9' ); - - return i; - } - - /// Utility routine to rescale a pixel value from a non-eight-bit maxval. - private int fixDepth( int p ) - { - return ( p * 255 + maxval / 2 ) / maxval; - } - - /// Utility routine make an RGBdefault pixel from three color values. - private static int makeRgb( int r, int g, int b ) - { - return 0xff000000 | ( r << 16 ) | ( g << 8 ) | b; - } - - } diff --git a/src/Acme/JPM/Encoders/JpegEncoder.java b/src/Acme/JPM/Encoders/JpegEncoder.java deleted file mode 100644 index 8f434d2b..00000000 --- a/src/Acme/JPM/Encoders/JpegEncoder.java +++ /dev/null @@ -1,448 +0,0 @@ -// JpegEncoder - write out an image as a JPEG -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Encoders; - -import java.util.*; -import java.io.*; -import java.awt.Image; -import java.awt.image.*; - -/// Write out an image as a JPEG. -// DOESN'T WORK YET. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see ToJpeg - -public class JpegEncoder extends ImageEncoder - { - - /// Constructor. - // @param img The image to encode. - // @param out The stream to write the JPEG to. - public JpegEncoder( Image img, OutputStream out ) throws IOException - { - super( img, out ); - } - - /// Constructor. - // @param prod The ImageProducer to encode. - // @param out The stream to write the JPEG to. - public JpegEncoder( ImageProducer prod, OutputStream out ) throws IOException - { - super( prod, out ); - } - - int qfactor = 100; - - /// Set the Q-factor. - public void setQfactor( int qfactor ) - { - this.qfactor = qfactor; - } - - int width, height; - int[][] rgbPixels; - - void encodeStart( int width, int height ) throws IOException - { - this.width = width; - this.height = height; - rgbPixels = new int[height][width]; - } - - void encodePixels( - int x, int y, int w, int h, int[] rgbPixels, int off, int scansize ) - throws IOException - { - // Save the pixels. - for ( int row = 0; row < h; ++row ) - System.arraycopy( - rgbPixels, row * scansize + off, - this.rgbPixels[y + row], x, w ); - - } - - void encodeDone() throws IOException - { - writeJfifHuffHeader(); - // !!! - } - - - // Some of the following code is derived from the Berkeley Continuous - // Media Toolkit (http://bmrc.berkeley.edu/projects/cmt/), which is - // Copyright (c) 1996 The Regents of the University of California. - // All rights reserved. - // - // IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR - // DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING - // OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE - // UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - // DAMAGE. - // - // THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, - // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - // ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION - // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - - - // This array represents the default JFIF header for quality = 100 and - // size = 640x480, with Huffman tables. The values are adjusted when a - // file is generated. - private static byte[] jfifHuff100Header = { - // SOI - (byte) 0xFF, (byte) 0xD8, - - // JFIF header - (byte) 0xFF, (byte) 0xE0, // Marker - (byte) 0x00, (byte) 0x10, // Length = 16 bytes - (byte) 0x4A, (byte) 0x46, (byte) 0x49, (byte) 0x46, // "JFIF" - (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, - (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, - - // Start of frame (section B.2.2) - (byte) 0xFF, (byte) 0xC0, // Baseline DCT - (byte) 0x00, (byte) 0x11, // Length = 17 bytes - (byte) 0x08, // Sample precision - (byte) 0x01, (byte) 0xE0, // Height - (byte) 0x02, (byte) 0x80, // Width - (byte) 0x03, // Number of components = 3 - // Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0 - (byte) 0x01, (byte) 0x21, (byte) 0x00, - // Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1 - (byte) 0x02, (byte) 0x11, (byte) 0x01, - // Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1 - (byte) 0x03, (byte) 0x11, (byte) 0x01, - - // Define Quant table (section B.2.4.1) - (byte) 0xFF, (byte) 0xDB, // Marker - (byte) 0x00, (byte) 0x84, // Length (both tables) - (byte) 0x00, // 8 bit values, (byte) table 0 - (byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E, (byte) 0x0C, - (byte) 0x0A, (byte) 0x10, (byte) 0x0E, (byte) 0x0D, (byte) 0x0E, - (byte) 0x12, (byte) 0x11, (byte) 0x10, (byte) 0x13, (byte) 0x18, - (byte) 0x28, (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16, - (byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25, (byte) 0x1D, - (byte) 0x28, (byte) 0x3A, (byte) 0x33, (byte) 0x3D, (byte) 0x3C, - (byte) 0x39, (byte) 0x33, (byte) 0x38, (byte) 0x37, (byte) 0x40, - (byte) 0x48, (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44, - (byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38, (byte) 0x50, - (byte) 0x6D, (byte) 0x51, (byte) 0x57, (byte) 0x5F, (byte) 0x62, - (byte) 0x67, (byte) 0x68, (byte) 0x67, (byte) 0x3E, (byte) 0x4D, - (byte) 0x71, (byte) 0x79, (byte) 0x70, (byte) 0x64, (byte) 0x78, - (byte) 0x5C, (byte) 0x65, (byte) 0x67, (byte) 0x63, - - (byte) 0x01, // 8 bit values, (byte) table 1 - (byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18, (byte) 0x15, - (byte) 0x18, (byte) 0x2F, (byte) 0x1A, (byte) 0x1A, (byte) 0x2F, - (byte) 0x63, (byte) 0x42, (byte) 0x38, (byte) 0x42, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - - // Define huffman table (section B.2.4.1) - (byte) 0xFF, (byte) 0xC4, // Marker - (byte) 0x00, (byte) 0x1F, // Length (31 bytes) - (byte) 0x00, // DC, (byte) table 0 - (byte) 0x00, (byte) 0x01, (byte) 0x05, (byte) 0x01, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, - (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, - (byte) 0x09, (byte) 0x0A, (byte) 0x0B, - - // Define huffman table (section B.2.4.1) - (byte) 0xFF, (byte) 0xC4, // Marker - (byte) 0x00, (byte) 0xB5, // Length (181 bytes) - (byte) 0x10, // AC, (byte) table 0 - (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x03, - (byte) 0x02, (byte) 0x04, (byte) 0x03, (byte) 0x05, (byte) 0x05, - (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x01, - (byte) 0x7D, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x00, - (byte) 0x04, (byte) 0x11, (byte) 0x05, (byte) 0x12, (byte) 0x21, - (byte) 0x31, (byte) 0x41, (byte) 0x06, (byte) 0x13, (byte) 0x51, - (byte) 0x61, (byte) 0x07, (byte) 0x22, (byte) 0x71, (byte) 0x14, - (byte) 0x32, (byte) 0x81, (byte) 0x91, (byte) 0xA1, (byte) 0x08, - (byte) 0x23, (byte) 0x42, (byte) 0xB1, (byte) 0xC1, (byte) 0x15, - (byte) 0x52, (byte) 0xD1, (byte) 0xF0, (byte) 0x24, (byte) 0x33, - (byte) 0x62, (byte) 0x72, (byte) 0x82, (byte) 0x09, (byte) 0x0A, - (byte) 0x16, (byte) 0x17, (byte) 0x18, (byte) 0x19, (byte) 0x1A, - (byte) 0x25, (byte) 0x26, (byte) 0x27, (byte) 0x28, (byte) 0x29, - (byte) 0x2A, (byte) 0x34, (byte) 0x35, (byte) 0x36, (byte) 0x37, - (byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x43, (byte) 0x44, - (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49, - (byte) 0x4A, (byte) 0x53, (byte) 0x54, (byte) 0x55, (byte) 0x56, - (byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5A, (byte) 0x63, - (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68, - (byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74, (byte) 0x75, - (byte) 0x76, (byte) 0x77, (byte) 0x78, (byte) 0x79, (byte) 0x7A, - (byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87, - (byte) 0x88, (byte) 0x89, (byte) 0x8A, (byte) 0x92, (byte) 0x93, - (byte) 0x94, (byte) 0x95, (byte) 0x96, (byte) 0x97, (byte) 0x98, - (byte) 0x99, (byte) 0x9A, (byte) 0xA2, (byte) 0xA3, (byte) 0xA4, - (byte) 0xA5, (byte) 0xA6, (byte) 0xA7, (byte) 0xA8, (byte) 0xA9, - (byte) 0xAA, (byte) 0xB2, (byte) 0xB3, (byte) 0xB4, (byte) 0xB5, - (byte) 0xB6, (byte) 0xB7, (byte) 0xB8, (byte) 0xB9, (byte) 0xBA, - (byte) 0xC2, (byte) 0xC3, (byte) 0xC4, (byte) 0xC5, (byte) 0xC6, - (byte) 0xC7, (byte) 0xC8, (byte) 0xC9, (byte) 0xCA, (byte) 0xD2, - (byte) 0xD3, (byte) 0xD4, (byte) 0xD5, (byte) 0xD6, (byte) 0xD7, - (byte) 0xD8, (byte) 0xD9, (byte) 0xDA, (byte) 0xE1, (byte) 0xE2, - (byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6, (byte) 0xE7, - (byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xF1, (byte) 0xF2, - (byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, - (byte) 0xF8, (byte) 0xF9, (byte) 0xFA, - - // Define huffman table (section B.2.4.1) - (byte) 0xFF, (byte) 0xC4, // Marker - (byte) 0x00, (byte) 0x1F, // Length (31 bytes) - (byte) 0x01, // DC, (byte) table 1 - (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, - (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, - (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, - (byte) 0x09, (byte) 0x0A, (byte) 0x0B, - - // Define huffman table (section B.2.4.1) - (byte) 0xFF, (byte) 0xC4, // Marker - (byte) 0x00, (byte) 0xB5, // Length (181 bytes) - (byte) 0x11, // AC, (byte) table 1 - (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x04, - (byte) 0x04, (byte) 0x03, (byte) 0x04, (byte) 0x07, (byte) 0x05, - (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x02, - (byte) 0x77, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, - (byte) 0x11, (byte) 0x04, (byte) 0x05, (byte) 0x21, (byte) 0x31, - (byte) 0x06, (byte) 0x12, (byte) 0x41, (byte) 0x51, (byte) 0x07, - (byte) 0x61, (byte) 0x71, (byte) 0x13, (byte) 0x22, (byte) 0x32, - (byte) 0x81, (byte) 0x08, (byte) 0x14, (byte) 0x42, (byte) 0x91, - (byte) 0xA1, (byte) 0xB1, (byte) 0xC1, (byte) 0x09, (byte) 0x23, - (byte) 0x33, (byte) 0x52, (byte) 0xF0, (byte) 0x15, (byte) 0x62, - (byte) 0x72, (byte) 0xD1, (byte) 0x0A, (byte) 0x16, (byte) 0x24, - (byte) 0x34, (byte) 0xE1, (byte) 0x25, (byte) 0xF1, (byte) 0x17, - (byte) 0x18, (byte) 0x19, (byte) 0x1A, (byte) 0x26, (byte) 0x27, - (byte) 0x28, (byte) 0x29, (byte) 0x2A, (byte) 0x35, (byte) 0x36, - (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x43, - (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48, - (byte) 0x49, (byte) 0x4A, (byte) 0x53, (byte) 0x54, (byte) 0x55, - (byte) 0x56, (byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5A, - (byte) 0x63, (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67, - (byte) 0x68, (byte) 0x69, (byte) 0x6A, (byte) 0x73, (byte) 0x74, - (byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78, (byte) 0x79, - (byte) 0x7A, (byte) 0x82, (byte) 0x83, (byte) 0x84, (byte) 0x85, - (byte) 0x86, (byte) 0x87, (byte) 0x88, (byte) 0x89, (byte) 0x8A, - (byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96, - (byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9A, (byte) 0xA2, - (byte) 0xA3, (byte) 0xA4, (byte) 0xA5, (byte) 0xA6, (byte) 0xA7, - (byte) 0xA8, (byte) 0xA9, (byte) 0xAA, (byte) 0xB2, (byte) 0xB3, - (byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7, (byte) 0xB8, - (byte) 0xB9, (byte) 0xBA, (byte) 0xC2, (byte) 0xC3, (byte) 0xC4, - (byte) 0xC5, (byte) 0xC6, (byte) 0xC7, (byte) 0xC8, (byte) 0xC9, - (byte) 0xCA, (byte) 0xD2, (byte) 0xD3, (byte) 0xD4, (byte) 0xD5, - (byte) 0xD6, (byte) 0xD7, (byte) 0xD8, (byte) 0xD9, (byte) 0xDA, - (byte) 0xE2, (byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6, - (byte) 0xE7, (byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xF2, - (byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7, - (byte) 0xF8, (byte) 0xF9, (byte) 0xFA, - - // Start of Scan (section B.2.3) - (byte) 0xFF, (byte) 0xDA, // Marker - (byte) 0x00, (byte) 0x0C, // Length of header - (byte) 0x03, // Number of image components - // Scan 1: use DC/AC huff tables 0/0 - (byte) 0x01, (byte) 0x00, - // Scan 2: use DC/AC huff tables 1/1 - (byte) 0x02, (byte) 0x11, - // Scan 3: use DC/AC huff tables 1/1 - (byte) 0x03, (byte) 0x11, - (byte) 0x00, (byte) 0x3F, (byte) 0x00 // Not used - }; - - // This array represents the default JFIF header for quality = 100 and - // size = 640x480, without Huffman tables. The values are adjusted when a - // file is generated. - private static byte[] jfifNoHuff100Header = { - // SOI - (byte) 0xFF, (byte) 0xD8, - - // JFIF header - (byte) 0xFF, (byte) 0xE0, // Marker - (byte) 0x00, (byte) 0x10, // Length = 16 bytes - (byte) 0x4A, (byte) 0x46, (byte) 0x49, (byte) 0x46, // "JFIF" - (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, - (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, - - // Start of frame (section B.2.2) - (byte) 0xFF, (byte) 0xC0, // Baseline DCT - (byte) 0x00, (byte) 0x11, // Length = 17 bytes - (byte) 0x08, // Sample precision - (byte) 0x01, (byte) 0xE0, // Height - (byte) 0x02, (byte) 0x80, // Width - (byte) 0x03, // Number of components = 3 - // Scan 1: 2:1 horiz, (byte) 1:1 vertical, (byte) use QT 0 - (byte) 0x01, (byte) 0x21, (byte) 0x00, - // Scan 2: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1 - (byte) 0x02, (byte) 0x11, (byte) 0x01, - // Scan 3: 1:1 horiz, (byte) 1:1 vertical, (byte) use QT 1 - (byte) 0x03, (byte) 0x11, (byte) 0x01, - - // Define Quant table (section B.2.4.1) - (byte) 0xFF, (byte) 0xDB, // Marker - (byte) 0x00, (byte) 0x84, // Length (both tables) - (byte) 0x00, // 8 bit values, (byte) table 0 - (byte) 0x10, (byte) 0x0B, (byte) 0x0C, (byte) 0x0E, (byte) 0x0C, - (byte) 0x0A, (byte) 0x10, (byte) 0x0E, (byte) 0x0D, (byte) 0x0E, - (byte) 0x12, (byte) 0x11, (byte) 0x10, (byte) 0x13, (byte) 0x18, - (byte) 0x28, (byte) 0x1A, (byte) 0x18, (byte) 0x16, (byte) 0x16, - (byte) 0x18, (byte) 0x31, (byte) 0x23, (byte) 0x25, (byte) 0x1D, - (byte) 0x28, (byte) 0x3A, (byte) 0x33, (byte) 0x3D, (byte) 0x3C, - (byte) 0x39, (byte) 0x33, (byte) 0x38, (byte) 0x37, (byte) 0x40, - (byte) 0x48, (byte) 0x5C, (byte) 0x4E, (byte) 0x40, (byte) 0x44, - (byte) 0x57, (byte) 0x45, (byte) 0x37, (byte) 0x38, (byte) 0x50, - (byte) 0x6D, (byte) 0x51, (byte) 0x57, (byte) 0x5F, (byte) 0x62, - (byte) 0x67, (byte) 0x68, (byte) 0x67, (byte) 0x3E, (byte) 0x4D, - (byte) 0x71, (byte) 0x79, (byte) 0x70, (byte) 0x64, (byte) 0x78, - (byte) 0x5C, (byte) 0x65, (byte) 0x67, (byte) 0x63, - - (byte) 0x01, // 8 bit values, (byte) table 1 - (byte) 0x11, (byte) 0x12, (byte) 0x12, (byte) 0x18, (byte) 0x15, - (byte) 0x18, (byte) 0x2F, (byte) 0x1A, (byte) 0x1A, (byte) 0x2F, - (byte) 0x63, (byte) 0x42, (byte) 0x38, (byte) 0x42, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - (byte) 0x63, (byte) 0x63, (byte) 0x63, (byte) 0x63, - - // Start of Scan (section B.2.3) - (byte) 0xFF, (byte) 0xDA, // Marker - (byte) 0x00, (byte) 0x0C, // Length of header - (byte) 0x03, // Number of image components - // Scan 1: use DC/AC huff tables 0/0 - (byte) 0x01, (byte) 0x00, - // Scan 2: use DC/AC huff tables 1/1 - (byte) 0x02, (byte) 0x11, - // Scan 3: use DC/AC huff tables 1/1 - (byte) 0x03, (byte) 0x11, - (byte) 0x00, (byte) 0x3F, (byte) 0x00 // Not used - }; - - private void writeJfifHuffHeader() throws IOException - { - byte[] newHeader = new byte[jfifHuff100Header.length]; - - System.arraycopy( - jfifHuff100Header, 0, newHeader, 0, jfifHuff100Header.length ); - - // Set image width in JFIF header. - newHeader[27] = (byte) ( ( width >>> 8 ) & 0xff ); - newHeader[28] = (byte) ( width & 0xff ); - - // Set image height in JFIF header. - newHeader[25] = (byte) ( ( height >>> 8 ) & 0xff ); - newHeader[26] = (byte) ( height & 0xff ); - - // Adjust the quality factor. - // - // The default quality factor is 100, therefore if - // our quality factor does not equal 100 we must - // scale the quantization matrices in the JFIF header. - // Note that values are clipped to a max of 255. - if ( qfactor != 100 ) - { - for ( int i = 44; i < 108; ++i ) - { - int t = ( newHeader[i] * qfactor ) / 100; - newHeader[i] = (byte) Math.max( t, 0xff ); - } - for ( int i = 109; i < 173; ++i ) - { - int t = ( newHeader[i] * qfactor ) / 100; - newHeader[i] = (byte) Math.max( t, 0xff ); - } - } - - // Write out buffer. - out.write( newHeader ); - } - - private void writeJfifNoHuffHeader() throws IOException - { - byte[] newHeader = new byte[jfifNoHuff100Header.length]; - - System.arraycopy( - jfifNoHuff100Header, 0, newHeader, 0, jfifNoHuff100Header.length ); - - // Set image width in JFIF header. - newHeader[27] = (byte) ( ( width >>> 8 ) & 0xff ); - newHeader[28] = (byte) ( width & 0xff ); - - // Set image height in JFIF header. - newHeader[25] = (byte) ( ( height >>> 8 ) & 0xff ); - newHeader[26] = (byte) ( height & 0xff ); - - // Adjust the quality factor. - // - // The default quality factor is 100, therefore if - // our quality factor does not equal 100 we must - // scale the quantization matrices in the JFIF header. - // Note that values are clipped to a max of 255. - if ( qfactor != 100 ) - { - for ( int i = 44; i < 108; ++i ) - { - int t = ( newHeader[i] * qfactor ) / 100; - newHeader[i] = (byte) Math.max( t, 0xff ); - } - for ( int i = 109; i < 173; ++i ) - { - int t = ( newHeader[i] * qfactor ) / 100; - newHeader[i] = (byte) Math.max( t, 0xff ); - } - } - - // Write out buffer. - out.write( newHeader ); - } - - } diff --git a/src/Acme/JPM/Encoders/PpmEncoder.java b/src/Acme/JPM/Encoders/PpmEncoder.java deleted file mode 100644 index bb15382e..00000000 --- a/src/Acme/JPM/Encoders/PpmEncoder.java +++ /dev/null @@ -1,103 +0,0 @@ -// PpmEncoder - write out an image as a PPM -// -// Copyright (C)1996,1998 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Encoders; - -import java.util.*; -import java.io.*; -import java.awt.Image; -import java.awt.image.*; - -/// Write out an image as a PPM. -//

-// Writes an image onto a specified OutputStream in the PPM file format. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see ToPpm - -public class PpmEncoder extends ImageEncoder - { - - /// Constructor. - // @param img The image to encode. - // @param out The stream to write the PPM to. - public PpmEncoder( Image img, OutputStream out ) throws IOException - { - super( img, out ); - } - - /// Constructor. - // @param prod The ImageProducer to encode. - // @param out The stream to write the PPM to. - public PpmEncoder( ImageProducer prod, OutputStream out ) throws IOException - { - super( prod, out ); - } - - - void encodeStart( int width, int height ) throws IOException - { - writeString( out, "P6\n" ); - writeString( out, width + " " + height + "\n" ); - writeString( out, "255\n" ); - } - - static void writeString( OutputStream out, String str ) throws IOException - { - byte[] buf = str.getBytes(); - out.write( buf ); - } - - void encodePixels( - int x, int y, int w, int h, int[] rgbPixels, int off, int scansize ) - throws IOException - { - byte[] ppmPixels = new byte[w * 3]; - for ( int row = 0; row < h; ++row ) - { - int rowOff = off + row * scansize; - for ( int col = 0; col < w; ++col ) - { - int i = rowOff + col; - int j = col * 3; - ppmPixels[j ] = (byte) ( ( rgbPixels[i] & 0xff0000 ) >> 16 ); - ppmPixels[j + 1] = (byte) ( ( rgbPixels[i] & 0x00ff00 ) >> 8 ); - ppmPixels[j + 2] = (byte) ( rgbPixels[i] & 0x0000ff ); - } - out.write( ppmPixels ); - } - } - - void encodeDone() throws IOException - { - // Nothing. - } - - } diff --git a/src/Acme/JPM/Filters/CompositeFilter.java b/src/Acme/JPM/Filters/CompositeFilter.java deleted file mode 100644 index 0ed59c1f..00000000 --- a/src/Acme/JPM/Filters/CompositeFilter.java +++ /dev/null @@ -1,106 +0,0 @@ -// CompositeFilter - compose two filters into one -// -// Copyright (C) 1997 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; -import java.util.*; - -/// Compose two filters into one. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class CompositeFilter extends ImageFilterPlus - { - - private ImageFilterPlus filterOne, filterTwo; - private ImageFilter instanceOne, instanceTwo; - - /// Constructor. Builds a filter chain with a FilteredImageSource as - // the glue. - public CompositeFilter( ImageProducer producer, ImageFilterPlus filterOne, ImageFilterPlus filterTwo ) - { - super( producer ); - this.filterOne = filterOne; - this.filterTwo = filterTwo; - - filterOne.setSource( producer ); - ImageProducer producerOne = - new FilteredImageSource( producer, filterOne ); - filterTwo.setSource( producerOne ); - } - - public ImageFilter getFilterInstance( ImageConsumer consumer ) - { - CompositeFilter instance = (CompositeFilter) clone(); - instance.instanceTwo = filterTwo.getFilterInstance( consumer ); - instance.instanceOne = filterOne.getFilterInstance( instanceTwo ); - return (ImageFilter) instance; - } - - - // The rest of the methods just delegate to instanceOne. - - public void setColorModel( ColorModel model ) - { - instanceOne.setColorModel( model ); - } - - public void setDimensions( int width, int height ) - { - instanceOne.setDimensions( width, height ); - } - - public void setHints( int hintflags ) - { - instanceOne.setHints( hintflags ); - } - - public void setProperties( Hashtable props ) - { - instanceOne.setProperties( props ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - instanceOne.setPixels( x, y, w, h, model, pixels, off, scansize ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - instanceOne.setPixels( x, y, w, h, model, pixels, off, scansize ); - } - - public void imageComplete( int status ) - { - //super.imageComplete( status ); - instanceOne.imageComplete( status ); - } - - } diff --git a/src/Acme/JPM/Filters/EdgeDetect.java b/src/Acme/JPM/Filters/EdgeDetect.java deleted file mode 100644 index f5758b07..00000000 --- a/src/Acme/JPM/Filters/EdgeDetect.java +++ /dev/null @@ -1,169 +0,0 @@ -// EdgeDetect - edge-detection filter -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.io.*; -import java.awt.image.*; -import Acme.JPM.Decoders.*; -import Acme.JPM.Encoders.*; - -/// Edge-detection filter. -// -// -//

-// Outlines the edges of an image. -// The edge detection technique used is to take the Pythagorean sum of -// two Sobel gradient operators at 90 degrees to each other, separately -// for each color component. -// For more details see "Digital Image Processing" by Gonzalez and Wintz, -// chapter 7. -//

-// This filter is slow. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class EdgeDetect extends RGBAllFilter - { - - // Constructor. - public EdgeDetect( ImageProducer producer ) - { - super( producer ); - } - - - private static final double SCALE = 1.8D; - - public void filterRGBAll( int width, int height, int[][] rgbPixels ) - { - int[][] newPixels = new int[height][width]; - long sum1, sum2; - double sum; - int r, g, b; - - // First and last rows are black. - for ( int col = 0; col < width; ++col ) - { - newPixels[0][col] = 0xff000000; - newPixels[height - 1][col] = 0xff000000; - } - for ( int row = 1; row < height - 1; ++row ) - { - // First and last columns are black too. - newPixels[row][0] = 0xff000000; - newPixels[row][width - 1] = 0xff000000; - // The real pixels. - for ( int col = 1; col < width - 1; ++col ) - { - sum1 = - rgbModel.getRed( rgbPixels[row - 1][col + 1] ) - - rgbModel.getRed( rgbPixels[row - 1][col - 1] ) + - 2 * ( - rgbModel.getRed( rgbPixels[row][col + 1] ) - - rgbModel.getRed( rgbPixels[row][col - 1] ) ) + - rgbModel.getRed( rgbPixels[row + 1][col + 1] ) - - rgbModel.getRed( rgbPixels[row + 1][col - 1] ); - sum2 = ( - rgbModel.getRed( rgbPixels[row + 1][col - 1] ) + - 2 * rgbModel.getRed( rgbPixels[row + 1][col] ) + - rgbModel.getRed( rgbPixels[row + 1][col + 1] ) - ) - ( - rgbModel.getRed( rgbPixels[row - 1][col - 1] ) + - 2 * rgbModel.getRed( rgbPixels[row - 1][col] ) + - rgbModel.getRed( rgbPixels[row - 1][col + 1] ) - ); - sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE; - r = Math.min( (int) sum, 255 ); - - sum1 = - rgbModel.getGreen( rgbPixels[row - 1][col + 1] ) - - rgbModel.getGreen( rgbPixels[row - 1][col - 1] ) + - 2 * ( - rgbModel.getGreen( rgbPixels[row][col + 1] ) - - rgbModel.getGreen( rgbPixels[row][col - 1] ) ) + - rgbModel.getGreen( rgbPixels[row + 1][col + 1] ) - - rgbModel.getGreen( rgbPixels[row + 1][col - 1] ); - sum2 = ( - rgbModel.getGreen( rgbPixels[row + 1][col - 1] ) + - 2 * rgbModel.getGreen( rgbPixels[row + 1][col] ) + - rgbModel.getGreen( rgbPixels[row + 1][col + 1] ) - ) - ( - rgbModel.getGreen( rgbPixels[row - 1][col - 1] ) + - 2 * rgbModel.getGreen( rgbPixels[row - 1][col] ) + - rgbModel.getGreen( rgbPixels[row - 1][col + 1] ) - ); - sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE; - g = Math.min( (int) sum, 255 ); - - sum1 = - rgbModel.getBlue( rgbPixels[row - 1][col + 1] ) - - rgbModel.getBlue( rgbPixels[row - 1][col - 1] ) + - 2 * ( - rgbModel.getBlue( rgbPixels[row][col + 1] ) - - rgbModel.getBlue( rgbPixels[row][col - 1] ) ) + - rgbModel.getBlue( rgbPixels[row + 1][col + 1] ) - - rgbModel.getBlue( rgbPixels[row + 1][col - 1] ); - sum2 = ( - rgbModel.getBlue( rgbPixels[row + 1][col - 1] ) + - 2 * rgbModel.getBlue( rgbPixels[row + 1][col] ) + - rgbModel.getBlue( rgbPixels[row + 1][col + 1] ) - ) - ( - rgbModel.getBlue( rgbPixels[row - 1][col - 1] ) + - 2 * rgbModel.getBlue( rgbPixels[row - 1][col] ) + - rgbModel.getBlue( rgbPixels[row - 1][col + 1] ) - ); - sum = Math.sqrt( (double) ( sum1*sum1 + sum2*sum2 ) ) / SCALE; - b = Math.min( (int) sum, 255 ); - - newPixels[row][col] = - 0xff000000 | ( r << 16 ) | ( g << 8 ) | b; - } - } - setPixels( width, height, newPixels ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 0 ) - usage(); - ImageFilterPlus filter = new EdgeDetect( null ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: EdgeDetect" ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Enlarge.java b/src/Acme/JPM/Filters/Enlarge.java deleted file mode 100644 index e090b2bd..00000000 --- a/src/Acme/JPM/Filters/Enlarge.java +++ /dev/null @@ -1,140 +0,0 @@ -// Enlarge - an ImageFilter that enlarges by pixel replication -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// An ImageFilter that enlarges by pixel replication. -//

-// Enlarges an image an integral factor by replicating pixels. -// The output uses the same color model as the input. -// This filter is very fast. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see Shrink -// @see ScaleCopy - -public class Enlarge extends ImageFilterPlus - { - - private int multiplier; - private int newWidth, newHeight; - - /// Constructor. - public Enlarge( ImageProducer producer, int multiplier ) - { - super( producer ); - this.multiplier = multiplier; - } - - - public void setDimensions( int width, int height ) - { - newWidth = width * multiplier; - newHeight = height * multiplier; - consumer.setDimensions( newWidth, newHeight ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - int newX = Math.min( x * multiplier, newWidth - 1 ); - int newY = Math.min( y * multiplier, newHeight - 1 ); - int newW = w * multiplier; - if ( newX + newW > newWidth ) - newW = newWidth - newX; - int newH = h * multiplier; - if ( newY + newH > newHeight ) - newH = newHeight - newY; - byte[] newPixels = new byte[newW * newH]; - for ( int row = 0; row < h; ++row ) - { - for ( int col = 0; col < w; ++col ) - { - byte pixel = pixels[row * scansize + off + col]; - for ( int i = 0; i < multiplier; ++i ) - for ( int j = 0; j < multiplier; ++j ) - { - int newRow = row * multiplier + i; - int newCol = col * multiplier + j; - newPixels[newRow * newW + newCol] = pixel; - } - } - } - consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - int newX = Math.min( x * multiplier, newWidth - 1 ); - int newY = Math.min( y * multiplier, newHeight - 1 ); - int newW = w * multiplier; - if ( newX + newW > newWidth ) - newW = newWidth - newX; - int newH = h * multiplier; - if ( newY + newH > newHeight ) - newH = newHeight - newY; - int[] newPixels = new int[newW * newH]; - for ( int row = 0; row < h; ++row ) - { - for ( int col = 0; col < w; ++col ) - { - int pixel = pixels[row * scansize + off + col]; - for ( int i = 0; i < multiplier; ++i ) - for ( int j = 0; j < multiplier; ++j ) - { - int newRow = row * multiplier + i; - int newCol = col * multiplier + j; - newPixels[newRow * newW + newCol] = pixel; - } - } - } - consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 1 ) - usage(); - ImageFilterPlus filter = - new Enlarge( null, Integer.parseInt( args[0] ) ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Enlarge " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Flip.java b/src/Acme/JPM/Filters/Flip.java deleted file mode 100644 index 25c25b6c..00000000 --- a/src/Acme/JPM/Filters/Flip.java +++ /dev/null @@ -1,295 +0,0 @@ -// Flip - an ImageFilter that flips or rotates the image -// -// Copyright (C) 1997 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// An ImageFilter that flips or rotates the image. -//

-// Flips the image left-right, top-bottom, rotates clockwise or -// counter-clockwise, or otherwise munges the image as specified. -// This filter is fast. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Flip extends ImageFilterPlus - { - - /// The null transformation. - public static final int FLIP_NULL = 0; - - /// Flip left to right. - public static final int FLIP_LR = 1; - - /// Flip top to bottom. - public static final int FLIP_TB = 2; - - /// Transpose X and Y - reflection along a diagonal. - public static final int FLIP_XY = 3; - - /// Rotate clockwise 90 degrees. - public static final int FLIP_CW = 4; - - /// Rotate counter-clockwise 90 degrees. - public static final int FLIP_CCW = 5; - - /// Rotate 180 degrees. - public static final int FLIP_R180 = 6; - - private int flipType; - private int width, height; - private int newWidth, newHeight; - - /// Constructor. - public Flip( ImageProducer producer, int flipType ) - { - super( producer, true ); - this.flipType = flipType; - } - - - public void setDimensions( int width, int height ) - { - this.width = width; - this.height = height; - switch ( flipType ) - { - case FLIP_NULL: - case FLIP_LR: - case FLIP_TB: - case FLIP_R180: - newWidth = width; - newHeight = height; - break; - case FLIP_XY: - case FLIP_CW: - case FLIP_CCW: - newWidth = height; - newHeight = width; - break; - } - consumer.setDimensions( newWidth, newHeight ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - int newX = x; - int newY = y; - int newW = w; - int newH = h; - switch ( flipType ) - { - case FLIP_NULL: - break; - case FLIP_LR: - newX = width - ( x + w ); - break; - case FLIP_TB: - newY = height - ( y + h ); - break; - case FLIP_XY: - newW = h; - newH = w; - newX = y; - newY = x; - break; - case FLIP_CW: - newW = h; - newH = w; - newX = height - ( y + h ); - newY = x; - break; - case FLIP_CCW: - newW = h; - newH = w; - newX = y; - newY = width - ( x + w ); - break; - case FLIP_R180: - newX = width - ( x + w ); - newY = height - ( y + h ); - break; - } - byte[] newPixels = new byte[newW * newH]; - for ( int row = 0; row < h; ++row ) - { - for ( int col = 0; col < w; ++col ) - { - int index = row * scansize + off + col; - int newRow = row; - int newCol = col; - switch ( flipType ) - { - case FLIP_NULL: - break; - case FLIP_LR: - newCol = w - col - 1; - break; - case FLIP_TB: - newRow = h - row - 1; - break; - case FLIP_XY: - newRow = col; - newCol = row; - break; - case FLIP_CW: - newRow = col; - newCol = h - row - 1;; - break; - case FLIP_CCW: - newRow = w - col - 1; - newCol = row; - break; - case FLIP_R180: - newRow = h - row - 1; - newCol = w - col - 1; - break; - } - int newIndex = newRow * newW + newCol; - newPixels[newIndex] = pixels[index]; - } - } - consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - int newX = x; - int newY = y; - int newW = w; - int newH = h; - switch ( flipType ) - { - case FLIP_NULL: - break; - case FLIP_LR: - newX = width - ( x + w ); - break; - case FLIP_TB: - newY = height - ( y + h ); - break; - case FLIP_XY: - newW = h; - newH = w; - newX = y; - newY = x; - break; - case FLIP_CW: - newW = h; - newH = w; - newX = height - ( y + h ); - newY = x; - break; - case FLIP_CCW: - newW = h; - newH = w; - newX = y; - newY = width - ( x + w ); - break; - case FLIP_R180: - newX = width - ( x + w ); - newY = height - ( y + h ); - break; - } - int[] newPixels = new int[newW * newH]; - for ( int row = 0; row < h; ++row ) - { - for ( int col = 0; col < w; ++col ) - { - int index = row * scansize + off + col; - int newRow = row; - int newCol = col; - switch ( flipType ) - { - case FLIP_NULL: - break; - case FLIP_LR: - newCol = w - col - 1; - break; - case FLIP_TB: - newRow = h - row - 1; - break; - case FLIP_XY: - newRow = col; - newCol = row; - break; - case FLIP_CW: - newRow = col; - newCol = h - row - 1;; - break; - case FLIP_CCW: - newRow = w - col - 1; - newCol = row; - break; - case FLIP_R180: - newRow = h - row - 1; - newCol = w - col - 1; - break; - } - int newIndex = newRow * newW + newCol; - newPixels[newIndex] = pixels[index]; - } - } - consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 1 ) - usage(); - int flipType = FLIP_NULL; - if ( args[0].equalsIgnoreCase( "-lr" ) ) - flipType = FLIP_LR; - else if ( args[0].equalsIgnoreCase( "-tb" ) ) - flipType = FLIP_TB; - else if ( args[0].equalsIgnoreCase( "-xy" ) ) - flipType = FLIP_XY; - else if ( args[0].equalsIgnoreCase( "-cw" ) ) - flipType = FLIP_CW; - else if ( args[0].equalsIgnoreCase( "-ccw" ) ) - flipType = FLIP_CCW; - else if ( args[0].equalsIgnoreCase( "-r180" ) ) - flipType = FLIP_R180; - else - usage(); - ImageFilterPlus filter = new Flip( null, flipType ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Flip -lr|-tb|-xy|-cw|-ccw|-r180" ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Gamma.java b/src/Acme/JPM/Filters/Gamma.java deleted file mode 100644 index 765c7fd7..00000000 --- a/src/Acme/JPM/Filters/Gamma.java +++ /dev/null @@ -1,148 +0,0 @@ -// Gamma - gamma-correction filter -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// Gamma-correction filter. -//

-// Gamma correction fixes a form of color distortion common to many monitors. -// Values less than 1.0 darken the image, and greater than 1.0 lighten it. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Gamma extends RGBBlockFilter - { - - private double rValue, gValue, bValue; - - /// Constructor, single exponent. - public Gamma( ImageProducer producer, double value ) - { - this( producer, value, value, value ); - } - - /// Constructor, different exponents for R G and B. - public Gamma( ImageProducer producer, double rValue, double gValue, double bValue ) - { - super( producer ); - this.rValue = rValue; - this.gValue = gValue; - this.bValue = bValue; - } - - - private int[] rTable, gTable, bTable; - - public int[][] filterRGBBlock( int x, int y, int width, int height, int[][] rgbPixels ) - { - initialize(); - for ( int row = 0; row < height; ++row ) - for ( int col = 0; col < width; ++col ) - { - int rgb = rgbPixels[row][col]; - int a = ( rgb >> 24 ) & 0xff; - int r = ( rgb >> 16 ) & 0xff; - int g = ( rgb >> 8 ) & 0xff; - int b = rgb & 0xff; - r = rTable[r]; - g = gTable[g]; - b = bTable[b]; - rgbPixels[row][col] = - ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b; - } - return rgbPixels; - } - - - private boolean initialized = false; - - private void initialize() - { - if ( initialized ) - return; - initialized = true; - - rTable = buildTable( rValue ); - - if ( gValue == rValue ) - gTable = rTable; - else - gTable = buildTable( gValue ); - - if ( bValue == rValue ) - bTable = rTable; - else if ( bValue == gValue ) - bTable = gTable; - else - bTable = buildTable( bValue ); - } - - private int[] buildTable( double gamma ) - { - int[] table = new int[256]; - double oneOverGamma = 1.0D / gamma; - for ( int i = 0; i < 256; ++i ) - { - int v = (int) ( - ( 255.0D * Math.pow( i / 255.0D, oneOverGamma ) ) + 0.5D ); - if ( v > 255 ) - v = 255; - table[i] = v; - } - return table; - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - ImageFilterPlus filter = null; - if ( args.length == 1 ) - filter = new Gamma( null, Double.valueOf( args[0] ).doubleValue() ); - else if ( args.length == 3 ) - filter = new Gamma( null, - Double.valueOf( args[0] ).doubleValue(), - Double.valueOf( args[1] ).doubleValue(), - Double.valueOf( args[2] ).doubleValue() ); - else - usage(); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Gamma " ); - System.err.println( "or: Gamma " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/ImageFilterPlus.java b/src/Acme/JPM/Filters/ImageFilterPlus.java deleted file mode 100644 index 7c36b8d9..00000000 --- a/src/Acme/JPM/Filters/ImageFilterPlus.java +++ /dev/null @@ -1,160 +0,0 @@ -// ImageFilterPlus - an ImageFilter with some extra features and bug fixes -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; -import java.io.*; -import Acme.JPM.Decoders.*; -import Acme.JPM.Encoders.*; - -/// An ImageFilter with some extra features and bug fixes. -//

-// You can use an image filter to turn one Image into another via -// a FilteredImageSource, e.g.: -//

-// Image newImage = comp.createImage( new FilteredImageSource(
-//     oldImage.getSource(), new SomeFilter( oldImage.getSource() ) ) );
-// 
-// Or use the convenient utility JPMUtils.filterImage(): -//
-// Image newImage = JPMUtils.filterImage(
-//     comp, SomeFilter( oldImage.getSource() ) );
-// 
-//

-// You can also use image filters from the command line, reading PPM -// from stdin and writing PPM to stdout, if you add code like the following -// to each filter: -//

-// System.exit( 
-//     ImageFilterPlus.filterStream(
-//         System.in, System.out,
-//         new SomeFilter( null ) ) );
-// 
-//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class ImageFilterPlus extends ImageFilter - { - - private ImageProducer producer; - private boolean pixelOrderChanges; - - /// Constructor. - // @param producer The ImageProducer is required, so that we can - // remove ourself from its consumers list when we're done. - // However, if you don't have the producer available when you want - // to create the filter, you can pass in null and set it later - // via setSource(). - public ImageFilterPlus( ImageProducer producer ) - { - this( producer, false ); - } - - /// Constructor, with pixel order change. - // @param producer The ImageProducer is required, so that we can - // remove ourself from its consumers list when we're done. - // However, if you don't have the producer available when you want - // to create the filter, you can pass in null and set it later - // via setSource(). - // @param pixelOrderChanges If the filter may output pixels in a different - // order from the one they were delivered in, this flag must be set. - public ImageFilterPlus( ImageProducer producer, boolean pixelOrderChanges ) - { - setSource( producer ); - this.pixelOrderChanges = pixelOrderChanges; - } - - - /// The default color model - useful for comparisons. - public static final ColorModel rgbModel = ColorModel.getRGBdefault(); - - - /// Return the ImageProducer for this filter. - public ImageProducer getSource() - { - return producer; - } - - /// Set the ImageProducer for this filter, if it wasn't set by the - // constructor. - public void setSource( ImageProducer producer ) - { - this.producer = producer; - } - - - /// Set the hint flags. If the pixel order may change, we have to - // turn off the TOPDOWNLEFTRIGHT flag; otherwise the flags are passed - // through unmodified. - public void setHints( int hintflags ) - { - if ( pixelOrderChanges ) - hintflags &= ~TOPDOWNLEFTRIGHT; - consumer.setHints( hintflags ); - } - - - /// This routine fixes a bug in java.awt.image.ImageFilter. All - // ImageConsumers are required remove themselves from the producer's - // list when they're done reading. If they don't do this then some - // producers will generate an error. The standard ImageFilter class - // fails to do this, but this one does it. - public void imageComplete( int status ) - { - if ( status != ImageConsumer.SINGLEFRAMEDONE ) - producer.removeConsumer( this ); - super.imageComplete( status ); - } - - - /// Filter a PPM InputStream to a PPM OutputStream. - //

- // Create the filter with a null producer, and this routine will - // fill it in for you. - // @return a status code suitable for use with System.exit(). - public static int filterStream( InputStream in, OutputStream out, ImageFilterPlus filter ) - { - ImageDecoder producer = new PpmDecoder( in ); - filter.setSource( producer ); - try - { - ImageEncoder consumer = new PpmEncoder( - new FilteredImageSource( producer, filter ), out ); - consumer.encode(); - } - catch ( IOException e ) - { - System.err.println( e.toString() ); - return 1; - } - return 0; - } - - } diff --git a/src/Acme/JPM/Filters/Invert.java b/src/Acme/JPM/Filters/Invert.java deleted file mode 100644 index c4d65b32..00000000 --- a/src/Acme/JPM/Filters/Invert.java +++ /dev/null @@ -1,83 +0,0 @@ -// Invert - color-inversion filter -// -// Copyright (C) 1997 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// Color-inversion filter. -//

-// Switches black for white, and all the other colors too. -// This filter is very fast. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Invert extends RGBBlockFilter - { - - /// Constructor. - public Invert( ImageProducer producer ) - { - super( producer ); - } - - - public int[][] filterRGBBlock( int x, int y, int width, int height, int[][] rgbPixels ) - { - for ( int row = 0; row < height; ++row ) - for ( int col = 0; col < width; ++col ) - { - int rgb = rgbPixels[row][col]; - int alpha = rgb & 0xff000000; - int rest = ( ~ rgb ) & 0x00ffffff; - rgbPixels[row][col] = alpha | rest; - } - return rgbPixels; - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - ImageFilterPlus filter = null; - if ( args.length == 0 ) - filter = new Invert( null ); - else - usage(); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Invert" ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Margin.java b/src/Acme/JPM/Filters/Margin.java deleted file mode 100644 index 5375bb54..00000000 --- a/src/Acme/JPM/Filters/Margin.java +++ /dev/null @@ -1,133 +0,0 @@ -// Margin - an ImageFilter that adds a margin to an image -// -// Copyright (C) 1997 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.*; -import java.awt.image.*; - -/// An ImageFilter that adds a margin to an image. -//

-// Adds a margin of a specified color and width around an image. -// The output uses the same color model as the input. -// This filter is very fast. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Margin extends ImageFilterPlus - { - - private Color color; - private int size; - private int width, height; - private int newWidth; - - /// Constructor. - public Margin( ImageProducer producer, Color color, int size ) - { - super( producer, true ); - this.color = color; - this.size = size; - } - - - public void setDimensions( int width, int height ) - { - this.width = width; - this.height = height; - newWidth = width + size * 2; - consumer.setDimensions( newWidth, height + size * 2 ); - } - - private boolean started = false; - - private void start() - { - started = true; - int rgb = color.getRGB(); - - int[] fullRow = new int[newWidth]; - for ( int col = 0; col < newWidth; ++col ) - fullRow[col] = rgb; - for ( int row = 0; row < size; ++row ) - { - consumer.setPixels( - 0, row, newWidth, 1, rgbModel, fullRow, 0, newWidth ); - consumer.setPixels( - 0, size + height + row, newWidth, 1, rgbModel, fullRow, 0, - newWidth ); - } - - int[] sideRow = new int[size]; - for ( int col = 0; col < size; ++col ) - sideRow[col] = rgb; - for ( int row = 0; row < height; ++row ) - { - consumer.setPixels( - 0, size + row, size, 1, rgbModel, sideRow, 0, size ); - consumer.setPixels( - size + width, size + row, size, 1, rgbModel, sideRow, 0, size ); - } - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - if ( ! started ) - start(); - consumer.setPixels( - x + size, y + size, w, h, model, pixels, off, scansize ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - if ( ! started ) - start(); - consumer.setPixels( - x + size, y + size, w, h, model, pixels, off, scansize ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 1 ) - usage(); - ImageFilterPlus filter = - new Margin( null, Color.black, Integer.parseInt( args[0] ) ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Margin " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Oil.java b/src/Acme/JPM/Filters/Oil.java deleted file mode 100644 index cd39df9e..00000000 --- a/src/Acme/JPM/Filters/Oil.java +++ /dev/null @@ -1,141 +0,0 @@ -// Oil - oil-transfer filter -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// Oil-transfer filter. -// -// -//

-// The oil transfer is described in "Beyond Photography" by Holzmann, -// chapter 4, photo 7. -// It's a sort of localized smearing. -// The parameter controls the size of the smeared area, with a default of 3. -//

-// This filter is very slow. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Oil extends RGBAllFilter - { - - private int n; - - /// Constructor. - public Oil( ImageProducer producer, int n ) - { - super( producer ); - this.n = n; - } - - /// Constructor, default value. - public Oil( ImageProducer producer ) - { - this( producer, 3 ); - } - - - public void filterRGBAll( int width, int height, int[][] rgbPixels ) - { - int[][] newPixels = new int[height][width]; - int[] rHist = new int[256]; - int[] gHist = new int[256]; - int[] bHist = new int[256]; - - for ( int row = 0; row < height; ++row ) - { - for ( int col = 0; col < width; ++col ) - { - for ( int i = 0; i < 256; ++i ) - rHist[i] = gHist[i] = bHist[i] =0; - for ( int drow = row - n; drow <= row + n; ++drow ) - if ( drow >= 0 && drow < height ) - for ( int dcol = col - n; dcol <= col + n; ++dcol ) - if ( dcol >= 0 && dcol < width ) - { - int rgb = rgbPixels[drow][dcol]; - rHist[( rgb >> 16 ) & 0xff]++; - gHist[( rgb >> 8 ) & 0xff]++; - bHist[rgb & 0xff]++; - } - int r = 0, g = 0, b = 0; - for ( int i = 1; i < 256; ++i ) - { - if ( rHist[i] > rHist[r] ) - r = i; - if ( gHist[i] > gHist[g] ) - g = i; - if ( bHist[i] > bHist[b] ) - b = i; - } - newPixels[row][col] = - 0xff000000 | ( r << 16 ) | ( g << 8 ) | b; - } - } - setPixels( width, height, newPixels ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - int n = -1; - int argc = args.length; - int argn; - for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ++argn ) - { - if ( args[argn].equals( "-n" ) && argn + 1 < argc ) - { - ++argn; - n = Integer.parseInt( args[argn] ); - } - else - usage(); - } - if ( argn != argc ) - usage(); - - ImageFilterPlus filter; - if ( n == -1 ) - filter = new Oil( null ); - else - filter = new Oil( null, n ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Oil [-n N]" ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/RGBAllFilter.java b/src/Acme/JPM/Filters/RGBAllFilter.java deleted file mode 100644 index b9da544f..00000000 --- a/src/Acme/JPM/Filters/RGBAllFilter.java +++ /dev/null @@ -1,170 +0,0 @@ -// RGBAllFilter - an ImageFilter that grabs the whole image -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// An ImageFilter that grabs the whole image. -//

-// Many image filters need to work on the whole image at once. -// This class collects up the image and hands it to a single -// routine for processing. -//

-// Also, because Java's image classes allow each setPixels() call to -// use a different color model, we have to convert all pixels into -// the default RGB model. -//

-// Here's a sample RGBAllFilter that smooths an image by averaging -// nine adjacent pixels. -//

-// class SmoothFilter extends RGBAllFilter
-//     {
-//     public void filterRGBAll( int width, int height, int[][] rgbPixels )
-//         {
-//         int[][] newPixels = new int[height][width];
-//         for ( int row = 0; row < height; ++row )
-//             for ( int col = 0; col < width; ++col )
-//                 {
-//                 int a = 0, r = 0, g = 0, b = 0, c = 0;
-//                 for ( int subrow = row - 1; subrow <= row + 1; ++subrow )
-//                     if ( subrow >= 0 && subrow < height )
-//                         for ( int subcol = col - 1; subcol <= col + 1; ++subcol )
-//                             if ( subcol >= 0 && subcol < width )
-//                                 {
-//                                 int pixel = rgbPixels[subrow][subcol];
-//                                 a += rgbModel.getAlpha( pixel );
-//                                 r += rgbModel.getRed( pixel );
-//                                 g += rgbModel.getGreen( pixel );
-//                                 b += rgbModel.getBlue( pixel );
-//                                 ++c;
-//                                 }
-//                 a /= c;
-//                 r /= c;
-//                 g /= c;
-//                 b /= c;
-//                 newPixels[row][col] =
-//                     ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
-//                 }
-//         setPixels( width, height, newPixels );
-//         }
-//     }
-// 
-//

-// Fetch the software.
-// Fetch the entire Acme package. - -public abstract class RGBAllFilter extends ImageFilterPlus - { - - private int width = -1, height = -1; - private int[][] rgbPixels = null; - - public RGBAllFilter( ImageProducer producer ) - { - super( producer ); - } - - - /// This is the routine that subclasses must implement. - // It gets the entire image as an int[height][width] in the default - // RGB color model. It should call setPixels() with a filtered array, - // same color model. - public abstract void filterRGBAll( int width, int height, int[][] rgbPixels ); - - - /// The version of setPixels() that gets called by the subclass. - public void setPixels( int newWidth, int newHeight, int[][] newPixels ) - { - // Send it on to the consumer. - consumer.setDimensions( newWidth, newHeight ); - for ( int row = 0; row < newHeight; ++row ) - consumer.setPixels( - 0, row, newWidth, 1, rgbModel, newPixels[row], 0, newWidth ); - - } - - - public void setColorModel( ColorModel model ) - { - consumer.setColorModel( rgbModel ); - } - - public void setDimensions( int width, int height ) - { - if ( width == this.width && height == this.height ) - return; - this.width = width; - this.height = height; - rgbPixels = new int[height][width]; - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - for ( int row = 0; row < h; ++row ) - { - int rowOffsetIn = row * scansize + off; - for ( int col = 0; col < w; ++col ) - rgbPixels[y + row][x + col] = - model.getRGB( pixels[rowOffsetIn + col] & 0xff ); - } - } - - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - for ( int row = 0; row < h; ++row ) - { - int rowOffsetIn = row * scansize + off; - if ( model == rgbModel ) - System.arraycopy( - pixels, rowOffsetIn, rgbPixels[y + row], x, w ); - else - for ( int col = 0; col < w; ++col ) - rgbPixels[y + row][x + col] = - model.getRGB( pixels[rowOffsetIn + col] ); - } - } - - public void imageComplete( int status ) - { - if ( status == ImageConsumer.IMAGEERROR || - status == ImageConsumer.IMAGEABORTED ) - { - super.imageComplete( status ); - return; - } - - // Do the actual work. - filterRGBAll( width, height, rgbPixels ); - - // And we're done. - super.imageComplete( status ); - } - - } diff --git a/src/Acme/JPM/Filters/RGBBlockFilter.java b/src/Acme/JPM/Filters/RGBBlockFilter.java deleted file mode 100644 index 5fc60e07..00000000 --- a/src/Acme/JPM/Filters/RGBBlockFilter.java +++ /dev/null @@ -1,135 +0,0 @@ -// RGBBlockFilter - more efficient RGB ImageFilter -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// More efficient RGB ImageFilter. -//

-// Similar in concept to java.awt.image.RGBImageFilter, but designed -// to run more efficiently when filtering large images. -//

-// As with RGBImageFilter, you only have to implement a single routine -// to use the filter. However, RGBImageFilter's routine filters a single -// pixel at a time. This means a lot of routine-calling overhead. -// RGBBlockFilter filters a block at a time. -//

-// Here's a sample RGBBlockFilter that makes an image translucent -// by setting all the alpha values to 0x80: -//

-// class TranslucentFilter extends RGBBlockFilter
-//     {
-//     public int[] filterRGBBlock(
-//         int x, int y, int width, int height, int[][] rgbPixels )
-//         {
-//         for ( int row = 0; row < height; ++row )
-//             for ( int col = 0; col < width; ++col )
-//                 rgbPixels[row][col] =
-//                     ( rgbPixels[row][col] & 0x00ffffff ) | 0x80000000;
-//         return rgbPixels;
-//         }
-//     }
-// 
-//

-// Fetch the software.
-// Fetch the entire Acme package. - -public abstract class RGBBlockFilter extends ImageFilterPlus - { - - public RGBBlockFilter( ImageProducer producer ) - { - super( producer ); - } - - - /// This is the routine that subclasses must implement. - // It gets a block of the image as an int[height][width] in the default - // RGB color model. It should return a filtered array, same size - // and same model. - public abstract int[][] filterRGBBlock( - int x, int y, int width, int height, int[][] rgbPixels ); - - - public void setColorModel( ColorModel model ) - { - consumer.setColorModel( rgbModel ); - } - - /// Byte version of setPixels reformats the pixels to RGB and the - // array to 2 dimensions. - public void setPixels( - int x, int y, int width, int height, ColorModel model, - byte[] pixels, int offset, int scansize ) - { - int[][] rgbPixels = new int[height][width]; - for ( int row = 0; row < height; ++row ) - { - int rowOffsetIn = offset + row * scansize; - for ( int col = 0; col < width; ++col ) - rgbPixels[row][col] = - model.getRGB( pixels[rowOffsetIn + col] & 0xff ); - } - setPixels( x, y, width, height, rgbPixels ); - } - - /// Int version of setPixels reformats the array to 2 dimensions. - public void setPixels( - int x, int y, int width, int height, ColorModel model, - int[] pixels, int offset, int scansize ) - { - int[][] rgbPixels = new int[height][width]; - for ( int row = 0; row < height; ++row ) - { - int rowOffsetIn = offset + row * scansize; - int rowOffsetOut = row * width; - // Convert color models if necessary. - if ( model == rgbModel ) - System.arraycopy( - pixels, rowOffsetIn, rgbPixels[row], 0, width ); - else - for ( int col = 0; col < width; ++col ) - rgbPixels[row][col] = - model.getRGB( pixels[rowOffsetIn + col] ); - } - setPixels( x, y, width, height, rgbPixels ); - } - - /// Call the filter routine, and send the results to the consumer. - private void setPixels( int x, int y, int width, int height, int[][] rgbPixels ) - { - int[][] newPixels = filterRGBBlock( x, y, width, height, rgbPixels ); - - // And send it on to the consumer. - for ( int row = 0; row < height; ++row ) - consumer.setPixels( - x, y + row, width, 1, rgbModel, newPixels[row], 0, width ); - } - - } diff --git a/src/Acme/JPM/Filters/Rotate.java b/src/Acme/JPM/Filters/Rotate.java deleted file mode 100644 index 93d7fcc0..00000000 --- a/src/Acme/JPM/Filters/Rotate.java +++ /dev/null @@ -1,81 +0,0 @@ -// Rotate - rotate an image by some angle -// -// Copyright (C) 1997 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// Rotate an image by some angle. -//

-// Rotates an image by the specified angle. -// The angle is in degrees measured counter-clockwise. -// It can be negative, but it should be between -90 and 90 -// or the resulting image will be unreasonably large. -// Staying between -45 and 45 is best. -//

-// The rotation algorithm is Alan Paeth's three-shear method, described -// in "A Fast Algorithm for General Raster Rotation", Graphics Interface -// '86, pp. 77-81. -//

-// This filter is slow. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Rotate extends CompositeFilter - { - - private double angle; - - /// Constructor. - public Rotate( ImageProducer producer, double angle ) - { - super( producer, new Shear( null, angle ), new Flip( null, Flip.FLIP_XY ) ); - this.angle = angle * Math.PI / 180.0; - double xshearfac = Math.tan( angle / 2.0 ); - double yshearfac = Math.sin( angle ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 1 ) - usage(); - ImageFilterPlus filter = new Rotate( null, Integer.parseInt( args[0] ) ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Rotate " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/ScaleCopy.java b/src/Acme/JPM/Filters/ScaleCopy.java deleted file mode 100644 index 1c568e17..00000000 --- a/src/Acme/JPM/Filters/ScaleCopy.java +++ /dev/null @@ -1,159 +0,0 @@ -// ScaleCopy - an ImageFilter that scales by pixel copying -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// An ImageFilter that scales by pixel copying. -//

-// Scales an image by copying pixels. -// If the image is being enlarged, pixels get replicated; -// if the image is being shrunk, pixels get dropped. -// The output uses the same color model as the input. -// For enlarging, this filter is slightly slower than Enlarge due -// to the floating-point arithmetic; -// for shrinking, it's much faster than Shrink, but -// the results aren't as nice. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see Enlarge -// @see Shrink - -public class ScaleCopy extends ImageFilterPlus - { - - private double xScale, yScale; - private int newWidth, newHeight; - - /// Constructor, same X and Y scale factor. - public ScaleCopy( ImageProducer producer, double scale ) - { - this( producer, scale, scale ); - } - - /// Constructor, different X and Y scale factors. - public ScaleCopy( ImageProducer producer, double xScale, double yScale ) - { - super( producer ); - this.xScale = xScale; - this.yScale = yScale; - } - - - public void setDimensions( int width, int height ) - { - newWidth = (int) ( width * xScale ); - newHeight = (int) ( height * yScale ); - consumer.setDimensions( newWidth, newHeight ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - int newX = Math.min( (int) ( x * xScale ), newWidth - 1 ); - int newY = Math.min( (int) ( y * yScale ), newHeight - 1 ); - int newW = Math.max( (int) ( w * xScale ), 1 ); - if ( newX + newW > newWidth ) - newW = newWidth - newX; - int newH = Math.max( (int) ( h * yScale ), 1 ); - if ( newY + newH > newHeight ) - newH = newHeight - newY; - byte[] newPixels = new byte[newW * newH]; - for ( int newRow = 0; newRow < newH; ++newRow ) - { - int row = (int) ( newRow / yScale ); - if ( row >= h ) - continue; - for ( int newCol = 0; newCol < newW; ++newCol ) - { - int col = (int) ( newCol / xScale ); - if ( col >= w ) - continue; - newPixels[newRow * newW + newCol] = - pixels[row * scansize + off + col]; - } - } - consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW ); - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - int newX = Math.min( (int) ( x * xScale ), newWidth - 1 ); - int newY = Math.min( (int) ( y * yScale ), newHeight - 1 ); - int newW = Math.max( (int) ( w * xScale ), 1 ); - if ( newX + newW > newWidth ) - newW = newWidth - newX; - int newH = Math.max( (int) ( h * yScale ), 1 ); - if ( newY + newH > newHeight ) - newH = newHeight - newY; - int[] newPixels = new int[newW * newH]; - for ( int newRow = 0; newRow < newH; ++newRow ) - { - int row = (int) ( newRow / yScale ); - if ( row >= h ) - continue; - for ( int newCol = 0; newCol < newW; ++newCol ) - { - int col = (int) ( newCol / xScale ); - if ( col >= w ) - continue; - newPixels[newRow * newW + newCol] = - pixels[row * scansize + off + col]; - } - } - consumer.setPixels( newX, newY, newW, newH, model, newPixels, 0, newW ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - ImageFilterPlus filter = null; - if ( args.length == 1 ) - filter = new ScaleCopy( null, - Double.valueOf( args[0] ).doubleValue() ); - else if ( args.length == 2 ) - filter = new ScaleCopy( null, - Double.valueOf( args[0] ).doubleValue(), - Double.valueOf( args[1] ).doubleValue() ); - else - usage(); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: ScaleCopy scale" ); - System.err.println( "or: ScaleCopy xScale yScale" ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Shear.java b/src/Acme/JPM/Filters/Shear.java deleted file mode 100644 index 31bd2054..00000000 --- a/src/Acme/JPM/Filters/Shear.java +++ /dev/null @@ -1,144 +0,0 @@ -// Shear - shear an image by some angle -// -// Copyright (C) 1997 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// Shear an image by some angle. -//

-// Shears an image by the specified angle. -// The angle is in degrees (floating point), and measures this: -//


-// +-------+  +-------+
-// |       |  |\       \
-// |  OLD  |  | \  NEW  \
-// |       |  |an\       \
-// +-------+  |gle+-------+
-// 
-// If the angle is negative, it shears the other way: -//

-// +-------+  |-an+-------+
-// |       |  |gl/       /
-// |  OLD  |  |e/  NEW  /
-// |       |  |/       /
-// +-------+  +-------+
-// 
-// The angle should not get too close to 90 or -90, or the resulting -// image will be unreasonably wide. Staying between -45 and 45 is best. -//

-// The shearing is implemented by looping over the source pixels and -// distributing fractions to each of the destination pixels. -// This has an "anti-aliasing" effect - it avoids jagged edges and similar -// artifacts. -//

-// This filter is fast. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Shear extends RGBAllFilter - { - - private double angle; - - /// Constructor. - public Shear( ImageProducer producer, double angle ) - { - super( producer ); - this.angle = angle * Math.PI / 180.0; - } - - - public void filterRGBAll( int width, int height, int[][] rgbPixels ) - { - double shearfac = Math.tan( angle ); - if ( shearfac < 0.0 ) - shearfac = -shearfac; - int newWidth = (int) ( height * shearfac + width + 0.999999 ); - int[][] newPixels = new int[height][newWidth]; - for ( int row = 0; row < height; ++row ) - { - double new0; - if ( angle > 0.0 ) - new0 = row * shearfac; - else - new0 = ( height - row ) * shearfac; - int intnew0 = (int) new0; - double fracnew0 = new0 - intnew0; - double omfracnew0 = 1.0 - fracnew0; - - for ( int col = 0; col < newWidth; ++col ) - newPixels[row][col] = 0x00000000; - - int preva = 0; - int prevr = ( rgbPixels[row][0] >> 16 ) & 0xff; - int prevg = ( rgbPixels[row][0] >> 8 ) & 0xff; - int prevb = rgbPixels[row][0] & 0xff; - for ( int col = 0; col < width; ++col ) - { - int rgb = rgbPixels[row][col]; - int a = ( rgb >> 24 ) & 0xff; - int r = ( rgb >> 16 ) & 0xff; - int g = ( rgb >> 8 ) & 0xff; - int b = rgb & 0xff; - newPixels[row][intnew0 + col] = - ( (int) ( fracnew0 * preva + omfracnew0 * a ) << 24 ) | - ( (int) ( fracnew0 * prevr + omfracnew0 * r ) << 16 ) | - ( (int) ( fracnew0 * prevg + omfracnew0 * g ) << 8 ) | - ( (int) ( fracnew0 * prevb + omfracnew0 * b ) ); - preva = a; - prevr = r; - prevg = g; - prevb = b; - } - newPixels[row][intnew0 + width] = - ( (int) ( fracnew0 * preva ) << 24 ) | - ( prevr << 16 ) | ( prevg << 8 ) | prevb; - } - setPixels( newWidth, height, newPixels ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 1 ) - usage(); - ImageFilterPlus filter = new Shear( null, Integer.parseInt( args[0] ) ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Shear " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Shrink.java b/src/Acme/JPM/Filters/Shrink.java deleted file mode 100644 index 4599cb1b..00000000 --- a/src/Acme/JPM/Filters/Shrink.java +++ /dev/null @@ -1,116 +0,0 @@ -// Shrink - an ImageFilter that shrinks by pixel averaging -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// An ImageFilter that shrinks by pixel averaging. -//

-// Shrinks an image an integral factor by averaging pixels. -// Because the resulting pixels might not fit into the input's -// color model, the output is always in the default RGB color model. -// This filter is somewhat slow. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see Enlarge -// @see ScaleCopy - -public class Shrink extends RGBAllFilter - { - - private int divisor; - - /// Constructor. - public Shrink( ImageProducer producer, int divisor ) - { - super( producer ); - this.divisor = divisor; - } - - - public void filterRGBAll( int width, int height, int[][] rgbPixels ) - { - int divisor2 = divisor * divisor; - int newWidth = Math.max( width / divisor, 1 ); - int newHeight = Math.max( height / divisor, 1 ); - int[][] newPixels = new int[newHeight][newWidth]; - for ( int newRow = 0; newRow < newHeight; ++newRow ) - { - for ( int newCol = 0; newCol < newWidth; ++newCol ) - { - int a = 0, r = 0, g = 0, b = 0; - for ( int i = 0; i < divisor; ++i ) - { - int row = newRow * divisor + i; - if ( row >= height ) - continue; - for ( int j = 0; j < divisor; ++j ) - { - int col = newCol * divisor + j; - if ( col >= width ) - continue; - int rgb = rgbPixels[row][col]; - a += ( rgb >> 24 ) & 0xff; - r += ( rgb >> 16 ) & 0xff; - g += ( rgb >> 8 ) & 0xff; - b += rgb & 0xff; - } - } - a /= divisor2; - r /= divisor2; - g /= divisor2; - b /= divisor2; - newPixels[newRow][newCol] = - ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b; - } - } - setPixels( newWidth, newHeight, newPixels ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 1 ) - usage(); - ImageFilterPlus filter = new Enlarge( - null, Integer.parseInt( args[0] ) ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Shrink " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Smooth.java b/src/Acme/JPM/Filters/Smooth.java deleted file mode 100644 index aadab230..00000000 --- a/src/Acme/JPM/Filters/Smooth.java +++ /dev/null @@ -1,123 +0,0 @@ -// Smooth - smoothing filter -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// Smoothing filter. -//

-// Smooths an image by averaging adjacent pixels. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Smooth extends RGBAllFilter - { - - private int n; - - /// Constructor. - public Smooth( ImageProducer producer, int n ) - { - super( producer ); - this.n = n; - } - - /// Constructor, default value. - public Smooth( ImageProducer producer ) - { - this( producer, 1 ); - } - - - public void filterRGBAll( int width, int height, int[][] rgbPixels ) - { - int[][] newPixels = new int[height][width]; - for ( int row = 0; row < height; ++row ) - for ( int col = 0; col < width; ++col ) - { - int a = 0, r = 0, g = 0, b = 0, c = 0; - for ( int subrow = row - n; subrow <= row + n; ++subrow ) - if ( subrow >= 0 && subrow < height ) - for ( int subcol = col - n; subcol <= col + n; ++subcol ) - if ( subcol >= 0 && subcol < width ) - { - int rgb = rgbPixels[subrow][subcol]; - a += ( rgb >> 24 ) & 0xff; - r += ( rgb >> 16 ) & 0xff; - g += ( rgb >> 8 ) & 0xff; - b += rgb & 0xff; - ++c; - } - a /= c; - r /= c; - g /= c; - b /= c; - newPixels[row][col] = - ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b; - } - setPixels( width, height, newPixels ); - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - int n = -1; - int argc = args.length; - int argn; - for ( argn = 0; argn < argc && args[argn].charAt( 0 ) == '-'; ++argn ) - { - if ( args[argn].equals( "-n" ) && argn + 1 < argc ) - { - ++argn; - n = Integer.parseInt( args[argn] ); - } - else - usage(); - } - if ( argn != argc ) - usage(); - - ImageFilterPlus filter; - if ( n == -1 ) - filter = new Smooth( null ); - else - filter = new Smooth( null, n ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Smooth [-n N]" ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/Filters/Tile.java b/src/Acme/JPM/Filters/Tile.java deleted file mode 100644 index 1d374d15..00000000 --- a/src/Acme/JPM/Filters/Tile.java +++ /dev/null @@ -1,126 +0,0 @@ -// Tile - an ImageFilter that replicates an image in a tiled pattern -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM.Filters; - -import java.awt.image.*; - -/// An ImageFilter that replicates an image in a tiled pattern. -//

-// Tiles the image onto an output image of a specified size. -// The output uses the same color model as the input. -// This filter is very fast. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Tile extends ImageFilterPlus - { - - private int width, height; - private int newWidth, newHeight; - private int nWide, nHigh; - - /// Constructor. - public Tile( ImageProducer producer, int newWidth, int newHeight ) - { - super( producer, true ); - this.newWidth = newWidth; - this.newHeight = newHeight; - } - - - public void setDimensions( int width, int height ) - { - this.width = width; - this.height = height; - consumer.setDimensions( newWidth, newHeight ); - nWide = ( newWidth + width - 1 ) / width; - nHigh = ( newHeight + height - 1 ) / height; - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, byte[] pixels, int off, int scansize ) - { - for ( int r = 0; r < nHigh; ++r ) - { - int ty = r * height + y; - int th = h; - if ( ty + th > newHeight ) - th = newHeight - ty; - for ( int c = 0; c < nWide; ++c ) - { - int tx = c * width + x; - int tw = w; - if ( tx + tw > newWidth ) - tw = newWidth - tx; - consumer.setPixels( - tx, ty, tw, th, model, pixels, off, scansize ); - } - } - } - - public void setPixels( int x, int y, int w, int h, ColorModel model, int[] pixels, int off, int scansize ) - { - for ( int r = 0; r < nHigh; ++r ) - { - int ty = r * height + y; - int th = h; - if ( ty + th > newHeight ) - th = newHeight - ty; - for ( int c = 0; c < nWide; ++c ) - { - int tx = c * width + x; - int tw = w; - if ( tx + tw > newWidth ) - tw = newWidth - tx; - consumer.setPixels( - tx, ty, tw, th, model, pixels, off, scansize ); - } - } - } - - - // Main routine for command-line interface. - public static void main( String[] args ) - { - if ( args.length != 2 ) - usage(); - ImageFilterPlus filter = - new Tile( null, - Integer.parseInt( args[0] ), Integer.parseInt( args[1] ) ); - System.exit( - ImageFilterPlus.filterStream( System.in, System.out, filter ) ); - } - - private static void usage() - { - System.err.println( "usage: Tile " ); - System.exit( 1 ); - } - - } diff --git a/src/Acme/JPM/JPMUtils.java b/src/Acme/JPM/JPMUtils.java deleted file mode 100644 index 003c987a..00000000 --- a/src/Acme/JPM/JPMUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -// JPMUtils - static utility routines for the JPM packages -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme.JPM; - -import java.awt.*; -import java.awt.image.*; -import Acme.JPM.Filters.*; - -/// Static utility routines for the JPM packages. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class JPMUtils - { - - /// Filter one image into another. - public static Image filterImage( Component comp, ImageFilterPlus filter ) - { - return comp.createImage( - new FilteredImageSource( filter.getSource(), filter ) ); - } - - } diff --git a/src/Acme/LruHashtable.java b/src/Acme/LruHashtable.java deleted file mode 100644 index 9611a237..00000000 --- a/src/Acme/LruHashtable.java +++ /dev/null @@ -1,303 +0,0 @@ -// LruHashtable - a Hashtable that expires least-recently-used objects -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme; - -import java.util.*; - -/// A Hashtable that expires least-recently-used objects. -//

-// Use just like java.util.Hashtable, except that the initial-capacity -// parameter is required. Instead of growing bigger than that size, -// it will throw out objects that haven't been looked at in a while. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see java.util.Hashtable - -public class LruHashtable extends Hashtable - { - - // Number of buckets. - private static final int nBuckets = 2; - - // Load factor. - private float loadFactor; - - // When count exceeds this threshold, expires the old table. - private int threshold; - - // Capacity of each bucket. - private int eachCapacity; - - // The tables. - private Hashtable oldTable; - private Hashtable newTable; - - /// Constructs a new, empty hashtable with the specified initial - // capacity and the specified load factor. - // Unlike a plain Hashtable, an LruHashtable will never grow or - // shrink from this initial capacity. - // @param initialCapacity the initial number of buckets - // @param loadFactor a number between 0.0 and 1.0, it defines - // the threshold for expiring old entries - // @exception IllegalArgumentException If the initial capacity - // is less than or equal to zero. - // @exception IllegalArgumentException If the load factor is - // less than or equal to zero. - public LruHashtable( int initialCapacity, float loadFactor ) - { - // We have to call a superclass constructor, but we're not actually - // going to use it at all. The only reason we want to extend Hashtable - // is for type conformance. So, make a parent hash table of minimum - // size and then ignore it. - super( 1 ); - - if ( initialCapacity <= 0 || loadFactor <= 0.0 ) - throw new IllegalArgumentException(); - this.loadFactor = loadFactor; - threshold = (int) ( initialCapacity * loadFactor ) - 1; - eachCapacity = initialCapacity / nBuckets + 1; - oldTable = new Hashtable( eachCapacity, loadFactor ); - newTable = new Hashtable( eachCapacity, loadFactor ); - } - - /// Constructs a new, empty hashtable with the specified initial - // capacity. - // Unlike a plain Hashtable, an LruHashtable will never grow or - // shrink from this initial capacity. - // @param initialCapacity the initial number of buckets - public LruHashtable( int initialCapacity ) - { - this( initialCapacity, 0.75F ); - } - - /// Returns the number of elements contained in the hashtable. - public int size() - { - return newTable.size() + oldTable.size(); - } - - /// Returns true if the hashtable contains no elements. - public boolean isEmpty() - { - return size() == 0; - } - - /// Returns an enumeration of the hashtable's keys. - // @see LruHashtable#elements - // @see Enumeration - public synchronized Enumeration keys() - { - return new LruHashtableEnumerator( oldTable, newTable, true ); - } - - /// Returns an enumeration of the elements. Use the Enumeration methods - // on the returned object to fetch the elements sequentially. - // @see LruHashtable#keys - // @see Enumeration - public synchronized Enumeration elements() - { - return new LruHashtableEnumerator( oldTable, newTable, false ); - } - - /// Returns true if the specified object is an element of the hashtable. - // This operation is more expensive than the containsKey() method. - // @param value the value that we are looking for - // @exception NullPointerException If the value being searched - // for is equal to null. - // @see LruHashtable#containsKey - public synchronized boolean contains( Object value ) - { - if ( newTable.contains( value ) ) - return true; - if ( oldTable.contains( value ) ) - { - // We would like to move the object from the old table to the - // new table. However, we need keys to re-add the objects, and - // there's no good way to find all the keys for the given object. - // We'd have to enumerate through all the keys and check each - // one. Yuck. For now we just punt. Anyway, contains() is - // probably not a commonly-used operation. - return true; - } - return false; - } - - /// Returns true if the collection contains an element for the key. - // @param key the key that we are looking for - // @see LruHashtable#contains - public synchronized boolean containsKey( Object key ) - { - if ( newTable.containsKey( key ) ) - return true; - if ( oldTable.containsKey( key ) ) - { - // Move object from old table to new table. - Object value = oldTable.get( key ); - newTable.put( key, value ); - oldTable.remove( key ); - return true; - } - return false; - } - - /// Gets the object associated with the specified key in the - // hashtable. - // @param key the specified key - // @returns the element for the key or null if the key - // is not defined in the hash table. - // @see LruHashtable#put - public synchronized Object get( Object key ) - { - Object value; - value = newTable.get( key ); - if ( value != null ) - return value; - value = oldTable.get( key ); - if ( value != null ) - { - // Move object from old table to new table. - newTable.put( key, value ); - oldTable.remove( key ); - return value; - } - return null; - } - - /// Puts the specified element into the hashtable, using the specified - // key. The element may be retrieved by doing a get() with the same key. - // The key and the element cannot be null. - // @param key the specified key in the hashtable - // @param value the specified element - // @exception NullPointerException If the value of the element - // is equal to null. - // @see LruHashtable#get - // @return the old value of the key, or null if it did not have one. - public synchronized Object put( Object key, Object value ) - { - Object oldValue = newTable.put( key, value ); - if ( oldValue != null ) - return oldValue; - oldValue = oldTable.get( key ); - if ( oldValue != null ) - oldTable.remove( key ); - else - { - if ( size() >= threshold ) - { - // Rotate the tables. - oldTable = newTable; - newTable = new Hashtable( eachCapacity, loadFactor ); - } - } - return oldValue; - } - - /// Removes the element corresponding to the key. Does nothing if the - // key is not present. - // @param key the key that needs to be removed - // @return the value of key, or null if the key was not found. - public synchronized Object remove( Object key ) - { - Object oldValue = newTable.remove( key ); - if ( oldValue == null ) - oldValue = oldTable.remove( key ); - return oldValue; - } - - /// Clears the hash table so that it has no more elements in it. - public synchronized void clear() - { - newTable.clear(); - oldTable.clear(); - } - - /// Creates a clone of the hashtable. A shallow copy is made, - // the keys and elements themselves are NOT cloned. This is a - // relatively expensive operation. - public synchronized Object clone() - { - LruHashtable n = (LruHashtable) super.clone(); - n.newTable = (Hashtable) n.newTable.clone(); - n.oldTable = (Hashtable) n.oldTable.clone(); - return n; - } - - // toString() can be inherited. - - } - - -class LruHashtableEnumerator implements Enumeration - { - Enumeration oldEnum; - Enumeration newEnum; - boolean old; - - LruHashtableEnumerator( Hashtable oldTable, Hashtable newTable, boolean keys ) - { - if ( keys ) - { - oldEnum = oldTable.keys(); - newEnum = newTable.keys(); - } - else - { - oldEnum = oldTable.elements(); - newEnum = newTable.elements(); - } - old = true; - } - - public boolean hasMoreElements() - { - boolean r; - if ( old ) - { - r = oldEnum.hasMoreElements(); - if ( ! r ) - { - old = false; - r = newEnum.hasMoreElements(); - } - } - else - r = newEnum.hasMoreElements(); - return r; - } - - public Object nextElement() - { - if ( old ) - return oldEnum.nextElement(); - return newEnum.nextElement(); - } - - } diff --git a/src/Acme/Utils.java b/src/Acme/Utils.java deleted file mode 100644 index 6adf82ef..00000000 --- a/src/Acme/Utils.java +++ /dev/null @@ -1,1053 +0,0 @@ -// Utils - assorted static utility routines -// -// Copyright (C)1996,1998 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme; - -import java.util.*; -import java.io.*; -import java.net.*; - -/// Assorted static utility routines. -//

-// Whenever I come up with a static routine that might be of general use, -// I put it here. So far the class includes: -//

-// and lots more. -//

-// Fetch the software.
-// Fetch the entire Acme package. - -public class Utils - { - - /// Returns a date string formatted in Unix ls style - if it's within - // six months of now, Mmm dd hh:ss, else Mmm dd yyyy. - public static String lsDateStr( Date date ) - { - Calendar cal = new GregorianCalendar(); - cal.setTime( date ); - long dateTime = date.getTime(); - if ( dateTime == -1L ) - return "------------"; - long nowTime = (new Date()).getTime(); - String[] months = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - String part1 = - months[cal.get(Calendar.MONTH)] + - Fmt.fmt( cal.get(Calendar.DATE), 3 ); - if ( Math.abs( nowTime - dateTime ) < 183L * 24L * 60L * 60L * 1000L ) - return part1 + Fmt.fmt( cal.get(Calendar.HOUR_OF_DAY), 3 ) + ":" + - Fmt.fmt( cal.get(Calendar.MINUTE), 2, Fmt.ZF ); - else - return part1 + Fmt.fmt( cal.get(Calendar.YEAR), 6 ); - } - - - /// Returns "s" for numbers other than one, and "" for one. - public static String pluralStr( long n ) - { - if ( n == 1 ) - return ""; - else - return "s"; - } - - - // Various interval constants. Some are only approximate. - public static final long INT_SECOND = 1000L; - public static final long INT_MINUTE = INT_SECOND * 60L; - public static final long INT_HOUR = INT_MINUTE * 60L; - public static final long INT_DAY = INT_HOUR * 24L; - public static final long INT_WEEK = INT_DAY * 7L; - public static final long INT_MONTH = INT_DAY * 30L; - public static final long INT_YEAR = INT_DAY * 365L; - public static final long INT_DECADE = INT_DAY * 3652L; - - /// Returns a string approximately describing a given time interval. - // @param interval the interval, in milliseconds - public static String intervalStr( long interval ) - { - long decades, years, months, weeks, days, hours, minutes, seconds, millis; - - decades = interval / INT_DECADE; - interval -= decades * INT_DECADE; - years = interval / INT_YEAR; - interval -= years * INT_YEAR; - months = interval / INT_MONTH; - interval -= months * INT_MONTH; - weeks = interval / INT_WEEK; - interval -= weeks * INT_WEEK; - days = interval / INT_DAY; - interval -= days * INT_DAY; - hours = interval / INT_HOUR; - interval -= hours * INT_HOUR; - minutes = interval / INT_MINUTE; - interval -= minutes * INT_MINUTE; - seconds = interval / INT_SECOND; - interval -= seconds * INT_SECOND; - millis = interval; - - if ( decades > 0 ) - if ( years == 0 ) - return decades + " decade" + pluralStr( decades ); - else - return - decades + " decade" + pluralStr( decades ) + ", " + - years + " years" + pluralStr( years ); - else if ( years > 0 ) - if ( months == 0 ) - return years + " year" + pluralStr( years ); - else - return - years + " year" + pluralStr( years ) + ", " + - months + " month" + pluralStr( months ); - else if ( months > 0 ) - if ( weeks == 0 ) - return months + " month" + pluralStr( months ); - else - return - months + " month" + pluralStr( months ) + ", " + - weeks + " week" + pluralStr( weeks ); - else if ( weeks > 0 ) - if ( days == 0 ) - return weeks + " week" + pluralStr( weeks ); - else - return - weeks + " week" + pluralStr( weeks ) + ", " + - days + " day" + pluralStr( days ); - else if ( days > 0 ) - if ( hours == 0 ) - return days + " day" + pluralStr( days ); - else - return - days + " day" + pluralStr( days ) + ", " + - hours + " hour" + pluralStr( hours ); - else if ( hours > 0 ) - if ( minutes == 0 ) - return hours + " hour" + pluralStr( hours ); - else - return - hours + " hour" + pluralStr( hours ) + ", " + - minutes + " minute" + pluralStr( minutes ); - else if ( minutes > 0 ) - if ( seconds == 0 ) - return minutes + " minute" + pluralStr( minutes ); - else - return - minutes + " minute" + pluralStr( minutes ) + ", " + - seconds + " second" + pluralStr( seconds ); - else if ( seconds > 0 ) - if ( millis == 0 ) - return seconds + " second" + pluralStr( seconds ); - else - return - seconds + " second" + pluralStr( seconds ) + ", " + - millis + " millisecond" + pluralStr( millis ); - else - return millis + " millisecond" + pluralStr( millis ); - } - - - /// Returns the length of the initial segment of str which consists - // entirely of characters from charSet. - public static int strSpan( String str, String charSet ) - { - return strSpan( str, charSet, 0 ); - } - - /// Returns the length of the initial segment of str which consists - // entirely of characters from charSet, starting at the given index. - public static int strSpan( String str, String charSet, int fromIdx ) - { - int i; - for ( i = fromIdx; i < str.length(); ++i ) - if ( charSet.indexOf( str.charAt( i ) ) == -1 ) - break; - return i - fromIdx; - } - - /// Returns the length of the initial segment of str which consists - // entirely of characters NOT from charSet. - public static int strCSpan( String str, String charSet ) - { - return strCSpan( str, charSet, 0 ); - } - - /// Returns the length of the initial segment of str which consists - // entirely of characters NOT from charSet, starting at the given index. - public static int strCSpan( String str, String charSet, int fromIdx ) - { - int i; - for ( i = fromIdx; i < str.length(); ++i ) - if ( charSet.indexOf( str.charAt( i ) ) != -1 ) - break; - return i - fromIdx; - } - - /// Checks whether a string matches a given wildcard pattern. - // Only does ? and *, and multiple patterns separated by |. - public static boolean match( String pattern, String string ) - { - for ( int p = 0; ; ++p ) - { - for ( int s = 0; ; ++p, ++s ) - { - boolean sEnd = ( s >= string.length() ); - boolean pEnd = ( p >= pattern.length() || - pattern.charAt( p ) == '|' ); - if ( sEnd && pEnd ) - return true; - if ( sEnd || pEnd ) - break; - if ( pattern.charAt( p ) == '?' ) - continue; - if ( pattern.charAt( p ) == '*' ) - { - int i; - ++p; - for ( i = string.length(); i >= s; --i ) - if ( match( - pattern.substring( p ), - string.substring( i ) ) ) /* not quite right */ - return true; - break; - } - if ( pattern.charAt( p ) != string.charAt( s ) ) - break; - } - p = pattern.indexOf( '|', p ); - if ( p == -1 ) - return false; - } - } - -// /// Finds the maximum length of a string that matches a given wildcard -// // pattern. Only does ? and *, and multiple patterns separated by |. -// public static int matchSpan( String pattern, String string ) -// { -// // !!! -// return 0; -// } - - /// Returns the length of the initial segment of str1 that equals str2. - public static int sameSpan( String str1, String str2 ) - { - int i; - for ( i = 0; - i < str1.length() && i < str2.length() && - str1.charAt( i ) == str2.charAt( i ); - ++i ) - ; - return i; - } - - /// Returns the number of times the given character appears in the string. - public static int charCount( String str, char c ) - { - int n = 0; - for ( int i = 0; i < str.length(); ++i ) - if ( str.charAt( i ) == c ) - ++n; - return n; - } - - - /// Turns a String into an array of Strings, by using StringTokenizer - // to split it up at whitespace. - public static String[] splitStr( String str ) - { - StringTokenizer st = new StringTokenizer( str ); - int n = st.countTokens(); - String[] strs = new String[n]; - for ( int i = 0; i < n; ++i ) - strs[i] = st.nextToken(); - return strs; - } - - /// Turns a String into an array of Strings, by splitting it at - // the specified character. This does not use StringTokenizer, - // and therefore can handle empty fields. - public static String[] splitStr( String str, char delim ) - { - int n = 1; - int index = -1; - while ( true ) - { - index = str.indexOf( delim, index + 1 ); - if ( index == -1 ) - break; - ++n; - } - String[] strs = new String[n]; - index = -1; - for ( int i = 0; i < n - 1; ++i ) - { - int nextIndex = str.indexOf( delim, index + 1 ); - strs[i] = str.substring( index + 1, nextIndex ); - index = nextIndex; - } - strs[n - 1] = str.substring( index + 1 ); - return strs; - } - - /// Turns an array of Strings into a single String, with the components - // separated by spaces. - public static String flattenStrarr( String[] strs ) - { - StringBuffer sb = new StringBuffer(); - for ( int i = 0; i < strs.length; ++i ) - { - if ( i > 0 ) - sb.append( ' ' ); - sb.append( strs[i] ); - } - return sb.toString(); - } - - /// Sorts an array of Strings. - // Java currently has no general sort function. Sorting Strings is - // common enough that it's worth making a special case. - public static void sortStrings( String[] strings ) - { - // Just does a bubblesort. - for ( int i = 0; i < strings.length - 1; ++i ) - { - for ( int j = i + 1; j < strings.length; ++j ) - { - if ( strings[i].compareTo( strings[j] ) > 0 ) - { - String t = strings[i]; - strings[i] = strings[j]; - strings[j] = t; - } - } - } - } - - /// Locates a String in an array of Strings. - // Returns -1 if the String is not found. - public static int indexOfString( String[] strings, String string ) - { - for ( int i = 0; i < strings.length; ++i ) - if ( string.equals( strings[i] ) ) - return i; - return -1; - } - - /// Locates a String in an array of Strings, ignoring case. - // Returns -1 if the String is not found. - public static int indexOfStringIgnoreCase( String[] strings, String string ) - { - for ( int i = 0; i < strings.length; ++i ) - if ( string.equalsIgnoreCase( strings[i] ) ) - return i; - return -1; - } - - /// Compares two arrays of Strings for equality. - public static boolean equalsStrings( String[] strings1, String[] strings2 ) - { - if ( strings1.length != strings2.length ) - return false; - for ( int i = 0; i < strings1.length; ++i ) - if ( ! strings1[i].equals( strings2[i] ) ) - return false; - return true; - } - - - /// Returns the number a raised to the power of b. Long version - // of Math.pow(). Throws ArithmeticException if b is negative. - public static long pow( long a, long b ) throws ArithmeticException - { - if ( b < 0 ) - throw new ArithmeticException(); - long r = 1; - while ( b != 0 ) - { - if ( odd( b ) ) - r *= a; - b >>>= 1; - a *= a; - } - return r; - } - - - /// Parse an integer, returning a default value on errors. - public static int parseInt( String str, int def ) - { - try - { - return Integer.parseInt( str ); - } - catch ( Exception e ) - { - return def; - } - } - - /// Parse a long, returning a default value on errors. - public static long parseLong( String str, long def ) - { - try - { - return Long.parseLong( str ); - } - catch ( Exception e ) - { - return def; - } - } - - - /// An array-to-String routine. Handles arrays of arbitrary - // type, including nested arrays. Sample output: - //

-    // byte[]:    { (byte)0, (byte)1, (byte)2 }
-    // char[]:    { '0', '1', '2' }
-    // short[]:   { (short)0, (short)1, (short)2 }
-    // int[]:     { 0, 1, 2 }
-    // long[]:    { 0L, 1L, 2L }
-    // float[]:   { 0F, 1F, 2F }
-    // double[]:  { 0D, 1D, 2D }
-    // String[]:  { "0", "1", "2" }
-    // int[][]:   { { 0, 1, 2 }, { 3, 4, 5 } }
-    // 
- public static String arrayToString( Object o ) - { - if ( o == null ) - return "null"; - String cl = o.getClass().getName(); - if ( ! cl.startsWith( "[" ) ) - // It's not an array; just call its toString method. - return o.toString(); - StringBuffer sb = new StringBuffer( "{ " ); - if ( o instanceof byte[] ) - { - byte[] ba = (byte[]) o; - for ( int i = 0; i < ba.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( "(byte)" ); - sb.append( ba[i] ); - } - } - else if ( o instanceof char[] ) - { - char[] ca = (char[]) o; - for ( int i = 0; i < ca.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( "'" ); - sb.append( ca[i] ); - sb.append( "'" ); - } - } - else if ( o instanceof short[] ) - { - short[] sa = (short[]) o; - for ( int i = 0; i < sa.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( "(short)" ); - sb.append( sa[i] ); - } - } - else if ( o instanceof int[] ) - { - int[] ia = (int[]) o; - for ( int i = 0; i < ia.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( ia[i] ); - } - } - else if ( o instanceof long[] ) - { - long[] la = (long[]) o; - for ( int i = 0; i < la.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( la[i] ); - sb.append( "L" ); - } - } - else if ( o instanceof float[] ) - { - float[] fa = (float[]) o; - for ( int i = 0; i < fa.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( fa[i] ); - sb.append( "F" ); - } - } - else if ( o instanceof double[] ) - { - double[] da = (double[]) o; - for ( int i = 0; i < da.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( da[i] ); - sb.append( "D" ); - } - } - else if ( o instanceof String ) - { - // Special-case Strings so we can surround them with quotes. - String[] sa = (String[]) o; - for ( int i = 0; i < sa.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( "\"" ); - sb.append( sa[i] ); - sb.append( "\"" ); - } - } - else if ( cl.startsWith( "[L" ) ) - { - // Some random class. - Object[] oa = (Object[]) o; - for ( int i = 0; i < oa.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( oa[i] ); - } - } - else if ( cl.startsWith( "[[" ) ) - { - // Nested arrays. - Object[] aa = (Object[]) o; - for ( int i = 0; i < aa.length; ++i ) - { - if ( i > 0 ) sb.append( ", " ); - sb.append( arrayToString( aa[i] ) ); - } - } - else - sb.append( "(unknown array type)" ); - sb.append( " }" ); - return sb.toString(); - } - - - /// Check if an object extends a given class or one of its superclasses. - // An instanceof that works on Class objects at runtime, instead - // of type descriptors at compile time. - public static boolean instanceOf( Object o, Class cl ) - { - // Null check. - if ( o == null || cl == null ) - return false; - Class ocl = o.getClass(); - // Check if they are the same class. - if ( ocl.equals( cl ) ) - return true; - // If the class is not itself an interface, then check its interfaces. - if ( ! cl.isInterface() ) - { - Class ifs[] = cl.getInterfaces(); - for ( int i = 0; i < ifs.length; ++i ) - if ( instanceOf( o, ifs[i] ) ) - return true; - } - // And check supeclasses. - Class scl = cl.getSuperclass(); - if ( scl != null ) - if ( instanceOf( o, scl ) ) - return true; - // Guess not. - return false; - } - - - /// Test is a number is even. - public static boolean even( long n ) - { - return ( n & 1 ) == 0; - } - - /// Test is a number is odd. - public static boolean odd( long n ) - { - return ( n & 1 ) != 0; - } - - - /// Count the number of 1-bits in a byte. - public static int countOnes( byte n ) - { - return countOnes( n & 0xffL ); - } - - /// Count the number of 1-bits in an int. - public static int countOnes( int n ) - { - return countOnes( n & 0xffffffffL ); - } - - /// Count the number of 1-bits in a long. - public static int countOnes( long n ) - { - // There are faster ways to do this, all the way up to looking - // up bytes in a 256-element table. But this is not too bad. - int count = 0; - while ( n != 0 ) - { - if ( odd( n ) ) - ++count; - n >>>= 1; - } - return count; - } - - - /// A fixed version of java.io.InputStream.read(byte[], int, int). The - // standard version catches and ignores IOExceptions from below. - // This version sends them on to the caller. - public static int read( InputStream in, byte[] b, int off, int len ) throws IOException - { - if ( len <= 0 ) - return 0; - int c = in.read(); - if ( c == -1 ) - return -1; - if ( b != null ) - b[off] = (byte) c; - int i; - for ( i = 1; i < len ; ++i ) - { - c = in.read(); - if ( c == -1 ) - break; - if ( b != null ) - b[off + i] = (byte) c; - } - return i; - } - - /// A version of read that reads the entire requested block, instead - // of sometimes terminating early. - // @return -1 on EOF, otherwise len - public static int readFully( InputStream in, byte[] b, int off, int len ) throws IOException - { - int l, r; - for ( l = 0; l < len; ) - { - r = read( in, b, l, len - l ); - if ( r == -1 ) - return -1; - l += r; - } - return len; - } - - - /// Make a URL with no ref part and no query string. Also, if it's - // a directory then make sure there's a trailing slash. - public static URL plainUrl( URL context, String urlStr ) throws MalformedURLException - { - URL url = new URL( context, urlStr ); - String fileStr = url.getFile(); - int i = fileStr.indexOf( '?' ); - if ( i != -1 ) - fileStr = fileStr.substring( 0, i ); - url = new URL( - url.getProtocol(), url.getHost(), url.getPort(), fileStr ); - if ( ( ! fileStr.endsWith( "/" ) ) && - urlStrIsDir( url.toExternalForm() ) ) - { - fileStr = fileStr + "/"; - url = new URL( - url.getProtocol(), url.getHost(), url.getPort(), fileStr ); - } - return url; - } - - /// Make a URL with no ref part and no query string. Also, if it's - // a directory then make sure there's a trailing slash. - public static URL plainUrl( String urlStr ) throws MalformedURLException - { - return plainUrl( null, urlStr ); - } - - /// Figure out the base URL for a given URL. What this means is - // if the URL points to a directory, you get that directory; if the - // URL points to a file, you get the directory the file is in. - public static String baseUrlStr( String urlStr ) - { - if ( urlStr.endsWith( "/" ) ) - return urlStr; - if ( urlStrIsDir( urlStr ) ) - return urlStr + "/"; - return urlStr.substring( 0, urlStr.lastIndexOf( '/' ) + 1 ); - } - - /// Makes sure if a URL is a directory, it ends with a slash. - public static String fixDirUrlStr( String urlStr ) - { - if ( urlStr.endsWith( "/" ) ) - return urlStr; - if ( urlStrIsDir( urlStr ) ) - return urlStr + "/"; - return urlStr; - } - - /// Figures out whether a URL points to a directory or not. - // Web servers are lenient and accept directory-URLs without - // the trailing slash. What they actually do is return a - // redirect to the same URL with the trailing slash appended. - // Unfortunately, Java doesn't let us see that such a redirect - // happened. Instead we have to figure out it's a directory - // indirectly and heuristically. - public static boolean urlStrIsDir( String urlStr ) - { - // If it ends with a slash, it's probably a directory. - if ( urlStr.endsWith( "/" ) ) - return true; - - // If the last component has a dot, it's probably not a directory. - int lastSlash = urlStr.lastIndexOf( '/' ); - int lastPeriod = urlStr.lastIndexOf( '.' ); - if ( lastPeriod != -1 && ( lastSlash == -1 || lastPeriod > lastSlash ) ) - return false; - - // Otherwise, append a slash and try to connect. This is - // fairly expensive. - String urlStrWithSlash = urlStr + "/"; - try - { - URL url = new URL( urlStrWithSlash ); - InputStream f = url.openStream(); - f.close(); - // Worked fine - it's probably a directory. - return true; - } - catch ( Exception e ) - { - // Got an error - must not be a directory. - return false; - } - } - - - // Figures out whether a URL is absolute or not. - public static boolean urlStrIsAbsolute( String urlStr ) - { - if ( urlStr.startsWith( "/" ) || urlStr.indexOf( ":/" ) != -1 ) - return true; - // Should handle :8000/ and such too. - return false; - } - - // Returns an equivalent URL string that is guaranteed to be absolute. - public static String absoluteUrlStr( String urlStr, URL contextUrl ) throws MalformedURLException - { - URL url = new URL( contextUrl, urlStr ); - return url.toExternalForm(); - } - - - /// URLDecoder to go along with java.net.URLEncoder. Why there isn't - // already a decoder in the standard library is a mystery to me. - public static String urlDecoder( String encoded ) - { - StringBuffer decoded = new StringBuffer(); - int len = encoded.length(); - for ( int i = 0; i < len; ++i ) - { - if ( encoded.charAt( i ) == '%' && i + 2 < len ) - { - int d1 = Character.digit( encoded.charAt( i + 1 ), 16 ); - int d2 = Character.digit( encoded.charAt( i + 2 ), 16 ); - if ( d1 != -1 && d2 != -1 ) - decoded.append( (char) ( ( d1 << 4 ) + d2 ) ); - i += 2; - } - else if ( encoded.charAt( i ) == '+' ) - decoded.append( ' ' ); - else - decoded.append( encoded.charAt( i ) ); - } - return decoded.toString(); - } - - - /// A base-64 encoder, necessary for doing the client side of Basic - // Authentication. This encodes binary data as printable ASCII - // characters. Three 8-bit binary bytes are turned into four 6-bit - // values, like so: - // - // [11111111] [22222222] [33333333] - // - // [111111] [112222] [222233] [333333] - // - // Then the 6-bit values are represented using the characters "A-Za-z0-9+/". - public static String base64Encode( byte[] src ) - { - StringBuffer encoded = new StringBuffer(); - int i, phase = 0; - char c = 0; - - for ( i = 0; i < src.length; ++i ) - { - switch ( phase ) - { - case 0: - c = b64EncodeTable[( src[i] >> 2 ) & 0x3f]; - encoded.append( c ); - c = b64EncodeTable[( src[i] & 0x3 ) << 4]; - encoded.append( c ); - ++phase; - break; - case 1: - c = b64EncodeTable[ - ( b64DecodeTable[c] | ( src[i] >> 4 ) ) & 0x3f]; - encoded.setCharAt( encoded.length() - 1, c ); - c = b64EncodeTable[( src[i] & 0xf ) << 2]; - encoded.append( c ); - ++phase; - break; - case 2: - c = b64EncodeTable[ - ( b64DecodeTable[c] | ( src[i] >> 6 ) ) & 0x3f]; - encoded.setCharAt( encoded.length() - 1, c ); - c = b64EncodeTable[src[i] & 0x3f]; - encoded.append( c ); - phase = 0; - break; - } - } - /* Pad with ='s. */ - while ( phase++ < 3 ) - encoded.append( '=' ); - return encoded.toString(); - } - - private static char b64EncodeTable[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 00-07 - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 08-15 - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16-23 - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24-31 - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32-39 - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40-47 - 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48-55 - '4', '5', '6', '7', '8', '9', '+', '/' // 56-63 - }; - - private static int b64DecodeTable[] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 00-0F - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 10-1F - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, // 20-2F - 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, // 30-3F - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, // 40-4F - 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, // 50-5F - -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, // 60-6F - 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, // 70-7F - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 80-8F - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 90-9F - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // A0-AF - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // B0-BF - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // C0-CF - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // D0-DF - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // E0-EF - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 // F0-FF - }; - - /// A base-64 encoder that takes a String, for convenience. - public static String base64Encode( String srcString ) - { - byte[] src = new byte[srcString.length()]; - srcString.getBytes( 0, src.length, src, 0 ); - return base64Encode( src ); - } - - - /// Check if an array contains a given element. - public static boolean arraycontains( Object[] array, Object element ) - { - for ( int i = 0; i < array.length; ++i ) - if ( array[i].equals( element ) ) - return true; - return false; - } - - - /// Run a program on the host system. - //

- // This routine runs the specified command, waits for it to - // finish, and returns the exit status. - // This is like the Unix system() routine. Unlike the Unix version, - // though, stdout and stderr get thrown away unless you redirect them. - public static int system( String cmd ) - { - try - { - return runCommand( cmd ).waitFor(); - } - catch ( IOException e ) - { - return -1; - } - catch ( InterruptedException e ) - { - return -1; - } - } - - /// Run a program on the host system, and capture the output. - //

- // This routine runs the specified command, and returns an InputStream - // for reading the output of the program. - //

- // WARNING: In JDK1.0.2 there is a serious bug in the process - // IO routines, such that reading all the way to the end of a process's - // output will invariably get you an IOException( "read error" ). - // In some cases you will also lose the last bufferload of - // the output. The workaround is to add a " ; sleep 1" to the end of - // your command, and to ignore the "read error" IOException. - public static InputStream popenr( String cmd ) - { - try - { - return runCommand( cmd ).getInputStream(); - } - catch ( IOException e ) - { - return null; - } - } - - /// Run a program on the host system, and send it some input. - //

- // This routine runs the specified command, and returns an OutputStream - // for writing the program's input. - public static OutputStream popenw( String cmd ) - { - try - { - return runCommand( cmd ).getOutputStream(); - } - catch ( IOException e ) - { - return null; - } - } - - /// Run a program on the host system. - //

- // This routine runs the specified command, and returns a Process - // object so you can do what you like with it. - //

- // WARNING: In JDK1.0.2 there is a serious bug in the process - // IO routines, such that reading all the way to the end of a process's - // output will invariably get you an IOException( "read error" ). - // In some cases you will also lose the last bufferload of - // the output. The workaround is to add a " ; sleep 1" to the end of - // your command, and to ignore the "read error" IOException. - public static Process runCommand( String cmd ) throws IOException - { - Runtime runtime = Runtime.getRuntime(); - String[] shCmd = new String[3]; - shCmd[0] = "/bin/sh"; - shCmd[1] = "-c"; - shCmd[2] = cmd; - return runtime.exec( shCmd ); - } - - - /// Copy the input to the output until EOF. - public static void copyStream( InputStream in, OutputStream out ) throws IOException - { - byte[] buf = new byte[4096]; - int len; - while ( ( len = in.read( buf ) ) != -1 ) - out.write( buf, 0, len ); - } - - /// Copy the input to the output until EOF. - public static void copyStream( Reader in, Writer out ) throws IOException - { - char[] buf = new char[4096]; - int len; - while ( ( len = in.read( buf ) ) != -1 ) - out.write( buf, 0, len ); - } - - /// Copy the input to the output until EOF. - public static void copyStream( InputStream in, Writer out ) throws IOException - { - byte[] buf1 = new byte[4096]; - char[] buf2 = new char[4096]; - int len, i; - while ( ( len = in.read( buf1 ) ) != -1 ) - { - for ( i = 0; i < len; ++i ) - buf2[i] = (char) buf1[i]; - out.write( buf2, 0, len ); - } - } - - /// Copy the input to the output until EOF. - public static void copyStream( Reader in, OutputStream out ) throws IOException - { - char[] buf1 = new char[4096]; - byte[] buf2 = new byte[4096]; - int len, i; - while ( ( len = in.read( buf1 ) ) != -1 ) - { - for ( i = 0; i < len; ++i ) - buf2[i] = (byte) buf1[i]; - out.write( buf2, 0, len ); - } - } - - - /// Dump out the current call stack. - public static void dumpStack( PrintStream p ) - { - (new Throwable()).printStackTrace( p ); - } - - /// Dump out the current call stack onto System.err. - public static void dumpStack() - { - (new Throwable()).printStackTrace(); - } - - } diff --git a/src/Acme/WildcardDictionary.java b/src/Acme/WildcardDictionary.java deleted file mode 100644 index ee957be7..00000000 --- a/src/Acme/WildcardDictionary.java +++ /dev/null @@ -1,147 +0,0 @@ -// WildcardDictionary - a dictionary with wildcard lookups -// -// Copyright (C) 1996 by Jef Poskanzer . All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. -// -// Visit the ACME Labs Java page for up-to-date versions of this and other -// fine Java utilities: http://www.acme.com/java/ - -package Acme; - -import java.util.*; - -/// A dictionary with wildcard lookups. -//

-// The keys in this dictionary are wildcard patterns. When you do a get(), -// the string you pass in is matched against all the patterns, and the -// first match is returned. -//

-// The wildcard matcher is fairly simple, it implements * meaning any -// string, ? meaning any single character, and | separating multiple -// patterns. All other characters must match literally. -//

-// Fetch the software.
-// Fetch the entire Acme package. -//

-// @see Acme.Utils#match - -public class WildcardDictionary extends Dictionary - { - - private Vector keys; - private Vector elements; - - /// Constructor. - public WildcardDictionary() - { - keys = new Vector(); - elements = new Vector(); - } - - /// Returns the number of elements contained within the dictionary. - public int size() - { - return elements.size(); - } - - /// Returns true if the dictionary contains no elements. - public boolean isEmpty() - { - return size() == 0; - } - - /// Returns an enumeration of the dictionary's keys. - public Enumeration keys() - { - return keys.elements(); - } - - /// Returns an enumeration of the elements. Use the Enumeration methods - // on the returned object to fetch the elements sequentially. - public Enumeration elements() - { - return elements.elements(); - } - - /// Gets the object associated with the specified key in the dictionary. - // The key is assumed to be a String, which is matched against - // the wildcard-pattern keys in the dictionary. - // @param key the string to match - // @returns the element for the key, or null if there's no match - // @see Acme.Utils#match - public synchronized Object get( Object key ) - { - String sKey = (String) key; - for ( int i = 0; i < keys.size(); ++i ) - { - String thisKey = (String) keys.elementAt( i ); - if ( Acme.Utils.match( thisKey, sKey ) ) - return elements.elementAt( i ); - } - return null; - } - - /// Puts the specified element into the Dictionary, using the specified - // key. The element may be retrieved by doing a get() with the same - // key. The key and the element cannot be null. - // @param key the specified wildcard-pattern key - // @param value the specified element - // @return the old value of the key, or null if it did not have one. - // @exception NullPointerException If the value of the specified - // element is null. - public synchronized Object put( Object key, Object element ) - { - int i = keys.indexOf( key ); - if ( i != -1 ) - { - Object oldElement = elements.elementAt( i ); - elements.setElementAt( element, i ); - return oldElement; - } - else - { - keys.addElement( key ); - elements.addElement( element ); - return null; - } - } - - /// Removes the element corresponding to the key. Does nothing if the - // key is not present. - // @param key the key that needs to be removed - // @return the value of key, or null if the key was not found. - public synchronized Object remove( Object key ) - { - int i = keys.indexOf( key ); - if ( i != -1 ) - { - Object oldElement = elements.elementAt( i ); - keys.removeElementAt( i ); - elements.removeElementAt( i ); - return oldElement; - } - else - return null; - } - - } diff --git a/src/helma/xmlrpc/AsyncCallback.java b/src/helma/xmlrpc/AsyncCallback.java deleted file mode 100644 index 78815a64..00000000 --- a/src/helma/xmlrpc/AsyncCallback.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2001 Hannes Wallnoefer - */ - -package helma.xmlrpc; - -import java.net.URL; - -/** - * A callback interface for an asynchronous XML-RPC call. - */ - -public interface AsyncCallback { - - /** - * Call went ok, handle result. - */ - public void handleResult (Object result, URL url, String method); - - /** - * Something went wrong, handle error. - */ - public void handleError (Exception exception, URL url, String method); - -} diff --git a/src/helma/xmlrpc/AuthenticatedXmlRpcHandler.java b/src/helma/xmlrpc/AuthenticatedXmlRpcHandler.java deleted file mode 100644 index c6e5d0f3..00000000 --- a/src/helma/xmlrpc/AuthenticatedXmlRpcHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2000 Hannes Wallnoefer - */ - -package helma.xmlrpc; - -import java.util.Vector; - -/** - * An XML-RPC handler that also handles user authentication. - */ - -public interface AuthenticatedXmlRpcHandler { - - /** - * Return the result, or throw an Exception if something went wrong. - */ - public Object execute (String method, Vector params, String user, String password) throws Exception; - -} \ No newline at end of file diff --git a/src/helma/xmlrpc/Base64.java b/src/helma/xmlrpc/Base64.java deleted file mode 100644 index 86cf8e5f..00000000 --- a/src/helma/xmlrpc/Base64.java +++ /dev/null @@ -1,286 +0,0 @@ -//////////////////////license & copyright header///////////////////////// -// // -// Base64 - encode/decode data using the Base64 encoding scheme // -// // -// Copyright (c) 1998 by Kevin Kelley // -// // -// This library is free software; you can redistribute it and/or // -// modify it under the terms of the GNU Lesser General Public // -// License as published by the Free Software Foundation; either // -// version 2.1 of the License, or (at your option) any later version. // -// // -// This library is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU Lesser General Public License for more details. // -// // -// You should have received a copy of the GNU Lesser General Public // -// License along with this library; if not, write to the Free Software // -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // -// 02111-1307, USA, or contact the author: // -// // -// Kevin Kelley - 30718 Rd. 28, La Junta, CO, // -// 81050 USA. // -// // -////////////////////end license & copyright header/////////////////////// - -package helma.xmlrpc; - -import java.io.*; // needed only for main() method. - - -/** -* Provides encoding of raw bytes to base64-encoded characters, and -* decoding of base64 characters to raw bytes. -* -* @author Kevin Kelley (kelley@ruralnet.net) -* @version 1.3 -* @date 06 August 1998 -* @modified 14 February 2000 -* @modified 22 September 2000 -*/ -public class Base64 { - -/** -* returns an array of base64-encoded characters to represent the -* passed data array. -* -* @param data the array of bytes to encode -* @return base64-coded character array. -*/ -static public char[] encode(byte[] data) -{ - char[] out = new char[((data.length + 2) / 3) * 4]; - - // - // 3 bytes encode to 4 chars. Output is always an even - // multiple of 4 characters. - // - for (int i=0, index=0; i>= 6; - out[index+2] = alphabet[(trip? (val & 0x3F): 64)]; - val >>= 6; - out[index+1] = alphabet[val & 0x3F]; - val >>= 6; - out[index+0] = alphabet[val & 0x3F]; - } - return out; -} - - /** - * Decodes a BASE-64 encoded stream to recover the original - * data. White space before and after will be trimmed away, - * but no other manipulation of the input will be performed. - * - * As of version 1.2 this method will properly handle input - * containing junk characters (newlines and the like) rather - * than throwing an error. It does this by pre-parsing the - * input and generating from that a count of VALID input - * characters. - **/ -static public byte[] decode(char[] data) -{ - // as our input could contain non-BASE64 data (newlines, - // whitespace of any sort, whatever) we must first adjust - // our count of USABLE data so that... - // (a) we don't misallocate the output array, and - // (b) think that we miscalculated our data length - // just because of extraneous throw-away junk - - int tempLen = data.length; - for( int ix=0; ix 255) || codes[ data[ix] ] < 0 ) - --tempLen; // ignore non-valid chars and padding - } - // calculate required length: - // -- 3 bytes for every 4 valid base64 chars - // -- plus 2 bytes if there are 3 extra base64 chars, - // or plus 1 byte if there are 2 extra. - - int len = (tempLen / 4) * 3; - if ((tempLen % 4) == 3) len += 2; - if ((tempLen % 4) == 2) len += 1; - - byte[] out = new byte[len]; - - - - int shift = 0; // # of excess bits stored in accum - int accum = 0; // excess bits - int index = 0; - - // we now go through the entire array (NOT using the 'tempLen' value) - for (int ix=0; ix255)? -1: codes[ data[ix] ]; - - if ( value >= 0 ) // skip over non-code - { - accum <<= 6; // bits shift up by 6 each time thru - shift += 6; // loop, with new bits being put in - accum |= value; // at the bottom. - if ( shift >= 8 ) // whenever there are 8 or more shifted in, - { - shift -= 8; // write them out (from the top, leaving any - out[index++] = // excess at the bottom for next iteration. - (byte) ((accum >> shift) & 0xff); - } - } - // we will also have skipped processing a padding null byte ('=') here; - // these are used ONLY for padding to an even length and do not legally - // occur as encoded data. for this reason we can ignore the fact that - // no index++ operation occurs in that special case: the out[] array is - // initialized to all-zero bytes to start with and that works to our - // advantage in this combination. - } - - // if there is STILL something wrong we just have to throw up now! - if( index != out.length) - { - throw new Error("Miscalculated data length (wrote " + index + " instead of " + out.length + ")"); - } - - return out; -} - - -// -// code characters for values 0..63 -// -static private char[] alphabet = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" - .toCharArray(); - -// -// lookup table for converting base64 characters to value in range 0..63 -// -static private byte[] codes = new byte[256]; -static { - for (int i=0; i<256; i++) codes[i] = -1; - for (int i = 'A'; i <= 'Z'; i++) codes[i] = (byte)( i - 'A'); - for (int i = 'a'; i <= 'z'; i++) codes[i] = (byte)(26 + i - 'a'); - for (int i = '0'; i <= '9'; i++) codes[i] = (byte)(52 + i - '0'); - codes['+'] = 62; - codes['/'] = 63; -} - - - - -/////////////////////////////////////////////////// -// remainder (main method and helper functions) is -// for testing purposes only, feel free to clip it. -/////////////////////////////////////////////////// - -public static void main(String[] args) -{ - boolean decode = false; - - if (args.length == 0) { - System.out.println("usage: java Base64 [-d[ecode]] filename"); - System.exit(0); - } - for (int i=0; i 0) baos.write(buf, 0, count); - } - is.close(); - } - catch (Exception e) { e.printStackTrace(); } - - return baos.toByteArray(); -} - -private static char[] readChars(File file) -{ - CharArrayWriter caw = new CharArrayWriter(); - try - { - Reader fr = new FileReader(file); - Reader in = new BufferedReader(fr); - int count = 0; - char[] buf = new char[16384]; - while ((count=in.read(buf)) != -1) { - if (count > 0) caw.write(buf, 0, count); - } - in.close(); - } - catch (Exception e) { e.printStackTrace(); } - - return caw.toCharArray(); -} - -private static void writeBytes(File file, byte[] data) { - try { - OutputStream fos = new FileOutputStream(file); - OutputStream os = new BufferedOutputStream(fos); - os.write(data); - os.close(); - } - catch (Exception e) { e.printStackTrace(); } -} - -private static void writeChars(File file, char[] data) { - try { - Writer fos = new FileWriter(file); - Writer os = new BufferedWriter(fos); - os.write(data); - os.close(); - } - catch (Exception e) { e.printStackTrace(); } -} -/////////////////////////////////////////////////// -// end of test code. -/////////////////////////////////////////////////// - -} diff --git a/src/helma/xmlrpc/ServerInputStream.java b/src/helma/xmlrpc/ServerInputStream.java deleted file mode 100644 index b9213a2d..00000000 --- a/src/helma/xmlrpc/ServerInputStream.java +++ /dev/null @@ -1,74 +0,0 @@ -package helma.xmlrpc; - -import java.io.*; - -// This class is borrowed from Apache JServ -class ServerInputStream extends InputStream { - // bytes remaining to be read from the input stream. This is - // initialized from CONTENT_LENGTH (or getContentLength()). - // This is used in order to correctly return a -1 when all the - // data POSTed was read. If this is left to -1, content length is - // assumed as unknown and the standard InputStream methods will be used - long available = -1; - long markedAvailable; - - private BufferedInputStream in; - - public ServerInputStream(BufferedInputStream in, int available) { - this.in = in; - this.available = available; - } - - public int read() throws IOException { - if (available > 0) { - available--; - return in.read(); - } else if (available == -1) - return in.read (); - return -1; - } - - public int read(byte b[]) throws IOException { - return read(b, 0, b.length); - } - - public int read(byte b[], int off, int len) throws IOException { - if (available > 0) { - if (len > available) { - // shrink len - len = (int) available; - } - int read = in.read(b, off, len); - if (read != -1) { - available -= read; - } else { - available = -1; - } - return read; - } else if (available == -1) - return in.read (b, off, len); - return -1; - } - - public long skip(long n) throws IOException { - long skip = in.skip(n); - if (available > 0) - available -= skip; - return skip; - } - - public void mark (int readlimit) { - in.mark (readlimit); - markedAvailable = available; - } - - public void reset () throws IOException { - in.reset (); - available = markedAvailable; - } - - public boolean markSupported () { - return true; - } - -} diff --git a/src/helma/xmlrpc/WebServer.java b/src/helma/xmlrpc/WebServer.java deleted file mode 100644 index f6bbd219..00000000 --- a/src/helma/xmlrpc/WebServer.java +++ /dev/null @@ -1,460 +0,0 @@ -package helma.xmlrpc; - -import java.io.*; -import java.net.*; -import java.util.*; - -/** - * A minimal web server that exclusively handles XML-RPC requests. - */ -public class WebServer implements Runnable { - - XmlRpcServer xmlrpc; - private ServerSocket serverSocket; - private int port; - private Thread listener; - private boolean paranoid; - private Vector accept, deny; - private Stack threadpool; - private ThreadGroup runners; - - - static final byte[] ctype = "Content-Type: text/xml\r\n".getBytes(); - static final byte[] clength = "Content-Length: ".getBytes(); - static final byte[] newline = "\r\n".getBytes(); - static final byte[] doubleNewline = "\r\n\r\n".getBytes(); - static final byte[] conkeep = "Connection: Keep-Alive\r\n".getBytes(); - static final byte[] conclose = "Connection: close\r\n".getBytes(); - static final byte[] ok = " 200 OK\r\n".getBytes(); - static final byte[] server = "Server: Helma XML-RPC 1.0\r\n".getBytes(); - - - /** - * This can be called from command line, but you'll have to edit and recompile - * to change the server port or handler objects. By default, it sets up the following responders: - *

- */ - public static void main (String args[]) { - System.err.println ("Usage: java helma.xmlrpc.WebServer [port]"); - int p = 8080; - if (args.length > 0) try { - p = Integer.parseInt (args[0]); - } catch (NumberFormatException nfx) { - System.err.println ("Error parsing port number: "+args[0]); - } - // XmlRpc.setDebug (true); - XmlRpc.setKeepAlive (true); - // XmlRpc.setEncoding ("UTF-8"); - try { - WebServer webserver = new WebServer (p); - // webserver.setParanoid (true); - // webserver.acceptClient ("192.168.*.*"); - webserver.addHandler ("string", "Welcome to XML-RPC!"); - webserver.addHandler ("math", Math.class); - webserver.addHandler ("auth", new AuthDemo()); - webserver.addHandler ("$default", new Echo()); - // XmlRpcClients can be used as Proxies in XmlRpcServers which is a cool feature for applets. - webserver.addHandler ("mttf", new XmlRpcClient ("http://www.mailtothefuture.com:80/RPC2")); - System.err.println ("started web server on port "+p); - } catch (IOException x) { - System.err.println ("Error creating web server: "+x); - } - - } - - - /** - * Creates a Web server at the specified port number. - */ - public WebServer (int port) throws IOException { - this (port, null); - } - - - /** - * Creates a Web server at the specified port number and IP address. - */ - public WebServer (int port, InetAddress add) throws IOException { - this.port = port; - xmlrpc = new XmlRpcServer (); - accept = new Vector (); - deny = new Vector (); - threadpool = new Stack (); - runners = new ThreadGroup ("XML-RPC Runner"); - serverSocket = new ServerSocket (port, 50, add); - if (port == 0) // do we need to get the actual port of the socket? - port = serverSocket.getLocalPort (); - listener = new Thread (this, "XML-RPC Weblistener"); - listener.start(); - } - - - /** - * Register a handler object with this name. Methods of this objects will be - * callable over XML-RPC as "name.method". - */ - public void addHandler (String name, Object target) { - xmlrpc.addHandler (name, target); - } - - /** - * Remove a handler object that was previously registered with this server. - */ - public void removeHandler (String name) { - xmlrpc.removeHandler (name); - } - - /** - * Switch client filtering on/off. - * @see acceptClient(java.lang.String) - * @see denyClient(java.lang.String) - */ - public void setParanoid (boolean p) { - paranoid = p; - } - - /** - * Return the port the server is listening on. Useful when the initial port parameter - * was 0 which means that any free port is used. - */ - public int getServerPort () { - return port; - } - - /** - * Add an IP address to the list of accepted clients. The parameter can contain '*' as wildcard - * character, e.g. "192.168.*.*". You must call setParanoid(true) in order for this to have any - * effect. - * - * @see denyClient(java.lang.String) - * @see setParanoid(boolean) - */ - public void acceptClient (String address) throws IllegalArgumentException { - try { - AddressMatcher m = new AddressMatcher (address); - accept.addElement (m); - } catch (Exception x) { - throw new IllegalArgumentException ("\""+address+"\" does not represent a valid IP address"); - } - } - - /** - * Add an IP address to the list of denied clients. The parameter can contain '*' as wildcard - * character, e.g. "192.168.*.*". You must call setParanoid(true) in order for this to have any - * effect. - * - * @see acceptClient(java.lang.String) - * @see setParanoid(boolean) - */ - public void denyClient (String address) throws IllegalArgumentException { - try { - AddressMatcher m = new AddressMatcher (address); - deny.addElement (m); - } catch (Exception x) { - throw new IllegalArgumentException ("\""+address+"\" does not represent a valid IP address"); - } - } - - private boolean checkSocket (Socket s) { - int l = deny.size (); - byte address[] = s.getInetAddress ().getAddress (); - for (int i=0; i 255) - throw new RuntimeException ("System overload"); - return new Runner (); - } - } - - void releaseRunner (Runner runner) { - threadpool.push (runner); - } - - class Runner implements Runnable { - - Thread thread; - Connection con; - int count; - - public void handle (Socket socket) throws IOException { - con = new Connection (socket); - count = 0; - if (thread == null || !thread.isAlive()) { - thread = new Thread (runners, this); - thread.start (); - } else { - synchronized (this) { - notify (); - } - } - } - - public void run () { - while (Thread.currentThread () == thread) { - con.run (); - count++; - con = null; - - if (count > 200 || threadpool.size() > 20) - return; - - synchronized (this) { - releaseRunner (this); - try { - wait (); - } catch (InterruptedException ir) { - Thread.currentThread().interrupt(); - } - } - } - } - -} // end class Runner - - -class Connection implements Runnable { - - private Socket socket; - private BufferedInputStream input; - private BufferedOutputStream output; - private long lastRequest; - private String user, password; - - public Connection (Socket socket) throws IOException { - // set read timeout to 30 seconds - socket.setSoTimeout (30000); - - this.socket = socket; - input = new BufferedInputStream (socket.getInputStream()); - output = new BufferedOutputStream (socket.getOutputStream()); - } - - - public void run () { - try { - boolean keepalive = false; - - do { - // reset user authentication - user = password = null; - String line = readLine (); - // Netscape sends an extra \n\r after bodypart, swallow it - if ("".equals (line)) - line = readLine(); - if (XmlRpc.debug) - System.err.println (line); - // get time of last request - lastRequest = System.currentTimeMillis (); - int contentLength = -1; - - // tokenize first line of HTTP request - StringTokenizer tokens = new StringTokenizer(line); - String method = tokens.nextToken(); - String uri = tokens.nextToken (); - String httpversion = tokens.nextToken (); - keepalive = XmlRpc.getKeepAlive() && "HTTP/1.1".equalsIgnoreCase (httpversion); - do { - line = readLine(); - if (line != null) { - if (XmlRpc.debug) - System.err.println (line); - String lineLower = line.toLowerCase (); - if (lineLower.startsWith ("content-length:")) - contentLength = Integer.parseInt (line.substring (15).trim ()); - if (lineLower.startsWith ("connection:")) - keepalive = XmlRpc.getKeepAlive() && lineLower.indexOf ("keep-alive") > -1; - if (lineLower.startsWith ("authorization: basic ")) - parseAuth (line); - } - } while (line != null && ! line.equals("")); - - if ("POST".equalsIgnoreCase (method)) { - ServerInputStream sin = new ServerInputStream (input, contentLength); - byte result[] = xmlrpc.execute (sin, user, password); - output.write (httpversion.getBytes()); - output.write (ok); - output.write (server); - if (keepalive) - output.write (conkeep); - else - output.write (conclose); - output.write (ctype); - output.write (clength); - output.write (Integer.toString (result.length).getBytes()); - output.write (doubleNewline); - output.write (result); - output.flush (); - } else { - output.write (httpversion.getBytes()); - output.write (" 400 Bad Request\r\n".getBytes()); - output.write ("Server: helma.XML-RPC\r\n\r\n".getBytes()); - output.write (("Method "+method+" not implemented (try POST)").getBytes()); - output.flush (); - keepalive = false; - } - } while (keepalive); - } catch (Exception exception) { - if (XmlRpc.debug) { - System.err.println (exception); - exception.printStackTrace (); - } - } finally { - try { - socket.close(); - } catch (IOException ignore) {} - } - } - - byte[] buffer; - private String readLine () throws IOException { - if (buffer == null) { - buffer = new byte[512]; - } - int next; - int count = 0; - for (;;) { - next = input.read(); - if (next < 0 || next == '\n') - break; - if (next != '\r') { - buffer[count++] = (byte) next; - } - if (count >= 512) - throw new IOException ("HTTP Header too long"); - } - return new String (buffer, 0, count); - } - - private void parseAuth (String line) { - try { - byte[] c = Base64.decode (line.substring (21).toCharArray ()); - String str = new String (c); - int col = str.indexOf (":"); - user = str.substring (0, col); - password = str.substring (col+1); - } catch (Throwable ignore) {} - } - -} - - -class AddressMatcher { - - int pattern[]; - - public AddressMatcher (String address) throws Exception { - pattern = new int[4]; - StringTokenizer st = new StringTokenizer (address, "."); - if (st.countTokens () != 4) - throw new Exception ("\""+address+"\" does not represent a valid IP address"); - for (int i=0; i<4; i++) { - String next = st.nextToken (); - if ("*".equals (next)) - pattern[i] = 256; - else - pattern[i] = (byte) Integer.parseInt (next); - } - } - - public boolean matches (byte address[]) { - for (int i=0; i<4; i++) { - if (pattern[i] > 255) // wildcard - continue; - if (pattern[i] != address[i]) - return false; - } - return true; - } -} - -} - -// An echo handler for debugging purposes -class Echo implements XmlRpcHandler { - public Object execute (String method, Vector v) throws Exception { - return (v); - } -} - -// An simple class that implements authentication -class AuthDemo implements AuthenticatedXmlRpcHandler { - public Object execute (String method, Vector v, String user, String password) throws Exception { - // our simplistic authentication guidelines never fail ;) - if (user == null || user.startsWith ("script kiddie")) - throw new XmlRpcException (5, "Sorry, you're not allowed in here!"); - return ("Hello "+user); - } -} - diff --git a/src/helma/xmlrpc/XmlRpc.java b/src/helma/xmlrpc/XmlRpc.java deleted file mode 100644 index 2a745229..00000000 --- a/src/helma/xmlrpc/XmlRpc.java +++ /dev/null @@ -1,628 +0,0 @@ -/** - * Copyright 1999 Hannes Wallnoefer - * XML-RPC base class. See http://www.xmlrpc.com/ - */ - -package helma.xmlrpc; - -import java.io.*; -import java.util.*; -import java.text.*; -import org.xml.sax.*; - - -/** - * This abstract base class provides basic capabilities for XML-RPC, like parsing of parameters - * or encoding Java objects into XML-RPC format. Any XML parser with a - * SAX interface can be used.

- * XmlRpcServer and XmlRpcClient are the classes that actually implement an XML-RCP server and client. - * @see XmlRpcServer - * @see XmlRpcClient - */ - -public abstract class XmlRpc extends HandlerBase { - - public static final String version = "helma XML-RPC 1.0"; - - String methodName; - - // class name of SAX parser to use - private static Class parserClass; - private static Hashtable saxDrivers = new Hashtable (); - static { - saxDrivers.put ("xp", "com.jclark.xml.sax.Driver"); - saxDrivers.put ("ibm1", "com.ibm.xml.parser.SAXDriver"); - saxDrivers.put ("ibm2", "com.ibm.xml.parsers.SAXParser"); - saxDrivers.put ("aelfred", "com.microstar.xml.SAXDriver"); - saxDrivers.put ("oracle1", "oracle.xml.parser.XMLParser"); - saxDrivers.put ("oracle2", "oracle.xml.parser.v2.SAXParser"); - saxDrivers.put ("openxml", "org.openxml.parser.XMLSAXParser"); - saxDrivers.put ("minml", "uk.co.wilson.xml.MinML"); - } - - - // the stack we're parsing our values into. - Stack values; - Value currentValue; - - // formats for parsing and generating dateTime values - - // DateFormat datetime; - // now comes wapped into a synchronized class because dateFormat is not threadsafe - static Formatter dateformat = new Formatter (); - - // used to collect character data of parameter values - StringBuffer cdata; - boolean readCdata; - - // XML RPC parameter types used for dataMode - static final int STRING = 0; - static final int INTEGER = 1; - static final int BOOLEAN = 2; - static final int DOUBLE = 3; - static final int DATE = 4; - static final int BASE64 = 5; - static final int STRUCT = 6; - static final int ARRAY = 7; - - // Error level + message - int errorLevel; - String errorMsg; - - static final int NONE = 0; - static final int RECOVERABLE = 1; - static final int FATAL = 2; - - // use HTTP keepalive? - static boolean keepalive = false; - - // for debugging output - public static boolean debug = false; - final static String types[] = {"String", "Integer", "Boolean", "Double", "Date", "Base64", "Struct", "Array"}; - - // mapping between java encoding names and "real" names used in XML prolog. - // if you use an encoding not listed here send feedback to xmlrpc@helma.org - - - static String encoding = "ISO8859_1"; - static Properties encodings = new Properties (); - static { - encodings.put ("UTF8", "UTF-8"); - encodings.put ("ISO8859_1", "ISO-8859-1"); - } - private final char[] encdecl = {'e','n','c','o','d','i','n','g','='}; - - - /** - * Set the SAX Parser to be used. The argument can either be the full class name or - * a user friendly shortcut if the parser is known to this class. The parsers that can - * currently be set by shortcut are listed in the main documentation page. If you are using - * another parser please send me the name of the SAX driver and I'll include it in a future release. - * If setDriver() is never called then the System property "sax.driver" is consulted. If that is not defined - * the driver defaults to OpenXML. - */ - public static void setDriver (String driver) throws ClassNotFoundException { - String parserClassName = null; - try { - parserClassName = (String) saxDrivers.get (driver); - if (parserClassName == null) - parserClassName = driver; - parserClass = Class.forName (parserClassName); - } catch (ClassNotFoundException x) { - throw new ClassNotFoundException ("SAX driver not found: "+parserClassName); - } - } - - /** - * Set the SAX Parser to be used by directly passing the Class object. - */ - public static void setDriver (Class driver) { - parserClass = driver; - } - - /** - * Set the encoding of the XML. This should be the name of a Java encoding - * contained in the encodings Hashtable. - */ - public static void setEncoding (String enc) { - encoding = enc; - } - - public String getEncoding () { - return encodings.getProperty (encoding, encoding); - } - - - /** - * Switch debugging output on/off. - */ - public static void setDebug (boolean val) { - debug = val; - } - - /** - * Switch HTTP keepalive on/off. - */ - public static void setKeepAlive (boolean val) { - keepalive = val; - } - - /** - * get current HTTP keepalive mode. - */ - public static boolean getKeepAlive () { - return keepalive; - } - - - /** - * Parse the input stream. For each root level object, method objectParsed - * is called. - */ - synchronized void parse (InputStream is) throws Exception { - - // reset values (XmlRpc objects are reusable) - errorLevel = NONE; - errorMsg = null; - values = new Stack (); - if (cdata == null) - cdata = new StringBuffer (128); - else - cdata.setLength (0); - readCdata = false; - currentValue = null; - - long now = System.currentTimeMillis (); - if (parserClass == null) { - // try to get the name of the SAX driver from the System properties - setDriver (System.getProperty ("sax.driver", "uk.co.wilson.xml.MinML")); - } - - Parser parser = null; - try { - parser = (Parser) parserClass.newInstance (); - } catch (NoSuchMethodError nsm) { - // This is thrown if no constructor exists for the parser class - // and is transformed into a regular exception. - throw new Exception ("Can't create Parser: "+parserClass); - } - - parser.setDocumentHandler (this); - parser.setErrorHandler (this); - - parser.parse (new InputSource (getReader (is))); - if (debug) - System.err.println ("Spent "+(System.currentTimeMillis () - now)+" millis parsing"); - } - - public Reader getReader (InputStream is) throws IOException { - if (is.markSupported ()) { - // here we try to get to the encoding declaration in the XML declaration. - // we deliberately don't do it right, instead we just scan the first 64 characters - // for 'encoding="..."'. Actually this should be done by the parser, but it seems only - // the 2+MB parsers like Xerces do. - is.mark (64); - int matchidx = 0; - boolean seenquote = false; - StringBuffer encb = new StringBuffer (16); - for (int i=0; i<64; i++) { - int c = is.read(); - if (matchidx < encdecl.length) { - if (c == encdecl[matchidx]) - matchidx ++; - } else if ('"' == c || '\'' == c) { - if (!seenquote) - seenquote = true; - else { - is.reset (); - if (encb.length() > 0) { - try { - return new InputStreamReader (is, encb.toString ()); - } catch (UnsupportedEncodingException ue) { - System.err.println ("Warning: guessed invalid encoding from XML stream: "+ue.getMessage ()); - return new InputStreamReader (is); - } - } else { - return new InputStreamReader (is); - } - } - } else if (seenquote) { - encb.append ((char) c); - } - } - is.reset (); - } - return new InputStreamReader (is); - } - - /** - * Writes the XML representation of a supported Java object to the XML writer. - */ - void writeObject (Object what, XmlWriter writer) throws XmlRpcException { - writer.startElement ("value"); - if (what instanceof String) { - writer.chardata (what.toString ()); - } else if (what instanceof Integer) { - writer.startElement ("int"); - writer.write (what.toString ()); - writer.endElement ("int"); - } else if (what instanceof Boolean) { - writer.startElement ("boolean"); - writer.write (((Boolean) what).booleanValue () ? "1" : "0"); - writer.endElement ("boolean"); - } else if (what instanceof Double || what instanceof Float) { - writer.startElement ("double"); - writer.write (what.toString ()); - writer.endElement ("double"); - } else if (what instanceof Date) { - writer.startElement ("dateTime.iso8601"); - Date d = (Date) what; - writer.write (dateformat.format (d)); - writer.endElement ("dateTime.iso8601"); - } else if (what instanceof byte[]) { - writer.startElement ("base64"); - writer.write (Base64.encode ((byte[]) what)); - writer.endElement ("base64"); - } else if (what instanceof Vector) { - writer.startElement ("array"); - writer.startElement ("data"); - Vector v = (Vector) what; - int l2 = v.size (); - for (int i2=0; i2 (see code below). - if (depth == 0 || values.peek ().hashCode () != STRUCT) { - Value v = currentValue; - if (depth == 0) { - // This is a top-level object - objectParsed (v.value); - currentValue = null; - } else { - // add object to sub-array; if current container is a struct, add later (at ) - currentValue = (Value) values.pop (); - currentValue.endElement (v); - } - } - } - - // Handle objects contained in structs. - if ("member".equals (name)) { - Value v = currentValue; - currentValue = (Value) values.pop (); - currentValue.endElement (v); - } - - else if ("methodName".equals (name)) { - methodName = cdata.toString (); - cdata.setLength (0); - readCdata = false; - } - } - - - /** - * Method called by SAX driver. - */ - public void startElement (String name, AttributeList atts) throws SAXException { - - if (debug) - System.err.println ("startElement: "+name); - - if ("value".equals (name)) { - // System.err.println ("starting value"); - if (currentValue != null) - values.push (currentValue); - currentValue = new Value (); - // cdata object is reused - cdata.setLength(0); - readCdata = true; - } - - else if ("methodName".equals (name)) { - cdata.setLength(0); - readCdata = true; - } - - else if ("name".equals (name)) { - cdata.setLength(0); - readCdata = true; - } - - else if ("string".equals (name)) { - cdata.setLength(0); - readCdata = true; - } else if ("i4".equals (name) || "int".equals (name)) { - currentValue.setType (INTEGER); - cdata.setLength(0); - readCdata = true; - } else if ("boolean".equals (name)) { - currentValue.setType (BOOLEAN); - cdata.setLength(0); - readCdata = true; - } else if ("double".equals (name)) { - currentValue.setType (DOUBLE); - cdata.setLength(0); - readCdata = true; - } else if ("dateTime.iso8601".equals (name)) { - currentValue.setType (DATE); - cdata.setLength(0); - readCdata = true; - } else if ("base64".equals (name)) { - currentValue.setType (BASE64); - cdata.setLength(0); - readCdata = true; - } else if ("struct".equals (name)) - currentValue.setType (STRUCT); - else if ("array".equals (name)) - currentValue.setType (ARRAY); - } - - - public void error (SAXParseException e) throws SAXException { - System.err.println ("Error parsing XML: "+e); - errorLevel = RECOVERABLE; - errorMsg = e.toString (); - } - - public void fatalError(SAXParseException e) throws SAXException { - System.err.println ("Fatal error parsing XML: "+e); - errorLevel = FATAL; - errorMsg = e.toString (); - } - - /** - * This represents an XML-RPC Value while the request is being parsed. - */ - class Value { - - int type; - Object value; - // the name to use for the next member of struct values - String nextMemberName; - - Hashtable struct; - Vector array; - - /** - * Constructor. - */ - public Value () { - this.type = STRING; - } - - /** - * Notification that a new child element has been parsed. - */ - public void endElement (Value child) { - if (type == ARRAY) - array.addElement (child.value); - else if (type == STRUCT) - struct.put (nextMemberName, child.value); - } - - /** - * Set the type of this value. If it's a container, create the corresponding java container. - */ - public void setType (int type) { - // System.err.println ("setting type to "+types[type]); - this.type = type; - if (type == ARRAY) - value = array = new Vector (); - if (type == STRUCT) - value = struct = new Hashtable (); - } - - /** - * Set the character data for the element and interpret it according to the - * element type - */ - public void characterData (String cdata) { - switch (type) { - case INTEGER: - value = new Integer (cdata.trim ()); - break; - case BOOLEAN: - value = "1".equals (cdata.trim ()) ? Boolean.TRUE : Boolean.FALSE; - break; - case DOUBLE: - value = new Double (cdata.trim ()); - break; - case DATE: - try { - value = dateformat.parse (cdata.trim ()); - } catch (ParseException p) { - // System.err.println ("Exception while parsing date: "+p); - throw new RuntimeException (p.getMessage ()); - } - break; - case BASE64: - value = Base64.decode (cdata.toCharArray ()); - break; - case STRING: - value = cdata; - break; - case STRUCT: - // this is the name to use for the next member of this struct - nextMemberName = cdata; - break; - } - } - - // This is a performance hack to get the type of a value without casting the Object. - // It breaks the contract of method hashCode, but it doesn't matter since - // Value objects are never used as keys in Hashtables. - public int hashCode () { - return type; - } - - public String toString () { - return (types[type]+" element "+value); - } - } - - - // A quick and dirty XML writer. - class XmlWriter { - - StringBuffer buf; - String enc; - - public XmlWriter (StringBuffer buf) { - // The encoding used for XML-RPC is ISO-8859-1 for pragmatical reasons (Frontier/Win). - this (buf, encoding); - } - - public XmlWriter (StringBuffer buf, String enc) { - this.buf = buf; - buf.setLength (0); - this.enc = enc; - // get name of encoding for XML prolog - String encName = encodings.getProperty (enc, enc); - buf.append (""); - } - - public void startElement (String elem) { - buf.append ("<"); - buf.append (elem); - buf.append (">"); - } - - public void endElement (String elem) { - buf.append (""); - } - - public void emptyElement (String elem) { - buf.append ("<"); - buf.append (elem); - buf.append ("/>"); - } - - - public void chardata (String text) { - int l = text.length (); - for (int i=0; iXmlRpcClientLite - * may work better for you. - */ -public class XmlRpcClient implements XmlRpcHandler { - - URL url; - String auth; - int maxThreads = 100; - - // pool of worker instances - Stack pool = new Stack (); - int workers = 0; - int asyncWorkers = 0; - - - // average roundtrip of this method call. This is used to decide if - // additional threads are needed or not in async mode - int roundtrip = 1000; - - // a queue of calls to be handled asynchronously - CallData first, last; - - /** - * Construct a XML-RPC client with this URL. - */ - public XmlRpcClient (URL url) { - this.url = url; - } - - /** - * Construct a XML-RPC client for the URL represented by this String. - */ - public XmlRpcClient (String url) throws MalformedURLException { - this.url = new URL (url); - } - - /** - * Construct a XML-RPC client for the specified hostname and port. - */ - public XmlRpcClient (String hostname, int port) throws MalformedURLException { - this.url = new URL ("http://"+hostname+":"+port+"/RPC2"); - } - - /** - * Return the URL for this XML-RPC client. - */ - public URL getURL () { - return url; - } - - /** - * Sets Authentication for this client. This will be sent as Basic Authentication header - * to the server as described in http://www.ietf.org/rfc/rfc2617.txt. - */ - public void setBasicAuthentication (String user, String password) { - if (user == null || password == null) - auth = null; - else { - char[] basicAuth = Base64.encode ((user+":"+password).getBytes()); - auth = new String (basicAuth).trim(); - } - } - - - /** - * Generate an XML-RPC request and send it to the server. Parse the result and - * return the corresponding Java object. - * - * @exception XmlRpcException: If the remote host returned a fault message. - * @exception IOException: If the call could not be made because of lower level problems. - */ - public Object execute (String method, Vector params) throws XmlRpcException, IOException { - Worker worker = getWorker (false); - long start = System.currentTimeMillis (); - try { - Object retval = worker.execute (method, params); - long end = System.currentTimeMillis (); - roundtrip = (int) ((roundtrip*4)+(end-start))/5; - return retval; - } finally { - releaseWorker (worker, false); - } - } - - /** - * Generate an XML-RPC request and send it to the server in a new thread. - * This method returns immediately. - * If the callback parameter is not null, it will be called later to handle the result or error when the call is finished. - * - */ - public void executeAsync (String method, Vector params, AsyncCallback callback) { - if (asyncWorkers > 2) { - enqueue (method, params, callback); - return; - } - Worker worker = null; - try { - worker = getWorker (true); - worker.executeAsync (method, params, callback); - } catch (IOException iox) { - // make a queued worker that doesn't run immediately - enqueue (method, params, callback); - } - } - - - synchronized Worker getWorker (boolean async) throws IOException { - try { - Worker w = (Worker) pool.pop (); - if (async) - asyncWorkers += 1; - else - workers += 1; - return w; - } catch (EmptyStackException x) { - if (workers < maxThreads) { - if (async) - asyncWorkers += 1; - else - workers += 1; - return new Worker (); - } - throw new IOException ("XML-RPC System overload"); - } - } - - /** - * Release possibly big per-call object references to allow them to be garbage collected - */ - synchronized void releaseWorker (Worker w, boolean async) { - w.result = null; - w.call = null; - if (pool.size() < 20 && !w.fault) - pool.push (w); - if (async) - asyncWorkers -= 1; - else - workers -= 1; - } - - - synchronized void enqueue (String method, Vector params, AsyncCallback callback) { - CallData call = new CallData (method, params, callback); - if (last == null) - first = last = call; - else { - last.next = call; - last = call; - } - } - - synchronized CallData dequeue () { - if (first == null) - return null; - if (asyncWorkers > 4 && asyncWorkers*4 > roundtrip) - return null; - CallData call = first; - if (first == last) - first = last = null; - else - first = first.next; - return call; - } - - class Worker extends XmlRpc implements Runnable { - - boolean fault; - Object result = null; - StringBuffer strbuf; - - CallData call; - - public Worker () { - super (); - } - - - public void executeAsync (String method, Vector params, AsyncCallback callback) { - this.call = new CallData (method, params, callback); - Thread t = new Thread (this); - t.start (); - } - - public void run () { - while (call != null) { - runAsync (call.method, call.params, call.callback); - call = dequeue (); - } - releaseWorker (this, true); - } - - void runAsync (String method, Vector params, AsyncCallback callback) { - Object res = null; - long start = System.currentTimeMillis (); - try { - res = execute (method, params); - // notify callback object - if (callback != null) - callback.handleResult (res, url, method); - } catch (Exception x) { - if (callback != null) try { - callback.handleError (x, url, method); - } catch (Exception ignore) {} - } - long end = System.currentTimeMillis (); - roundtrip = (int) ((roundtrip*4)+(end-start))/5; - } - - Object execute (String method, Vector params) throws XmlRpcException, IOException { - fault = false; - long now = System.currentTimeMillis (); - try { - ByteArrayOutputStream bout = new ByteArrayOutputStream (); - - if (strbuf == null) - strbuf = new StringBuffer (); - - XmlWriter writer = new XmlWriter (strbuf); - writeRequest (writer, method, params); - byte[] request = writer.getBytes(); - - URLConnection con = url.openConnection (); - con.setDoInput (true); - con.setDoOutput (true); - con.setUseCaches (false); - con.setAllowUserInteraction(false); - con.setRequestProperty ("Content-Length", Integer.toString (request.length)); - con.setRequestProperty ("Content-Type", "text/xml"); - if (auth != null) - con.setRequestProperty ("Authorization", "Basic "+auth); - // con.connect (); - OutputStream out = con.getOutputStream (); - out.write (request); - out.flush (); - InputStream in = con.getInputStream (); - parse (in); - } catch (Exception x) { - x.printStackTrace (); - throw new IOException (x.getMessage ()); - } - if (fault) { // generate an XmlRpcException - XmlRpcException exception = null; - try { - Hashtable f = (Hashtable) result; - String faultString = (String) f.get ("faultString"); - int faultCode = Integer.parseInt (f.get ("faultCode").toString ()); - exception = new XmlRpcException (faultCode, faultString.trim ()); - } catch (Exception x) { - throw new XmlRpcException (0, "Invalid fault response"); - } - throw exception; - } - if (debug) - System.err.println ("Spent "+(System.currentTimeMillis () - now)+" in request"); - return result; - } - - - /** - * Called when the return value has been parsed. - */ - void objectParsed (Object what) { - result = what; - } - - - /** - * Generate an XML-RPC request from a method name and a parameter vector. - */ - void writeRequest (XmlWriter writer, String method, Vector params) throws IOException, XmlRpcException { - writer.startElement ("methodCall"); - - writer.startElement ("methodName"); - writer.write (method); - writer.endElement ("methodName"); - - writer.startElement ("params"); - int l = params.size (); - for (int i=0; i ...."); - System.err.println ("Arguments are sent as integers or strings."); - } - } -} - - diff --git a/src/helma/xmlrpc/XmlRpcClientLite.java b/src/helma/xmlrpc/XmlRpcClientLite.java deleted file mode 100644 index 7dced08b..00000000 --- a/src/helma/xmlrpc/XmlRpcClientLite.java +++ /dev/null @@ -1,304 +0,0 @@ -/** - * Copyright 1999 Hannes Wallnoefer - * Implements a XML-RPC client. See http://www.xmlrpc.com/ - */ - -package helma.xmlrpc; - -import java.net.*; -import java.io.*; -import java.util.*; -import org.xml.sax.*; - -/** - * A multithreaded, reusable XML-RPC client object. This version uses a homegrown - * HTTP client which can be quite a bit faster than java.net.URLConnection, especially - * when used with XmlRpc.setKeepAlive(true). - */ -public class XmlRpcClientLite extends XmlRpcClient { - - static String auth; - - /** - * Construct a XML-RPC client with this URL. - */ - public XmlRpcClientLite (URL url) { - super (url); - } - - /** - * Construct a XML-RPC client for the URL represented by this String. - */ - public XmlRpcClientLite (String url) throws MalformedURLException { - super (url); - } - - /** - * Construct a XML-RPC client for the specified hostname and port. - */ - public XmlRpcClientLite (String hostname, int port) throws MalformedURLException { - super (hostname, port); - } - - - synchronized Worker getWorker (boolean async) throws IOException { - try { - Worker w = (Worker) pool.pop (); - if (async) - asyncWorkers += 1; - else - workers += 1; - return w; - } catch (EmptyStackException x) { - if (workers < maxThreads) { - if (async) - asyncWorkers += 1; - else - workers += 1; - return new LiteWorker (); - } - throw new IOException ("XML-RPC System overload"); - } - } - - class LiteWorker extends Worker implements Runnable { - - HttpClient client = null; - - public LiteWorker () { - super (); - } - - - Object execute (String method, Vector params) throws XmlRpcException, IOException { - long now = System.currentTimeMillis (); - fault = false; - try { - if (strbuf == null) - strbuf = new StringBuffer (); - else - strbuf.setLength (0); - XmlWriter writer = new XmlWriter (strbuf); - writeRequest (writer, method, params); - byte[] request = writer.getBytes(); - - // and send it to the server - if (client == null) - client = new HttpClient (url); - - client.write (request); - - InputStream in = client.getInputStream (); - - // parse the response - parse (in); - - // client keepalive is always false if XmlRpc.keepalive is false - if (!client.keepalive) - client.closeConnection (); - - if (debug) - System.err.println ("result = "+result); - - // check for errors from the XML parser - if (errorLevel == FATAL) - throw new Exception (errorMsg); - } catch (IOException iox) { - // this is a lower level problem, client could not talk to server for some reason. - - throw iox; - - } catch (Exception x) { - // same as above, but exception has to be converted to IOException. - if (XmlRpc.debug) - x.printStackTrace (); - - String msg = x.getMessage (); - if (msg == null || msg.length () == 0) - msg = x.toString (); - throw new IOException (msg); - } - - if (fault) { - // this is an XML-RPC-level problem, i.e. the server reported an error. - // throw an XmlRpcException. - - XmlRpcException exception = null; - try { - Hashtable f = (Hashtable) result; - String faultString = (String) f.get ("faultString"); - int faultCode = Integer.parseInt (f.get ("faultCode").toString ()); - exception = new XmlRpcException (faultCode, faultString.trim ()); - } catch (Exception x) { - throw new XmlRpcException (0, "Server returned an invalid fault response."); - } - throw exception; - } - if (debug) - System.err.println ("Spent "+(System.currentTimeMillis () - now)+" millis in request"); - return result; - } - - - - } // end of class Worker - - - // A replacement for java.net.URLConnection, which seems very slow on MS Java. - class HttpClient { - - String hostname; - String host; - int port; - String uri; - Socket socket = null; - BufferedOutputStream output; - BufferedInputStream input; - boolean keepalive; - boolean fresh; - - - public HttpClient (URL url) throws IOException { - hostname = url.getHost (); - port = url.getPort (); - if (port < 1) port = 80; - uri = url.getFile (); - if (uri == null || "".equals (uri)) - uri = "/"; - host = port == 80 ? hostname : hostname+":"+port; - initConnection (); - } - - protected void initConnection () throws IOException { - fresh = true; - socket = new Socket (hostname, port); - output = new BufferedOutputStream (socket.getOutputStream()); - input = new BufferedInputStream (socket.getInputStream ()); - } - - protected void closeConnection () { - try { - socket.close (); - } catch (Exception ignore) {} - } - - public void write (byte[] request) throws IOException { - try { - output.write (("POST "+uri+" HTTP/1.0\r\n").getBytes()); - output.write (("User-Agent: "+XmlRpc.version+"\r\n").getBytes()); - output.write (("Host: "+host+"\r\n").getBytes()); - if (XmlRpc.getKeepAlive()) - output.write ("Connection: Keep-Alive\r\n".getBytes()); - output.write ("Content-Type: text/xml\r\n".getBytes()); - if (auth != null) - output.write (("Authorization: Basic "+auth+"\r\n").getBytes()); - output.write (("Content-Length: "+request.length).getBytes()); - output.write ("\r\n\r\n".getBytes()); - output.write (request); - output.flush (); - fresh = false; - } catch (IOException iox) { - // if the connection is not "fresh" (unused), the exception may have occurred - // because the server timed the connection out. Give it another try. - if (!fresh) { - initConnection (); - write (request); - } else { - throw (iox); - } - } - } - - - public InputStream getInputStream () throws IOException { - String line = readLine (); - if (XmlRpc.debug) - System.err.println (line); - int contentLength = -1; - try { - StringTokenizer tokens = new StringTokenizer (line); - String httpversion = tokens.nextToken (); - String statusCode = tokens.nextToken(); - String statusMsg = tokens.nextToken ("\n\r"); - keepalive = XmlRpc.getKeepAlive() && "HTTP/1.1".equals (httpversion); - if (!"200".equals (statusCode)) - throw new IOException ("Unexpected Response from Server: "+statusMsg); - } catch (IOException iox) { - throw iox; - } catch (Exception x) { - // x.printStackTrace (); - throw new IOException ("Server returned invalid Response."); - } - do { - line = readLine (); - if (line != null) { - if (XmlRpc.debug) - System.err.println (line); - line = line.toLowerCase (); - if (line.startsWith ("content-length:")) - contentLength = Integer.parseInt (line.substring (15).trim ()); - if (line.startsWith ("connection:")) - keepalive = XmlRpc.getKeepAlive() && line.indexOf ("keep-alive") > -1; - } - } while (line != null && ! line.equals("")); - return new ServerInputStream (input, contentLength); - } - - - byte[] buffer; - private String readLine () throws IOException { - if (buffer == null) - buffer = new byte[512]; - int next; - int count = 0; - while (true) { - next = input.read(); - if (next < 0 || next == '\n') - break; - if (next != '\r') - buffer[count++] = (byte) next; - if (count >= 512) - throw new IOException ("HTTP Header too long"); - } - return new String (buffer, 0, count); - } - - - protected void finalize () throws Throwable { - closeConnection (); - } - - } - - /** - * Just for testing. - */ - public static void main (String args[]) throws Exception { - // XmlRpc.setDebug (true); - try { - String url = args[0]; - String method = args[1]; - XmlRpcClientLite client = new XmlRpcClientLite (url); - Vector v = new Vector (); - for (int i=2; i ...."); - System.err.println ("Arguments are sent as integers or strings."); - } - } - - -} - - diff --git a/src/helma/xmlrpc/XmlRpcException.java b/src/helma/xmlrpc/XmlRpcException.java deleted file mode 100644 index 8bba5448..00000000 --- a/src/helma/xmlrpc/XmlRpcException.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright 1999 Hannes Wallnoefer - */ - -package helma.xmlrpc; - -/** - * This is thrown by the XmlRpcClient if the remote server reported an error. If something - * went wrong at a lower level (e.g. no http connection) an IOException will be thrown instead. - */ -public class XmlRpcException extends Exception { - - /** - * The fault code of the exception. For servers based on this library, this will always be 0. - * (If there are predefined error codes, they should be in the XML-RPC spec.) - */ - public final int code; - - public XmlRpcException (int code, String message) { - super (message); - this.code = code; - } - -} diff --git a/src/helma/xmlrpc/XmlRpcHandler.java b/src/helma/xmlrpc/XmlRpcHandler.java deleted file mode 100644 index 7b004a0e..00000000 --- a/src/helma/xmlrpc/XmlRpcHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 1999 Hannes Wallnoefer - */ - -package helma.xmlrpc; - -import java.util.Vector; - -/** - * The XML-RPC server uses this interface to call a method of an RPC handler. This should - * be implemented by any class that wants to directly take control when it is called over RPC. Classes - * not implementing this interface will be wrapped into an Invoker - * object that tries to find the matching method for an XML-RPC request. - */ - -public interface XmlRpcHandler { - - /** - * Return the result, or throw an Exception if something went wrong. - */ - public Object execute (String method, Vector params) throws Exception; - -} \ No newline at end of file diff --git a/src/helma/xmlrpc/XmlRpcProxyServlet.java b/src/helma/xmlrpc/XmlRpcProxyServlet.java deleted file mode 100644 index 9ae072ac..00000000 --- a/src/helma/xmlrpc/XmlRpcProxyServlet.java +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2000 Hannes Wallnöfer - -package helma.xmlrpc; - -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; -import java.util.Vector; - -/** - * A Servlet that acts as a XML-RPC Proxy .

- * - * The URL of the server to connect to is taken from the init parameter url. - */ - -public class XmlRpcProxyServlet extends HttpServlet { - - private XmlRpcServer xmlrpc; - - public void init (ServletConfig config) throws ServletException { - if ("true".equalsIgnoreCase (config.getInitParameter ("debug"))) - XmlRpc.setDebug (true); - String url = config.getInitParameter ("url"); - xmlrpc = new XmlRpcServer (); - try { - xmlrpc.addHandler ("$default", new XmlRpcClientLite (url)); - } catch (Exception x) { - throw new ServletException ("Invalid URL: "+url+" ("+x.toString ()+")"); - } - } - - public void doPost(HttpServletRequest req, HttpServletResponse res) - throws ServletException, IOException { - byte[] result = xmlrpc.execute (req.getInputStream ()); - res.setContentType("text/xml"); - res.setContentLength (result.length); - OutputStream output = res.getOutputStream(); - output.write (result); - output.flush (); - } - -} diff --git a/src/helma/xmlrpc/XmlRpcServer.java b/src/helma/xmlrpc/XmlRpcServer.java deleted file mode 100644 index 8182049c..00000000 --- a/src/helma/xmlrpc/XmlRpcServer.java +++ /dev/null @@ -1,296 +0,0 @@ -/** - * Copyright 1999 Hannes Wallnoefer - * Implements an XML-RPC server. See http://www.xmlrpc.com/ - */ - -package helma.xmlrpc; - -import java.io.*; -import java.util.*; -import java.lang.reflect.*; - -/** - * A multithreaded, reusable XML-RPC server object. The name may be misleading because this does not open any - * server sockets. Instead it is fed by passing an XML-RPC input stream to the execute method. - * If you want to open a HTTP listener, use the WebServer class instead. - */ -public class XmlRpcServer { - - /** - * - */ - - Hashtable handlers; - - /** - * Construct a new XML-RPC server. You have to register handlers to make it - * do something useful. - */ - public XmlRpcServer () { - handlers = new Hashtable (); - } - - /** - * Register a handler object with this name. Methods of this objects will be - * callable over XML-RPC as "handlername.methodname". For more information - * about XML-RPC handlers see the main documentation page. - */ - public void addHandler (String handlername, Object handler) { - if (handler instanceof XmlRpcHandler || handler instanceof AuthenticatedXmlRpcHandler) - handlers.put (handlername, handler); - else if (handler != null) - handlers.put (handlername, new Invoker (handler)); - } - - /** - * Remove a handler object that was previously registered with this server. - */ - public void removeHandler (String handlername) { - handlers.remove (handlername); - } - - /** - * Parse the request and execute the handler method, if one is found. Returns the result as XML. - * The calling Java code doesn't need to know whether the call was successful or not since this is all - * packed into the response. - */ - public byte[] execute (InputStream is) { - return execute (is, null, null); - } - - /** - * Parse the request and execute the handler method, if one is found. If the invoked handler is - * AuthenticatedXmlRpcHandler, use the credentials to authenticate the user. - */ - public byte[] execute (InputStream is, String user, String password) { - Worker worker = getWorker (); - byte[] retval = worker.execute (is, user, password); - pool.push (worker); - return retval; - } - - Stack pool = new Stack (); - int workers = 0; - - private final Worker getWorker () { - try { - return (Worker) pool.pop (); - } catch (EmptyStackException x) { - if (workers < 100) { - workers += 1; - return new Worker (); - } - throw new RuntimeException ("System overload"); - } - } - - - class Worker extends XmlRpc { - - Vector inParams; - Object outParam; - byte[] result; - StringBuffer strbuf; - - public byte[] execute (InputStream is, String user, String password) { - inParams = new Vector (); - if (strbuf == null) - strbuf = new StringBuffer (); - - long now = System.currentTimeMillis (); - - try { - parse (is); - if (debug) { - System.err.println ("method name: "+methodName); - System.err.println ("inparams: "+inParams); - } - // check for errors from the XML parser - if (errorLevel > NONE) - throw new Exception (errorMsg); - - Object handler = null; - - String handlerName = null; - int dot = methodName.indexOf ("."); - if (dot > -1) { - handlerName = methodName.substring (0, dot); - handler = handlers.get (handlerName); - if (handler != null) - methodName = methodName.substring (dot+1); - } - - if (handler == null) { - handler = handlers.get ("$default"); - } - - if (handler == null) { - if (dot > -1) - throw new Exception ("RPC handler object \""+handlerName+"\" not found and no default handler registered."); - else - throw new Exception ("RPC handler object not found for \""+methodName+"\": no default handler registered."); - } - - if (handler instanceof AuthenticatedXmlRpcHandler) - outParam = ((AuthenticatedXmlRpcHandler) handler).execute (methodName, inParams, user, password); - else - outParam = ((XmlRpcHandler) handler).execute (methodName, inParams); - if (debug) - System.err.println ("outparam = "+outParam); - - XmlWriter writer = new XmlWriter (strbuf); - writeResponse (outParam, writer); - result = writer.getBytes (); - - } catch (Exception x) { - if (debug) - x.printStackTrace (); - XmlWriter writer = new XmlWriter (strbuf); - String message = x.toString (); - // check if XmlRpcException was thrown so we can get an error code - int code = x instanceof XmlRpcException ? ((XmlRpcException) x).code : 0; - try { - writeError (code, message, writer); - } catch (XmlRpcException xrx) { - // won't happen, we just sent a struct with an int and a string - } - try { - result = writer.getBytes (); - } catch (UnsupportedEncodingException encx) { - System.err.println ("XmlRpcServer.execute: "+encx); - result = writer.toString().getBytes(); - } - } - if (debug) - System.err.println ("Spent "+(System.currentTimeMillis () - now)+" millis in request"); - return result; - } - - /** - * Called when an object to be added to the argument list has been parsed. - */ - void objectParsed (Object what) { - inParams.addElement (what); - } - - /** - * Writes an XML-RPC response to the XML writer. - */ - void writeResponse (Object param, XmlWriter writer) throws XmlRpcException { - writer.startElement ("methodResponse"); - // if (param == null) param = ""; // workaround for Frontier bug - writer.startElement ("params"); - writer.startElement ("param"); - writeObject (param, writer); - writer.endElement ("param"); - writer.endElement ("params"); - writer.endElement ("methodResponse"); - } - - /** - * Writes an XML-RPC error response to the XML writer. - */ - void writeError (int code, String message, XmlWriter writer) throws XmlRpcException { - // System.err.println ("error: "+message); - Hashtable h = new Hashtable (); - h.put ("faultCode", new Integer (code)); - h.put ("faultString", message); - writer.startElement ("methodResponse"); - writer.startElement ("fault"); - writeObject (h, writer); - writer.endElement ("fault"); - writer.endElement ("methodResponse"); - } - - } // end of inner class Worker - -} // XmlRpcServer - -// This class uses Java Reflection to call methods matching an XML-RPC call -class Invoker implements XmlRpcHandler { - - private Object invokeTarget; - private Class targetClass; - - public Invoker(Object target) { - invokeTarget = target; - targetClass = invokeTarget instanceof Class ? - (Class) invokeTarget : invokeTarget.getClass(); - if (XmlRpc.debug) - System.err.println("Target object is " + targetClass); - } - - - // main method, sucht methode in object, wenn gefunden dann aufrufen. - public Object execute (String methodName, Vector params) throws Exception { - - - // Array mit Classtype bilden, ObjectAry mit Values bilden - Class[] argClasses = null; - Object[] argValues = null; - if(params != null){ - argClasses = new Class[params.size()]; - argValues = new Object[params.size()]; - for(int i = 0; i < params.size(); i++){ - argValues[i] = params.elementAt(i); - if (argValues[i] instanceof Integer) - argClasses[i] = Integer.TYPE; - else if (argValues[i] instanceof Double) - argClasses[i] = Double.TYPE; - else if (argValues[i] instanceof Boolean) - argClasses[i] = Boolean.TYPE; - else - argClasses[i] = argValues[i].getClass(); - } - } - - // Methode da ? - Method method = null; - - if (XmlRpc.debug) { - System.err.println("Searching for method: " + methodName); - for(int i = 0; i < argClasses.length; i++) - System.err.println("Parameter " + i + ": " + argClasses[i] + " = " + argValues[i]); - } - - try { - method = targetClass.getMethod(methodName, argClasses); - } - // Wenn nicht da dann entsprechende Exception returnen - catch(NoSuchMethodException nsm_e){ - throw nsm_e; - } - catch (SecurityException s_e){ - throw s_e; - } - - // our policy is to make all public methods callable except the ones defined in java.lang.Object - if (method.getDeclaringClass () == Class.forName ("java.lang.Object")) - throw new XmlRpcException (0, "Invoker can't call methods defined in java.lang.Object"); - - // invoke - Object returnValue = null; - try { - returnValue = method.invoke (invokeTarget, argValues); - } - catch (IllegalAccessException iacc_e){ - throw iacc_e; - } - catch (IllegalArgumentException iarg_e){ - throw iarg_e; - } - catch (InvocationTargetException it_e) { - if (XmlRpc.debug) - it_e.getTargetException ().printStackTrace (); - // check whether the thrown exception is XmlRpcException - Throwable t=it_e.getTargetException(); - if ( t instanceof XmlRpcException) - throw (XmlRpcException) t; - // It is some other exception - throw new Exception (t.toString ()); - } - - return returnValue; - } - -} diff --git a/src/helma/xmlrpc/XmlRpcServlet.java b/src/helma/xmlrpc/XmlRpcServlet.java deleted file mode 100644 index a420684a..00000000 --- a/src/helma/xmlrpc/XmlRpcServlet.java +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 1999 Hannes Wallnöfer, Raphael Spannocchi - -package helma.xmlrpc; - -import javax.servlet.*; -import javax.servlet.http.*; -import java.io.*; -import java.util.Vector; - -/** - * A prototype servlet to run XML-RPC.

- * - * Note that some clients like the one in Frontier 5 and the first version of XmlRpcApplet - * had XML-RPC requests hard-coded to URI /RPC2. To work with these clients, you have - * to configure your servlet environment to respond to /RPC2. This has been fixed in the - * new version of the XmlRpcApplet. - * - */ - -public class XmlRpcServlet extends HttpServlet implements XmlRpcHandler { - - public XmlRpcServer xmlrpc; - - public void init(ServletConfig config) throws ServletException { - xmlrpc = new XmlRpcServer (); - xmlrpc.addHandler ("example", this); - } - - public void doPost(HttpServletRequest req, HttpServletResponse res) - throws ServletException, IOException { - byte[] result = xmlrpc.execute (req.getInputStream ()); - res.setContentType("text/xml"); - res.setContentLength (result.length); - OutputStream output = res.getOutputStream(); - output.write (result); - output.flush (); - } - - /** - * Callback method for XML-RPC server - */ - public Object execute (String methodname, Vector params) { - return params; - } - -} diff --git a/src/helma/xmlrpc/fesi/FesiRpcExtension.java b/src/helma/xmlrpc/fesi/FesiRpcExtension.java deleted file mode 100644 index b7b069d3..00000000 --- a/src/helma/xmlrpc/fesi/FesiRpcExtension.java +++ /dev/null @@ -1,170 +0,0 @@ -// RpcXtension.java -// Copyright (c) Hannes Wallnöfer, 1999 - All rights reserved - -package helma.xmlrpc.fesi; - -import helma.xmlrpc.*; - -import FESI.Interpreter.*; -import FESI.Exceptions.*; -import FESI.Extensions.*; -import FESI.Data.*; - -import java.io.*; -import java.util.*; -import java.net.*; - - -/** - * An extension to transparently call and serve XML-RPC from the - * FESI EcmaScript interpreter. - * The extension adds constructors for XML-RPC clients and servers to the Global Object. - * For more information on how to use this please look at the files server.es and - * client.es in the src/fesi directory of the distribution. - * - * All argument conversion is done automatically. Currently the following argument and return - * types are supported: - *

    - *
  • plain objects (with all properties returned by ESObject.getProperties ()) - *
  • arrays - *
  • strings - *
  • date objects - *
  • booleans - *
  • integer and float numbers (long values are not supported!) - *
- * - */ -public class FesiRpcExtension extends Extension { - - Evaluator evaluator; - ESObject op; - - public void initializeExtension (Evaluator evaluator) throws EcmaScriptException { - // XmlRpc.setDebug (true); - this.evaluator = evaluator; - GlobalObject go = evaluator.getGlobalObject(); - FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype(); - - op = evaluator.getObjectPrototype(); - - go.putHiddenProperty ("Remote", new GlobalObjectRemote ("Remote", evaluator, fp)); // the Remote constructor - go.putHiddenProperty ("RemoteServer", new GlobalObjectRemoteServer ("RemoteServer", evaluator, fp)); // the RemoteServer constructor - - } - - - class GlobalObjectRemote extends BuiltinFunctionObject { - - GlobalObjectRemote (String name, Evaluator evaluator, FunctionPrototype fp) { - super(fp, evaluator, name, 1); - } - - public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return doConstruct(thisObject, arguments); - } - - public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - ESObject remote = null; - String url = null; - String robj = null; - if (arguments.length >= 1) - url = arguments[0].toString (); - if (arguments.length >= 2) - robj = arguments[1].toString (); - try { - remote = new ESRemote (op, this.evaluator, url, robj); - } catch (MalformedURLException x) { - throw new EcmaScriptException (x.toString ()); - } - return remote; - } - } - - class GlobalObjectRemoteServer extends BuiltinFunctionObject { - - - - GlobalObjectRemoteServer (String name, Evaluator evaluator, FunctionPrototype fp) { - super(fp, evaluator, name, 1); - } - - public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return doConstruct(thisObject, arguments); - } - - public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - ESObject remotesrv = null; - String globalname = null; - if (arguments.length < 1 || arguments.length > 2) - throw new EcmaScriptException ("Wrong number of arguments for constructor RemoteServer"); - int port = arguments[0].toInt32 (); - if (arguments.length == 2) - globalname = arguments[1].toString (); - try { - remotesrv = new FesiRpcServer (port, op, this.evaluator); - if (globalname != null) - this.evaluator.getGlobalObject ().putProperty (globalname, remotesrv, globalname.hashCode ()); - } catch (IOException x) { - throw new EcmaScriptException (x.toString ()); - } - return remotesrv; - } - } - - class ESRemote extends ObjectPrototype { - - URL url; - String remoteObject; - - public ESRemote (ESObject prototype, Evaluator evaluator, String urlstring, String robj) throws MalformedURLException { - super (prototype, evaluator); - this.url = new URL (urlstring); - remoteObject = robj; - } - - public ESRemote (ESObject prototype, Evaluator evaluator, URL url, String robj) { - super (prototype, evaluator); - this.url = url; - remoteObject = robj; - } - - public ESValue doIndirectCall(Evaluator evaluator, ESObject target, String functionName, ESValue arguments[]) - throws EcmaScriptException, NoSuchMethodException { - // System.out.println ("doIndirectCall called with "+functionName); - XmlRpcClient client = new XmlRpcClient (url); - long now = System.currentTimeMillis (); - Object retval = null; - int l = arguments.length; - Vector v = new Vector (); - for (int i=0; i - * Server.someObject = new SomeObject (); - * - * - */ - -public class FesiRpcServer extends ObjectPrototype { - - // This is public (for now) to be able to set access restrictions from the outside. - public WebServer srv; - Evaluator evaluator; - - /** - * Create an XML-RPC server with an already existing WebServer. - */ - public FesiRpcServer (WebServer srv, ESObject op, Evaluator eval) throws IOException, EcmaScriptException { - super (op, eval); - this.evaluator = eval; - this.srv = srv; - } - - /** - * Create an XML-RPC server listening on a specific port. - */ - public FesiRpcServer (int port, ESObject op, Evaluator eval) throws IOException, EcmaScriptException { - super (op, eval); - this.evaluator = eval; - srv = new WebServer (port); - } - - public void putProperty(String propertyName, ESValue propertyValue, int hash) throws EcmaScriptException { - if (propertyValue instanceof ESObject) - srv.addHandler (propertyName, new FesiInvoker ((ESObject) propertyValue)); - super.putProperty (propertyName, propertyValue, hash); - } - - public boolean deleteProperty (String propertyName, int hash) throws EcmaScriptException { - srv.removeHandler (propertyName); - super.deleteProperty (propertyName, hash); - return true; - } - - - class FesiInvoker implements XmlRpcHandler { - - ESObject target; - - public FesiInvoker (ESObject target) { - this.target = target; - } - - public Object execute (String method, Vector argvec) throws Exception { - // convert arguments - int l = argvec.size (); - - ESObject callTarget = target; - if (method.indexOf (".") > -1) { - StringTokenizer st = new StringTokenizer (method, "."); - int cnt = st.countTokens (); - for (int i=1; i 0 && args.length < 3) { - url = args[0]; - XmlRpc.setKeepAlive (true); - if (args.length == 2) - XmlRpc.setDriver (args[1]); - new AsyncBenchmark (); - } else { - System.err.println ("Usage: java helma.xmlrpc.Benchmark URL [SAXDriver]"); - } - } - - class Callback implements AsyncCallback { - - - int n; - - public Callback (Integer n) { - this.n = Math.abs (n.intValue()); - } - - public synchronized void handleResult (Object result, URL url, String method) { - if (n == ((Integer) result).intValue ()) - gCalls += 1; - else - gErrors += 1; - if (gCalls + gErrors >= clients*loops) - printStats (); - } - - public synchronized void handleError (Exception exception, URL url, String method) { - System.err.println (exception); - exception.printStackTrace (); - gErrors += 1; - if (gCalls + gErrors >= clients*loops) - printStats (); - } - - public void printStats () { - System.err.println (""); - System.err.println (gCalls+" calls, "+gErrors+" errors in "+(System.currentTimeMillis()-start)+" millis"); - System.err.println ((1000*(gCalls+gErrors)/(System.currentTimeMillis()-start))+" calls per second"); - } - -} - - -} diff --git a/src/helma/xmlrpc/test/Benchmark.java b/src/helma/xmlrpc/test/Benchmark.java deleted file mode 100644 index f876c4c4..00000000 --- a/src/helma/xmlrpc/test/Benchmark.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright 1999 Hannes Wallnoefer - */ - -package helma.xmlrpc.test; - -import helma.xmlrpc.*; -import java.util.*; -import java.io.IOException; - -public class Benchmark implements Runnable { - - XmlRpcClient client; - static String url; - static int clients = 16; - static int loops = 100; - - int gCalls = 0, gErrors = 0; - - Date date; - - public Benchmark () throws Exception { - client = new XmlRpcClientLite (url); - - Vector args = new Vector (); - // Some JITs (Symantec, IBM) have problems with several Threads - // starting all at the same time. - // This initial XML-RPC call seems to pacify them. - args.addElement (new Integer (123)); - client.execute ("math.abs", args); - date = new Date (); - date = new Date ((date.getTime()/1000)*1000); - - for (int i=0; i 0 && args.length < 3) { - url = args[0]; - XmlRpc.setKeepAlive (true); - if (args.length == 2) - XmlRpc.setDriver (args[1]); - new Benchmark (); - } else { - System.err.println ("Usage: java helma.xmlrpc.Benchmark URL [SAXDriver]"); - } - } - -} diff --git a/src/helma/xmlrpc/test/TestBase64.java b/src/helma/xmlrpc/test/TestBase64.java deleted file mode 100644 index dc885d86..00000000 --- a/src/helma/xmlrpc/test/TestBase64.java +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright 1999 Hannes Wallnoefer - */ - -package helma.xmlrpc.test; - -import helma.xmlrpc.*; -import java.util.*; -import java.io.IOException; - -public class TestBase64 implements Runnable { - - XmlRpcClient client; - static String url; - static int clients = 1; // 6; - static int loops = 1; //00; - - int gCalls = 0, gErrors = 0; - - byte[] data; - - public TestBase64 () throws Exception { - client = new XmlRpcClientLite (url); - - Vector args = new Vector (); - // Some JITs (Symantec, IBM) have problems with several Threads - // starting all at the same time. - // This initial XML-RPC call seems to pacify them. - args.addElement (new Integer (123)); - client.execute ("math.abs", args); - - data = new byte[20000]; - for (int j=0; j 0 && args.length < 3) { - url = args[0]; - XmlRpc.setKeepAlive (true); - // XmlRpc.setDebug (true); - if (args.length == 2) - XmlRpc.setDriver (args[1]); - new TestBase64 (); - } else { - System.err.println ("Usage: java helma.xmlrpc.Benchmark URL [SAXDriver]"); - } - } - -}