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.support.connectionmanager;
17  
18  import org.fourthline.cling.binding.annotations.UpnpAction;
19  import org.fourthline.cling.binding.annotations.UpnpInputArgument;
20  import org.fourthline.cling.binding.annotations.UpnpOutputArgument;
21  import org.fourthline.cling.binding.annotations.UpnpService;
22  import org.fourthline.cling.binding.annotations.UpnpServiceId;
23  import org.fourthline.cling.binding.annotations.UpnpServiceType;
24  import org.fourthline.cling.binding.annotations.UpnpStateVariable;
25  import org.fourthline.cling.binding.annotations.UpnpStateVariables;
26  import org.fourthline.cling.model.ServiceReference;
27  import org.fourthline.cling.model.action.ActionException;
28  import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
29  import org.fourthline.cling.model.types.csv.CSV;
30  import org.fourthline.cling.model.types.csv.CSVUnsignedIntegerFourBytes;
31  import org.fourthline.cling.support.model.ConnectionInfo;
32  import org.fourthline.cling.support.model.ProtocolInfo;
33  import org.fourthline.cling.support.model.ProtocolInfos;
34  
35  import java.beans.PropertyChangeSupport;
36  import java.util.Map;
37  import java.util.concurrent.ConcurrentHashMap;
38  import java.util.logging.Logger;
39  
40  /**
41   * Base for connection management, implements the connection ID "0" behavior.
42   *
43   * @author Christian Bauer
44   * @author Alessio Gaeta
45   */
46  @UpnpService(
47          serviceId = @UpnpServiceId("ConnectionManager"),
48          serviceType = @UpnpServiceType(value = "ConnectionManager", version = 1),
49          stringConvertibleTypes = {ProtocolInfo.class, ProtocolInfos.class, ServiceReference.class}
50  )
51  @UpnpStateVariables({
52          @UpnpStateVariable(name = "SourceProtocolInfo", datatype = "string"),
53          @UpnpStateVariable(name = "SinkProtocolInfo", datatype = "string"),
54          @UpnpStateVariable(name = "CurrentConnectionIDs", datatype = "string"),
55          @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionStatus", allowedValuesEnum = ConnectionInfo.Status.class, sendEvents = false),
56          @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionManager", datatype = "string", sendEvents = false),
57          @UpnpStateVariable(name = "A_ARG_TYPE_Direction", allowedValuesEnum = ConnectionInfo.Direction.class, sendEvents = false),
58          @UpnpStateVariable(name = "A_ARG_TYPE_ProtocolInfo", datatype = "string", sendEvents = false),
59          @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionID", datatype = "i4", sendEvents = false),
60          @UpnpStateVariable(name = "A_ARG_TYPE_AVTransportID", datatype = "i4", sendEvents = false),
61          @UpnpStateVariable(name = "A_ARG_TYPE_RcsID", datatype = "i4", sendEvents = false)
62  })
63  public class ConnectionManagerService {
64  
65      final private static Logger log = Logger.getLogger(ConnectionManagerService.class.getName());
66  
67      final protected PropertyChangeSupport propertyChangeSupport;
68      final protected Map<Integer, ConnectionInfo> activeConnections = new ConcurrentHashMap();
69      final protected ProtocolInfos sourceProtocolInfo;
70      final protected ProtocolInfos sinkProtocolInfo;
71  
72      /**
73       * Creates a default "active" connection with identifier "0".
74       */
75      public ConnectionManagerService() {
76          this(new ConnectionInfo());
77      }
78  
79      /**
80       * Creates a default "active" connection with identifier "0".
81       */
82      public ConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo) {
83          this(sourceProtocolInfo, sinkProtocolInfo, new ConnectionInfo());
84      }
85  
86      public ConnectionManagerService(ConnectionInfo... activeConnections) {
87          this(null, new ProtocolInfos(), new ProtocolInfos(), activeConnections);
88      }
89  
90      public ConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, ConnectionInfo... activeConnections) {
91          this(null, sourceProtocolInfo, sinkProtocolInfo, activeConnections);
92      }
93  
94      public ConnectionManagerService(PropertyChangeSupport propertyChangeSupport,
95                                              ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo,
96                                              ConnectionInfo... activeConnections) {
97          this.propertyChangeSupport =
98                  propertyChangeSupport == null
99                          ? new PropertyChangeSupport(this) : propertyChangeSupport;
100 
101         this.sourceProtocolInfo = sourceProtocolInfo;
102         this.sinkProtocolInfo = sinkProtocolInfo;
103 
104         for (ConnectionInfo activeConnection : activeConnections) {
105             this.activeConnections.put(activeConnection.getConnectionID(), activeConnection);
106         }
107     }
108 
109     public PropertyChangeSupport getPropertyChangeSupport() {
110         return propertyChangeSupport;
111     }
112 
113     @UpnpAction(out = {
114             @UpnpOutputArgument(name = "RcsID", getterName = "getRcsID"),
115             @UpnpOutputArgument(name = "AVTransportID", getterName = "getAvTransportID"),
116             @UpnpOutputArgument(name = "ProtocolInfo", getterName = "getProtocolInfo"),
117             @UpnpOutputArgument(name = "PeerConnectionManager", stateVariable = "A_ARG_TYPE_ConnectionManager", getterName = "getPeerConnectionManager"),
118             @UpnpOutputArgument(name = "PeerConnectionID", stateVariable = "A_ARG_TYPE_ConnectionID", getterName = "getPeerConnectionID"),
119             @UpnpOutputArgument(name = "Direction", getterName = "getDirection"),
120             @UpnpOutputArgument(name = "Status", stateVariable = "A_ARG_TYPE_ConnectionStatus", getterName = "getConnectionStatus")
121     })
122     synchronized public ConnectionInfo getCurrentConnectionInfo(@UpnpInputArgument(name = "ConnectionID") int connectionId)
123             throws ActionException {
124         log.fine("Getting connection information of connection ID: " + connectionId);
125         ConnectionInfo info;
126         if ((info = activeConnections.get(connectionId)) == null) {
127             throw new ConnectionManagerException(
128                     ConnectionManagerErrorCode.INVALID_CONNECTION_REFERENCE,
129                     "Non-active connection ID: " + connectionId
130             );
131         }
132         return info;
133     }
134 
135     @UpnpAction(out = {
136             @UpnpOutputArgument(name = "ConnectionIDs")
137     })
138     synchronized public CSV<UnsignedIntegerFourBytes> getCurrentConnectionIDs() {
139         CSV<UnsignedIntegerFourBytes> csv = new CSVUnsignedIntegerFourBytes();
140         for (Integer connectionID : activeConnections.keySet()) {
141             csv.add(new UnsignedIntegerFourBytes(connectionID));
142         }
143         log.fine("Returning current connection IDs: " + csv.size());
144         return csv;
145     }
146 
147     @UpnpAction(out = {
148             @UpnpOutputArgument(name = "Source", stateVariable = "SourceProtocolInfo", getterName = "getSourceProtocolInfo"),
149             @UpnpOutputArgument(name = "Sink", stateVariable = "SinkProtocolInfo", getterName = "getSinkProtocolInfo")
150     })
151     synchronized public void getProtocolInfo() throws ActionException {
152         // NOOP
153     }
154 
155     synchronized public ProtocolInfos getSourceProtocolInfo() {
156         return sourceProtocolInfo;
157     }
158 
159     synchronized public ProtocolInfos getSinkProtocolInfo() {
160         return sinkProtocolInfo;
161     }
162 }