org.castor.mapping.MappingUnmarshaller Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of castor-xml Show documentation
Show all versions of castor-xml Show documentation
The core XML data binding framework with support for marshalling Java objects to
and unmarshalling from XML documents.
/*
* Copyright 2005 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.
*/
package org.castor.mapping;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.castor.core.CoreProperties;
import org.castor.core.util.Messages;
import org.castor.xml.InternalContext;
import org.castor.xml.AbstractInternalContext;
import org.exolab.castor.mapping.Mapping;
import org.exolab.castor.mapping.MappingException;
import org.exolab.castor.mapping.MappingLoader;
import org.exolab.castor.mapping.loader.AbstractMappingLoader;
import org.exolab.castor.mapping.xml.ClassMapping;
import org.exolab.castor.mapping.xml.Include;
import org.exolab.castor.mapping.xml.KeyGeneratorDef;
import org.exolab.castor.mapping.xml.MappingRoot;
import org.exolab.castor.util.DTDResolver;
import org.exolab.castor.xml.ClassDescriptorResolverFactory;
import org.exolab.castor.xml.Introspector;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.XMLClassDescriptorResolver;
import org.exolab.castor.xml.util.ResolverStrategy;
import org.exolab.castor.xml.util.resolvers.CastorXMLStrategy;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* @author Ralf Joachim
* @version $Revision: 5951 $ $Date: 2006-04-25 16:09:10 -0600 (Tue, 25 Apr 2006) $
*/
public final class MappingUnmarshaller {
//--------------------------------------------------------------------------
/** The Jakarta Commons
* Logging instance used for all logging. */
private static final Log LOG = LogFactory.getLog(MappingUnmarshaller.class);
/** The registry of MappingLoader's. */
private final MappingLoaderRegistry _registry;
/** The IDResolver to give to the Unmarshaller. This allows resolving "extends" and
* "depends" for included Mappings. */
private final MappingUnmarshallIDResolver _idResolver;
/** A flag that indicates of whether or not to allow redefinitions of class
* mappings. */
private boolean _allowRedefinitions = false;
/**
* The {@link AbstractInternalContext}?holds all 'global' Castor states and access to
* configuration.
*/
private InternalContext _internalContext;
//--------------------------------------------------------------------------
/**
* Construct a new MappingUnmarshaller.
*/
public MappingUnmarshaller() {
_registry = new MappingLoaderRegistry(new CoreProperties());
_idResolver = new MappingUnmarshallIDResolver();
AbstractInternalContext internalContext = new AbstractInternalContext() { };
internalContext.setClassLoader(getClass().getClassLoader());
XMLClassDescriptorResolver cdr = (XMLClassDescriptorResolver) ClassDescriptorResolverFactory
.createClassDescriptorResolver(BindingType.XML);
cdr.setInternalContext(internalContext);
internalContext.setXMLClassDescriptorResolver(cdr);
Introspector introspector = new Introspector();
introspector.setInternalContext(internalContext);
internalContext.setIntrospector(introspector);
cdr.setIntrospector(introspector);
ResolverStrategy resolverStrategy = new CastorXMLStrategy();
internalContext.setResolverStrategy(resolverStrategy);
cdr.setResolverStrategy(resolverStrategy);
_internalContext = internalContext;
}
/**
* Enables or disables the ability to allow the redefinition
* of class mappings.
*
* @param allow a boolean that when true enables redefinitions.
**/
public void setAllowRedefinitions(final boolean allow) {
_allowRedefinitions = allow;
}
//--------------------------------------------------------------------------
/**
* Returns a mapping resolver for the suitable engine. The engine's
* specific mapping loader is created and used to create engine
* specific descriptors, returning a suitable mapping resolver.
* The mapping resolver is cached in memory and returned in
* subsequent method calls.
*
* @param mapping The mapping to load and resolve.
* @param bindingType The binding type to read from mapping.
* @return A mapping resolver.
* @throws MappingException A mapping error occured preventing
* descriptors from being generated from the loaded mapping.
*/
public MappingLoader getMappingLoader(final Mapping mapping,
final BindingType bindingType)
throws MappingException {
return getMappingLoader(mapping, bindingType, null);
}
/**
* Returns a mapping resolver for the suitable engine. The engine's
* specific mapping loader is created and used to create engine
* specific descriptors, returning a suitable mapping resolver.
* The mapping resolver is cached in memory and returned in
* subsequent method calls.
*
* @param mapping The mapping to load and resolve.
* @param bindingType The binding type to read from mapping.
* @param param Arbitrary parameter that is to be passed to resolver.loadMapping().
* @return A mapping resolver
* @throws MappingException A mapping error occured preventing
* descriptors from being generated from the loaded mapping.
*/
public MappingLoader getMappingLoader(final Mapping mapping,
final BindingType bindingType,
final Object param)
throws MappingException {
synchronized (this) {
Iterator iter = mapping.getMappingSources().iterator();
while (iter.hasNext()) {
MappingSource source = (MappingSource) iter.next();
loadMappingInternal(mapping, source.getResolver(), source.getSource());
}
AbstractMappingLoader loader;
loader = (AbstractMappingLoader) _registry.getMappingLoader(
"CastorXmlMapping", bindingType);
loader.setClassLoader(mapping.getClassLoader());
loader.setAllowRedefinitions(_allowRedefinitions);
loader.setInternalContext(_internalContext);
loader.loadMapping(mapping.getRoot(), param);
return loader;
}
}
public void loadMappingOnly(final Mapping mapping)
throws MappingException {
synchronized (this) {
Iterator iter = mapping.getMappingSources().iterator();
while (iter.hasNext()) {
MappingSource source = (MappingSource) iter.next();
loadMappingInternal(mapping, source.getResolver(), source.getSource());
}
}
}
//--------------------------------------------------------------------------
/**
* Internal recursive loading method. This method will load the
* mapping document into a mapping object and load all the included
* mapping along the way into a single collection.
*
* @param mapping The mapping instance.
* @param resolver The entity resolver to use.
* @param url The URL of the mapping file.
* @throws IOException An error occured when reading the mapping file.
* @throws MappingException The mapping file is invalid.
*/
protected void loadMappingInternal(final Mapping mapping, final DTDResolver resolver,
final String url)
throws IOException, MappingException {
try {
InputSource source = resolver.resolveEntity(null, url);
if (source == null) { source = new InputSource(url); }
if (source.getSystemId() == null) { source.setSystemId(url); }
LOG.info(Messages.format("mapping.loadingFrom", url));
loadMappingInternal(mapping, resolver, source);
} catch (SAXException ex) {
throw new MappingException(ex);
}
}
/**
* Internal recursive loading method. This method will load the
* mapping document into a mapping object and load all the included
* mapping along the way into a single collection.
*
* @param mapping The mapping instance.
* @param resolver The entity resolver to use. May be null.
* @param source The input source.
* @throws MappingException The mapping file is invalid.
*/
private void loadMappingInternal(final Mapping mapping, final DTDResolver resolver,
final InputSource source)
throws MappingException {
// Clear all the cached resolvers, so they can be reconstructed a
// second time based on the new mappings loaded
_registry.clear();
Object id = source.getSystemId();
if (id == null) { id = source.getByteStream(); }
if (id != null) {
//check that the mapping has already been processed
if (mapping.processed(id)) { return; }
//mark the mapping as being processed
mapping.markAsProcessed(id);
}
MappingRoot root = mapping.getRoot();
_idResolver.setMapping(root);
try {
// Load the specificed mapping source
Unmarshaller unm = new Unmarshaller(MappingRoot.class);
unm.setValidation(false);
unm.setEntityResolver(resolver);
unm.setClassLoader(Mapping.class.getClassLoader());
unm.setIDResolver(_idResolver);
unm.setUnmarshalListener(
new MappingUnmarshallListener(this, mapping, resolver));
MappingRoot loaded = (MappingRoot) unm.unmarshal(source);
// Load all the included mapping by reference
//-- note: this is just for processing any
//-- includes which may have previously failed
//-- using the IncludeListener...and to
//-- report any potential errors.
Enumeration includes = loaded.enumerateInclude();
while (includes.hasMoreElements()) {
Include include = (Include) includes.nextElement();
if (!mapping.processed(include.getHref())) {
try {
loadMappingInternal(mapping, resolver, include.getHref());
} catch (Exception ex) {
throw new MappingException(ex);
}
}
}
// gather "class" tags
Enumeration enumeration = loaded.enumerateClassMapping();
while (enumeration.hasMoreElements()) {
root.addClassMapping((ClassMapping) enumeration.nextElement());
}
// gather "key-generator" tags
enumeration = loaded.enumerateKeyGeneratorDef();
while (enumeration.hasMoreElements()) {
root.addKeyGeneratorDef((KeyGeneratorDef) enumeration.nextElement());
}
// gather "field-handler" tags
root.setFieldHandlerDef(loaded.getFieldHandlerDef());
} catch (Exception ex) {
throw new MappingException(ex);
}
}
/**
* To set the internal context.
* @param internalContext the {@link AbstractInternalContext}?to use
*/
// public void setInternalContext(final InternalContext internalContext) {
// _internalContext = internalContext;
// }
//--------------------------------------------------------------------------
}