blob: 6a1537d8e16fc2e9a2b3512f2416ef7a59f7aac3 [file] [log] [blame]
package jpos.config.simple;
///////////////////////////////////////////////////////////////////////////////
//
// This software is provided "AS IS". The JavaPOS working group (including
// each of the Corporate members, contributors and individuals) MAKES NO
// REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NON-INFRINGEMENT. The JavaPOS working group shall not be liable for
// any damages suffered as a result of using, modifying or distributing this
// software or its derivatives. Permission to use, copy, modify, and distribute
// the software and its documentation for any purpose is hereby granted.
//
// The JavaPOS Config/Loader (aka JCL) is now under the CPL license, which
// is an OSS Apache-like license. The complete license is located at:
// http://oss.software.ibm.com/developerworks/opensource/license-cpl.html
//
///////////////////////////////////////////////////////////////////////////////
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.net.URL;
import jpos.util.tracing.Tracer;
import jpos.util.tracing.TracerFactory;
import jpos.config.*;
import jpos.config.simple.AbstractRegPopulator;
/**
* Simple implementation of the JposRegPopulator loading and saving from a
* serialized set of entries
* <p>
* <b>NOTE</b>: this class must define a public no-argument ctor so that it may be created
* via reflection when its defined in the jpos.properties as
* the jpos.config.regPopulatorClass
* </p>
* @see jpos.util.JposProperties#JPOS_REG_POPULATOR_CLASS_PROP_NAME
* @since 1.2 (NY 2K 99 meeting)
* @author E. Michael Maximilien (maxim@us.ibm.com)
*/
public class SimpleRegPopulator extends AbstractRegPopulator
{
//-------------------------------------------------------------------------
// Ctor(s)
//
/**
* Default ctor
* @since 1.2 (NY 2K meeting)
*/
public SimpleRegPopulator()
{ super( SimpleRegPopulator.class.getName() ); }
/**
* 1-arg ctor that takes the unique ID string
* @param s the unique ID string
* @since 1.3 (Washington DC 2001 meeting)
*/
public SimpleRegPopulator( String s ) { super( s ); }
//-------------------------------------------------------------------------
// Public methods
//
/**
* @return the fully qualified class name implementing the
* JposRegPopulator interface
* @since 1.3 (Washington DC 2001 meeting)
*/
public String getClassName()
{ return SimpleRegPopulator.class.getName(); }
/**
* Tell the populator to save the current entries
* @param entries an enumeration of JposEntry objects
* @since 1.2 (NY 2K meeting)
* @throws java.lang.Exception if any error occurs while saving
*/
public void save( Enumeration entries ) throws Exception
{
saveJposEntries( entries );
}
/**
* Tell the populator to save the current entries in the file specified
* @param entries an enumeration of JposEntry objects
* @param fileName the file name to save entries
* @since 1.3 (SF 2K meeting)
* @throws java.lang.Exception if any error occurs while saving
*/
public void save( Enumeration entries, String fileName ) throws Exception
{
File file = new File( fileName );
FileOutputStream fos = new FileOutputStream( file );
saveJposEntries( entries, fos );
fos.close();
}
/**
* Tell the populator to load the entries
* @since 1.2 (NY 2K meeting)
*/
public void load()
{
getJposEntries().clear();
Enumeration entries = readJposEntries();
while( entries.hasMoreElements() )
{
try
{
JposEntry entry = (JposEntry)entries.nextElement();
String logicalName = logicalName = (String)entry.
getPropertyValue( JposEntry.LOGICAL_NAME_PROP_NAME );
if( logicalName != null )
getJposEntries().put( logicalName, entry );
lastLoadException = null;
}
catch( Exception e )
{
lastLoadException = e;
tracer.println( "Error loading serialized JposEntry file: " +
"Exception.message= " + e.getMessage() );
}
}
}
/**
* Loads the entries specified in the fileName
* @param fileName the entries file name
* @since 1.3 (SF 2K meeting)
*/
public void load( String fileName )
{
try
{
getJposEntries().clear();
Enumeration entries = readJposEntries( new FileInputStream( fileName ) );
while( entries.hasMoreElements() )
{
JposEntry entry = (JposEntry)entries.nextElement();
String logicalName = (String)entry.
getPropertyValue( JposEntry.LOGICAL_NAME_PROP_NAME );
if( logicalName != null )
getJposEntries().put( logicalName, entry );
}
lastLoadException = null;
}
catch( Exception e )
{
lastLoadException = e;
tracer.println( "Error loading serialized JposEntry file: " +
"Exception.message=" + e.getMessage() );
}
}
/**
* @return the URL pointing to the entries file loaded or saved
* @since 1.2 (NY 2K meeting)
*/
public URL getEntriesURL()
{
URL url = null;
if( serInZipFile )
url = createURLFromFile( zipSerFile );
else
url = createURLFromFile( serFile );
return url;
}
/**
* @return the name of this populator. This should be a short descriptive name
* @since 1.3 (Washington DC 2001 meeting)
*/
public String getName() { return SIMPLE_REG_POPULATOR_NAME_STRING; }
//--------------------------------------------------------------------------
// Protected methods
//
/**
* Tries to save the entries as a ZipEntry in the ZipFile
* @param entries an Enumeration of JposEntry objects
* NOTE: if the the serialized entries is in a Sip/JAR file then if must be an
* entry in the "root" of the Sip/JAR file...
* Also when saving in a Zip/JAR file could get an error because the Zip/JAR file
* is being used by a process in Win32 environment
* @since 1.2 (NY 2K meeting)
* @throws java.lang.Exception if any problems occurs while saving
*/
protected void saveSerInZipFile( Enumeration entries ) throws Exception
{
ZipOutputStream zos = new ZipOutputStream( new
FileOutputStream( zipSerFile.getName() + ".temp.jar" ) );
Enumeration zipEntries = zipSerFile.entries();
while( zipEntries.hasMoreElements() )
{
ZipEntry zipEntry = (ZipEntry)zipEntries.nextElement();
zos.putNextEntry( zipEntry );
if( zipEntry.getName() != serFileName )
{
InputStream is = zipSerFile.getInputStream( zipEntry );
while( is.available() > 0 )
{
byte[] byteArray = new byte[ is.available() ];
is.read( byteArray );
zos.write( byteArray );
}
zos.closeEntry();
}
else
{
ObjectOutputStream oos = new ObjectOutputStream( new
FileOutputStream( TEMP_SER_FILE_NAME ) );
while( entries.hasMoreElements() )
{
JposEntry entry = (JposEntry)entries.nextElement();
oos.writeObject( entry );
}
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream( TEMP_SER_FILE_NAME );
while( fis.available() > 0 )
{
byte[] byteArray = new byte[ fis.available() ];
fis.read( byteArray );
zos.write( byteArray );
}
zos.closeEntry();
}
}
zos.flush();
zos.close();
}
/**
* Tries to save the entries in the file where they were loaded
* @param entries an Enumeration of JposEntry objects
* @since 1.2 (NY 2K meeting)
* @throws java.lang.Exception if any problems occurs while saving
*/
protected void saveSerFile( Enumeration entries ) throws Exception
{
saveJposEntries( entries, new FileOutputStream( serFileName ) );
}
/**
* Save the JposEntry object to the OutputStream as serialized objects
* @param entries an enumeration of JposEntry objects
* @param os the OuputStream to save to
* @since 1.2 (NY 2K meeting)
* @throws java.lang.Exception if any error occurs while saving
*/
protected void saveJposEntries( Enumeration entries, OutputStream os )
throws Exception
{
ObjectOutputStream oos = new ObjectOutputStream( os );
while( entries.hasMoreElements() )
{
JposEntry entry = (JposEntry)entries.nextElement();
oos.writeObject( entry );
}
oos.close();
}
/**
* @return an ObjectInputStream of the first serFileName found. The algorithm is:
* 1) Goes through the CLASSPATH and get the first serialized file name in the paths in order
* 2) If no simple ser file is found then looks in the JAR files in order
* @since 1.2 (NY 2K meeting)
*/
protected ObjectInputStream findSerOIS()
{
Vector classpathJarFiles = new Vector();
//Try to find the serialized file in the directory of each path in CLASSPATH
//As a side effect put each JAR/Zip file in the vector
ObjectInputStream ois = findSerOISInClasspath( classpathJarFiles );
//If no serialized file found in the directories of the path in the CLASSPATH then
//try to open each JAR/Zip file and see if they contain a serialized file
if( ois == null )
ois = findSerOISInJar( classpathJarFiles );
return ois;
}
/**
* Finds the first serialized JposEntry file in directory of each classpath
* <b>NOTE:</b>Decorated the FileInputStream with a BufferedInputStream to
* improve load time...
* @param jarZipFilesVector a vector of JAR/Zip file names
* @since 1.2 (NY 2K meeting)
*/
protected ObjectInputStream findSerOISInClasspath( Vector jarZipFilesVector )
{
ObjectInputStream ois = null;
String classpath = System.getProperty( "java.class.path" );
String pathSeparator = System.getProperty( "path.separator" );
String fileSeparator = System.getProperty( "file.separator" );
String path = "";
//Searches for the serialized JposEntry file
for( StringTokenizer st = new StringTokenizer( classpath, pathSeparator, false );
st.hasMoreTokens(); )
{
try
{
path = st.nextToken().trim();
if( path.equals("") ) continue;
if( path.length() > 4 && ( path.endsWith( ".zip" ) || path.endsWith( ".jar" ) ) )
jarZipFilesVector.addElement( path );
else
{
absoluteFileName = path + fileSeparator + serFileName;
ois = new ObjectInputStream( new BufferedInputStream( new FileInputStream( absoluteFileName ) ) );
serFile = new File( absoluteFileName );
serInZipFile = false;
break;
}
}
catch( Exception e ) { continue; }
}
return ois;
}
/**
* Finds the first serialized JposEntry file in the JAR files
* @param jarFilesVector a vector of JAR/Zip file names
* @since 1.2 (NY 2K meeting)
*/
protected ObjectInputStream findSerOISInJar( Vector jarFilesVector )
{
ObjectInputStream ois = null;
for( int i = 0; i < jarFilesVector.size(); ++i )
{
String jarFileName = (String)jarFilesVector.elementAt( i );
try
{
ZipFile zipFile = new ZipFile( jarFileName );
Enumeration zipEntries = zipFile.entries();
while( zipEntries.hasMoreElements() )
{
ZipEntry zipEntry = (ZipEntry)zipEntries.nextElement();
String entryName = zipEntry.getName();
if( entryName.endsWith( serFileName ) )
{
ois = new ObjectInputStream( zipFile.getInputStream( zipEntry ) );
zipSerFile = zipFile;
serInZipFile = true;
break;
}
}
}
catch( Exception e ) {}
if( ois != null ) break;
}
return ois;
}
/**
* Searches the current class path for the serialized file and un-serializes the JposEntry objects
* @return an Enumeration of JposEntry objects un-serializes from the file specified
* @param is the InputStream from which to read the serialized entries from
* @since 1.2 (NY 2K meeting)
*/
protected Enumeration readJposEntries( InputStream is )
{
Vector entries = new Vector();
try
{
//Added in 1.3 (SF-2K meeting) (not elegant since need to do
//a instanceof operation but works :-)
ObjectInputStream in = null;
if( is instanceof ObjectInputStream )
in = (ObjectInputStream)is;
else
if( is != null )
in = new ObjectInputStream( is );
if( in == null )
tracer.println( "Can't find serialized JposEntry file: " +
serFileName );
else
while( true )
entries.addElement( in.readObject() );
serFileName = absoluteFileName;
}
catch( EOFException eofe ) {}
catch( Exception e )
{ tracer.println( "ERROR while reading serialized JposEntry file: " +
serFileName + " Exception.message=" +
e.getMessage() ); }
return entries.elements();
}
/**
* @return an Enumeration of JposEntry objects
* @since 1.2 (NY 2K meeting)
*/
protected Enumeration readJposEntries()
{
Enumeration entries = null;
if( isPopulatorFileDefined() )
try { entries = readJposEntries( getPopulatorFileIS() ); }
catch( Exception e )
{ entries = ( new Vector() ).elements(); }
else
entries = readJposEntries( findSerOIS() );
return entries;
}
/**
*
* @param entries an enumeration of JposEntry objects
* @since 1.2 (NY 2K meeting)
* @throws java.lang.Exception if any error occurs while saving
*/
protected void saveJposEntries( Enumeration entries ) throws Exception
{
if( isPopulatorFileDefined() )
saveJposEntries( entries, getPopulatorFileOS() );
else
{
if( serInZipFile )
saveSerInZipFile( entries );
else
saveSerFile( entries );
}
}
//--------------------------------------------------------------------------
// Instance variables
//
private File serFile = null;
private ZipFile zipSerFile = null;
private boolean serInZipFile = false;
private String absoluteFileName = "";
private String serFileName = DEFAULT_JPOS_SER_FILE_NAME;
private Tracer tracer = TracerFactory.getInstance().
createTracer( "SimpleRegPopulator" );
//--------------------------------------------------------------------------
// Class constants
//
/**
* The default serialized JposEntry file name
* @since 1.2 (NY 2K meeting)
*/
public static final String DEFAULT_JPOS_SER_FILE_NAME = "jpos.cfg";
/**
* A tempory file name used for temporary storage
* @since 1.2 (NY 2K meeting)
*/
public static final String TEMP_SER_FILE_NAME = "__jpos_temp.cfg";
/**
* The default name for the SimpleRegPopulator
* @since 1.3 (Washington DC 2001 meeting)
*/
public static final String SIMPLE_REG_POPULATOR_NAME_STRING = "JCL Serialized Entries Populator";
}