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