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.conf;
19  
20  import java.text.MessageFormat;
21  import java.util.Arrays;
22  import java.util.HashSet;
23  import java.util.LinkedList;
24  import java.util.List;
25  import java.util.Set;
26  import java.util.concurrent.locks.ReadWriteLock;
27  import java.util.concurrent.locks.ReentrantReadWriteLock;
28  import org.apache.log4j.Level;
29  import org.apache.log4j.Logger;
30  import org.w3c.dom.Document;
31  import org.w3c.dom.Element;
32  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType;
33  import at.ac.tuwien.infosys.sm4all.copal.api.event.XMLContextEventType;
34  import at.ac.tuwien.infosys.sm4all.copal.api.event.xml.XMLContextEventTypeUnmarshaller;
35  import at.ac.tuwien.infosys.sm4all.copal.api.service.ContextEventTypeRegistry;
36  import at.ac.tuwien.infosys.sm4all.copal.api.util.AlreadyRegisteredException;
37  import at.ac.tuwien.infosys.sm4all.copal.api.util.FailedUnmarshallingException;
38  import at.ac.tuwien.infosys.sm4all.copal.api.util.NotRegisteredException;
39  
40  /**
41   * Configuration helper class that reads definitions of {@link ContextEventType}
42   * s from a XML configuration file that can be found in classpath.
43   * 
44   * @author sanjin
45   */
46  public class EventTypesConfiguration extends
47          BaseConfiguration<ContextEventType> {
48  
49      private static final ContextEventType[] EMPTY_EVENT_TYPES = new ContextEventType[0];
50      private static final Logger LOGGER = Logger.getLogger(EventTypesConfiguration.class);
51  
52      private final ReadWriteLock lock = new ReentrantReadWriteLock();
53      private final Set<ContextEventType> registeredTypes = new HashSet<ContextEventType>();
54      private final ContextEventType[] definedTypes;
55      private ContextEventTypeRegistry registry;
56  
57      /**
58       * Create instance of {@link ContextEventType} configuration that uses
59       * specified {@link ClassLoader} to find the XML configuration file with
60       * specified name.
61       * 
62       * @param classLoader the {@link ClassLoader}.
63       * @param fileName the name of the configuration file.
64       */
65      public EventTypesConfiguration(final ClassLoader classLoader,
66              final String fileName) {
67          super(classLoader, fileName, ContextEventTypeRegistry.class.getName());
68  
69          final Document document = getDocument();
70          if (null == document) {
71              this.definedTypes = EMPTY_EVENT_TYPES;
72          } else {
73              final Element context = document.getDocumentElement();
74              List<XMLContextEventType> eventTypes = new LinkedList<XMLContextEventType>();
75              try {
76                  eventTypes = XMLContextEventTypeUnmarshaller.getListBuilder(
77                          classLoader).withElement(context).build().unmarshal();
78              } catch (final FailedUnmarshallingException ex) {
79                  if (LOGGER.isEnabledFor(Level.ERROR)) {
80                      LOGGER.error("Could not unmarshal event type definitions!",
81                              ex);
82                  }
83              }
84              this.definedTypes = eventTypes.toArray(new ContextEventType[eventTypes.size()]);
85          }
86      }
87  
88      /**
89       * Returns the defined {@link ContextEventType}s in the XML configuration
90       * file or an empty array if there was problem reading the file.
91       * 
92       * @return the defined {@link ContextEventType}s in the XML configuration
93       *         file.
94       */
95      @Override
96      public ContextEventType[] getDefined() {
97          return Arrays.copyOf(this.definedTypes, this.definedTypes.length);
98      }
99  
100     /**
101      * Returns all registered {@link ContextEventType}s.
102      * 
103      * @return all registered {@link ContextEventType}s.
104      */
105     public ContextEventType[] getRegistered() {
106         final ContextEventType[] result;
107 
108         this.lock.readLock().lock();
109         try {
110             result = this.registeredTypes.toArray(new ContextEventType[this.registeredTypes.size()]);
111         } finally {
112             this.lock.readLock().unlock();
113         }
114 
115         return result;
116     }
117 
118     @Override
119     protected void start() {
120         this.lock.writeLock().lock();
121         try {
122             this.registry = getDependency(ContextEventTypeRegistry.class.getName());
123 
124             for (final ContextEventType eventType : this.definedTypes) {
125                 try {
126                     this.registry.register(eventType);
127                     this.registeredTypes.add(eventType);
128                 } catch (final AlreadyRegisteredException ex) {
129                     if (LOGGER.isEnabledFor(Level.WARN)) {
130                         LOGGER.warn(
131                                 MessageFormat.format(
132                                         "Could not register event type ''{0}''! Ignoring",
133                                         eventType.getName()), ex);
134                     }
135                 }
136             }
137         } finally {
138             this.lock.writeLock().unlock();
139         }
140     }
141 
142     @Override
143     protected void stop() {
144         this.lock.writeLock().lock();
145         try {
146             for (final ContextEventType eventType : this.registeredTypes) {
147                 final String eventName = eventType.getName();
148                 try {
149                     this.registry.unregister(eventName);
150                 } catch (final NotRegisteredException ex) {
151                     if (LOGGER.isEnabledFor(Level.WARN)) {
152                         LOGGER.warn(
153                                 MessageFormat.format(
154                                         "Could not unregister event type ''{0}''! Ignoring",
155                                         eventName), ex);
156                     }
157                 }
158             }
159 
160             this.registeredTypes.clear();
161             this.registry = null;
162         } finally {
163             this.lock.writeLock().unlock();
164         }
165     }
166 }