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.rest.model;
19  
20  import java.io.BufferedReader;
21  import java.io.IOException;
22  import java.io.InputStreamReader;
23  import java.io.OutputStream;
24  import java.net.HttpURLConnection;
25  import java.net.URL;
26  import java.net.URLConnection;
27  import java.text.MessageFormat;
28  import javax.xml.transform.OutputKeys;
29  import javax.xml.transform.Transformer;
30  import javax.xml.transform.TransformerException;
31  import javax.xml.transform.TransformerFactory;
32  import javax.xml.transform.dom.DOMSource;
33  import javax.xml.transform.stream.StreamResult;
34  import org.apache.log4j.Level;
35  import org.apache.log4j.Logger;
36  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEvent;
37  import at.ac.tuwien.infosys.sm4all.copal.api.event.XMLContextEvent;
38  import at.ac.tuwien.infosys.sm4all.copal.api.listener.BaseListener;
39  import at.ac.tuwien.infosys.sm4all.copal.api.listener.ContextListener;
40  
41  /**
42   * {@link ContextListener} that is used by REST service to listen on and publish
43   * events remotely.
44   * 
45   * @author sanjin
46   */
47  public class RESTfulListener extends BaseListener {
48  
49      private static final Logger LOGGER = Logger.getLogger(RESTfulListener.class);
50  
51      private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
52  
53      private final URL url;
54  
55      /**
56       * Creates an instance of RESTful {@link ContextListener} that has specified
57       * name and publishes each received event to specified {@link URL}.
58       * 
59       * @param name the name.
60       * @param url the {@link URL} where to publish received events.
61       */
62      public RESTfulListener(final String name, final URL url) {
63          super(name);
64  
65          this.url = url;
66      }
67  
68      @Override
69      public void onEvent(final ContextEvent event) {
70          if (event instanceof XMLContextEvent) {
71              URLConnection connection = null;
72              OutputStream out = null;
73              BufferedReader in = null;
74              try {
75                  connection = this.url.openConnection();
76  
77                  connection.setDoOutput(true);
78                  if (connection instanceof HttpURLConnection) {
79                      ((HttpURLConnection) connection).setRequestMethod("POST");
80                  }
81  
82                  out = connection.getOutputStream();
83  
84                  final Transformer transformer = this.transformerFactory.newTransformer();
85                  transformer.setOutputProperty(OutputKeys.INDENT, "yes");
86                  final StreamResult result = new StreamResult(out);
87                  final DOMSource source = new DOMSource(
88                          ((XMLContextEvent) event).getDocument());
89                  transformer.transform(source, result);
90  
91                  in = new BufferedReader(new InputStreamReader(
92                          connection.getInputStream()));
93                  for (String response = in.readLine(); null != response; response = in.readLine()) {
94                      if (LOGGER.isInfoEnabled()) {
95                          LOGGER.info(MessageFormat.format(
96                                  "Received response on POST from ''{0}'': {1}",
97                                  this.url, response));
98                      }
99                  }
100 
101                 if (LOGGER.isInfoEnabled()) {
102                     LOGGER.info(MessageFormat.format(
103                             "Successfully sent event to {0}.", this.url));
104                 }
105             } catch (final IOException ex) {
106                 if (LOGGER.isEnabledFor(Level.ERROR)) {
107                     LOGGER.error(MessageFormat.format(
108                             "Could not connect to {0}! Event not sent.",
109                             this.url), ex);
110                 }
111             } catch (final TransformerException ex) {
112                 if (LOGGER.isEnabledFor(Level.ERROR)) {
113                     LOGGER.error(MessageFormat.format(
114                             "Could not send event to {0}!", this.url), ex);
115                 }
116             } finally {
117                 if (null != out) {
118                     try {
119                         out.close();
120                     } catch (final IOException ex) {
121                         if (LOGGER.isEnabledFor(Level.WARN)) {
122                             LOGGER.warn(
123                                     MessageFormat.format(
124                                             "Could not cleanly close connection to {0}! Ignoring.",
125                                             this.url), ex);
126                         }
127                     }
128                 }
129                 if (null != in) {
130                     try {
131                         in.close();
132                     } catch (final IOException ex) {
133                         if (LOGGER.isEnabledFor(Level.WARN)) {
134                             LOGGER.warn(
135                                     MessageFormat.format(
136                                             "Could not cleanly close connection to {0}! Ignoring.",
137                                             this.url), ex);
138                         }
139                     }
140                 }
141                 if ((null != connection)
142                         && (connection instanceof HttpURLConnection)) {
143                     ((HttpURLConnection) connection).disconnect();
144                 }
145             }
146         }
147     }
148 }