| /* |
| * 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.scr.impl.config; |
| |
| |
| import java.util.Dictionary; |
| import java.util.Hashtable; |
| |
| import org.apache.felix.scr.impl.Activator; |
| import org.apache.felix.scr.impl.ComponentCommands; |
| import org.apache.felix.scr.impl.manager.ScrConfiguration; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.Constants; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.service.log.LogService; |
| import org.osgi.service.metatype.MetaTypeProvider; |
| |
| |
| /** |
| * The <code>ScrConfiguration</code> class conveys configuration for the |
| * Felix DS implementation bundle. |
| * <p> |
| * <b>Configuration Source</b> |
| * <p> |
| * <ol> |
| * <li>Framework properties: These are read when the Declarative Services |
| * implementation is first started.</li> |
| * <li>Configuration Admin Service: Properties are provided by means of a |
| * <code>ManagedService</code> with Service PID |
| * <code>org.apache.felix.scr.ScrService</code>. This class uses an OSGi |
| * Service Factory ({@link ScrManagedServiceServiceFactory}) to register the |
| * managed service without requiring the Configuration Admin Service API to be |
| * required upfront. |
| * </li> |
| * </ol> |
| * <p> |
| * See the <i>Configuration</i> section of the |
| * <a href="http://felix.apache.org/site/apache-felix-service-component-runtime.html">Apache Felix Service Component Runtime</a> |
| * documentation page for detailed information. |
| */ |
| public class ScrConfigurationImpl implements ScrConfiguration |
| { |
| |
| private static final String VALUE_TRUE = Boolean.TRUE.toString(); |
| |
| private static final String LOG_LEVEL_DEBUG = "debug"; |
| |
| private static final String LOG_LEVEL_INFO = "info"; |
| |
| private static final String LOG_LEVEL_WARN = "warn"; |
| |
| private static final String LOG_LEVEL_ERROR = "error"; |
| |
| private static final String PROP_SHOWTRACE = "ds.showtrace"; |
| |
| private static final String PROP_SHOWERRORS = "ds.showerrors"; |
| |
| private final Activator activator; |
| |
| private int logLevel; |
| |
| private boolean factoryEnabled; |
| |
| private boolean keepInstances; |
| |
| private boolean infoAsService; |
| |
| private boolean cacheMetadata; |
| |
| private long lockTimeout = DEFAULT_LOCK_TIMEOUT_MILLISECONDS; |
| |
| private long stopTimeout = DEFAULT_STOP_TIMEOUT_MILLISECONDS; |
| |
| private long serviceChangecountTimeout = DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS; |
| |
| private Boolean globalExtender; |
| |
| private volatile BundleContext bundleContext; |
| |
| private volatile ServiceRegistration<?> managedServiceRef; |
| |
| private volatile ServiceRegistration<?> metatypeProviderRef; |
| |
| private ComponentCommands scrCommand; |
| |
| public ScrConfigurationImpl(Activator activator ) |
| { |
| this.activator = activator; |
| } |
| |
| public void start(final BundleContext bundleContext) |
| { |
| this.bundleContext = bundleContext; |
| |
| // listen for Configuration Admin configuration |
| final Dictionary<String, Object> msProps = new Hashtable<>(); |
| msProps.put(Constants.SERVICE_PID, PID); |
| msProps.put(Constants.SERVICE_DESCRIPTION, "SCR Configurator"); |
| msProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); |
| |
| |
| // Process configure from bundle context properties so they can be predictably |
| // overriden by configuration admin later. |
| // Note that if the managed service is registered first then it is random which will win since |
| // configuration may be delivered asynchronously |
| configure( null, false ); |
| |
| managedServiceRef = bundleContext.registerService("org.osgi.service.cm.ManagedService", new ScrManagedServiceServiceFactory(this), |
| msProps); |
| |
| final Dictionary<String, Object> mtProps = new Hashtable<>(); |
| mtProps.put(MetaTypeProvider.METATYPE_PID, PID); |
| mtProps.put(Constants.SERVICE_DESCRIPTION, "SCR Configurator MetaTypeProvider"); |
| mtProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); |
| |
| metatypeProviderRef = bundleContext.registerService("org.osgi.service.metatype.MetaTypeProvider", new ScrMetaTypeProviderServiceFactory(this), |
| mtProps); |
| } |
| |
| public void stop() |
| { |
| if (this.managedServiceRef != null) |
| { |
| this.managedServiceRef.unregister(); |
| this.managedServiceRef = null; |
| } |
| |
| if (this.metatypeProviderRef != null) |
| { |
| this.metatypeProviderRef.unregister(); |
| this.metatypeProviderRef = null; |
| } |
| |
| this.bundleContext = null; |
| } |
| |
| public void setScrCommand(ComponentCommands scrCommand) |
| { |
| this.scrCommand = scrCommand; |
| scrCommand.updateProvideScrInfoService(infoAsService()); |
| } |
| |
| // Called from the ScrManagedService.updated method to reconfigure |
| void configure( Dictionary<String, ?> config, boolean fromConfig ) |
| { |
| Boolean newGlobalExtender; |
| Boolean oldGlobalExtender; |
| synchronized (this) |
| { |
| if ( config == null ) |
| { |
| if (!fromConfig) |
| { |
| if (this.bundleContext == null) |
| { |
| logLevel = LogService.LOG_ERROR; |
| factoryEnabled = false; |
| keepInstances = false; |
| infoAsService = false; |
| lockTimeout = DEFAULT_LOCK_TIMEOUT_MILLISECONDS; |
| stopTimeout = DEFAULT_STOP_TIMEOUT_MILLISECONDS; |
| serviceChangecountTimeout = DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS; |
| newGlobalExtender = false; |
| cacheMetadata = false; |
| } |
| else |
| { |
| logLevel = getDefaultLogLevel(); |
| factoryEnabled = getDefaultFactoryEnabled(); |
| keepInstances = getDefaultKeepInstances(); |
| infoAsService = getDefaultInfoAsService(); |
| lockTimeout = getDefaultLockTimeout(); |
| stopTimeout = getDefaultStopTimeout(); |
| serviceChangecountTimeout = getServiceChangecountTimeout(); |
| newGlobalExtender = getDefaultGlobalExtender(); |
| cacheMetadata = getDefaultCacheMetadata(); |
| } |
| } |
| else |
| { |
| newGlobalExtender = this.globalExtender; |
| } |
| } |
| else |
| { |
| logLevel = getLogLevel( config.get( PROP_LOGLEVEL ) ); |
| factoryEnabled = VALUE_TRUE.equalsIgnoreCase( String.valueOf( config.get( PROP_FACTORY_ENABLED ) ) ); |
| keepInstances = VALUE_TRUE.equalsIgnoreCase( String.valueOf( config.get( PROP_DELAYED_KEEP_INSTANCES ) ) ); |
| infoAsService = VALUE_TRUE.equalsIgnoreCase( String.valueOf( config.get( PROP_INFO_SERVICE) ) ); |
| Long timeout = ( Long ) config.get( PROP_LOCK_TIMEOUT ); |
| lockTimeout = timeout == null? DEFAULT_LOCK_TIMEOUT_MILLISECONDS: timeout; |
| timeout = ( Long ) config.get( PROP_STOP_TIMEOUT ); |
| stopTimeout = timeout == null? DEFAULT_STOP_TIMEOUT_MILLISECONDS: timeout; |
| newGlobalExtender = VALUE_TRUE.equalsIgnoreCase( String.valueOf( config.get( PROP_GLOBAL_EXTENDER) ) ); |
| cacheMetadata = VALUE_TRUE.equalsIgnoreCase( |
| String.valueOf(config.get(PROP_CACHE_METADATA))); |
| } |
| if ( scrCommand != null ) |
| { |
| scrCommand.updateProvideScrInfoService( infoAsService() ); |
| } |
| oldGlobalExtender = this.globalExtender; |
| this.globalExtender = newGlobalExtender; |
| } |
| if ( newGlobalExtender != oldGlobalExtender ) |
| { |
| activator.restart( newGlobalExtender ); |
| } |
| } |
| |
| /** |
| * Returns the current log level. |
| * Note that this log level is not used with an R7 LogService implementation. |
| * @return |
| */ |
| @Override |
| public int getLogLevel() |
| { |
| return logLevel; |
| } |
| |
| |
| @Override |
| public boolean isFactoryEnabled() |
| { |
| return factoryEnabled; |
| } |
| |
| |
| @Override |
| public boolean keepInstances() |
| { |
| return keepInstances; |
| } |
| |
| @Override |
| public boolean infoAsService() |
| { |
| return infoAsService; |
| } |
| |
| @Override |
| public long lockTimeout() |
| { |
| return lockTimeout; |
| } |
| |
| @Override |
| public long stopTimeout() |
| { |
| return stopTimeout; |
| } |
| |
| @Override |
| public boolean globalExtender() |
| { |
| return globalExtender; |
| } |
| |
| @Override |
| public boolean cacheMetadata() |
| { |
| return cacheMetadata; |
| } |
| |
| @Override |
| public long serviceChangecountTimeout() |
| { |
| return serviceChangecountTimeout; |
| } |
| |
| private boolean getDefaultFactoryEnabled() |
| { |
| return VALUE_TRUE.equals( bundleContext.getProperty( PROP_FACTORY_ENABLED ) ); |
| } |
| |
| |
| private boolean getDefaultKeepInstances() |
| { |
| return VALUE_TRUE.equals( bundleContext.getProperty( PROP_DELAYED_KEEP_INSTANCES ) ); |
| } |
| |
| |
| private int getDefaultLogLevel() |
| { |
| return getLogLevel( bundleContext.getProperty( PROP_LOGLEVEL ) ); |
| } |
| |
| private boolean getDefaultInfoAsService() |
| { |
| return VALUE_TRUE.equalsIgnoreCase( bundleContext.getProperty( PROP_INFO_SERVICE) ); |
| } |
| |
| private long getDefaultLockTimeout() |
| { |
| String val = bundleContext.getProperty( PROP_LOCK_TIMEOUT); |
| if ( val == null) |
| { |
| return DEFAULT_LOCK_TIMEOUT_MILLISECONDS; |
| } |
| return Long.parseLong( val ); |
| } |
| |
| private long getDefaultStopTimeout() |
| { |
| String val = bundleContext.getProperty( PROP_STOP_TIMEOUT); |
| if ( val == null) |
| { |
| return DEFAULT_STOP_TIMEOUT_MILLISECONDS; |
| } |
| return Long.parseLong( val ); |
| } |
| |
| private long getServiceChangecountTimeout() |
| { |
| String val = bundleContext.getProperty( PROP_SERVICE_CHANGECOUNT_TIMEOUT ); |
| if ( val == null) |
| { |
| return DEFAULT_SERVICE_CHANGECOUNT_TIMEOUT_MILLISECONDS; |
| } |
| return Long.parseLong( val ); |
| } |
| |
| private boolean getDefaultGlobalExtender() |
| { |
| return VALUE_TRUE.equalsIgnoreCase( bundleContext.getProperty( PROP_GLOBAL_EXTENDER) ); |
| } |
| |
| private boolean getDefaultCacheMetadata() |
| { |
| return VALUE_TRUE.equalsIgnoreCase( |
| bundleContext.getProperty(PROP_CACHE_METADATA)); |
| } |
| |
| private int getLogLevel( final Object levelObject ) |
| { |
| if ( levelObject != null ) |
| { |
| if ( levelObject instanceof Number ) |
| { |
| return ( ( Number ) levelObject ).intValue(); |
| } |
| |
| String levelString = levelObject.toString(); |
| try |
| { |
| return Integer.parseInt( levelString ); |
| } |
| catch ( NumberFormatException nfe ) |
| { |
| // might be a descriptive name |
| } |
| |
| if ( LOG_LEVEL_DEBUG.equalsIgnoreCase( levelString ) ) |
| { |
| return LogService.LOG_DEBUG; |
| } |
| else if ( LOG_LEVEL_INFO.equalsIgnoreCase( levelString ) ) |
| { |
| return LogService.LOG_INFO; |
| } |
| else if ( LOG_LEVEL_WARN.equalsIgnoreCase( levelString ) ) |
| { |
| return LogService.LOG_WARNING; |
| } |
| else if ( LOG_LEVEL_ERROR.equalsIgnoreCase( levelString ) ) |
| { |
| return LogService.LOG_ERROR; |
| } |
| } |
| |
| // check ds.showtrace property |
| if ( VALUE_TRUE.equalsIgnoreCase( bundleContext.getProperty( PROP_SHOWTRACE ) ) ) |
| { |
| return LogService.LOG_DEBUG; |
| } |
| |
| // next check ds.showerrors property |
| if ( "false".equalsIgnoreCase( bundleContext.getProperty( PROP_SHOWERRORS ) ) ) |
| { |
| return -1; // no logging at all !! |
| } |
| |
| // default log level (errors only) |
| return LogService.LOG_ERROR; |
| } |
| } |