Index: C:/Java/castor-1/codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java =================================================================== --- C:/Java/castor-1/codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java (revision 7076) +++ C:/Java/castor-1/codegen/src/main/java/org/exolab/castor/builder/SourceGenerator.java (working copy) @@ -61,6 +61,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.castor.core.exceptions.CastorRuntimeException; import org.exolab.castor.builder.binding.BindingException; import org.exolab.castor.builder.binding.BindingLoader; import org.exolab.castor.builder.binding.ExtendedBinding; @@ -76,7 +77,6 @@ import org.exolab.castor.builder.factory.FieldInfoFactory; import org.exolab.castor.builder.factory.SourceFactory; import org.exolab.castor.builder.info.ClassInfo; -import org.exolab.castor.core.exceptions.CastorRuntimeException; import org.exolab.castor.mapping.xml.MappingRoot; import org.exolab.castor.util.Configuration; import org.exolab.castor.util.LocalConfiguration; Index: C:/Java/castor-1/cpa/src/main/java/org/castor/cpa/CPAConfiguration.java =================================================================== --- C:/Java/castor-1/cpa/src/main/java/org/castor/cpa/CPAConfiguration.java (revision 0) +++ C:/Java/castor-1/cpa/src/main/java/org/castor/cpa/CPAConfiguration.java (revision 0) @@ -0,0 +1,175 @@ +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.cpa; + +import org.castor.core.CoreConfiguration; +import org.castor.core.util.CastorConfiguration; +import org.castor.core.util.Configuration; +import org.castor.xml.XMLConfiguration; + +/** + * Castor configuration of CPA modul. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public final class CPAConfiguration extends Configuration { + //-------------------------------------------------------------------------- + + /** Path to Castor configuration of core modul. */ + private static final String FILEPATH = "/org/castor/cpa/"; + + /** Name of Castor configuration of core modul. */ + private static final String FILENAME = "castor.cpa.properties"; + + /** A static configuration instance to be used during migration to a none static one. */ + // TODO Remove property after support for static configuration has been terminated. + private static Configuration _instance = null; + + //-------------------------------------------------------------------------- + + /** + * Get the one and only static CPA configuration. + * + * @return One and only configuration instance for Castor CPA modul. + * @deprecated Don't limit your applications flexibility by using a static configuration. Use + * your own configuration instance created with one of the newInstance() methods + * instead. + */ + // TODO Remove method after support for static configuration has been terminated. + public static synchronized Configuration getInstance() { + if (_instance == null) { _instance = newInstance(); } + return _instance; + } + + /** + * Factory method for a default CPA configuration instance. Application and domain class + * loaders will be initialized to the one used to load the Configuration class. The + * configuration instance returned will be a CastorConfiguration with a CPAConfiguration, a + * XMLConfiguration and a CoreConfiguration instance as parents. The CastorConfiguration + * holding user specific properties is the only one that can be modified by put() and remove() + * methods. CPAConfiguration, XMLConfiguration and CoreConfiguration are responsble to deliver + * Castor's default values if they have not been overwritten by the user. + * + * @return Configuration instance for Castor CPA modul. + */ + public static Configuration newInstance() { + Configuration core = new CoreConfiguration(); + Configuration cpa = new CPAConfiguration(core); + Configuration xml = new XMLConfiguration(cpa); + Configuration castor = new CastorConfiguration(xml); + return castor; + } + + /** + * Factory method for a CPA configuration instance that uses the specified class loaders. The + * configuration instance returned will be a CastorConfiguration with a CPAConfiguration, a + * XMLConfiguration and a CoreConfiguration instance as parents. The CastorConfiguration + * holding user specific properties is the only one that can be modified by put() and remove() + * methods. CPAConfiguration, XMLConfiguration and CoreConfiguration are responsble to deliver + * Castor's default values if they have not been overwritten by the user. + * + * @param app Classloader to be used for all classes of Castor and its required libraries. + * @param domain Classloader to be used for all domain objects. + * @return Configuration instance for Castor CPA modul. + */ + public static Configuration newInstance(final ClassLoader app, final ClassLoader domain) { + Configuration core = new CoreConfiguration(app, domain); + Configuration cpa = new CPAConfiguration(core); + Configuration xml = new XMLConfiguration(cpa); + Configuration castor = new CastorConfiguration(xml); + return castor; + } + + //-------------------------------------------------------------------------- + + /** + * Construct a configuration with given parent. Application and domain class loaders will be + * initialized to the ones of the parent. + *
+ * Note: This constructor is not intended for public use. Use one of the newInstance() methods + * instead. + * + * @param parent Parent configuration. + */ + public CPAConfiguration(final Configuration parent) { + super(parent); + loadDefaultProperties(FILEPATH, FILENAME); + } + + //-------------------------------------------------------------------------- + + // Specify public keys of xml configuration properties here. + + /** Property listing all available {@link org.castor.cache.Cache} implementations + * (org.castor.cache.Factories). */ + public static final String CACHE_FACTORIES = + "org.castor.cache.Factories"; + + /** Property listing all the available + * {@link org.castor.transactionmanager.TransactionManagerFactory} + * implementations (org.castor.transaction.TransactionManagerFactories). */ + public static final String TRANSACTION_MANAGER_FACTORIES = + "org.castor.transactionmanager.Factories"; + + /** Property telling if TransactionManager should be initialized at registration. */ + public static final String TRANSACTION_MANAGER_INIT = + "org.castor.transactionmanager.InitializeAtRegistration"; + + /** Property telling if database should be initialized when loading. */ + public static final String INITIALIZE_AT_LOAD = + "org.exolab.castor.jdo.DatabaseInitializeAtLoad"; + + /** Property name of default timezone in castor.properties. */ + public static final String DEFAULT_TIMEZONE = + "org.exolab.castor.jdo.defaultTimeZone"; + + /** Property listing all the available key genence + * factories. (org.exolab.castor.jdo.keyGeneratorFactories). */ + public static final String KEYGENERATOR_FACTORIES = + "org.exolab.castor.jdo.keyGeneratorFactories"; + + /** Property name of LOB buffer size in castor.properties. */ + public static final String LOB_BUFFER_SIZE = + "org.exolab.castor.jdo.lobBufferSize"; + + /** Property listing all the available persistence + * factories. (org.exolab.castor.jdo.engines). */ + public static final String PERSISTENCE_FACTORIES = + "org.exolab.castor.jdo.engines"; + + /** Property listing all the available + * {@link org.exolab.castor.persist.TxSynchronizable} + * implementations (org.exolab.castor.persit.TxSynchronizable). */ + public static final String TX_SYNCHRONIZABLE = + "org.exolab.castor.persist.TxSynchronizable"; + + /** Property specifying whether JDBC 3.0-specific features should be used, + * such as e.g. the use of Statement.getGeneratedKeys() + *
org.castor.jdo.use.jdbc30
. */ + public static final String USE_JDBC30 = + "org.castor.jdo.use.jdbc30"; + + /** Property specifying whether JDBC proxy classes should be used + *
org.exolab.castor.persist.useProxies
. */ + public static final String USE_JDBC_PROXIES = + "org.exolab.castor.persist.useProxies"; + + //-------------------------------------------------------------------------- +} Index: C:/Java/castor-1/cpa/src/main/resources/org/castor/cpa/castor.cpa.properties =================================================================== --- C:/Java/castor-1/cpa/src/main/resources/org/castor/cpa/castor.cpa.properties (revision 0) +++ C:/Java/castor-1/cpa/src/main/resources/org/castor/cpa/castor.cpa.properties (revision 0) @@ -0,0 +1,104 @@ +# Castor CPA properties file +# +# This file specifies default values of Castor's CPA modul which may be +# overwritten by the user through castor.properties file. +# +# $Id: castor.properties 7076 2007-07-24 22:03:25Z rjoachim $ + + +# List of persistence factories for the supported database servers: +# +org.exolab.castor.jdo.engines=\ + org.exolab.castor.jdo.drivers.OracleFactory,\ + org.exolab.castor.jdo.drivers.PostgreSQLFactory,\ + org.exolab.castor.jdo.drivers.SybaseFactory,\ + org.exolab.castor.jdo.drivers.SQLServerFactory,\ + org.exolab.castor.jdo.drivers.DB2Factory,\ + org.exolab.castor.jdo.drivers.InformixFactory,\ + org.exolab.castor.jdo.drivers.HsqlFactory,\ + org.exolab.castor.jdo.drivers.InstantDBFactory,\ + org.exolab.castor.jdo.drivers.InterbaseFactory,\ + org.exolab.castor.jdo.drivers.MySQLFactory,\ + org.exolab.castor.jdo.drivers.SapDbFactory,\ + org.exolab.castor.jdo.drivers.GenericFactory,\ + org.exolab.castor.jdo.drivers.DerbyFactory,\ + org.castor.jdo.drivers.PointbaseFactory,\ + org.castor.jdo.drivers.ProgressFactory + +# List of key generator factories: +# +org.exolab.castor.jdo.keyGeneratorFactories=\ + org.exolab.castor.jdo.keygen.MaxKeyGeneratorFactory,\ + org.exolab.castor.jdo.keygen.HighLowKeyGeneratorFactory,\ + org.exolab.castor.jdo.keygen.IdentityKeyGeneratorFactory,\ + org.exolab.castor.jdo.keygen.SequenceKeyGeneratorFactory,\ + org.exolab.castor.jdo.keygen.UUIDKeyGeneratorFactory + +# Configures the default time zone to apply to dates/times fetched from database +# fields (if not already part of the data). Specify same format as in +# java.util.TimeZone.getTimeZone (e.g GMT-8:00), or the empty string to use the +# computer's local time zone. Please see http://de.wikipedia.org/wiki/Zeitzone for +# detailed information about time zones. +# +org.exolab.castor.jdo.defaultTimeZone= + +# List of TxSynchronizeable implementations: +# +#org.exolab.castor.persist.TxSynchronizable= + +# Sets the buffer size in bytes for fetching LOBs (this is dependent upon +# the JDBC driver implementation). The value below == 5k. +# +org.exolab.castor.jdo.lobBufferSize=5120 + +# True if database configuration should be initalized dircetly after loading it. +# When set to false the database instances are lazy initialized at first use. +# Defaults to true. +# +org.exolab.castor.jdo.DatabaseInitializeAtLoad=true + +# True if proxy classes should be used for JDBC connections and prepared statements. +# Defaults to true. +# +org.exolab.castor.persist.useProxies=false + +# Cache implementations: +# +org.castor.cache.Factories=\ + org.castor.cache.simple.NoCacheFactory,\ + org.castor.cache.simple.TimeLimitedFactory,\ + org.castor.cache.simple.CountLimitedFactory,\ + org.castor.cache.simple.UnlimitedFactory,\ + org.castor.cache.distributed.FKCacheFactory,\ + org.castor.cache.distributed.JcsCacheFactory,\ + org.castor.cache.distributed.JCacheFactory,\ + org.castor.cache.distributed.CoherenceCacheFactory,\ + org.castor.cache.distributed.OsCacheFactory,\ + org.castor.cache.hashbelt.FIFOHashbeltFactory,\ + org.castor.cache.hashbelt.LRUHashbeltFactory,\ + org.castor.cache.distributed.EHCacheFactory,\ + org.castor.cache.distributed.GigaspacesCacheFactory + +# TransactionManagerFactory implementations: +# +org.castor.transactionmanager.Factories=\ + org.castor.transactionmanager.WebSphereTransactionManagerFactory,\ + org.castor.transactionmanager.WebSphere5TransactionManagerFactory,\ + org.castor.transactionmanager.WebSphere51TransactionManagerFactory,\ + org.castor.transactionmanager.LocalTransactionManagerFactory,\ + org.castor.transactionmanager.JNDIENCTransactionManagerFactory,\ + org.castor.transactionmanager.JOTMTransactionManagerFactory + +# Selects whether the TransactionManager should be initialized at registration, +# or lazily when requested for the first time. Defaults to false. +# +org.castor.transactionmanager.InitializeAtRegistration=false + +# Instructs Castor JDO to use the JDBC 3.0-specific features to obtain the +# generated value of an identity column. Defaults to false. +# +org.castor.jdo.use.jdbc30=false + +# Specifies whether to use ANSI-compliant SQL for MS SQL Server. Defaults to false. +# +org.exolab.castor.jdo.sqlserver.ansi-compliant=false Index: C:/Java/castor-1/src/doc/release-notes.xml =================================================================== --- C:/Java/castor-1/src/doc/release-notes.xml (revision 7076) +++ C:/Java/castor-1/src/doc/release-notes.xml (working copy) @@ -69,8 +69,39 @@

