View Javadoc

1   /* This file is part of COPAL (COntext Provisioning for All).
2    *
3    * COPAL is a part of SM4All (Smart hoMes for All) project.
4    *
5    * COPAL is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU Lesser General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * COPAL is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with COPAL. If not, see <http://www.gnu.org/licenses/>.
17   */
18  package at.ac.tuwien.infosys.sm4all.copal.api.helpers;
19  
20  import java.util.LinkedList;
21  import java.util.List;
22  import java.util.concurrent.locks.ReadWriteLock;
23  import java.util.concurrent.locks.ReentrantReadWriteLock;
24  import org.apache.log4j.Logger;
25  import org.osgi.framework.BundleActivator;
26  import org.osgi.framework.BundleContext;
27  import at.ac.tuwien.infosys.sm4all.copal.api.ContextPublisher;
28  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType;
29  import at.ac.tuwien.infosys.sm4all.copal.service.copal.ContextPublisherRegistry;
30  
31  /**
32   * Abstract helper class to be used as an OSGi Activator for bundles that need
33   * to register {@link ContextPublisher}s.
34   * 
35   * @author sanjin
36   */
37  public abstract class AbstractPublisherActivator implements BundleActivator {
38  
39      private static final Logger LOGGER = Logger.getLogger(AbstractPublisherActivator.class);
40  
41      private final List<ContextPublisher> publishers = new LinkedList<ContextPublisher>();
42      private final ReadWriteLock lock = new ReentrantReadWriteLock();
43      private final PublisherRegistryTracker tracker;
44      private final Context context;
45      private final ContextActivator contextActivator;
46      private ContextPublisherRegistry registry;
47  
48      /**
49       * Creates instance of OSGi Activator for bundles that need to register
50       * {@link ContextPublisher}s.
51       */
52      public AbstractPublisherActivator() {
53          super();
54          this.tracker = new PublisherRegistryTracker(this);
55          this.context = new Context(getClass().getClassLoader(),
56                  "publishers.cfg.xml");
57          this.contextActivator = new ContextActivator(this.context);
58  
59          if (this.context.getDefinedQueries().length > 0)
60              LOGGER.warn("Definitions of queries found in publishers.cfg.xml! They will not be created.");
61      }
62  
63      /**
64       * Called when bundle is started.
65       */
66      protected void start() {
67      /* do nothing */
68      }
69  
70      /**
71       * Called when {@link ContextPublisherRegistry} becomes available.
72       * 
73       * @param publisherRegistry the {@link ContextPublisherRegistry}.
74       */
75      protected void start(final ContextPublisherRegistry publisherRegistry) {
76      /* do nothing */
77      }
78  
79      /**
80       * Called when {@link ContextPublisherRegistry} becomes unavailable.
81       */
82      protected void stop() {
83      /* do nothing */
84      }
85  
86      /**
87       * @return all successfully registered {@link ContextEventType}s defined in
88       *         the <code>context.cfg.xml</code> file.
89       */
90      public ContextEventType[] getRegisteredEventTypes() {
91          return this.contextActivator.getRegisteredEventTypes();
92      }
93  
94      @Override
95      public final void start(final BundleContext bundleContext) {
96          this.contextActivator.start(bundleContext);
97          this.tracker.start(bundleContext);
98  
99          start();
100     }
101 
102     @Override
103     public final void stop(final BundleContext bundleContext) {
104         setRegistry(null);
105 
106         this.tracker.stop(bundleContext);
107         this.contextActivator.stop(bundleContext);
108     }
109 
110     /**
111      * Register specified {@link ContextPublisher} when
112      * {@link ContextPublisherRegistry} becomes available (or immediately if it
113      * is already available).
114      * 
115      * @param publisher the {@link ContextPublisher} to register.
116      */
117     public final void register(final ContextPublisher publisher) {
118         this.lock.writeLock().lock();
119         try {
120             this.publishers.add(publisher);
121 
122             if (this.registry != null)
123                 this.registry.register(publisher);
124         } finally {
125             this.lock.writeLock().unlock();
126         }
127     }
128 
129     /**
130      * Do not register specified {@link ContextPublisher} when
131      * {@link ContextPublisherRegistry} becomes available (and unregister it
132      * immediately if it is already available).
133      * 
134      * @param publisher the {@link ContextPublisher} to unregister.
135      */
136     public final void unregister(final ContextPublisher publisher) {
137         this.lock.writeLock().lock();
138         try {
139             if (this.registry != null)
140                 this.registry.unregister(publisher.getSourceID());
141 
142             this.publishers.remove(publisher);
143         } finally {
144             this.lock.writeLock().unlock();
145         }
146     }
147 
148     /**
149      * Sets the {@link ContextPublisherRegistry}, unregisters all
150      * {@link ContextPublisher}s from previously set
151      * {@link ContextPublisherRegistry} if it was not <code>null</code> and
152      * registers all {@link ContextPublisher}s with specified
153      * {@link ContextPublisherRegistry} if it is not <code>null</code> .
154      * 
155      * @param registry the {@link ContextPublisherRegistry}.
156      */
157     protected void setRegistry(final ContextPublisherRegistry registry) {
158         this.lock.readLock().lock();
159         try {
160             if (this.registry != null) {
161                 stop();
162                 unregisterAll();
163             }
164             this.registry = registry;
165             if (this.registry != null) {
166                 registerAll();
167                 start(registry);
168             }
169         } finally {
170             this.lock.readLock().unlock();
171         }
172     }
173 
174     private void registerAll() {
175         this.lock.readLock().lock();
176         try {
177             for (final ContextPublisher publisher : this.publishers)
178                 this.registry.register(publisher);
179         } finally {
180             this.lock.readLock().unlock();
181         }
182     }
183 
184     private void unregisterAll() {
185         this.lock.readLock().lock();
186         try {
187             for (final ContextPublisher publisher : this.publishers)
188                 this.registry.unregister(publisher.getSourceID());
189         } finally {
190             this.lock.readLock().unlock();
191         }
192     }
193 
194     private static class PublisherRegistryTracker extends
195             AbstractGenericActivator {
196 
197         private final AbstractPublisherActivator activator;
198 
199         public PublisherRegistryTracker(
200                 final AbstractPublisherActivator activator) {
201             super(ContextPublisherRegistry.class.getName());
202             this.activator = activator;
203         }
204 
205         @Override
206         protected void start() {
207             final ContextPublisherRegistry registry = getDependency(ContextPublisherRegistry.class.getName());
208             this.activator.setRegistry(registry);
209         }
210 
211         @Override
212         protected void stop() {
213             this.activator.setRegistry(null);
214         }
215     }
216 }