| /* |
| * Copyright 2006 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.felix.daemon; |
| |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.Enumeration; |
| import java.util.Properties; |
| |
| import org.apache.directory.daemon.DaemonApplication; |
| import org.apache.directory.daemon.InstallationLayout; |
| |
| import org.apache.felix.framework.Felix; |
| import org.apache.felix.framework.cache.BundleCache; |
| import org.apache.felix.framework.util.StringMap; |
| |
| |
| /** |
| * NOTE: Does not set system properties which are done via a daemon ui, some |
| * init script, or a main() application entry point. |
| */ |
| public class Service implements DaemonApplication |
| { |
| /** |
| * The system property name used to specify an URL to the configuration |
| * property file to be used for the created the framework instance. |
| */ |
| public static final String CONFIG_PROPERTIES_PROP = "felix.config.properties"; |
| /** The default name used for the configuration properties file. */ |
| public static final String CONFIG_PROPERTIES_FILE_VALUE = "config.properties"; |
| /** the default profile if no profile name or path is specified */ |
| public static final String DEFAULT_PRODUCTION_PROFILE = "production"; |
| |
| /** the instance of Felix managed by this daemon/service */ |
| private Felix instance; |
| /** the configuration properties loaded from the configuration file */ |
| private Properties configationProperties; |
| /** the felix installation layout */ |
| private FelixLayout layout; |
| |
| |
| public Felix getFelixInstance() |
| { |
| return instance; |
| } |
| |
| |
| public void init( InstallationLayout suppliedLayout, String[] args ) throws Exception |
| { |
| if ( !( suppliedLayout instanceof FelixLayout ) ) |
| { |
| this.layout = new FelixLayout( suppliedLayout ); |
| } |
| else |
| { |
| this.layout = ( FelixLayout ) suppliedLayout; |
| } |
| |
| configationProperties = readConfigProperties(); |
| instance = new Felix(new StringMap(configationProperties, false ), null ); |
| } |
| |
| |
| public void start() |
| { |
| // See if the profile name property was specified. |
| String profileName = configationProperties.getProperty( BundleCache.CACHE_PROFILE_PROP ); |
| |
| // See if the profile directory property was specified. |
| String profileDirName = configationProperties.getProperty( BundleCache.CACHE_PROFILE_DIR_PROP ); |
| |
| // If no profile or profile directory is specified in the properties, then set the |
| // name to the default production mode profile name since this is not started from main() |
| if ( ( profileName == null ) && ( profileDirName == null ) ) |
| { |
| configationProperties.setProperty( BundleCache.CACHE_PROFILE_PROP, DEFAULT_PRODUCTION_PROFILE ); |
| } |
| |
| // start up the instance using the loaded and possibly altered configuration |
| try |
| { |
| instance.start(); |
| } |
| catch (Exception ex) |
| { |
| // TODO: find out what to do |
| } |
| } |
| |
| |
| public void stop( String[] arg0 ) throws Exception |
| { |
| instance.stop(); |
| } |
| |
| |
| public void destroy() |
| { |
| } |
| |
| |
| /** |
| * Exposes configuration properties for potential alteration between load |
| * time at init() and start() by the managing framework or by the main(). |
| * |
| * @return the configuration properties loaded by default from conf/config.properties |
| */ |
| public Properties getConfigurationProperties() |
| { |
| return configationProperties; |
| } |
| |
| |
| /** |
| * <p> |
| * Reads the configuration properties in the configuration property |
| * file associated with the framework installation; these properties are |
| * only accessible to the framework and are intended for configuration |
| * purposes. By default, the configuration property file is located in |
| * the same directory as the <tt>felix.jar</tt> file and is called |
| * "<tt>config.properties</tt>". This may be changed by setting the |
| * "<tt>felix.config.properties</tt>" system property to an |
| * arbitrary URL. |
| * </p> |
| * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error. |
| */ |
| private Properties readConfigProperties() |
| { |
| // The config properties file is either present in a default |
| // location using the layout, or is specified by a system property |
| // Try to load it from one of these places. |
| |
| // See if the property URL was specified as a property. |
| URL propURL = null; |
| String custom = System.getProperty( CONFIG_PROPERTIES_PROP ); |
| if ( custom != null ) |
| { |
| try |
| { |
| propURL = new URL( custom ); |
| } |
| catch ( MalformedURLException ex ) |
| { |
| System.err.print( "Main: " + ex ); |
| return null; |
| } |
| } |
| else |
| { |
| try |
| { |
| propURL = layout.getConfigurationFile().toURL(); |
| } |
| catch ( MalformedURLException ex ) |
| { |
| System.err.print( "Main: " + ex ); |
| return null; |
| } |
| } |
| |
| // Read the properties file. |
| Properties props = new Properties(); |
| InputStream is = null; |
| try |
| { |
| is = propURL.openConnection().getInputStream(); |
| props.load( is ); |
| is.close(); |
| } |
| catch ( FileNotFoundException ex ) |
| { |
| // Ignore file not found. |
| } |
| catch ( Exception ex ) |
| { |
| System.err.println( "Error loading config properties from " + propURL ); |
| System.err.println( "Main: " + ex ); |
| |
| try |
| { |
| if ( is != null ) |
| { |
| is.close(); |
| } |
| } |
| catch ( IOException ex2 ) |
| { |
| // Nothing we can do. |
| } |
| |
| return null; |
| } |
| |
| // Perform variable substitution for system properties. |
| for ( Enumeration e = props.propertyNames(); e.hasMoreElements(); /* EMPTY */ ) |
| { |
| String name = ( String ) e.nextElement(); |
| props.setProperty( name, substVars( ( String ) props.getProperty( name ) ) ); |
| } |
| |
| return props; |
| } |
| |
| |
| private static final String DELIM_START = "${"; |
| private static final char DELIM_STOP = '}'; |
| private static final int DELIM_START_LEN = 2; |
| private static final int DELIM_STOP_LEN = 1; |
| |
| |
| /** |
| * <p> |
| * This method performs system property variable substitution on the |
| * specified string value. If the specified string contains the syntax |
| * <tt>${<system-prop-name>}</tt>, then the corresponding system |
| * property value is substituted for the marker. |
| * </p> |
| * |
| * @param val |
| * The string on which to perform system property substitution. |
| * @return The value of the specified string after system property |
| * substitution. |
| * @throws IllegalArgumentException |
| * If there was a syntax error in the system property variable |
| * marker syntax. |
| */ |
| public static String substVars( String val ) throws IllegalArgumentException |
| { |
| StringBuffer sbuf = new StringBuffer(); |
| |
| if ( val == null ) |
| { |
| return val; |
| } |
| |
| int i = 0; |
| int j, k; |
| |
| while ( true ) |
| { |
| j = val.indexOf( DELIM_START, i ); |
| if ( j == -1 ) |
| { |
| if ( i == 0 ) |
| { |
| return val; |
| } |
| else |
| { |
| sbuf.append( val.substring( i, val.length() ) ); |
| return sbuf.toString(); |
| } |
| } |
| else |
| { |
| sbuf.append( val.substring( i, j ) ); |
| k = val.indexOf( DELIM_STOP, j ); |
| if ( k == -1 ) |
| { |
| throw new IllegalArgumentException( '"' + val |
| + "\" has no closing brace. Opening brace at position " + j + '.' ); |
| } |
| else |
| { |
| j += DELIM_START_LEN; |
| String key = val.substring( j, k ); |
| // Try system properties. |
| String replacement = System.getProperty( key, null ); |
| if ( replacement != null ) |
| { |
| sbuf.append( replacement ); |
| } |
| i = k + DELIM_STOP_LEN; |
| } |
| } |
| } |
| } |
| } |