View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.protocol;
17  
18  import org.fourthline.cling.UpnpService;
19  import org.fourthline.cling.model.message.UpnpMessage;
20  import org.fourthline.cling.model.message.header.UpnpHeader;
21  import org.fourthline.cling.transport.RouterException;
22  import org.seamless.util.Exceptions;
23  
24  import java.util.logging.Level;
25  import java.util.logging.Logger;
26  
27  /**
28   * Supertype for all asynchronously executing protocols, handling reception of UPnP messages.
29   * <p>
30   * After instantiation by the {@link ProtocolFactory}, this protocol <code>run()</code>s and
31   * calls its own {@link #waitBeforeExecution()} method. By default, the protocol does not wait
32   * before then proceeding with {@link #execute()}.
33   * </p>
34   *
35   * @param <M> The type of UPnP message handled by this protocol.
36   *
37   * @author Christian Bauer
38   */
39  public abstract class ReceivingAsync<M extends UpnpMessage> implements Runnable {
40  
41      final private static Logger log = Logger.getLogger(UpnpService.class.getName());
42  
43      private final UpnpService upnpService;
44  
45      private M inputMessage;
46  
47      protected ReceivingAsync(UpnpService upnpService, M inputMessage) {
48          this.upnpService = upnpService;
49          this.inputMessage = inputMessage;
50      }
51  
52      public UpnpService getUpnpService() {
53          return upnpService;
54      }
55  
56      public M getInputMessage() {
57          return inputMessage;
58      }
59  
60      public void run() {
61          boolean proceed;
62          try {
63              proceed = waitBeforeExecution();
64          } catch (InterruptedException ex) {
65              log.info("Protocol wait before execution interrupted (on shutdown?): " + getClass().getSimpleName());
66              proceed = false;
67          }
68  
69          if (proceed) {
70              try {
71                  execute();
72              } catch (Exception ex) {
73                  Throwable cause = Exceptions.unwrap(ex);
74                  if (cause instanceof InterruptedException) {
75                      log.log(Level.INFO, "Interrupted protocol '" + getClass().getSimpleName() + "': " + ex, cause);
76                  } else {
77                      throw new RuntimeException(
78                          "Fatal error while executing protocol '" + getClass().getSimpleName() + "': " + ex, ex
79                      );
80                  }
81              }
82          }
83      }
84  
85      /**
86       * Provides an opportunity to pause before executing the protocol.
87       *
88       * @return <code>true</code> (default) if execution should continue after waiting.
89       *
90       * @throws InterruptedException If waiting has been interrupted, which also stops execution.
91       */
92      protected boolean waitBeforeExecution() throws InterruptedException {
93          // Don't wait by default
94          return true;
95      }
96  
97      protected abstract void execute() throws RouterException;
98  
99      protected <H extends UpnpHeader> H getFirstHeader(UpnpHeader.Type headerType, Class<H> subtype) {
100         return getInputMessage().getHeaders().getFirstHeader(headerType, subtype);
101     }
102 
103     @Override
104     public String toString() {
105         return "(" + getClass().getSimpleName() + ")";
106     }
107 
108 }