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.sync;
17  
18  import java.util.logging.Logger;
19  import org.fourthline.cling.UpnpService;
20  import org.fourthline.cling.model.gena.LocalGENASubscription;
21  import org.fourthline.cling.model.message.StreamResponseMessage;
22  import org.fourthline.cling.model.message.gena.OutgoingEventRequestMessage;
23  import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
24  import org.fourthline.cling.protocol.SendingSync;
25  import org.fourthline.cling.transport.RouterException;
26  
27  import java.net.URL;
28  
29  /**
30   * Sending GENA event messages to remote subscribers.
31   * <p>
32   * Any {@link org.fourthline.cling.model.gena.LocalGENASubscription} instantiates and executes this protocol
33   * when the state of a local service changes. However, a remote subscriber might require event
34   * notification messages on more than one callback URL, so this protocol potentially sends
35   * many messages. What is returned is always the last response, that is, the response for the
36   * message sent to the last callback URL in the list of the subscriber.
37   * </p>
38   *
39   * @author Christian Bauer
40   */
41  public class SendingEvent extends SendingSync<OutgoingEventRequestMessage, StreamResponseMessage> {
42  
43      final private static Logger log = Logger.getLogger(SendingEvent.class.getName());
44  
45      final protected String subscriptionId;
46      final protected OutgoingEventRequestMessage[] requestMessages;
47      final protected UnsignedIntegerFourBytes currentSequence;
48  
49      public SendingEvent(UpnpService upnpService, LocalGENASubscription subscription) {
50          super(upnpService, null); // Special case, we actually need to send several messages to each callback URL
51  
52          // TODO: Ugly design! It is critical (concurrency) that we prepare the event messages here, in the constructor thread!
53  
54          subscriptionId = subscription.getSubscriptionId();
55  
56          requestMessages = new OutgoingEventRequestMessage[subscription.getCallbackURLs().size()];
57          int i = 0;
58          for (URL url : subscription.getCallbackURLs()) {
59              requestMessages[i] = new OutgoingEventRequestMessage(subscription, url);
60              getUpnpService().getConfiguration().getGenaEventProcessor().writeBody(requestMessages[i]);
61              i++;
62          }
63  
64          currentSequence = subscription.getCurrentSequence();
65  
66          // Always increment sequence now, as (its value) has already been set on the headers and the
67          // next event will use the incremented value
68          subscription.incrementSequence();
69      }
70  
71      protected StreamResponseMessage executeSync() throws RouterException {
72  
73          log.fine("Sending event for subscription: " + subscriptionId);
74  
75          StreamResponseMessage lastResponse = null;
76  
77          for (OutgoingEventRequestMessage requestMessage : requestMessages) {
78  
79              if (currentSequence.getValue() == 0) {
80                  log.fine("Sending initial event message to callback URL: " + requestMessage.getUri());
81              } else {
82                  log.fine("Sending event message '"+currentSequence+"' to callback URL: " + requestMessage.getUri());
83              }
84  
85  
86              // Send request
87              lastResponse = getUpnpService().getRouter().send(requestMessage);
88              log.fine("Received event callback response: " + lastResponse);
89  
90          }
91  
92          // It's not really used, so just return the last one - we have only one callback URL most of the
93          // time anyway
94          return lastResponse;
95  
96      }
97  }