blob: 40552dbb0ffbd2a83e9515459b7c4f92ce032ff2 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache
* XMLBeans", nor may "Apache" appear in their name, without prior
* written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 2000-2003 BEA Systems
* Inc., <http://www.bea.com/>. For more information on the Apache Software
* Foundation, please see <http://www.apache.org/>.
*/
package org.apache.xmlbeans;
import javax.xml.namespace.QName;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Provides an assortment of utilities
* for managing XML Bean types, type systems, QNames, paths,
* and queries.
*/
public final class XmlBeans
{
/**
* Thread local QName cache for general use
*/
private static final ThreadLocal _threadLocalLoaderQNameCache =
new ThreadLocal()
{
protected Object initialValue()
{
return new QNameCache( 32 );
}
};
/**
* Returns a thread local QNameCache
*/
public static QNameCache getQNameCache ( )
{
return (QNameCache) _threadLocalLoaderQNameCache.get();
}
/**
* Obtains a name from the thread local QNameCache
*/
public static QName getQName ( String localPart )
{
return getQNameCache().getName( "", localPart );
}
/**
* Obtains a name from the thread local QNameCache
*/
public static QName getQName ( String namespaceUri, String localPart )
{
return getQNameCache().getName( namespaceUri, localPart );
}
private static final Method _getContextTypeLoaderMethod = buildGetContextTypeLoaderMethod();
private static final Method _getBuiltinSchemaTypeSystemMethod = buildGetBuiltinSchemaTypeSystemMethod();
private static final Method _getNoTypeMethod = buildGetNoTypeMethod();
private static final Method _typeLoaderBuilderMethod = buildTypeLoaderBuilderMethod();
private static final Method _compilationMethod = buildCompilationMethod();
private static RuntimeException causedException(RuntimeException e, Throwable cause)
{
e.initCause(cause);
return e;
}
private static XmlException wrappedException(Throwable e)
{
if (e instanceof XmlException)
return (XmlException) e;
return new XmlException( e.getMessage(), e );
}
private static Method buildGetContextTypeLoaderMethod()
{
try
{
return Class.forName("org.apache.xmlbeans.impl.schema.SchemaTypeLoaderImpl", false, XmlBeans.class.getClassLoader()).getMethod("getContextTypeLoader", new Class[0]);
}
catch (Exception e)
{
throw causedException(new IllegalStateException("Cannot load SchemaTypeLoaderImpl: verify that xbean.jar is on the classpath"), e);
}
}
private static final Method buildGetBuiltinSchemaTypeSystemMethod()
{
try
{
return Class.forName("org.apache.xmlbeans.impl.schema.BuiltinSchemaTypeSystem", false, XmlBeans.class.getClassLoader()).getMethod("get", new Class[0]);
}
catch (Exception e)
{
throw causedException(new IllegalStateException("Cannot load BuiltinSchemaTypeSystem: verify that xbean.jar is on the classpath"), e);
}
}
private static final Method buildGetNoTypeMethod()
{
try
{
return Class.forName("org.apache.xmlbeans.impl.schema.BuiltinSchemaTypeSystem", false, XmlBeans.class.getClassLoader()).getMethod("getNoType", new Class[0]);
}
catch (Exception e)
{
throw causedException(new IllegalStateException("Cannot load BuiltinSchemaTypeSystem: verify that xbean.jar is on the classpath"), e);
}
}
private static final Method buildTypeLoaderBuilderMethod()
{
try
{
Class resourceLoaderClass = Class.forName("org.apache.xmlbeans.impl.schema.ResourceLoader", false, XmlBeans.class.getClassLoader());
return Class.forName("org.apache.xmlbeans.impl.schema.SchemaTypeLoaderImpl", false, XmlBeans.class.getClassLoader()).getMethod("build", new Class[] { SchemaTypeLoader[].class, resourceLoaderClass, ClassLoader.class });
}
catch (Exception e)
{
throw causedException(new IllegalStateException("Cannot load SchemaTypeLoaderImpl: verify that xbean.jar is on the classpath"), e);
}
}
private static final Method buildCompilationMethod()
{
try
{
return Class.forName("org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl", false, XmlBeans.class.getClassLoader()).getMethod("forSchemaXml", new Class[] { XmlObject[].class, SchemaTypeLoader.class, XmlOptions.class });
}
catch (Exception e)
{
throw causedException(new IllegalStateException("Cannot load SchemaTypeSystemImpl: verify that xbean.jar is on the classpath"), e);
}
}
/**
* Compiles an XPath, returning a String equal to that which was passed,
* but whose identity is that of one which has been precompiled and cached.
*/
public static String compilePath ( String pathExpr ) throws XmlException
{
return compilePath( pathExpr, null );
}
/**
* Compiles an XPath, returning a String equal to that which was passed,
* but whose identity is that of one which has been precompiled and cached;
* takes an option for specifying text that indicates the name of context node.
* The default is "this", as in "$this".
*
* @param options Options for the path. For example, you can call
* the {@link XmlOptions#setXqueryCurrentNodeVar(String) XmlOptions.setXqueryCurrentNodeVar(String)}
* method to specify a particular name for the expression
* variable that indicates the context node.
*/
public static String compilePath ( String pathExpr, XmlOptions options )
throws XmlException
{
return getContextTypeLoader().compilePath( pathExpr, options );
}
/**
* Compiles an XQuery, returning a String equal to that which was passed,
* but whose identity is that of one which has been precompiled and cached.
*/
public static String compileQuery ( String queryExpr ) throws XmlException
{
return compileQuery( queryExpr, null );
}
/**
* Compiles an XQuery, returning a String equal to that which was passed,
* but whose identity is that of one which has been precompiled and cached;
* takes an option for specifying text that indicates the context node.
*
* @param options Options for the query. For example, you can call
* the {@link XmlOptions#setXqueryCurrentNodeVar(String) XmlOptions.setXqueryCurrentNodeVar(String)}
* method to specify a particular name for the expression
* variable that indicates the context node.
*/
public static String compileQuery ( String queryExpr, XmlOptions options )
throws XmlException
{
return getContextTypeLoader().compileQuery( queryExpr, options );
}
/**
* Gets the SchemaTypeLoader based on the current thread's context
* ClassLoader. This is the SchemaTypeLoader that is used to assign
* schema types to XML documents by default. The SchemaTypeLoader is
* also consulted to resolve wildcards and xsi:type attributes.
* <p>
* The "parse" methods of XmlBeans all delegate to the
* "parseInstance" methods of the context type loader.
*/
public static SchemaTypeLoader getContextTypeLoader()
{
try
{
return (SchemaTypeLoader)_getContextTypeLoaderMethod.invoke(null, null);
}
catch (IllegalAccessException e)
{
throw causedException(new IllegalStateException("No access to SchemaTypeLoaderImpl.getContextTypeLoader(): verify that version of xbean.jar is correct"), e);
}
catch (InvocationTargetException e)
{
throw causedException(new IllegalStateException(e.getMessage()), e.getCause());
}
}
/**
* Returns the builtin type system. This SchemaTypeSystem contains
* only the 46 builtin types defined by the XML Schema specification.
*/
public static SchemaTypeSystem getBuiltinTypeSystem()
{
try
{
return (SchemaTypeSystem)_getBuiltinSchemaTypeSystemMethod.invoke(null, null);
}
catch (IllegalAccessException e)
{
throw causedException(new IllegalStateException("No access to BuiltinSchemaTypeSystem.get(): verify that version of xbean.jar is correct"), e);
}
catch (InvocationTargetException e)
{
throw causedException(new IllegalStateException(e.getMessage()), e.getCause());
}
}
/**
* Returns the SchemaTypeSystem that results from compiling the XML
* schema definitions passed.
* <p>
* Just like compileTypeSystem, but uses the context type loader for
* linking, and returns a unioned typeloader that is suitable for
* creating instances.
*/
public static SchemaTypeLoader loadXsd(XmlObject[] schemas) throws XmlException
{
return loadXsd(schemas, null);
}
/**
* <p>Returns the SchemaTypeSystem that results from compiling the XML
* schema definitions passed in <em>schemas</em>.</p>
*
* <p>This is just like compileTypeSystem, but uses the context type loader for
* linking, and returns a unioned typeloader that is suitable for
* creating instances.</p>
*
* <p>Use the <em>options</em> parameter to specify one or both of the following:</p>
*
* <ul>
* <li>A collection instance that should be used as an error listener during
* compilation, as described in {@link XmlOptions#setErrorListener}.</li>
* <li>Whether validation should not be done when building the SchemaTypeSystem,
* as described in {@link XmlOptions#setCompileNoValidation}.</li>
* </ul>
*
* @param schemas The schema definitions from which to build the schema type system.
* @param options Options specifying an error listener and/or validation behavior.
*/
public static SchemaTypeLoader loadXsd(XmlObject[] schemas, XmlOptions options) throws XmlException
{
try
{
SchemaTypeSystem sts =
(SchemaTypeSystem)
_compilationMethod.invoke(
null, new Object[] { schemas, getContextTypeLoader(), options });
if (sts == null)
return null;
return
typeLoaderUnion(
new SchemaTypeLoader[] { sts, getContextTypeLoader() } );
}
catch (IllegalAccessException e)
{
throw causedException(new IllegalStateException("No access to SchemaTypeLoaderImpl.forSchemaXml(): verify that version of xbean.jar is correct"), e);
}
catch (InvocationTargetException e)
{
throw wrappedException(e.getCause());
}
}
/**
* <p>Returns the SchemaTypeSystem that results from compiling the XML
* schema definitions passed.</p>
*
* <p>The XmlObjects passed in should be w3c &lt;schema&gt; elements whose type
* is org.w3c.x2001.xmlSchema.Schema. (That is, schema elements in
* the XML namespace http://www.w3c.org/2001/XMLSchema.) Also
* org.w3c.x2001.xmlSchema.SchemaDocument is permitted.</p>
*
* <p>The optional second argument is a SchemaTypeLoader which will be
* consulted for already-compiled schema types which may be linked
* while processing the given schemas.</p>
*
* <p>The SchemaTypeSystem that is returned should be combined
* (via {@link #typeLoaderUnion}) with the typepath typeloader in order
* to create a typeloader that can be used for creating and validating
* instances.</p>
*
* <p>Use the <em>options</em> parameter to specify the following:</p>
*
* <ul>
* <li>A collection instance that should be used as an error listener during
* compilation, as described in {@link XmlOptions#setErrorListener}.</li>
* <li>Whether validation should not be done when building the SchemaTypeSystem,
* as described in {@link XmlOptions#setCompileNoValidation}.</li>
* </ul>
*
* @param schemas The schema definitions from which to build the schema type system.
* @param typepath The path to already-compiled schema types for linking while processing.
* @param options Options specifying an error listener and/or validation behavior.
*/
public static SchemaTypeSystem compileXsd(XmlObject[] schemas, SchemaTypeLoader typepath, XmlOptions options) throws XmlException
{
if (typepath == null)
throw new IllegalArgumentException("Must supply a SchemaTypeLoader for compiletime linking");
try
{
return (SchemaTypeSystem)_compilationMethod.invoke(null, new Object[] { schemas, typepath, options });
}
catch (IllegalAccessException e)
{
throw new IllegalStateException("No access to SchemaTypeLoaderImpl.forSchemaXml(): verify that version of xbean.jar is correct");
}
catch (InvocationTargetException e)
{
throw wrappedException(e.getCause());
}
}
/**
* Returns the union of a list of typeLoaders. The returned
* SchemaTypeLoader searches the given list of SchemaTypeLoaders
* in order from first to last.
*/
public static SchemaTypeLoader typeLoaderUnion(SchemaTypeLoader[] typeLoaders)
{
try
{
if (typeLoaders.length == 1)
return typeLoaders[0];
return (SchemaTypeLoader)_typeLoaderBuilderMethod.invoke(null, new Object[] {typeLoaders, null, null});
}
catch (IllegalAccessException e)
{
throw causedException(new IllegalStateException("No access to SchemaTypeLoaderImpl: verify that version of xbean.jar is correct"), e);
}
catch (InvocationTargetException e)
{
throw causedException(new IllegalStateException(e.getMessage()), e.getCause());
}
}
/**
* Returns a SchemaTypeLoader that searches for compiled schema types
* in the given ClassLoader.
*/
public static SchemaTypeLoader typeLoaderForClassLoader(ClassLoader loader)
{
try
{
return (SchemaTypeLoader)_typeLoaderBuilderMethod.invoke(null, new Object[] {null, null, loader});
}
catch (IllegalAccessException e)
{
throw causedException(new IllegalStateException("No access to SchemaTypeLoaderImpl: verify that version of xbean.jar is correct"), e);
}
catch (InvocationTargetException e)
{
throw causedException( new IllegalStateException(e.getMessage()), e );
}
}
/**
* Returns the SchemaType from a corresponding XmlObject subclass,
* or null if none.
*/
public static SchemaType typeForClass(Class c)
{
if (c == null || !XmlObject.class.isAssignableFrom(c))
return null;
try
{
Field typeField = c.getField("type");
if (typeField == null)
return null;
return (SchemaType)typeField.get(null);
}
catch (Exception e)
{
return null;
}
}
private static SchemaType getNoType()
{
try
{
return (SchemaType)_getNoTypeMethod.invoke(null, null);
}
catch (IllegalAccessException e)
{
throw causedException(new IllegalStateException("No access to SchemaTypeLoaderImpl.getContextTypeLoader(): verify that version of xbean.jar is correct"), e);
}
catch (InvocationTargetException e)
{
throw causedException(new IllegalStateException(e.getMessage()), e.getCause());
}
}
/**
* The SchemaType object given to an XmlObject instance when
* no type can be determined.
* <p>
* The NO_TYPE is the universal derived type. That is, it is
* derived from all other schema types, and no instances of the
* NO_TYPE are valid. (It is not to be confused with the anyType,
* which is the universal base type from which all other types
* can be derived, and of which all instances are valid.)
*/
public static SchemaType NO_TYPE = getNoType();
private XmlBeans ( ) { }
}