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.processor;
19  
20  import java.text.MessageFormat;
21  import org.apache.log4j.Level;
22  import org.apache.log4j.Logger;
23  import org.osgi.framework.BundleActivator;
24  import org.osgi.framework.BundleContext;
25  import at.ac.tuwien.infosys.sm4all.copal.api.ContextException;
26  import at.ac.tuwien.infosys.sm4all.copal.api.conf.EventTypesConfiguration;
27  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType;
28  import at.ac.tuwien.infosys.sm4all.copal.api.osgi.Tracker;
29  import at.ac.tuwien.infosys.sm4all.copal.api.service.ContextProcessorRegistry;
30  import at.ac.tuwien.infosys.sm4all.copal.api.util.Register;
31  import at.ac.tuwien.infosys.sm4all.copal.api.util.RegistryObservable.RegistrationState;
32  
33  /**
34   * AClass to be used as an OSGi {@link BundleActivator} for bundles that need to
35   * register {@link BaseProcessor}s.
36   * 
37   * @author sanjin
38   */
39  public class ProcessorsActivator extends
40          Register<String, ContextProcessor, BaseProcessor> implements
41          BundleActivator {
42  
43      /**
44       * The name of configuration file that defines {@link ContextEventType}s
45       * used by the registered {@link ContextProcessor}s.
46       */
47      public static final String CONFIGURATION_FILE = "processors.cfg.xml";
48  
49      private static final Logger LOGGER = Logger.getLogger(ProcessorsActivator.class);
50  
51      private final Tracker<ContextProcessorRegistry> tracker;
52      private final EventTypesConfiguration configuration;
53      private BundleContext bundleContext;
54  
55      {
56          this.tracker = new Tracker<ContextProcessorRegistry>(
57                  ContextProcessorRegistry.class.getName()) {
58  
59              @Override
60              protected void start(final ContextProcessorRegistry registry) {
61                  setRegistry(registry);
62              }
63  
64              @Override
65              protected void stop(final ContextProcessorRegistry registry) {
66                  setRegistry(null);
67              }
68          };
69      }
70  
71      /**
72       * Creates instance of OSGi {@link BundleActivator} for bundles that need to
73       * register {@link BaseProcessor}s.
74       */
75      protected ProcessorsActivator() {
76          super();
77  
78          this.configuration = new EventTypesConfiguration(
79                  getClass().getClassLoader(), CONFIGURATION_FILE);
80      }
81  
82      /**
83       * Called when bundle is started.
84       */
85      protected void start() {
86          /* do nothing */
87      }
88  
89      /**
90       * Called when {@link ContextProcessorRegistry} becomes available.
91       * 
92       * @param processorRegistry the {@link ContextProcessorRegistry}.
93       */
94      protected void start(final ContextProcessorRegistry processorRegistry) {
95          /* do nothing */
96      }
97  
98      /**
99       * Returns registered {@link ContextEventType} that has specified name
100      * defined in the {@link #CONFIGURATION_FILE}. If {@link ContextEventType}
101      * with specified name is not defined in the {@link #CONFIGURATION_FILE} or
102      * the {@link ContextEventType} was not successfully registered, the
103      * <code>null</code> value is returned.
104      * 
105      * @param name the name of registered {@link ContextEventType}.
106      * @return the registered {@link ContextEventType}.
107      */
108     public ContextEventType getRegisteredEventType(final String name) {
109         ContextEventType result = null;
110 
111         for (final ContextEventType eventType : this.configuration.getRegistered()) {
112             if (name.equals(eventType.getName())) {
113                 result = eventType;
114                 break;
115             }
116         }
117 
118         return result;
119     }
120 
121     /**
122      * Returns all registered {@link ContextEventType}s defined in the
123      * {@link #CONFIGURATION_FILE}.
124      * 
125      * @return all registered {@link ContextEventType}s.
126      */
127     public ContextEventType[] getRegisteredEventTypes() {
128         return this.configuration.getRegistered();
129     }
130 
131     @Override
132     public final void start(final BundleContext context) {
133         this.bundleContext = context;
134 
135         this.configuration.start(context);
136         this.tracker.start(context);
137 
138         start();
139     }
140 
141     @Override
142     public final void stop(final BundleContext context) {
143         setRegistry(null);
144 
145         this.tracker.stop(context);
146         this.configuration.stop(context);
147 
148         this.bundleContext = null;
149     }
150 
151     /**
152      * Register specified {@link BaseProcessor} when
153      * {@link ContextProcessorRegistry} becomes available (or register it
154      * immediately if it is already available).
155      * 
156      * @param processor the {@link BaseProcessor} to register.
157      */
158     @Override
159     public void register(final BaseProcessor processor) {
160         try {
161             super.register(processor);
162         } catch (final ContextException ex) {
163             if (LOGGER.isEnabledFor(Level.ERROR)) {
164                 LOGGER.error(MessageFormat.format(
165                         "Failed to register processor {0}!",
166                         processor.getName()), ex);
167             }
168         }
169     }
170 
171     /**
172      * Do not register specified {@link BaseProcessor} when
173      * {@link ContextProcessorRegistry} becomes available (or unregister it
174      * immediately if it is already available).
175      * 
176      * @param processor the {@link BaseProcessor} to unregister.
177      */
178     @Override
179     public void unregister(final BaseProcessor processor) {
180         try {
181             super.unregister(processor);
182         } catch (final ContextException ex) {
183             if (LOGGER.isEnabledFor(Level.ERROR)) {
184                 LOGGER.error(MessageFormat.format(
185                         "Failed to unregister processor {0}!",
186                         processor.getName()), ex);
187             }
188         }
189     }
190 
191     /**
192      * Sets the new {@link ContextProcessorRegistry}, unregisters all
193      * {@link BaseProcessor}s from previously set
194      * {@link ContextProcessorRegistry} if it was not <code>null</code> and
195      * registers all {@link BaseProcessor}s with specified
196      * {@link ContextProcessorRegistry} if it is not <code>null</code>.
197      * 
198      * @param registry the new {@link ContextProcessorRegistry}.
199      */
200     protected void setRegistry(final ContextProcessorRegistry registry) {
201         super.setRegistry(registry);
202         if (null != registry) {
203             start(registry);
204         }
205     }
206 
207     @Override
208     protected String getKey(final BaseProcessor processor) {
209         return processor.getName();
210     }
211 
212     @Override
213     protected void update(final RegistrationState state,
214             final BaseProcessor processor) {
215         switch (state) {
216         case Registered:
217             processor.start(this.bundleContext);
218             break;
219         case Unregistered:
220             processor.stop(this.bundleContext);
221             break;
222         default:
223             break;
224         }
225     }
226 }