/* Copyright 2007 Niclas Hedhman.
* Copyright 2007 Alin Dreghiciu.
*
* 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.ops4j.pax.web.service.internal;
import java.io.File;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.http.HttpService;
import org.osgi.util.tracker.ServiceTracker;
import org.ops4j.pax.swissbox.property.BundleContextPropertyResolver;
import org.ops4j.pax.web.service.WebContainer;
import static org.ops4j.pax.web.service.WebContainerConstants.*;
import org.ops4j.pax.web.service.spi.Configuration;
import org.ops4j.pax.web.service.spi.ServerController;
import org.ops4j.pax.web.service.spi.ServerControllerFactory;
import org.ops4j.pax.web.service.spi.model.ServerModel;
import org.ops4j.util.property.DictionaryPropertyResolver;
import org.ops4j.util.property.PropertyResolver;
public class Activator
implements BundleActivator
{
private static final Log LOG = LogFactory.getLog( Activator.class );
private final Lock m_lock;
private ServerController m_serverController;
private ServerModel m_serverModel;
private ServiceRegistration m_httpServiceFactoryReg;
private Dictionary m_httpServiceFactoryProps;
public Activator()
{
m_lock = new ReentrantLock();
}
public void start( final BundleContext bundleContext )
throws Exception
{
LOG.debug( "Starting Pax Web" );
m_serverModel = new ServerModel();
new Thread(
new Runnable()
{
public void run()
{
createServerController( bundleContext );
createManagedService( bundleContext );
createHttpServiceFactory( bundleContext );
}
}
).start();
LOG.info( "Pax Web started" );
}
public void stop( final BundleContext bundleContext )
throws Exception
{
LOG.debug( "Stopping Pax Web" );
if( m_serverController != null )
{
m_serverController.stop();
m_serverController = null;
}
m_serverModel = null;
LOG.info( "Pax Web stopped" );
}
private void createHttpServiceFactory( final BundleContext bundleContext )
{
m_httpServiceFactoryReg = bundleContext.registerService(
new String[]{ HttpService.class.getName(), WebContainer.class.getName() },
new HttpServiceFactoryImpl()
{
HttpService createService( final Bundle bundle )
{
return new HttpServiceProxy(
new HttpServiceStarted( bundle, m_serverController, m_serverModel )
);
}
},
m_httpServiceFactoryProps
);
}
private void createServerController( final BundleContext bundleContext )
{
// TODO Must implement server controller factory dynamics
try
{
final ServiceTracker st =
new ServiceTracker( bundleContext, ServerControllerFactory.class.getName(), null );
st.open();
final ServerControllerFactory factory = (ServerControllerFactory) st.waitForService( 0 );
m_serverController = factory.createServerController( m_serverModel );
}
catch( InterruptedException e )
{
throw new RuntimeException( e );
}
}
/**
* Registers a managed service to listen on configuration updates.
*
* @param bundleContext bundle context to use for registration
*/
private void createManagedService( final BundleContext bundleContext )
{
final ManagedService managedService = new ManagedService()
{
/**
* Sets the resolver on sever controller.
*
* @see org.osgi.service.cm.ManagedService#updated(java.util.Dictionary)
*/
public void updated( final Dictionary config )
throws ConfigurationException
{
try
{
m_lock.lock();
final PropertyResolver resolver;
if( config == null )
{
resolver =
new BundleContextPropertyResolver(
bundleContext,
new DefaultPropertyResolver()
);
}
else
{
resolver =
new DictionaryPropertyResolver(
config,
new BundleContextPropertyResolver(
bundleContext,
new DefaultPropertyResolver()
)
);
}
final ConfigurationImpl configuration = new ConfigurationImpl( resolver );
m_serverController.configure( configuration );
determineServiceProperties(
config, configuration, m_serverController.getHttpPort(), m_serverController.getHttpSecurePort()
);
if( m_httpServiceFactoryReg != null )
{
m_httpServiceFactoryReg.setProperties( m_httpServiceFactoryProps );
}
}
finally
{
m_lock.unlock();
}
}
};
final Dictionary<String, String> props = new Hashtable<String, String>();
props.put( Constants.SERVICE_PID, PID );
bundleContext.registerService(
ManagedService.class.getName(),
managedService,
props
);
try
{
m_lock.lock();
if( !m_serverController.isConfigured() )
{
try
{
managedService.updated( null );
}
catch( ConfigurationException ignore )
{
// this should never happen
LOG.error( "Internal error. Cannot set initial configuration resolver.", ignore );
}
}
}
finally
{
m_lock.unlock();
}
}
private void determineServiceProperties( final Dictionary managedConfig,
final Configuration config,
final Integer httpPort,
final Integer httpSecurePort )
{
final Hashtable<String, Object> toPropagate = new Hashtable<String, Object>();
// first store all configuration properties as received via managed service
if( managedConfig != null && !managedConfig.isEmpty() )
{
final Enumeration enumeration = managedConfig.keys();
while( enumeration.hasMoreElements() )
{
String key = (String) enumeration.nextElement();
toPropagate.put( key, managedConfig.get( key ) );
}
}
// then add/replace configuration properties
setProperty( toPropagate, PROPERTY_HTTP_ENABLED, config.isHttpEnabled() );
setProperty( toPropagate, PROPERTY_HTTP_PORT, config.getHttpPort() );
setProperty( toPropagate, PROPERTY_HTTP_SECURE_ENABLED, config.isHttpEnabled() );
setProperty( toPropagate, PROPERTY_HTTP_SECURE_PORT, config.getHttpSecurePort() );
setProperty( toPropagate, PROPERTY_HTTP_USE_NIO, config.useNIO() );
setProperty( toPropagate, PROPERTY_SSL_CLIENT_AUTH_NEEDED, config.isClientAuthNeeded() );
setProperty( toPropagate, PROPERTY_SSL_CLIENT_AUTH_WANTED, config.isClientAuthWanted() );
setProperty( toPropagate, PROPERTY_SSL_KEYSTORE, config.getSslKeystore() );
setProperty( toPropagate, PROPERTY_SSL_KEYSTORE_TYPE, config.getSslKeystoreType() );
//store( toPropagate, PROPERTY_SSL_PASSWORD, config.getSslPassword());
setProperty( toPropagate, PROPERTY_SSL_PASSWORD, null );
//store( toPropagate, PROPERTY_SSL_KEYPASSWORD, config.getSslKeyPassword());
setProperty( toPropagate, PROPERTY_SSL_KEYPASSWORD, null );
setProperty( toPropagate, PROPERTY_TEMP_DIR, config.getTemporaryDirectory() );
setProperty( toPropagate, PROPERTY_SESSION_TIMEOUT, config.getSessionTimeout() );
setProperty( toPropagate, PROPERTY_SESSION_URL, config.getSessionUrl() );
setProperty( toPropagate, PROPERTY_SESSION_COOKIE, config.getSessionCookie() );
setProperty( toPropagate, PROPERTY_WORKER_NAME, config.getWorkerName() );
setProperty( toPropagate, PROPERTY_LISTENING_ADDRESSES, config.getListeningAddresses() );
// then replace ports
setProperty( toPropagate, PROPERTY_HTTP_PORT, httpPort );
setProperty( toPropagate, PROPERTY_HTTP_SECURE_PORT, httpSecurePort );
m_httpServiceFactoryProps = toPropagate;
}
private void setProperty( final Hashtable<String, Object> properties,
final String name,
final Object value )
{
if( value != null )
{
if( value instanceof File )
{
properties.put( name, ( (File) value ).getAbsolutePath() );
}
else if( value instanceof Object[] )
{
properties.put( name, join( ",", (Object[]) value ) );
}
else
{
properties.put( name, value.toString() );
}
}
else
{
properties.remove( name );
}
}
private static String join( String token, Object[] array )
{
if( array == null )
{
return null;
}
if( array.length == 0 )
{
return "";
}
StringBuffer sb = new StringBuffer();
for( int x = 0; x < ( array.length - 1 ); x++ )
{
if( array[ x ] != null )
{
sb.append( array[ x ].toString() );
}
else
{
sb.append( "null" );
}
sb.append( token );
}
sb.append( array[ array.length - 1 ] );
return ( sb.toString() );
}
}