/*
* XML 2 Java Binding (X2JB) - the excellent Java tool.
* Copyright 2009, by Richard Opalka.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not see the FSF site:
* http://www.fsf.org/ and search for the LGPL License document there.
*/
package com.x2jb.bind.provider;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Properties;
import org.x2jb.bind.BindingException;
import org.x2jb.bind.spi.provider.BindingDefinition;
import org.x2jb.bind.spi.provider.BindingFactory;
/**
* Binding factory extension for Java resource bundles.
*
* @author <a href="mailto:richard_opalka@yahoo.com">Richard Opalka</a>
*/
public final class PropertiesBindingFactoryImpl implements BindingFactory
{
/** '.' character. */
private static final char DOT = '.';
/** '/' character. */
private static final char SEPARATOR = '/';
/** ".binding" properties key suffix. */
private static final String BINDING_SUFFIX = ".binding";
/** ".nodeNamespace" properties key suffix. */
private static final String NAMESPACE_SUFFIX = ".nodeNamespace";
/** ".nodeName" properties key suffix. */
private static final String NAME_SUFFIX = ".nodeName";
/** ".isElementNode" properties key suffix. */
private static final String IS_ELEMENT_SUFFIX = ".isElementNode";
/** ".isNodeUnique" properties key suffix. */
private static final String IS_UNIQUE_SUFFIX = ".isNodeUnique";
/** ".isNodeMandatory" properties key suffix. */
private static final String IS_MANDATORY_SUFFIX = ".isNodeMandatory";
/** ".typeHandler" properties key suffix. */
private static final String TYPE_HANDLER_SUFFIX = ".typeHandler";
/** ".defaultValue" properties key suffix. */
private static final String DEFAULT_VALUE_SUFFIX = ".defaultValue";
/**
* Constructor.
*/
public PropertiesBindingFactoryImpl()
{
super();
}
/**
* Returns binding definition associated with method.
*
* @param method method
* @return binding definition
*/
public BindingDefinition getBinding( final Method method )
{
final Properties bindingProperties = PropertiesBindingFactoryImpl
.getBindingProperties( method.getDeclaringClass() );
return PropertiesBindingFactoryImpl.getBinding( bindingProperties, method );
}
/**
* Returns binding definition associated with passed method.
*
* @param bindingProperties to read binding metadata from
* @param method to lookup binding definition for
* @return binding definition
*/
private static BindingDefinition getBinding( final Properties bindingProperties, final Method method )
{
if ( bindingProperties == null )
{
return null;
}
return PropertiesBindingFactoryImpl.convertToBinding( method.getName(), bindingProperties );
}
/**
* Converts string to boolean.
*
* @param b string boolean representation
* @return boolean value
*/
private static boolean toBoolean( final String b )
{
return ( b == null ) ? true : Boolean.valueOf( b ).booleanValue();
}
/**
* Returns binding definition associated with method name.
*
* @param methodName method name
* @param props properties file to read binding definition from
* @return binding definition
*/
private static BindingDefinition convertToBinding( final String methodName, final Properties props )
{
final String nameString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.NAME_SUFFIX );
final String namespaceString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.NAMESPACE_SUFFIX );
final String isElementString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.IS_ELEMENT_SUFFIX );
final String isUniqueString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.IS_UNIQUE_SUFFIX );
final String isMandatoryString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.IS_MANDATORY_SUFFIX );
final String typeHandlerString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.TYPE_HANDLER_SUFFIX );
final String defaultValueString = props.getProperty(
methodName + PropertiesBindingFactoryImpl.DEFAULT_VALUE_SUFFIX );
if ( nameString == null )
{
return null;
}
final boolean isElement = PropertiesBindingFactoryImpl.toBoolean( isElementString );
final boolean isMandatory = PropertiesBindingFactoryImpl.toBoolean( isMandatoryString );
final boolean isUnique = PropertiesBindingFactoryImpl.toBoolean( isUniqueString );
return new PropertiesBindingImpl
(
namespaceString, nameString, isElement, isMandatory, isUnique, typeHandlerString, defaultValueString
);
}
/**
* Lookups properties based binding definition for passed class.
*
* @param clazz to lookup properties resource for
* @return binding definition properties
*/
private static Properties getBindingProperties( final Class< ? > clazz )
{
final String bindingResourceName = PropertiesBindingFactoryImpl.SEPARATOR +
clazz.getName().replace( PropertiesBindingFactoryImpl.DOT,
PropertiesBindingFactoryImpl.SEPARATOR ) + PropertiesBindingFactoryImpl.BINDING_SUFFIX;
final InputStream bindingResource = AccessController.doPrivileged(
new PrivilegedAction< InputStream >()
{
public InputStream run()
{
return clazz.getResourceAsStream( bindingResourceName );
}
}
);
if ( bindingResource == null )
{
return null;
}
final Properties bindingProperties = new Properties();
try
{
bindingProperties.load( bindingResource );
}
catch ( IOException ioe )
{
throw new BindingException( ioe.getMessage(), ioe );
}
finally
{
try
{
bindingResource.close();
}
catch ( IOException ignore )
{
; // ignore
}
}
return bindingProperties;
}
}