blob: 953371d6f4307b730a586d23ca290443ebadbfe1 [file] [log] [blame]
Karl Paulsd7db2462006-06-01 11:49:22 +00001/*
2 * Copyright 2006 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
Alex Karasulu07d20492006-03-06 15:35:44 +000017package org.apache.felix.daemon;
18
19
20import java.io.FileNotFoundException;
21import java.io.IOException;
22import java.io.InputStream;
23import java.net.MalformedURLException;
24import java.net.URL;
25import java.util.Enumeration;
26import java.util.Properties;
27
28import org.apache.directory.daemon.DaemonApplication;
29import org.apache.directory.daemon.InstallationLayout;
30
31import org.apache.felix.framework.Felix;
Richard S. Halla086e3f2006-03-15 15:08:51 +000032import org.apache.felix.framework.cache.BundleCache;
Alex Karasulu07d20492006-03-06 15:35:44 +000033import org.apache.felix.framework.util.StringMap;
34
35
36/**
37 * NOTE: Does not set system properties which are done via a daemon ui, some
38 * init script, or a main() application entry point.
39 */
40public class Service implements DaemonApplication
41{
42 /**
43 * The system property name used to specify an URL to the configuration
44 * property file to be used for the created the framework instance.
45 */
46 public static final String CONFIG_PROPERTIES_PROP = "felix.config.properties";
47 /** The default name used for the configuration properties file. */
48 public static final String CONFIG_PROPERTIES_FILE_VALUE = "config.properties";
49 /** the default profile if no profile name or path is specified */
50 public static final String DEFAULT_PRODUCTION_PROFILE = "production";
51
52 /** the instance of Felix managed by this daemon/service */
53 private Felix instance;
54 /** the configuration properties loaded from the configuration file */
55 private Properties configationProperties;
56 /** the felix installation layout */
57 private FelixLayout layout;
58
Alex Karasulu9fee5e22006-08-17 17:53:44 +000059
60 public Felix getFelixInstance()
61 {
62 return instance;
63 }
64
Alex Karasulu07d20492006-03-06 15:35:44 +000065
66 public void init( InstallationLayout suppliedLayout, String[] args ) throws Exception
67 {
68 if ( !( suppliedLayout instanceof FelixLayout ) )
69 {
70 this.layout = new FelixLayout( suppliedLayout );
71 }
72 else
73 {
74 this.layout = ( FelixLayout ) suppliedLayout;
75 }
Karl Pauls10461212007-07-05 21:24:02 +000076
Alex Karasulu07d20492006-03-06 15:35:44 +000077 configationProperties = readConfigProperties();
Karl Paulsbe2991e2007-07-12 08:37:56 +000078 instance = new Felix(new StringMap(configationProperties, false ), null );
Alex Karasulu07d20492006-03-06 15:35:44 +000079 }
80
81
82 public void start()
83 {
84 // See if the profile name property was specified.
Richard S. Halla086e3f2006-03-15 15:08:51 +000085 String profileName = configationProperties.getProperty( BundleCache.CACHE_PROFILE_PROP );
Alex Karasulu07d20492006-03-06 15:35:44 +000086
87 // See if the profile directory property was specified.
Richard S. Halla086e3f2006-03-15 15:08:51 +000088 String profileDirName = configationProperties.getProperty( BundleCache.CACHE_PROFILE_DIR_PROP );
Alex Karasulu07d20492006-03-06 15:35:44 +000089
90 // If no profile or profile directory is specified in the properties, then set the
91 // name to the default production mode profile name since this is not started from main()
92 if ( ( profileName == null ) && ( profileDirName == null ) )
93 {
Richard S. Halla086e3f2006-03-15 15:08:51 +000094 configationProperties.setProperty( BundleCache.CACHE_PROFILE_PROP, DEFAULT_PRODUCTION_PROFILE );
Alex Karasulu07d20492006-03-06 15:35:44 +000095 }
96
97 // start up the instance using the loaded and possibly altered configuration
Karl Pauls10461212007-07-05 21:24:02 +000098 try
99 {
100 instance.start();
101 }
102 catch (Exception ex)
103 {
104 // TODO: find out what to do
105 }
Alex Karasulu07d20492006-03-06 15:35:44 +0000106 }
107
108
109 public void stop( String[] arg0 ) throws Exception
110 {
Karl Pauls10461212007-07-05 21:24:02 +0000111 instance.stop();
Alex Karasulu07d20492006-03-06 15:35:44 +0000112 }
113
114
115 public void destroy()
116 {
117 }
118
119
120 /**
121 * Exposes configuration properties for potential alteration between load
122 * time at init() and start() by the managing framework or by the main().
123 *
124 * @return the configuration properties loaded by default from conf/config.properties
125 */
126 public Properties getConfigurationProperties()
127 {
128 return configationProperties;
129 }
130
131
132 /**
133 * <p>
134 * Reads the configuration properties in the configuration property
135 * file associated with the framework installation; these properties are
136 * only accessible to the framework and are intended for configuration
137 * purposes. By default, the configuration property file is located in
138 * the same directory as the <tt>felix.jar</tt> file and is called
139 * "<tt>config.properties</tt>". This may be changed by setting the
140 * "<tt>felix.config.properties</tt>" system property to an
141 * arbitrary URL.
142 * </p>
143 * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error.
144 */
145 private Properties readConfigProperties()
146 {
147 // The config properties file is either present in a default
148 // location using the layout, or is specified by a system property
149 // Try to load it from one of these places.
150
151 // See if the property URL was specified as a property.
152 URL propURL = null;
153 String custom = System.getProperty( CONFIG_PROPERTIES_PROP );
154 if ( custom != null )
155 {
156 try
157 {
158 propURL = new URL( custom );
159 }
160 catch ( MalformedURLException ex )
161 {
162 System.err.print( "Main: " + ex );
163 return null;
164 }
165 }
166 else
167 {
168 try
169 {
170 propURL = layout.getConfigurationFile().toURL();
171 }
172 catch ( MalformedURLException ex )
173 {
174 System.err.print( "Main: " + ex );
175 return null;
176 }
177 }
178
179 // Read the properties file.
180 Properties props = new Properties();
181 InputStream is = null;
182 try
183 {
184 is = propURL.openConnection().getInputStream();
185 props.load( is );
186 is.close();
187 }
188 catch ( FileNotFoundException ex )
189 {
190 // Ignore file not found.
191 }
192 catch ( Exception ex )
193 {
194 System.err.println( "Error loading config properties from " + propURL );
195 System.err.println( "Main: " + ex );
196
197 try
198 {
199 if ( is != null )
200 {
201 is.close();
202 }
203 }
204 catch ( IOException ex2 )
205 {
206 // Nothing we can do.
207 }
208
209 return null;
210 }
211
212 // Perform variable substitution for system properties.
213 for ( Enumeration e = props.propertyNames(); e.hasMoreElements(); /* EMPTY */ )
214 {
215 String name = ( String ) e.nextElement();
216 props.setProperty( name, substVars( ( String ) props.getProperty( name ) ) );
217 }
218
219 return props;
220 }
221
222
223 private static final String DELIM_START = "${";
224 private static final char DELIM_STOP = '}';
225 private static final int DELIM_START_LEN = 2;
226 private static final int DELIM_STOP_LEN = 1;
227
228
229 /**
230 * <p>
231 * This method performs system property variable substitution on the
232 * specified string value. If the specified string contains the syntax
233 * <tt>${&lt;system-prop-name&gt;}</tt>, then the corresponding system
234 * property value is substituted for the marker.
235 * </p>
236 *
237 * @param val
238 * The string on which to perform system property substitution.
239 * @return The value of the specified string after system property
240 * substitution.
241 * @throws IllegalArgumentException
242 * If there was a syntax error in the system property variable
243 * marker syntax.
244 */
245 public static String substVars( String val ) throws IllegalArgumentException
246 {
247 StringBuffer sbuf = new StringBuffer();
248
249 if ( val == null )
250 {
251 return val;
252 }
253
254 int i = 0;
255 int j, k;
256
257 while ( true )
258 {
259 j = val.indexOf( DELIM_START, i );
260 if ( j == -1 )
261 {
262 if ( i == 0 )
263 {
264 return val;
265 }
266 else
267 {
268 sbuf.append( val.substring( i, val.length() ) );
269 return sbuf.toString();
270 }
271 }
272 else
273 {
274 sbuf.append( val.substring( i, j ) );
275 k = val.indexOf( DELIM_STOP, j );
276 if ( k == -1 )
277 {
278 throw new IllegalArgumentException( '"' + val
279 + "\" has no closing brace. Opening brace at position " + j + '.' );
280 }
281 else
282 {
283 j += DELIM_START_LEN;
284 String key = val.substring( j, k );
285 // Try system properties.
286 String replacement = System.getProperty( key, null );
287 if ( replacement != null )
288 {
289 sbuf.append( replacement );
290 }
291 i = k + DELIM_STOP_LEN;
292 }
293 }
294 }
295 }
296}