1 /*******************************************************************************
2 * Copyright (c) 1997, 2010 by ProSyst Software GmbH
3 * http://www.prosyst.com
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * ProSyst Software GmbH - initial API and implementation
11 *******************************************************************************/
12 package org.eclipse.equinox.internal.ds;
13
14 import java.io.IOException;
15 import java.util.Dictionary;
16 import java.util.Hashtable;
17 import org.apache.felix.scr.ScrService;
18 import org.eclipse.equinox.internal.util.ref.Log;
19 import org.eclipse.osgi.framework.log.FrameworkLog;
20 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
21 import org.eclipse.osgi.service.debug.DebugOptions;
22 import org.eclipse.osgi.service.environment.EnvironmentInfo;
23 import org.osgi.framework.*;
24 import org.osgi.service.cm.*;
25 import org.osgi.service.component.ComponentConstants;
26 import org.osgi.service.log.LogService;
27 import org.osgi.util.tracker.ServiceTracker;
28
29 /**
30 * This is the main starting class for the Service Component Runtime.
31 * The SCR is not fully initialized until it detects at least one bundle providing DS components.
32 * Thus it has considerably small startup time and does improve a little the runtime performance
33 * since it does not listen for service events.
34 *
35 * @author Valentin Valchev
36 * @author Stoyan Boshev
37 * @author Pavlin Dobrev
38 */
39
40 public class Activator implements BundleActivator, SynchronousBundleListener, ServiceListener {
41
42 public static BundleContext bc = null;
43 public static ConfigurationAdmin configAdmin = null;
44 public static boolean security = false;
45
46 private ServiceRegistration configListenerReg;
47 private SCRManager scrManager = null;
48 public ScrServiceImpl scrService = null;
49 private ServiceRegistration scrServiceReg;
50 private ServiceRegistration scrCommandProviderReg;
51 private static FrameworkLog fwLog;
52 private boolean inited = false;
53
54 public static Log log;
55 public static boolean DEBUG;
56 public static boolean PERF;
57 public static boolean DBSTORE;
58 public static boolean INSTANTIATE_ALL;
59 public static boolean startup;
60
61 static long time[] = null;
62
63 public static void timeLog(String message) {
64 time[1] = time[0];
65 log.debug(message + String.valueOf((time[0] = System.currentTimeMillis()) - time[1]), null);
66 }
67
68 private void initSCR() {
69 synchronized (this) {
70 if (inited)
71 return;
72 inited = true;
73 }
74
75 boolean lazyIniting = false;
76 if (startup && time == null) {
77 long tmp = System.currentTimeMillis();
78 time = new long[] {tmp, 0, tmp};
79 lazyIniting = true;
80 if (startup)
81 timeLog("[BEGIN - lazy SCR init]"); //$NON-NLS-1$
82 }
83
84 WorkThread.IDLE_TIMEOUT = getInteger("equinox.ds.idle_timeout", 1000); //$NON-NLS-1$
85 WorkThread.BLOCK_TIMEOUT = getInteger("equinox.ds.block_timeout", 30000); //$NON-NLS-1$
86
87 try {
88 bc.addServiceListener(this, "(objectClass=" + ConfigurationAdmin.class.getName() + ')'); //$NON-NLS-1$
89 } catch (InvalidSyntaxException e) {
90 //should never happen
91 }
92 //get config admin service if available
93 ServiceReference caRef = bc.getServiceReference(ConfigurationAdmin.class.getName());
94 if (caRef != null) {
95 configAdmin = (ConfigurationAdmin) bc.getService(caRef);
96 }
97 if (startup)
98 timeLog("ConfigurationAdmin service getting took "); //$NON-NLS-1$
99
100 scrManager = new SCRManager();
101 if (startup)
102 timeLog("SCRManager instantiation took "); //$NON-NLS-1$
103
104 // add the configuration listener - we to receive CM events to restart
105 // components
106 configListenerReg = bc.registerService(ConfigurationListener.class.getName(), scrManager, null);
107 if (startup)
108 timeLog("ConfigurationListener service registered for "); //$NON-NLS-1$
109 bc.addServiceListener(scrManager);
110
111 scrManager.startIt();
112 if (Activator.startup)
113 Activator.timeLog("startIt() method took "); //$NON-NLS-1$
114
115 installCommandProvider();
116
117 if (startup && lazyIniting) {
118 log.debug("[END - lazy SCR init] Activator.initSCR() method executed for " + String.valueOf(time[0] - time[2]), null); //$NON-NLS-1$
119 time = null;
120 }
121 }
122
123 /*
124 * (non-Javadoc)
125 *
126 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
127 */
128 public void start(BundleContext bundleContext) throws Exception {
129 Activator.bc = bundleContext;
130 startup = getBoolean("equinox.measurements.bundles", false); //$NON-NLS-1$
131 if (startup) {
132 long tmp = System.currentTimeMillis();
133 time = new long[] {tmp, 0, tmp};
134 }
135 // initialize the logging routines
136 log = new Log(bundleContext, false);
137 ServiceTracker debugTracker = new ServiceTracker(bundleContext, DebugOptions.class.getName(), null);
138 debugTracker.open();
139 DebugOptions debugOptions = (DebugOptions) debugTracker.getService();
140 DEBUG = getBooleanDebugOption(debugOptions, "org.eclipse.equinox.ds/debug", false) || getBoolean("equinox.ds.debug", false); //$NON-NLS-1$ //$NON-NLS-2$
141 PERF = getBooleanDebugOption(debugOptions, "org.eclipse.equinox.ds/performance", false) || getBoolean("equinox.ds.perf", false); //$NON-NLS-1$ //$NON-NLS-2$
142 INSTANTIATE_ALL = getBooleanDebugOption(debugOptions, "org.eclipse.equinox.ds/instantiate_all", false) || getBoolean("equinox.ds.instantiate_all", false); //$NON-NLS-1$ //$NON-NLS-2$
143
144 DBSTORE = getBooleanDebugOption(debugOptions, "org.eclipse.equinox.ds/cache_descriptions", true) || getBoolean("equinox.ds.dbstore", true); //$NON-NLS-1$ //$NON-NLS-2$
145 boolean print = getBooleanDebugOption(debugOptions, "org.eclipse.equinox.ds/print_on_console", false) || getBoolean("equinox.ds.print", false); //$NON-NLS-1$ //$NON-NLS-2$
146 log.setDebug(DEBUG);
147 log.setPrintOnConsole(print);
148 //DebugOptions no longer needed
149 debugTracker.close();
150 ServiceReference fwRef = bc.getServiceReference(FrameworkLog.class.getName());
151 if (fwRef != null) {
152 fwLog = (FrameworkLog) bc.getService(fwRef);
153 }
154
155 if (startup)
156 timeLog("[BEGIN - start method] Creating Log instance and initializing log system took "); //$NON-NLS-1$
157
158 security = Log.security();
159 boolean hasHeaders = false;
160 Bundle[] allBundles = bundleContext.getBundles();
161 for (int i = 0; i < allBundles.length; i++) {
162 Dictionary allHeaders = allBundles[i].getHeaders(""); //$NON-NLS-1$
163 if (allHeaders.get(ComponentConstants.SERVICE_COMPONENT) != null) {
164 hasHeaders = true;
165 break;
166 }
167 }
168
169 if (hasHeaders) {
170 initSCR();
171 } else {
172 // there are no bundles holding components - SCR will not be
173 // initialized yet
174 bundleContext.addBundleListener(this);
175 }
176 ServiceReference envInfoRef = bc.getServiceReference(EnvironmentInfo.class.getName());
177 EnvironmentInfo envInfo = null;
178 if (envInfoRef != null) {
179 envInfo = (EnvironmentInfo) bc.getService(envInfoRef);
180 }
181 if (envInfo != null) {
182 envInfo.setProperty("equinox.use.ds", "true"); //$NON-NLS-1$//$NON-NLS-2$
183 bc.ungetService(envInfoRef);
184 } else {
185 System.setProperty("equinox.use.ds", "true"); //$NON-NLS-1$ //$NON-NLS-2$
186 }
187
188 scrService = new ScrServiceImpl();
189 scrServiceReg = bc.registerService(ScrService.class.getName(), scrService, null);
190
191 if (startup) {
192 log.debug("[END - start method] Activator.start() method executed for " + String.valueOf(time[0] - time[2]), null); //$NON-NLS-1$
193 time = null;
194 }
195 }
196
197 /*
198 * (non-Javadoc)
199 *
200 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
201 */
202 public void stop(BundleContext bundleContext) throws Exception {
203 if (scrManager != null) {
204 scrManager.stopIt();
205 bundleContext.removeServiceListener(scrManager);
206 }
207 // dispose the CM Listener
208 if (configListenerReg != null) {
209 configListenerReg.unregister();
210 }
211 if (scrService != null) {
212 scrService.dispose();
213 scrServiceReg.unregister();
214 }
215
216 if (scrCommandProviderReg != null)
217 scrCommandProviderReg.unregister();
218
219 if (scrManager != null) {
220 bundleContext.removeBundleListener(scrManager);
221 } else {
222 bundleContext.removeBundleListener(this);
223 }
224 ServiceReference envInfoRef = bc.getServiceReference(EnvironmentInfo.class.getName());
225 EnvironmentInfo envInfo = null;
226 if (envInfoRef != null) {
227 envInfo = (EnvironmentInfo) bc.getService(envInfoRef);
228 }
229 if (envInfo != null) {
230 envInfo.setProperty("equinox.use.ds", "false"); //$NON-NLS-1$//$NON-NLS-2$
231 bc.ungetService(envInfoRef);
232 } else {
233 System.setProperty("equinox.use.ds", "false"); //$NON-NLS-1$ //$NON-NLS-2$
234 }
235
236 log.close();
237 log = null;
238 }
239
240 public static Filter createFilter(String filter) throws InvalidSyntaxException {
241 return bc.createFilter(filter);
242 }
243
244 public void bundleChanged(BundleEvent event) {
245 if (event.getType() == BundleEvent.STARTED || event.getType() == BundleEvent.LAZY_ACTIVATION) {
246 Dictionary allHeaders = event.getBundle().getHeaders(""); //$NON-NLS-1$
247 if ((allHeaders.get(ComponentConstants.SERVICE_COMPONENT)) != null) {
248 // The bundle is holding components - activate scr
249 bc.removeBundleListener(this);
250 initSCR();
251 }
252 }
253 }
254
255 public static Configuration getConfiguration(String pid) throws IOException {
256 if (configAdmin != null) {
257 return configAdmin.getConfiguration(pid);
258 }
259 return null;
260 }
261
262 public static Configuration[] listConfigurations(String filter) throws IOException, InvalidSyntaxException {
263 if (configAdmin != null) {
264 return configAdmin.listConfigurations(filter);
265 }
266 return null;
267 }
268
269 public static boolean getBoolean(String property, boolean defaultValue) {
270 String prop = (bc != null) ? bc.getProperty(property) : System.getProperty(property);
271 if (prop != null) {
272 return prop.equalsIgnoreCase("true"); //$NON-NLS-1$
273 }
274 return defaultValue;
275 }
276
277 public static boolean getBoolean(String property) {
278 return getBoolean(property, false);
279 }
280
281 public static int getInteger(String property, int defaultValue) {
282 String prop = (bc != null) ? bc.getProperty(property) : System.getProperty(property);
283 if (prop != null) {
284 try {
285 return Integer.decode(prop).intValue();
286 } catch (NumberFormatException e) {
287 //do nothing
288 }
289 }
290 return defaultValue;
291 }
292
293 public boolean getBooleanDebugOption(DebugOptions optionsService, String option, boolean defaultValue) {
294 if (optionsService != null) {
295 String value = optionsService.getOption(option);
296 if (value != null)
297 return value.equalsIgnoreCase("true"); //$NON-NLS-1$
298 }
299 return defaultValue;
300 }
301
302 private void installCommandProvider() {
303 try {
304 SCRCommandProvider scrCommandProvider = new SCRCommandProvider(scrManager);
305 Hashtable reg_props = new Hashtable(1, 1);
306 reg_props.put(org.osgi.framework.Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE));
307 scrCommandProviderReg = bc.registerService(org.eclipse.osgi.framework.console.CommandProvider.class.getName(), scrCommandProvider, reg_props);
308 } catch (NoClassDefFoundError e) {
309 //the org.eclipse.osgi.framework.console package is optional
310 if (Activator.DEBUG) {
311 log.debug("Cannot register SCR CommandProvider!", e); //$NON-NLS-1$
312 }
313 }
314 }
315
316 public static void log(BundleContext bundleContext, int level, String message, Throwable t) {
317 LogService logService = null;
318 ServiceReference logRef = null;
319 if (bundleContext != null) {
320 try {
321 logRef = bundleContext.getServiceReference(LogService.class.getName());
322 if (logRef != null) {
323 logService = (LogService) bundleContext.getService(logRef);
324 }
325 } catch (Exception e) {
326 if (Activator.DEBUG) {
327 log.debug("Cannot get LogService for bundle " + bundleContext.getBundle().getSymbolicName(), e); //$NON-NLS-1$
328 }
329 }
330 }
331 if (logService != null) {
332 logService.log(level, message, t);
333 bundleContext.ungetService(logRef);
334 if (log.getPrintOnConsole()) {
335 String prefix = ""; //$NON-NLS-1$
336 switch (level) {
337 case LogService.LOG_ERROR :
338 prefix = "ERROR "; //$NON-NLS-1$
339 break;
340 case LogService.LOG_WARNING :
341 prefix = "WARNING "; //$NON-NLS-1$
342 break;
343 case LogService.LOG_INFO :
344 prefix = "INFO "; //$NON-NLS-1$
345 break;
346 }
347 dumpOnConsole(prefix, bundleContext, message, t, level == LogService.LOG_ERROR);
348 }
349 } else {
350 logRef = bc.getServiceReference(LogService.class.getName());
351 if (logRef == null) {
352 //log service is not available
353 if (!log.getPrintOnConsole() && !log.autoPrintOnConsole && fwLog == null) {
354 //The log will not print the message on the console and the FrameworkLog service is not available
355 //Will print errors on the console as last resort
356 if (level == LogService.LOG_ERROR) {
357 dumpOnConsole("ERROR ", bundleContext, message, t, true); //$NON-NLS-1$
358 }
359 }
360 }
361
362 //using the SCR log
363 switch (level) {
364 case LogService.LOG_ERROR :
365 log.error(message, t);
366 break;
367 case LogService.LOG_WARNING :
368 log.warning(message, t);
369 break;
370 case LogService.LOG_INFO :
371 log.info(message);
372 break;
373 default :
374 log.debug(message, t);
375 break;
376 }
377 }
378 if (fwLog != null) {
379 logToFWLog(bundleContext != null ? bundleContext.getBundle().getSymbolicName() : bc.getBundle().getSymbolicName(), level, message, t);
380 }
381 }
382
383 private static void dumpOnConsole(String prefix, BundleContext bundleContext, String msg, Throwable t, boolean printInErr) {
384 String message = prefix + bundleContext.getBundle().getBundleId() + " " + msg; //$NON-NLS-1$
385 if (printInErr) {
386 System.err.println(message);
387 } else {
388 System.out.println(message);
389 }
390 if (t != null) {
391 t.printStackTrace();
392 }
393 }
394
395 private static void logToFWLog(String bsn, int level, String message, Throwable t) {
396 int severity = FrameworkLogEntry.INFO;
397 switch (level) {
398 case LogService.LOG_ERROR :
399 severity = FrameworkLogEntry.ERROR;
400 break;
401 case LogService.LOG_WARNING :
402 severity = FrameworkLogEntry.WARNING;
403 break;
404 case LogService.LOG_INFO :
405 severity = FrameworkLogEntry.INFO;
406 break;
407 case LogService.LOG_DEBUG :
408 severity = FrameworkLogEntry.INFO;
409 break;
410 }
411 fwLog.log(new FrameworkLogEntry(bsn, severity, 0, message, 0, t, null));
412 }
413
414 public void serviceChanged(ServiceEvent event) {
415 switch (event.getType()) {
416 case ServiceEvent.REGISTERED :
417 Object caService = bc.getService(event.getServiceReference());
418 configAdmin = (ConfigurationAdmin) caService;
419 if (caService != null) {
420 // Config Admin registered
421 if (scrManager != null) {
422 scrManager.configAdminRegistered((ConfigurationAdmin) caService, event.getServiceReference());
423 }
424 }
425 break;
426 case ServiceEvent.UNREGISTERING :
427 //get replacement config admin service if available
428 ServiceReference caRef = bc.getServiceReference(ConfigurationAdmin.class.getName());
429 if (caRef != null) {
430 configAdmin = (ConfigurationAdmin) bc.getService(caRef);
431 } else {
432 configAdmin = null;
433 }
434 break;
435 }
436 }
437 }