📄 beanreader.java
字号:
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* 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.apache.commons.betwixt.io;
import java.beans.IntrospectionException;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.SAXParser;
import org.apache.commons.betwixt.BindingConfiguration;
import org.apache.commons.betwixt.ElementDescriptor;
import org.apache.commons.betwixt.XMLBeanInfo;
import org.apache.commons.betwixt.XMLIntrospector;
import org.apache.commons.betwixt.io.read.ReadConfiguration;
import org.apache.commons.betwixt.io.read.ReadContext;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.ExtendedBaseRules;
import org.apache.commons.digester.RuleSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.XMLReader;
/** <p><code>BeanReader</code> reads a tree of beans from an XML document.</p>
*
* <p>Call {@link #registerBeanClass(Class)} or {@link #registerBeanClass(String, Class)}
* to add rules to map a bean class.</p>
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
*/
public class BeanReader extends Digester {
/** Introspector used */
private XMLIntrospector introspector = new XMLIntrospector();
/** Log used for logging (Doh!) */
private Log log = LogFactory.getLog( BeanReader.class );
/** The registered classes */
private Set registeredClasses = new HashSet();
/** Dynamic binding configuration settings */
private BindingConfiguration bindingConfiguration = new BindingConfiguration();
/** Reading specific configuration settings */
private ReadConfiguration readConfiguration = new ReadConfiguration();
/**
* Construct a new BeanReader with default properties.
*/
public BeanReader() {
// TODO: now we require extended rules may need to document this
setRules(new ExtendedBaseRules());
}
/**
* Construct a new BeanReader, allowing a SAXParser to be passed in. This
* allows BeanReader to be used in environments which are unfriendly to
* JAXP1.1 (such as WebLogic 6.0). Thanks for the request to change go to
* James House (james@interobjective.com). This may help in places where
* you are able to load JAXP 1.1 classes yourself.
*
* @param parser use this <code>SAXParser</code>
*/
public BeanReader(SAXParser parser) {
super(parser);
setRules(new ExtendedBaseRules());
}
/**
* Construct a new BeanReader, allowing an XMLReader to be passed in. This
* allows BeanReader to be used in environments which are unfriendly to
* JAXP1.1 (such as WebLogic 6.0). Note that if you use this option you
* have to configure namespace and validation support yourself, as these
* properties only affect the SAXParser and emtpy constructor.
*
* @param reader use this <code>XMLReader</code> as source for SAX events
*/
public BeanReader(XMLReader reader) {
super(reader);
setRules(new ExtendedBaseRules());
}
/**
* <p>Register a bean class and add mapping rules for this bean class.</p>
*
* <p>A bean class is introspected when it is registered.
* It will <strong>not</strong> be introspected again even if the introspection
* settings are changed.
* If re-introspection is required, then {@link #deregisterBeanClass} must be called
* and the bean re-registered.</p>
*
* <p>A bean class can only be registered once.
* If the same class is registered a second time, this registration will be ignored.
* In order to change a registration, call {@link #deregisterBeanClass}
* before calling this method.</p>
*
* <p>All the rules required to digest this bean are added when this method is called.
* Other rules that you want to execute before these should be added before this
* method is called.
* Those that should be executed afterwards, should be added afterwards.</p>
*
* @param beanClass the <code>Class</code> to be registered
* @throws IntrospectionException if the bean introspection fails
*/
public void registerBeanClass(Class beanClass) throws IntrospectionException {
if ( ! registeredClasses.contains( beanClass ) ) {
if ( log.isTraceEnabled() ) {
log.trace( "Registering class " + beanClass );
}
registeredClasses.add( beanClass );
// introspect and find the ElementDescriptor to use as the root
XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();
String path = elementDescriptor.getQualifiedName();
if (log.isTraceEnabled()) {
log.trace("Added path: " + path + ", mapped to: " + beanClass.getName());
}
addBeanCreateRule( path, elementDescriptor, beanClass );
} else {
if ( log.isWarnEnabled() ) {
log.warn("Cannot add class " + beanClass.getName() + " since it already exists");
}
}
}
/**
* <p>Registers a bean class
* and add mapping rules for this bean class at the given path expression.</p>
*
*
* <p>A bean class is introspected when it is registered.
* It will <strong>not</strong> be introspected again even if the introspection
* settings are changed.
* If re-introspection is required, then {@link #deregisterBeanClass} must be called
* and the bean re-registered.</p>
*
* <p>A bean class can only be registered once.
* If the same class is registered a second time, this registration will be ignored.
* In order to change a registration, call {@link #deregisterBeanClass}
* before calling this method.</p>
*
* <p>All the rules required to digest this bean are added when this method is called.
* Other rules that you want to execute before these should be added before this
* method is called.
* Those that should be executed afterwards, should be added afterwards.</p>
*
* @param path the xml path expression where the class is to registered.
* This should be in digester path notation
* @param beanClass the <code>Class</code> to be registered
* @throws IntrospectionException if the bean introspection fails
*/
public void registerBeanClass(String path, Class beanClass) throws IntrospectionException {
if ( ! registeredClasses.contains( beanClass ) ) {
registeredClasses.add( beanClass );
// introspect and find the ElementDescriptor to use as the root
XMLBeanInfo xmlInfo = introspector.introspect( beanClass );
ElementDescriptor elementDescriptor = xmlInfo.getElementDescriptor();
addBeanCreateRule( path, elementDescriptor, beanClass );
} else {
if ( log.isWarnEnabled() ) {
log.warn("Cannot add class " + beanClass.getName() + " since it already exists");
}
}
}
/**
* <p>Flush all registered bean classes.
* This allows all bean classes to be re-registered
* by a subsequent calls to <code>registerBeanClass</code>.</p>
*
* <p><strong>Note</strong> that deregistering a bean does <strong>not</strong>
* remove the Digester rules associated with that bean.</p>
* @since 0.5
*/
public void flushRegisteredBeanClasses() {
registeredClasses.clear();
}
/**
* <p>Remove the given class from the register.
* Calling this method will allow the bean class to be re-registered
* by a subsequent call to <code>registerBeanClass</code>.
* This allows (for example) a bean to be reintrospected after a change
* to the introspection settings.</p>
*
* <p><strong>Note</strong> that deregistering a bean does <strong>not</strong>
* remove the Digester rules associated with that bean.</p>
*
* @param beanClass the <code>Class</code> to remove from the set of registered bean classes
* @since 0.5
*/
public void deregisterBeanClass( Class beanClass ) {
registeredClasses.remove( beanClass );
}
// Properties
//-------------------------------------------------------------------------
/**
* <p> Get the introspector used. </p>
*
* <p> The {@link XMLBeanInfo} used to map each bean is
* created by the <code>XMLIntrospector</code>.
* One way in which the mapping can be customized is by
* altering the <code>XMLIntrospector</code>. </p>
*
* @return the <code>XMLIntrospector</code> used for the introspection
*/
public XMLIntrospector getXMLIntrospector() {
return introspector;
}
/**
* <p> Set the introspector to be used. </p>
*
* <p> The {@link XMLBeanInfo} used to map each bean is
* created by the <code>XMLIntrospector</code>.
* One way in which the mapping can be customized is by
* altering the <code>XMLIntrospector</code>. </p>
*
* @param introspector use this introspector
*/
public void setXMLIntrospector(XMLIntrospector introspector) {
this.introspector = introspector;
}
/**
* <p> Get the current level for logging. </p>
*
* @return the <code>Log</code> implementation this class logs to
*/
public Log getLog() {
return log;
}
/**
* <p> Set the current logging level. </p>
*
* @param log the <code>Log</code>implementation to use for logging
*/
public void setLog(Log log) {
this.log = log;
setLogger(log);
}
/**
* Should the reader use <code>ID</code> attributes to match beans.
*
* @return true if <code>ID</code> and <code>IDREF</code>
* attributes should be used to match instances
* @deprecated 0.5 use {@link BindingConfiguration#getMapIDs}
*/
public boolean getMatchIDs() {
return getBindingConfiguration().getMapIDs();
}
/**
* Set whether the read should use <code>ID</code> attributes to match beans.
*
* @param matchIDs pass true if <code>ID</code>'s should be matched
* @deprecated 0.5 use {@link BindingConfiguration#setMapIDs}
*/
public void setMatchIDs(boolean matchIDs) {
getBindingConfiguration().setMapIDs( matchIDs );
}
/**
* Gets the dynamic configuration setting to be used for bean reading.
* @return the BindingConfiguration settings, not null
* @since 0.5
*/
public BindingConfiguration getBindingConfiguration() {
return bindingConfiguration;
}
/**
* Sets the dynamic configuration setting to be used for bean reading.
* @param bindingConfiguration the BindingConfiguration settings, not null
* @since 0.5
*/
public void setBindingConfiguration( BindingConfiguration bindingConfiguration ) {
this.bindingConfiguration = bindingConfiguration;
}
/**
* Gets read specific configuration details.
* @return the ReadConfiguration, not null
* @since 0.5
*/
public ReadConfiguration getReadConfiguration() {
return readConfiguration;
}
/**
* Sets the read specific configuration details.
* @param readConfiguration not null
* @since 0.5
*/
public void setReadConfiguration( ReadConfiguration readConfiguration ) {
this.readConfiguration = readConfiguration;
}
// Implementation methods
//-------------------------------------------------------------------------
/**
* Adds a new bean create rule for the specified path
*
* @param path the digester path at which this rule should be added
* @param elementDescriptor the <code>ElementDescriptor</code> describes the expected element
* @param beanClass the <code>Class</code> of the bean created by this rule
*/
protected void addBeanCreateRule(
String path,
ElementDescriptor elementDescriptor,
Class beanClass ) {
if (log.isTraceEnabled()) {
log.trace("Adding BeanRuleSet for " + beanClass);
}
RuleSet ruleSet = new BeanRuleSet(
introspector,
path ,
elementDescriptor,
beanClass,
makeContext());
addRuleSet( ruleSet );
}
/**
* Factory method for new contexts.
* Ensure that they are correctly configured.
* @return the ReadContext created, not null
*/
private ReadContext makeContext() {
return new ReadContext( log, bindingConfiguration, readConfiguration );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -