View Javadoc

1   /**
2    * Copyright 2009 OPS4J
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.ops4j.pax.useradmin.service.internal;
19  
20  import java.util.Collection;
21  import java.util.Dictionary;
22  import java.util.HashMap;
23  import java.util.Hashtable;
24  import java.util.Map;
25  import java.util.concurrent.ExecutorService;
26  import java.util.concurrent.LinkedBlockingQueue;
27  import java.util.concurrent.ThreadPoolExecutor;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.ops4j.pax.useradmin.service.PaxUserAdminConstants;
31  import org.ops4j.pax.useradmin.service.spi.StorageProvider;
32  import org.osgi.framework.BundleActivator;
33  import org.osgi.framework.BundleContext;
34  import org.osgi.framework.Constants;
35  import org.osgi.framework.ServiceReference;
36  import org.osgi.service.cm.ConfigurationException;
37  import org.osgi.service.event.EventAdmin;
38  import org.osgi.service.log.LogService;
39  import org.osgi.service.useradmin.UserAdminListener;
40  import org.osgi.util.tracker.ServiceTracker;
41  import org.osgi.util.tracker.ServiceTrackerCustomizer;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  /**
46   * Activator which starts a ServiceTracker for StorageProvider services.
47   * UserAdmin services are started/stopped on adding/removing providers.
48   * 
49   * @author Matthias Kuespert
50   * @since 02.07.2009
51   */
52  public class Activator implements BundleActivator, ServiceTrackerCustomizer<StorageProvider, PaxUserAdmin> {
53  
54      /**
55       * Maximum number of parralllel event threads
56       */
57      private static final int                                     MAXIMUM_POOL_SIZE = 10;
58  
59      private static final Logger                                  LOG               = LoggerFactory.getLogger(Activator.class);
60  
61      private ServiceTracker<StorageProvider, PaxUserAdmin>        providerTracker;
62  
63      private BundleContext                                        context;
64  
65      private ServiceTracker<EventAdmin, EventAdmin>               eventAdminTracker;
66  
67      private ServiceTracker<LogService, LogService>               logServiceTracker;
68  
69      private ServiceTracker<UserAdminListener, UserAdminListener> listenerTracker;
70  
71      private final Map<String, ConfigurationListener>             managedServiceMap = new HashMap<String, ConfigurationListener>();
72  
73      private final ExecutorService                                eventExecutor     = new ThreadPoolExecutor(0, MAXIMUM_POOL_SIZE, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
74  
75      @Override
76      public void start(BundleContext context) throws Exception {
77          this.context = context;
78          LOG.info("Start PaxUserAdmin service bundle {} (version {}) and wait for StorageProvider...", context.getBundle().getSymbolicName(), context.getBundle().getVersion());
79          //Create all tracker
80          providerTracker = new ServiceTracker<StorageProvider, PaxUserAdmin>(context, StorageProvider.class.getName(), this);
81          eventAdminTracker = new ServiceTracker<EventAdmin, EventAdmin>(context, EventAdmin.class, null);
82          logServiceTracker = new ServiceTracker<LogService, LogService>(context, LogService.class, null);
83          listenerTracker = new ServiceTracker<UserAdminListener, UserAdminListener>(context, UserAdminListener.class, null);
84          //and open them...
85          logServiceTracker.open();
86          eventAdminTracker.open();
87          providerTracker.open();
88      }
89  
90      @Override
91      public void stop(BundleContext context) throws Exception {
92          LOG.info("Shutdown PaxUserAdmin service bundle {} (version {})...", context.getBundle().getSymbolicName(), context.getBundle().getVersion());
93          providerTracker.close();
94          eventAdminTracker.close();
95          logServiceTracker.close();
96          listenerTracker.close();
97          synchronized (managedServiceMap) {
98              Collection<ConfigurationListener> values = managedServiceMap.values();
99              for (ConfigurationListener serviceRegistration : values) {
100                 serviceRegistration.unregister();
101             }
102             managedServiceMap.clear();
103         }
104     }
105 
106     @Override
107     public PaxUserAdmin addingService(ServiceReference<StorageProvider> reference) {
108         String type = (String) reference.getProperty(PaxUserAdminConstants.STORAGEPROVIDER_TYPE);
109         if (null == type) {
110             LOG.error("Ignoring provider without storage provider type");
111             return null;
112         }
113         StorageProvider storageProvider = context.getService(reference);
114         if (storageProvider != null) {
115             try {
116                 PaxUserAdmin userAdminImpl = new PaxUserAdmin(storageProvider, logServiceTracker, eventAdminTracker, listenerTracker, eventExecutor);
117                 userAdminImpl.register(context, type, (Long) reference.getProperty(Constants.SERVICE_ID));
118                 LOG.info("New UserAdmin for StorageProvider {} (service.id = {}) is now available.", type, reference.getProperty(Constants.SERVICE_ID));
119                 synchronized (managedServiceMap) {
120                     String pid = reference.getBundle().getSymbolicName();
121                     ConfigurationListener l = managedServiceMap.get(pid);
122                     if (l == null) {
123                         LOG.info("The configuration PID for StorageProviders of type {} is {}", type, pid);
124                         Dictionary<String, Object> properties = new Hashtable<String, Object>();
125                         properties.put(Constants.SERVICE_PID, pid);
126                         ConfigurationListener listener = new ConfigurationListener(type, providerTracker, properties, context);
127                         managedServiceMap.put(pid, listener);
128                     } else {
129                         try {
130                             l.updateProvider(userAdminImpl);
131                         } catch (ConfigurationException e) {
132                             LOG.error("Can't update configuration: {}", e.getMessage(), e);
133                         }
134                     }
135                 }
136                 return userAdminImpl;
137             } catch (RuntimeException e) {
138                 //unget the service
139                 context.ungetService(reference);
140                 LOG.warn("registration of UserAdmin failed!", e);
141                 return null;
142             }
143         } else {
144             return null;
145         }
146     }
147 
148     @Override
149     public void modifiedService(ServiceReference<StorageProvider> reference, PaxUserAdmin service) {
150         // we not support modifications yet
151     }
152 
153     @Override
154     public void removedService(ServiceReference<StorageProvider> reference, PaxUserAdmin service) {
155         String type = (String) reference.getProperty(PaxUserAdminConstants.STORAGEPROVIDER_TYPE);
156         //unget whatever happens
157         context.ungetService(reference);
158         service.unregister();
159         LOG.info("UserAdmin for StorageProvider {} (service.id = {}) is now removed and no longer available.", type, reference.getProperty(Constants.SERVICE_ID));
160     }
161 }