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.esper.internal;
19  
20  import java.text.MessageFormat;
21  import java.util.HashMap;
22  import java.util.Map;
23  import java.util.concurrent.locks.ReadWriteLock;
24  import java.util.concurrent.locks.ReentrantReadWriteLock;
25  import org.apache.log4j.Level;
26  import org.apache.log4j.Logger;
27  import org.osgi.framework.BundleActivator;
28  import at.ac.tuwien.infosys.sm4all.copal.api.event.XMLContextEventType;
29  import at.ac.tuwien.infosys.sm4all.copal.api.osgi.GenericActivator;
30  import at.ac.tuwien.infosys.sm4all.copal.api.query.ContextQuery;
31  import at.ac.tuwien.infosys.sm4all.copal.api.query.QueryObserver;
32  import at.ac.tuwien.infosys.sm4all.copal.api.query.QueryState;
33  import at.ac.tuwien.infosys.sm4all.copal.api.service.ContextQueryFactory;
34  import at.ac.tuwien.infosys.sm4all.copal.api.util.RegistryObservable;
35  import at.ac.tuwien.infosys.sm4all.copal.esper.XMLEventNotifier;
36  import com.espertech.esper.client.EPAdministrator;
37  import com.espertech.esper.client.EPServiceProvider;
38  
39  /**
40   * The OSGi {@link BundleActivator} that starts and stops instances of
41   * {@link XMLEventNotifier}s. Each created {@link ContextQuery} will result in a
42   * creation of a {@link XMLEventNotifier} and the {@link XMLEventNotifier} will
43   * be running until the {@link ContextQuery} is destroyed.
44   * 
45   * @author sanjin
46   */
47  public class NotifiersActivator extends GenericActivator implements
48          QueryObserver {
49  
50      private static final Logger LOGGER = Logger.getLogger(NotifiersActivator.class);
51  
52      private final Map<String, XMLEventNotifier> notifiers = new HashMap<String, XMLEventNotifier>();
53      private final ReadWriteLock lock = new ReentrantReadWriteLock();
54      private final EPAdministrator administrator;
55      private final RegistryObservable<XMLContextEventType> observable;
56      private ContextQueryFactory queryFactory;
57  
58      /**
59       * Creates an instance of the {@link NotifiersActivator} that uses specified
60       * {@link EPServiceProvider} and listens on specified
61       * {@link XMLContextEventType} {@link RegistryObservable}.
62       * 
63       * @param serviceProvider the {@link EPServiceProvider}.
64       * @param observable the {@link XMLContextEventType}
65       *        {@link RegistryObservable}.
66       */
67      public NotifiersActivator(final EPServiceProvider serviceProvider,
68              final RegistryObservable<XMLContextEventType> observable) {
69          super(ContextQueryFactory.class.getName());
70  
71          this.administrator = serviceProvider.getEPAdministrator();
72          this.observable = observable;
73      }
74  
75      @Override
76      protected void start() {
77          this.queryFactory = getDependency(ContextQueryFactory.class.getName());
78  
79          this.queryFactory.attach(this);
80      }
81  
82      @Override
83      protected void stop() {
84          this.queryFactory.detach(this);
85  
86          this.queryFactory = null;
87      }
88  
89      @Override
90      public void update(final QueryState state, final ContextQuery query) {
91          switch (state) {
92          case Created:
93              start(query);
94              break;
95          case Destroyed:
96              stop(query.getName());
97              break;
98          default:
99              break;
100         }
101     }
102 
103     private void start(final ContextQuery query) {
104         final String queryName = query.getName();
105 
106         this.lock.writeLock().lock();
107         try {
108             if (this.notifiers.containsKey(queryName)) {
109                 if (LOGGER.isEnabledFor(Level.ERROR)) {
110                     LOGGER.error(MessageFormat.format(
111                             "Failed to create notifier ''{0}''! Notifier already exists.",
112                             queryName));
113                 }
114             } else {
115                 final XMLEventNotifier notifier = new XMLEventNotifier(
116                         this.administrator, query);
117                 this.notifiers.put(queryName, notifier);
118                 this.observable.attach(notifier);
119 
120                 if (LOGGER.isInfoEnabled()) {
121                     LOGGER.info(MessageFormat.format(
122                             "Successfully created notifier ''{0}''.", queryName));
123                 }
124             }
125         } finally {
126             this.lock.writeLock().unlock();
127         }
128     }
129 
130     private void stop(final String queryName) {
131         this.lock.writeLock().lock();
132         try {
133             if (this.notifiers.containsKey(queryName)) {
134                 final XMLEventNotifier notifier = this.notifiers.get(queryName);
135 
136                 this.observable.detach(notifier);
137                 this.notifiers.remove(queryName);
138 
139                 if (LOGGER.isInfoEnabled()) {
140                     LOGGER.info(MessageFormat.format(
141                             "Successfully destroyed notifier ''{0}''.",
142                             queryName));
143                 }
144             } else {
145                 if (LOGGER.isEnabledFor(Level.ERROR)) {
146                     LOGGER.error(MessageFormat.format(
147                             "Failed to destroy notifier ''{0}''! Notifier does not exist.",
148                             queryName));
149                 }
150             }
151         } finally {
152             this.lock.writeLock().unlock();
153         }
154     }
155 }