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.ContextProcessor;
28  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType;
29  import at.ac.tuwien.infosys.sm4all.copal.service.copal.ContextProcessorRegistry;
30  
31  /**
32   * Abstract helper class to be used as an OSGi Activator for bundles that need
33   * to register {@link ContextProcessor}s.
34   * 
35   * @author sanjin
36   */
37  public abstract class AbstractProcessorActivator implements BundleActivator {
38  
39      private static final Logger LOGGER = Logger.getLogger(AbstractProcessorActivator.class);
40  
41      private final List<ContextProcessor> processors = new LinkedList<ContextProcessor>();
42      private final ReadWriteLock lock = new ReentrantReadWriteLock();
43      private final ProcessorRegistryTracker tracker;
44      private final Context context;
45      private final ContextActivator contextActivator;
46      private ContextProcessorRegistry registry;
47  
48      /**
49       * Creates instance of OSGi Activator for bundles that need to register
50       * {@link ContextProcessor}s.
51       */
52      public AbstractProcessorActivator() {
53          super();
54          this.tracker = new ProcessorRegistryTracker(this);
55          this.context = new Context(getClass().getClassLoader(),
56                  "processors.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 processors.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 ContextProcessorRegistry} becomes available.
72       * 
73       * @param processorRegistry the {@link ContextProcessorRegistry}.
74       */
75      protected void start(final ContextProcessorRegistry processorRegistry) {
76      /* do nothing */
77      }
78  
79      /**
80       * Called when {@link ContextProcessorRegistry} 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 ContextProcessor} when
112      * {@link ContextProcessorRegistry} becomes available (or register it
113      * immediately if it is already available).
114      * 
115      * @param processor the {@link ContextProcessor} to register.
116      */
117     public final void register(final ContextProcessor processor) {
118         this.lock.writeLock().lock();
119         try {
120             this.processors.add(processor);
121 
122             if (this.registry != null)
123                 this.registry.register(processor);
124         } finally {
125             this.lock.writeLock().unlock();
126         }
127     }
128 
129     /**
130      * Do not register specified {@link ContextProcessor} when
131      * {@link ContextProcessorRegistry} becomes available (or unregister it
132      * immediately if it is already available).
133      * 
134      * @param processor the {@link ContextProcessor} to unregister.
135      */
136     public final void unregister(final ContextProcessor processor) {
137         this.lock.writeLock().lock();
138         try {
139             if (this.registry != null)
140                 this.registry.unregister(processor.getName());
141 
142             this.processors.remove(processor);
143         } finally {
144             this.lock.writeLock().unlock();
145         }
146     }
147 
148     /**
149      * Sets the {@link ContextProcessorRegistry}, unregisters all
150      * {@link ContextProcessor}s from previously set
151      * {@link ContextProcessorRegistry} if it was not <code>null</code> and
152      * registers all {@link ContextProcessor}s with specified
153      * {@link ContextProcessorRegistry} if it is not <code>null</code> .
154      * 
155      * @param registry the {@link ContextProcessorRegistry}.
156      */
157     protected void setRegistry(final ContextProcessorRegistry 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 ContextProcessor processor : this.processors)
178                 this.registry.register(processor);
179         } finally {
180             this.lock.readLock().unlock();
181         }
182     }
183 
184     private void unregisterAll() {
185         this.lock.readLock().lock();
186         try {
187             for (final ContextProcessor processor : this.processors)
188                 this.registry.unregister(processor.getName());
189         } finally {
190             this.lock.readLock().unlock();
191         }
192     }
193 
194     private static class ProcessorRegistryTracker extends
195             AbstractGenericActivator {
196 
197         private final AbstractProcessorActivator activator;
198 
199         public ProcessorRegistryTracker(
200                 final AbstractProcessorActivator activator) {
201             super(ContextProcessorRegistry.class.getName());
202             this.activator = activator;
203         }
204 
205         @Override
206         protected void start() {
207             final ContextProcessorRegistry registry = getDependency(ContextProcessorRegistry.class.getName());
208             this.activator.setRegistry(registry);
209         }
210 
211         @Override
212         protected void stop() {
213             this.activator.setRegistry(null);
214         }
215     }
216 }