All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.felix.eventadmin.impl.Configuration Maven / Gradle / Ivy

/*
 * 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.felix.eventadmin.impl;


import java.util.Dictionary;
import java.util.Hashtable;
import java.util.StringTokenizer;

import org.apache.felix.eventadmin.impl.adapter.AbstractAdapter;
import org.apache.felix.eventadmin.impl.adapter.BundleEventAdapter;
import org.apache.felix.eventadmin.impl.adapter.FrameworkEventAdapter;
import org.apache.felix.eventadmin.impl.adapter.LogEventAdapter;
import org.apache.felix.eventadmin.impl.adapter.ServiceEventAdapter;
import org.apache.felix.eventadmin.impl.handler.EventAdminImpl;
import org.apache.felix.eventadmin.impl.security.SecureEventAdminFactory;
import org.apache.felix.eventadmin.impl.tasks.DefaultThreadPool;
import org.apache.felix.eventadmin.impl.util.LogWrapper;
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.event.EventAdmin;
import org.osgi.service.metatype.MetaTypeProvider;


/**
 * The Configuration class encapsules the
 * configuration for the event admin.
 *
 * The service knows about the following properties which are read at bundle startup:
 * 

*

* org.apache.felix.eventadmin.ThreadPoolSize - The size of the thread * pool. *

* The default value is 10. Increase in case of a large amount of synchronous events * where the EventHandler services in turn send new synchronous events in * the event dispatching thread or a lot of timeouts are to be expected. A value of * less then 2 triggers the default value. A value of 2 effectively disables thread * pooling. *

*

*

* org.apache.felix.eventadmin.Timeout - The black-listing timeout in * milliseconds *

* The default value is 5000. Increase or decrease at own discretion. A value of less * then 100 turns timeouts off. Any other value is the time in milliseconds granted * to each EventHandler before it gets blacklisted. *

*

*

* org.apache.felix.eventadmin.RequireTopic - Are EventHandler * required to be registered with a topic? *

* The default is true. The specification says that EventHandler * must register with a list of topics they are interested in. Setting this value to * false will enable that handlers without a topic are receiving all events * (i.e., they are treated the same as with a topic=*). *

*

*

* org.apache.felix.eventadmin.IgnoreTimeout - Configure * EventHandlers to be called without a timeout. *

*

* If a timeout is configured by default all event handlers are called using the timeout. * For performance optimization it is possible to configure event handlers where the * timeout handling is not used - this reduces the thread usage from the thread pools * as the timout handling requires an additional thread to call the event handler. * However, the application should work without this configuration property. It is a * pure optimization! *

*

* The value is a list of strings (separated by comma). If the string ends with a dot, * all handlers in exactly this package are ignored. If the string ends with a star, * all handlers in this package and all subpackages are ignored. If the string neither * ends with a dot nor with a start, this is assumed to define an exact class name. *

*

*

* org.apache.felix.eventadmin.IgnoreTopic - Configure * topics to be ignore and not delivered to registered handlers. *

*

* For performance optimization it is possible to configure topics which are ignored * by the event admin implementation. In this case, a event is not delivered to * registered event handlers. *

*

* The value is a list of strings (separated by comma). If a single value ends with a dot, * all topics in exactly this package are ignored. If a single value ends with a star, * all topics in this package and all sub packages are ignored. If a single value neither * ends with a dot nor with a start, this is assumed to define an exact topic. A single * star can be used to disable delivery completely. *

*

*

* These properties are read at startup and serve as a default configuration. * If a configuration admin is configured, the event admin can be configured * through the config admin. *

* * @author Felix Project Team */ public class Configuration { /** The PID for the event admin. */ static final String PID = "org.apache.felix.eventadmin.impl.EventAdmin"; static final String PROP_THREAD_POOL_SIZE = "org.apache.felix.eventadmin.ThreadPoolSize"; static final String PROP_TIMEOUT = "org.apache.felix.eventadmin.Timeout"; static final String PROP_REQUIRE_TOPIC = "org.apache.felix.eventadmin.RequireTopic"; static final String PROP_IGNORE_TIMEOUT = "org.apache.felix.eventadmin.IgnoreTimeout"; static final String PROP_IGNORE_TOPIC = "org.apache.felix.eventadmin.IgnoreTopic"; static final String PROP_LOG_LEVEL = "org.apache.felix.eventadmin.LogLevel"; /** The bundle context. */ private final BundleContext m_bundleContext; private int m_threadPoolSize; private int m_timeout; private boolean m_requireTopic; private String[] m_ignoreTimeout; private String[] m_ignoreTopics; private int m_logLevel; // The thread pool used - this is a member because we need to close it on stop private volatile DefaultThreadPool m_sync_pool; private volatile DefaultThreadPool m_async_pool; // The actual implementation of the service - this is a member because we need to // close it on stop. Note, security is not part of this implementation but is // added via a decorator in the start method (this is the wrapped object without // the wrapper). private volatile EventAdminImpl m_admin; // The registration of the security decorator factory (i.e., the service) private volatile ServiceRegistration m_registration; // all adapters private AbstractAdapter[] m_adapters; private ServiceRegistration m_managedServiceReg; public Configuration( BundleContext bundleContext ) { m_bundleContext = bundleContext; // default configuration configure( null ); startOrUpdate(); // check for Configuration Admin configuration try { Object service = tryToCreateManagedService(); if ( service != null ) { // add meta type provider if interfaces are available Object enhancedService = tryToCreateMetaTypeProvider(service); final String[] interfaceNames; if ( enhancedService == null ) { interfaceNames = new String[] {ManagedService.class.getName()}; } else { interfaceNames = new String[] {ManagedService.class.getName(), MetaTypeProvider.class.getName()}; service = enhancedService; } Dictionary props = new Hashtable(); props.put( Constants.SERVICE_PID, PID ); m_managedServiceReg = m_bundleContext.registerService( interfaceNames, service, props ); } } catch ( Throwable t ) { // don't care } } void updateFromConfigAdmin(final Dictionary config) { // do this in the background as we don't want to stop // the config admin new Thread() { @Override public void run() { synchronized ( Configuration.this ) { Configuration.this.configure( config ); Configuration.this.startOrUpdate(); } } }.start(); } /** * Configures this instance. */ void configure( Dictionary config ) { if ( config == null ) { // The size of the internal thread pool. Note that we must execute // each synchronous event dispatch that happens in the synchronous event // dispatching thread in a new thread, hence a small thread pool is o.k. // A value of less then 2 triggers the default value. A value of 2 // effectively disables thread pooling. Furthermore, this will be used by // a lazy thread pool (i.e., new threads are created when needed). Ones the // the size is reached and no cached thread is available new threads will // be created. m_threadPoolSize = getIntProperty( PROP_THREAD_POOL_SIZE, m_bundleContext.getProperty(PROP_THREAD_POOL_SIZE), 20, 2); // The timeout in milliseconds - A value of less then 100 turns timeouts off. // Any other value is the time in milliseconds granted to each EventHandler // before it gets blacklisted. m_timeout = getIntProperty(PROP_TIMEOUT, m_bundleContext.getProperty(PROP_TIMEOUT), 5000, Integer.MIN_VALUE); // Are EventHandler required to be registered with a topic? - The default is // true. The specification says that EventHandler must register with a list // of topics they are interested in. Setting this value to false will enable // that handlers without a topic are receiving all events // (i.e., they are treated the same as with a topic=*). m_requireTopic = getBooleanProperty( m_bundleContext.getProperty(PROP_REQUIRE_TOPIC), true); final String value = m_bundleContext.getProperty(PROP_IGNORE_TIMEOUT); if ( value == null ) { m_ignoreTimeout = null; } else { final StringTokenizer st = new StringTokenizer(value, ","); m_ignoreTimeout = new String[st.countTokens()]; for(int i=0; i 5 ? m_threadPoolSize / 2 : 2; if ( m_async_pool == null ) { m_async_pool = new DefaultThreadPool(asyncThreadPoolSize, false); } else { m_async_pool.configure(asyncThreadPoolSize); } if ( m_admin == null ) { m_admin = new EventAdminImpl(m_bundleContext, m_sync_pool, m_async_pool, m_timeout, m_ignoreTimeout, m_requireTopic, m_ignoreTopics); // Finally, adapt the outside events to our kind of events as per spec adaptEvents(m_admin); // register the admin wrapped in a service factory (SecureEventAdminFactory) // that hands-out the m_admin object wrapped in a decorator that checks // appropriated permissions of each calling bundle m_registration = m_bundleContext.registerService(EventAdmin.class.getName(), new SecureEventAdminFactory(m_admin), null); } else { m_admin.update(m_timeout, m_ignoreTimeout, m_requireTopic, m_ignoreTopics); } } /** * Called upon stopping the bundle. This will block until all pending events are * delivered. An IllegalStateException will be thrown on new events starting with * the begin of this method. However, it might take some time until we settle * down which is somewhat cumbersome given that the spec asks for return in * a timely manner. */ public void destroy() { synchronized ( this ) { if ( m_adapters != null ) { for(int i=0;i properties ) throws ConfigurationException { updateFromConfigAdmin(properties); } }; } catch (Throwable t) { // we simply ignore this } return null; } /** * Returns either the parsed int from the value of the property if it is set and * not less then the min value or the default. Additionally, a warning is * generated in case the value is erroneous (i.e., can not be parsed as an int or * is less then the min value). */ private int getIntProperty(final String key, final Object value, final int defaultValue, final int min) { if(null != value) { final int result; if ( value instanceof Integer ) { result = ((Integer)value).intValue(); } else { try { result = Integer.parseInt(value.toString()); } catch (NumberFormatException e) { LogWrapper.getLogger().log(LogWrapper.LOG_WARNING, "Unable to parse property: " + key + " - Using default", e); return defaultValue; } } if(result >= min) { return result; } LogWrapper.getLogger().log(LogWrapper.LOG_WARNING, "Value for property: " + key + " is to low - Using default"); } return defaultValue; } /** * Returns true if the value of the property is set and is either 1, true, or yes * Returns false if the value of the property is set and is either 0, false, or no * Returns the defaultValue otherwise */ private boolean getBooleanProperty(final Object obj, final boolean defaultValue) { if(null != obj) { if ( obj instanceof Boolean ) { return ((Boolean)obj).booleanValue(); } String value = obj.toString().trim().toLowerCase(); if(0 < value.length() && ("0".equals(value) || "false".equals(value) || "no".equals(value))) { return false; } if(0 < value.length() && ("1".equals(value) || "true".equals(value) || "yes".equals(value))) { return true; } } return defaultValue; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy