1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.opencastproject.execute.impl.endpoint;
24
25 import org.opencastproject.execute.api.ExecuteException;
26 import org.opencastproject.execute.api.ExecuteService;
27 import org.opencastproject.job.api.JaxbJob;
28 import org.opencastproject.job.api.Job;
29 import org.opencastproject.job.api.JobProducer;
30 import org.opencastproject.mediapackage.MediaPackage;
31 import org.opencastproject.mediapackage.MediaPackageElement;
32 import org.opencastproject.mediapackage.MediaPackageElementParser;
33 import org.opencastproject.mediapackage.MediaPackageException;
34 import org.opencastproject.mediapackage.MediaPackageParser;
35 import org.opencastproject.rest.AbstractJobProducerEndpoint;
36 import org.opencastproject.serviceregistry.api.ServiceRegistry;
37 import org.opencastproject.util.doc.rest.RestParameter;
38 import org.opencastproject.util.doc.rest.RestQuery;
39 import org.opencastproject.util.doc.rest.RestResponse;
40 import org.opencastproject.util.doc.rest.RestService;
41
42 import org.apache.commons.lang3.StringUtils;
43 import org.osgi.service.component.annotations.Component;
44 import org.osgi.service.component.annotations.Reference;
45 import org.osgi.service.jaxrs.whiteboard.propertytypes.JaxrsResource;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import javax.servlet.http.HttpServletResponse;
50 import javax.ws.rs.FormParam;
51 import javax.ws.rs.POST;
52 import javax.ws.rs.Path;
53 import javax.ws.rs.Produces;
54 import javax.ws.rs.core.MediaType;
55 import javax.ws.rs.core.Response;
56
57
58
59
60 @Path("/execute")
61
62 @RestService(
63 name = "execute",
64 title = "Execute Service",
65 notes = {"" },
66 abstractText = "Runs CLI commands with MediaPackageElement's as parameters"
67 )
68 @Component(
69 immediate = true,
70 service = ExecuteRestEndpoint.class,
71 property = {
72 "service.description=Execute REST Endpoint",
73 "opencast.service.type=org.opencastproject.execute",
74 "opencast.service.path=/execute",
75 "opencast.service.jobproducer=true"
76 }
77 )
78 @JaxrsResource
79 public class ExecuteRestEndpoint extends AbstractJobProducerEndpoint {
80
81
82 private static final Logger logger = LoggerFactory.getLogger(ExecuteRestEndpoint.class);
83
84
85 protected ServiceRegistry serviceRegistry = null;
86
87
88 protected ExecuteService service;
89
90 @POST
91 @Produces(MediaType.TEXT_XML)
92 @Path(ExecuteService.ENDPOINT_NAME)
93 @RestQuery(
94 name = "name",
95 description = "Executes the given command",
96 restParameters = {
97 @RestParameter(description = "The command to execute", isRequired = true,
98 name = ExecuteService.EXEC_FORM_PARAM, type = RestParameter.Type.STRING),
99 @RestParameter(description = "The arguments to the command", isRequired = true,
100 name = ExecuteService.PARAMS_FORM_PARAM, type = RestParameter.Type.STRING),
101 @RestParameter(description = "The estimated load placed on the system by this command", isRequired = false,
102 name = ExecuteService.LOAD_FORM_PARAM, type = RestParameter.Type.FLOAT),
103 @RestParameter(description = "The mediapackage to apply the command to. Either this or "
104 + ExecuteService.INPUT_ELEM_FORM_PARAM + " are required", isRequired = false,
105 name = ExecuteService.INPUT_MP_FORM_PARAM, type = RestParameter.Type.TEXT),
106 @RestParameter(description = "The mediapackage element to apply the command to. Either this or "
107 + ExecuteService.INPUT_MP_FORM_PARAM + " are required", isRequired = false,
108 name = ExecuteService.INPUT_ELEM_FORM_PARAM, type = RestParameter.Type.TEXT),
109 @RestParameter(description = "The mediapackage element produced by the command", isRequired = false,
110 name = ExecuteService.OUTPUT_NAME_FORM_PARAMETER, type = RestParameter.Type.STRING),
111 @RestParameter(description = "The type of the returned element", isRequired = false,
112 name = ExecuteService.TYPE_FORM_PARAMETER, type = RestParameter.Type.STRING)
113 },
114 responses = {
115 @RestResponse(description = "XML-encoded Job is returned.", responseCode = HttpServletResponse.SC_NO_CONTENT),
116 @RestResponse(description = "Service unavailabe or not currently present",
117 responseCode = HttpServletResponse.SC_SERVICE_UNAVAILABLE),
118 @RestResponse(description = "Incorrect parameters", responseCode = HttpServletResponse.SC_BAD_REQUEST),
119 @RestResponse(description = "Problem executing the command or serializing the arguments/results",
120 responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
121 },
122 returnDescription = "")
123 public Response execute(@FormParam(ExecuteService.EXEC_FORM_PARAM) String exec,
124 @FormParam(ExecuteService.PARAMS_FORM_PARAM) String params,
125 @FormParam(ExecuteService.LOAD_FORM_PARAM) Float loadParam,
126 @FormParam(ExecuteService.INPUT_ELEM_FORM_PARAM) String inputElementStr,
127 @FormParam(ExecuteService.INPUT_MP_FORM_PARAM) String inputMpStr,
128 @FormParam(ExecuteService.OUTPUT_NAME_FORM_PARAMETER) String outputFileName,
129 @FormParam(ExecuteService.TYPE_FORM_PARAMETER) String elementTypeStr) {
130
131 checkNotNull(service);
132 try {
133
134 MediaPackageElement.Type expectedType = null;
135 if (StringUtils.isNotBlank(elementTypeStr)) {
136 for (MediaPackageElement.Type candidateType : MediaPackageElement.Type.values()) {
137 if (candidateType.toString().equalsIgnoreCase(elementTypeStr)) {
138 expectedType = candidateType;
139 break;
140 }
141 }
142 if (expectedType == null) {
143 logger.error("Wrong element type specified: {}", elementTypeStr);
144 return Response.status(Response.Status.BAD_REQUEST).build();
145 }
146 }
147
148 float load = 1.0f;
149 if (loadParam != null) {
150 load = loadParam;
151 }
152
153 Job retJob = null;
154 if (StringUtils.isNotBlank(inputElementStr) && StringUtils.isNotBlank(inputMpStr)) {
155 logger.error("Only one input MediaPackage OR input MediaPackageElement can be set at the same time");
156 return Response.status(Response.Status.BAD_REQUEST).build();
157 } else if (StringUtils.isNotBlank(inputElementStr)) {
158 MediaPackageElement inputElement = MediaPackageElementParser.getFromXml(inputElementStr);
159 retJob = service.execute(exec, params, inputElement, outputFileName, expectedType, load);
160 } else if (StringUtils.isNotBlank(inputMpStr)) {
161 MediaPackage inputMp = MediaPackageParser.getFromXml(inputMpStr);
162 retJob = service.execute(exec, params, inputMp, outputFileName, expectedType, load);
163 } else {
164 logger.error("A MediaPackage OR MediaPackageElement must be provided");
165 return Response.status(Response.Status.BAD_REQUEST).build();
166 }
167
168 return Response.ok(new JaxbJob(retJob)).build();
169
170 } catch (IllegalArgumentException e) {
171 logger.error("The expected element type is required if an output filename is specified");
172 return Response.status(Response.Status.BAD_REQUEST).build();
173 } catch (MediaPackageException e) {
174 logger.error("Received excepcion: {}", e.getMessage());
175 return Response.serverError().build();
176 } catch (ExecuteException e) {
177 logger.error("Received error from the execute service: {}", e.getMessage());
178 return Response.serverError().build();
179 }
180 }
181
182
183
184
185
186
187
188 @Reference
189 public void setExecuteService(ExecuteService service) {
190 this.service = service;
191 }
192
193
194
195
196
197
198 @Override
199 public JobProducer getService() {
200 if (service instanceof JobProducer) {
201 return (JobProducer) service;
202 } else {
203 return null;
204 }
205 }
206
207
208
209
210
211
212
213 protected void checkNotNull(Object... services) {
214 if (services != null) {
215 for (Object object : services) {
216 if (object == null) {
217 throw new javax.ws.rs.WebApplicationException(javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE);
218 }
219 }
220 }
221 }
222
223
224
225
226
227
228
229 @Reference
230 protected void setServiceRegistry(ServiceRegistry serviceRegistry) {
231 this.serviceRegistry = serviceRegistry;
232 }
233
234
235
236
237
238
239 @Override
240 public ServiceRegistry getServiceRegistry() {
241 return serviceRegistry;
242 }
243 }