package net.xoetrope.xui;
import java.applet.Applet;
import java.awt.Frame;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Window;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import java.util.Hashtable;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import net.xoetrope.debug.DebugLogger;
import net.xoetrope.xml.XmlParserFactory;
import net.xoetrope.xui.build.BuildProperties;
import net.xoetrope.xui.data.XDataBindingFactory;
import net.xoetrope.xui.data.XModel;
import net.xoetrope.xui.events.XuiEventHandler;
import net.xoetrope.xui.exception.XExceptionHandler;
import net.xoetrope.xui.helper.MessageHelper;
import net.xoetrope.xui.helper.ReflectionHelper;
import net.xoetrope.xui.helper.ResourceBundleLoader;
import net.xoetrope.xui.helper.SwingWorker;
import net.xoetrope.xui.helper.XLayoutHelper;
import net.xoetrope.xui.helper.XTranslator;
import net.xoetrope.xui.helper.XuiUtilities;
import net.xoetrope.xui.style.XStyleManager;
/**
* A holder for references to the objects and resources used by a Xui project
* <p> Copyright (c) Xoetrope Ltd., 2002-2003</p>
* <p> $Revision: 2.40 $</p>
* <p> License: see License.txt</p>
*/
public class XProject
{
public static final int UNKNOWN = 0;
public static final int CREATED = 1;
public static final int INITIALIZED = 2;
public static final int STARTED = 3;
public static final int CLOSING = 4;
public static final int TERMINATED = 5;
public static final int RESTARTING = 6;
/**
* The XStyleManager for this XProject instance
*/
protected XStyleManager styleManager;
/**
* The XPageManager for this XProject instance
*/
protected XPageManager pageManager;
/**
* The root XModel for this XProject instance
*/
protected XModel modelRoot;
/**
* The XmlParserFactory to be used by this XProject instance
*/
protected XmlParserFactory xmlParserFactory;
/**
* Store a reference to the MessageHelper utility class
*/
protected MessageHelper messageHelper;
/**
* Stores a Vector of XDataBindingFactory Object for this XProject instance
*/
protected Vector bindingFactories;
/**
* The name of the startup file for this XProject instance
*/
protected String startupFile;
/**
* Properties Object created from the statup properties
*/
protected Properties startSettings;
/**
* The path to the startup directory for this XProject instance
*/
protected URL documentBase;
/**
* Hashtable for storing other non-XUI object such as Routes and Services
*/
protected Hashtable managerObjects;
/**
* The default XModel based class to be used in this XProject instance. Defaulted
* to XBaseModel
*/
protected Class defaultModelClass = net.xoetrope.xui.data.XBaseModel.class;
/**
* The name of the event handler class which is to be used
*/
protected String eventHandlerClassName = "net.xoetrope.xui.XEventHandler";
// Former XResourceManager members
protected String defaultFile;
/**
* Encoding with which to read and write XML files. Defaulted to UTF-8
*/
protected String defaultEncoding;
/**
* The package where event hadlers can be found
*/
protected String basePackageName = XPage.XUI_AWT_PACKAGE;
/**
* The package name of the components to be used (AWT or Swing)
*/
protected String widgetPackageName = XPage.XUI_AWT_PACKAGE;
/**
* The XProject XApplet Object
*/
protected Applet app;
/**
* The XProject Window Object
*/
protected Window appWindow;
/**
* The XProject Frame Object
*/
protected Frame appFrame;
protected XStartupObject startupObject;
/**
* Vector of
* s used to locate resources for this XProject instance
*/
protected Vector customClassLoaders;
/**
* ResourceBundleLoader used to load ResourceBundles
*/
protected ResourceBundleLoader resourceBundleLoader;
/**
* Hashtable of images already accessed
*/
protected Hashtable imageCache;
/**
* A generic handler for exceptions
*/
protected XExceptionHandler exceptionHandler;
/*
* Project status
*/
protected int status;
/**
* Create a new project
*/
protected XProject()
{
styleManager = null;
pageManager = null;
modelRoot = null;
xmlParserFactory = null;
bindingFactories = new Vector();
managerObjects = new Hashtable();
customClassLoaders = new Vector();
defaultEncoding = "UTF8";
status = CREATED;
setObject( "LayoutHelper", new XLayoutHelper());
XProjectManager.addProject( null, this );
}
/**
* Setup the project and configure its resources
* @param startFile the startup file
*/
public void initialise( String startFile )
{
if ( status < INITIALIZED ) {
setStartupFile( startFile );
pageManager = new XPageManager( this );
DebugLogger.setDebugLevel( getStartupParam( "LogLevel" ));
DebugLogger.readLoggerZones( this );
setDefaultModel( getStartupParam( "DefaultModelClass" ));
styleManager = createStyleManager();
status = INITIALIZED;
}
}
private XStyleManager createStyleManager()
{
XStyleManager mgr = null;
String defStyleManager = getStartupParam( "DefaultStyleManager" );
if ( defStyleManager != null && defStyleManager.length() > 0 ) {
try {
Class c = Class.forName( defStyleManager.trim());
mgr = (XStyleManager) c.newInstance();
}
catch ( Exception ex ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "StyleManager NOT found: " + defStyleManager );
}
}
if ( mgr == null ) {
mgr = new XStyleManager( this, 10 );
}
return mgr;
}
//----------------------------------------------------------------------------
/**
* Get a reference to the XStyleManager. A new instance is created if required
* @return the style manager
* @since 1.03
*/
public XStyleManager getStyleManager()
{
if ( styleManager == null )
DebugLogger.logError( "No XStyleManager instantiated, please check the startup sequence" );
return styleManager;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Gets an instance of the page manager. A new instance is created if required
* @return the XPageManager instance
* @since 1.03
*/
public XPageManager getPageManager()
{
if ( pageManager == null ) {
// This code should not be executed, so an exception is deliberately
// thrown to provide an early warning.
DebugLogger.logError( "No XPageManager instantiated, please check the startup sequence" );
if ( !BuildProperties.BUILD_JDK_118 ) {
throw new java.lang.UnsupportedOperationException();
}
}
return pageManager;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Gets the application context for this project
* @return the XApplicationContext instance
* @since 3.0
*/
public XApplicationContext getApplicationContext()
{
Object o = getObject( "AppContext" );
return (XApplicationContext)o;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Get the root instance of the model. This class is unique to the project so it
* should be unique. If no instance has been created then a new one is
* constructed.
* @return the root XModel instance.
*/
public XModel getModel()
{
if ( modelRoot == null ) {
try {
modelRoot = ( XModel ) defaultModelClass.newInstance();
}
catch ( IllegalAccessException ex ) {
ex.printStackTrace();
}
catch ( InstantiationException ex ) {
ex.printStackTrace();
}
modelRoot.setId( "base" );
}
return modelRoot;
}
/**
* Sets the default model class. By default the XBaseModel is
* used. An instance is not constructed till the first call to getInstance().
* If an instance has been constructed then this method will have no effect.
* @param className the name of the model class e.g. net.xoetrope.xui.data.XBaseModel
*/
public void setDefaultModel( String className )
{
try {
if ( className != null )
defaultModelClass = Class.forName( className.trim());
}
catch ( ClassNotFoundException ex ) {
}
}
/**
* Reset the model to its initial state. Discard all the child nodess
*/
public void resetModel()
{
modelRoot = null;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Get the XML parser factory
* @return the parser factory
*/
public XmlParserFactory getXmlParserFactory()
{
if ( xmlParserFactory == null )
xmlParserFactory = new XmlParserFactory();
return xmlParserFactory;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Create the XuiEventHandler for the passed owner (XPage) and set it's
* XValidationHandler
* @param owner The XPage for which the passed XValidationHandler is working
* @param validationHandler The XValidationHandler for this XProject instance
* @return The created XuiEventHandler
*/
public XuiEventHandler createEventHandler( Object owner, net.xoetrope.xui.validation.XValidationHandler validationHandler )
{
try {
Class clazz = Class.forName( eventHandlerClassName.trim());
Class[] parameterTypes = new Class[ 3 ];
parameterTypes[ 0 ] = XProject.class;
parameterTypes[ 1 ] = Object.class;
parameterTypes[ 2 ] = net.xoetrope.xui.validation.XValidationHandler.class;
Constructor ctor = clazz.getConstructor( parameterTypes );
Object[] args = new Object[ 3 ];
args[ 0 ] = this;
args[ 1 ] = owner;
args[ 2 ] = validationHandler;
return (XuiEventHandler)ctor.newInstance( args );
}
catch( Exception e ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Unable to create event handler." );
e.printStackTrace();
}
return null;
}
/**
* Set the name of the class which will handle events for this XProject instance
* @param className The name of the event handler class
*/
public void setEventHandlerClass( String className )
{
eventHandlerClassName = className;
}
/**
* Set an exception handler for unhandled errors during method response method
* invocation
* @return the exception handler
*/
public XExceptionHandler getExceptionHandler()
{
return exceptionHandler;
}
/**
* Set an exception handler for unhandled errors during method response method
* invocation
* @param eh the exception handler
*/
public void setExceptionHandler( XExceptionHandler eh )
{
exceptionHandler = eh;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Get the message helper (for formatting messages)
* @return the message helper
*/
public MessageHelper getMessageHelper()
{
if ( messageHelper == null )
messageHelper = new MessageHelper();
return messageHelper;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Get the binding factories. The binding factories are requested to create
* component data bindings when a page is loaded from XML.
* @return the registered binding factories
*/
public Vector getBindingsFactories()
{
if ( bindingFactories == null )
bindingFactories = new Vector();
return bindingFactories;
}
/**
* Register a binding factory with the project. The factories
* are used to add bindings in the order in which they appear in the array of
* bindings and the iteration of factories stops once a binding is created.
*
* @param fact the new factory
* @param pos the postion in the array at which to add the factory.
*/
public void registerBindingFactory( XDataBindingFactory fact, int pos )
{
String newFactoryClassName = fact.getClass().getName();
int numFactories = bindingFactories.size();
for ( int i = 0; i < numFactories; i++ ) {
if ( bindingFactories.elementAt( i ).getClass().getName().equals( newFactoryClassName ))
return;
}
// The factory isn't already in use so add it.
if ( !BuildProperties.BUILD_JDK_118 )
bindingFactories.add( Math.min( Math.max( pos, 0 ), bindingFactories.size()), fact );
else
bindingFactories.addElement( fact );
}
/**
* Register a data binding factory. An add-on library or plug-in may wish to
* customize the data bindings, particularly if it provides extended model
* node types. Such extended nodes may need adapters to be useful for some or
* all widgets and other binding contexts. Registration of the binding factory
* allows the necessary adapters and bindings to be created on request.
* @param fact the new binding factory
*/
public void registerBindingFactory( XDataBindingFactory fact )
{
registerBindingFactory( fact, -1 );
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Get the name of the startup file.
* @return the startup file name, normally startup.properties
*/
public String getStartupFile()
{
return startupFile;
}
/**
* Sets the startup file and loads the associated resource.
* @param fileName the name of the startup resource file.
*/
public void setStartupFile( String fileName )
{
startupFile = fileName;
int pos = fileName.lastIndexOf( File.separatorChar );
try {
if ( pos > 0 ) {
if ( BuildProperties.DEBUG ) {
DebugLogger.trace( "Startup file: " + fileName );
DebugLogger.trace( "-- Document base: " + "file://" + fileName.substring( 0, pos+1 ));
DebugLogger.trace( "-- Startup file: " + fileName.substring( pos + 1 ) );
}
// URL url = findResource( fileName );
documentBase = new URL( "file", "", slashify( fileName.substring( 0, pos+1 ), true ));
startupFile = fileName.substring( pos + 1 );
}
}
catch ( Exception ex ) {
ex.printStackTrace();
}
try {
URL suUrl = findResource( startupFile );
startSettings = new Properties();
if ( suUrl != null ) {
if ( documentBase == null ) {
String s = suUrl.toString();
s = s.substring( 0, s.lastIndexOf( "/" ) + 1 );
documentBase = new URL( s );
}
InputStream is = suUrl.openStream();
startSettings.load( is );
String encoding = getStartupParam( "DefaultEncoding" );
if ( encoding != null )
defaultEncoding = encoding;
String antiAlias = getStartupParam( "AntiAlias" );
if ( antiAlias != null )
XPage.antiAlias = antiAlias.equals( "true" );
String startupPath = suUrl.getFile();
if ( startupPath.charAt( 0 ) == '/' )
startupPath = startupPath.substring( 1 );
// This is a URL reference so the path separator is always "/"
if ( ( pos = startupPath.indexOf( "/" + "resources" ) ) > 0 )
startupPath = startupPath.substring( 0, pos );
else if ( ( pos = startupPath.lastIndexOf( "/" ) ) > 0 )
startupPath = startupPath.substring( 0, pos );
startSettings.put( "ProjectPath", startupPath );
}
}
catch ( Exception e ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Unable to load startup file: " + fileName );
else
System.err.println( e.getMessage());
}
try {
String ncl = getStartupParam( "NumClassLoaders" );
if ( ncl != null ) {
int numClassLoaders = new Integer( ncl ).intValue();
for ( int i = 0; i < numClassLoaders; i++ ) {
ClassLoader cl = ( ClassLoader )Class.forName( getStartupParam( "ClassLoader" + ( i + 1 )).trim()).newInstance();
customClassLoaders.addElement( cl );
}
}
}
catch ( Exception e ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Unable to load class loader: " + e.getMessage() );
else
System.err.println( e.getMessage());
}
try {
String helper = getStartupParam( "LayoutHelper" );
if ( helper != null ) {
LayoutHelper layoutHelper = (LayoutHelper)Class.forName( helper.trim()).newInstance();
XComponentFactory.setLayoutHelper( layoutHelper );
}
}
catch ( Exception e ) {
if ( BuildProperties.DEBUG )
DebugLogger.logError( "Unable to set the layout helper: " + e.getMessage() );
}
String sp = getStartupParam( "CacheImages" );
if (( sp != null ) && !sp.equals( "false" ))
imageCache = new Hashtable();
}
/**
* Gets a startup parameter
* @param name the paramenter name
* @return the value
*/
public String getStartupParam( String name )
{
if ( startSettings == null ) {
if ( BuildProperties.DEBUG )
DebugLogger.logWarning( "No startup file available: param '" + name + "' not found" );
return null;
}
return startSettings.getProperty( name );
}
/**
* Sets a startup parameter
* @param name the paramenter name
* @param value the new value
* @return true if the value is new or different from the old value
*/
public boolean setStartupParam( String name, String value )
{
if (( name != null ) && ( value != null )) {
Object obj = startSettings.get( name );
String oldValue = obj == null ? null : obj.toString();
if (( oldValue == null ) || !oldValue.equals( value )) {
startSettings.setProperty( name, value );
return true;
}
}
return false;
}
/**
* Gets a startup parameter
* @param name the paramenter name
* @return the value
*/
public int getStartupParamAsInt( String name )
{
String p = startSettings.getProperty( name );
if ( p != null )
return Integer.parseInt( p );
return 0;
}
/**
* Get the project status
* @return the current status
*/
public int getStatus()
{
return status;
}
/**
* Set the application status
* @param newStatus the new status
*/
public void setStatus( int newStatus )
{
status = newStatus;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
/**
* Get a manager object
* @param key the name of the object e.g. "Routes", "Services"
* @return the object instance or null if it hasn't been added
*/
public Object getObject( String key )
{
return managerObjects.get( key );
}
/**
* Set an manager object value
* @param key the name of the object e.g. "Routes", "Services"
* @param obj the object instance
*/
public void setObject( String key, Object obj )
{
Object o = managerObjects.get( key );
if ( o != null )
managerObjects.remove( key );
if ( obj != null )
managerObjects.put( key, obj );
}
/**
* Remove a manager object value
* @param key the name of the object e.g. "Routes", "Services"
*/
public void removeObject( String key )
{
Object obj = managerObjects.get( key );
if ( obj != null )
managerObjects.remove( obj );
} //----------------------------------------------------------------------------
//-Former XResourceManager methods--------------------------------------------
/**
* Loads an image icon
* @param name the image resource name
* @return the image
*/
public Object getIcon( String name )
{
try {
Image img = getImage( name );
Class imageIconClazz = Class.forName( "javax.swing.ImageIcon" );
Constructor ctor = imageIconClazz.getConstructor( new Class[] { Image.class } );
Object imageIcon = ctor.newInstance(new Object[]{ img });
return imageIcon;
}
catch ( Exception e )
{
return null;
}
}
/**
* Loads an image resource
* @param name the image resource name
* @return the image
*/
public Image getImage( String name )
{
if ( name == null )
return null;
URL jarSource = XuiUtilities.checkUrl( getUrl( name ));
Image result = null;
if ( jarSource != null )
result = Toolkit.getDefaultToolkit().getImage( jarSource );
try {
if ( result == null ) {
URL url = XuiUtilities.checkUrl( new URL( documentBase, name ));
if ( url != null )
result = Toolkit.getDefaultToolkit().getImage( url );
}
}
catch ( MalformedURLException ex ) {
URL url = XuiUtilities.checkUrl( ClassLoader.getSystemResource( name ));
if ( url != null )
result = Toolkit.getDefaultToolkit().getImage( url );
}
finally {
if ( BuildProperties.DEBUG ) {
if ( result == null )
DebugLogger.logWarning( "Cannot load image: " + name );
}
}
return result;
}
/**
* Loads an image resource in a background thread
* @param holder the component containing to display the image
* @param name the image resource name
*/
public synchronized void getImage( XImageHolder holder, String name )
{
if ( name == null )
return;
final String imageName = name;
final SwingWorker worker = new SwingWorker()
{
Image result = null;
public Object construct()
{
if ( imageCache != null )
result = (Image)imageCache.get( imageName );
if ( result == null )
result = createImage( getBufferedInputStream( imageName ) );
if (( result != null ) && ( imageCache != null ))
imageCache.put( imageName, result );
return result; //return value not used by this program
}
//Runs on the event-dispatching thread.
public void finished()
{
Object holder = getExtraValue();
if ( holder != null )
((XImageHolder)holder).setImage( result );
}
};
worker.setExtraValue( holder );
worker.start();
}
/**
* Gets a stream for a resource
* @param fileName the resource file name
* @return the InputStream
*/
public InputStream getInputStream( String fileName )
{
// Try a file stream
if ( BuildProperties.DEBUG )
DebugLogger.trace( "RESOURCES", "Opening file:" + fileName );
InputStream result = null;
try {
ClassLoader cl = getClass().getClassLoader();
if ( cl != null ) {
try {
int numClassLoaders = customClassLoaders.size();
if ( numClassLoaders > 0 ) {
for ( int i = 0; i < numClassLoaders; i++ ) {
ClassLoader classLoader = ((ClassLoader)customClassLoaders.elementAt( i ));
if ( canAccessDefaultPackage( classLoader, fileName ))
result = classLoader.getResourceAsStream( fileName );
if ( result != null )
break;
}
}
if ( result == null ) {
// This check causes a problem where files are contained in a jar in the
// default package. The file will not load.
//if ( new File( fileName ).getParent() != null )
if ( fileName.indexOf( "http" ) == 0 ) {
try {
URL url = new URL( fileName );
result = url.openStream();
}
catch( Exception e ) {
if ( BuildProperties.DEBUG )
e.printStackTrace();
result = null;
}
}
else if ( canAccessDefaultPackage( cl, fileName ))
result = cl.getResourceAsStream( fileName );
}
}
catch ( Exception ex1 ) {
result = null;
if ( BuildProperties.DEBUG )
ex1.printStackTrace();
}
}
if ( result == null ) {
try {
result = new FileInputStream( fileName );
}
catch ( Exception ex ) {
try {
result = new FileInputStream( new URL( documentBase, fileName ).getFile() );
}
catch ( Exception ex2 ) {
try {
result = ClassLoader.getSystemResourceAsStream( fileName );
}
catch ( Exception ex4 ) {
result = null;
}
}
}
}
}
finally {
if ( BuildProperties.DEBUG ) {
if ( result == null )
DebugLogger.logWarning( "File not loaded:" + fileName );
}
}
return result;
}
/**
* Find a resource and get its filename (unencoded)
* @param fileName the resource file name
* @return the complete filename
*/
public String findResourceAsString( String fileName )
{
URL resUrl = findResource( fileName );
if ( resUrl != null ) {
String docfileName = resUrl.getFile();
if ( !BuildProperties.BUILD_JDK_118 )
docfileName = URLDecoder.decode( docfileName );
if ( docfileName.charAt( 0 ) == '/' )
docfileName = docfileName.substring( 1 );
return docfileName;
}
return null;
}
/**
* Find a resource
* @param fileName the resource file name
* @return the resource URL or null if it is not found
*/
public URL findResource( String fileName )
{
URL result = null;
ClassLoader cl = getClass().getClassLoader();
if ( cl != null ) {
try {
int numClassLoaders = customClassLoaders.size();
if ( numClassLoaders > 0 ) {
for ( int i = 0; i < numClassLoaders; i++ ) {
ClassLoader classLoader = ((ClassLoader)customClassLoaders.elementAt( i ));
if ( canAccessDefaultPackage( classLoader, fileName ))
result = classLoader.getResource( fileName );
if ( result != null )
return result;
}
}
try {
if ( canAccessDefaultPackage( cl, fileName ))
result = cl.getResource( fileName );
if ( result != null )
return result;
}
catch ( Exception ex3 ) {
}
}
catch ( Exception ex1 ) {
ex1.printStackTrace();
}
}
// Try the sytsem
try {
return ClassLoader.getSystemResource( fileName );
}
catch ( Exception ex ) {
}
return null;
}
/**
* Gets a buffered stream for a resource
* @param s the resource name
* @return the input stream
*/
public BufferedInputStream getBufferedInputStream( String s )
{
return new BufferedInputStream( getInputStream( s ) );
}
/**
* Gets a URL for a resource
* @param fileName the resource file name
* @return the InputStream
*/
public URL getUrl( String fileName )
{
ClassLoader cl = getClass().getClassLoader();
URL resUrl = null;
if ( cl != null ) {
try {
int numClassLoaders = customClassLoaders.size();
for ( int i = 0; i < numClassLoaders; i++ ) {
ClassLoader classLoader = ((ClassLoader)customClassLoaders.elementAt( i ));
if ( canAccessDefaultPackage( classLoader, fileName ))
resUrl = classLoader.getResource( fileName );
if ( resUrl != null )
break;
}
if ( resUrl == null )
resUrl = cl.getResource( fileName );
if ( BuildProperties.DEBUG ) {
if ( resUrl == null )
DebugLogger.logWarning( "File not loaded from classpath: " + fileName );
}
}
catch ( Exception ex1 ) {
ex1.printStackTrace();
}
}
try {
if ( resUrl == null )
resUrl = new URL( documentBase, fileName );
}
catch ( Exception ex ) {}
return resUrl;
}
/**
* Add a custom class loader. Customer class loaders are sometimes added to
* help locate resources in file structures, jars, remote locations etc...
* @param c the classloader
*/
public void addCustomClassLoader( ClassLoader c )
{
if ( c != null )
customClassLoaders.addElement( c );
}
/**
* Get the custom classloaders
* @return the class loaders or null if none or specified
*/
public Vector getCustomerClassLoaders()
{
return customClassLoaders;
}
/**
* Gets the <code>XProjectClassLoader</code> object. If any instance of
* <code>XProjectClassLoader</code> class was created, it is registered in
* this <code>XProject</code> object.
* @return <code>XProjectClassLoader</code> object.
*/
public ClassLoader getProjectClassLoader()
{
ClassLoader classLoader = null;
Enumeration enumClassLoaders = customClassLoaders.elements();
while ( ( enumClassLoaders.hasMoreElements() ) && ( classLoader == null ) ) {
Object o = enumClassLoaders.nextElement();
if ( o.getClass().getName().equals( "net.xoetrope.optional.resources.XProjectClassLoader" ))
classLoader = (ClassLoader)o;
}
return classLoader;
}
/**
* Gets a stream for a file
* @param file the file
* @return the input stream
*/
public InputStream getInputStream( File file )
{
FileInputStream result = null;
try {
if ( BuildProperties.DEBUG )
DebugLogger.trace( "RESOURCES", "Opening file:" + file.getAbsolutePath() + ", exists:" + file.exists() );
result = new FileInputStream( file );
}
catch ( FileNotFoundException ex ) {
result = null;
}
finally {
if ( BuildProperties.DEBUG ) {
if ( result == null )
DebugLogger.logWarning( "File open failed:" + file.getAbsolutePath());
}
}
return result;
}
/**
* Gets a buffered stream for a file
* @param file the file
* @return the input stream
*/
public BufferedInputStream getBufferedInputStream( File file )
{
return new BufferedInputStream( getInputStream( file ) );
}
/**
* Gets a BufferedReader for a resource
* @return the BufferedReader
* @param file the resource file name
* @throws java.lang.Exception throw an exception if there's a problem
*/
public BufferedReader getBufferedReader( String file ) throws Exception
{
InputStream is;
BufferedReader r = null;
try {
is = getInputStream( file );
if ( is != null )
r = new BufferedReader( new InputStreamReader( is ) );
}
catch ( Exception ex ) {
throw( ex );
}
return r;
}
/**
* Gets a BufferedReader for a resource
* @return the BufferedReader
* @param file the resource file name
* @param encoding the input encoding e.g. "UTF8" or null for the default
* encoding (UTF8 unless it has been changed)
* @throws java.lang.Exception throw an exception if there's a problem
*/
public BufferedReader getBufferedReader( String file, String encoding ) throws Exception
{
if ( encoding == null )
encoding = defaultEncoding;
InputStream is;
BufferedReader r = null;
try {
is = getInputStream( file );
if ( is != null ) {
InputStreamReader isr = new InputStreamReader( is, encoding );
r = new BufferedReader( isr );
}
}
catch ( UnsupportedEncodingException ex ) {
throw new Exception( "Encoding " + encoding + " not supported for file '" + file + "'" );
}
catch ( Exception ex ) {
if ( BuildProperties.DEBUG )
ex.printStackTrace();
throw new Exception( "Could not access file '" + file + "'" );
}
return r;
}
/**
* Gets a BufferedReader for a resource
* @return the BufferedReader
* @param file the resource file
* @param encoding the input encoding e.g. "UTF8" or null for the default
* encoding (UTF8 unless it has been changed)
* @throws java.lang.Exception throw an exception if there a problem
*/
public BufferedReader getBufferedReader( File file, String encoding ) throws Exception
{
if ( encoding == null )
encoding = defaultEncoding;
InputStream is;
BufferedReader r = null;
try {
is = getInputStream( file );
InputStreamReader isr = new InputStreamReader( is, encoding );
r = new BufferedReader( isr );
}
catch ( UnsupportedEncodingException ex ) {
throw new Exception( "Encoding " + encoding + " not supported for file '" + file + "'" );
}
catch ( Exception ex ) {
throw new Exception( "Could not access file '" + file + "'" );
}
return r;
}
/**
* Gets a stream for a file
* @param file the file
* @return the output stream
*/
public OutputStream getOutputStream( String file )
{
return getOutputStream( file, true );
}
/**
* Gets a buffered stream for a file
* @param file the file
* @return the output stream
*/
public BufferedOutputStream getBufferedOutputStream( String file )
{
return new BufferedOutputStream( getOutputStream( file ));
}
/**
* Gets a stream for a file
* @param file the file
* @param useProjectParent use the projects default file specification to locate the file
* @return the output stream
*/
public OutputStream getOutputStream( String file, boolean useProjectParent )
{
try {
if ( getClass().getClassLoader() == null ) {
return new FileOutputStream( file );
}
else {
if ( useProjectParent ) {
File f = new File( defaultFile );
return new FileOutputStream( new File( f, file ) );
}
else
return new FileOutputStream( new File( file ) );
}
}
catch ( Exception ex ) {
ex.printStackTrace();
return null;
}
}
/**
* Gets a buffered stream for a file
* @param file the file
* @param useProjectParent use the projects default file specification to locate the file
* @return the output stream
*/
public BufferedOutputStream getBufferedOutputStream( String file, boolean useProjectParent )
{
return new BufferedOutputStream( getOutputStream( file, useProjectParent ));
}
/**
* Set the default package name. The default package when accessing user event
* handlers.
* @param pn The name of the package to be used
*/
public void setPackageName( String pn )
{
basePackageName = pn;
}
/**
* Get the default package name
* @return the default package name
*/
public String getPackageName()
{
return basePackageName;
}
/**
* Set the default widget package name. The default package name is used when
* constructing widgets.
* @param pn The name of the widget package to be used
*/
public void setWidgetPackageName( String pn )
{
widgetPackageName = pn;
}
/**
* Get the default widget package name
* @return the default widget package name
*/
public String getWidgetPackageName()
{
return widgetPackageName;
}
/**
* Get the applet document base.
* @return the url
*/
public URL getDocumentBase()
{
return documentBase;
}
/**
* Set/Record the URL from which the applet was loaded
* @param u The path to the start directory
*/
public void setDocumentBase( URL u )
{
documentBase = u;
}
/**
* Set tbe applet reference
* @param applet The XApplet
*/
public void setApplet( Applet applet )
{
app = applet;
}
/**
* Set tbe startup object reference
* @param so the XStartupObject
*/
public void setStartupObject( XStartupObject so )
{
startupObject = so;
}
/**
* Set the main Frame reference
* @param frame The main application frame
*/
public void setAppFrame( Frame frame )
{
appFrame = frame;
}
/**
* Set the main Window reference
* @param window The main application window
*/
public void setAppWindow( Window window )
{
appWindow = window;
}
/**
* Get a reference to the applet object
* @return a reference to the applet
*/
public Applet getApplet()
{
return app;
}
/**
* Get the startup object
* @return the startup object
*/
public XStartupObject getStartupObject()
{
return startupObject;
}
/**
* Get a areference to the applet's Frame
* @return a reference to the frame
*/
public Frame getAppFrame()
{
return appFrame;
}
/**
* Get a reference to the application's main Window
* @return a reference to the Window
*/
public Window getAppWindow()
{
return appWindow;
}
/**
* Taken from java.io.File in JDK 1.4
* @param path The path to be corrected
* @param isDirectory Does the path lead to a directory?
* @return The corrected path String
*/
protected String slashify( String path, boolean isDirectory )
{
String p = path;
if ( File.separatorChar != '/' )
p = p.replace( File.separatorChar, '/' );
if ( !p.startsWith( "/" ) )
p = "/" + p;
if ( !p.endsWith( "/" ) && isDirectory )
p = p + "/";
return p;
}
/**
* Returns an Image, or null if the path was invalid.
* @param imgStream The InputStream from which the image is to be read
* @return The Image created from the InputStream
*/
protected Image createImage( InputStream imgStream )
{
int MAX_IMAGE_SIZE = 75000; //Change this to the size of
//your biggest image, in bytes.
int count = 0;
if ( imgStream != null ) {
byte buf[] = new byte[ MAX_IMAGE_SIZE ];
try {
count = imgStream.read( buf );
}
catch ( IOException ieo ) {
System.err.println( "Couldn't read stream from file" );
}
try {
imgStream.close();
}
catch ( IOException ieo ) {
System.err.println( "Can't close file" );
}
if ( count <= 0 ) {
System.err.println( "Empty file" );
return null;
}
return Toolkit.getDefaultToolkit().createImage( buf );
}
return null;
}
/**
* Get the default file encoding (UTF8 unless modified)
* @return the encoding
*/
public String getDefaultEncoding()
{
return defaultEncoding;
}
/**
* Set the default file encoding (UTF8 unless modified)
* see http://java.sun.com/j2se/1.4.2/docs/guide/intl/encoding.doc.html
* @param encoding the encoding e.g. "UTF8" or "ISO-8859-1"
*/
public void setDefaultEncoding( String encoding )
{
if ( encoding != null )
defaultEncoding = encoding;
}
/**
* Set the object to load language resource bundles
* @param loader the new loader
*/
public void setResourceBundleLoader( ResourceBundleLoader loader )
{
resourceBundleLoader = loader;
}
/**
* Get the resource bundle loader
* @return the loader
*/
public ResourceBundleLoader getResourceBundleLoader()
{
return resourceBundleLoader;
}
/**
* Get a resource bundle
* @param name the unqualified name of the resource bundle
* @return The ResourceBundle created from the passed name
*/
public ResourceBundle getResourceBundle( String name )
{
Hashtable bundles = (Hashtable)getObject( "ResourceBundles" );
if ( bundles == null ) {
bundles = new Hashtable();
setObject( "ResourceBundles", bundles );
}
if ( name == null )
name = "unnamed";
Object res = bundles.get( name );
if ( res == null ) {
try {
if ( resourceBundleLoader != null )
res = resourceBundleLoader.getResourceBundle( name );
else
res = new PropertyResourceBundle( getInputStream( name + ".properties" ) );
}
catch ( Exception ex ) {
if ( BuildProperties.DEBUG )
DebugLogger.logWarning( "Could not load the ResourceBundle: " + name );
return null;
}
bundles.put( name, res );
}
return (ResourceBundle)res;
}
/**
* Get the default translation object
* @return the translation object that operates on the resource bundle
*/
public XTranslator getTranslator()
{
return getTranslator( "" );
}
/**
* Get the translation object for the named bundle.
* @param name the name of the resource used for translation
* @return the translation object that operates on the resource bundle
*/
public XTranslator getTranslator( String name )
{
XTranslator translator = (XTranslator)getObject( "Translator" + name );
if ( translator == null ) {
String translatorClass = getStartupParam( "Translator" );
if (( translatorClass == null ) || ( translatorClass.length() == 0 ))
translatorClass = "net.xoetrope.xui.helper.XDefaultTranslator";
try {
translator = (XTranslator)ReflectionHelper.constructViaReflection( null, translatorClass, XProject.class, this );
setObject( "Translator" + name, translator );
}
catch( Exception e )
{
if ( BuildProperties.DEBUG )
e.getCause().printStackTrace();
}
}
return translator;
}
/**
* Set the default file/directory specification used to locate files by the
* getOutputStream( String file, boolean useProjectParent ) method
* @param file the file or directory specification
*/
public void setDefaultFile( String file )
{
defaultFile = file;
}
//-End of Former XResourceManager methods-------------------------------------
/**
* Attempt to fix an error when running a XUI application
* @param errorName the name of the error, this should correzpond to a fully
* qualified class name or a class within the net.xoetrope.selfhealing package
* @param sourceObj the instance of the class from which the error handler was
* invoked, or the object being repaired
* @param t throwable the exception that was trapped, or null
*/
public boolean fixError( String errorName, Object sourceObj, Throwable t )
{
return fixError( getClass(), errorName, sourceObj, t );
}
/**
* Attempt to fix an error when running a XUI application
* @param klass the class through which the healer wiull be loader
* @param errorName the name of the error, this should correzpond to a fully
* qualified class name or a class within the net.xoetrope.selfhealing package
* @param sourceObj the instance of the class from which the error handler was
* invoked, or the object being repaired
* @param t throwable the exception that was trapped, or null
*/
public boolean fixError( Class klass, String errorName, Object sourceObj, Throwable t )
{
if ( BuildProperties.DEBUG ) {
try {
String healer = errorName.trim();
if ( healer.indexOf( "." ) < 0 )
healer = "net.xoetrope.debug.selfhealing." + healer;
Class cls = klass.getClassLoader().loadClass( healer );
Object errorObj = cls.newInstance();
Class[] argTypes = { XProject.class, Object.class, Throwable.class };
Object[] args = new Object[ 3 ];
args[ 0 ] = this;
args[ 1 ] = sourceObj;
args[ 2 ] = t;
Method repairMethod = cls.getMethod( "fixError", argTypes );
Object rc = repairMethod.invoke( errorObj, args );
return true;
}
catch ( Exception e ) {
Throwable cause = e.getCause();
if ( cause != null )
cause.printStackTrace();
else
e.printStackTrace();
}
}
return false;
}
/**
* Can the project access the default package. Within the editor the NetBeans
* classloader causes problems if the default package is accessed!
*/
public boolean canAccessDefaultPackage( ClassLoader cl, String path )
{
return true;
}
}