1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.protocol.sync;
17
18 import org.fourthline.cling.UpnpService;
19 import org.fourthline.cling.model.action.ActionCancelledException;
20 import org.fourthline.cling.model.action.ActionException;
21 import org.fourthline.cling.model.action.ActionInvocation;
22 import org.fourthline.cling.model.message.StreamResponseMessage;
23 import org.fourthline.cling.model.message.UpnpResponse;
24 import org.fourthline.cling.model.message.control.IncomingActionResponseMessage;
25 import org.fourthline.cling.model.message.control.OutgoingActionRequestMessage;
26 import org.fourthline.cling.model.meta.Device;
27 import org.fourthline.cling.model.types.ErrorCode;
28 import org.fourthline.cling.protocol.SendingSync;
29 import org.fourthline.cling.model.UnsupportedDataException;
30 import org.fourthline.cling.transport.RouterException;
31 import org.seamless.util.Exceptions;
32
33 import java.net.URL;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class SendingAction extends SendingSync<OutgoingActionRequestMessage, IncomingActionResponseMessage> {
52
53 final private static Logger log = Logger.getLogger(SendingAction.class.getName());
54
55 final protected ActionInvocation actionInvocation;
56
57 public SendingAction(UpnpService upnpService, ActionInvocation actionInvocation, URL controlURL) {
58 super(upnpService, new OutgoingActionRequestMessage(actionInvocation, controlURL));
59 this.actionInvocation = actionInvocation;
60 }
61
62 protected IncomingActionResponseMessage executeSync() throws RouterException {
63 return invokeRemote(getInputMessage());
64 }
65
66 protected IncomingActionResponseMessage invokeRemote(OutgoingActionRequestMessage requestMessage) throws RouterException {
67 Device device = actionInvocation.getAction().getService().getDevice();
68
69 log.fine("Sending outgoing action call '" + actionInvocation.getAction().getName() + "' to remote service of: " + device);
70 IncomingActionResponseMessage responseMessage = null;
71 try {
72
73 StreamResponseMessage streamResponse = sendRemoteRequest(requestMessage);
74
75 if (streamResponse == null) {
76 log.fine("No connection or no no response received, returning null");
77 actionInvocation.setFailure(new ActionException(ErrorCode.ACTION_FAILED, "Connection error or no response received"));
78 return null;
79 }
80
81 responseMessage = new IncomingActionResponseMessage(streamResponse);
82
83 if (responseMessage.isFailedNonRecoverable()) {
84 log.fine("Response was a non-recoverable failure: " + responseMessage);
85 throw new ActionException(
86 ErrorCode.ACTION_FAILED, "Non-recoverable remote execution failure: " + responseMessage.getOperation().getResponseDetails()
87 );
88 } else if (responseMessage.isFailedRecoverable()) {
89 handleResponseFailure(responseMessage);
90 } else {
91 handleResponse(responseMessage);
92 }
93
94 return responseMessage;
95
96
97 } catch (ActionException ex) {
98 log.fine("Remote action invocation failed, returning Internal Server Error message: " + ex.getMessage());
99 actionInvocation.setFailure(ex);
100 if (responseMessage == null || !responseMessage.getOperation().isFailed()) {
101 return new IncomingActionResponseMessage(new UpnpResponse(UpnpResponse.Status.INTERNAL_SERVER_ERROR));
102 } else {
103 return responseMessage;
104 }
105 }
106 }
107
108 protected StreamResponseMessage sendRemoteRequest(OutgoingActionRequestMessage requestMessage)
109 throws ActionException, RouterException {
110
111 try {
112 log.fine("Writing SOAP request body of: " + requestMessage);
113 getUpnpService().getConfiguration().getSoapActionProcessor().writeBody(requestMessage, actionInvocation);
114
115 log.fine("Sending SOAP body of message as stream to remote device");
116 return getUpnpService().getRouter().send(requestMessage);
117 } catch (RouterException ex) {
118 Throwable cause = Exceptions.unwrap(ex);
119 if (cause instanceof InterruptedException) {
120 if (log.isLoggable(Level.FINE)) {
121 log.fine("Sending action request message was interrupted: " + cause);
122 }
123 throw new ActionCancelledException((InterruptedException)cause);
124 }
125 throw ex;
126 } catch (UnsupportedDataException ex) {
127 if (log.isLoggable(Level.FINE)) {
128 log.fine("Error writing SOAP body: " + ex);
129 log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex));
130 }
131 throw new ActionException(ErrorCode.ACTION_FAILED, "Error writing request message. " + ex.getMessage());
132 }
133 }
134
135 protected void handleResponse(IncomingActionResponseMessage responseMsg) throws ActionException {
136
137 try {
138 log.fine("Received response for outgoing call, reading SOAP response body: " + responseMsg);
139 getUpnpService().getConfiguration().getSoapActionProcessor().readBody(responseMsg, actionInvocation);
140 } catch (UnsupportedDataException ex) {
141 log.fine("Error reading SOAP body: " + ex);
142 log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex));
143 throw new ActionException(
144 ErrorCode.ACTION_FAILED,
145 "Error reading SOAP response message. " + ex.getMessage(),
146 false
147 );
148 }
149 }
150
151 protected void handleResponseFailure(IncomingActionResponseMessage responseMsg) throws ActionException {
152
153 try {
154 log.fine("Received response with Internal Server Error, reading SOAP failure message");
155 getUpnpService().getConfiguration().getSoapActionProcessor().readBody(responseMsg, actionInvocation);
156 } catch (UnsupportedDataException ex) {
157 log.fine("Error reading SOAP body: " + ex);
158 log.log(Level.FINE, "Exception root cause: ", Exceptions.unwrap(ex));
159 throw new ActionException(
160 ErrorCode.ACTION_FAILED,
161 "Error reading SOAP response failure message. " + ex.getMessage(),
162 false
163 );
164 }
165 }
166
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189