Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 1 | /* |
Richard S. Hall | e449eca | 2006-09-28 20:00:47 +0000 | [diff] [blame] | 2 | * 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. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 9 | * |
Richard S. Hall | e449eca | 2006-09-28 20:00:47 +0000 | [diff] [blame] | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 11 | * |
Richard S. Hall | e449eca | 2006-09-28 20:00:47 +0000 | [diff] [blame] | 12 | * 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. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 18 | */ |
Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 19 | package org.apache.felix.scr.impl; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 20 | |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 21 | |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 22 | import java.io.PrintStream; |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 23 | import java.text.MessageFormat; |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 24 | import java.util.HashMap; |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 25 | import java.util.Map; |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 26 | import java.util.concurrent.CountDownLatch; |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 27 | import java.util.concurrent.TimeUnit; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 28 | |
Felix Meschberger | 2136bed | 2009-11-26 10:08:12 +0000 | [diff] [blame] | 29 | import org.apache.felix.scr.impl.config.ScrConfiguration; |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 30 | import org.apache.felix.utils.extender.AbstractExtender; |
| 31 | import org.apache.felix.utils.extender.Extension; |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 32 | import org.osgi.framework.Bundle; |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 33 | import org.osgi.framework.BundleContext; |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 34 | import org.osgi.framework.Constants; |
Felix Meschberger | ba3da7a | 2009-07-09 12:26:58 +0000 | [diff] [blame] | 35 | import org.osgi.service.component.ComponentConstants; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 36 | import org.osgi.service.log.LogService; |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 37 | import org.osgi.util.tracker.ServiceTracker; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 38 | |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 39 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 40 | /** |
| 41 | * This activator is used to cover requirement described in section 112.8.1 @@ -27,14 |
| 42 | * 37,202 @@ in active bundles. |
Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 43 | * |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 44 | */ |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 45 | public class Activator extends AbstractExtender |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 46 | { |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 47 | // name of the LogService class (this is a string to not create a reference to the class) |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 48 | static final String LOGSERVICE_CLASS = "org.osgi.service.log.LogService"; |
| 49 | |
Felix Meschberger | 08aaff6 | 2010-08-05 13:26:31 +0000 | [diff] [blame] | 50 | // name of the PackageAdmin class (this is a string to not create a reference to the class) |
| 51 | static final String PACKAGEADMIN_CLASS = "org.osgi.service.packageadmin.PackageAdmin"; |
| 52 | |
Felix Meschberger | 2136bed | 2009-11-26 10:08:12 +0000 | [diff] [blame] | 53 | // Our configuration from bundle context properties and Config Admin |
David Jencks | 2d3a00a | 2014-04-27 06:58:04 +0000 | [diff] [blame^] | 54 | private static ScrConfiguration m_configuration; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 55 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 56 | // this bundle's context |
Felix Meschberger | 08aaff6 | 2010-08-05 13:26:31 +0000 | [diff] [blame] | 57 | private static BundleContext m_context; |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 58 | |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 59 | // this bundle |
| 60 | private static Bundle m_bundle; |
| 61 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 62 | // the log service to log messages to |
David Jencks | 081fa83 | 2013-05-09 05:50:38 +0000 | [diff] [blame] | 63 | private static volatile ServiceTracker m_logService; |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 64 | |
Felix Meschberger | 08aaff6 | 2010-08-05 13:26:31 +0000 | [diff] [blame] | 65 | // the package admin service (see BindMethod.getParameterClass) |
David Jencks | 081fa83 | 2013-05-09 05:50:38 +0000 | [diff] [blame] | 66 | private static volatile ServiceTracker m_packageAdmin; |
Felix Meschberger | 08aaff6 | 2010-08-05 13:26:31 +0000 | [diff] [blame] | 67 | |
Felix Meschberger | 64e99f9 | 2009-10-11 08:35:25 +0000 | [diff] [blame] | 68 | // map of BundleComponentActivator instances per Bundle indexed by Bundle id |
David Jencks | eeb03d2 | 2012-11-29 23:53:21 +0000 | [diff] [blame] | 69 | private Map<Long, BundleComponentActivator> m_componentBundles; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 70 | |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 71 | // registry of managed component |
| 72 | private ComponentRegistry m_componentRegistry; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 73 | |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 74 | // thread acting upon configurations |
| 75 | private ComponentActorThread m_componentActor; |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 76 | |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 77 | public Activator() { |
David Jencks | 2d3a00a | 2014-04-27 06:58:04 +0000 | [diff] [blame^] | 78 | m_configuration = new ScrConfiguration( this ); |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 79 | setSynchronous(true); |
| 80 | } |
| 81 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 82 | /** |
| 83 | * Registers this instance as a (synchronous) bundle listener and loads the |
| 84 | * components of already registered bundles. |
Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 85 | * |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 86 | * @param context The <code>BundleContext</code> of the SCR implementation |
| 87 | * bundle. |
| 88 | */ |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 89 | public void start( BundleContext context ) throws Exception |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 90 | { |
| 91 | m_context = context; |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 92 | m_bundle = context.getBundle(); |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 93 | // require the log service |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 94 | m_logService = new ServiceTracker( m_context, LOGSERVICE_CLASS, null ); |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 95 | m_logService.open(); |
David Jencks | 2d3a00a | 2014-04-27 06:58:04 +0000 | [diff] [blame^] | 96 | // get the configuration |
| 97 | m_configuration.start( m_context ); //this will call restart, which calls super.start. |
| 98 | } |
| 99 | |
| 100 | public void restart( boolean globalExtender ) |
| 101 | { |
| 102 | BundleContext context; |
| 103 | if ( globalExtender ) |
| 104 | { |
| 105 | context = m_context.getBundle( 0 ).getBundleContext(); |
| 106 | } |
| 107 | else |
| 108 | { |
| 109 | context = m_context; |
| 110 | } |
| 111 | if ( m_packageAdmin != null ) |
| 112 | { |
| 113 | //this really is a restart, not the initial start |
| 114 | try |
| 115 | { |
| 116 | super.stop(context); |
| 117 | } |
| 118 | catch ( Exception e ) |
| 119 | { |
| 120 | log( LogService.LOG_ERROR, m_bundle, "Exception stopping during restart", e ); |
| 121 | } |
| 122 | } |
| 123 | try |
| 124 | { |
| 125 | super.start( context ); |
| 126 | } |
| 127 | catch ( Exception e ) |
| 128 | { |
| 129 | log( LogService.LOG_ERROR, m_bundle, "Exception starting during restart", e ); |
| 130 | } |
| 131 | |
| 132 | } |
| 133 | |
| 134 | protected void doStart() throws Exception { |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 135 | |
Felix Meschberger | fb1ce2f | 2011-02-04 10:49:51 +0000 | [diff] [blame] | 136 | // prepare component registry |
David Jencks | eeb03d2 | 2012-11-29 23:53:21 +0000 | [diff] [blame] | 137 | m_componentBundles = new HashMap<Long, BundleComponentActivator>(); |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 138 | m_componentRegistry = new ComponentRegistry( m_context ); |
Felix Meschberger | fb1ce2f | 2011-02-04 10:49:51 +0000 | [diff] [blame] | 139 | |
Felix Meschberger | 2136bed | 2009-11-26 10:08:12 +0000 | [diff] [blame] | 140 | |
| 141 | // log SCR startup |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 142 | log( LogService.LOG_INFO, m_bundle, " Version = {0}", |
| 143 | new Object[] {m_bundle.getHeaders().get( Constants.BUNDLE_VERSION )}, null ); |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 144 | |
Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 145 | // create and start the component actor |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 146 | m_componentActor = new ComponentActorThread(); |
Felix Meschberger | f7dfd27 | 2009-10-30 17:26:25 +0000 | [diff] [blame] | 147 | Thread t = new Thread(m_componentActor, "SCR Component Actor"); |
| 148 | t.setDaemon( true ); |
| 149 | t.start(); |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 150 | |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 151 | super.doStart(); |
Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 152 | |
Felix Meschberger | 44add77 | 2010-12-23 18:13:24 +0000 | [diff] [blame] | 153 | // register the Gogo and old Shell commands |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 154 | ScrCommand scrCommand = ScrCommand.register(m_context, m_componentRegistry, m_configuration); |
David Jencks | cb9f942 | 2013-02-04 02:16:11 +0000 | [diff] [blame] | 155 | m_configuration.setScrCommand( scrCommand ); |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 156 | } |
David Jencks | 2d3a00a | 2014-04-27 06:58:04 +0000 | [diff] [blame^] | 157 | |
| 158 | public void stop(BundleContext context) throws Exception |
| 159 | { |
| 160 | super.stop(context); |
| 161 | m_configuration.stop(); |
| 162 | m_configuration = null; |
| 163 | } |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 164 | |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 165 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 166 | /** |
| 167 | * Unregisters this instance as a bundle listener and unloads all components |
| 168 | * which have been registered during the active life time of the SCR |
| 169 | * implementation bundle. |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 170 | */ |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 171 | public void doStop() throws Exception |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 172 | { |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 173 | // stop tracking |
| 174 | super.doStop(); |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 175 | |
Felix Meschberger | 689e5f4 | 2009-07-28 14:06:58 +0000 | [diff] [blame] | 176 | // dispose component registry |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 177 | m_componentRegistry.dispose(); |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 178 | |
Felix Meschberger | f7dfd27 | 2009-10-30 17:26:25 +0000 | [diff] [blame] | 179 | // terminate the actor thread |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 180 | if ( m_componentActor != null ) |
| 181 | { |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 182 | m_componentActor.terminate(); |
Felix Meschberger | f7dfd27 | 2009-10-30 17:26:25 +0000 | [diff] [blame] | 183 | m_componentActor = null; |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 184 | } |
Felix Meschberger | 08aaff6 | 2010-08-05 13:26:31 +0000 | [diff] [blame] | 185 | |
| 186 | // close the LogService tracker now |
| 187 | if ( m_logService != null ) |
| 188 | { |
| 189 | m_logService.close(); |
| 190 | m_logService = null; |
| 191 | } |
| 192 | |
| 193 | // close the PackageAdmin tracker now |
| 194 | if ( m_packageAdmin != null ) |
| 195 | { |
| 196 | m_packageAdmin.close(); |
| 197 | m_packageAdmin = null; |
| 198 | } |
| 199 | |
| 200 | // remove the reference to the component context |
| 201 | m_context = null; |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 202 | } |
| 203 | |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 204 | |
Felix Meschberger | c90e316 | 2007-03-28 14:34:01 +0000 | [diff] [blame] | 205 | //---------- Component Management ----------------------------------------- |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 206 | |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 207 | |
| 208 | @Override |
| 209 | protected Extension doCreateExtension(final Bundle bundle) throws Exception |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 210 | { |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 211 | return new ScrExtension(bundle); |
| 212 | } |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 213 | |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 214 | protected class ScrExtension implements Extension { |
| 215 | |
| 216 | private final Bundle bundle; |
| 217 | private final CountDownLatch started; |
| 218 | |
| 219 | public ScrExtension(Bundle bundle) { |
| 220 | this.bundle = bundle; |
| 221 | this.started = new CountDownLatch(1); |
| 222 | } |
| 223 | |
| 224 | public void start() { |
| 225 | try { |
| 226 | loadComponents( ScrExtension.this.bundle ); |
| 227 | } finally { |
| 228 | started.countDown(); |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 229 | } |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | public void destroy() { |
| 233 | try { |
Guillaume Nodet | 3651814 | 2013-11-20 09:17:46 +0000 | [diff] [blame] | 234 | this.started.await(m_configuration.stopTimeout(), TimeUnit.MILLISECONDS); |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 235 | } catch (InterruptedException e) { |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 236 | log( LogService.LOG_WARNING, m_bundle, "The wait for bundle {0}/{1} being started before destruction has been interrupted.", |
Guillaume Nodet | 6574df2 | 2013-11-13 07:42:20 +0000 | [diff] [blame] | 237 | new Object[] {bundle.getSymbolicName(), bundle.getBundleId()}, e ); |
| 238 | } |
| 239 | disposeComponents( this.bundle ); |
| 240 | } |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 241 | } |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 242 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 243 | /** |
| 244 | * Loads the components of the given bundle. If the bundle has no |
| 245 | * <i>Service-Component</i> header, this method has no effect. The |
| 246 | * fragments of a bundle are not checked for the header (112.4.1). |
| 247 | * <p> |
Felix Meschberger | a4b12bd | 2012-05-31 13:06:30 +0000 | [diff] [blame] | 248 | * This method calls the {@link Bundle#getBundleContext()} method to find |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 249 | * the <code>BundleContext</code> of the bundle. If the context cannot be |
| 250 | * found, this method does not load components for the bundle. |
| 251 | */ |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 252 | private void loadComponents( Bundle bundle ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 253 | { |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 254 | if ( bundle.getHeaders().get( "Service-Component" ) == null ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 255 | { |
| 256 | // no components in the bundle, abandon |
| 257 | return; |
| 258 | } |
| 259 | |
| 260 | // there should be components, load them with a bundle context |
Felix Meschberger | 8a8c633 | 2009-10-29 13:48:37 +0000 | [diff] [blame] | 261 | BundleContext context = bundle.getBundleContext(); |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 262 | if ( context == null ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 263 | { |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 264 | log( LogService.LOG_ERROR, m_bundle, "Cannot get BundleContext of bundle {0}/{1}", |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 265 | new Object[] {bundle.getSymbolicName(), bundle.getBundleId()}, null ); |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 266 | return; |
| 267 | } |
| 268 | |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 269 | // FELIX-1666 method is called for the LAZY_ACTIVATION event and |
| 270 | // the started event. Both events cause this method to be called; |
| 271 | // so we have to make sure to not load components twice |
| 272 | // FELIX-2231 Mark bundle loaded early to prevent concurrent loading |
| 273 | // if LAZY_ACTIVATION and STARTED event are fired at the same time |
| 274 | final boolean loaded; |
David Jencks | eeb03d2 | 2012-11-29 23:53:21 +0000 | [diff] [blame] | 275 | final Long bundleId = bundle.getBundleId(); |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 276 | synchronized ( m_componentBundles ) |
| 277 | { |
| 278 | if ( m_componentBundles.containsKey( bundleId ) ) |
| 279 | { |
| 280 | loaded = true; |
| 281 | } |
| 282 | else |
| 283 | { |
David Jencks | eeb03d2 | 2012-11-29 23:53:21 +0000 | [diff] [blame] | 284 | m_componentBundles.put( bundleId, null ); |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 285 | loaded = false; |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | // terminate if already loaded (or currently being loaded) |
| 290 | if ( loaded ) |
| 291 | { |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 292 | log( LogService.LOG_DEBUG, m_bundle, "Components for bundle {0}/{1} already loaded. Nothing to do.", |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 293 | new Object[] {bundle.getSymbolicName(), bundle.getBundleId()}, null ); |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 294 | return; |
| 295 | } |
| 296 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 297 | try |
| 298 | { |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 299 | BundleComponentActivator ga = new BundleComponentActivator( m_componentRegistry, m_componentActor, context, |
Felix Meschberger | 2136bed | 2009-11-26 10:08:12 +0000 | [diff] [blame] | 300 | m_configuration ); |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 301 | |
| 302 | // replace bundle activator in the map |
| 303 | synchronized ( m_componentBundles ) |
| 304 | { |
| 305 | m_componentBundles.put( bundleId, ga ); |
| 306 | } |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 307 | } |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 308 | catch ( Exception e ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 309 | { |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 310 | // remove the bundle id from the bundles map to ensure it is |
| 311 | // not marked as being loaded |
| 312 | synchronized ( m_componentBundles ) |
| 313 | { |
| 314 | m_componentBundles.remove( bundleId ); |
| 315 | } |
| 316 | |
Felix Meschberger | f9b7336 | 2008-08-25 06:58:56 +0000 | [diff] [blame] | 317 | if ( e instanceof IllegalStateException && bundle.getState() != Bundle.ACTIVE ) |
| 318 | { |
| 319 | log( |
Felix Meschberger | 9cb2972 | 2011-02-03 22:50:27 +0000 | [diff] [blame] | 320 | LogService.LOG_DEBUG, |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 321 | m_bundle, |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 322 | "Bundle {0}/{1} has been stopped while trying to activate its components. Trying again when the bundles gets started again.", |
| 323 | new Object[] {bundle.getSymbolicName(), bundle.getBundleId()}, |
Felix Meschberger | f9b7336 | 2008-08-25 06:58:56 +0000 | [diff] [blame] | 324 | e ); |
| 325 | } |
| 326 | else |
| 327 | { |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 328 | log( LogService.LOG_ERROR, m_bundle, "Error while loading components of bundle {0}/{1}", |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 329 | new Object[] {bundle.getSymbolicName(), bundle.getBundleId()}, e ); |
Felix Meschberger | f9b7336 | 2008-08-25 06:58:56 +0000 | [diff] [blame] | 330 | } |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 331 | } |
| 332 | } |
| 333 | |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 334 | |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 335 | /** |
| 336 | * Unloads components of the given bundle. If no components have been loaded |
| 337 | * for the bundle, this method has no effect. |
| 338 | */ |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 339 | private void disposeComponents( Bundle bundle ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 340 | { |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 341 | final Object ga; |
| 342 | synchronized ( m_componentBundles ) |
| 343 | { |
David Jencks | eeb03d2 | 2012-11-29 23:53:21 +0000 | [diff] [blame] | 344 | ga = m_componentBundles.remove( bundle.getBundleId() ); |
Felix Meschberger | 99d5fba | 2010-03-24 09:22:39 +0000 | [diff] [blame] | 345 | } |
| 346 | |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 347 | if ( ga != null ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 348 | { |
| 349 | try |
| 350 | { |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 351 | int reason = isStopping() |
| 352 | ? ComponentConstants.DEACTIVATION_REASON_DISPOSED |
| 353 | : ComponentConstants.DEACTIVATION_REASON_BUNDLE_STOPPED; |
| 354 | ( ( BundleComponentActivator ) ga ).dispose( reason ); |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 355 | } |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 356 | catch ( Exception e ) |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 357 | { |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 358 | log( LogService.LOG_ERROR, m_bundle, "Error while disposing components of bundle {0}/{1}", |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 359 | new Object[] {bundle.getSymbolicName(), bundle.getBundleId()}, e ); |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 360 | } |
| 361 | } |
| 362 | } |
| 363 | |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 364 | @Override |
| 365 | protected void debug(Bundle bundle, String msg) { |
| 366 | log( LogService.LOG_DEBUG, bundle, msg, null ); |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 367 | } |
| 368 | |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 369 | @Override |
| 370 | protected void warn(Bundle bundle, String msg, Throwable t) { |
| 371 | log( LogService.LOG_WARNING, bundle, msg, t ); |
| 372 | } |
| 373 | |
| 374 | @Override |
| 375 | protected void error(String msg, Throwable t) { |
Guillaume Nodet | 2241a5f | 2013-11-20 10:10:20 +0000 | [diff] [blame] | 376 | log( LogService.LOG_DEBUG, m_bundle, msg, t ); |
Guillaume Nodet | d767b21 | 2013-08-02 13:22:32 +0000 | [diff] [blame] | 377 | } |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 378 | |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 379 | public static void log( int level, Bundle bundle, String pattern, Object[] arguments, Throwable ex ) |
| 380 | { |
| 381 | if ( isLogEnabled( level ) ) |
| 382 | { |
| 383 | final String message = MessageFormat.format( pattern, arguments ); |
| 384 | log( level, bundle, message, ex ); |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | /** |
| 389 | * Returns <code>true</code> if logging for the given level is enabled. |
| 390 | */ |
| 391 | public static boolean isLogEnabled( int level ) |
| 392 | { |
David Jencks | 2d3a00a | 2014-04-27 06:58:04 +0000 | [diff] [blame^] | 393 | return m_configuration == null || m_configuration.getLogLevel() >= level; |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 394 | } |
| 395 | |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 396 | /** |
| 397 | * Method to actually emit the log message. If the LogService is available, |
| 398 | * the message will be logged through the LogService. Otherwise the message |
| 399 | * is logged to stdout (or stderr in case of LOG_ERROR level messages), |
Felix Meschberger | d25a63d | 2007-11-23 13:02:49 +0000 | [diff] [blame] | 400 | * |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 401 | * @param level The log level to log the message at |
| 402 | * @param message The message to log |
| 403 | * @param ex An optional <code>Throwable</code> whose stack trace is written, |
| 404 | * or <code>null</code> to not log a stack trace. |
| 405 | */ |
Felix Meschberger | 689e5f4 | 2009-07-28 14:06:58 +0000 | [diff] [blame] | 406 | public static void log( int level, Bundle bundle, String message, Throwable ex ) |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 407 | { |
David Jencks | 77ef1fc | 2013-08-19 23:10:49 +0000 | [diff] [blame] | 408 | if ( isLogEnabled( level ) ) |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 409 | { |
David Jencks | 88cf57e | 2012-10-25 17:59:55 +0000 | [diff] [blame] | 410 | ServiceTracker t = m_logService; |
| 411 | Object logger = ( t != null ) ? t.getService() : null; |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 412 | if ( logger == null ) |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 413 | { |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 414 | // output depending on level |
| 415 | PrintStream out = ( level == LogService.LOG_ERROR ) ? System.err : System.out; |
| 416 | |
| 417 | // level as a string |
| 418 | StringBuffer buf = new StringBuffer(); |
| 419 | switch ( level ) |
| 420 | { |
| 421 | case ( LogService.LOG_DEBUG ): |
| 422 | buf.append( "DEBUG: " ); |
| 423 | break; |
| 424 | case ( LogService.LOG_INFO ): |
| 425 | buf.append( "INFO : " ); |
| 426 | break; |
| 427 | case ( LogService.LOG_WARNING ): |
| 428 | buf.append( "WARN : " ); |
| 429 | break; |
| 430 | case ( LogService.LOG_ERROR ): |
| 431 | buf.append( "ERROR: " ); |
| 432 | break; |
| 433 | default: |
| 434 | buf.append( "UNK : " ); |
| 435 | break; |
| 436 | } |
| 437 | |
| 438 | // bundle information |
| 439 | if ( bundle != null ) |
| 440 | { |
| 441 | buf.append( bundle.getSymbolicName() ); |
| 442 | buf.append( " (" ); |
| 443 | buf.append( bundle.getBundleId() ); |
| 444 | buf.append( "): " ); |
| 445 | } |
| 446 | |
| 447 | // the message |
| 448 | buf.append( message ); |
| 449 | |
| 450 | // keep the message and the stacktrace together |
| 451 | synchronized ( out) |
| 452 | { |
| 453 | out.println( buf ); |
| 454 | if ( ex != null ) |
| 455 | { |
| 456 | ex.printStackTrace( out ); |
| 457 | } |
| 458 | } |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 459 | } |
Felix Meschberger | 29e04e3 | 2007-08-30 14:53:12 +0000 | [diff] [blame] | 460 | else |
| 461 | { |
| 462 | ( ( LogService ) logger ).log( level, message, ex ); |
| 463 | } |
Felix Meschberger | d468b35 | 2007-05-15 10:38:24 +0000 | [diff] [blame] | 464 | } |
Richard S. Hall | 323d971 | 2006-09-22 18:55:50 +0000 | [diff] [blame] | 465 | } |
Felix Meschberger | 08aaff6 | 2010-08-05 13:26:31 +0000 | [diff] [blame] | 466 | |
| 467 | |
| 468 | public static Object getPackageAdmin() |
| 469 | { |
| 470 | if ( m_packageAdmin == null ) |
| 471 | { |
| 472 | synchronized ( Activator.class ) |
| 473 | { |
| 474 | if ( m_packageAdmin == null ) |
| 475 | { |
| 476 | m_packageAdmin = new ServiceTracker( m_context, PACKAGEADMIN_CLASS, null ); |
| 477 | m_packageAdmin.open(); |
| 478 | } |
| 479 | } |
| 480 | } |
| 481 | |
| 482 | return m_packageAdmin.getService(); |
| 483 | } |
Richard S. Hall | 7bd86ce | 2006-09-06 19:04:29 +0000 | [diff] [blame] | 484 | } |