Be aware that no proxy interfaces are defined by default as the interface search slightly decreases marshalling performance.

+

Changes

+ +

Refactord Castor configuration

+ +

We have added a new class hierarchy to handle independed configurations + for every modul of Castor. At the moment the old configuration classes + are still used but everything is in place to use the new one. Having said + that this should not change anything for the user of Castor as he still + specifies his properties in a single castor.properties file for all + moduls.

+ + + + Refactored Castor configuration. + + + Ralf Joachim + ralf.joachim@syscon.eu + + + Ralf Joachim + ralf.joachim@syscon.eu + + + Ralf Joachim + ralf.joachim@syscon.eu + + Enh. + All + 20070725 + Added special processing of proxied classes. Index: C:/Java/castor-1/src/main/java/org/castor/core/CoreConfiguration.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/core/CoreConfiguration.java (revision 0) +++ C:/Java/castor-1/src/main/java/org/castor/core/CoreConfiguration.java (revision 0) @@ -0,0 +1,77 @@ +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.core; + +import org.castor.core.util.Configuration; + +/** + * Castor configuration of core modul. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public final class CoreConfiguration extends Configuration { + //-------------------------------------------------------------------------- + + /** Path to Castor configuration of core modul. */ + private static final String FILEPATH = "/org/castor/core/"; + + /** Name of Castor configuration of core modul. */ + private static final String FILENAME = "castor.core.properties"; + + //-------------------------------------------------------------------------- + + /** + * Default constructor. Application and domain class loaders will be initialized to the one + * used to load the Configuration class. No parent configuration will be set. + *
+ * Note: This constructor is not intended for public use. Use one of the newInstance() methods + * of the modul specific configuration instead. + */ + public CoreConfiguration() { + super(); + loadDefaultProperties(FILEPATH, FILENAME); + } + + /** + * Construct a configuration that uses the specified class loaders. No parent configuration + * will be set. + *
+ * Note: This constructor is not intended for public use. Use one of the newInstance() methods + * of the modul specific configuration instead. + * + * @param app Classloader to be used for all classes of Castor and its required libraries. + * @param domain Classloader to be used for all domain objects. + */ + public CoreConfiguration(final ClassLoader application, final ClassLoader domain) { + super(application, domain); + loadDefaultProperties(FILEPATH, FILENAME); + } + + //-------------------------------------------------------------------------- + + // Specify public keys of core configuration properties here. + + /** Property listing all available {@link org.exolab.castor.mapping.MappingLoader} + * implementations (org.castor.mapping.Loaders). */ + public static final String MAPPING_LOADER_FACTORIES = + "org.castor.mapping.loaderFactories"; + + //-------------------------------------------------------------------------- +} Index: C:/Java/castor-1/src/main/java/org/castor/core/exceptions/CastorRuntimeException.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/core/exceptions/CastorRuntimeException.java (revision 0) +++ C:/Java/castor-1/src/main/java/org/castor/core/exceptions/CastorRuntimeException.java (working copy) @@ -1,4 +1,21 @@ -package org.exolab.castor.core.exceptions; +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.core.exceptions; import java.io.PrintStream; import java.io.PrintWriter; @@ -3,13 +20,28 @@ import java.io.PrintStream; import java.io.PrintWriter; -public final class CastorRuntimeException extends RuntimeException { +/** + * CastorRuntimeException is the superclass of all unchecked Castor exceptions that are thrown + * during the normal operation of the Java Virtual Machine. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public class CastorRuntimeException extends RuntimeException { /** SerialVersionUID */ - private static final long serialVersionUID = 6183971667763969115L; + private static final long serialVersionUID = 3984585622253325513L; + + /** The cause of this exception or null if the cause is nonexistent or unknown. */ + private Throwable _cause = null; - /** The cause for this exception. */ - private Throwable _cause; + /** Has the cause of this exception been initialized? */ + private boolean _initCause = false; + /** + * Constructs a new Castor runtime exception without a message. The cause is not initialized + * but may subsequently be initialized by a call to initCause(Throwable). + */ public CastorRuntimeException() { super(); } @@ -14,26 +46,59 @@ super(); } + /** + * Constructs a new Castor runtime exception with the specified detail message. The cause is + * not initialized but may subsequently be initialized by a call to initCause(Throwable). + * + * @param message The detail message. + */ + public CastorRuntimeException(final String message) { + super(message); + } + + /** + * Constructs a new Castor runtime exception with the specified cause and the detail message + * of the cause. This constructor is useful for exceptions that are wrappers for others. + * + * @param cause The cause. + */ public CastorRuntimeException(final Throwable cause) { - super(); + super((cause == null) ? null : cause.getMessage()); _cause = cause; + _initCause = true; } - public CastorRuntimeException(final String message) { + /** + * Constructs a new Castor runtime exception with the specified detail message and cause. + * + * @param message The detail message. + * @param cause The cause. + */ + public CastorRuntimeException(final String message, final Throwable cause) { super(message); + _cause = cause; + _initCause = true; } - - public CastorRuntimeException(final String message, final Throwable cause) { - super(message); + + /** + * The method emulates the JDK 1.4 Throwable version of initCause() for JDKs before 1.4. + *
+ * {@inheritDoc} + */ + public final Throwable initCause(final Throwable cause) { + if (cause == this) { throw new IllegalArgumentException(); } + if (_initCause) { throw new IllegalStateException(); } _cause = cause; + _initCause = true; + return this; } /** - * Match the JDK 1.4 Throwable version of getCause() on JDK<1.4 systems. - * - * @return The throwable cause of this exception. + * The method emulates the JDK 1.4 Throwable version of getCause() for JDKs before 1.4. + *
+ * {@inheritDoc} */ - public Throwable getCause() { + public final Throwable getCause() { return _cause; } @@ -38,7 +103,7 @@ } /** - * Print a stack trace to stderr. + * {@inheritDoc} */ public void printStackTrace() { // Print the stack trace for this exception. @@ -51,11 +116,9 @@ } /** - * Print a stack trace to the specified PrintStream. - * - * @param s The PrintStream to print a stack trace to. + * {@inheritDoc} */ - public void printStackTrace(final PrintStream s) { + public final void printStackTrace(final PrintStream s) { // Print the stack trace for this exception. super.printStackTrace(s); @@ -66,11 +129,9 @@ } /** - * Print a stack trace to the specified PrintWriter. - * - * @param w The PrintWriter to print a stack trace to. + * {@inheritDoc} */ - public void printStackTrace(final PrintWriter w) { + public final void printStackTrace(final PrintWriter w) { // Print the stack trace for this exception. super.printStackTrace(w); Index: C:/Java/castor-1/src/main/java/org/castor/core/util/CastorConfiguration.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/core/util/CastorConfiguration.java (revision 0) +++ C:/Java/castor-1/src/main/java/org/castor/core/util/CastorConfiguration.java (revision 0) @@ -0,0 +1,51 @@ +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.core.util; + + +/** + * Castor configuration holding user properties. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public final class CastorConfiguration extends Configuration { + //-------------------------------------------------------------------------- + + /** Name of common Castor configuration file. */ + private static final String FILENAME = "castor.properties"; + + //-------------------------------------------------------------------------- + + /** + * Construct a configuration with given parent. Application and domain class loaders will be + * initialized to the ones of the parent. + *
+ * Note: This constructor is not intended for public use. Use one of the newInstance() methods + * instead. + * + * @param parent Parent configuration. + */ + public CastorConfiguration(final Configuration parent) { + super(parent); + loadUserProperties(FILENAME); + } + + //-------------------------------------------------------------------------- +} Index: C:/Java/castor-1/src/main/java/org/castor/core/util/Configuration.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/core/util/Configuration.java (revision 0) +++ C:/Java/castor-1/src/main/java/org/castor/core/util/Configuration.java (revision 0) @@ -0,0 +1,707 @@ +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.core.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Abstract base class to hold Castor configuration properties. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public abstract class Configuration { + //-------------------------------------------------------------------------- + + /** The Jakarta + * Commons Logging instance used for all logging. */ + private static final Log LOG = LogFactory.getLog(Configuration.class); + + /** Classloader to be used for all classes of Castor and its required libraries. */ + private final ClassLoader _applicationClassLoader; + + /** Classloader to be used for all domain objects that are marshalled/unmarshalled or + * loaded from the database. */ + private final ClassLoader _domainClassLoader; + + /** Parent configuration. */ + private final Configuration _parent; + + /** Properties map. */ + private final Map _map = new HashMap(); + + //-------------------------------------------------------------------------- + + /** + * Default constructor. Application and domain class loaders will be initialized to the one + * used to load the Configuration class. No parent configuration will be set. + */ + protected Configuration() { + _applicationClassLoader = getClass().getClassLoader(); + _domainClassLoader = getClass().getClassLoader(); + + _parent = null; + } + + /** + * Construct a configuration that uses the specified class loaders. No parent configuration + * will be set. + * + * @param app Classloader to be used for all classes of Castor and its required libraries. + * @param domain Classloader to be used for all domain objects. + */ + protected Configuration(final ClassLoader app, final ClassLoader domain) { + _applicationClassLoader = app; + _domainClassLoader = domain; + + _parent = null; + } + + /** + * Construct a configuration with given parent. Application and domain class loaders will be + * initialized to the ones of the parent. + * + * @param parent Parent configuration. + */ + protected Configuration(final Configuration parent) { + _applicationClassLoader = parent.getApplicationClassLoader(); + _domainClassLoader = parent.getDomainClassLoader(); + + _parent = parent; + } + + //-------------------------------------------------------------------------- + + /** + * Get classloader to be used for all classes of Castor and its required libraries. + * + * @return Classloader to be used for all classes of Castor and its required libraries. + */ + public final ClassLoader getApplicationClassLoader() { + return _applicationClassLoader; + } + + /** + * Get classloader to be used for all domain objects that are marshalled/unmarshalled or + * loaded from the database. + * + * @return Classloader to be used for all domain objects. + */ + public final ClassLoader getDomainClassLoader() { + return _domainClassLoader; + } + + //-------------------------------------------------------------------------- + + /** + * Load modul configuration from default locations. + *
+ * First it loads default configuration contained in Castor JAR. This gets overwritten + * by a configuration found on Java library directory. If no configuration could be found + * until that point a ConfigurationException will be thrown. + * + * @param path Path to the default configuration to load. + * @param filename Name of the configuration file. + */ + protected void loadDefaultProperties(final String path, final String filename) { + Properties properties = new Properties(); + + // Get detault configuration from the Castor JAR. + boolean inCastorJar = loadFromClassPath(properties, path + filename); + + // Get overriding configuration from the Java library directory, ignore if not + // found. If found merge existing properties. + boolean inJavaLibDir = loadFromJavaHome(properties, filename); + + // Couldn't find configuration in Castor jar nor Java library directory. + if (!inCastorJar && !inJavaLibDir) { + throw new ConfigurationException("Failed to load configuration: " + filename); + } + + _map.putAll(properties); + } + + /** + * Load common user configuration from classpath root and current working directory. + *
+ * First it loads default configuration contained in Castor JAR. This gets overwritten + * by a configuration found on Java library directory. If no configuration could be found + * until that point a ConfigurationException will be thrown. At last an overriding + * configuration is loaded from root of classpath or, if that could not be found, from + * local working directory. + * + * @param filename Name of the configuration file. + */ + protected void loadUserProperties(final String filename) { + Properties properties = new Properties(); + + // Get common configuration from the classpath root, ignore if not found. + boolean onClasspathRoot = loadFromClassPath(properties, "/" + filename); + + // If not found on classpath root, either it doesn't exist, or "." is not part of + // the classpath, try looking at local working directory. + if (!onClasspathRoot) { loadFromWorkingDirectory(properties, filename); } + + _map.putAll(properties); + } + + /** + * Load properties with given filename from classpath and merge them into the given properties. + * + * @param properties Properties to merge the loaded ones into. + * @param filename Name of the properties file to load from classpath. + * @return true if properties could be loaded, false otherwise. + */ + private boolean loadFromClassPath(final Properties properties, final String filename) { + InputStream classPathStream = null; + try { + URL url = getClass().getResource(filename); + if (url != null) { + classPathStream = url.openStream(); + properties.load(classPathStream); + + if (LOG.isDebugEnabled()) { + LOG.debug("Configuration loaded from classpath: " + filename); + } + + return true; + } + return false; + } catch (Exception ex) { + LOG.warn("Failed to load configuration from classpath: " + filename, ex); + return false; + } finally { + if (classPathStream != null) { + try { + classPathStream.close(); + } catch (IOException e) { + LOG.warn("Failed to close configuration from classpath: " + filename); + } + } + } + } + + /** + * Load properties with given filename from Java library directory and merge them into + * the given properties. + * + * @param properties Properties to merge the loaded ones into. + * @param filename Name of the properties file to load from Java library directory. + * @return true if properties could be loaded, false otherwise. + */ + private boolean loadFromJavaHome(final Properties properties, final String filename) { + try { + String javaHome = System.getProperty("java.home"); + if (javaHome == null) { return false; } + return loadFromFile(properties, new File(new File(javaHome, "lib"), filename)); + } catch (SecurityException ex) { + LOG.warn("Security policy prevented access to system property 'java.home'.", ex); + return false; + } + } + + /** + * Load properties with given filename from local working directory and merge them into + * the given properties. + * + * @param properties Properties to merge the loaded ones into. + * @param filename Name of the properties file to load from local working directory. + * @return true if properties could be loaded, false otherwise. + */ + private boolean loadFromWorkingDirectory(final Properties properties, final String filename) { + return loadFromFile(properties, new File(filename)); + } + + /** + * Load properties with given file and merge them into the given properties. + * + * @param properties Properties to merge the loaded ones into. + * @param file Properties file to load. + * @return true if properties could be loaded, false otherwise. + */ + private boolean loadFromFile(final Properties properties, final File file) { + InputStream fileStream = null; + try { + if (file.exists() && file.canRead()) { + fileStream = new FileInputStream(file); + properties.load(fileStream); + + if (LOG.isDebugEnabled()) { + LOG.debug("Configuration file loaded: " + file); + } + + return true; + } + return false; + } catch (SecurityException ex) { + LOG.warn("Security policy prevented access to configuration file: " + file, ex); + return false; + } catch (Exception ex) { + LOG.warn("Failed to load configuration file: " + file, ex); + return false; + } finally { + if (fileStream != null) { + try { + fileStream.close(); + } catch (IOException e) { + LOG.warn("Failed to close configuration file: " + file); + } + } + } + } + + //-------------------------------------------------------------------------- + + /** + * Put given value associated with given key into the properties map of this configuration. If + * the configuration previously associated the key to another value the previous value will be + * returned. If a mapping for the key previously exist in the parent configuration only, the + * method returns null and not the value of the parent. This allows to distingush + * if the mapping existed in this configuration or one of its parents. + *
+ * Putting a value in this configuration does not change the value of its parent but the + * parents value isn't visible any more as it gets overwritten by this configurations one. + * While this allows to redifine the value of a property it isn't allowed to undefine it. + * Therefore a NullPointerException will be thrown if the given value is + * null. + * + * @param key Key of the property to put into configuration. + * @param value Value to put into configuration associated with the given key.. + * @return Object in this configuration that previously has been associated with the given key. + */ + public final synchronized Object put(final String key, final Object value) { + if (value == null) { throw new NullPointerException(); } + return _map.put(key, value); + } + + /** + * Remove any value previously associated with the given key from this configuration. The value + * previously associated with the key int this configuration will be returned. If a mapping + * for the key existed in the parent configuration only, the method returns null + * and not the value of the parent. This allows to distingush if the mapping existed in this + * configuration or one of its parents. + *
+ * Removing the value from this configuration does not mean that consecutive gets return + * null as one of the parents may still contain a mapping for the key that + * was hidden by the mapping in this configuration. + * + * @param key Key of the property to remove from configuration. + * @return Object in this configuration that previously has been associated with the given key. + */ + public final synchronized Object remove(final String key) { + return _map.remove(key); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to any object value, it will be returned as is. If the property is not found, + * null will be returned. + * + * @param key Key of the property to get from configuration. + * @return Object in this property map with the specified key value. + */ + protected synchronized Object get(final String key) { + Object value = _map.get(key); + if ((value == null) && (_parent != null)) { + value = _parent.get(key); + } + return value; + } + + //-------------------------------------------------------------------------- + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a boolean value, it will be returned as is. For string values that are + * equal, ignore case, to 'true' or 'false', the respective boolean value will be returned. If + * the property is not found, null will be returned. For all other types and + * string values a ConfigurationException will be thrown. This behaviour is intended for those + * usecases that need distinguish between values that are missconfigured or not specified at + * all. + * + * @param key Property key. + * @return Boolean value in this property map with the specified key value. + */ + public final Boolean getBoolean(final String key) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof Boolean) { + return (Boolean) objectValue; + } else if (objectValue instanceof String) { + String stringValue = (String) objectValue; + if ("true".equalsIgnoreCase(stringValue)) { + return Boolean.TRUE; + } else if ("false".equalsIgnoreCase(stringValue)) { + return Boolean.FALSE; + } + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value can not be converted to boolean: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a boolean value, it will be returned as is. For string values that are + * equal, ignore case, to 'true' or 'false', the respective boolean value will be returned. In + * all other cases the given default value will be returned. + * + * @param key Property key. + * @param defaultValue Default value. + * @return Boolean value in this property map with the specified key value. + */ + public final boolean getBoolean(final String key, final boolean defaultValue) { + Object objectValue = get(key); + + if (objectValue instanceof Boolean) { + return ((Boolean) objectValue).booleanValue(); + } else if (objectValue instanceof String) { + String stringValue = (String) objectValue; + if ("true".equalsIgnoreCase(stringValue)) { + return true; + } else if ("false".equalsIgnoreCase(stringValue)) { + return false; + } + } + + return defaultValue; + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a integer value, it will be returned as is. For string values that can + * be interpreted as signed decimal integer, the respective integer value will be returned. If + * the property is not found, null will be returned. For all other types and + * string values a ConfigurationException will be thrown. This behaviour is intended for those + * usecases that need distinguish between values that are missconfigured or not specified at + * all. + * + * @param key Property key. + * @return Integer value in this property map with the specified key value. + */ + public final Integer getInteger(final String key) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof Integer) { + return (Integer) objectValue; + } else if (objectValue instanceof String) { + try { + return Integer.valueOf((String) objectValue); + } catch (NumberFormatException ex) { + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value can not be converted to int: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value can not be converted to int: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a integer value, it will be returned as is. For string values that can + * be interpreted as signed decimal integer, the respective integer value will be returned. In + * all other cases the given default value will be returned. + * + * @param key Property key. + * @param defaultValue Default value. + * @return Integer value in this property map with the specified key value. + */ + public final int getInteger(final String key, final int defaultValue) { + Object objectValue = get(key); + + if (objectValue instanceof Integer) { + return ((Integer) objectValue).intValue(); + } else if (objectValue instanceof String) { + String stringValue = (String) objectValue; + try { + return Integer.parseInt(stringValue); + } catch (NumberFormatException ex) { + return defaultValue; + } + } + + return defaultValue; + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a string value, it will be returned as is. If the property is not found, + * null will be returned. For all other types a ConfigurationException will be + * thrown. + * + * @param key Property key. + * @return String value in this property map with the specified key value. + */ + public final String getString(final String key) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof String) { + return (String) objectValue; + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value is not a string: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a string value that is not empty, it will be returned as is. In all other + * cases the given default value will be returned. + * + * @param key Property key. + * @param defaultValue Default value. + * @return String value in this property map with the specified key value. + */ + public final String getString(final String key, final String defaultValue) { + Object objectValue = get(key); + + if ((objectValue instanceof String) && !"".equals(objectValue)) { + return (String) objectValue; + } + + return defaultValue; + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a string array, it will be returned as is. A simple string will be + * converted into a string array by splitting it into substrings at every occurence of ',' + * character. If the property is not found, null will be returned. For all other + * types a ConfigurationException will be thrown. + * + * @param key Property key. + * @return String array in this property map with the specified key value. + */ + public final String[] getStringArray(final String key) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof String[]) { + return (String[]) objectValue; + } else if (objectValue instanceof String) { + return ((String) objectValue).split(","); + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value is not a String[]: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a class, it will be returned as is. A simple string will be interpreted + * as class name of which the class will be loaded with the given class loader. If the property + * is not found, null will be returned. For all other types and if loading of the + * class fails a ConfigurationException will be thrown. + * + * @param key Property key. + * @param loader Class loader to load classes with. + * @return Class in this property map with the specified key value. + */ + public final Class getClass(final String key, final ClassLoader loader) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof Class) { + return (Class) objectValue; + } else if (objectValue instanceof String) { + String classname = (String) objectValue; + try { + return loader.loadClass(classname); + } catch (ClassNotFoundException ex) { + Object[] args = new Object[] {key, classname}; + String msg = "Could not find class of configuration value: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value is not a Class: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a class array, it will be returned as is. A simple string will be + * splitted it into substrings at every occurence of ',' character. Each of these substrings + * will interpreted as class name of which the class will be loaded with the given class + * loader. If the property is not found, null will be returned. For all other + * types and if loading of one of the classes fails a ConfigurationException will be thrown. + * + * @param key Property key. + * @param loader Class loader to load classes with. + * @return Class array in this property map with the specified key value. + */ + public final Class[] getClassArray(final String key, final ClassLoader loader) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof Class[]) { + return (Class[]) objectValue; + } else if (objectValue instanceof String) { + String[] classnames = ((String) objectValue).split(","); + Class[] classes = new Class[classnames.length]; + for (int i = 0; i < classnames.length; i++) { + try { + classes[i] = loader.loadClass(classnames[i]); + } catch (ClassNotFoundException ex) { + Object[] args = new Object[] {key, new Integer(i), classnames[i]}; + String msg = "Could not find class of configuration value: {0}[{1}]={2}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } + } + return classes; + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value is not a Class[]: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to any object value, it will be returned as is. If the property is not found, + * null will be returned. + * + * @param key Property key. + * @return Object in this property map with the specified key value. + */ + public final Object getObject(final String key) { + return get(key); + } + + /** + * Searches for the property with the specified key in this property map. If the key is not + * found in this property map, the parent property map, and its parents, recursively, are then + * checked. + *
+ * If the key maps to a object array, it will be returned as is. A simple string will be + * splitted it into substrings at every occurence of ',' character. Each of these substrings + * will interpreted as class name of which the class will be loaded with the given class + * loader and instantiated using its default constructor. If the property is not found, + * null will be returned. For all other types and if loading or instantiation of + * one of the classes fails a ConfigurationException will be thrown. + * + * @param key Property key. + * @param loader Class loader to load classes with. + * @return Class array in this property map with the specified key value. + */ + public final Object[] getObjectArray(final String key, final ClassLoader loader) { + Object objectValue = get(key); + + if (objectValue == null) { + return null; + } else if (objectValue instanceof Object[]) { + return (Object[]) objectValue; + } else if (objectValue instanceof String) { + String[] classnames = ((String) objectValue).split(","); + Object[] objects = new Class[classnames.length]; + for (int i = 0; i < classnames.length; i++) { + try { + objects[i] = loader.loadClass(classnames[i]).newInstance(); + } catch (ClassNotFoundException ex) { + Object[] args = new Object[] {key, new Integer(i), classnames[i]}; + String msg = "Could not find configured class: {0}[{1}]={2}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } catch (IllegalAccessException ex) { + Object[] args = new Object[] {key, new Integer(i), classnames[i]}; + String msg = "Could not instantiate configured class: {0}[{1}]={2}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } catch (InstantiationException ex) { + Object[] args = new Object[] {key, new Integer(i), classnames[i]}; + String msg = "Could not instantiate configured class: {0}[{1}]={2}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } catch (ExceptionInInitializerError ex) { + Object[] args = new Object[] {key, new Integer(i), classnames[i]}; + String msg = "Could not instantiate configured class: {0}[{1}]={2}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } catch (SecurityException ex) { + Object[] args = new Object[] {key, new Integer(i), classnames[i]}; + String msg = "Could not instantiate configured class: {0}[{1}]={2}"; + throw new ConfigurationException(MessageFormat.format(msg, args), ex); + } + } + return objects; + } + + Object[] args = new Object[] {key, objectValue}; + String msg = "Configuration value is not an Object[]: {0}={1}"; + throw new ConfigurationException(MessageFormat.format(msg, args)); + } + + //-------------------------------------------------------------------------- +} Index: C:/Java/castor-1/src/main/java/org/castor/core/util/ConfigurationException.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/core/util/ConfigurationException.java (revision 0) +++ C:/Java/castor-1/src/main/java/org/castor/core/util/ConfigurationException.java (revision 0) @@ -0,0 +1,71 @@ +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.core.util; + +import org.castor.core.exceptions.CastorRuntimeException; + +/** + * ConfigurationException is an unchecked exception thrown when Configuration can not be loaded + * or if configuration property can't be converted to the requested type. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public final class ConfigurationException extends CastorRuntimeException { + /** SerialVersionUID */ + private static final long serialVersionUID = 4446761026170253291L; + + /** + * Constructs a new ConfigurationException without a message. The cause is not initialized + * but may subsequently be initialized by a call to initCause(Throwable). + */ + public ConfigurationException() { + super(); + } + + /** + * Constructs a new ConfigurationException with the specified detail message. The cause is + * not initialized but may subsequently be initialized by a call to initCause(Throwable). + * + * @param message The detail message. + */ + public ConfigurationException(final String message) { + super(message); + } + + /** + * Constructs a new ConfigurationException with the specified cause and the detail message + * of the cause. This constructor is useful for exceptions that are wrappers for others. + * + * @param cause The cause. + */ + public ConfigurationException(final Throwable cause) { + super(cause); + } + + /** + * Constructs a new ConfigurationException with the specified detail message and cause. + * + * @param message The detail message. + * @param cause The cause. + */ + public ConfigurationException(final String message, final Throwable cause) { + super(message, cause); + } +} Index: C:/Java/castor-1/src/main/java/org/castor/util/Configuration.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/util/Configuration.java (revision 7076) +++ C:/Java/castor-1/src/main/java/org/castor/util/Configuration.java (working copy) @@ -30,7 +30,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.exolab.castor.core.exceptions.CastorRuntimeException; +import org.castor.core.exceptions.CastorRuntimeException; /** * Class to hold Castor configuration properties. Index: C:/Java/castor-1/src/main/java/org/castor/xml/XMLConfiguration.java =================================================================== --- C:/Java/castor-1/src/main/java/org/castor/xml/XMLConfiguration.java (revision 0) +++ C:/Java/castor-1/src/main/java/org/castor/xml/XMLConfiguration.java (revision 0) @@ -0,0 +1,118 @@ +/* + * Copyright 2007 Ralf Joachim + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Id: Configuration.java 6907 2007-03-28 21:24:52Z rjoachim $ + */ +package org.castor.xml; + +import org.castor.core.CoreConfiguration; +import org.castor.core.util.CastorConfiguration; +import org.castor.core.util.Configuration; + +/** + * Castor configuration of XML modul. + * + * @version $Id: Configuration.java,v 1.8 2006/03/08 17:25:52 jens Exp $ + * @author Ralf Joachim + * @since 1.1.3 + */ +public final class XMLConfiguration extends Configuration { + //-------------------------------------------------------------------------- + + /** Path to Castor configuration of core modul. */ + private static final String FILEPATH = "/org/castor/xml/"; + + /** Name of Castor configuration of core modul. */ + private static final String FILENAME = "castor.xml.properties"; + + /** A static configuration instance to be used during migration to a none static one. */ + // TODO Remove property after support for static configuration has been terminated. + private static Configuration _instance = null; + + //-------------------------------------------------------------------------- + + /** + * Get the one and only static XML configuration. + * + * @return One and only configuration instance for Castor XML modul. + * @deprecated Don't limit your applications flexibility by using a static configuration. Use + * your own configuration instance created with one of the newInstance() methods + * instead. + */ + // TODO Remove method after support for static configuration has been terminated. + public static synchronized Configuration getInstance() { + if (_instance == null) { _instance = newInstance(); } + return _instance; + } + + /** + * Factory method for a default XML configuration instance. Application and domain class + * loaders will be initialized to the one used to load the Configuration class. The + * configuration instance returned will be a CastorConfiguration with a XMLConfiguration and + * a CoreConfiguration instance as parents. The CastorConfiguration holding user specific + * properties is the only one that can be modified by put() and remove() methods. + * XMLConfiguration and CoreConfiguration are responsble to deliver Castor's default values + * if they have not been overwritten by the user. + * + * @return Configuration instance for Castor XML modul. + */ + public static Configuration newInstance() { + Configuration core = new CoreConfiguration(); + Configuration xml = new XMLConfiguration(core); + Configuration castor = new CastorConfiguration(xml); + return castor; + } + + /** + * Factory method for a XML configuration instance that uses the specified class loaders. The + * configuration instance returned will be a CastorConfiguration with a XMLConfiguration and + * a CoreConfiguration instance as parents. The CastorConfiguration holding user specific + * properties is the only one that can be modified by put() and remove() methods. + * XMLConfiguration and CoreConfiguration are responsble to deliver Castor's default values + * if they have not been overwritten by the user. + * + * @param app Classloader to be used for all classes of Castor and its required libraries. + * @param domain Classloader to be used for all domain objects. + * @return Configuration instance for Castor XML modul. + */ + public static Configuration newInstance(final ClassLoader app, final ClassLoader domain) { + Configuration core = new CoreConfiguration(app, domain); + Configuration xml = new XMLConfiguration(core); + Configuration castor = new CastorConfiguration(xml); + return castor; + } + + //-------------------------------------------------------------------------- + + /** + * Construct a configuration with given parent. Application and domain class loaders will be + * initialized to the ones of the parent. + *
+ * Note: This constructor is not intended for public use. Use one of the newInstance() methods + * instead. + * + * @param parent Parent configuration. + */ + public XMLConfiguration(final Configuration parent) { + super(parent); + loadDefaultProperties(FILEPATH, FILENAME); + } + + //-------------------------------------------------------------------------- + + // Specify public keys of XML configuration properties here. + + //-------------------------------------------------------------------------- +} Index: C:/Java/castor-1/src/main/java/org/exolab/castor/core/exceptions/CastorRuntimeException.java =================================================================== --- C:/Java/castor-1/src/main/java/org/exolab/castor/core/exceptions/CastorRuntimeException.java (revision 7076) +++ C:/Java/castor-1/src/main/java/org/exolab/castor/core/exceptions/CastorRuntimeException.java (working copy) @@ -1,82 +0,0 @@ -package org.exolab.castor.core.exceptions; - -import java.io.PrintStream; -import java.io.PrintWriter; - -public final class CastorRuntimeException extends RuntimeException { - /** SerialVersionUID */ - private static final long serialVersionUID = 6183971667763969115L; - - /** The cause for this exception. */ - private Throwable _cause; - - public CastorRuntimeException() { - super(); - } - - public CastorRuntimeException(final Throwable cause) { - super(); - _cause = cause; - } - - public CastorRuntimeException(final String message) { - super(message); - } - - public CastorRuntimeException(final String message, final Throwable cause) { - super(message); - _cause = cause; - } - - /** - * Match the JDK 1.4 Throwable version of getCause() on JDK<1.4 systems. - * - * @return The throwable cause of this exception. - */ - public Throwable getCause() { - return _cause; - } - - /** - * Print a stack trace to stderr. - */ - public void printStackTrace() { - // Print the stack trace for this exception. - super.printStackTrace(); - - if (_cause != null) { - System.err.print("Caused by: "); - _cause.printStackTrace(); - } - } - - /** - * Print a stack trace to the specified PrintStream. - * - * @param s The PrintStream to print a stack trace to. - */ - public void printStackTrace(final PrintStream s) { - // Print the stack trace for this exception. - super.printStackTrace(s); - - if (_cause != null) { - s.print("Caused by: "); - _cause.printStackTrace(s); - } - } - - /** - * Print a stack trace to the specified PrintWriter. - * - * @param w The PrintWriter to print a stack trace to. - */ - public void printStackTrace(final PrintWriter w) { - // Print the stack trace for this exception. - super.printStackTrace(w); - - if (_cause != null) { - w.print("Caused by: "); - _cause.printStackTrace(w); - } - } -} Index: C:/Java/castor-1/src/main/resources/org/castor/core/castor.core.properties =================================================================== --- C:/Java/castor-1/src/main/resources/org/castor/core/castor.core.properties (revision 0) +++ C:/Java/castor-1/src/main/resources/org/castor/core/castor.core.properties (revision 0) @@ -0,0 +1,51 @@ +# Castor core properties file +# +# This file specifies default values of Castor's core modul which may be +# overwritten by the user through castor.properties file. +# +# $Id: castor.properties 7076 2007-07-24 22:03:25Z rjoachim $ + + +# Hashtable/Map default mapping. For backward compatibility with 0.9.5.2 and earlier. +# +#org.exolab.castor.xml.saveMapKeys=false + +# Defines the Regular Expression Evaluator to be used by Castor. The evaluator must +# implement org.exolab.castor.util.RegExpEvaluator. +# +# org.exolab.castor.xml.util.AlwaysTrueRegExpEvaluator +# Suppresses regular expressions evaluation. +# +# org.exolab.castor.util.JakartaRegExpEvaluator +# Uses the Jakarta RegExp library. +# +# org.exolab.castor.util.JakartaOroEvaluator +# Uses the Jakarta ORO library. +# +org.exolab.castor.regexp=org.exolab.castor.util.JakartaOroEvaluator + +# True if debugging output should be generated. +# Defaults to false. +# +org.exolab.castor.debug=false + +# List of collection handlers for Java 1.1 and Java 1.2 run-times: +# +org.exolab.castor.mapping.collections=\ + org.exolab.castor.mapping.loader.J1CollectionHandlers,\ + org.exolab.castor.mapping.loader.J2CollectionHandlers + +# Collection handlers for the source code generator: +# +org.exolab.castor.builder.type.j2=\ + org.exolab.castor.builder.FieldInfoFactoryJ2 +org.exolab.castor.builder.type.j1=\ + org.exolab.castor.builder.FieldInfoFactory +org.exolab.castor.builder.type.odmg=\ + org.exolab.castor.builder.FieldInfoFactoryODMG30 + +# MappingLoader implementations: +# +org.castor.mapping.loaderFactories=\ + org.castor.mapping.JDOMappingLoaderFactory,\ + org.castor.mapping.XMLMappingLoaderFactory Index: C:/Java/castor-1/src/main/resources/org/castor/xml/castor.xml.properties =================================================================== --- C:/Java/castor-1/src/main/resources/org/castor/xml/castor.xml.properties (revision 0) +++ C:/Java/castor-1/src/main/resources/org/castor/xml/castor.xml.properties (revision 0) @@ -0,0 +1,102 @@ +# Castor XML properties file +# +# This file specifies default values of Castor's XML modul which may be +# overwritten by the user through castor.properties file. +# +# $Id: castor.properties 7076 2007-07-24 22:03:25Z rjoachim $ + + +# Defines the default XML parser to be used by Castor. +# The parser must implement org.xml.sax.Parser. +# +org.exolab.castor.parser=org.apache.xerces.parsers.SAXParser + +# Defines the (default) XML serializer factory to use by Castor at marshalling. The +# factory must implement org.exolab.castor.xml.SerializerFactory. The default value is: +# org.exolab.castor.xml.XercesXMLSerializerFactory +# +# When using Castor XML with JDK 5.0, you may may want to switch to: +# org.exolab.castor.xml.XercesJDK5XMLSerializerFactory +# which will use the Xerces instance as shipped with the JDK itself. This avoids +# having to download another Xerces instance and installing it. +# +org.exolab.castor.xml.serializer.factory=org.exolab.castor.xml.XercesXMLSerializerFactory + +# Defines the NodeType for use with Java primitive types (int, long, boolean, etc). +# This value is only used by the Introspector. Valid values are either "attribute" or +# "element". By default, all primitives are marshaled as attributes. +# +org.exolab.castor.xml.introspector.primitive.nodetype=attribute + +# Defines the Naming "style" or conventions to use when creating XML names from Java +# class or field names. Valid values are as follows: +# +# ------------------------------------------------------------------------------------- +# lower (default) | All names are lowercase with hyphens separating words. +# | +# | Example: personInfo = person-info +# ------------------------------------------------------------------------------------- +# mixed | All names are mixed case, with Uppercase character as the first +# | letter of a new word. +# | +# | Example: personInfo = personInfo +# | Example: FooBar = fooBar +# ------------------------------------------------------------------------------------- +# {Any ClassName} | Any Class which implements org.exolab.castor.xml.XMLNaming. +# ------------------------------------------------------------------------------------- +# +# By default, all names are treated as the "lower" option. +# +org.exolab.castor.xml.naming=lower + +# True if all documents should be indented on output. Defaults to false. +# +org.exolab.castor.indent=false + +# True if xml documents should be validated by the SAX Parser. Defaults to false. +# +org.exolab.castor.parser.validation=false + +# True for parser to support Namespaces. Defaults to false. +# +org.exolab.castor.parser.namespaces=false + +# True if all documents should be validated by the marshaling framework +# Defaults to true. +# +org.exolab.castor.marshalling.validation=true + +# Comma separated list of SAX 2 features that should be enabled for the +# default parser. +# +#org.exolab.castor.sax.features= + +# Comma separated list of SAX 2 features that should be disabled for the +# default parser. +# +#org.exolab.castor.sax.features-to-disable= + +# Property specifying whether or not to search for an proxy interface at marshalling. +# If property is not empty the objects to be marshalled will be searched if they +# implement one of the given interface names. If the interface is implemented the +# superclass will be marshalled instead of the class itself. +# +#org.exolab.castor.xml.proxyInterfaces=\ +# net.sf.cglib.proxy.Factory, \ +# org.hibernate.proxy.HibernateProxy + +# Specifyies whether the ClassDescriptorResolver should (automatically) search +# for and consult with package mapping files (.castor.xml) to retrieve class +# descriptor information. Defaults to true. +# +org.exolab.castor.xml.loadPackageMappings=true + +# Property specifying whether sequence order validation should be lenient; +# Defaults to false +# +org.exolab.castor.xml.lenient.sequence.order=false + +# Property specifying whether id/href validation should be lenient; +# defaults to false +# +org.exolab.castor.xml.lenient.id.validation=false