/*=============================================================================*
* Copyright 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.ws.resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.naming.java.javaURLContextFactory;
import org.apache.ws.resource.i18n.Keys;
import org.apache.ws.resource.i18n.MessagesImpl;
import org.apache.ws.util.i18n.Messages;
import org.apache.ws.util.jndi.SpringJndiPopulator;
import org.apache.ws.util.jndi.XmlBeanJndiUtils;
import org.apache.ws.util.spring.ClassEditor;
import org.apache.ws.util.spring.QNameEditor;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Properties;
/**
* A singleton respresenting the WSRF runtime.
*/
public class WsrfRuntime
{
static
{
initJndiProvider( );
}
private static final Log LOG = LogFactory.getLog( WsrfRuntime.class );
private static final Messages MSG = MessagesImpl.getInstance( );
/** DOCUMENT_ME */
public static final String CONFIG_DIALECT_SPRING_BEANS =
"http://www.springframework.org/dtd/spring-beans.dtd";
/** DOCUMENT_ME */
public static final String CONFIG_DIALECT_WSRF_JNDI_CONFIG =
"http://www.apache.org/wsfx/wsrf/jndi/config";
private static final String DEFAULT_JNDI_CONFIG_LOCATION = "wsrf-config.xml";
private static final String DEFAULT_JNDI_CONFIG_DIALECT = CONFIG_DIALECT_SPRING_BEANS;
private static final String VERSION = "1.1";
private static final WsrfRuntime INSTANCE = new WsrfRuntime( );
/** DOCUMENT_ME */
public static final String JNDI_CONFIG_DIALECT = "jndi.config.dialect";
/** DOCUMENT_ME */
public static final String JNDI_CONFIG_LOCATION = "jndi.config.location";
private static final String PLACEHOLDER_IPADDRESS = "$IP_ADDRESS$";
private static final String PLACEHOLDER_HOSTNAME = "$HOST_NAME$";
private ConfigurableListableBeanFactory m_beanFactory;
private URL m_baseWebappUrl;
private WsrfRuntime( )
{
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public static WsrfRuntime getRuntime( )
{
return INSTANCE;
}
/**
* Sets the base webapp url.
* <p/>
* The URL should contin the webapp context name. (i.e. http://127.0.0.1:8080/wsrf)
* <p/>
* The URL may contain one of the following:
* <p/>
* <ol> <li>the marker <IP_ADDRESS> in which case we will attempt to determine the IP address at runtime. i.e.
* http://<IP_ADDRESS>:8080/wsrf (Do not use on multi-homed systems)</li> <li>the marker <HOST_NAME> in which
* case we will attempt to determine the host name at runtime i.e. http://<HOST_NAME>:8080/wsrf </li> <li>NO
* Marker in which case whatever value you add will be static and used. i.e. http://myhostname:8080/wsrf </li>
* </ol>
*
* @param baseWebappUrl The base webapp url containing the webapp context. (i.e. http://127.0.0.1:8080/wsrf)
*/
public void setBaseWebappUrl( URL baseWebappUrl )
{ //todo we may need to figure out a way to stop everything if this method fails.
//the url is nonexistant
if ( ( baseWebappUrl == null ) || baseWebappUrl.equals( "" ) )
{
try
{
try
{
m_baseWebappUrl = getDefaultUrl( );
LOG.fatal( "The baseWebappUrl from the wsrf-config.xml file was invalid! Defaulting to: "
+ m_baseWebappUrl );
}
catch ( MalformedURLException e )
{
LOG.fatal( "Unable to get build baseWebappURL.", e );
}
}
catch ( java.net.UnknownHostException e )
{
try
{
m_baseWebappUrl = new URL( "http://127.0.0.1:8080/wsrf" );
LOG.fatal( "The baseWebappUrl from the wsrf-config.xml file was invalid! Unable to determine host IP address using java.net.InetAddress.getLocalHost().getHostAddress() defaulting to: "
+ m_baseWebappUrl, e );
}
catch ( MalformedURLException e1 )
{
LOG.fatal( "Unable to get build baseWebappURL.", e );
}
return;
}
}
//the url is not to be modified
else if ( ( baseWebappUrl.getHost( ).indexOf( PLACEHOLDER_IPADDRESS ) == -1 )
&& ( baseWebappUrl.getHost( ).indexOf( PLACEHOLDER_HOSTNAME ) == -1 ) )
{
m_baseWebappUrl = baseWebappUrl;
return;
}
//url will need to be built
//define localhost to be used
java.net.InetAddress localHost = null;
try
{
localHost = java.net.InetAddress.getLocalHost( );
}
catch ( java.net.UnknownHostException e )
{
LOG.fatal( "Unable to get the InetAddress for localhost using InetAddress.getLocalHost(). Defaults will be used. This may cause problems with EndpointReferences in Resources." );
}
String sBaseUrl = baseWebappUrl.toString( );
if ( sBaseUrl.indexOf( PLACEHOLDER_IPADDRESS ) > -1 )
{
String ipAddress = null;
if ( localHost == null )
{
ipAddress = "127.0.0.1";
}
else
{
ipAddress = localHost.getHostAddress( );
}
try
{
m_baseWebappUrl =
new URL( sBaseUrl.substring( 0,
sBaseUrl.indexOf( PLACEHOLDER_IPADDRESS ) ) + ipAddress
+ sBaseUrl.substring( sBaseUrl.indexOf( PLACEHOLDER_IPADDRESS )
+ PLACEHOLDER_IPADDRESS.length( ) ) );
}
catch ( MalformedURLException e )
{
LOG.fatal( "Unable to get build baseWebappURL.", e );
}
return;
} //end if
else if ( sBaseUrl.indexOf( PLACEHOLDER_HOSTNAME ) > -1 )
{
String hostname = null;
if ( localHost == null )
{
hostname = "127.0.0.1";
}
else
{
hostname = localHost.getHostName( );
}
try
{
m_baseWebappUrl =
new URL( sBaseUrl.substring( 0,
sBaseUrl.indexOf( PLACEHOLDER_HOSTNAME ) ) + hostname
+ sBaseUrl.substring( sBaseUrl.indexOf( PLACEHOLDER_HOSTNAME )
+ PLACEHOLDER_HOSTNAME.length( ) ) );
}
catch ( MalformedURLException e )
{
LOG.fatal( "Unable to get build baseWebappURL.", e );
}
return;
} //end else if
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public URL getBaseWebappUrl( )
{
return m_baseWebappUrl;
}
/**
* If this runtime was configured via Spring, returns the Spring bean factory,
* otherwise returns null.
*
* @return the Spring bean factory, or null if this runtime was not configured via Spring
*/
public ListableBeanFactory getBeanFactory( )
{
return m_beanFactory;
}
/**
* Returns the <code>ResourceHome</code> for the JSR-109 portComponent with the specified name.
*
* @param portComponentName a JSR-109 portComponent name
*
* @return the <code>ResourceHome</code> for the JSR-109 portComponent with the specified name
*
* @throws ResourceException if no home is configured for the specified portComponent name
*/
public ResourceHome getResourceHome( String portComponentName )
throws ResourceException
{
ResourceHome home;
try
{
home = (ResourceHome) new InitialContext( ).lookup( getResourceHomeJndiName( portComponentName ) );
}
catch ( NameNotFoundException nnfe )
{
throw new ResourceException( "There is no resource home configured for a portComponent named "
+ portComponentName + "." );
}
catch ( NamingException ne )
{
throw new RuntimeException( "Unable to lookup resource home from JNDI using name " + portComponentName
+ ".", ne );
}
return home;
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
*/
public String getVersion( )
{
return VERSION;
}
/**
* Initializes the WSRF runtime - should only be called once.
*
* @param props properties that tell the runtime how to initialize itself; must not be null
*/
public synchronized void init( Properties props )
{
String jndiConfigDialect = props.getProperty( JNDI_CONFIG_DIALECT, DEFAULT_JNDI_CONFIG_DIALECT );
String jndiConfigLocation = props.getProperty( JNDI_CONFIG_LOCATION, DEFAULT_JNDI_CONFIG_LOCATION );
LOG.info( MSG.getMessage( Keys.POPULATING_JNDI, jndiConfigLocation ) );
try
{
if ( jndiConfigDialect.equals( CONFIG_DIALECT_WSRF_JNDI_CONFIG ) )
{
InputStream jndiConfigStream =
Thread.currentThread( ).getContextClassLoader( ).getResourceAsStream( jndiConfigLocation );
XmlBeanJndiUtils.initFromInputStream( jndiConfigStream );
}
else if ( jndiConfigDialect.equals( CONFIG_DIALECT_SPRING_BEANS ) )
{
m_beanFactory = createBeanFactory( jndiConfigLocation );
preinstantiateNonResourceSingletons( );
SpringJndiPopulator.populateJndi( m_beanFactory );
}
else
{
throw new RuntimeException( "Fatal error! An unsupported JNDI configuration dialect was specified via the 'jndi.config.dialect' initialization property." );
}
}
catch ( Exception e )
{
LOG.fatal( "Fatal error! Failed to initialize WSRF runtime." );
e.printStackTrace( );
throw new RuntimeException( "Fatal error! Failed to initialize WSRF runtime.", e );
}
}
/**
* DOCUMENT_ME
*
* @return DOCUMENT_ME
* @throws UnknownHostException
*
*/
protected URL getDefaultUrl( )
throws MalformedURLException,
UnknownHostException
{
return new URL( "http://" + java.net.InetAddress.getLocalHost( ).getHostAddress( ) + ":8080/wsrf" );
}
private static void initJndiProvider( )
{
System.setProperty( Context.INITIAL_CONTEXT_FACTORY,
javaURLContextFactory.class.getName( ) );
System.setProperty( Context.URL_PKG_PREFIXES, "org.apache.commons.naming" );
}
private String getResourceHomeJndiName( String portComponentName )
{
String homeJndiName;
if ( m_beanFactory != null ) // new way
{
homeJndiName = JndiConstants.CONTEXT_NAME_RESOURCE + "/" + portComponentName;
}
else // old way
{
homeJndiName =
JndiConstants.CONTEXT_NAME_SERVICES + "/" + portComponentName + "/" + JndiConstants.ATOMIC_NAME_HOME;
}
return homeJndiName;
}
private ConfigurableListableBeanFactory createBeanFactory( String jndiConfigLocation )
{
ConfigurableListableBeanFactory beanFactory =
new XmlBeanFactory( new ClassPathResource( jndiConfigLocation ) );
beanFactory.registerCustomEditor( Class.class,
new ClassEditor( ) );
beanFactory.registerCustomEditor( QName.class,
new QNameEditor( ) );
return beanFactory;
}
private void preinstantiateNonResourceSingletons( )
{
String[] beanDefNames = m_beanFactory.getBeanDefinitionNames( );
for ( int i = 0; i < beanDefNames.length; i++ )
{
String beanDefName = beanDefNames[i];
AbstractBeanDefinition beanDef = (AbstractBeanDefinition) m_beanFactory.getBeanDefinition( beanDefName );
if ( beanDef.isSingleton( ) && !Resource.class.isAssignableFrom( beanDef.getClass( ) ) )
{
LOG.debug( "Instantiating singleton bean with id " + beanDefName + " ..." );
m_beanFactory.getBean( beanDefName );
}
}
}
}