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(name = "execute", title = "Execute Service", notes = {"" }, abstractText = "Runs CLI commands with MediaPackageElement's as parameters")
63 @Component(
64 immediate = true,
65 service = ExecuteRestEndpoint.class,
66 property = {
67 "service.description=Execute REST Endpoint",
68 "opencast.service.type=org.opencastproject.execute",
69 "opencast.service.path=/execute",
70 "opencast.service.jobproducer=true"
71 }
72 )
73 @JaxrsResource
74 public class ExecuteRestEndpoint extends AbstractJobProducerEndpoint {
75
76
77 private static final Logger logger = LoggerFactory.getLogger(ExecuteRestEndpoint.class);
78
79
80 protected ServiceRegistry serviceRegistry = null;
81
82
83 protected ExecuteService service;
84
85 @POST
86 @Produces(MediaType.TEXT_XML)
87 @Path(ExecuteService.ENDPOINT_NAME)
88 @RestQuery(name = "name", description = "Executes the given command", restParameters = {
89 @RestParameter(description = "The command to execute", isRequired = true, name = ExecuteService.EXEC_FORM_PARAM, type = RestParameter.Type.STRING),
90 @RestParameter(description = "The arguments to the command", isRequired = true, name = ExecuteService.PARAMS_FORM_PARAM, type = RestParameter.Type.STRING),
91 @RestParameter(description = "The estimated load placed on the system by this command", isRequired = false, name = ExecuteService.LOAD_FORM_PARAM, type = RestParameter.Type.FLOAT),
92 @RestParameter(description = "The mediapackage to apply the command to. Either this or " + ExecuteService.INPUT_ELEM_FORM_PARAM + " are required",
93 isRequired = false, name = ExecuteService.INPUT_MP_FORM_PARAM, type = RestParameter.Type.TEXT),
94 @RestParameter(description = "The mediapackage element to apply the command to. Either this or " + ExecuteService.INPUT_MP_FORM_PARAM + " are required",
95 isRequired = false, name = ExecuteService.INPUT_ELEM_FORM_PARAM, type = RestParameter.Type.TEXT),
96 @RestParameter(description = "The mediapackage element produced by the command", isRequired = false, name = ExecuteService.OUTPUT_NAME_FORM_PARAMETER,
97 type = RestParameter.Type.STRING),
98 @RestParameter(description = "The type of the returned element", isRequired = false, name = ExecuteService.TYPE_FORM_PARAMETER, type = RestParameter.Type.STRING) },
99 responses = {
100 @RestResponse(description = "XML-encoded Job is returned.", responseCode = HttpServletResponse.SC_NO_CONTENT),
101 @RestResponse(description = "Service unavailabe or not currently present", responseCode = HttpServletResponse.SC_SERVICE_UNAVAILABLE),
102 @RestResponse(description = "Incorrect parameters", responseCode = HttpServletResponse.SC_BAD_REQUEST),
103 @RestResponse(description = "Problem executing the command or serializing the arguments/results", responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR)
104 },
105 returnDescription = "")
106 public Response execute(@FormParam(ExecuteService.EXEC_FORM_PARAM) String exec,
107 @FormParam(ExecuteService.PARAMS_FORM_PARAM) String params,
108 @FormParam(ExecuteService.LOAD_FORM_PARAM) Float loadParam,
109 @FormParam(ExecuteService.INPUT_ELEM_FORM_PARAM) String inputElementStr,
110 @FormParam(ExecuteService.INPUT_MP_FORM_PARAM) String inputMpStr,
111 @FormParam(ExecuteService.OUTPUT_NAME_FORM_PARAMETER) String outputFileName,
112 @FormParam(ExecuteService.TYPE_FORM_PARAMETER) String elementTypeStr) {
113
114 checkNotNull(service);
115 try {
116
117 MediaPackageElement.Type expectedType = null;
118 if (StringUtils.isNotBlank(elementTypeStr)) {
119 for (MediaPackageElement.Type candidateType : MediaPackageElement.Type.values())
120 if (candidateType.toString().equalsIgnoreCase(elementTypeStr)) {
121 expectedType = candidateType;
122 break;
123 }
124 if (expectedType == null) {
125 logger.error("Wrong element type specified: {}", elementTypeStr);
126 return Response.status(Response.Status.BAD_REQUEST).build();
127 }
128 }
129
130 float load = 1.0f;
131 if (loadParam != null) {
132 load = loadParam;
133 }
134
135 Job retJob = null;
136 if (StringUtils.isNotBlank(inputElementStr) && StringUtils.isNotBlank(inputMpStr)) {
137 logger.error("Only one input MediaPackage OR input MediaPackageElement can be set at the same time");
138 return Response.status(Response.Status.BAD_REQUEST).build();
139 } else if (StringUtils.isNotBlank(inputElementStr)) {
140 MediaPackageElement inputElement = MediaPackageElementParser.getFromXml(inputElementStr);
141 retJob = service.execute(exec, params, inputElement, outputFileName, expectedType, load);
142 } else if (StringUtils.isNotBlank(inputMpStr)) {
143 MediaPackage inputMp = MediaPackageParser.getFromXml(inputMpStr);
144 retJob = service.execute(exec, params, inputMp, outputFileName, expectedType, load);
145 } else {
146 logger.error("A MediaPackage OR MediaPackageElement must be provided");
147 return Response.status(Response.Status.BAD_REQUEST).build();
148 }
149
150 return Response.ok(new JaxbJob(retJob)).build();
151
152 } catch (IllegalArgumentException e) {
153 logger.error("The expected element type is required if an output filename is specified");
154 return Response.status(Response.Status.BAD_REQUEST).build();
155 } catch (MediaPackageException e) {
156 logger.error("Received excepcion: {}", e.getMessage());
157 return Response.serverError().build();
158 } catch (ExecuteException e) {
159 logger.error("Received error from the execute service: {}", e.getMessage());
160 return Response.serverError().build();
161 }
162 }
163
164
165
166
167
168
169
170 @Reference
171 public void setExecuteService(ExecuteService service) {
172 this.service = service;
173 }
174
175
176
177
178
179
180 @Override
181 public JobProducer getService() {
182 if (service instanceof JobProducer)
183 return (JobProducer) service;
184 else
185 return null;
186 }
187
188
189
190
191
192
193
194 protected void checkNotNull(Object... services) {
195 if (services != null) {
196 for (Object object : services) {
197 if (object == null) {
198 throw new javax.ws.rs.WebApplicationException(javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE);
199 }
200 }
201 }
202 }
203
204
205
206
207
208
209
210 @Reference
211 protected void setServiceRegistry(ServiceRegistry serviceRegistry) {
212 this.serviceRegistry = serviceRegistry;
213 }
214
215
216
217
218
219
220 @Override
221 public ServiceRegistry getServiceRegistry() {
222 return serviceRegistry;
223 }
224 }