blob: 461d1676ced3b0268f4d0c9f19a75c72479d417f [file] [log] [blame]
Karl Pauls49400ec2007-02-12 23:49:43 +00001/*
Richard S. Hallb3951672006-09-19 17:04:53 +00002 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
Richard S. Hall930fecc2005-08-16 18:33:34 +00009 *
Richard S. Hallb3951672006-09-19 17:04:53 +000010 * http://www.apache.org/licenses/LICENSE-2.0
Richard S. Hall930fecc2005-08-16 18:33:34 +000011 *
Richard S. Hallb3951672006-09-19 17:04:53 +000012 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Richard S. Hall930fecc2005-08-16 18:33:34 +000018 */
Richard S. Hall5a031592005-08-19 19:53:58 +000019package org.apache.felix.framework;
Richard S. Hall930fecc2005-08-16 18:33:34 +000020
21import java.io.*;
Karl Pauls49400ec2007-02-12 23:49:43 +000022import java.net.*;
Karl Pauls9a96b152007-01-22 16:35:58 +000023import java.security.*;
Richard S. Hall930fecc2005-08-16 18:33:34 +000024import java.util.*;
Richard S. Hall05fd75e2007-01-18 01:36:45 +000025
26import org.apache.felix.framework.cache.*;
Karl Pauls28636dc2008-02-03 21:32:48 +000027import org.apache.felix.framework.ext.SecurityProvider;
Richard S. Hall5a031592005-08-19 19:53:58 +000028import org.apache.felix.framework.searchpolicy.*;
29import org.apache.felix.framework.util.*;
Richard S. Hall78605422006-12-18 20:47:55 +000030import org.apache.felix.framework.util.manifestparser.*;
Richard S. Hall5a031592005-08-19 19:53:58 +000031import org.apache.felix.moduleloader.*;
Richard S. Hall930fecc2005-08-16 18:33:34 +000032import org.osgi.framework.*;
33import org.osgi.service.packageadmin.ExportedPackage;
Richard S. Hall17897152006-03-02 13:43:09 +000034import org.osgi.service.startlevel.StartLevel;
Richard S. Hall930fecc2005-08-16 18:33:34 +000035
Richard S. Hall26b91982007-07-04 21:15:05 +000036public class Felix extends FelixBundle
Richard S. Hall930fecc2005-08-16 18:33:34 +000037{
Karl Pauls1bab5662007-06-20 22:33:26 +000038 // The secure action used to do privileged calls
39 static SecureAction m_secureAction = new SecureAction();
Richard S. Hall26b91982007-07-04 21:15:05 +000040
41 // The extension manager to handle extension bundles
Karl Pauls758c2be2008-03-05 13:10:04 +000042 ExtensionManager m_extensionManager;
Karl Paulsad142d22007-09-16 19:53:22 +000043
Richard S. Hall930fecc2005-08-16 18:33:34 +000044 // Logging related member variables.
Richard S. Hall3875d692008-06-24 19:47:44 +000045 private Logger m_logger = null;
Richard S. Hall471e3e62007-07-11 19:25:33 +000046 // Immutable config properties.
47 private Map m_configMap = null;
48 // Mutable configuration properties passed into constructor.
49 private Map m_configMutableMap = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +000050
Richard S. Hall29a4fbc2006-02-03 12:54:52 +000051 // MODULE FACTORY.
52 private IModuleFactory m_factory = null;
53 private R4SearchPolicyCore m_policyCore = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +000054
55 // Object used as a lock when calculating which bundles
56 // when performing an operation on one or more bundles.
57 private Object[] m_bundleLock = new Object[0];
58
59 // Maps a bundle location to a bundle location;
60 // used to reserve a location when installing a bundle.
Richard S. Halle60d8782007-08-17 20:10:27 +000061 private Map m_installRequestMap = new HashMap();
Richard S. Hall930fecc2005-08-16 18:33:34 +000062 // This lock must be acquired to modify m_installRequestMap;
63 // to help avoid deadlock this lock as priority 1 and should
64 // be acquired before locks with lower priority.
65 private Object[] m_installRequestLock_Priority1 = new Object[0];
66
67 // Maps a bundle location to a bundle.
Richard S. Halle60d8782007-08-17 20:10:27 +000068 private HashMap m_installedBundleMap = new HashMap();
Karl Paulsa7e36b82008-04-13 19:09:20 +000069 private SortedMap m_installedBundleIndex = new TreeMap();
Richard S. Hall930fecc2005-08-16 18:33:34 +000070 // This lock must be acquired to modify m_installedBundleMap;
71 // to help avoid deadlock this lock as priority 2 and should
72 // be acquired before locks with lower priority.
73 private Object[] m_installedBundleLock_Priority2 = new Object[0];
74
75 // An array of uninstalled bundles before a refresh occurs.
Richard S. Hall26b91982007-07-04 21:15:05 +000076 private FelixBundle[] m_uninstalledBundles = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +000077 // This lock must be acquired to modify m_uninstalledBundles;
78 // to help avoid deadlock this lock as priority 3 and should
79 // be acquired before locks with lower priority.
80 private Object[] m_uninstalledBundlesLock_Priority3 = new Object[0];
81
Richard S. Hall930fecc2005-08-16 18:33:34 +000082 // Framework's active start level.
83 private int m_activeStartLevel =
84 FelixConstants.FRAMEWORK_INACTIVE_STARTLEVEL;
85
86 // Local file system cache.
Richard S. Hall04bdbb12006-03-15 14:26:15 +000087 private BundleCache m_cache = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +000088
Richard S. Hall26b91982007-07-04 21:15:05 +000089 // System bundle bundle info instance.
90 private BundleInfo m_systemBundleInfo = null;
91 // System bundle activator list.
92 List m_activatorList = null;
Richard S. Hall26b91982007-07-04 21:15:05 +000093
Richard S. Hall930fecc2005-08-16 18:33:34 +000094 // Next available bundle identifier.
95 private long m_nextId = 1L;
Richard S. Hall441c7152006-02-17 11:07:10 +000096 private Object m_nextIdLock = new Object[0];
Richard S. Hall930fecc2005-08-16 18:33:34 +000097
98 // List of event listeners.
Richard S. Hall92770632006-07-24 10:18:52 +000099 private EventDispatcher m_dispatcher = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +0000100
101 // Service registry.
102 private ServiceRegistry m_registry = null;
103
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000104 // Reusable bundle URL stream handler.
105 private URLStreamHandler m_bundleStreamHandler = null;
106
Richard S. Hall9955e902007-01-25 14:42:01 +0000107 // Execution environment.
108 private String m_executionEnvironment = "";
109 private Set m_executionEnvironmentCache = new HashSet();
110
Richard S. Hall26b91982007-07-04 21:15:05 +0000111 // Shutdown thread.
112 private Thread m_shutdownThread = null;
113
Richard S. Hall930fecc2005-08-16 18:33:34 +0000114 /**
Richard S. Hallc7a576d2007-12-19 22:34:23 +0000115 * Creates a new Felix framework instance with a default logger.
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000116 *
Richard S. Hallc7a576d2007-12-19 22:34:23 +0000117 * @param configMutableMap An map for obtaining configuration properties,
118 * may be <tt>null</tt>.
119 * @param activatorList A list of System Bundle activators.
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000120 *
Richard S. Hallc7a576d2007-12-19 22:34:23 +0000121 * @see #Felix(Logger, Map, List)
122 */
123 public Felix(Map configMutableMap, List activatorList)
124 {
125 this(null, configMutableMap, activatorList);
126 }
127
128 /**
Richard S. Hall930fecc2005-08-16 18:33:34 +0000129 * <p>
Richard S. Hall7adef032007-12-14 21:55:01 +0000130 * This method creates the framework instance; instances of the framework
131 * are not active until they are started. The constructor accepts a
Richard S. Hall471e3e62007-07-11 19:25:33 +0000132 * <tt>Map</tt> instance that will be used to obtain configuration or
133 * framework properties. Configuration properties are used internally by
134 * the framework and its extensions to alter its default behavior.
135 * Framework properties are used by bundles and are accessible from
136 * <tt>BundleContext.getProperty()</tt>. This map instance is used
137 * directly (i.e., it is not copied), which means that it is possible to
138 * change the property values externally at run time, but this is strongly
139 * discouraged for the framework's configuration properties.
Richard S. Hall930fecc2005-08-16 18:33:34 +0000140 * </p>
141 * <p>
142 * Configuration properties are the sole means to configure the framework's
143 * default behavior; the framework does not refer to any system properties for
Richard S. Hall471e3e62007-07-11 19:25:33 +0000144 * configuration information. If a <tt>Map</tt> is supplied to this method
145 * for configuration properties, then the framework will consult the
146 * <tt>Map</tt> instance for any and all configuration properties. It is
147 * possible to specify a <tt>null</tt> for the configuration property map,
148 * in which case the framework will use its default behavior in all cases.
149 * However, if the
Richard S. Hall930fecc2005-08-16 18:33:34 +0000150 * <a href="cache/DefaultBundleCache.html"><tt>DefaulBundleCache</tt></a>
151 * is used, then at a minimum a profile name or profile directory must
152 * be specified.
153 * </p>
154 * <p>
155 * The following configuration properties can be specified:
156 * </p>
157 * <ul>
Richard S. Hall5aa58c62006-12-08 17:08:14 +0000158 * <li><tt>felix.log.level</tt> - An integer value indicating the degree
159 * of logging reported by the framework; the higher the value the more
160 * logging is reported. If zero ('0') is specified, then logging is
161 * turned off completely. The log levels match those specified in the
162 * OSGi Log Service (i.e., 1 = error, 2 = warning, 3 = information,
163 * and 4 = debug). The default value is 1.
164 * </li>
Richard S. Hall930fecc2005-08-16 18:33:34 +0000165 * <li><tt>felix.startlevel.framework</tt> - The initial start level
166 * of the framework once it starts execution; the default
167 * value is 1.
168 * </li>
169 * <li><tt>felix.startlevel.bundle</tt> - The default start level for
170 * newly installed bundles; the default value is 1.
171 * </li>
Richard S. Hall5d226732005-11-08 09:09:05 +0000172 * <li><tt>framework.service.urlhandlers</tt> - Flag to indicate whether
173 * to activate the URL Handlers service for the framework instance;
174 * the default value is "<tt>true</tt>". Activating the URL Handlers
175 * service will result in the <tt>URL.setURLStreamHandlerFactory()</tt>
176 * and <tt>URLConnection.setContentHandlerFactory()</tt> being called.
177 * </li>
Richard S. Hall930fecc2005-08-16 18:33:34 +0000178 * <li><tt>felix.embedded.execution</tt> - Flag to indicate whether
179 * the framework is embedded into a host application; the default value is
180 * "<tt>false</tt>". If this flag is "<tt>true</tt>" then the framework
181 * will not called <tt>System.exit()</tt> upon termination.
182 * </li>
183 * <li><tt>felix.strict.osgi</tt> - Flag to indicate whether the framework is
184 * running in strict OSGi mode; the default value is "<tt>true</tt>".
185 * If this flag is "<tt>false</tt>" it enables a non-OSGi-compliant
186 * feature by persisting <tt>BundleActivator</tt>s that implement
187 * <tt>Serializable</tt>. This feature is not recommended since
188 * it is non-compliant.
189 * </li>
190 * </ul>
191 * <p>
192 * Besides the above framework configuration properties, it is also
193 * possible to specify properties for the bundle cache. The available
194 * bundle cache properties depend on the cache implementation
195 * being used. For the properties of the default bundle cache, refer to the
196 * <a href="cache/DefaultBundleCache.html"><tt>DefaulBundleCache</tt></a>
197 * API documentation.
198 * </p>
199 * <p>
Richard S. Hall930fecc2005-08-16 18:33:34 +0000200 * The <a href="Main.html"><tt>Main</tt></a> class implements some
201 * functionality for default property file handling, which makes it
202 * possible to specify configuration properties and framework properties
203 * in files that are automatically loaded when starting the framework. If you
204 * plan to create your own framework instance, you may be
205 * able to take advantage of the features it provides; refer to its
206 * class documentation for more information.
207 * </p>
Karl Pauls836bb402006-08-24 12:39:46 +0000208 *
Richard S. Hallc7a576d2007-12-19 22:34:23 +0000209 * @param logger The logger for use by the framework or <code>null</code>
210 * use the default logger.
Richard S. Hall7adef032007-12-14 21:55:01 +0000211 * @param configMutableMap A map for obtaining configuration properties,
Richard S. Hall930fecc2005-08-16 18:33:34 +0000212 * may be <tt>null</tt>.
Richard S. Hall930fecc2005-08-16 18:33:34 +0000213 * @param activatorList A list of System Bundle activators.
214 **/
Richard S. Hallc7a576d2007-12-19 22:34:23 +0000215 public Felix(Logger logger, Map configMutableMap, List activatorList)
Karl Pauls836bb402006-08-24 12:39:46 +0000216 {
Richard S. Hall930fecc2005-08-16 18:33:34 +0000217 // Initialize member variables.
Richard S. Hall471e3e62007-07-11 19:25:33 +0000218 m_configMutableMap = (configMutableMap == null)
219 ? new StringMap(false) : configMutableMap;
Richard S. Hall7adef032007-12-14 21:55:01 +0000220 m_configMap = createUnmodifiableMap(m_configMutableMap);
Karl Pauls28636dc2008-02-03 21:32:48 +0000221 m_activatorList = (activatorList == null) ? new ArrayList() : activatorList;
Richard S. Hall5aa58c62006-12-08 17:08:14 +0000222
223 // Create logger with appropriate log level. Even though the
224 // logger needs the system bundle's context for tracking log
225 // services, it is created now because it is needed before
226 // the system bundle is created. The system bundle's context
Richard S. Hallc7a576d2007-12-19 22:34:23 +0000227 // will be set below after the system bundle is created.\
228 m_logger = (logger == null) ? new Logger() : logger;
229 try
230 {
231 m_logger.setLogLevel(
232 Integer.parseInt(
233 (String) m_configMutableMap.get(FelixConstants.LOG_LEVEL_PROP)));
234 }
235 catch (NumberFormatException ex)
236 {
237 // Ignore and just use the default logging level.
238 }
Richard S. Hall5aa58c62006-12-08 17:08:14 +0000239
Richard S. Hall26b91982007-07-04 21:15:05 +0000240 // Initialize framework properties.
241 initializeFrameworkProperties();
242
Richard S. Halle60d8782007-08-17 20:10:27 +0000243 // Create the bundle cache since we need it for the system bundle
244 // archive, which in turn is needed by the system bundle info,
245 // which we need to keep track of the framework state.
246 try
247 {
248 m_cache = new BundleCache(m_logger, m_configMap);
249 }
250 catch (Exception ex)
251 {
252 System.err.println("Error creating bundle cache:");
253 ex.printStackTrace();
254
255 // Only shutdown the JVM if the framework is running stand-alone.
256 String embedded = (String) m_configMap.get(
257 FelixConstants.EMBEDDED_EXECUTION_PROP);
258 boolean isEmbedded = (embedded == null)
259 ? false : embedded.equals("true");
260 if (!isEmbedded)
261 {
262 m_secureAction.exit(-1);
263 }
264 else
265 {
266 throw new RuntimeException(ex.toString());
267 }
268 }
269
Richard S. Hall26b91982007-07-04 21:15:05 +0000270 // Create the module factory and add the system bundle
271 // module to it, since we need the system bundle info
272 // object to keep track of the framework state.
273 m_factory = new ModuleFactoryImpl(m_logger);
274 m_systemBundleInfo = new BundleInfo(
Richard S. Halle60d8782007-08-17 20:10:27 +0000275 m_logger, new SystemBundleArchive(m_cache), null);
Karl Paulsad142d22007-09-16 19:53:22 +0000276 m_extensionManager =
Richard S. Hall471e3e62007-07-11 19:25:33 +0000277 new ExtensionManager(m_logger, m_configMap, m_systemBundleInfo);
Richard S. Hall26b91982007-07-04 21:15:05 +0000278 m_systemBundleInfo.addModule(
279 m_factory.createModule("0", m_extensionManager));
280 }
281
Richard S. Hall7adef032007-12-14 21:55:01 +0000282 private Map createUnmodifiableMap(Map mutableMap)
Karl Pauls58248712007-11-06 21:09:10 +0000283 {
284 Map result = Collections.unmodifiableMap(mutableMap);
285
Richard S. Hall7adef032007-12-14 21:55:01 +0000286 // Work around a bug in certain version of J9 where a call to
287 // Collections.unmodifiableMap().keySet().iterator() throws
288 // a NoClassDefFoundError. We try to detect this and return
Karl Pauls58248712007-11-06 21:09:10 +0000289 // the given mutableMap instead.
Richard S. Hall7adef032007-12-14 21:55:01 +0000290 try
Karl Pauls58248712007-11-06 21:09:10 +0000291 {
292 result.keySet().iterator();
293 }
294 catch (NoClassDefFoundError ex)
295 {
296 return mutableMap;
297 }
298
299 return result;
300 }
301
Richard S. Hall26b91982007-07-04 21:15:05 +0000302 //
303 // System Bundle methods.
304 //
305
306 /* package private */ BundleInfo getInfo()
307 {
308 return m_systemBundleInfo;
309 }
310
311 public BundleContext getBundleContext()
312 {
313// TODO: SECURITY - We need a security check here.
314 if (m_systemBundleInfo != null)
315 {
316 return m_systemBundleInfo.getBundleContext();
317 }
318 return null;
319 }
320
321 public long getBundleId()
322 {
323 return 0;
324 }
325
326 public URL getEntry(String name)
327 {
328 Object sm = System.getSecurityManager();
329
330 if (sm != null)
331 {
332 try
333 {
334 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
335 AdminPermission.RESOURCE));
336 }
337 catch (Exception e)
338 {
339 return null; // No permission
340 }
341 }
342
343 return getBundleEntry(this, name);
344 }
345
346 public Enumeration getEntryPaths(String path)
347 {
348 Object sm = System.getSecurityManager();
349
350 if (sm != null)
351 {
352 try
353 {
354 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
355 AdminPermission.RESOURCE));
356 }
357 catch (Exception e)
358 {
359 return null; // No permission
360 }
361 }
362
363 return getBundleEntryPaths(this, path);
364 }
365
366 public Enumeration findEntries(String path, String filePattern, boolean recurse)
367 {
368 Object sm = System.getSecurityManager();
369
370 if (sm != null)
371 {
372 try
373 {
374 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
375 AdminPermission.RESOURCE));
376 }
377 catch (Exception e)
378 {
379 return null; // No permission
380 }
381 }
382
383 return findBundleEntries(this, path, filePattern, recurse);
384 }
385
386 public Dictionary getHeaders()
387 {
388 return getHeaders(Locale.getDefault().toString());
389 }
390
391 public Dictionary getHeaders(String locale)
392 {
393 Object sm = System.getSecurityManager();
394
395 if (sm != null)
396 {
397 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
398 AdminPermission.METADATA));
399 }
400 return getBundleHeaders(this, locale);
401 }
402
403 public long getLastModified()
404 {
405 if (m_systemBundleInfo != null)
406 {
407 return m_systemBundleInfo.getLastModified();
408 }
409 return -1;
410 }
411
412 public String getLocation()
413 {
414 Object sm = System.getSecurityManager();
415
416 if (sm != null)
417 {
418 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
419 AdminPermission.METADATA));
420 }
421 return Constants.SYSTEM_BUNDLE_LOCATION;
422 }
423
424 public URL getResource(String name)
425 {
426 return getBundleResource(this, name);
427 }
428
429 public Enumeration getResources(String name) throws IOException
430 {
431 Object sm = System.getSecurityManager();
432
433 if (sm != null)
434 {
435 try
436 {
437 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
438 AdminPermission.RESOURCE));
439 }
440 catch (Exception e)
441 {
442 return null; // No permission
443 }
444 }
445
446 return getBundleResources(this, name);
447 }
448
449 public ServiceReference[] getRegisteredServices()
450 {
451 Object sm = System.getSecurityManager();
452
453 if (sm != null)
454 {
455 ServiceReference[] refs = getBundleRegisteredServices(this);
456
457 if (refs == null)
458 {
459 return refs;
460 }
461
462 List result = new ArrayList();
463
464 for (int i = 0;i < refs.length;i++)
465 {
466 String[] objectClass = (String[]) refs[i].getProperty(
467 Constants.OBJECTCLASS);
468
469 if (objectClass == null)
470 {
471 continue;
472 }
473
474 for (int j = 0;j < objectClass.length;j++)
475 {
476 try
477 {
478 ((SecurityManager) sm).checkPermission(new ServicePermission(
479 objectClass[j], ServicePermission.GET));
480
481 result.add(refs[i]);
482
483 break;
484 }
485 catch (Exception ex)
486 {
487 // Silently ignore.
488 }
489 }
490 }
491
492 if (result.isEmpty())
493 {
494 return null;
495 }
496
497 return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
498 }
499 else
500 {
501 return getBundleRegisteredServices(this);
502 }
503 }
504
505 public ServiceReference[] getServicesInUse()
506 {
507 Object sm = System.getSecurityManager();
508
509 if (sm != null)
510 {
511 ServiceReference[] refs = getBundleServicesInUse(this);
512
513 if (refs == null)
514 {
515 return refs;
516 }
517
518 List result = new ArrayList();
519
520 for (int i = 0;i < refs.length;i++)
521 {
522 String[] objectClass = (String[]) refs[i].getProperty(
523 Constants.OBJECTCLASS);
524
525 if (objectClass == null)
526 {
527 continue;
528 }
529
530 for (int j = 0;j < objectClass.length;j++)
531 {
532 try
533 {
534 ((SecurityManager) sm).checkPermission(new ServicePermission(
535 objectClass[j], ServicePermission.GET));
536
537 result.add(refs[i]);
538
539 break;
540 }
541 catch (Exception e)
542 {
543 // Silently ignore.
544 }
545 }
546 }
547
548 if (result.isEmpty())
549 {
550 return null;
551 }
552
553 return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
554 }
555
556 return getBundleServicesInUse(this);
557 }
558
559 public int getState()
560 {
561 return m_systemBundleInfo.getState();
562 }
563
564 public String getSymbolicName()
565 {
Richard S. Hall9802e3f2008-07-07 01:37:22 +0000566 return Constants.SYSTEM_BUNDLE_SYMBOLICNAME;
Richard S. Hall26b91982007-07-04 21:15:05 +0000567 }
568
569 public boolean hasPermission(Object obj)
570 {
571 return true;
572 }
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000573
Karl Pauls28636dc2008-02-03 21:32:48 +0000574 Object getSignerMatcher()
575 {
576 return null;
577 }
Richard S. Hall26b91982007-07-04 21:15:05 +0000578
579 public Class loadClass(String name) throws ClassNotFoundException
580 {
581 Object sm = System.getSecurityManager();
582
583 if (sm != null)
584 {
585 try
586 {
587 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
588 AdminPermission.CLASS));
589 }
590 catch (Exception e)
591 {
592 throw new ClassNotFoundException("No permission.", e);
593 }
594 }
595
596 return loadBundleClass(this, name);
597 }
598
599 public synchronized void start() throws BundleException
600 {
601 // The system bundle is only started once and it
602 // is started by the framework.
603 if (getState() == Bundle.ACTIVE)
604 {
605 return;
606 }
607 else if (m_systemBundleInfo.getState() != Bundle.INSTALLED)
608 {
609 throw new IllegalStateException("Invalid framework state: " + m_systemBundleInfo.getState());
610 }
611
612 // The framework is now in its startup sequence.
613 m_systemBundleInfo.setState(Bundle.STARTING);
614
615 // Create default bundle stream handler.
616 m_bundleStreamHandler = new URLHandlersBundleStreamHandler(this);
617
618 // Create service registry.
619 m_registry = new ServiceRegistry(m_logger);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000620 // Add a listener to the service registry; this is
621 // used to distribute service registry events to
622 // service listeners.
623 m_registry.addServiceListener(new ServiceListener() {
624 public void serviceChanged(ServiceEvent event)
625 {
626 fireServiceEvent(event);
627 }
628 });
629
Richard S. Hall930fecc2005-08-16 18:33:34 +0000630 // Create search policy for module loader.
Richard S. Hall471e3e62007-07-11 19:25:33 +0000631 m_policyCore = new R4SearchPolicyCore(m_logger, m_configMap);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000632
633 // Add a resolver listener to the search policy
634 // so that we will be notified when modules are resolved
635 // in order to update the bundle state.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000636 m_policyCore.addResolverListener(new ResolveListener() {
Richard S. Hall930fecc2005-08-16 18:33:34 +0000637 public void moduleResolved(ModuleEvent event)
638 {
Richard S. Hall26b91982007-07-04 21:15:05 +0000639 FelixBundle bundle = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +0000640 try
641 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000642 long id = Util.getBundleIdFromModuleId(
Richard S. Hall930fecc2005-08-16 18:33:34 +0000643 event.getModule().getId());
Richard S. Hall26b91982007-07-04 21:15:05 +0000644 if (id > 0)
Richard S. Hall930fecc2005-08-16 18:33:34 +0000645 {
646 // Update the bundle's state to resolved when the
647 // current module is resolved; just ignore resolve
648 // events for older revisions since this only occurs
649 // when an update is done on an unresolved bundle
650 // and there was no refresh performed.
Richard S. Hall26b91982007-07-04 21:15:05 +0000651 bundle = (FelixBundle) getBundle(id);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000652
653 // Lock the bundle first.
654 try
655 {
656 acquireBundleLock(bundle);
657 if (bundle.getInfo().getCurrentModule() == event.getModule())
658 {
Richard S. Hall682e33f2007-09-30 16:52:34 +0000659 if (bundle.getInfo().getState() != Bundle.INSTALLED)
660 {
661 m_logger.log(
662 Logger.LOG_WARNING,
663 "Received a resolve event for a bundle that has already been resolved.");
664 }
665 else
666 {
667 bundle.getInfo().setState(Bundle.RESOLVED);
668 fireBundleEvent(BundleEvent.RESOLVED, bundle);
669 }
Richard S. Hall930fecc2005-08-16 18:33:34 +0000670 }
671 }
Richard S. Hall930fecc2005-08-16 18:33:34 +0000672 finally
673 {
674 releaseBundleLock(bundle);
675 }
676 }
677 }
678 catch (NumberFormatException ex)
679 {
680 // Ignore.
681 }
682 }
683
684 public void moduleUnresolved(ModuleEvent event)
685 {
686 // We can ignore this, because the only time it
687 // should happen is when a refresh occurs. The
688 // refresh operation resets the bundle's state
689 // by calling BundleInfo.reset(), thus it is not
690 // necessary for us to reset the bundle's state
691 // here.
692 }
693 });
694
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000695 m_policyCore.setModuleFactory(m_factory);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000696
Richard S. Hall92770632006-07-24 10:18:52 +0000697 // Initialize event dispatcher.
Felix Meschbergercf783012007-06-29 14:47:39 +0000698 m_dispatcher = EventDispatcher.start(m_logger);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000699
Richard S. Hall7adef032007-12-14 21:55:01 +0000700 // Reload the cached bundles bundles before creating and starting
701 // the system bundle, since we want all cached bundles to be reloaded
702 // when we activate the system bundle and any subsequent custom
703 // framework activators passed into the framework constructor.
Richard S. Hall04bdbb12006-03-15 14:26:15 +0000704 BundleArchive[] archives = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +0000705
706 // First get cached bundle identifiers.
707 try
708 {
709 archives = m_cache.getArchives();
710 }
711 catch (Exception ex)
712 {
713 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000714 Logger.LOG_ERROR,
Richard S. Halle60d8782007-08-17 20:10:27 +0000715 "Unable to list saved bundles.",
716 ex);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000717 archives = null;
718 }
719
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000720 // create the system bundle that is responsible for providing specific
Karl Pauls74d48dc2008-01-16 19:39:23 +0000721 // container related services.
722 IContentLoader cl = m_extensionManager;
723 cl.setSearchPolicy(
724 new R4SearchPolicy(
725 m_policyCore, m_systemBundleInfo.getCurrentModule()));
726 m_factory.setContentLoader(
727 m_systemBundleInfo.getCurrentModule(),
728 cl);
Karl Pauls74d48dc2008-01-16 19:39:23 +0000729
Karl Pauls020dc142008-03-05 13:10:37 +0000730 try
731 {
732 addSecurity(this);
733 }
734 catch (Exception e)
735 {
736 // This should not happen
737 }
Karl Pauls28636dc2008-02-03 21:32:48 +0000738
739 // Note: we need this ordering to launch:
740 // 1) create all stuff of the system bundle (extension manager needs it)
741 // 2) install all bundles from cache (will start extension bundles)
742 // 3) start the system bundle (will start custom activators)
743 // 4) start the other bundles via the start level
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000744 // it is important to keep this order because bundles are installed
745 // from added activators in step 3 and extension bundles are started
746 // in 2 and need the stuff from 1.
Karl Pauls74d48dc2008-01-16 19:39:23 +0000747 m_installedBundleMap.put(
748 m_systemBundleInfo.getLocation(), this);
Karl Paulsa7e36b82008-04-13 19:09:20 +0000749 m_installedBundleIndex.put(new Long(0), this);
Karl Pauls28636dc2008-02-03 21:32:48 +0000750
751 // Create system bundle activator.
752 m_systemBundleInfo.setActivator(new SystemBundleActivator());
753
754 // Create the bundle context for the system bundle and
755 // then activate it.
756 m_systemBundleInfo.setBundleContext(
757 new BundleContextImpl(m_logger, this, this));
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000758
Richard S. Hall26b91982007-07-04 21:15:05 +0000759 FelixBundle bundle = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +0000760
761 // Now install all cached bundles.
762 for (int i = 0; (archives != null) && (i < archives.length); i++)
763 {
Richard S. Hall930fecc2005-08-16 18:33:34 +0000764 try
765 {
Richard S. Halle60d8782007-08-17 20:10:27 +0000766 // Keep track of the max bundle ID currently in use since we
767 // will need to use this as our next bundle ID value if the
768 // persisted value cannot be read.
Richard S. Hall7c9da3d2006-02-24 20:09:28 +0000769 m_nextId = Math.max(m_nextId, archives[i].getId() + 1);
770
Richard S. Hall930fecc2005-08-16 18:33:34 +0000771 // It is possible that a bundle in the cache was previously
772 // uninstalled, but not completely deleted (perhaps because
773 // of a crash or a locked file), so if we see an archive
774 // with an UNINSTALLED persistent state, then try to remove
775 // it now.
776 if (archives[i].getPersistentState() == Bundle.UNINSTALLED)
777 {
778 m_cache.remove(archives[i]);
779 }
780 // Otherwise re-install the cached bundle.
781 else
782 {
783 // Install the cached bundle.
Richard S. Hall26b91982007-07-04 21:15:05 +0000784 bundle = (FelixBundle) installBundle(
Richard S. Hall930fecc2005-08-16 18:33:34 +0000785 archives[i].getId(), archives[i].getLocation(), null);
786 }
787 }
788 catch (Exception ex)
789 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +0000790ex.printStackTrace();
Richard S. Hallfaa3d612007-10-24 14:18:17 +0000791 fireFrameworkEvent(FrameworkEvent.ERROR, this, ex);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000792 try
793 {
794 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000795 Logger.LOG_ERROR,
Richard S. Hall930fecc2005-08-16 18:33:34 +0000796 "Unable to re-install " + archives[i].getLocation(),
797 ex);
798 }
799 catch (Exception ex2)
800 {
801 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +0000802 Logger.LOG_ERROR,
Richard S. Hall7c9da3d2006-02-24 20:09:28 +0000803 "Unable to re-install cached bundle.",
Richard S. Hall930fecc2005-08-16 18:33:34 +0000804 ex);
805 }
Richard S. Hall26b91982007-07-04 21:15:05 +0000806 // TODO: FRAMEWORK - Perhaps we should remove the cached bundle?
Richard S. Hall930fecc2005-08-16 18:33:34 +0000807 }
808 }
809
Richard S. Halle60d8782007-08-17 20:10:27 +0000810 // Now that we have loaded all cached bundles and have determined the
811 // max bundle ID of cached bundles, we need to try to load the next
812 // bundle ID from persistent storage. In case of failure, we should
813 // keep the max value.
814 m_nextId = Math.max(m_nextId, loadNextId());
Karl Paulsad142d22007-09-16 19:53:22 +0000815
Richard S. Hall930fecc2005-08-16 18:33:34 +0000816 // Get the framework's default start level.
817 int startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
Richard S. Hall471e3e62007-07-11 19:25:33 +0000818 String s = (String) m_configMap.get(FelixConstants.FRAMEWORK_STARTLEVEL_PROP);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000819 if (s != null)
820 {
821 try
822 {
823 startLevel = Integer.parseInt(s);
824 }
825 catch (NumberFormatException ex)
826 {
827 startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
828 }
829 }
830
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000831 // Now that the cached bundles are reloaded,
Karl Pauls74d48dc2008-01-16 19:39:23 +0000832 // activating all custom framework activators.
Richard S. Hall7adef032007-12-14 21:55:01 +0000833 try
834 {
Richard S. Hall7adef032007-12-14 21:55:01 +0000835 // Manually resolve the System Bundle, which will cause its
836 // state to be set to RESOLVED.
837 try
838 {
839 m_policyCore.resolve(m_systemBundleInfo.getCurrentModule());
840 }
841 catch (ResolveException ex)
842 {
843 // This should never happen.
844 throw new BundleException(
Richard S. Hall9802e3f2008-07-07 01:37:22 +0000845 "Unresolved constraint in System Bundle:"
Richard S. Hall7adef032007-12-14 21:55:01 +0000846 + ex.getRequirement());
847 }
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000848
849 Felix.m_secureAction.startActivator(m_systemBundleInfo.getActivator(),
Karl Pauls74d48dc2008-01-16 19:39:23 +0000850 m_systemBundleInfo.getBundleContext());
Richard S. Hall7adef032007-12-14 21:55:01 +0000851 }
852 catch (Throwable ex)
853 {
854 m_factory = null;
855 EventDispatcher.shutdown();
856 m_logger.log(Logger.LOG_ERROR, "Unable to start system bundle.", ex);
857 throw new RuntimeException("Unable to start system bundle.");
858 }
859
860 // Now that the system bundle is successfully created we can give
861 // its bundle context to the logger so that it can track log services.
862 m_logger.setSystemBundleContext(m_systemBundleInfo.getBundleContext());
Richard S. Hall930fecc2005-08-16 18:33:34 +0000863
Richard S. Hall17897152006-03-02 13:43:09 +0000864 // Set the start level using the start level service;
865 // this ensures that all start level requests are
866 // serialized.
Richard S. Hall17897152006-03-02 13:43:09 +0000867 try
868 {
869 StartLevel sl = (StartLevel) getService(
Richard S. Hall2846a2b2008-06-01 03:08:17 +0000870 getBundle(0),getServiceReferences((FelixBundle) getBundle(0),
Karl Pauls74d48dc2008-01-16 19:39:23 +0000871 StartLevel.class.getName(), null, true)[0]);
Richard S. Halla11f34d2006-10-31 19:39:03 +0000872 if (sl instanceof StartLevelImpl)
873 {
874 ((StartLevelImpl) sl).setStartLevelAndWait(startLevel);
875 }
876 else
877 {
878 sl.setStartLevel(startLevel);
879 }
Richard S. Hall17897152006-03-02 13:43:09 +0000880 }
881 catch (InvalidSyntaxException ex)
882 {
883 // Should never happen.
884 }
Richard S. Hall930fecc2005-08-16 18:33:34 +0000885
886 // The framework is now running.
Richard S. Hall26b91982007-07-04 21:15:05 +0000887 m_systemBundleInfo.setState(Bundle.ACTIVE);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000888
889 // Fire started event for system bundle.
Richard S. Hall26b91982007-07-04 21:15:05 +0000890 fireBundleEvent(BundleEvent.STARTED, this);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000891
892 // Send a framework event to indicate the framework has started.
Richard S. Hall26b91982007-07-04 21:15:05 +0000893 fireFrameworkEvent(FrameworkEvent.STARTED, this, null);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000894 }
895
Richard S. Hall23311f22008-08-01 19:32:10 +0000896 public void start(int options) throws BundleException
897 {
898 throw new UnsupportedOperationException("This feature has not yet been implemented.");
899 }
900
Richard S. Hall930fecc2005-08-16 18:33:34 +0000901 /**
902 * This method cleanly shuts down the framework, it must be called at the
903 * end of a session in order to shutdown all active bundles.
904 **/
Richard S. Hall26b91982007-07-04 21:15:05 +0000905 public void stop() throws BundleException
906 {
907 Object sm = System.getSecurityManager();
908
909 if (sm != null)
910 {
911 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
912 AdminPermission.EXECUTE));
913 }
914
915 stopBundle(this, true);
916 }
917
Richard S. Hall23311f22008-08-01 19:32:10 +0000918 public void stop(int options) throws BundleException
919 {
920 throw new UnsupportedOperationException("This feature has not yet been implemented.");
921 }
922
Richard S. Hall26b91982007-07-04 21:15:05 +0000923 public void stopAndWait()
Richard S. Hall930fecc2005-08-16 18:33:34 +0000924 {
Richard S. Hallfe87d662007-05-31 20:07:11 +0000925 // Shut the framework down by calling stop() on the system bundle.
926 // Since stop() on the system bundle will return immediately, we
927 // will synchronize on the framework instance so we can use it to
928 // be notified when the shutdown is complete.
929 synchronized (this)
Richard S. Hall930fecc2005-08-16 18:33:34 +0000930 {
Richard S. Hall26b91982007-07-04 21:15:05 +0000931 if (m_systemBundleInfo.getState() == Bundle.ACTIVE)
Richard S. Hallfe87d662007-05-31 20:07:11 +0000932 {
933 try
934 {
935 getBundle(0).stop();
936 }
937 catch (BundleException ex)
938 {
Richard S. Hallfaa3d612007-10-24 14:18:17 +0000939 fireFrameworkEvent(FrameworkEvent.ERROR, this, ex);
Richard S. Hallfe87d662007-05-31 20:07:11 +0000940 m_logger.log(
941 Logger.LOG_ERROR,
942 "Error stopping system bundle.",
943 ex);
944 }
945 }
Richard S. Hall930fecc2005-08-16 18:33:34 +0000946
Richard S. Hall26b91982007-07-04 21:15:05 +0000947 while (m_systemBundleInfo.getState() != Bundle.UNINSTALLED)
Richard S. Hallfe87d662007-05-31 20:07:11 +0000948 {
949 try
950 {
951 wait();
952 }
953 catch (InterruptedException ex)
954 {
955 // Keep waiting if necessary.
956 }
957 }
Richard S. Hall5eeb1442006-11-07 07:51:24 +0000958 }
959 }
Karl Pauls49400ec2007-02-12 23:49:43 +0000960
Richard S. Hall26b91982007-07-04 21:15:05 +0000961 public void uninstall() throws BundleException
Richard S. Hall5eeb1442006-11-07 07:51:24 +0000962 {
Richard S. Hall26b91982007-07-04 21:15:05 +0000963 throw new BundleException("Cannot uninstall the system bundle.");
Richard S. Halld2d8f9a2007-06-01 13:47:29 +0000964 }
Richard S. Hallfe87d662007-05-31 20:07:11 +0000965
Richard S. Hall26b91982007-07-04 21:15:05 +0000966 public void update() throws BundleException
Richard S. Halld2d8f9a2007-06-01 13:47:29 +0000967 {
Richard S. Hall26b91982007-07-04 21:15:05 +0000968 update(null);
Richard S. Hall930fecc2005-08-16 18:33:34 +0000969 }
970
Richard S. Hall26b91982007-07-04 21:15:05 +0000971 public void update(InputStream is) throws BundleException
Richard S. Hall930fecc2005-08-16 18:33:34 +0000972 {
Richard S. Hall26b91982007-07-04 21:15:05 +0000973 Object sm = System.getSecurityManager();
974
975 if (sm != null)
976 {
977 ((SecurityManager) sm).checkPermission(new AdminPermission(this,
978 AdminPermission.EXECUTE));
979 }
980
981 // TODO: FRAMEWORK - This is supposed to stop and then restart the framework.
982 throw new BundleException("System bundle update not implemented yet.");
983 }
984
985 public String toString()
986 {
987 return getSymbolicName() + " [" + getBundleId() +"]";
Richard S. Hall930fecc2005-08-16 18:33:34 +0000988 }
989
990 /**
991 * Returns the active start level of the framework; this method
992 * implements functionality for the Start Level service.
993 * @return The active start level of the framework.
994 **/
995 protected int getStartLevel()
996 {
997 return m_activeStartLevel;
998 }
999
1000 /**
1001 * Implements the functionality of the <tt>setStartLevel()</tt>
1002 * method for the StartLevel service, but does not do the security or
1003 * parameter check. The security and parameter check are done in the
1004 * StartLevel service implementation because this method is called on
1005 * a separate thread and the caller's thread would already be gone if
Richard S. Hall17897152006-03-02 13:43:09 +00001006 * we did the checks in this method. This method should not be called
1007 * directly.
Richard S. Hall930fecc2005-08-16 18:33:34 +00001008 * @param requestedLevel The new start level of the framework.
1009 **/
Richard S. Hall441c7152006-02-17 11:07:10 +00001010 protected void setFrameworkStartLevel(int requestedLevel)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001011 {
Richard S. Hall17897152006-03-02 13:43:09 +00001012 Bundle[] bundles = null;
1013
1014 // Synchronization for changing the start level is rather loose.
1015 // The install lock is grabbed initially to atomically change the
1016 // framework's start level and to grab a sorted snapshot of the
1017 // currently installed bundles, but then this lock is freed immediately.
1018 // No locks are held while processing the currently installed bundles
1019 // for starting/stopping based on the new start level. The only locking
1020 // that occurs is for individual bundles when startBundle()/stopBundle()
1021 // is called, but this locking is done in the respective method.
1022 //
1023 // This approach does mean that it is possible for a for individual
1024 // bundle states to change during this operation. For example, bundle
1025 // start levels can be changed or bundles can be uninstalled. If a
1026 // bundle's start level changes, then it is possible for it to be
1027 // processed out of order. Uninstalled bundles are just logged and
1028 // ignored. I had a bit of discussion with Peter Kriens about these
1029 // issues and he felt they were consistent with the spec, which
1030 // intended Start Level to have some leeway.
1031 //
1032 // Calls to this method are only made by the start level thread, which
1033 // serializes framework start level changes. Thus, it is not possible
1034 // for two requests to change the framework's start level to interfere
1035 // with each other.
1036
1037 synchronized (m_installedBundleLock_Priority2)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001038 {
Richard S. Hall17897152006-03-02 13:43:09 +00001039 // Determine if we are lowering or raising the
1040 // active start level.
1041 boolean lowering = (requestedLevel < m_activeStartLevel);
Karl Pauls836bb402006-08-24 12:39:46 +00001042
Richard S. Hall17897152006-03-02 13:43:09 +00001043 // Record new start level.
1044 m_activeStartLevel = requestedLevel;
Karl Pauls836bb402006-08-24 12:39:46 +00001045
Richard S. Hall17897152006-03-02 13:43:09 +00001046 // Get a snapshot of all installed bundles.
1047 bundles = getBundles();
1048
1049 // Sort bundle array by start level either ascending or
1050 // descending depending on whether the start level is being
1051 // lowered or raised to that the bundles can be efficiently
Richard S. Hall5259e3e2006-07-14 18:55:59 +00001052 // processed in order. Within a start level sort by bundle ID.
Richard S. Hall17897152006-03-02 13:43:09 +00001053 Comparator comparator = null;
1054 if (lowering)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001055 {
Richard S. Hall17897152006-03-02 13:43:09 +00001056 // Sort descending to stop highest start level first.
1057 comparator = new Comparator() {
1058 public int compare(Object o1, Object o2)
Richard S. Hall441c7152006-02-17 11:07:10 +00001059 {
Richard S. Hall26b91982007-07-04 21:15:05 +00001060 FelixBundle b1 = (FelixBundle) o1;
1061 FelixBundle b2 = (FelixBundle) o2;
Richard S. Hall17897152006-03-02 13:43:09 +00001062 if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
1063 < b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
1064 {
1065 return 1;
1066 }
1067 else if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
1068 > b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
1069 {
1070 return -1;
1071 }
Karl Paulsa7e36b82008-04-13 19:09:20 +00001072 else if (b1.getBundleId() < b2.getBundleId())
Richard S. Hall5259e3e2006-07-14 18:55:59 +00001073 {
1074 return 1;
1075 }
1076 return -1;
Richard S. Hall441c7152006-02-17 11:07:10 +00001077 }
Richard S. Hall17897152006-03-02 13:43:09 +00001078 };
1079 }
1080 else
1081 {
1082 // Sort ascending to start lowest start level first.
1083 comparator = new Comparator() {
1084 public int compare(Object o1, Object o2)
Richard S. Hall441c7152006-02-17 11:07:10 +00001085 {
Richard S. Hall26b91982007-07-04 21:15:05 +00001086 FelixBundle b1 = (FelixBundle) o1;
1087 FelixBundle b2 = (FelixBundle) o2;
Richard S. Hall17897152006-03-02 13:43:09 +00001088 if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
1089 > b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
Richard S. Hall441c7152006-02-17 11:07:10 +00001090 {
Richard S. Hall17897152006-03-02 13:43:09 +00001091 return 1;
Richard S. Hall441c7152006-02-17 11:07:10 +00001092 }
Richard S. Hall17897152006-03-02 13:43:09 +00001093 else if (b1.getInfo().getStartLevel(getInitialBundleStartLevel())
1094 < b2.getInfo().getStartLevel(getInitialBundleStartLevel()))
Richard S. Hall441c7152006-02-17 11:07:10 +00001095 {
Richard S. Hall17897152006-03-02 13:43:09 +00001096 return -1;
Richard S. Hall441c7152006-02-17 11:07:10 +00001097 }
Karl Paulsa7e36b82008-04-13 19:09:20 +00001098 else if (b1.getBundleId() > b2.getBundleId())
Richard S. Hall5259e3e2006-07-14 18:55:59 +00001099 {
1100 return 1;
1101 }
1102 return -1;
Richard S. Hall17897152006-03-02 13:43:09 +00001103 }
1104 };
1105 }
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001106
Richard S. Hall17897152006-03-02 13:43:09 +00001107 Arrays.sort(bundles, comparator);
1108 }
1109
1110 // Stop or start the bundles according to the start level.
1111 for (int i = 0; (bundles != null) && (i < bundles.length); i++)
1112 {
Richard S. Hall26b91982007-07-04 21:15:05 +00001113 FelixBundle impl = (FelixBundle) bundles[i];
Richard S. Hall17897152006-03-02 13:43:09 +00001114
1115 // Ignore the system bundle, since its start() and
1116 // stop() methods get called explicitly in Felix.start()
1117 // and Felix.shutdown(), respectively.
1118 if (impl.getInfo().getBundleId() == 0)
1119 {
1120 continue;
1121 }
1122
1123 // Lock the current bundle.
1124 acquireBundleLock(impl);
1125
1126 try
1127 {
1128 // Start the bundle if necessary.
1129 if ((impl.getInfo().getPersistentState() == Bundle.ACTIVE) &&
1130 (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
1131 <= m_activeStartLevel))
1132 {
1133 try
1134 {
1135 startBundle(impl, false);
1136 }
1137 catch (Throwable th)
1138 {
1139 fireFrameworkEvent(FrameworkEvent.ERROR, impl, th);
1140 m_logger.log(
1141 Logger.LOG_ERROR,
1142 "Error starting " + impl.getInfo().getLocation(), th);
Richard S. Hall441c7152006-02-17 11:07:10 +00001143 }
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001144 }
Richard S. Hall17897152006-03-02 13:43:09 +00001145 // Stop the bundle if necessary.
1146 else if (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
1147 > m_activeStartLevel)
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001148 {
Richard S. Hall17897152006-03-02 13:43:09 +00001149 try
Richard S. Hall441c7152006-02-17 11:07:10 +00001150 {
Richard S. Hall17897152006-03-02 13:43:09 +00001151 stopBundle(impl, false);
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001152 }
Richard S. Hall17897152006-03-02 13:43:09 +00001153 catch (Throwable th)
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001154 {
Richard S. Hall17897152006-03-02 13:43:09 +00001155 fireFrameworkEvent(FrameworkEvent.ERROR, impl, th);
1156 m_logger.log(
1157 Logger.LOG_ERROR,
1158 "Error stopping " + impl.getInfo().getLocation(), th);
Richard S. Hall441c7152006-02-17 11:07:10 +00001159 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001160 }
Richard S. Hall17897152006-03-02 13:43:09 +00001161 }
1162 finally
1163 {
1164 // Always release bundle lock.
1165 releaseBundleLock(impl);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001166 }
Richard S. Hall9b2a3292008-03-01 23:49:01 +00001167 // Hint to GC to collect bundle; not sure why this
1168 // is necessary, but it appears to help.
1169 bundles[i] = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001170 }
1171
Richard S. Hall26b91982007-07-04 21:15:05 +00001172 if (m_systemBundleInfo.getState() == Bundle.ACTIVE)
Richard S. Halla11f34d2006-10-31 19:39:03 +00001173 {
Richard S. Hallfaa3d612007-10-24 14:18:17 +00001174 fireFrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, this, null);
Richard S. Halla11f34d2006-10-31 19:39:03 +00001175 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001176 }
1177
1178 /**
1179 * Returns the start level into which newly installed bundles will
1180 * be placed by default; this method implements functionality for
1181 * the Start Level service.
1182 * @return The default start level for newly installed bundles.
1183 **/
1184 protected int getInitialBundleStartLevel()
1185 {
Richard S. Hall471e3e62007-07-11 19:25:33 +00001186 String s = (String) m_configMap.get(FelixConstants.BUNDLE_STARTLEVEL_PROP);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001187
1188 if (s != null)
1189 {
1190 try
1191 {
1192 int i = Integer.parseInt(s);
1193 return (i > 0) ? i : FelixConstants.BUNDLE_DEFAULT_STARTLEVEL;
1194 }
1195 catch (NumberFormatException ex)
1196 {
1197 // Ignore and return the default value.
1198 }
1199 }
1200 return FelixConstants.BUNDLE_DEFAULT_STARTLEVEL;
1201 }
1202
1203 /**
1204 * Sets the default start level into which newly installed bundles
1205 * will be placed; this method implements functionality for the Start
1206 * Level service.
1207 * @param startLevel The new default start level for newly installed
1208 * bundles.
1209 * @throws java.lang.IllegalArgumentException If the specified start
1210 * level is not greater than zero.
1211 * @throws java.security.SecurityException If the caller does not
1212 * have <tt>AdminPermission</tt>.
1213 **/
1214 protected void setInitialBundleStartLevel(int startLevel)
1215 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001216 if (startLevel <= 0)
1217 {
1218 throw new IllegalArgumentException(
1219 "Initial start level must be greater than zero.");
1220 }
1221
Richard S. Hall471e3e62007-07-11 19:25:33 +00001222 m_configMutableMap.put(
Richard S. Hall930fecc2005-08-16 18:33:34 +00001223 FelixConstants.BUNDLE_STARTLEVEL_PROP, Integer.toString(startLevel));
1224 }
1225
1226 /**
1227 * Returns the start level for the specified bundle; this method
1228 * implements functionality for the Start Level service.
1229 * @param bundle The bundle to examine.
1230 * @return The start level of the specified bundle.
1231 * @throws java.lang.IllegalArgumentException If the specified
1232 * bundle has been uninstalled.
1233 **/
1234 protected int getBundleStartLevel(Bundle bundle)
1235 {
1236 if (bundle.getState() == Bundle.UNINSTALLED)
1237 {
1238 throw new IllegalArgumentException("Bundle is uninstalled.");
1239 }
1240
Richard S. Hall26b91982007-07-04 21:15:05 +00001241 return ((FelixBundle) bundle).getInfo().getStartLevel(getInitialBundleStartLevel());
Richard S. Hall930fecc2005-08-16 18:33:34 +00001242 }
1243
1244 /**
1245 * Sets the start level of the specified bundle; this method
1246 * implements functionality for the Start Level service.
1247 * @param bundle The bundle whose start level is to be modified.
1248 * @param startLevel The new start level of the specified bundle.
1249 * @throws java.lang.IllegalArgumentException If the specified
1250 * bundle is the system bundle or if the bundle has been
1251 * uninstalled.
1252 * @throws java.security.SecurityException If the caller does not
1253 * have <tt>AdminPermission</tt>.
1254 **/
1255 protected void setBundleStartLevel(Bundle bundle, int startLevel)
1256 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001257 // Acquire bundle lock.
Richard S. Hall26b91982007-07-04 21:15:05 +00001258 acquireBundleLock((FelixBundle) bundle);
Karl Pauls836bb402006-08-24 12:39:46 +00001259
Richard S. Hall930fecc2005-08-16 18:33:34 +00001260 Throwable rethrow = null;
1261
1262 try
1263 {
1264 if (bundle.getState() == Bundle.UNINSTALLED)
1265 {
1266 throw new IllegalArgumentException("Bundle is uninstalled.");
1267 }
1268
1269 if (startLevel >= 1)
1270 {
Richard S. Hall26b91982007-07-04 21:15:05 +00001271 FelixBundle impl = (FelixBundle) bundle;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001272 impl.getInfo().setStartLevel(startLevel);
Karl Pauls836bb402006-08-24 12:39:46 +00001273
Richard S. Hall930fecc2005-08-16 18:33:34 +00001274 try
1275 {
1276 // Start the bundle if necessary.
1277 if ((impl.getInfo().getPersistentState() == Bundle.ACTIVE) &&
1278 (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
1279 <= m_activeStartLevel))
1280 {
1281 startBundle(impl, false);
1282 }
1283 // Stop the bundle if necessary.
1284 else if (impl.getInfo().getStartLevel(getInitialBundleStartLevel())
1285 > m_activeStartLevel)
1286 {
1287 stopBundle(impl, false);
1288 }
1289 }
1290 catch (Throwable th)
1291 {
1292 rethrow = th;
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001293 m_logger.log(Logger.LOG_ERROR, "Error starting/stopping bundle.", th);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001294 }
1295 }
1296 else
1297 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001298 m_logger.log(Logger.LOG_WARNING, "Bundle start level must be greater than zero.");
Richard S. Hall930fecc2005-08-16 18:33:34 +00001299 }
1300 }
1301 finally
1302 {
1303 // Always release bundle lock.
Richard S. Hall26b91982007-07-04 21:15:05 +00001304 releaseBundleLock((FelixBundle) bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001305 }
1306
1307 if (rethrow != null)
1308 {
1309 fireFrameworkEvent(FrameworkEvent.ERROR, bundle, rethrow);
1310 }
1311 }
1312
1313 /**
1314 * Returns whether a bundle is persistently started; this is an
1315 * method implementation for the Start Level service.
1316 * @param bundle The bundle to examine.
1317 * @return <tt>true</tt> if the bundle is marked as persistently
1318 * started, <tt>false</tt> otherwise.
1319 * @throws java.lang.IllegalArgumentException If the specified
1320 * bundle has been uninstalled.
1321 **/
1322 protected boolean isBundlePersistentlyStarted(Bundle bundle)
1323 {
1324 if (bundle.getState() == Bundle.UNINSTALLED)
1325 {
1326 throw new IllegalArgumentException("Bundle is uninstalled.");
1327 }
1328
Richard S. Hall26b91982007-07-04 21:15:05 +00001329 return (((FelixBundle) bundle).getInfo().getPersistentState() == Bundle.ACTIVE);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001330 }
1331
1332 //
1333 // Implementation of Bundle interface methods.
1334 //
1335
1336 /**
Richard S. Hall05fd75e2007-01-18 01:36:45 +00001337 * Get bundle headers and resolve any localized strings from resource bundles.
1338 * @param bundle
1339 * @param locale
1340 * @return localized bundle headers dictionary.
1341 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001342 protected Dictionary getBundleHeaders(FelixBundle bundle, String locale)
Richard S. Hall05fd75e2007-01-18 01:36:45 +00001343 {
1344 return new MapToDictionary(bundle.getInfo().getCurrentLocalizedHeader(locale));
Richard S. Hall930fecc2005-08-16 18:33:34 +00001345 }
1346
1347 /**
1348 * Implementation for Bundle.getLocation().
1349 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001350 protected String getBundleLocation(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001351 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001352 return bundle.getInfo().getLocation();
1353 }
1354
1355 /**
1356 * Implementation for Bundle.getResource().
1357 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001358 protected URL getBundleResource(FelixBundle bundle, String name)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001359 {
1360 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1361 {
1362 throw new IllegalStateException("The bundle is uninstalled.");
1363 }
Richard S. Hall001cc302006-02-03 15:03:24 +00001364 return bundle.getInfo().getCurrentModule().getResource(name);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001365 }
1366
Richard S. Hallbcbf83e2006-02-05 13:28:26 +00001367 /**
Richard S. Hall864dc662006-09-26 16:53:29 +00001368 * Implementation for Bundle.getResources().
1369 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001370 protected Enumeration getBundleResources(FelixBundle bundle, String name)
Richard S. Hall864dc662006-09-26 16:53:29 +00001371 {
1372 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1373 {
1374 throw new IllegalStateException("The bundle is uninstalled.");
1375 }
1376 return bundle.getInfo().getCurrentModule().getResources(name);
1377 }
1378
1379 /**
Richard S. Hallbcbf83e2006-02-05 13:28:26 +00001380 * Implementation for Bundle.getEntry().
1381 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001382 protected URL getBundleEntry(FelixBundle bundle, String name)
Richard S. Hallbcbf83e2006-02-05 13:28:26 +00001383 {
1384 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1385 {
1386 throw new IllegalStateException("The bundle is uninstalled.");
1387 }
Richard S. Hall8d861e52006-09-25 18:29:27 +00001388 return bundle.getInfo().getCurrentModule()
1389 .getContentLoader().getResourceFromContent(name);
Richard S. Hallbcbf83e2006-02-05 13:28:26 +00001390 }
1391
Richard S. Hall4f09b642006-02-06 10:59:19 +00001392 /**
1393 * Implementation for Bundle.getEntryPaths().
1394 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001395 protected Enumeration getBundleEntryPaths(FelixBundle bundle, String path)
Richard S. Hall4f09b642006-02-06 10:59:19 +00001396 {
1397 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1398 {
1399 throw new IllegalStateException("The bundle is uninstalled.");
1400 }
Richard S. Hall6fa05d02006-07-21 08:24:12 +00001401
1402 // Get the entry enumeration from the module content and
1403 // create a wrapper enumeration to filter it.
1404 Enumeration enumeration = new GetEntryPathsEnumeration(bundle, path);
1405
1406 // Return the enumeration if it has elements.
1407 return (!enumeration.hasMoreElements()) ? null : enumeration;
Richard S. Hall4f09b642006-02-06 10:59:19 +00001408 }
1409
Richard S. Hall4d2f3972006-07-20 15:58:17 +00001410 /**
1411 * Implementation for findEntries().
1412 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001413 protected Enumeration findBundleEntries(
1414 FelixBundle bundle, String path, String filePattern, boolean recurse)
Richard S. Hall4d2f3972006-07-20 15:58:17 +00001415 {
Richard S. Hall4d2f3972006-07-20 15:58:17 +00001416 // Try to resolve the bundle per the spec.
1417 resolveBundles(new Bundle[] { bundle });
1418
Richard S. Hall6fa05d02006-07-21 08:24:12 +00001419 // Get the entry enumeration from the module content and
1420 // create a wrapper enumeration to filter it.
1421 Enumeration enumeration =
1422 new FindEntriesEnumeration(bundle, path, filePattern, recurse);
Richard S. Hall4d2f3972006-07-20 15:58:17 +00001423
Richard S. Hall6fa05d02006-07-21 08:24:12 +00001424 // Return the enumeration if it has elements.
1425 return (!enumeration.hasMoreElements()) ? null : enumeration;
Richard S. Hall4d2f3972006-07-20 15:58:17 +00001426 }
1427
Richard S. Hall26b91982007-07-04 21:15:05 +00001428 protected ServiceReference[] getBundleRegisteredServices(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001429 {
1430 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1431 {
1432 throw new IllegalStateException("The bundle is uninstalled.");
1433 }
1434
1435 // Filter list of registered service references.
1436 ServiceReference[] refs = m_registry.getRegisteredServices(bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001437
Karl Paulsc19abb42006-07-21 10:23:11 +00001438 return refs;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001439 }
1440
1441 protected ServiceReference[] getBundleServicesInUse(Bundle bundle)
1442 {
1443 // Filter list of "in use" service references.
1444 ServiceReference[] refs = m_registry.getServicesInUse(bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001445
Karl Paulsc19abb42006-07-21 10:23:11 +00001446 return refs;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001447 }
1448
Richard S. Hall26b91982007-07-04 21:15:05 +00001449 protected boolean bundleHasPermission(FelixBundle bundle, Object obj)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001450 {
1451 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1452 {
1453 throw new IllegalStateException("The bundle is uninstalled.");
1454 }
1455
Richard S. Hall2cf44c92006-01-23 19:23:56 +00001456 if (System.getSecurityManager() != null)
Richard S. Hall65730962006-01-23 19:23:13 +00001457 {
1458 try
1459 {
Richard S. Halld1e3cbd2006-01-27 15:23:01 +00001460 return (obj instanceof java.security.Permission)
Karl Pauls28636dc2008-02-03 21:32:48 +00001461 ? impliesBundlePermission(
Richard S. Hall2846a2b2008-06-01 03:08:17 +00001462 (BundleProtectionDomain)
1463 bundle.getInfo().getProtectionDomain(),
Karl Pauls28636dc2008-02-03 21:32:48 +00001464 (java.security.Permission) obj, true)
Richard S. Halld1e3cbd2006-01-27 15:23:01 +00001465 : false;
Richard S. Hall65730962006-01-23 19:23:13 +00001466 }
1467 catch (Exception ex)
1468 {
1469 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001470 Logger.LOG_WARNING,
Richard S. Hall65730962006-01-23 19:23:13 +00001471 "Exception while evaluating the permission.",
1472 ex);
Karl Pauls836bb402006-08-24 12:39:46 +00001473 return false;
Richard S. Hall65730962006-01-23 19:23:13 +00001474 }
Richard S. Halld1e3cbd2006-01-27 15:23:01 +00001475 }
Richard S. Hall65730962006-01-23 19:23:13 +00001476
Richard S. Halld1e3cbd2006-01-27 15:23:01 +00001477 return true;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001478 }
1479
1480 /**
Richard S. Hall74b97972005-11-30 15:51:41 +00001481 * Implementation for Bundle.loadClass().
1482 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001483 protected Class loadBundleClass(FelixBundle bundle, String name) throws ClassNotFoundException
Richard S. Hall74b97972005-11-30 15:51:41 +00001484 {
Richard S. Hall044cda82007-12-20 19:14:25 +00001485 if (bundle.getInfo().getState() == Bundle.UNINSTALLED)
1486 {
1487 throw new IllegalStateException("Bundle is uninstalled");
1488 }
1489 else if (bundle.getInfo().getState() == Bundle.INSTALLED)
1490 {
1491 try
1492 {
1493 _resolveBundle(bundle);
1494 }
1495 catch (BundleException ex)
1496 {
1497 // The spec says we must fire a framework error.
1498 fireFrameworkEvent(FrameworkEvent.ERROR, bundle, ex);
1499 // Then throw a class not found exception.
1500 throw new ClassNotFoundException(name);
1501 }
1502 }
Karl Paulsb6ad9922008-08-20 16:37:33 +00001503 return bundle.getInfo().getCurrentModule().getClass(name);
Richard S. Hall74b97972005-11-30 15:51:41 +00001504 }
1505
1506 /**
Richard S. Hall930fecc2005-08-16 18:33:34 +00001507 * Implementation for Bundle.start().
1508 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00001509 protected void startBundle(FelixBundle bundle, boolean record)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001510 throws BundleException
1511 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001512 // CONCURRENCY NOTE:
1513 // Starting a bundle may actually impact many bundles, since
1514 // the bundle being started my need to be resolved, which in
1515 // turn may need to resolve other bundles. Despite this fact,
1516 // we only acquire the lock for the bundle being started, because
1517 // when resolve is called on this bundle, it will eventually
1518 // call resolve on the module loader search policy, which does
Karl Pauls836bb402006-08-24 12:39:46 +00001519 // its own locking on the module factory instance. Since the
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001520 // resolve algorithm is locking the module factory instance, it
Richard S. Hall930fecc2005-08-16 18:33:34 +00001521 // is not possible for other bundles to be installed or removed,
1522 // so we don't have to worry about these possibilities.
1523 //
1524 // Further, if other bundles are started during this operation,
1525 // then either they will resolve first because they got the lock
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001526 // on the module factory or we will resolve first since we got
1527 // the lock on the module factory, so there should be no interference.
Richard S. Hall930fecc2005-08-16 18:33:34 +00001528 // If other bundles are stopped or uninstalled, this should pose
1529 // no problems, since this does not impact their resolved state.
1530 // If a refresh occurs, then the refresh algorithm ulimately has
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001531 // to acquire the module factory instance lock too before it can
Richard S. Hall930fecc2005-08-16 18:33:34 +00001532 // completely purge old modules, so it should also complete either
1533 // before or after this bundle is started. At least that's the
1534 // theory.
1535
1536 // Acquire bundle lock.
1537 acquireBundleLock(bundle);
1538
1539 try
1540 {
1541 _startBundle(bundle, record);
1542 }
1543 finally
1544 {
1545 // Release bundle lock.
1546 releaseBundleLock(bundle);
1547 }
1548 }
1549
Richard S. Hall26b91982007-07-04 21:15:05 +00001550 private void _startBundle(FelixBundle bundle, boolean record)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001551 throws BundleException
1552 {
Karl Pauls49400ec2007-02-12 23:49:43 +00001553 // The spec doesn't say whether it is possible to start an extension
1554 // We just do nothing
1555 if (bundle.getInfo().isExtension())
1556 {
1557 return;
1558 }
1559
Richard S. Hall930fecc2005-08-16 18:33:34 +00001560 // Set and save the bundle's persistent state to active
1561 // if we are supposed to record state change.
1562 if (record)
1563 {
1564 bundle.getInfo().setPersistentStateActive();
1565 }
1566
1567 // Try to start the bundle.
1568 BundleInfo info = bundle.getInfo();
1569
1570 // Ignore bundles whose persistent state is not active
1571 // or whose start level is greater than the framework's.
1572 if ((info.getPersistentState() != Bundle.ACTIVE)
1573 || (info.getStartLevel(getInitialBundleStartLevel()) > getStartLevel()))
1574 {
1575 return;
1576 }
1577
1578 switch (info.getState())
1579 {
1580 case Bundle.UNINSTALLED:
1581 throw new IllegalStateException("Cannot start an uninstalled bundle.");
1582 case Bundle.STARTING:
1583 case Bundle.STOPPING:
1584 throw new BundleException("Starting a bundle that is starting or stopping is currently not supported.");
1585 case Bundle.ACTIVE:
1586 return;
1587 case Bundle.INSTALLED:
1588 _resolveBundle(bundle);
Richard S. Halle50da252006-07-25 07:48:06 +00001589 // No break.
Richard S. Hall930fecc2005-08-16 18:33:34 +00001590 case Bundle.RESOLVED:
1591 info.setState(Bundle.STARTING);
Richard S. Halle50da252006-07-25 07:48:06 +00001592 fireBundleEvent(BundleEvent.STARTING, bundle);
1593 break;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001594 }
1595
1596 try
1597 {
Richard S. Hall2a28c8d2006-07-25 07:50:41 +00001598 // Set the bundle's context.
Richard S. Hall26b91982007-07-04 21:15:05 +00001599 info.setBundleContext(new BundleContextImpl(m_logger, this, bundle));
Richard S. Hall2a28c8d2006-07-25 07:50:41 +00001600
Richard S. Hall930fecc2005-08-16 18:33:34 +00001601 // Set the bundle's activator.
Richard S. Halle50da252006-07-25 07:48:06 +00001602 info.setActivator(createBundleActivator(bundle.getInfo()));
Richard S. Hall930fecc2005-08-16 18:33:34 +00001603
1604 // Activate the bundle if it has an activator.
1605 if (bundle.getInfo().getActivator() != null)
1606 {
Richard S. Hallfe87d662007-05-31 20:07:11 +00001607 m_secureAction.startActivator(info.getActivator(),info.getBundleContext());
Richard S. Hall930fecc2005-08-16 18:33:34 +00001608 }
1609
Richard S. Hall3c26cc02006-02-17 13:51:21 +00001610 // TODO: CONCURRENCY - Reconsider firing event outside of the
1611 // bundle lock.
Richard S. Halle50da252006-07-25 07:48:06 +00001612 info.setState(Bundle.ACTIVE);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001613 fireBundleEvent(BundleEvent.STARTED, bundle);
1614 }
1615 catch (Throwable th)
1616 {
1617 // If there was an error starting the bundle,
1618 // then reset its state to RESOLVED.
1619 info.setState(Bundle.RESOLVED);
1620
Richard S. Hall2a28c8d2006-07-25 07:50:41 +00001621 // Clean up the bundle context.
Richard S. Hallfe87d662007-05-31 20:07:11 +00001622 ((BundleContextImpl) info.getBundleContext()).invalidate();
1623 info.setBundleContext(null);
Richard S. Hall187b87a2006-07-03 09:13:18 +00001624
Richard S. Hall930fecc2005-08-16 18:33:34 +00001625 // Unregister any services offered by this bundle.
1626 m_registry.unregisterServices(bundle);
1627
1628 // Release any services being used by this bundle.
1629 m_registry.ungetServices(bundle);
1630
1631 // Remove any listeners registered by this bundle.
Richard S. Hall92770632006-07-24 10:18:52 +00001632 m_dispatcher.removeListeners(bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001633
1634 // The spec says to expect BundleException or
1635 // SecurityException, so rethrow these exceptions.
1636 if (th instanceof BundleException)
1637 {
1638 throw (BundleException) th;
1639 }
1640 else if (th instanceof SecurityException)
1641 {
1642 throw (SecurityException) th;
1643 }
Karl Pauls836bb402006-08-24 12:39:46 +00001644 else if ((System.getSecurityManager() != null) &&
Karl Paulsc19abb42006-07-21 10:23:11 +00001645 (th instanceof java.security.PrivilegedActionException))
Richard S. Hall930fecc2005-08-16 18:33:34 +00001646 {
Karl Paulsc19abb42006-07-21 10:23:11 +00001647 th = ((java.security.PrivilegedActionException) th).getException();
Richard S. Hall930fecc2005-08-16 18:33:34 +00001648 }
1649
1650 // Rethrow all other exceptions as a BundleException.
1651 throw new BundleException("Activator start error.", th);
1652 }
1653 }
1654
Richard S. Hall26b91982007-07-04 21:15:05 +00001655 protected void _resolveBundle(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001656 throws BundleException
1657 {
Karl Paulsebce0842008-03-19 17:35:58 +00001658 if (bundle.getInfo().isExtension())
1659 {
1660 return;
1661 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001662 // If a security manager is installed, then check for permission
1663 // to import the necessary packages.
1664 if (System.getSecurityManager() != null)
1665 {
Richard S. Hall2846a2b2008-06-01 03:08:17 +00001666 BundleProtectionDomain pd = (BundleProtectionDomain)
Karl Pauls758c2be2008-03-05 13:10:04 +00001667 bundle.getInfo().getProtectionDomain();
Karl Pauls836bb402006-08-24 12:39:46 +00001668
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001669 IRequirement[] imports =
1670 bundle.getInfo().getCurrentModule().getDefinition().getRequirements();
Karl Pauls836bb402006-08-24 12:39:46 +00001671
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001672/*
1673 TODO: RB - We need to fix this import check by looking at the wire
1674 associated with it, not the import since we don't know the
1675 package name associated with the import since it is a filter.
1676
1677 for (int i = 0; i < imports.length; i++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001678 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001679 if (imports[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
Karl Paulsc19abb42006-07-21 10:23:11 +00001680 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001681 PackagePermission perm = new PackagePermission(
1682 imports[i].???,
1683 PackagePermission.IMPORT);
Karl Pauls49400ec2007-02-12 23:49:43 +00001684
Karl Pauls758c2be2008-03-05 13:10:04 +00001685 if (!pd.impliesDirect(perm))
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001686 {
1687 throw new java.security.AccessControlException(
1688 "PackagePermission.IMPORT denied for import: " +
1689 imports[i].getName(), perm);
1690 }
Karl Paulsc19abb42006-07-21 10:23:11 +00001691 }
Karl Pauls836bb402006-08-24 12:39:46 +00001692 }
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001693*/
Karl Pauls836bb402006-08-24 12:39:46 +00001694 // Check export permission for all exports of the current module.
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001695 ICapability[] exports =
1696 bundle.getInfo().getCurrentModule().getDefinition().getCapabilities();
1697 for (int i = 0; i < exports.length; i++)
Karl Pauls836bb402006-08-24 12:39:46 +00001698 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001699 if (exports[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
Karl Paulsc19abb42006-07-21 10:23:11 +00001700 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001701 PackagePermission perm = new PackagePermission(
1702 (String) exports[i].getProperties().get(ICapability.PACKAGE_PROPERTY), PackagePermission.EXPORT);
Karl Pauls49400ec2007-02-12 23:49:43 +00001703
Karl Pauls758c2be2008-03-05 13:10:04 +00001704 if (!pd.impliesDirect(perm))
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001705 {
1706 throw new java.security.AccessControlException(
1707 "PackagePermission.EXPORT denied for export: " +
1708 exports[i].getProperties().get(ICapability.PACKAGE_PROPERTY), perm);
1709 }
Karl Paulsc19abb42006-07-21 10:23:11 +00001710 }
1711 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001712 }
1713
Richard S. Hall9955e902007-01-25 14:42:01 +00001714 verifyExecutionEnvironment(bundle);
Karl Pauls49400ec2007-02-12 23:49:43 +00001715
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001716 IModule module = bundle.getInfo().getCurrentModule();
Richard S. Hall930fecc2005-08-16 18:33:34 +00001717 try
1718 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001719 m_policyCore.resolve(module);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001720 }
1721 catch (ResolveException ex)
1722 {
1723 if (ex.getModule() != null)
1724 {
1725 throw new BundleException(
Richard S. Hall9802e3f2008-07-07 01:37:22 +00001726 "Unresolved constraint in bundle "
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001727 + Util.getBundleIdFromModuleId(ex.getModule().getId())
Richard S. Hallbf12bf72007-01-22 07:15:25 +00001728 + ": " + ex.getRequirement());
Richard S. Hall930fecc2005-08-16 18:33:34 +00001729 }
1730 else
1731 {
1732 throw new BundleException(ex.getMessage());
1733 }
1734 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001735 }
1736
Richard S. Hall26b91982007-07-04 21:15:05 +00001737 protected void updateBundle(FelixBundle bundle, InputStream is)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001738 throws BundleException
1739 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001740 // Acquire bundle lock.
1741 acquireBundleLock(bundle);
1742
1743 try
1744 {
1745 _updateBundle(bundle, is);
1746 }
1747 finally
1748 {
1749 // Release bundle lock.
1750 releaseBundleLock(bundle);
1751 }
1752 }
1753
Richard S. Hall26b91982007-07-04 21:15:05 +00001754 protected void _updateBundle(FelixBundle bundle, InputStream is)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001755 throws BundleException
1756 {
1757 // We guarantee to close the input stream, so put it in a
1758 // finally clause.
Karl Pauls836bb402006-08-24 12:39:46 +00001759
Richard S. Hall930fecc2005-08-16 18:33:34 +00001760 try
1761 {
1762 // Variable to indicate whether bundle is active or not.
Karl Pauls49400ec2007-02-12 23:49:43 +00001763 Throwable rethrow = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001764
1765 // Cannot update an uninstalled bundle.
1766 BundleInfo info = bundle.getInfo();
1767 if (info.getState() == Bundle.UNINSTALLED)
1768 {
1769 throw new IllegalStateException("The bundle is uninstalled.");
1770 }
1771
1772 // First get the update-URL from our header.
1773 String updateLocation = (String)
1774 info.getCurrentHeader().get(Constants.BUNDLE_UPDATELOCATION);
1775
1776 // If no update location specified, use original location.
1777 if (updateLocation == null)
1778 {
1779 updateLocation = info.getLocation();
1780 }
1781
1782 // Stop the bundle, but do not change the persistent state.
1783 stopBundle(bundle, false);
1784
1785 try
1786 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001787 // Get the bundle's archive.
Richard S. Hall04bdbb12006-03-15 14:26:15 +00001788 BundleArchive archive = m_cache.getArchive(info.getBundleId());
Richard S. Hall930fecc2005-08-16 18:33:34 +00001789 // Update the bundle; this operation will increase
1790 // the revision count for the bundle.
Richard S. Hall7c9da3d2006-02-24 20:09:28 +00001791 archive.revise(updateLocation, is);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001792 // Create a module for the new revision; the revision is
1793 // base zero, so subtract one from the revision count to
1794 // get the revision of the new update.
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001795 try
1796 {
Karl Paulsc19abb42006-07-21 10:23:11 +00001797 Object sm = System.getSecurityManager();
Karl Pauls836bb402006-08-24 12:39:46 +00001798
Karl Paulsc19abb42006-07-21 10:23:11 +00001799 if (sm != null)
1800 {
1801 ((SecurityManager) sm).checkPermission(
1802 new AdminPermission(bundle, AdminPermission.LIFECYCLE));
1803 }
Karl Pauls836bb402006-08-24 12:39:46 +00001804
Karl Paulsad142d22007-09-16 19:53:22 +00001805 // We need to check whether this is an update to an
Karl Pauls49400ec2007-02-12 23:49:43 +00001806 // extension bundle (info.isExtension) or an update from
1807 // a normal bundle to an extension bundle
1808 // (isExtensionBundle())
Richard S. Hall219b0a22008-09-05 21:38:05 +00001809 Map headerMap = archive.getRevision(
1810 archive.getRevisionCount() - 1).getManifestHeader();
Karl Pauls49400ec2007-02-12 23:49:43 +00001811 IModule module = createModule(
1812 info.getBundleId(),
1813 archive.getRevisionCount() - 1,
Richard S. Hall219b0a22008-09-05 21:38:05 +00001814 headerMap,
Richard S. Hall2846a2b2008-06-01 03:08:17 +00001815 (bundle.getInfo().isExtension() ||
Karl Pauls28636dc2008-02-03 21:32:48 +00001816 m_extensionManager.isExtensionBundle(
Richard S. Hall219b0a22008-09-05 21:38:05 +00001817 headerMap)));
Karl Pauls49400ec2007-02-12 23:49:43 +00001818
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001819 // Add module to bundle info.
1820 info.addModule(module);
Karl Pauls49400ec2007-02-12 23:49:43 +00001821
1822 // If this is an update from a normal to an extension bundle
1823 // then attach the extension or else if this already is
Richard S. Hall3875d692008-06-24 19:47:44 +00001824 // an extension bundle then don't allow it to be resolved
Karl Pauls49400ec2007-02-12 23:49:43 +00001825 // again as per spec.
1826 if (!bundle.getInfo().isExtension() &&
Richard S. Hall26b91982007-07-04 21:15:05 +00001827 m_extensionManager.isExtensionBundle(bundle.getInfo().getCurrentHeader()))
Karl Pauls49400ec2007-02-12 23:49:43 +00001828 {
Karl Pauls28636dc2008-02-03 21:32:48 +00001829 addSecurity(bundle);
Richard S. Hall26b91982007-07-04 21:15:05 +00001830 m_extensionManager.addExtensionBundle(this, bundle);
Karl Paulsad142d22007-09-16 19:53:22 +00001831 m_factory.refreshModule(m_systemBundleInfo.getCurrentModule());
Richard S. Hall26b91982007-07-04 21:15:05 +00001832 bundle.getInfo().setState(Bundle.RESOLVED);
Karl Pauls49400ec2007-02-12 23:49:43 +00001833 }
1834 else if (bundle.getInfo().isExtension())
1835 {
Richard S. Hall26b91982007-07-04 21:15:05 +00001836 bundle.getInfo().setState(Bundle.INSTALLED);
Karl Pauls49400ec2007-02-12 23:49:43 +00001837 }
Karl Pauls28636dc2008-02-03 21:32:48 +00001838 else
1839 {
1840 addSecurity(bundle);
1841 }
Karl Pauls836bb402006-08-24 12:39:46 +00001842 }
Karl Pauls49400ec2007-02-12 23:49:43 +00001843 catch (Throwable ex)
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001844 {
Karl Pauls836bb402006-08-24 12:39:46 +00001845 try
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001846 {
1847 archive.undoRevise();
1848 }
1849 catch (Exception busted)
1850 {
1851 m_logger.log(Logger.LOG_ERROR, "Unable to rollback.", busted);
1852 }
Karl Pauls836bb402006-08-24 12:39:46 +00001853
Karl Pauls3390b4a2006-07-19 13:20:32 +00001854 throw ex;
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001855 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001856 }
Karl Pauls49400ec2007-02-12 23:49:43 +00001857 catch (Throwable ex)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001858 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001859 m_logger.log(Logger.LOG_ERROR, "Unable to update the bundle.", ex);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001860 rethrow = ex;
1861 }
1862
Karl Pauls836bb402006-08-24 12:39:46 +00001863 // Set new state, mark as needing a refresh, and fire updated event
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001864 // if successful.
Richard S. Hall930fecc2005-08-16 18:33:34 +00001865 if (rethrow == null)
1866 {
Karl Pauls9ff9bb82006-07-19 12:46:01 +00001867 info.setLastModified(System.currentTimeMillis());
Karl Pauls49400ec2007-02-12 23:49:43 +00001868
1869 if (!info.isExtension())
1870 {
1871 info.setState(Bundle.INSTALLED);
1872 }
1873
Richard S. Hall2dea05f2006-07-25 10:18:20 +00001874 fireBundleEvent(BundleEvent.UNRESOLVED, bundle);
Karl Pauls836bb402006-08-24 12:39:46 +00001875
Richard S. Hall3875d692008-06-24 19:47:44 +00001876 // Mark previous the bundle's old module for removal.
Richard S. Hall594145f2006-07-23 13:07:18 +00001877 ((ModuleImpl) info.getModules()[info.getModules().length - 2])
1878 .setRemovalPending(true);
Karl Pauls836bb402006-08-24 12:39:46 +00001879
Richard S. Hall930fecc2005-08-16 18:33:34 +00001880 fireBundleEvent(BundleEvent.UPDATED, bundle);
Richard S. Hall21cfb562007-02-09 19:46:47 +00001881
1882 // Determine if the bundle is in use by anyone.
Richard S. Hall21cfb562007-02-09 19:46:47 +00001883 boolean used = false;
Richard S. Hall771843f2007-06-14 18:13:03 +00001884 IModule[] modules = info.getModules();
1885 for (int i = 0; !used && (i < modules.length); i++)
Richard S. Hall21cfb562007-02-09 19:46:47 +00001886 {
Richard S. Hall771843f2007-06-14 18:13:03 +00001887 IModule[] dependents = ((ModuleImpl) modules[i]).getDependents();
Karl Paulsad142d22007-09-16 19:53:22 +00001888 for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++)
Richard S. Hall21cfb562007-02-09 19:46:47 +00001889 {
Karl Paulsad142d22007-09-16 19:53:22 +00001890 if (dependents[j] != modules[i])
1891 {
1892 used = true;
1893 }
Richard S. Hall21cfb562007-02-09 19:46:47 +00001894 }
1895 }
1896
1897 // If the bundle is not used by anyone, then garbage
1898 // collect it now.
1899 if (!used)
1900 {
1901 try
1902 {
1903 refreshPackages(new Bundle[] { bundle });
1904 }
1905 catch (Exception ex)
1906 {
1907 m_logger.log(
1908 Logger.LOG_ERROR,
1909 "Unable to immediately purge the bundle revisions.", ex);
1910 }
1911 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00001912 }
Karl Pauls836bb402006-08-24 12:39:46 +00001913
Richard S. Hall930fecc2005-08-16 18:33:34 +00001914 // Restart bundle, but do not change the persistent state.
1915 // This will not start the bundle if it was not previously
1916 // active.
1917 startBundle(bundle, false);
Richard S. Hall7c9da3d2006-02-24 20:09:28 +00001918
Richard S. Hall930fecc2005-08-16 18:33:34 +00001919 // If update failed, rethrow exception.
1920 if (rethrow != null)
1921 {
Karl Pauls836bb402006-08-24 12:39:46 +00001922 if ((System.getSecurityManager() != null) &&
Karl Paulsc19abb42006-07-21 10:23:11 +00001923 (rethrow instanceof SecurityException))
1924 {
1925 throw (SecurityException) rethrow;
1926 }
Karl Pauls836bb402006-08-24 12:39:46 +00001927
Richard S. Hall930fecc2005-08-16 18:33:34 +00001928 throw new BundleException("Update failed.", rethrow);
1929 }
1930 }
1931 finally
1932 {
1933 try
1934 {
1935 if (is != null) is.close();
1936 }
1937 catch (IOException ex)
1938 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00001939 m_logger.log(Logger.LOG_ERROR, "Unable to close input stream.", ex);
Richard S. Hall930fecc2005-08-16 18:33:34 +00001940 }
1941 }
1942 }
1943
Richard S. Hall26b91982007-07-04 21:15:05 +00001944 protected void stopBundle(FelixBundle bundle, boolean record)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001945 throws BundleException
1946 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00001947 // Acquire bundle lock.
1948 acquireBundleLock(bundle);
1949
1950 try
1951 {
1952 _stopBundle(bundle, record);
1953 }
1954 finally
1955 {
1956 // Always release bundle lock.
1957 releaseBundleLock(bundle);
1958 }
1959 }
1960
Richard S. Hall26b91982007-07-04 21:15:05 +00001961 private void _stopBundle(FelixBundle bundle, boolean record)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001962 throws BundleException
1963 {
1964 Throwable rethrow = null;
Karl Pauls836bb402006-08-24 12:39:46 +00001965
Richard S. Hall930fecc2005-08-16 18:33:34 +00001966 // Set the bundle's persistent state to inactive if necessary.
1967 if (record)
1968 {
1969 bundle.getInfo().setPersistentStateInactive();
1970 }
1971
1972 BundleInfo info = bundle.getInfo();
Karl Pauls836bb402006-08-24 12:39:46 +00001973
Richard S. Hall930fecc2005-08-16 18:33:34 +00001974 switch (info.getState())
1975 {
1976 case Bundle.UNINSTALLED:
1977 throw new IllegalStateException("Cannot stop an uninstalled bundle.");
1978 case Bundle.STARTING:
1979 case Bundle.STOPPING:
1980 throw new BundleException("Stopping a bundle that is starting or stopping is currently not supported.");
1981 case Bundle.INSTALLED:
1982 case Bundle.RESOLVED:
1983 return;
1984 case Bundle.ACTIVE:
1985 // Set bundle state..
1986 info.setState(Bundle.STOPPING);
Richard S. Halle50da252006-07-25 07:48:06 +00001987 fireBundleEvent(BundleEvent.STOPPING, bundle);
1988 break;
Richard S. Hall930fecc2005-08-16 18:33:34 +00001989 }
Richard S. Halle50da252006-07-25 07:48:06 +00001990
Richard S. Hall930fecc2005-08-16 18:33:34 +00001991 try
1992 {
Richard S. Hall675b0552007-07-23 17:03:39 +00001993 if (info.getActivator() != null)
Richard S. Hall930fecc2005-08-16 18:33:34 +00001994 {
Richard S. Hall675b0552007-07-23 17:03:39 +00001995 m_secureAction.stopActivator(info.getActivator(), info.getBundleContext());
Richard S. Hall930fecc2005-08-16 18:33:34 +00001996 }
Karl Pauls836bb402006-08-24 12:39:46 +00001997
Richard S. Hall930fecc2005-08-16 18:33:34 +00001998 // Try to save the activator in the cache.
1999 // NOTE: This is non-standard OSGi behavior and only
2000 // occurs if strictness is disabled.
Richard S. Hall471e3e62007-07-11 19:25:33 +00002001 String strict = (String) m_configMap.get(FelixConstants.STRICT_OSGI_PROP);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002002 boolean isStrict = (strict == null) ? true : strict.equals("true");
2003 if (!isStrict)
2004 {
2005 try
2006 {
2007 m_cache.getArchive(info.getBundleId())
2008 .setActivator(info.getActivator());
2009 }
2010 catch (Exception ex)
2011 {
2012 // Problem saving activator, so ignore it.
Richard S. Hall26b91982007-07-04 21:15:05 +00002013 // TODO: FRAMEWORK - Perhaps we should handle this some other way?
Richard S. Hall930fecc2005-08-16 18:33:34 +00002014 }
2015 }
2016 }
2017 catch (Throwable th)
2018 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002019 m_logger.log(Logger.LOG_ERROR, "Error stopping bundle.", th);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002020 rethrow = th;
2021 }
Richard S. Hall2a28c8d2006-07-25 07:50:41 +00002022
Richard S. Hallfe87d662007-05-31 20:07:11 +00002023 // Do not clean up after the system bundle since it will
2024 // clean up after itself.
2025 if (info.getBundleId() != 0)
2026 {
2027 // Clean up the bundle context.
2028 ((BundleContextImpl) info.getBundleContext()).invalidate();
2029 info.setBundleContext(null);
Richard S. Hall187b87a2006-07-03 09:13:18 +00002030
Richard S. Hallfe87d662007-05-31 20:07:11 +00002031 // Unregister any services offered by this bundle.
2032 m_registry.unregisterServices(bundle);
Karl Pauls836bb402006-08-24 12:39:46 +00002033
Richard S. Hallfe87d662007-05-31 20:07:11 +00002034 // Release any services being used by this bundle.
2035 m_registry.ungetServices(bundle);
Karl Pauls836bb402006-08-24 12:39:46 +00002036
Richard S. Hallfe87d662007-05-31 20:07:11 +00002037 // The spec says that we must remove all event
2038 // listeners for a bundle when it is stopped.
2039 m_dispatcher.removeListeners(bundle);
Karl Pauls836bb402006-08-24 12:39:46 +00002040
Richard S. Hallfe87d662007-05-31 20:07:11 +00002041 info.setState(Bundle.RESOLVED);
2042 fireBundleEvent(BundleEvent.STOPPED, bundle);
2043 }
Karl Pauls836bb402006-08-24 12:39:46 +00002044
Richard S. Hall930fecc2005-08-16 18:33:34 +00002045 // Throw activator error if there was one.
2046 if (rethrow != null)
2047 {
2048 // The spec says to expect BundleException or
2049 // SecurityException, so rethrow these exceptions.
2050 if (rethrow instanceof BundleException)
2051 {
2052 throw (BundleException) rethrow;
2053 }
2054 else if (rethrow instanceof SecurityException)
2055 {
2056 throw (SecurityException) rethrow;
2057 }
Karl Pauls836bb402006-08-24 12:39:46 +00002058 else if ((System.getSecurityManager() != null) &&
Karl Paulsc19abb42006-07-21 10:23:11 +00002059 (rethrow instanceof java.security.PrivilegedActionException))
Richard S. Hall930fecc2005-08-16 18:33:34 +00002060 {
Karl Paulsc19abb42006-07-21 10:23:11 +00002061 rethrow = ((java.security.PrivilegedActionException) rethrow).getException();
Richard S. Hall930fecc2005-08-16 18:33:34 +00002062 }
Karl Pauls836bb402006-08-24 12:39:46 +00002063
Richard S. Hall930fecc2005-08-16 18:33:34 +00002064 // Rethrow all other exceptions as a BundleException.
2065 throw new BundleException("Activator stop error.", rethrow);
2066 }
2067 }
2068
Richard S. Hall26b91982007-07-04 21:15:05 +00002069 protected void uninstallBundle(FelixBundle bundle) throws BundleException
Richard S. Hall930fecc2005-08-16 18:33:34 +00002070 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00002071 // Acquire bundle lock.
2072 acquireBundleLock(bundle);
2073
2074 try
2075 {
2076 _uninstallBundle(bundle);
2077 }
2078 finally
2079 {
2080 // Always release bundle lock.
2081 releaseBundleLock(bundle);
2082 }
2083 }
2084
Richard S. Hall26b91982007-07-04 21:15:05 +00002085 private void _uninstallBundle(FelixBundle bundle) throws BundleException
Richard S. Hall930fecc2005-08-16 18:33:34 +00002086 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00002087 BundleInfo info = bundle.getInfo();
2088 if (info.getState() == Bundle.UNINSTALLED)
2089 {
2090 throw new IllegalStateException("The bundle is uninstalled.");
2091 }
2092
Karl Pauls49400ec2007-02-12 23:49:43 +00002093 // Extension Bundles are not removed until the framework is shutdown
2094 if (bundle.getInfo().isExtension())
2095 {
2096 bundle.getInfo().setPersistentStateUninstalled();
2097 bundle.getInfo().setState(Bundle.INSTALLED);
2098 return;
2099 }
2100
Richard S. Hall930fecc2005-08-16 18:33:34 +00002101 // The spec says that uninstall should always succeed, so
2102 // catch an exception here if stop() doesn't succeed and
2103 // rethrow it at the end.
2104 try
2105 {
2106 stopBundle(bundle, true);
2107 }
2108 catch (BundleException ex)
2109 {
Richard S. Hall447c52f2006-07-04 09:25:07 +00002110 fireFrameworkEvent(FrameworkEvent.ERROR, bundle, ex);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002111 }
2112
2113 // Remove the bundle from the installed map.
Richard S. Hall26b91982007-07-04 21:15:05 +00002114 FelixBundle target = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00002115 synchronized (m_installedBundleLock_Priority2)
2116 {
Richard S. Hall26b91982007-07-04 21:15:05 +00002117 target = (FelixBundle) m_installedBundleMap.remove(info.getLocation());
Karl Paulsa7e36b82008-04-13 19:09:20 +00002118 m_installedBundleIndex.remove(new Long(target.getBundleId()));
Richard S. Hall930fecc2005-08-16 18:33:34 +00002119 }
2120
2121 // Finally, put the uninstalled bundle into the
2122 // uninstalled list for subsequent refreshing.
2123 if (target != null)
2124 {
2125 // Set the bundle's persistent state to uninstalled.
2126 target.getInfo().setPersistentStateUninstalled();
2127
Richard S. Hall60c26d42006-07-19 10:35:04 +00002128 // Mark current module for removal since it can no longer
2129 // be used to resolve other modules per the spec.
Richard S. Hall594145f2006-07-23 13:07:18 +00002130 ((ModuleImpl) target.getInfo().getCurrentModule()).setRemovalPending(true);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002131
2132 // Put bundle in uninstalled bundle array.
Karl Pauls49400ec2007-02-12 23:49:43 +00002133 rememberUninstalledBundle(bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002134 }
2135 else
2136 {
2137 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002138 Logger.LOG_ERROR, "Unable to remove bundle from installed map!");
Richard S. Hall930fecc2005-08-16 18:33:34 +00002139 }
2140
2141 // Set state to uninstalled.
2142 info.setState(Bundle.UNINSTALLED);
Richard S. Hall69d84792006-01-13 13:55:13 +00002143 info.setLastModified(System.currentTimeMillis());
Richard S. Hall930fecc2005-08-16 18:33:34 +00002144
2145 // Fire bundle event.
2146 fireBundleEvent(BundleEvent.UNINSTALLED, bundle);
Richard S. Hall21cfb562007-02-09 19:46:47 +00002147
2148 // Determine if the bundle is in use by anyone.
Richard S. Hall771843f2007-06-14 18:13:03 +00002149 boolean used = false;
2150 IModule[] modules = info.getModules();
2151 for (int i = 0; !used && (i < modules.length); i++)
2152 {
2153 IModule[] dependents = ((ModuleImpl) modules[i]).getDependents();
Karl Paulsad142d22007-09-16 19:53:22 +00002154 for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++)
Richard S. Hall771843f2007-06-14 18:13:03 +00002155 {
Karl Paulsad142d22007-09-16 19:53:22 +00002156 if (dependents[j] != modules[i])
2157 {
2158 used = true;
2159 }
Richard S. Hall771843f2007-06-14 18:13:03 +00002160 }
2161 }
Richard S. Hall21cfb562007-02-09 19:46:47 +00002162
Richard S. Hall771843f2007-06-14 18:13:03 +00002163 // If the bundle is not used by anyone, then garbage
2164 // collect it now.
2165 if (!used)
2166 {
2167 try
2168 {
2169 refreshPackages(new Bundle[] { bundle });
2170 }
2171 catch (Exception ex)
2172 {
2173 m_logger.log(
2174 Logger.LOG_ERROR,
2175 "Unable to immediately garbage collect the bundle.", ex);
2176 }
2177 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00002178 }
2179
2180 //
2181 // Implementation of BundleContext interface methods.
2182 //
2183
Richard S. Hall26b91982007-07-04 21:15:05 +00002184 protected void addRequirement(FelixBundle bundle, String s) throws BundleException
Richard S. Hallbdbc4d52007-06-18 15:14:44 +00002185 {
2186 // TODO: EXPERIMENTAL - Experimental implicit wire concept to try
2187 // to deal with code generation.
2188 synchronized (m_factory)
2189 {
2190 IRequirement[] reqs = ManifestParser.parseImportHeader(s);
2191 IRequirement[] dynamics = bundle.getInfo().getCurrentModule()
2192 .getDefinition().getDynamicRequirements();
2193 if (dynamics == null)
2194 {
2195 dynamics = reqs;
2196 }
2197 else
2198 {
2199 IRequirement[] tmp = new IRequirement[dynamics.length + reqs.length];
2200 System.arraycopy(dynamics, 0, tmp, 0, dynamics.length);
2201 System.arraycopy(reqs, 0, tmp, dynamics.length, reqs.length);
2202 dynamics = tmp;
2203 }
2204 ((ModuleDefinition) bundle.getInfo().getCurrentModule().getDefinition())
2205 .setDynamicRequirements(dynamics);
2206 }
2207 }
2208
Richard S. Hall930fecc2005-08-16 18:33:34 +00002209 /**
2210 * Implementation for BundleContext.getProperty(). Returns
2211 * environment property associated with the framework.
2212 *
2213 * @param key The name of the property to retrieve.
2214 * @return The value of the specified property or null.
2215 **/
2216 protected String getProperty(String key)
2217 {
2218 // First, check the config properties.
Richard S. Hall471e3e62007-07-11 19:25:33 +00002219 String val = (String) m_configMap.get(key);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002220 // If not found, then try the system properties.
2221 return (val == null) ? System.getProperty(key) : val;
2222 }
2223
2224 protected Bundle installBundle(String location, InputStream is)
2225 throws BundleException
2226 {
2227 return installBundle(-1, location, is);
2228 }
2229
2230 private Bundle installBundle(long id, String location, InputStream is)
2231 throws BundleException
2232 {
Richard S. Hall26b91982007-07-04 21:15:05 +00002233 FelixBundle bundle = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00002234
2235 // Acquire an install lock.
2236 acquireInstallLock(location);
2237
2238 try
2239 {
2240 // Check to see if the framework is still running;
Richard S. Hall26b91982007-07-04 21:15:05 +00002241 if ((getState() == Bundle.STOPPING) ||
2242 (getState() == Bundle.UNINSTALLED))
Richard S. Hall930fecc2005-08-16 18:33:34 +00002243 {
2244 throw new BundleException("The framework has been shutdown.");
2245 }
2246
2247 // If bundle location is already installed, then
2248 // return it as required by the OSGi specification.
Richard S. Hall26b91982007-07-04 21:15:05 +00002249 bundle = (FelixBundle) getBundle(location);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002250 if (bundle != null)
2251 {
2252 return bundle;
2253 }
2254
2255 // Determine if this is a new or existing bundle.
2256 boolean isNew = (id < 0);
2257
2258 // If the bundle is new we must cache its JAR file.
2259 if (isNew)
2260 {
2261 // First generate an identifier for it.
2262 id = getNextId();
2263
2264 try
2265 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00002266 // Add the bundle to the cache.
Richard S. Hall9a3e9852006-03-04 03:44:05 +00002267 m_cache.create(id, location, is);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002268 }
2269 catch (Exception ex)
2270 {
2271 throw new BundleException(
2272 "Unable to cache bundle: " + location, ex);
2273 }
2274 finally
2275 {
2276 try
2277 {
2278 if (is != null) is.close();
2279 }
2280 catch (IOException ex)
2281 {
2282 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002283 Logger.LOG_ERROR,
Richard S. Hall930fecc2005-08-16 18:33:34 +00002284 "Unable to close input stream.", ex);
2285 }
2286 }
2287 }
2288 else
2289 {
2290 // If the bundle we are installing is not new,
2291 // then try to purge old revisions before installing
2292 // it; this is done just in case a "refresh"
2293 // didn't occur last session...this would only be
2294 // due to an error or system crash.
2295 try
2296 {
2297 if (m_cache.getArchive(id).getRevisionCount() > 1)
2298 {
Richard S. Hall7c9da3d2006-02-24 20:09:28 +00002299 m_cache.getArchive(id).purge();
Richard S. Hall930fecc2005-08-16 18:33:34 +00002300 }
2301 }
2302 catch (Exception ex)
2303 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00002304 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002305 Logger.LOG_ERROR,
Richard S. Hall930fecc2005-08-16 18:33:34 +00002306 "Could not purge bundle.", ex);
2307 }
2308 }
2309
2310 try
2311 {
Richard S. Hall04bdbb12006-03-15 14:26:15 +00002312 BundleArchive archive = m_cache.getArchive(id);
Richard S. Hall219b0a22008-09-05 21:38:05 +00002313 Map headerMap = archive.getRevision(
2314 archive.getRevisionCount() - 1).getManifestHeader();
2315 bundle = new BundleImpl(
2316 this, createBundleInfo(
2317 archive, headerMap, m_extensionManager.isExtensionBundle(headerMap)));
Karl Pauls49400ec2007-02-12 23:49:43 +00002318
Richard S. Hall9955e902007-01-25 14:42:01 +00002319 verifyExecutionEnvironment(bundle);
Richard S. Hall2846a2b2008-06-01 03:08:17 +00002320
Karl Pauls28636dc2008-02-03 21:32:48 +00002321 addSecurity(bundle);
2322
Karl Pauls49400ec2007-02-12 23:49:43 +00002323 if (!bundle.getInfo().isExtension())
Karl Paulsc19abb42006-07-21 10:23:11 +00002324 {
Karl Pauls49400ec2007-02-12 23:49:43 +00002325 Object sm = System.getSecurityManager();
2326 if (sm != null)
2327 {
2328 ((SecurityManager) sm).checkPermission(
2329 new AdminPermission(bundle, AdminPermission.LIFECYCLE));
2330 }
Karl Paulsc19abb42006-07-21 10:23:11 +00002331 }
Karl Pauls49400ec2007-02-12 23:49:43 +00002332 else
2333 {
Richard S. Hall26b91982007-07-04 21:15:05 +00002334 m_extensionManager.addExtensionBundle(this, bundle);
Karl Paulsad142d22007-09-16 19:53:22 +00002335 m_factory.refreshModule(m_systemBundleInfo.getCurrentModule());
Karl Pauls49400ec2007-02-12 23:49:43 +00002336 }
2337
Richard S. Hall930fecc2005-08-16 18:33:34 +00002338 }
Karl Pauls49400ec2007-02-12 23:49:43 +00002339 catch (Throwable ex)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002340 {
2341 // If the bundle is new, then remove it from the cache.
Richard S. Hall26b91982007-07-04 21:15:05 +00002342 // TODO: FRAMEWORK - Perhaps it should be removed if it is not new too.
Richard S. Hall930fecc2005-08-16 18:33:34 +00002343 if (isNew)
2344 {
2345 try
2346 {
2347 m_cache.remove(m_cache.getArchive(id));
2348 }
2349 catch (Exception ex1)
2350 {
2351 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002352 Logger.LOG_ERROR,
Richard S. Hall930fecc2005-08-16 18:33:34 +00002353 "Could not remove from cache.", ex1);
2354 }
2355 }
Karl Pauls836bb402006-08-24 12:39:46 +00002356
Karl Pauls49400ec2007-02-12 23:49:43 +00002357 if (bundle != null)
2358 {
2359 ((ModuleImpl) bundle.getInfo().getCurrentModule()).setRemovalPending(true);
2360 }
2361
Karl Pauls836bb402006-08-24 12:39:46 +00002362 if ((System.getSecurityManager() != null) &&
Karl Paulsc19abb42006-07-21 10:23:11 +00002363 (ex instanceof SecurityException))
2364 {
2365 throw (SecurityException) ex;
2366 }
Karl Pauls836bb402006-08-24 12:39:46 +00002367
Karl Pauls49400ec2007-02-12 23:49:43 +00002368 ex.printStackTrace();
2369
Richard S. Hall930fecc2005-08-16 18:33:34 +00002370 throw new BundleException("Could not create bundle object.", ex);
2371 }
2372
2373 // If the bundle is new, then set its start level; existing
2374 // bundles already have their start level set.
2375 if (isNew)
2376 {
2377 // This will persistently set the bundle's start level.
2378 bundle.getInfo().setStartLevel(getInitialBundleStartLevel());
Richard S. Hall69d84792006-01-13 13:55:13 +00002379 bundle.getInfo().setLastModified(System.currentTimeMillis());
Richard S. Hall930fecc2005-08-16 18:33:34 +00002380 }
2381
2382 synchronized (m_installedBundleLock_Priority2)
2383 {
2384 m_installedBundleMap.put(location, bundle);
Karl Paulsa7e36b82008-04-13 19:09:20 +00002385 m_installedBundleIndex.put(new Long(bundle.getBundleId()), bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002386 }
Karl Paulsad142d22007-09-16 19:53:22 +00002387
2388 if (bundle.getInfo().isExtension())
Karl Pauls48e37482007-05-06 22:54:09 +00002389 {
Richard S. Hall26b91982007-07-04 21:15:05 +00002390 FelixBundle systemBundle = (FelixBundle) getBundle(0);
Karl Pauls48e37482007-05-06 22:54:09 +00002391 acquireBundleLock(systemBundle);
2392
2393 try
2394 {
Richard S. Hall26b91982007-07-04 21:15:05 +00002395 m_extensionManager.startExtensionBundle(this, bundle);
Karl Pauls48e37482007-05-06 22:54:09 +00002396 }
2397 finally
2398 {
2399 releaseBundleLock(systemBundle);
2400 }
2401 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00002402 }
2403 finally
2404 {
2405 // Always release install lock.
2406 releaseInstallLock(location);
2407
2408 // Always try to close the input stream.
2409 try
2410 {
2411 if (is != null) is.close();
2412 }
2413 catch (IOException ex)
2414 {
2415 m_logger.log(
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002416 Logger.LOG_ERROR,
Richard S. Hall930fecc2005-08-16 18:33:34 +00002417 "Unable to close input stream.", ex);
2418 // Not much else we can do.
2419 }
2420 }
Karl Pauls836bb402006-08-24 12:39:46 +00002421
Richard S. Hall930fecc2005-08-16 18:33:34 +00002422 // Fire bundle event.
2423 fireBundleEvent(BundleEvent.INSTALLED, bundle);
Karl Pauls836bb402006-08-24 12:39:46 +00002424
Richard S. Hall930fecc2005-08-16 18:33:34 +00002425 // Return new bundle.
2426 return bundle;
2427 }
2428
2429 /**
Richard S. Hall9955e902007-01-25 14:42:01 +00002430 * Checks the passed in bundle and checks to see if there is a required execution environment.
2431 * If there is, it gets the execution environment string and verifies that the framework provides it.
2432 * @param bundle The bundle to verify
2433 * @throws BundleException if the bundle's required execution environment does
2434 * not match the current execution environment.
2435 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00002436 private void verifyExecutionEnvironment(FelixBundle bundle)
Richard S. Hall9955e902007-01-25 14:42:01 +00002437 throws BundleException
2438 {
2439 String bundleEnvironment = (String)
2440 bundle.getInfo().getCurrentHeader().get(Constants.BUNDLE_REQUIREDEXECUTIONENVIRONMENT);
2441 if (bundleEnvironment != null)
2442 {
2443 bundleEnvironment = bundleEnvironment.trim();
2444 if (!bundleEnvironment.equals(""))
2445 {
2446 if (!isMatchingExecutionEnvironment(bundleEnvironment))
2447 {
2448 throw new BundleException("Execution Environment not supported: " + bundleEnvironment);
2449 }
2450 }
2451 }
2452 }
2453
2454 /**
2455 * Check the required bundle execution environment against the framework provided
2456 * exectution environment.
2457 * @param bundleEnvironment The required execution environment string
2458 * (from Bundle-RequiredExecutionEnvironment manifest header
2459 * @return True if the required bundle execution environment is provided by the framework
2460 * False if none of the provided framework execution environments match
2461 **/
2462 private boolean isMatchingExecutionEnvironment(String bundleEnvironment)
Karl Pauls49400ec2007-02-12 23:49:43 +00002463 {
Richard S. Hall9955e902007-01-25 14:42:01 +00002464 String frameworkEnvironment = getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
2465 if (frameworkEnvironment == null)
2466 {
2467 // If no framework execution environment is set, then all are valid
2468 return true;
2469 }
2470
2471 frameworkEnvironment = frameworkEnvironment.trim();
2472 if ("".equals(frameworkEnvironment))
2473 {
2474 // If no framework execution environment is set, then all are valid
2475 return true;
2476 }
2477
2478 // The execution environment has changed, so update the cache and EE set
2479 if (!m_executionEnvironment.equals(frameworkEnvironment))
2480 {
2481 updateFrameworkExecutionEnvironment(frameworkEnvironment);
2482 }
2483
2484 StringTokenizer tokens = new StringTokenizer(bundleEnvironment, ",");
2485 while (tokens.hasMoreTokens())
2486 {
2487 if (m_executionEnvironmentCache.contains(tokens.nextToken().trim()))
2488 {
2489 return true;
2490 }
2491 }
2492
2493 return false;
2494 }
2495
2496 /**
2497 * Updates the framework wide execution environment string and a cached Set of
2498 * execution environment tokens from the comma delimited list specified by the
2499 * system variable 'org.osgi.framework.executionenvironment'.
2500 * @param frameworkEnvironment Comma delimited string of provided execution environments
2501 **/
2502 private void updateFrameworkExecutionEnvironment(String frameworkEnvironment)
2503 {
2504 StringTokenizer tokens = new StringTokenizer(frameworkEnvironment, ",");
2505
2506 Set newSet = new HashSet(tokens.countTokens());
2507 while (tokens.hasMoreTokens())
2508 {
2509 newSet.add(tokens.nextToken().trim());
2510 }
2511
2512 synchronized (m_executionEnvironmentCache)
2513 {
2514 m_executionEnvironment = frameworkEnvironment;
2515 m_executionEnvironmentCache = newSet;
2516 }
2517 }
2518
2519 /**
Richard S. Hall930fecc2005-08-16 18:33:34 +00002520 * Retrieves a bundle from its location.
2521 *
2522 * @param location The location of the bundle to retrieve.
2523 * @return The bundle associated with the location or null if there
2524 * is no bundle associated with the location.
2525 **/
2526 protected Bundle getBundle(String location)
2527 {
2528 synchronized (m_installedBundleLock_Priority2)
2529 {
2530 return (Bundle) m_installedBundleMap.get(location);
2531 }
2532 }
2533
2534 /**
2535 * Implementation for BundleContext.getBundle(). Retrieves a
2536 * bundle from its identifier.
2537 *
2538 * @param id The identifier of the bundle to retrieve.
2539 * @return The bundle associated with the identifier or null if there
2540 * is no bundle associated with the identifier.
2541 **/
2542 protected Bundle getBundle(long id)
2543 {
2544 synchronized (m_installedBundleLock_Priority2)
2545 {
Karl Paulsa7e36b82008-04-13 19:09:20 +00002546 FelixBundle bundle = (FelixBundle) m_installedBundleIndex.get(new Long(id));
2547 if (bundle != null)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002548 {
Karl Paulsa7e36b82008-04-13 19:09:20 +00002549 return bundle;
Richard S. Hall930fecc2005-08-16 18:33:34 +00002550 }
2551 }
2552
Richard S. Halla6443462006-06-29 15:16:05 +00002553 synchronized (m_uninstalledBundlesLock_Priority3)
2554 {
Richard S. Hall5a1baf02006-07-20 08:02:42 +00002555 for (int i = 0;
2556 (m_uninstalledBundles != null) && (i < m_uninstalledBundles.length);
2557 i++)
Richard S. Halla6443462006-06-29 15:16:05 +00002558 {
Karl Paulsa7e36b82008-04-13 19:09:20 +00002559 if (m_uninstalledBundles[i].getBundleId() == id)
Richard S. Halla6443462006-06-29 15:16:05 +00002560 {
2561 return m_uninstalledBundles[i];
2562 }
2563 }
2564 }
2565
Richard S. Hall930fecc2005-08-16 18:33:34 +00002566 return null;
2567 }
2568
2569 // Private member for method below.
2570 private Comparator m_comparator = null;
2571
2572 /**
2573 * Implementation for BundleContext.getBundles(). Retrieves
2574 * all installed bundles.
2575 *
2576 * @return An array containing all installed bundles or null if
2577 * there are no installed bundles.
2578 **/
2579 protected Bundle[] getBundles()
2580 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00002581 synchronized (m_installedBundleLock_Priority2)
2582 {
2583 if (m_installedBundleMap.size() == 0)
2584 {
2585 return null;
2586 }
2587
Karl Paulsa7e36b82008-04-13 19:09:20 +00002588 return (Bundle[]) m_installedBundleIndex.values().toArray(
2589 new Bundle[m_installedBundleIndex.size()]);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002590 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00002591 }
2592
2593 protected void addBundleListener(Bundle bundle, BundleListener l)
2594 {
Richard S. Hall92770632006-07-24 10:18:52 +00002595 m_dispatcher.addListener(bundle, BundleListener.class, l, null);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002596 }
2597
Karl Pauls3390b4a2006-07-19 13:20:32 +00002598 protected void removeBundleListener(Bundle bundle, BundleListener l)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002599 {
Richard S. Hall92770632006-07-24 10:18:52 +00002600 m_dispatcher.removeListener(bundle, BundleListener.class, l);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002601 }
2602
2603 /**
2604 * Implementation for BundleContext.addServiceListener().
2605 * Adds service listener to the listener list so that is
2606 * can listen for <code>ServiceEvent</code>s.
2607 *
2608 * @param bundle The bundle that registered the listener.
2609 * @param l The service listener to add to the listener list.
2610 * @param f The filter for the listener; may be null.
2611 **/
2612 protected void addServiceListener(Bundle bundle, ServiceListener l, String f)
2613 throws InvalidSyntaxException
2614 {
Richard S. Hall92770632006-07-24 10:18:52 +00002615 m_dispatcher.addListener(
2616 bundle, ServiceListener.class, l, (f == null) ? null : new FilterImpl(m_logger, f));
Richard S. Hall930fecc2005-08-16 18:33:34 +00002617 }
2618
2619 /**
2620 * Implementation for BundleContext.removeServiceListener().
2621 * Removes service listeners from the listener list.
Karl Pauls836bb402006-08-24 12:39:46 +00002622 *
Karl Pauls3390b4a2006-07-19 13:20:32 +00002623 * @param bundle The context bundle of the listener
Richard S. Hall930fecc2005-08-16 18:33:34 +00002624 * @param l The service listener to remove from the listener list.
2625 **/
Karl Pauls3390b4a2006-07-19 13:20:32 +00002626 protected void removeServiceListener(Bundle bundle, ServiceListener l)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002627 {
Richard S. Hall92770632006-07-24 10:18:52 +00002628 m_dispatcher.removeListener(bundle, ServiceListener.class, l);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002629 }
2630
2631 protected void addFrameworkListener(Bundle bundle, FrameworkListener l)
2632 {
Richard S. Hall92770632006-07-24 10:18:52 +00002633 m_dispatcher.addListener(bundle, FrameworkListener.class, l, null);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002634 }
2635
Karl Pauls3390b4a2006-07-19 13:20:32 +00002636 protected void removeFrameworkListener(Bundle bundle, FrameworkListener l)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002637 {
Richard S. Hall92770632006-07-24 10:18:52 +00002638 m_dispatcher.removeListener(bundle, FrameworkListener.class, l);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002639 }
2640
2641 /**
2642 * Implementation for BundleContext.registerService(). Registers
2643 * a service for the specified bundle bundle.
2644 *
2645 * @param classNames A string array containing the names of the classes
2646 * under which the new service is available.
2647 * @param svcObj The service object or <code>ServiceFactory</code>.
2648 * @param dict A dictionary of properties that further describe the
2649 * service or null.
2650 * @return A <code>ServiceRegistration</code> object or null.
2651 **/
2652 protected ServiceRegistration registerService(
Richard S. Hall26b91982007-07-04 21:15:05 +00002653 FelixBundle bundle, String[] classNames, Object svcObj, Dictionary dict)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002654 {
2655 if (classNames == null)
2656 {
2657 throw new NullPointerException("Service class names cannot be null.");
2658 }
2659 else if (svcObj == null)
2660 {
2661 throw new IllegalArgumentException("Service object cannot be null.");
2662 }
2663
Richard S. Hall930fecc2005-08-16 18:33:34 +00002664 // Acquire bundle lock.
Richard S. Hall3c26cc02006-02-17 13:51:21 +00002665 acquireBundleLock(bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002666
2667 ServiceRegistration reg = null;
2668
2669 try
2670 {
2671 BundleInfo info = bundle.getInfo();
2672
2673 // Can only register services if starting or active.
Karl Pauls28636dc2008-02-03 21:32:48 +00002674 if (((info.getState() & (Bundle.STARTING | Bundle.ACTIVE)) == 0) && !info.isExtension())
Richard S. Hall930fecc2005-08-16 18:33:34 +00002675 {
2676 throw new IllegalStateException(
2677 "Can only register services while bundle is active or activating.");
2678 }
2679
2680 // Check to make sure that the service object is
2681 // an instance of all service classes; ignore if
2682 // service object is a service factory.
2683 if (!(svcObj instanceof ServiceFactory))
2684 {
2685 for (int i = 0; i < classNames.length; i++)
2686 {
Richard S. Hallbc549622006-07-13 13:33:22 +00002687 Class clazz = Util.loadClassUsingClass(svcObj.getClass(), classNames[i]);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002688 if (clazz == null)
2689 {
2690 throw new IllegalArgumentException(
2691 "Cannot cast service: " + classNames[i]);
2692 }
2693 else if (!clazz.isAssignableFrom(svcObj.getClass()))
2694 {
2695 throw new IllegalArgumentException(
2696 "Service object is not an instance of \""
2697 + classNames[i] + "\".");
2698 }
2699 }
2700 }
2701
2702 reg = m_registry.registerService(bundle, classNames, svcObj, dict);
2703 }
2704 finally
2705 {
2706 // Always release bundle lock.
2707 releaseBundleLock(bundle);
2708 }
Richard S. Hall3c26cc02006-02-17 13:51:21 +00002709
2710 // TODO: CONCURRENCY - Reconsider firing event here, outside of the
2711 // bundle lock.
2712
Richard S. Hall930fecc2005-08-16 18:33:34 +00002713 // NOTE: The service registered event is fired from the service
2714 // registry to the framework, where it is then redistributed to
2715 // interested service event listeners.
2716
2717 return reg;
2718 }
2719
Richard S. Hallad76efe2007-01-29 17:37:55 +00002720 /**
2721 * Retrieves an array of {@link ServiceReference} objects based on calling bundle,
2722 * service class name, and filter expression. Optionally checks for isAssignable to
2723 * make sure that the service can be cast to the
2724 * @param bundle Calling Bundle
2725 * @param className Service Classname or <code>null</code> for all
2726 * @param expr Filter Criteria or <code>null</code>
2727 * @return Array of ServiceReference objects that meet the criteria
2728 * @throws InvalidSyntaxException
2729 */
Richard S. Hall930fecc2005-08-16 18:33:34 +00002730 protected ServiceReference[] getServiceReferences(
Richard S. Hall26b91982007-07-04 21:15:05 +00002731 FelixBundle bundle, String className, String expr, boolean checkAssignable)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002732 throws InvalidSyntaxException
2733 {
2734 // Define filter if expression is not null.
2735 Filter filter = null;
2736 if (expr != null)
2737 {
2738 filter = new FilterImpl(m_logger, expr);
2739 }
2740
2741 // Ask the service registry for all matching service references.
2742 List refList = m_registry.getServiceReferences(className, filter);
2743
Richard S. Hallad76efe2007-01-29 17:37:55 +00002744 // Filter on assignable references
2745 if (checkAssignable)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002746 {
Richard S. Hallad76efe2007-01-29 17:37:55 +00002747 for (int refIdx = 0; (refList != null) && (refIdx < refList.size()); refIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002748 {
Richard S. Hallad76efe2007-01-29 17:37:55 +00002749 // Get the current service reference.
2750 ServiceReference ref = (ServiceReference) refList.get(refIdx);
2751
2752 // Now check for castability.
Richard S. Hall211b5a52007-07-09 19:19:29 +00002753 if (!Util.isServiceAssignable(bundle, ref))
Richard S. Hallad76efe2007-01-29 17:37:55 +00002754 {
2755 refList.remove(refIdx);
2756 refIdx--;
2757 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00002758 }
2759 }
2760
2761 if (refList.size() > 0)
2762 {
2763 return (ServiceReference[]) refList.toArray(new ServiceReference[refList.size()]);
2764 }
2765
2766 return null;
2767 }
2768
2769 /**
Richard S. Hallad76efe2007-01-29 17:37:55 +00002770 * Retrieves Array of {@link ServiceReference} objects based on calling bundle, service class name,
2771 * optional filter expression, and optionally filters further on the version.
2772 * If running under a {@link SecurityManager}, checks that the calling bundle has permissions to
2773 * see the service references and removes references that aren't.
2774 * @param bundle Calling Bundle
2775 * @param className Service Classname or <code>null</code> for all
2776 * @param expr Filter Criteria or <code>null</code>
2777 * @param checkAssignable <code>true</code> to check for isAssignable, <code>false</code> to return all versions
2778 * @return Array of ServiceReference objects that meet the criteria
2779 * @throws InvalidSyntaxException
2780 */
2781 protected ServiceReference[] getAllowedServiceReferences(
Richard S. Hall26b91982007-07-04 21:15:05 +00002782 FelixBundle bundle, String className, String expr, boolean checkAssignable)
Richard S. Hallad76efe2007-01-29 17:37:55 +00002783 throws InvalidSyntaxException
2784 {
2785 ServiceReference[] refs = getServiceReferences(bundle, className, expr, checkAssignable);
2786
2787 Object sm = System.getSecurityManager();
2788
Karl Pauls80ca00c2007-01-30 14:03:32 +00002789 if ((sm == null) || (refs == null))
Richard S. Hallad76efe2007-01-29 17:37:55 +00002790 {
2791 return refs;
2792 }
2793
2794 List result = new ArrayList();
2795
2796 for (int i = 0;i < refs.length;i++)
2797 {
2798 String[] objectClass = (String[]) refs[i].getProperty(Constants.OBJECTCLASS);
2799
2800 if (objectClass == null)
2801 {
2802 continue;
2803 }
2804
2805 for (int j = 0; j < objectClass.length; j++)
2806 {
2807 try
2808 {
2809 ((SecurityManager) sm).checkPermission(new ServicePermission(
2810 objectClass[j], ServicePermission.GET));
2811 result.add(refs[i]);
2812 break;
2813 }
2814 catch (Exception ex)
2815 {
2816 // Ignore, since we are just testing permission.
2817 }
2818 }
2819 }
2820
2821 if (result.isEmpty())
2822 {
2823 return null;
2824 }
2825
2826 return (ServiceReference[]) result.toArray(new ServiceReference[result.size()]);
2827
2828 }
2829
Richard S. Hall930fecc2005-08-16 18:33:34 +00002830 protected Object getService(Bundle bundle, ServiceReference ref)
2831 {
2832 // Check that the bundle has permission to get at least
2833 // one of the service interfaces; the objectClass property
2834 // of the service stores its service interfaces.
2835 String[] objectClass = (String[])
2836 ref.getProperty(Constants.OBJECTCLASS);
2837 if (objectClass == null)
2838 {
2839 return null;
2840 }
2841
Richard S. Hall930fecc2005-08-16 18:33:34 +00002842 return m_registry.getService(bundle, ref);
2843 }
2844
2845 protected boolean ungetService(Bundle bundle, ServiceReference ref)
2846 {
2847 return m_registry.ungetService(bundle, ref);
2848 }
2849
Richard S. Hall26b91982007-07-04 21:15:05 +00002850 protected File getDataFile(FelixBundle bundle, String s)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002851 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00002852 try
2853 {
Karl Pauls28636dc2008-02-03 21:32:48 +00002854 if (bundle == this)
2855 {
2856 return m_systemBundleInfo.getArchive().getDataFile(s);
2857 }
Richard S. Hall2846a2b2008-06-01 03:08:17 +00002858
Richard S. Hall930fecc2005-08-16 18:33:34 +00002859 return m_cache.getArchive(
Karl Paulsa7e36b82008-04-13 19:09:20 +00002860 bundle.getBundleId()).getDataFile(s);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002861 }
2862 catch (Exception ex)
2863 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00002864 m_logger.log(Logger.LOG_ERROR, ex.getMessage());
Richard S. Hall930fecc2005-08-16 18:33:34 +00002865 return null;
2866 }
2867 }
2868
2869 //
2870 // PackageAdmin related methods.
2871 //
2872
2873 /**
Richard S. Hallc87d41a2006-07-03 07:57:28 +00002874 * This method returns the bundle associated with the specified class if
2875 * the class was loaded from a bundle from this framework instance. If the
2876 * class was not loaded from a bundle or was loaded by a bundle in another
2877 * framework instance, then <tt>null</tt> is returned.
Karl Pauls836bb402006-08-24 12:39:46 +00002878 *
Richard S. Hallc87d41a2006-07-03 07:57:28 +00002879 * @param clazz the class for which to find its associated bundle.
2880 * @return the bundle associated with the specified class or <tt>null</tt>
2881 * if the class was not loaded by a bundle or its associated
2882 * bundle belongs to a different framework instance.
2883 **/
2884 protected Bundle getBundle(Class clazz)
2885 {
2886 if (clazz.getClassLoader() instanceof ContentClassLoader)
2887 {
2888 IContentLoader contentLoader =
2889 ((ContentClassLoader) clazz.getClassLoader()).getContentLoader();
2890 IModule[] modules = m_factory.getModules();
2891 for (int i = 0; i < modules.length; i++)
2892 {
2893 if (modules[i].getContentLoader() == contentLoader)
2894 {
2895 long id = Util.getBundleIdFromModuleId(modules[i].getId());
2896 return getBundle(id);
2897 }
2898 }
2899 }
Karl Paulsb6ad9922008-08-20 16:37:33 +00002900 try
2901 {
2902 return (getInfo().getCurrentModule().getClass(clazz.getName()) == clazz) ? this : null;
2903 }
2904 catch(ClassNotFoundException ex)
2905 {
2906 return null;
2907 }
Richard S. Hallc87d41a2006-07-03 07:57:28 +00002908 }
2909
2910 /**
Richard S. Hall1bdc3722006-07-03 09:52:07 +00002911 * Returns the exported packages associated with the specified
Richard S. Hallafc52d42006-02-09 13:04:32 +00002912 * package name. This is used by the PackageAdmin service
2913 * implementation.
2914 *
Richard S. Hallbf12bf72007-01-22 07:15:25 +00002915 * @param pkgName The name of the exported package to find.
Richard S. Hallafc52d42006-02-09 13:04:32 +00002916 * @return The exported package or null if no matching package was found.
2917 **/
Richard S. Hallbf12bf72007-01-22 07:15:25 +00002918 protected ExportedPackage[] getExportedPackages(String pkgName)
Richard S. Hallafc52d42006-02-09 13:04:32 +00002919 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00002920 // First, get all exporters of the package.
Richard S. Hall441cc662007-01-31 21:12:57 +00002921 R4SearchPolicyCore.PackageSource[] exporters =
Richard S. Hallbf12bf72007-01-22 07:15:25 +00002922 m_policyCore.getInUseCandidates(
2923 new Requirement(
2924 ICapability.PACKAGE_NAMESPACE,
2925 null,
Richard S. Hall21cfb562007-02-09 19:46:47 +00002926 new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }));
Richard S. Hallbf12bf72007-01-22 07:15:25 +00002927
Richard S. Hall930fecc2005-08-16 18:33:34 +00002928 if (exporters != null)
2929 {
Karl Paulsad142d22007-09-16 19:53:22 +00002930 List pkgs = new ArrayList();
2931
2932 Requirement req = new Requirement(ICapability.PACKAGE_NAMESPACE,
2933 null,
Karl Paulsad142d22007-09-16 19:53:22 +00002934 new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) });
2935
2936 for (int pkgIdx = 0; pkgIdx < exporters.length; pkgIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002937 {
Richard S. Hallafc52d42006-02-09 13:04:32 +00002938 // Get the bundle associated with the current exporting module.
Richard S. Hall26b91982007-07-04 21:15:05 +00002939 FelixBundle bundle = (FelixBundle) getBundle(
Richard S. Hallbf12bf72007-01-22 07:15:25 +00002940 Util.getBundleIdFromModuleId(exporters[pkgIdx].m_module.getId()));
Richard S. Hallafc52d42006-02-09 13:04:32 +00002941
2942 // We need to find the version of the exported package, but this
2943 // is tricky since there may be multiple versions of the package
2944 // offered by a given bundle, since multiple revisions of the
2945 // bundle JAR file may exist if the bundle was updated without
2946 // refreshing the framework. In this case, each revision of the
2947 // bundle JAR file is represented as a module in the BundleInfo
2948 // module array, which is ordered from oldest to newest. We assume
2949 // that the first module found to be exporting the package is the
2950 // provider of the package, which makes sense since it must have
2951 // been resolved first.
2952 IModule[] modules = bundle.getInfo().getModules();
2953 for (int modIdx = 0; modIdx < modules.length; modIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00002954 {
Karl Paulsad142d22007-09-16 19:53:22 +00002955 ICapability[] ec = modules[modIdx].getDefinition().getCapabilities();
2956 for (int i = 0; (ec != null) && (i < ec.length); i++)
Richard S. Hallafc52d42006-02-09 13:04:32 +00002957 {
Karl Paulsad142d22007-09-16 19:53:22 +00002958 if (ec[i].getNamespace().equals(req.getNamespace()) &&
2959 req.isSatisfied(ec[i]))
2960 {
2961 pkgs.add(new ExportedPackageImpl(this, bundle, modules[modIdx], (Capability) ec[i]));
2962 }
Richard S. Hallafc52d42006-02-09 13:04:32 +00002963 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00002964 }
2965 }
Karl Paulsad142d22007-09-16 19:53:22 +00002966
2967 return (pkgs.isEmpty()) ? null : (ExportedPackage[]) pkgs.toArray(new ExportedPackage[pkgs.size()]);
Richard S. Hall930fecc2005-08-16 18:33:34 +00002968 }
2969
Karl Paulsad142d22007-09-16 19:53:22 +00002970 return null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00002971 }
2972
2973 /**
2974 * Returns an array of all actively exported packages from the specified
2975 * bundle or if the specified bundle is <tt>null</tt> an array
2976 * containing all actively exported packages by all bundles.
2977 *
2978 * @param b The bundle whose exported packages are to be retrieved
2979 * or <tt>null</tt> if the exported packages of all bundles are
2980 * to be retrieved.
2981 * @return An array of exported packages.
2982 **/
2983 protected ExportedPackage[] getExportedPackages(Bundle b)
2984 {
2985 List list = new ArrayList();
2986
2987 // If a bundle is specified, then return its
2988 // exported packages.
2989 if (b != null)
2990 {
Richard S. Hall26b91982007-07-04 21:15:05 +00002991 FelixBundle bundle = (FelixBundle) b;
Richard S. Hall930fecc2005-08-16 18:33:34 +00002992 getExportedPackages(bundle, list);
2993 }
2994 // Otherwise return all exported packages.
2995 else
2996 {
2997 // To create a list of all exported packages, we must look
2998 // in the installed and uninstalled sets of bundles. To
2999 // ensure a somewhat consistent view, we will gather all
3000 // of this information from within the installed bundle
3001 // lock.
3002 synchronized (m_installedBundleLock_Priority2)
3003 {
3004 // First get exported packages from uninstalled bundles.
3005 synchronized (m_uninstalledBundlesLock_Priority3)
3006 {
3007 for (int bundleIdx = 0;
3008 (m_uninstalledBundles != null) && (bundleIdx < m_uninstalledBundles.length);
3009 bundleIdx++)
3010 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003011 FelixBundle bundle = m_uninstalledBundles[bundleIdx];
Richard S. Hall930fecc2005-08-16 18:33:34 +00003012 getExportedPackages(bundle, list);
3013 }
3014 }
3015
3016 // Now get exported packages from installed bundles.
3017 Bundle[] bundles = getBundles();
3018 for (int bundleIdx = 0; bundleIdx < bundles.length; bundleIdx++)
3019 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003020 FelixBundle bundle = (FelixBundle) bundles[bundleIdx];
Richard S. Hall930fecc2005-08-16 18:33:34 +00003021 getExportedPackages(bundle, list);
3022 }
3023 }
3024 }
3025
3026 return (ExportedPackage[]) list.toArray(new ExportedPackage[list.size()]);
3027 }
3028
3029 /**
3030 * Adds any current active exported packages from the specified bundle
3031 * to the passed in list.
3032 * @param bundle The bundle from which to retrieve exported packages.
3033 * @param list The list to which the exported packages are added
3034 **/
Richard S. Hall26b91982007-07-04 21:15:05 +00003035 private void getExportedPackages(FelixBundle bundle, List list)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003036 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00003037 // Since a bundle may have many modules associated with it,
3038 // one for each revision in the cache, search each module
3039 // for each revision to get all exports.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003040 IModule[] modules = bundle.getInfo().getModules();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003041 for (int modIdx = 0; modIdx < modules.length; modIdx++)
3042 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00003043 ICapability[] caps = modules[modIdx].getDefinition().getCapabilities();
3044 if ((caps != null) && (caps.length > 0))
Richard S. Hall930fecc2005-08-16 18:33:34 +00003045 {
Richard S. Hallbf12bf72007-01-22 07:15:25 +00003046 for (int capIdx = 0; capIdx < caps.length; capIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003047 {
3048 // See if the target bundle's module is one of the
3049 // "in use" exporters of the package.
Richard S. Hall352a0332007-01-29 17:41:28 +00003050 if (caps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
Richard S. Hall930fecc2005-08-16 18:33:34 +00003051 {
Richard S. Hall441cc662007-01-31 21:12:57 +00003052 R4SearchPolicyCore.PackageSource[] inUseModules = m_policyCore.getInUseCandidates(
Richard S. Hall352a0332007-01-29 17:41:28 +00003053 new Requirement(
3054 ICapability.PACKAGE_NAMESPACE,
3055 null,
Richard S. Hall21cfb562007-02-09 19:46:47 +00003056 new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }));
Karl Pauls49400ec2007-02-12 23:49:43 +00003057
Richard S. Hall352a0332007-01-29 17:41:28 +00003058 // Search through the current providers to find the target
3059 // module.
3060 for (int i = 0; (inUseModules != null) && (i < inUseModules.length); i++)
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003061 {
Richard S. Hall352a0332007-01-29 17:41:28 +00003062 if (inUseModules[i].m_module == modules[modIdx])
3063 {
3064 list.add(new ExportedPackageImpl(
3065 this, bundle, modules[modIdx], (Capability) caps[capIdx]));
3066 }
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003067 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003068 }
3069 }
3070 }
3071 }
3072 }
3073
Richard S. Hall26b91982007-07-04 21:15:05 +00003074 protected Bundle[] getDependentBundles(FelixBundle exporter)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003075 {
Richard S. Halle1f53a52006-07-17 11:06:59 +00003076 // Get exporting bundle.
Richard S. Hall930fecc2005-08-16 18:33:34 +00003077 BundleInfo exporterInfo = exporter.getInfo();
3078
3079 // Create list for storing importing bundles.
3080 List list = new ArrayList();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003081
Richard S. Hall771843f2007-06-14 18:13:03 +00003082 // Get all dependent modules from all exporter module revisions.
3083 IModule[] modules = exporterInfo.getModules();
3084 for (int modIdx = 0; modIdx < modules.length; modIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003085 {
Richard S. Hall771843f2007-06-14 18:13:03 +00003086 IModule[] dependents = ((ModuleImpl) modules[modIdx]).getDependents();
3087 for (int depIdx = 0;
3088 (dependents != null) && (depIdx < dependents.length);
3089 depIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003090 {
Richard S. Hall771843f2007-06-14 18:13:03 +00003091 Bundle b = getBundle(Util.getBundleIdFromModuleId(dependents[depIdx].getId()));
3092 list.add(b);
3093 }
3094 }
Richard S. Hall82699422006-07-19 14:37:45 +00003095
Richard S. Hall771843f2007-06-14 18:13:03 +00003096 // Return the results.
3097 if (list.size() > 0)
3098 {
3099 return (Bundle[]) list.toArray(new Bundle[list.size()]);
3100 }
3101
3102 return null;
3103 }
3104
3105 protected Bundle[] getImportingBundles(ExportedPackage ep)
3106 {
3107 // Create list for storing importing bundles.
3108 List list = new ArrayList();
3109
3110 // Get exporting bundle information.
Richard S. Hall26b91982007-07-04 21:15:05 +00003111 FelixBundle exporter = (FelixBundle)
Richard S. Hall771843f2007-06-14 18:13:03 +00003112 ((ExportedPackage) ep).getExportingBundle();
3113
3114 // Search the dependents of the exporter's module revisions
3115 // for importers of the specific package.
3116 IModule[] expModules = exporter.getInfo().getModules();
3117 for (int expIdx = 0; (expModules != null) && (expIdx < expModules.length); expIdx++)
3118 {
3119 IModule[] depModules = ((ModuleImpl) expModules[expIdx]).getDependents();
3120 for (int depIdx = 0; (depModules != null) && (depIdx < depModules.length); depIdx++)
3121 {
Richard S. Hallfc873412007-12-20 19:54:37 +00003122 // ExportedPackage.getImportingBundles() does not expect bundles
3123 // to depend on themselves, so we will filter that case here.
3124 if (!expModules[expIdx].equals(depModules[depIdx]))
Richard S. Hall930fecc2005-08-16 18:33:34 +00003125 {
Richard S. Hallfc873412007-12-20 19:54:37 +00003126 // See if the dependent module has a wire for the specific
3127 // package. If so, see if the provider module is from the
3128 // exporter and record it if it is.
3129 IWire wire = Util.getWire(depModules[depIdx], ep.getName());
3130 if ((wire != null) && expModules[expIdx].equals(wire.getExporter()) &&
3131 wire.getRequirement().isSatisfied(
3132 new Capability(ICapability.PACKAGE_NAMESPACE, null, new R4Attribute[] {
3133 new R4Attribute(ICapability.PACKAGE_PROPERTY, ep.getName(), false),
3134 new R4Attribute(ICapability.VERSION_PROPERTY, ep.getVersion(), false)
3135 })))
3136 {
3137 // Add the bundle to the list of importers.
3138 list.add(getBundle(Util.getBundleIdFromModuleId(depModules[depIdx].getId())));
3139 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003140 }
3141 }
3142 }
3143
3144 // Return the results.
3145 if (list.size() > 0)
3146 {
3147 return (Bundle[]) list.toArray(new Bundle[list.size()]);
3148 }
3149
3150 return null;
3151 }
3152
Richard S. Hall1a4ab602006-05-24 13:46:06 +00003153 protected boolean resolveBundles(Bundle[] targets)
3154 {
Richard S. Hall1a4ab602006-05-24 13:46:06 +00003155 // Acquire locks for all bundles to be resolved.
Richard S. Hall26b91982007-07-04 21:15:05 +00003156 FelixBundle[] bundles = acquireBundleResolveLocks(targets);
Richard S. Hall1a4ab602006-05-24 13:46:06 +00003157
3158 try
3159 {
3160 boolean result = true;
3161
3162 // If there are targets, then resolve each one.
3163 if (bundles != null)
3164 {
3165 for (int i = 0; i < bundles.length; i++)
3166 {
3167 try
3168 {
3169 _resolveBundle(bundles[i]);
3170 }
3171 catch (BundleException ex)
3172 {
3173 result = false;
3174 m_logger.log(
3175 Logger.LOG_WARNING,
3176 "Unable to resolve bundle " + bundles[i].getBundleId(),
3177 ex);
3178 }
3179 }
3180 }
3181
3182 return result;
3183 }
3184 finally
3185 {
3186 // Always release all bundle locks.
3187 releaseBundleLocks(bundles);
3188 }
3189 }
3190
Richard S. Hall930fecc2005-08-16 18:33:34 +00003191 protected void refreshPackages(Bundle[] targets)
3192 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00003193 // Acquire locks for all impacted bundles.
Richard S. Hall26b91982007-07-04 21:15:05 +00003194 FelixBundle[] bundles = acquireBundleRefreshLocks(targets);
Karl Pauls49400ec2007-02-12 23:49:43 +00003195 boolean restart = false;
Karl Paulsad142d22007-09-16 19:53:22 +00003196
Karl Pauls49400ec2007-02-12 23:49:43 +00003197 Bundle systemBundle = getBundle(0);
3198
3199 // We need to restart the framework if either an extension bundle is
3200 // refreshed or the system bundle is refreshed and any extension bundle
3201 // has been updated or uninstalled.
3202 for (int i = 0; (bundles != null) && !restart && (i < bundles.length); i++)
3203 {
3204 if (bundles[i].getInfo().isExtension())
3205 {
3206 restart = true;
3207 }
3208 else if (systemBundle == bundles[i])
3209 {
3210 Bundle[] allBundles = getBundles();
3211 for (int j = 0; !restart && j < allBundles.length; j++)
3212 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003213 if (((FelixBundle) allBundles[j]).getInfo().isExtension() &&
3214 (allBundles[j].getState() == Bundle.INSTALLED))
Karl Pauls49400ec2007-02-12 23:49:43 +00003215 {
3216 restart = true;
3217 }
3218 }
3219 }
3220 }
3221
3222 if (restart)
3223 {
3224// TODO: Extension Bundle - We need a way to restart the framework
3225 m_logger.log(Logger.LOG_WARNING, "Framework restart not implemented.");
3226 }
3227
Richard S. Hall930fecc2005-08-16 18:33:34 +00003228 // Remove any targeted bundles from the uninstalled bundles
3229 // array, since they will be removed from the system after
3230 // the refresh.
3231 for (int i = 0; (bundles != null) && (i < bundles.length); i++)
3232 {
3233 forgetUninstalledBundle(bundles[i]);
3234 }
3235
3236 try
3237 {
3238 // If there are targets, then refresh each one.
3239 if (bundles != null)
3240 {
3241 // At this point the map contains every bundle that has been
3242 // updated and/or removed as well as all bundles that import
3243 // packages from these bundles.
Karl Pauls836bb402006-08-24 12:39:46 +00003244
Richard S. Hall930fecc2005-08-16 18:33:34 +00003245 // Create refresh helpers for each bundle.
3246 RefreshHelper[] helpers = new RefreshHelper[bundles.length];
3247 for (int i = 0; i < bundles.length; i++)
3248 {
Karl Pauls49400ec2007-02-12 23:49:43 +00003249 if (!bundles[i].getInfo().isExtension())
3250 {
3251 helpers[i] = new RefreshHelper(bundles[i]);
3252 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003253 }
3254
3255 // Stop, purge or remove, and reinitialize all bundles first.
3256 for (int i = 0; i < helpers.length; i++)
3257 {
Karl Pauls49400ec2007-02-12 23:49:43 +00003258 if (helpers[i] != null)
3259 {
3260 helpers[i].stop();
3261 helpers[i].purgeOrRemove();
3262 helpers[i].reinitialize();
3263 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003264 }
3265
3266 // Then restart all bundles that were previously running.
3267 for (int i = 0; i < helpers.length; i++)
3268 {
Karl Pauls49400ec2007-02-12 23:49:43 +00003269 if (helpers[i] != null)
3270 {
3271 helpers[i].restart();
3272 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003273 }
3274 }
3275 }
3276 finally
3277 {
3278 // Always release all bundle locks.
3279 releaseBundleLocks(bundles);
3280 }
3281
Richard S. Hallfaa3d612007-10-24 14:18:17 +00003282 fireFrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, this, null);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003283 }
3284
Richard S. Hall26b91982007-07-04 21:15:05 +00003285 private void populateImportGraph(FelixBundle exporter, Map map)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003286 {
Richard S. Hall771843f2007-06-14 18:13:03 +00003287 // Get all dependent bundles of this bundle.
3288 Bundle[] importers = getDependentBundles(exporter);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003289
Richard S. Hall771843f2007-06-14 18:13:03 +00003290 for (int impIdx = 0;
3291 (importers != null) && (impIdx < importers.length);
3292 impIdx++)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003293 {
Richard S. Hall771843f2007-06-14 18:13:03 +00003294 // Avoid cycles if the bundle is already in map.
3295 if (!map.containsKey(importers[impIdx]))
Richard S. Hall930fecc2005-08-16 18:33:34 +00003296 {
Richard S. Hall771843f2007-06-14 18:13:03 +00003297 // Add each importing bundle to map.
3298 map.put(importers[impIdx], importers[impIdx]);
3299 // Now recurse into each bundle to get its importers.
3300 populateImportGraph(
Richard S. Hall26b91982007-07-04 21:15:05 +00003301 (FelixBundle) importers[impIdx], map);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003302 }
3303 }
3304 }
3305
3306 //
3307 // Miscellaneous private methods.
3308 //
3309
Richard S. Hall219b0a22008-09-05 21:38:05 +00003310 private BundleInfo createBundleInfo(BundleArchive archive, Map headerMap, boolean isExtension)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003311 throws Exception
3312 {
Richard S. Hall930fecc2005-08-16 18:33:34 +00003313 // Create the module for the bundle; although there should only
3314 // ever be one revision at this point, create the module for
3315 // the current revision to be safe.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003316 IModule module = createModule(
Richard S. Hall2846a2b2008-06-01 03:08:17 +00003317 archive.getId(), archive.getRevisionCount() - 1, headerMap,
Karl Pauls28636dc2008-02-03 21:32:48 +00003318 isExtension);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003319
3320 // Finally, create an return the bundle info.
Karl Pauls49400ec2007-02-12 23:49:43 +00003321 BundleInfo info = new BundleInfo(m_logger, archive, module);
3322 info.setExtension(isExtension);
3323
3324 return info;
3325 }
3326
Karl Pauls28636dc2008-02-03 21:32:48 +00003327 private volatile SecurityProvider m_securityProvider;
Karl Pauls49400ec2007-02-12 23:49:43 +00003328
Karl Pauls28636dc2008-02-03 21:32:48 +00003329 void setSecurityProvider(SecurityProvider securityProvider)
3330 {
3331 m_securityProvider = securityProvider;
3332 }
3333
3334 Object getSignerMatcher(FelixBundle bundle)
3335 {
3336 if (m_securityProvider != null)
3337 {
3338 return m_securityProvider.getSignerMatcher(bundle);
3339 }
3340 return null;
3341 }
3342
3343 boolean impliesBundlePermission(BundleProtectionDomain bundleProtectionDomain, Permission permission, boolean direct)
3344 {
3345 if (m_securityProvider != null)
3346 {
3347 return m_securityProvider.hasBundlePermission(bundleProtectionDomain, permission, direct);
3348 }
Karl Pauls118c9162008-08-06 15:59:20 +00003349 else if ((bundleProtectionDomain.getBundle() != this) && (System.getSecurityManager() != null))
3350 {
3351 return m_secureAction.getPolicy().implies(bundleProtectionDomain, permission);
3352 }
Karl Pauls28636dc2008-02-03 21:32:48 +00003353 return true;
3354 }
3355
Karl Pauls758c2be2008-03-05 13:10:04 +00003356 void addSecurity(final FelixBundle bundle) throws Exception
Karl Pauls28636dc2008-02-03 21:32:48 +00003357 {
Karl Pauls758c2be2008-03-05 13:10:04 +00003358 if (m_securityProvider != null)
3359 {
3360 m_securityProvider.checkBundle(bundle);
3361 }
Karl Pauls28636dc2008-02-03 21:32:48 +00003362 bundle.getInfo().setProtectionDomain(new BundleProtectionDomain(this, bundle));
Richard S. Hall930fecc2005-08-16 18:33:34 +00003363 }
3364
3365 /**
3366 * Creates a module for a given bundle by reading the bundle's
3367 * manifest meta-data and converting it to work with the underlying
3368 * import/export search policy of the module loader.
Richard S. Hallbf6bc8a2006-07-03 13:43:46 +00003369 * @param targetId The identifier of the bundle for which the module should
Richard S. Hall930fecc2005-08-16 18:33:34 +00003370 * be created.
Richard S. Hallbf6bc8a2006-07-03 13:43:46 +00003371 * @param headerMap The headers map associated with the bundle.
Richard S. Hall930fecc2005-08-16 18:33:34 +00003372 * @return The initialized and/or newly created module.
3373 **/
Karl Pauls49400ec2007-02-12 23:49:43 +00003374 private IModule createModule(long targetId, int revision, Map headerMap,
Karl Pauls28636dc2008-02-03 21:32:48 +00003375 boolean isExtensionBundle) throws Exception
Richard S. Hall930fecc2005-08-16 18:33:34 +00003376 {
Richard S. Hall471e3e62007-07-11 19:25:33 +00003377 ManifestParser mp = new ManifestParser(m_logger, m_configMap, headerMap);
Richard S. Halla2878c12006-07-21 14:50:07 +00003378
3379 // Verify that the bundle symbolic name and version is unique.
Richard S. Hall56b11942006-10-26 14:40:07 +00003380 if (mp.getManifestVersion().equals("2"))
Richard S. Hall930fecc2005-08-16 18:33:34 +00003381 {
Richard S. Hall56b11942006-10-26 14:40:07 +00003382 Version bundleVersion = mp.getBundleVersion();
3383 bundleVersion = (bundleVersion == null) ? Version.emptyVersion : bundleVersion;
3384 String symName = (String) mp.getSymbolicName();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003385
Richard S. Hall8bebf412006-07-03 12:54:50 +00003386 Bundle[] bundles = getBundles();
3387 for (int i = 0; (bundles != null) && (i < bundles.length); i++)
3388 {
Karl Paulsa7e36b82008-04-13 19:09:20 +00003389 long id = ((FelixBundle) bundles[i]).getBundleId();
Richard S. Hallc7da25d2008-08-01 15:41:32 +00003390 String sym = bundles[i].getSymbolicName();
Richard S. Hall26b91982007-07-04 21:15:05 +00003391 Version ver = Version.parseVersion((String) ((FelixBundle) bundles[i])
Richard S. Hall56b11942006-10-26 14:40:07 +00003392 .getInfo().getCurrentHeader().get(Constants.BUNDLE_VERSION));
Richard S. Halla2878c12006-07-21 14:50:07 +00003393 if (symName.equals(sym) && bundleVersion.equals(ver) && (targetId != id))
Richard S. Hall8bebf412006-07-03 12:54:50 +00003394 {
3395 throw new BundleException("Bundle symbolic name and version are not unique.");
3396 }
3397 }
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003398 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003399
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003400 // Now that we have all of the metadata associated with the
3401 // module, we need to create the module itself. This is somewhat
3402 // complicated because a module is constructed out of several
Richard S. Hall594145f2006-07-23 13:07:18 +00003403 // interrelated pieces (e.g., module definition, content loader,
3404 // search policy, url policy). We need to create all of these
3405 // pieces and bind them together.
Richard S. Hall930fecc2005-08-16 18:33:34 +00003406
Richard S. Hall594145f2006-07-23 13:07:18 +00003407 // Create the module definition for the new module.
Karl Pauls49400ec2007-02-12 23:49:43 +00003408 // Note, in case this is an extension bundle it's exports are removed -
3409 // they will be added to the system bundle directly later on.
Richard S. Hall594145f2006-07-23 13:07:18 +00003410 IModuleDefinition md = new ModuleDefinition(
Richard S. Hall95d97de2008-08-29 16:17:26 +00003411 headerMap,
Karl Pauls49400ec2007-02-12 23:49:43 +00003412 (isExtensionBundle) ? null : mp.getCapabilities(),
Richard S. Hallbf12bf72007-01-22 07:15:25 +00003413 mp.getRequirements(),
3414 mp.getDynamicRequirements(),
Richard S. Hall5eda19c2008-02-29 19:52:53 +00003415 mp.getLibraries());
Karl Pauls836bb402006-08-24 12:39:46 +00003416
Richard S. Hall594145f2006-07-23 13:07:18 +00003417 // Create the module using the module definition.
3418 IModule module = m_factory.createModule(
3419 Long.toString(targetId) + "." + Integer.toString(revision), md);
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003420
Richard S. Hall594145f2006-07-23 13:07:18 +00003421 // Create the content loader from the module archive.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003422 IContentLoader contentLoader = new ContentLoaderImpl(
Richard S. Hall5eda19c2008-02-29 19:52:53 +00003423 m_logger, m_cache.getArchive(targetId).getRevision(revision).getContent());
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003424 // Set the content loader's search policy.
3425 contentLoader.setSearchPolicy(
3426 new R4SearchPolicy(m_policyCore, module));
3427 // Set the content loader's URL policy.
3428 contentLoader.setURLPolicy(
Richard S. Hallfb5221e2006-02-20 10:22:28 +00003429// TODO: ML - SUCKS NEEDING URL POLICY PER MODULE.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003430 new URLPolicyImpl(
3431 m_logger, m_bundleStreamHandler, module));
3432
3433 // Set the module's content loader to the created content loader.
3434 m_factory.setContentLoader(module, contentLoader);
3435
Richard S. Hall5eda19c2008-02-29 19:52:53 +00003436 // Verify that all native libraries exist in advance; this will
3437 // throw an exception if the native library does not exist.
3438 // TODO: CACHE - It would be nice if this check could be done
3439 // some place else in the module, perhaps.
3440 R4Library[] libs = md.getLibraries();
3441 for (int i = 0; (libs != null) && (i < libs.length); i++)
3442 {
3443 String entryName = libs[i].getEntryName();
3444 if (entryName != null)
3445 {
3446 if (contentLoader.getContent().getEntryAsNativeLibrary(entryName) == null)
3447 {
3448 // The content loader was opened when trying to find the libraries,
3449 // so make sure to close it since it will be deleted.
3450 contentLoader.close();
3451 throw new BundleException("Native library does not exist: " + entryName);
3452 }
3453 }
3454 }
3455
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003456 // Done, so return the module.
Richard S. Hall930fecc2005-08-16 18:33:34 +00003457 return module;
3458 }
3459
3460 private BundleActivator createBundleActivator(BundleInfo info)
3461 throws Exception
3462 {
3463 // CONCURRENCY NOTE:
3464 // This method is called indirectly from startBundle() (via _startBundle()),
3465 // which has the exclusion lock, so there is no need to do any locking here.
Karl Pauls836bb402006-08-24 12:39:46 +00003466
Richard S. Hall930fecc2005-08-16 18:33:34 +00003467 BundleActivator activator = null;
Karl Pauls836bb402006-08-24 12:39:46 +00003468
Richard S. Hall471e3e62007-07-11 19:25:33 +00003469 String strict = (String) m_configMap.get(FelixConstants.STRICT_OSGI_PROP);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003470 boolean isStrict = (strict == null) ? true : strict.equals("true");
3471 if (!isStrict)
3472 {
3473 try
3474 {
Richard S. Hall219b0a22008-09-05 21:38:05 +00003475 activator = info.getArchive().getActivator(info.getCurrentModule());
Richard S. Hall930fecc2005-08-16 18:33:34 +00003476 }
3477 catch (Exception ex)
3478 {
3479 activator = null;
3480 }
3481 }
Karl Pauls836bb402006-08-24 12:39:46 +00003482
Richard S. Hall930fecc2005-08-16 18:33:34 +00003483 // If there was no cached activator, then get the activator
3484 // class from the bundle manifest.
3485 if (activator == null)
3486 {
Richard S. Hall219b0a22008-09-05 21:38:05 +00003487 // Get the activator class from the header map.
3488 Map headerMap = info.getCurrentHeader();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003489 String className = (String) headerMap.get(Constants.BUNDLE_ACTIVATOR);
3490 // Try to instantiate activator class if present.
3491 if (className != null)
3492 {
3493 className = className.trim();
Karl Paulsb6ad9922008-08-20 16:37:33 +00003494 Class clazz;
3495 try
Richard S. Hall930fecc2005-08-16 18:33:34 +00003496 {
Karl Paulsb6ad9922008-08-20 16:37:33 +00003497 clazz = info.getCurrentModule().getClass(className);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003498 }
Karl Paulsb6ad9922008-08-20 16:37:33 +00003499 catch (ClassNotFoundException ex) {
3500 throw new BundleException("Not found: "
3501 + className, ex);
3502 }
3503
Richard S. Hall930fecc2005-08-16 18:33:34 +00003504 activator = (BundleActivator) clazz.newInstance();
3505 }
3506 }
Karl Pauls836bb402006-08-24 12:39:46 +00003507
Richard S. Hall930fecc2005-08-16 18:33:34 +00003508 return activator;
3509 }
3510
Richard S. Hall26b91982007-07-04 21:15:05 +00003511 private void purgeBundle(FelixBundle bundle) throws Exception
Richard S. Hall930fecc2005-08-16 18:33:34 +00003512 {
3513 // Acquire bundle lock.
3514 acquireBundleLock(bundle);
3515
3516 try
3517 {
3518 BundleInfo info = bundle.getInfo();
Karl Pauls836bb402006-08-24 12:39:46 +00003519
Richard S. Hall930fecc2005-08-16 18:33:34 +00003520 // In case of a refresh, then we want to physically
3521 // remove the bundle's modules from the module manager.
3522 // This is necessary for two reasons: 1) because
3523 // under Windows we won't be able to delete the bundle
3524 // because files might be left open in the resource
3525 // sources of its modules and 2) we want to make sure
3526 // that no references to old modules exist since they
3527 // will all be stale after the refresh. The only other
3528 // way to do this is to remove the bundle, but that
3529 // would be incorrect, because this is a refresh operation
3530 // and should not trigger bundle REMOVE events.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003531 IModule[] modules = info.getModules();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003532 for (int i = 0; i < modules.length; i++)
3533 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003534 m_factory.removeModule(modules[i]);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003535 }
3536
3537 // Purge all bundle revisions, but the current one.
Richard S. Hall7c9da3d2006-02-24 20:09:28 +00003538 m_cache.getArchive(info.getBundleId()).purge();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003539 }
3540 finally
3541 {
3542 // Always release the bundle lock.
3543 releaseBundleLock(bundle);
3544 }
3545 }
3546
Richard S. Hall26b91982007-07-04 21:15:05 +00003547 private void garbageCollectBundle(FelixBundle bundle) throws Exception
Richard S. Hall930fecc2005-08-16 18:33:34 +00003548 {
3549 // CONCURRENCY NOTE: There is no reason to lock this bundle,
3550 // because this method is only called during shutdown or a
3551 // refresh operation and these are already guarded by locks.
3552
3553 // Remove the bundle's associated modules from
3554 // the module manager.
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003555 IModule[] modules = bundle.getInfo().getModules();
Richard S. Hall930fecc2005-08-16 18:33:34 +00003556 for (int i = 0; i < modules.length; i++)
3557 {
Richard S. Hall29a4fbc2006-02-03 12:54:52 +00003558 m_factory.removeModule(modules[i]);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003559 }
3560
3561 // Remove the bundle from the cache.
Karl Paulsa7e36b82008-04-13 19:09:20 +00003562 m_cache.remove(m_cache.getArchive(bundle.getBundleId()));
Richard S. Hall930fecc2005-08-16 18:33:34 +00003563 }
3564
3565 //
3566 // Event-related methods.
3567 //
3568
3569 /**
3570 * Fires bundle events.
3571 **/
3572 private void fireFrameworkEvent(
3573 int type, Bundle bundle, Throwable throwable)
3574 {
Richard S. Hall92770632006-07-24 10:18:52 +00003575 m_dispatcher.fireFrameworkEvent(new FrameworkEvent(type, bundle, throwable));
Richard S. Hall930fecc2005-08-16 18:33:34 +00003576 }
3577
3578 /**
3579 * Fires bundle events.
3580 *
3581 * @param type The type of bundle event to fire.
3582 * @param bundle The bundle associated with the event.
3583 **/
3584 private void fireBundleEvent(int type, Bundle bundle)
3585 {
Richard S. Hall92770632006-07-24 10:18:52 +00003586 m_dispatcher.fireBundleEvent(new BundleEvent(type, bundle));
Richard S. Hall930fecc2005-08-16 18:33:34 +00003587 }
3588
3589 /**
3590 * Fires service events.
3591 *
3592 * @param type The type of service event to fire.
3593 * @param ref The service reference associated with the event.
3594 **/
3595 private void fireServiceEvent(ServiceEvent event)
3596 {
Richard S. Hall92770632006-07-24 10:18:52 +00003597 m_dispatcher.fireServiceEvent(event);
Richard S. Hall930fecc2005-08-16 18:33:34 +00003598 }
3599
3600 //
3601 // Property related methods.
3602 //
3603
3604 private void initializeFrameworkProperties()
3605 {
3606 // Standard OSGi properties.
Richard S. Hall471e3e62007-07-11 19:25:33 +00003607 m_configMutableMap.put(
Richard S. Hall930fecc2005-08-16 18:33:34 +00003608 FelixConstants.FRAMEWORK_VERSION,
3609 FelixConstants.FRAMEWORK_VERSION_VALUE);
Richard S. Hall471e3e62007-07-11 19:25:33 +00003610 m_configMutableMap.put(
Richard S. Hall930fecc2005-08-16 18:33:34 +00003611 FelixConstants.FRAMEWORK_VENDOR,
3612 FelixConstants.FRAMEWORK_VENDOR_VALUE);
Richard S. Hall471e3e62007-07-11 19:25:33 +00003613 m_configMutableMap.put(
Richard S. Hall930fecc2005-08-16 18:33:34 +00003614 FelixConstants.FRAMEWORK_LANGUAGE,
3615 System.getProperty("user.language"));
Richard S. Hall471e3e62007-07-11 19:25:33 +00003616 m_configMutableMap.put(
Richard S. Hall930fecc2005-08-16 18:33:34 +00003617 FelixConstants.FRAMEWORK_OS_VERSION,
3618 System.getProperty("os.version"));
3619
3620 String s = null;
Richard S. Hall8d116d42006-09-01 19:23:28 +00003621 s = R4LibraryClause.normalizeOSName(System.getProperty("os.name"));
Richard S. Hall471e3e62007-07-11 19:25:33 +00003622 m_configMutableMap.put(FelixConstants.FRAMEWORK_OS_NAME, s);
Richard S. Hall8d116d42006-09-01 19:23:28 +00003623 s = R4LibraryClause.normalizeProcessor(System.getProperty("os.arch"));
Richard S. Hall471e3e62007-07-11 19:25:33 +00003624 m_configMutableMap.put(FelixConstants.FRAMEWORK_PROCESSOR, s);
3625 m_configMutableMap.put(
Richard S. Hall03ddc842006-03-09 14:50:16 +00003626 FelixConstants.FELIX_VERSION_PROPERTY, getFrameworkVersion());
Richard S. Hall930fecc2005-08-16 18:33:34 +00003627 }
3628
Richard S. Hall03ddc842006-03-09 14:50:16 +00003629 /**
3630 * Read the framework version from the property file.
3631 * @return the framework version as a string.
3632 **/
3633 private static String getFrameworkVersion()
Alex Karasulu5cfd2a02006-03-09 14:15:38 +00003634 {
3635 // The framework version property.
3636 Properties props = new Properties();
Richard S. Hall03ddc842006-03-09 14:50:16 +00003637 InputStream in = Felix.class.getResourceAsStream("Felix.properties");
Karl Pauls8da2c202007-11-25 23:08:12 +00003638 if (in != null)
Alex Karasulu5cfd2a02006-03-09 14:15:38 +00003639 {
Karl Pauls8da2c202007-11-25 23:08:12 +00003640 try
3641 {
3642 props.load(in);
3643 }
3644 catch (IOException ex)
3645 {
3646 ex.printStackTrace();
3647 }
Karl Pauls836bb402006-08-24 12:39:46 +00003648 }
3649
Richard S. Halla155e2e2006-03-09 21:20:02 +00003650 // Maven uses a '-' to separate the version qualifier,
3651 // while OSGi uses a '.', so we need to convert to a '.'
3652 StringBuffer sb =
3653 new StringBuffer(
3654 props.getProperty(
Karl Pauls8da2c202007-11-25 23:08:12 +00003655 FelixConstants.FELIX_VERSION_PROPERTY, "0.0.0"));
Richard S. Hall1615e552006-05-30 14:10:06 +00003656 if (sb.toString().indexOf("-") >= 0)
Richard S. Halla155e2e2006-03-09 21:20:02 +00003657 {
Richard S. Hall1615e552006-05-30 14:10:06 +00003658 sb.setCharAt(sb.toString().indexOf("-"), '.');
Richard S. Halla155e2e2006-03-09 21:20:02 +00003659 }
3660 return sb.toString();
Alex Karasulu5cfd2a02006-03-09 14:15:38 +00003661 }
Karl Pauls836bb402006-08-24 12:39:46 +00003662
Richard S. Hall930fecc2005-08-16 18:33:34 +00003663 //
3664 // Private utility methods.
3665 //
3666
3667 /**
3668 * Generated the next valid bundle identifier.
3669 **/
Richard S. Halle60d8782007-08-17 20:10:27 +00003670 private long loadNextId()
3671 {
3672 synchronized (m_nextIdLock)
3673 {
3674 // Read persisted next bundle identifier.
3675 InputStream is = null;
3676 BufferedReader br = null;
3677 try
3678 {
3679 File file = m_cache.getSystemBundleDataFile("bundle.id");
3680 is = m_secureAction.getFileInputStream(file);
3681 br = new BufferedReader(new InputStreamReader(is));
3682 return Long.parseLong(br.readLine());
3683 }
3684 catch (FileNotFoundException ex)
3685 {
3686 // Ignore this case because we assume that this is the
3687 // initial startup of the framework and therefore the
3688 // file does not exist yet.
3689 }
3690 catch (Exception ex)
3691 {
3692 m_logger.log(
3693 Logger.LOG_WARNING,
3694 "Unable to initialize next bundle identifier from persistent storage.",
3695 ex);
3696 }
3697 finally
3698 {
3699 try
3700 {
3701 if (br != null) br.close();
3702 if (is != null) is.close();
3703 }
3704 catch (Exception ex)
3705 {
3706 m_logger.log(
3707 Logger.LOG_WARNING,
3708 "Unable to close next bundle identifier file.",
3709 ex);
3710 }
3711 }
3712 }
3713
3714 return -1;
3715 }
3716
Richard S. Hall441c7152006-02-17 11:07:10 +00003717 private long getNextId()
Richard S. Hall930fecc2005-08-16 18:33:34 +00003718 {
Richard S. Hall441c7152006-02-17 11:07:10 +00003719 synchronized (m_nextIdLock)
3720 {
Richard S. Halle60d8782007-08-17 20:10:27 +00003721 // Save the current id.
3722 long id = m_nextId;
3723
3724 // Increment the next id.
3725 m_nextId++;
3726
3727 // Write the bundle state.
3728 OutputStream os = null;
3729 BufferedWriter bw = null;
3730 try
3731 {
3732 File file = m_cache.getSystemBundleDataFile("bundle.id");
3733 os = m_secureAction.getFileOutputStream(file);
3734 bw = new BufferedWriter(new OutputStreamWriter(os));
3735 String s = Long.toString(m_nextId);
3736 bw.write(s, 0, s.length());
3737 }
3738 catch (Exception ex)
3739 {
3740 m_logger.log(
3741 Logger.LOG_WARNING,
3742 "Unable to save next bundle identifier to persistent storage.",
3743 ex);
3744 }
3745 finally
3746 {
3747 try
3748 {
3749 if (bw != null) bw.close();
3750 if (os != null) os.close();
3751 }
3752 catch (Exception ex)
3753 {
3754 m_logger.log(
3755 Logger.LOG_WARNING,
3756 "Unable to close next bundle identifier file.",
3757 ex);
3758 }
3759 }
3760
3761 return id;
Richard S. Hall441c7152006-02-17 11:07:10 +00003762 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003763 }
3764
3765 //
Richard S. Hall26b91982007-07-04 21:15:05 +00003766 // Miscellaneous inner classes.
Richard S. Hall930fecc2005-08-16 18:33:34 +00003767 //
3768
Richard S. Hall26b91982007-07-04 21:15:05 +00003769 class SystemBundleActivator implements BundleActivator, Runnable
Richard S. Hall930fecc2005-08-16 18:33:34 +00003770 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003771 public void start(BundleContext context) throws Exception
Richard S. Hall930fecc2005-08-16 18:33:34 +00003772 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003773 // Add the bundle activator for the package admin service.
Richard S. Hall7adef032007-12-14 21:55:01 +00003774 m_activatorList.add(0, new PackageAdminActivator(Felix.this));
Richard S. Hall26b91982007-07-04 21:15:05 +00003775 // Add the bundle activator for the start level service.
Richard S. Hall7adef032007-12-14 21:55:01 +00003776 m_activatorList.add(0, new StartLevelActivator(m_logger, Felix.this));
Richard S. Hall26b91982007-07-04 21:15:05 +00003777 // Add the bundle activator for the url handler service.
Richard S. Hall7adef032007-12-14 21:55:01 +00003778 m_activatorList.add(0, new URLHandlersActivator(m_configMap, Felix.this));
Richard S. Hall26b91982007-07-04 21:15:05 +00003779
3780 // Start all activators.
3781 for (int i = 0; i < m_activatorList.size(); i++)
3782 {
3783 Felix.m_secureAction.startActivator(
3784 (BundleActivator) m_activatorList.get(i), context);
3785 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003786 }
3787
Richard S. Hall26b91982007-07-04 21:15:05 +00003788 public void stop(BundleContext context)
Richard S. Hall930fecc2005-08-16 18:33:34 +00003789 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003790 // Spec says stop() on SystemBundle should return immediately and
3791 // shutdown framework on another thread.
3792 if (m_shutdownThread == null)
3793 {
3794 // Initial call of stop, so kick off shutdown.
3795 m_shutdownThread = new Thread(this, "FelixShutdown");
3796 m_shutdownThread.start();
3797 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003798 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003799
Richard S. Hall26b91982007-07-04 21:15:05 +00003800 public void run()
3801 {
3802 // First, start the framework shutdown, which will
3803 // stop all bundles.
Richard S. Hall675b0552007-07-23 17:03:39 +00003804 synchronized (Felix.this)
Richard S. Hall26b91982007-07-04 21:15:05 +00003805 {
3806 // Change framework state from active to stopping.
3807 // If framework is not active, then just return.
3808 if (m_systemBundleInfo.getState() != Bundle.STOPPING)
3809 {
3810 return;
3811 }
3812 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003813
Richard S. Hall26b91982007-07-04 21:15:05 +00003814 // Use the start level service to set the start level to zero
3815 // in order to stop all bundles in the framework. Since framework
3816 // shutdown happens on its own thread, we can wait for the start
3817 // level service to finish before proceeding by calling the
3818 // non-spec setStartLevelAndWait() method.
3819 try
3820 {
3821 StartLevelImpl sl = (StartLevelImpl) getService(
3822 Felix.this,
3823 getServiceReferences(Felix.this, StartLevel.class.getName(), null, true)[0]);
3824 sl.setStartLevelAndWait(0);
3825 }
3826 catch (InvalidSyntaxException ex)
3827 {
3828 // Should never happen.
3829 }
3830
3831 // Since there may be updated and uninstalled bundles that
3832 // have not been refreshed, we will take care of refreshing
3833 // them during shutdown.
3834
3835 // First loop through all bundled and purge old revisions
3836 // from updated bundles.
3837 Bundle[] bundles = getBundles();
3838 for (int i = 0; i < bundles.length; i++)
3839 {
3840 FelixBundle bundle = (FelixBundle) bundles[i];
3841 if (bundle.getInfo().getArchive().getRevisionCount() > 1)
3842 {
3843 try
3844 {
3845 purgeBundle(bundle);
3846 }
3847 catch (Exception ex)
3848 {
3849 fireFrameworkEvent(FrameworkEvent.ERROR, bundle, ex);
3850 m_logger.log(Logger.LOG_ERROR, "Unable to purge bundle "
3851 + bundle.getInfo().getLocation(), ex);
3852 }
3853 }
3854 }
3855
3856 // Next garbage collection any uninstalled bundles.
3857 for (int i = 0;
3858 (m_uninstalledBundles != null) && (i < m_uninstalledBundles.length);
3859 i++)
3860 {
3861 try
3862 {
3863 garbageCollectBundle(m_uninstalledBundles[i]);
3864 }
3865 catch (Exception ex)
3866 {
3867 m_logger.log(
3868 Logger.LOG_ERROR,
3869 "Unable to remove "
3870 + m_uninstalledBundles[i].getInfo().getLocation(), ex);
3871 }
3872 }
3873
3874 // Shutdown event dispatching queue.
3875 EventDispatcher.shutdown();
3876
3877 // Remove all bundles from the module factory so that any
3878 // open resources will be closed.
3879 bundles = getBundles();
3880 for (int i = 0; i < bundles.length; i++)
3881 {
3882 FelixBundle bundle = (FelixBundle) bundles[i];
3883 IModule[] modules = bundle.getInfo().getModules();
3884 for (int j = 0; j < modules.length; j++)
3885 {
3886 try
3887 {
3888 m_factory.removeModule(modules[j]);
3889 }
3890 catch (Exception ex)
3891 {
3892 m_logger.log(Logger.LOG_ERROR,
3893 "Unable to clean up " + bundle.getInfo().getLocation(), ex);
3894 }
3895 }
3896 }
3897
3898 // Next, stop all system bundle activators.
Karl Pauls758c2be2008-03-05 13:10:04 +00003899 for (int i = 0; i < m_activatorList.size(); i++)
Richard S. Hall26b91982007-07-04 21:15:05 +00003900 {
Karl Pauls758c2be2008-03-05 13:10:04 +00003901 try
Richard S. Hall26b91982007-07-04 21:15:05 +00003902 {
Richard S. Hall2846a2b2008-06-01 03:08:17 +00003903 Felix.m_secureAction.stopActivator((BundleActivator)
Karl Pauls758c2be2008-03-05 13:10:04 +00003904 m_activatorList.get(i), getInfo().getBundleContext());
3905 }
3906 catch (Throwable throwable)
3907 {
3908 m_logger.log(
3909 Logger.LOG_WARNING,
3910 "Exception stopping a system bundle activator.",
3911 throwable);
Richard S. Hall26b91982007-07-04 21:15:05 +00003912 }
3913 }
3914
3915 if (m_extensionManager != null)
3916 {
3917 m_extensionManager.removeExtensions(Felix.this);
3918 }
3919
3920 // Notify any waiters that the framework is back in its initial state.
Richard S. Hall675b0552007-07-23 17:03:39 +00003921 synchronized (Felix.this)
Richard S. Hall26b91982007-07-04 21:15:05 +00003922 {
3923 m_systemBundleInfo.setState(Bundle.UNINSTALLED);
Richard S. Hall675b0552007-07-23 17:03:39 +00003924 Felix.this.notifyAll();
Richard S. Hall26b91982007-07-04 21:15:05 +00003925 }
3926
3927 // Finally shutdown the JVM if the framework is running stand-alone.
Richard S. Hall471e3e62007-07-11 19:25:33 +00003928 String embedded = (String) m_configMap.get(FelixConstants.EMBEDDED_EXECUTION_PROP);
Richard S. Hall26b91982007-07-04 21:15:05 +00003929 boolean isEmbedded = (embedded == null) ? false : embedded.equals("true");
3930 if (!isEmbedded)
3931 {
3932 m_secureAction.exit(0);
3933 }
3934 }
Richard S. Hall930fecc2005-08-16 18:33:34 +00003935 }
3936
3937 /**
3938 * Simple class that is used in <tt>refreshPackages()</tt> to embody
3939 * the refresh logic in order to keep the code clean. This class is
3940 * not static because it needs access to framework event firing methods.
3941 **/
3942 private class RefreshHelper
3943 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003944 private FelixBundle m_bundle = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00003945
3946 public RefreshHelper(Bundle bundle)
3947 {
Richard S. Hall26b91982007-07-04 21:15:05 +00003948 m_bundle = (FelixBundle) bundle;
Richard S. Hall930fecc2005-08-16 18:33:34 +00003949 }
3950
3951 public void stop()
3952 {
3953 if (m_bundle.getInfo().getState() == Bundle.ACTIVE)
3954 {
3955 try
3956 {
3957 stopBundle(m_bundle, false);
3958 }
3959 catch (BundleException ex)
3960 {
3961 fireFrameworkEvent(FrameworkEvent.ERROR, m_bundle, ex);
3962 }
3963 }
3964 }
3965
3966 public void purgeOrRemove()
3967 {
3968 try
3969 {
3970 BundleInfo info = m_bundle.getInfo();
3971
Richard S. Halle1f53a52006-07-17 11:06:59 +00003972 // Mark the bundle as stale.
3973 info.setStale();
3974
Richard S. Hall930fecc2005-08-16 18:33:34 +00003975 // Remove or purge the bundle depending on its
3976 // current state.
3977 if (info.getState() == Bundle.UNINSTALLED)
3978 {
3979 // This physically removes the bundle from memory
3980 // as well as the bundle cache.
3981 garbageCollectBundle(m_bundle);
3982 m_bundle = null;
3983 }
3984 else
3985 {
3986 // This physically removes all old revisions of the
3987 // bundle from memory and only maintains the newest
3988 // version in the bundle cache.
3989 purgeBundle(m_bundle);
3990 }
3991 }
3992 catch (Exception ex)
3993 {
3994 fireFrameworkEvent(FrameworkEvent.ERROR, m_bundle, ex);
3995 }
3996 }
3997
3998 public void reinitialize()
3999 {
4000 if (m_bundle != null)
4001 {
4002 try
4003 {
4004 BundleInfo info = m_bundle.getInfo();
Richard S. Hall219b0a22008-09-05 21:38:05 +00004005 BundleInfo newInfo = createBundleInfo(
4006 info.getArchive(), info.getCurrentHeader(), info.isExtension());
Richard S. Hall930fecc2005-08-16 18:33:34 +00004007 newInfo.syncLock(info);
Richard S. Hall26b91982007-07-04 21:15:05 +00004008 ((BundleImpl) m_bundle).setInfo(newInfo);
Karl Pauls28636dc2008-02-03 21:32:48 +00004009 addSecurity(m_bundle);
Richard S. Hall2dea05f2006-07-25 10:18:20 +00004010 fireBundleEvent(BundleEvent.UNRESOLVED, m_bundle);
Richard S. Hall930fecc2005-08-16 18:33:34 +00004011 }
4012 catch (Exception ex)
4013 {
4014 fireFrameworkEvent(FrameworkEvent.ERROR, m_bundle, ex);
4015 }
4016 }
4017 }
4018
4019 public void restart()
4020 {
4021 if (m_bundle != null)
4022 {
4023 try
4024 {
4025 startBundle(m_bundle, false);
4026 }
4027 catch (BundleException ex)
4028 {
4029 fireFrameworkEvent(FrameworkEvent.ERROR, m_bundle, ex);
4030 }
4031 }
4032 }
4033 }
4034
4035 //
4036 // Locking related methods.
4037 //
4038
Richard S. Hall26b91982007-07-04 21:15:05 +00004039 private void rememberUninstalledBundle(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004040 {
4041 synchronized (m_uninstalledBundlesLock_Priority3)
4042 {
4043 // Verify that the bundle is not already in the array.
4044 for (int i = 0;
4045 (m_uninstalledBundles != null) && (i < m_uninstalledBundles.length);
4046 i++)
4047 {
4048 if (m_uninstalledBundles[i] == bundle)
4049 {
4050 return;
4051 }
4052 }
4053
4054 if (m_uninstalledBundles != null)
4055 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004056 FelixBundle[] newBundles =
4057 new FelixBundle[m_uninstalledBundles.length + 1];
Richard S. Hall930fecc2005-08-16 18:33:34 +00004058 System.arraycopy(m_uninstalledBundles, 0,
4059 newBundles, 0, m_uninstalledBundles.length);
4060 newBundles[m_uninstalledBundles.length] = bundle;
4061 m_uninstalledBundles = newBundles;
4062 }
4063 else
4064 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004065 m_uninstalledBundles = new FelixBundle[] { bundle };
Richard S. Hall930fecc2005-08-16 18:33:34 +00004066 }
4067 }
4068 }
4069
Richard S. Hall26b91982007-07-04 21:15:05 +00004070 private void forgetUninstalledBundle(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004071 {
4072 synchronized (m_uninstalledBundlesLock_Priority3)
4073 {
4074 if (m_uninstalledBundles == null)
4075 {
4076 return;
4077 }
Karl Pauls836bb402006-08-24 12:39:46 +00004078
Richard S. Hall930fecc2005-08-16 18:33:34 +00004079 int idx = -1;
4080 for (int i = 0; i < m_uninstalledBundles.length; i++)
4081 {
4082 if (m_uninstalledBundles[i] == bundle)
4083 {
4084 idx = i;
4085 break;
4086 }
4087 }
Karl Pauls836bb402006-08-24 12:39:46 +00004088
Richard S. Hall930fecc2005-08-16 18:33:34 +00004089 if (idx >= 0)
4090 {
4091 // If this is the only bundle, then point to empty list.
4092 if ((m_uninstalledBundles.length - 1) == 0)
4093 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004094 m_uninstalledBundles = new FelixBundle[0];
Richard S. Hall930fecc2005-08-16 18:33:34 +00004095 }
4096 // Otherwise, we need to do some array copying.
4097 else
4098 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004099 FelixBundle[] newBundles =
4100 new FelixBundle[m_uninstalledBundles.length - 1];
Richard S. Hall930fecc2005-08-16 18:33:34 +00004101 System.arraycopy(m_uninstalledBundles, 0, newBundles, 0, idx);
4102 if (idx < newBundles.length)
4103 {
4104 System.arraycopy(
4105 m_uninstalledBundles, idx + 1,
4106 newBundles, idx, newBundles.length - idx);
4107 }
4108 m_uninstalledBundles = newBundles;
4109 }
4110 }
4111 }
4112 }
4113
4114 protected void acquireInstallLock(String location)
4115 throws BundleException
4116 {
4117 synchronized (m_installRequestLock_Priority1)
4118 {
4119 while (m_installRequestMap.get(location) != null)
4120 {
4121 try
4122 {
4123 m_installRequestLock_Priority1.wait();
4124 }
4125 catch (InterruptedException ex)
4126 {
4127 throw new BundleException("Unable to install, thread interrupted.");
4128 }
4129 }
Karl Pauls836bb402006-08-24 12:39:46 +00004130
Richard S. Hall930fecc2005-08-16 18:33:34 +00004131 m_installRequestMap.put(location, location);
4132 }
4133 }
Karl Pauls836bb402006-08-24 12:39:46 +00004134
Richard S. Hall930fecc2005-08-16 18:33:34 +00004135 protected void releaseInstallLock(String location)
4136 {
4137 synchronized (m_installRequestLock_Priority1)
4138 {
4139 m_installRequestMap.remove(location);
4140 m_installRequestLock_Priority1.notifyAll();
4141 }
4142 }
4143
Richard S. Hall26b91982007-07-04 21:15:05 +00004144 protected void acquireBundleLock(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004145 {
4146 synchronized (m_bundleLock)
4147 {
4148 while (!bundle.getInfo().isLockable())
4149 {
4150 try
4151 {
4152 m_bundleLock.wait();
4153 }
4154 catch (InterruptedException ex)
4155 {
4156 // Ignore and just keep waiting.
4157 }
4158 }
4159 bundle.getInfo().lock();
4160 }
4161 }
Karl Pauls836bb402006-08-24 12:39:46 +00004162
Richard S. Hall26b91982007-07-04 21:15:05 +00004163 protected boolean acquireBundleLockOrFail(FelixBundle bundle)
Richard S. Hall3c26cc02006-02-17 13:51:21 +00004164 {
4165 synchronized (m_bundleLock)
4166 {
4167 if (!bundle.getInfo().isLockable())
4168 {
4169 return false;
4170 }
4171 bundle.getInfo().lock();
4172 return true;
4173 }
4174 }
4175
Richard S. Hall26b91982007-07-04 21:15:05 +00004176 protected void releaseBundleLock(FelixBundle bundle)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004177 {
4178 synchronized (m_bundleLock)
4179 {
4180 bundle.getInfo().unlock();
4181 m_bundleLock.notifyAll();
4182 }
4183 }
4184
Richard S. Hall26b91982007-07-04 21:15:05 +00004185 protected FelixBundle[] acquireBundleResolveLocks(Bundle[] targets)
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004186 {
4187 // Hold bundles to be locked.
Richard S. Hall26b91982007-07-04 21:15:05 +00004188 FelixBundle[] bundles = null;
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004189 // Convert existing target bundle array to bundle impl array.
4190 if (targets != null)
4191 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004192 bundles = new FelixBundle[targets.length];
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004193 for (int i = 0; i < targets.length; i++)
4194 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004195 bundles[i] = (FelixBundle) targets[i];
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004196 }
4197 }
4198
4199 synchronized (m_bundleLock)
4200 {
4201 boolean success = false;
4202 while (!success)
4203 {
4204 // If targets is null, then resolve all unresolved bundles.
4205 if (targets == null)
4206 {
4207 List list = new ArrayList();
4208
4209 // Add all unresolved bundles to the list.
4210 synchronized (m_installedBundleLock_Priority2)
4211 {
4212 Iterator iter = m_installedBundleMap.values().iterator();
4213 while (iter.hasNext())
4214 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004215 FelixBundle bundle = (FelixBundle) iter.next();
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004216 if (bundle.getInfo().getState() == Bundle.INSTALLED)
4217 {
4218 list.add(bundle);
4219 }
4220 }
4221 }
4222
4223 // Create an array.
4224 if (list.size() > 0)
4225 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004226 bundles = (FelixBundle[]) list.toArray(new FelixBundle[list.size()]);
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004227 }
4228 }
Karl Pauls836bb402006-08-24 12:39:46 +00004229
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004230 // Check if all unresolved bundles can be locked.
4231 boolean lockable = true;
4232 if (bundles != null)
4233 {
4234 for (int i = 0; lockable && (i < bundles.length); i++)
4235 {
4236 lockable = bundles[i].getInfo().isLockable();
4237 }
Karl Pauls836bb402006-08-24 12:39:46 +00004238
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004239 // If we can lock all bundles, then lock them.
4240 if (lockable)
4241 {
4242 for (int i = 0; i < bundles.length; i++)
4243 {
4244 bundles[i].getInfo().lock();
4245 }
4246 success = true;
4247 }
4248 // Otherwise, wait and try again.
4249 else
4250 {
4251 try
4252 {
4253 m_bundleLock.wait();
4254 }
4255 catch (InterruptedException ex)
4256 {
4257 // Ignore and just keep waiting.
4258 }
4259 }
4260 }
4261 else
4262 {
4263 // If there were no bundles to lock, then we can just
4264 // exit the lock loop.
4265 success = true;
4266 }
4267 }
4268 }
4269
4270 return bundles;
4271 }
4272
Richard S. Hall26b91982007-07-04 21:15:05 +00004273 protected FelixBundle[] acquireBundleRefreshLocks(Bundle[] targets)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004274 {
4275 // Hold bundles to be locked.
Richard S. Hall26b91982007-07-04 21:15:05 +00004276 FelixBundle[] bundles = null;
Richard S. Hall930fecc2005-08-16 18:33:34 +00004277
4278 synchronized (m_bundleLock)
4279 {
4280 boolean success = false;
4281 while (!success)
4282 {
4283 // If targets is null, then refresh all pending bundles.
4284 Bundle[] newTargets = targets;
4285 if (newTargets == null)
4286 {
4287 List list = new ArrayList();
4288
4289 // First add all uninstalled bundles.
4290 synchronized (m_uninstalledBundlesLock_Priority3)
4291 {
4292 for (int i = 0;
4293 (m_uninstalledBundles != null) && (i < m_uninstalledBundles.length);
4294 i++)
4295 {
4296 list.add(m_uninstalledBundles[i]);
4297 }
4298 }
4299
4300 // Then add all updated bundles.
4301 synchronized (m_installedBundleLock_Priority2)
4302 {
4303 Iterator iter = m_installedBundleMap.values().iterator();
4304 while (iter.hasNext())
4305 {
Richard S. Hall26b91982007-07-04 21:15:05 +00004306 FelixBundle bundle = (FelixBundle) iter.next();
Richard S. Hall60c26d42006-07-19 10:35:04 +00004307 if (bundle.getInfo().getArchive().getRevisionCount() > 1)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004308 {
4309 list.add(bundle);
4310 }
4311 }
4312 }
4313
4314 // Create an array.
4315 if (list.size() > 0)
4316 {
4317 newTargets = (Bundle[]) list.toArray(new Bundle[list.size()]);
4318 }
4319 }
4320
4321 // If there are targets, then find all dependencies
4322 // for each one.
4323 if (newTargets != null)
4324 {
4325 // Create map of bundles that import the packages
4326 // from the target bundles.
4327 Map map = new HashMap();
4328 for (int targetIdx = 0; targetIdx < newTargets.length; targetIdx++)
4329 {
4330 // Add the current target bundle to the map of
4331 // bundles to be refreshed.
Richard S. Hall26b91982007-07-04 21:15:05 +00004332 FelixBundle target = (FelixBundle) newTargets[targetIdx];
Richard S. Hall930fecc2005-08-16 18:33:34 +00004333 map.put(target, target);
4334 // Add all importing bundles to map.
4335 populateImportGraph(target, map);
4336 }
Karl Pauls836bb402006-08-24 12:39:46 +00004337
Richard S. Hall26b91982007-07-04 21:15:05 +00004338 bundles = (FelixBundle[]) map.values().toArray(new FelixBundle[map.size()]);
Richard S. Hall930fecc2005-08-16 18:33:34 +00004339 }
Karl Pauls836bb402006-08-24 12:39:46 +00004340
Richard S. Hall1a4ab602006-05-24 13:46:06 +00004341 // Check if all corresponding bundles can be locked.
Richard S. Hall930fecc2005-08-16 18:33:34 +00004342 boolean lockable = true;
4343 if (bundles != null)
4344 {
4345 for (int i = 0; lockable && (i < bundles.length); i++)
4346 {
4347 lockable = bundles[i].getInfo().isLockable();
4348 }
Karl Pauls836bb402006-08-24 12:39:46 +00004349
Richard S. Hall930fecc2005-08-16 18:33:34 +00004350 // If we can lock all bundles, then lock them.
4351 if (lockable)
4352 {
4353 for (int i = 0; i < bundles.length; i++)
4354 {
4355 bundles[i].getInfo().lock();
4356 }
4357 success = true;
4358 }
4359 // Otherwise, wait and try again.
4360 else
4361 {
4362 try
4363 {
4364 m_bundleLock.wait();
4365 }
4366 catch (InterruptedException ex)
4367 {
4368 // Ignore and just keep waiting.
4369 }
4370 }
4371 }
4372 else
4373 {
4374 // If there were no bundles to lock, then we can just
4375 // exit the lock loop.
4376 success = true;
4377 }
4378 }
4379 }
4380
4381 return bundles;
4382 }
4383
Richard S. Hall26b91982007-07-04 21:15:05 +00004384 protected void releaseBundleLocks(FelixBundle[] bundles)
Richard S. Hall930fecc2005-08-16 18:33:34 +00004385 {
4386 // Always unlock any locked bundles.
4387 synchronized (m_bundleLock)
4388 {
4389 for (int i = 0; (bundles != null) && (i < bundles.length); i++)
4390 {
4391 bundles[i].getInfo().unlock();
4392 }
4393 m_bundleLock.notifyAll();
4394 }
4395 }
Richard S. Hall9b2a3292008-03-01 23:49:01 +00004396}