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.publisher;
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.ContextPublisherRegistry;
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   * Class to be used as an OSGi {@link BundleActivator} for bundles that need to
35   * register {@link BasePublisher}s.
36   * 
37   * @author sanjin
38   */
39  public class PublishersActivator extends
40          Register<String, ContextPublisher, BasePublisher> implements
41          BundleActivator {
42  
43      /**
44       * The name of configuration file that defines {@link ContextEventType}s
45       * used by the registered {@link ContextPublisher}s.
46       */
47      public static final String CONFIGURATION_FILE = "publishers.cfg.xml";
48      private static final Logger LOGGER = Logger.getLogger(PublishersActivator.class);
49  
50      private final Tracker<ContextPublisherRegistry> tracker;
51      private final EventTypesConfiguration configuration;
52      private BundleContext bundleContext;
53  
54      {
55          this.tracker = new Tracker<ContextPublisherRegistry>(
56                  ContextPublisherRegistry.class.getName()) {
57  
58              @Override
59              protected void start(final ContextPublisherRegistry registry) {
60                  setRegistry(registry);
61              }
62  
63              @Override
64              protected void stop(final ContextPublisherRegistry registry) {
65                  setRegistry(null);
66              }
67          };
68      }
69  
70      /**
71       * Creates instance of OSGi {@link BundleActivator} for bundles that need to
72       * register {@link BasePublisher}s.
73       */
74      protected PublishersActivator() {
75          super();
76  
77          this.configuration = new EventTypesConfiguration(
78                  getClass().getClassLoader(), CONFIGURATION_FILE);
79      }
80  
81      /**
82       * Called when bundle is started.
83       */
84      protected void start() {
85          /* do nothing */
86      }
87  
88      /**
89       * Called when a {@link ContextPublisherRegistry} becomes available.
90       * 
91       * @param publisherRegistry the {@link ContextPublisherRegistry}.
92       */
93      protected void start(final ContextPublisherRegistry publisherRegistry) {
94          /* do nothing */
95      }
96  
97      /**
98       * Returns registered {@link ContextEventType} that has specified name
99       * defined in the {@link #CONFIGURATION_FILE}. If {@link ContextEventType}
100      * with specified name is not defined in the {@link #CONFIGURATION_FILE} or
101      * the {@link ContextEventType} was not successfully registered, the
102      * <code>null</code> value is returned.
103      * 
104      * @param name the name of registered {@link ContextEventType}.
105      * @return the registered {@link ContextEventType}.
106      */
107     public ContextEventType getRegisteredEventType(final String name) {
108         ContextEventType result = null;
109 
110         for (final ContextEventType eventType : this.configuration.getRegistered()) {
111             if (name.equals(eventType.getName())) {
112                 result = eventType;
113                 break;
114             }
115         }
116 
117         return result;
118     }
119 
120     /**
121      * Returns all registered {@link ContextEventType}s defined in the
122      * {@link #CONFIGURATION_FILE}.
123      * 
124      * @return all registered {@link ContextEventType}s.
125      */
126     public ContextEventType[] getRegisteredEventTypes() {
127         return this.configuration.getRegistered();
128     }
129 
130     /**
131      * Returns a {@link SimplePublisher} with specified source ID and name of
132      * published {@link ContextEventType}. The {@link SimplePublisher} is
133      * already registered with this {@link PublishersActivator}.
134      * 
135      * @param sourceID the source ID for {@link SimplePublisher}.
136      * @param publishedType the name of published {@link ContextEventType}
137      * @return the {@link SimplePublisher}.
138      * @throws IllegalArgumentException if specified name of published
139      *         {@link ContextEventType} is not registered with this
140      *         {@link PublishersActivator}.
141      */
142     public SimplePublisher getPublisher(final String sourceID,
143             final String publishedType) {
144         final ContextEventType type = getRegisteredEventType(publishedType);
145 
146         if (null == publishedType) {
147             throw new IllegalArgumentException(MessageFormat.format(
148                     "''{0}'' event is not registered with this activator.",
149                     publishedType));
150         }
151 
152         final SimplePublisher result = new SimplePublisher(sourceID, type);
153         register(result);
154 
155         return result;
156     }
157 
158     @Override
159     public final void start(final BundleContext context) {
160         this.bundleContext = context;
161 
162         this.configuration.start(context);
163         this.tracker.start(context);
164 
165         start();
166     }
167 
168     @Override
169     public final void stop(final BundleContext context) {
170         setRegistry(null);
171 
172         this.tracker.stop(context);
173         this.configuration.stop(context);
174 
175         this.bundleContext = null;
176     }
177 
178     /**
179      * Register specified {@link BasePublisher} when
180      * {@link ContextPublisherRegistry} becomes available (or immediately if it
181      * is already available).
182      * 
183      * @param publisher the {@link BasePublisher} to register.
184      */
185     @Override
186     public final void register(final BasePublisher publisher) {
187         try {
188             super.register(publisher);
189         } catch (final ContextException ex) {
190             if (LOGGER.isEnabledFor(Level.ERROR)) {
191                 LOGGER.error(MessageFormat.format(
192                         "Failed to register publisher {0}!",
193                         publisher.getSourceID()), ex);
194             }
195         }
196     }
197 
198     /**
199      * Do not register specified {@link BasePublisher} when
200      * {@link ContextPublisherRegistry} becomes available (and unregister it
201      * immediately if it is already available).
202      * 
203      * @param publisher the {@link BasePublisher} to unregister.
204      */
205     @Override
206     public final void unregister(final BasePublisher publisher) {
207         try {
208             super.unregister(publisher);
209         } catch (final ContextException ex) {
210             if (LOGGER.isEnabledFor(Level.ERROR)) {
211                 LOGGER.error(MessageFormat.format(
212                         "Failed to unregister publisher {0}!",
213                         publisher.getSourceID()), ex);
214             }
215         }
216     }
217 
218     /**
219      * Sets the new {@link ContextPublisherRegistry}, unregisters all
220      * {@link BasePublisher}s from previously set
221      * {@link ContextPublisherRegistry} if it was not <code>null</code> and
222      * registers all {@link BasePublisher}s with specified
223      * {@link ContextPublisherRegistry} if it is not <code>null</code>.
224      * 
225      * @param registry the new {@link ContextPublisherRegistry}.
226      */
227     protected void setRegistry(final ContextPublisherRegistry registry) {
228         super.setRegistry(registry);
229         if (null != registry) {
230             start(registry);
231         }
232     }
233 
234     @Override
235     protected String getKey(final BasePublisher publisher) {
236         return publisher.getSourceID();
237     }
238 
239     @Override
240     protected void update(final RegistrationState state,
241             final BasePublisher publisher) {
242         switch (state) {
243         case Registered:
244             publisher.start(this.bundleContext);
245             break;
246         case Unregistered:
247             publisher.stop(this.bundleContext);
248             break;
249         default:
250             break;
251         }
252     }
253 }