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.RemoteActionInvocation;
22 import org.fourthline.cling.model.message.StreamRequestMessage;
23 import org.fourthline.cling.model.message.StreamResponseMessage;
24 import org.fourthline.cling.model.message.UpnpResponse;
25 import org.fourthline.cling.model.message.control.IncomingActionRequestMessage;
26 import org.fourthline.cling.model.message.control.OutgoingActionResponseMessage;
27 import org.fourthline.cling.model.message.header.ContentTypeHeader;
28 import org.fourthline.cling.model.message.header.UpnpHeader;
29 import org.fourthline.cling.model.resource.ServiceControlResource;
30 import org.fourthline.cling.model.types.ErrorCode;
31 import org.fourthline.cling.protocol.ReceivingSync;
32 import org.fourthline.cling.model.UnsupportedDataException;
33 import org.fourthline.cling.transport.RouterException;
34 import org.seamless.util.Exceptions;
35
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
38
39
40
41
42
43
44
45
46
47
48
49 public class ReceivingAction extends ReceivingSync<StreamRequestMessage, StreamResponseMessage> {
50
51 final private static Logger log = Logger.getLogger(ReceivingAction.class.getName());
52
53 public ReceivingAction(UpnpService upnpService, StreamRequestMessage inputMessage) {
54 super(upnpService, inputMessage);
55 }
56
57 protected StreamResponseMessage executeSync() throws RouterException{
58
59 ContentTypeHeader contentTypeHeader =
60 getInputMessage().getHeaders().getFirstHeader(UpnpHeader.Type.CONTENT_TYPE, ContentTypeHeader.class);
61
62
63
64
65 if (contentTypeHeader != null && !contentTypeHeader.isUDACompliantXML()) {
66 log.warning("Received invalid Content-Type '" + contentTypeHeader + "': " + getInputMessage());
67 return new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.UNSUPPORTED_MEDIA_TYPE));
68 }
69
70 if (contentTypeHeader == null) {
71 log.warning("Received without Content-Type: " + getInputMessage());
72 }
73
74 ServiceControlResource resource =
75 getUpnpService().getRegistry().getResource(
76 ServiceControlResource.class,
77 getInputMessage().getUri()
78 );
79
80 if (resource == null) {
81 log.fine("No local resource found: " + getInputMessage());
82 return null;
83 }
84
85 log.fine("Found local action resource matching relative request URI: " + getInputMessage().getUri());
86
87 RemoteActionInvocation invocation;
88 OutgoingActionResponseMessage responseMessage = null;
89
90 try {
91
92
93 IncomingActionRequestMessage requestMessage =
94 new IncomingActionRequestMessage(getInputMessage(), resource.getModel());
95
96 log.finer("Created incoming action request message: " + requestMessage);
97 invocation = new RemoteActionInvocation(requestMessage.getAction(), getRemoteClientInfo());
98
99
100 log.fine("Reading body of request message");
101 getUpnpService().getConfiguration().getSoapActionProcessor().readBody(requestMessage, invocation);
102
103 log.fine("Executing on local service: " + invocation);
104 resource.getModel().getExecutor(invocation.getAction()).execute(invocation);
105
106 if (invocation.getFailure() == null) {
107 responseMessage =
108 new OutgoingActionResponseMessage(invocation.getAction());
109 } else {
110
111 if (invocation.getFailure() instanceof ActionCancelledException) {
112 log.fine("Action execution was cancelled, returning 404 to client");
113
114
115
116 return null;
117 } else {
118 responseMessage =
119 new OutgoingActionResponseMessage(
120 UpnpResponse.Status.INTERNAL_SERVER_ERROR,
121 invocation.getAction()
122 );
123 }
124 }
125
126 } catch (ActionException ex) {
127 log.finer("Error executing local action: " + ex);
128
129 invocation = new RemoteActionInvocation(ex, getRemoteClientInfo());
130 responseMessage = new OutgoingActionResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR);
131
132 } catch (UnsupportedDataException ex) {
133 log.log(Level.WARNING, "Error reading action request XML body: " + ex.toString(), Exceptions.unwrap(ex));
134
135 invocation =
136 new RemoteActionInvocation(
137 Exceptions.unwrap(ex) instanceof ActionException
138 ? (ActionException)Exceptions.unwrap(ex)
139 : new ActionException(ErrorCode.ACTION_FAILED, ex.getMessage()),
140 getRemoteClientInfo()
141 );
142 responseMessage = new OutgoingActionResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR);
143
144 }
145
146 try {
147
148 log.fine("Writing body of response message");
149 getUpnpService().getConfiguration().getSoapActionProcessor().writeBody(responseMessage, invocation);
150
151 log.fine("Returning finished response message: " + responseMessage);
152 return responseMessage;
153
154 } catch (UnsupportedDataException ex) {
155 log.warning("Failure writing body of response message, sending '500 Internal Server Error' without body");
156 log.log(Level.WARNING, "Exception root cause: ", Exceptions.unwrap(ex));
157 return new StreamResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR);
158 }
159 }
160
161 }