/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.avalon.framework.configuration;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
A DefaultConfigurationBuilder builds Configuration
s from XML,
via a SAX2 compliant parser.
XML namespace support is optional, and disabled by default to preserve backwards-compatibility. To enable it, pass the DefaultConfigurationBuilder(boolean)
constructor the flag true
, or pass
a namespace-enabled XMLReader
to the DefaultConfigurationBuilder(XMLReader)
constructor.
The mapping from XML namespaces to Configuration
namespaces is pretty straightforward, with one caveat: attribute namespaces are (deliberately) not supported. Enabling namespace processing has the following effects:
- Attributes starting with
xmlns:
are interpreted as
declaring a prefix:namespaceURI mapping, and won't result in the creation of
xmlns
-prefixed attributes in the Configuration
.
-
Prefixed XML elements, like <doc:title xmlns:doc="http://foo.com">,
will result in a
Configuration
with getName()
.equals("title")
and getNamespace()
.equals("http://foo.com")
.
Whitespace handling. Since mixed content is not allowed in the
configurations, whitespace is completely discarded in non-leaf nodes.
For the leaf nodes the default behavior is to trim the space
surrounding the value. This can be changed by specifying
xml:space
attribute with value of preserve
in that case the whitespace is left intact.
Author: Avalon Development Team Version: $Id: DefaultConfigurationBuilder.java 506231 2007-02-12 02:36:54Z crossley $
/**
* A DefaultConfigurationBuilder builds <code>Configuration</code>s from XML,
* via a SAX2 compliant parser.
*
* <p>
* XML namespace support is optional, and disabled by default to preserve
* backwards-compatibility. To enable it, pass the {@link
* #DefaultConfigurationBuilder(boolean)} constructor the flag <code>true</code>, or pass
* a namespace-enabled <code>XMLReader</code> to the {@link
* #DefaultConfigurationBuilder(XMLReader)} constructor.
* </p>
* <p>
* The mapping from XML namespaces to {@link Configuration} namespaces is pretty
* straightforward, with one caveat: attribute namespaces are (deliberately) not
* supported. Enabling namespace processing has the following effects:</p>
* <ul>
* <li>Attributes starting with <code>xmlns:</code> are interpreted as
* declaring a prefix:namespaceURI mapping, and won't result in the creation of
* <code>xmlns</code>-prefixed attributes in the <code>Configuration</code>.
* </li>
* <li>
* Prefixed XML elements, like <tt><doc:title xmlns:doc="http://foo.com">,</tt>
* will result in a <code>Configuration</code> with <code>{@link
* Configuration#getName getName()}.equals("title")</code> and <code>{@link
* Configuration#getNamespace getNamespace()}.equals("http://foo.com")</code>.
* </li>
* </ul>
* <p>
* Whitespace handling. Since mixed content is not allowed in the
* configurations, whitespace is completely discarded in non-leaf nodes.
* For the leaf nodes the default behavior is to trim the space
* surrounding the value. This can be changed by specifying
* <code>xml:space</code> attribute with value of <code>preserve</code>
* in that case the whitespace is left intact.
* </p>
*
* @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
* @version $Id: DefaultConfigurationBuilder.java 506231 2007-02-12 02:36:54Z crossley $
*/
public class DefaultConfigurationBuilder
{
private SAXConfigurationHandler m_handler;
private XMLReader m_parser;
Create a Configuration Builder with a default XMLReader that ignores
namespaces. In order to enable namespaces, use either the constructor
that has a boolean or that allows you to pass in your own
namespace-enabled XMLReader.
/**
* Create a Configuration Builder with a default XMLReader that ignores
* namespaces. In order to enable namespaces, use either the constructor
* that has a boolean or that allows you to pass in your own
* namespace-enabled XMLReader.
*/
public DefaultConfigurationBuilder()
{
this( false );
}
Create a Configuration Builder, specifying a flag that determines
namespace support.
Params: - enableNamespaces – If
true
, a namespace-aware
SAXParser
is used. If false
, the default JAXP
SAXParser
(without namespace support) is used.
Since: 4.1
/**
* Create a Configuration Builder, specifying a flag that determines
* namespace support.
*
* @param enableNamespaces If <code>true</code>, a namespace-aware
* <code>SAXParser</code> is used. If <code>false</code>, the default JAXP
* <code>SAXParser</code> (without namespace support) is used.
* @since 4.1
*/
public DefaultConfigurationBuilder( final boolean enableNamespaces )
{
//yaya the bugs with some compilers and final variables ..
try
{
final SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
if( enableNamespaces )
{
saxParserFactory.setNamespaceAware( true );
}
final SAXParser saxParser = saxParserFactory.newSAXParser();
setParser( saxParser.getXMLReader() );
}
catch( final Exception se )
{
throw new Error( "Unable to setup SAX parser" + se );
}
}
Create a Configuration Builder with your own XMLReader.
Params: - parser – an
XMLReader
/**
* Create a Configuration Builder with your own XMLReader.
* @param parser an <code>XMLReader</code>
*/
public DefaultConfigurationBuilder( XMLReader parser )
{
setParser( parser );
}
Internally sets up the XMLReader
/**
* Internally sets up the XMLReader
*/
private void setParser( XMLReader parser )
{
m_parser = parser;
m_handler = getHandler();
m_parser.setContentHandler( m_handler );
m_parser.setErrorHandler( m_handler );
}
Get a SAXConfigurationHandler for your configuration reading.
Returns: a SAXConfigurationHandler
/**
* Get a SAXConfigurationHandler for your configuration reading.
* @return a <code>SAXConfigurationHandler</code>
*/
protected SAXConfigurationHandler getHandler()
{
try
{
if( m_parser.getFeature( "http://xml.org/sax/features/namespaces" ) )
{
return new NamespacedSAXConfigurationHandler();
}
}
catch( Exception e )
{
// ignore error and fall through to the non-namespaced version
}
return new SAXConfigurationHandler();
}
Build a configuration object from a file using a filename.
Params: - filename – name of the file
Throws: - SAXException – if a parsing error occurs
- IOException – if an I/O error occurs
- ConfigurationException – if an error occurs
Returns: a Configuration
object
/**
* Build a configuration object from a file using a filename.
* @param filename name of the file
* @return a <code>Configuration</code> object
* @throws SAXException if a parsing error occurs
* @throws IOException if an I/O error occurs
* @throws ConfigurationException if an error occurs
*/
public Configuration buildFromFile( final String filename )
throws SAXException, IOException, ConfigurationException
{
return buildFromFile( new File( filename ) );
}
Build a configuration object from a file using a File object.
Params: - file – a
File
object
Throws: - SAXException – if a parsing error occurs
- IOException – if an I/O error occurs
- ConfigurationException – if an error occurs
Returns: a Configuration
object
/**
* Build a configuration object from a file using a File object.
* @param file a <code>File</code> object
* @return a <code>Configuration</code> object
* @throws SAXException if a parsing error occurs
* @throws IOException if an I/O error occurs
* @throws ConfigurationException if an error occurs
*/
public Configuration buildFromFile( final File file )
throws SAXException, IOException, ConfigurationException
{
synchronized( this )
{
m_handler.clear();
m_parser.parse( file.toURL().toString() );
return m_handler.getConfiguration();
}
}
Build a configuration object using an InputStream.
Params: - inputStream – an
InputStream
value
Throws: - SAXException – if a parsing error occurs
- IOException – if an I/O error occurs
- ConfigurationException – if an error occurs
Returns: a Configuration
object
/**
* Build a configuration object using an InputStream.
* @param inputStream an <code>InputStream</code> value
* @return a <code>Configuration</code> object
* @throws SAXException if a parsing error occurs
* @throws IOException if an I/O error occurs
* @throws ConfigurationException if an error occurs
*/
public Configuration build( final InputStream inputStream )
throws SAXException, IOException, ConfigurationException
{
return build( new InputSource( inputStream ) );
}
Build a configuration object using an InputStream;
supplying a systemId to make messages about all
kinds of errors more meaningfull.
Params: - inputStream – an
InputStream
value - systemId – the systemId to set on the intermediate sax
inputSource
Throws: - SAXException – if a parsing error occurs
- IOException – if an I/O error occurs
- ConfigurationException – if an error occurs
Returns: a Configuration
object
/**
* Build a configuration object using an InputStream;
* supplying a systemId to make messages about all
* kinds of errors more meaningfull.
* @param inputStream an <code>InputStream</code> value
* @param systemId the systemId to set on the intermediate sax
* inputSource
* @return a <code>Configuration</code> object
* @throws SAXException if a parsing error occurs
* @throws IOException if an I/O error occurs
* @throws ConfigurationException if an error occurs
*/
public Configuration build( final InputStream inputStream,
final String systemId )
throws SAXException, IOException, ConfigurationException
{
final InputSource inputSource = new InputSource( inputStream );
inputSource.setSystemId( systemId );
return build( inputSource );
}
Build a configuration object using an URI
Params: - uri – a
String
value
Throws: - SAXException – if a parsing error occurs
- IOException – if an I/O error occurs
- ConfigurationException – if an error occurs
Returns: a Configuration
object
/**
* Build a configuration object using an URI
* @param uri a <code>String</code> value
* @return a <code>Configuration</code> object
* @throws SAXException if a parsing error occurs
* @throws IOException if an I/O error occurs
* @throws ConfigurationException if an error occurs
*/
public Configuration build( final String uri )
throws SAXException, IOException, ConfigurationException
{
return build( new InputSource( uri ) );
}
Build a configuration object using an XML InputSource object
Params: - input – an
InputSource
value
Throws: - SAXException – if a parsing error occurs
- IOException – if an I/O error occurs
- ConfigurationException – if an error occurs
Returns: a Configuration
object
/**
* Build a configuration object using an XML InputSource object
* @param input an <code>InputSource</code> value
* @return a <code>Configuration</code> object
* @throws SAXException if a parsing error occurs
* @throws IOException if an I/O error occurs
* @throws ConfigurationException if an error occurs
*/
public Configuration build( final InputSource input )
throws SAXException, IOException, ConfigurationException
{
synchronized( this )
{
m_handler.clear();
m_parser.parse( input );
return m_handler.getConfiguration();
}
}
Sets the EntityResolver
to
be used by parser. Useful when dealing with xml
files that reference external entities.
Params: - resolver – implementation of
EntityResolver
/**
* Sets the <code>EntityResolver</code> to
* be used by parser. Useful when dealing with xml
* files that reference external entities.
*
* @param resolver implementation of <code>EntityResolver</code>
*/
public void setEntityResolver( final EntityResolver resolver )
{
synchronized( this )
{
m_parser.setEntityResolver( resolver );
}
}
}