View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  package org.opencastproject.assetmanager.impl.endpoint;
22  
23  import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
24  import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
25  import static javax.servlet.http.HttpServletResponse.SC_OK;
26  import static org.opencastproject.util.RestUtil.R.badRequest;
27  import static org.opencastproject.util.RestUtil.R.ok;
28  
29  import org.opencastproject.assetmanager.impl.AssetManagerJobProducer;
30  import org.opencastproject.assetmanager.impl.VersionImpl;
31  import org.opencastproject.job.api.JaxbJob;
32  import org.opencastproject.job.api.Job;
33  import org.opencastproject.job.api.JobProducer;
34  import org.opencastproject.serviceregistry.api.ServiceRegistry;
35  import org.opencastproject.util.doc.rest.RestParameter;
36  import org.opencastproject.util.doc.rest.RestQuery;
37  import org.opencastproject.util.doc.rest.RestResponse;
38  
39  import org.apache.commons.lang3.StringUtils;
40  
41  import java.text.DateFormat;
42  import java.text.ParseException;
43  import java.text.SimpleDateFormat;
44  import java.util.Date;
45  
46  import javax.ws.rs.FormParam;
47  import javax.ws.rs.POST;
48  import javax.ws.rs.Path;
49  import javax.ws.rs.Produces;
50  import javax.ws.rs.core.MediaType;
51  import javax.ws.rs.core.Response;
52  
53  public abstract class AbstractTieredStorageAssetManagerRestEndpoint extends AbstractAssetManagerRestEndpoint {
54    public static final String SDF_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
55  
56    protected AssetManagerJobProducer tsamjp = null;
57    protected ServiceRegistry serviceRegistry = null;
58  
59    public void setJobProducer(AssetManagerJobProducer producer) {
60      tsamjp = producer;
61    }
62  
63    @Override
64    public JobProducer getService() {
65      return this.tsamjp;
66    }
67  
68    /**
69     * Callback from the OSGi declarative services to set the service registry.
70     *
71     * @param serviceRegistry
72     *          the service registry
73     */
74    protected void setServiceRegistry(ServiceRegistry serviceRegistry) {
75      this.serviceRegistry = serviceRegistry;
76    }
77  
78    @Override
79    public ServiceRegistry getServiceRegistry() {
80      return this.serviceRegistry;
81    }
82  
83    @POST
84    @Path("moveById")
85    @Produces(MediaType.TEXT_XML)
86    @RestQuery(name = "moveById", description = "Move a mediapackage based on its ID.",
87        restParameters = {
88            @RestParameter(
89                name = "id",
90                isRequired = true,
91                type = RestParameter.Type.STRING,
92                defaultValue = "",
93                description = "The mediapackage ID to move."),
94            @RestParameter(
95                name = "target",
96                isRequired = true,
97                type = RestParameter.Type.STRING,
98                defaultValue = "",
99                description = "The target storage to move the mediapackage to.")},
100       responses = {
101           @RestResponse(
102               description = "The job created to move the snapshot.",
103               responseCode = SC_OK),
104           @RestResponse(
105               description = "Invalid parameters, and the job was not created",
106               responseCode = SC_BAD_REQUEST),
107           @RestResponse(
108               description = "There has been an internal error, and the job was not created",
109               responseCode = SC_INTERNAL_SERVER_ERROR)},
110       returnDescription = "The Job created")
111   public Response moveById(@FormParam("id") final String id, @FormParam("target") final String target) {
112     String mpid = StringUtils.trimToNull(id);
113     if (null == mpid) {
114       return badRequest("Invalid mediapackage ID: " + mpid);
115     }
116 
117     final String trimmedTarget = StringUtils.trimToNull(target);
118     if (null == trimmedTarget) {
119       return badRequest("Invalid target store ID: " + trimmedTarget);
120     } else if (!tsamjp.datastoreExists(trimmedTarget)) {
121       return badRequest("Target store " + trimmedTarget + " not found");
122     }
123 
124     try {
125       Job j = tsamjp.moveById(mpid, trimmedTarget);
126       return Response.ok(new JaxbJob(j)).build();
127     } catch (Exception e) {
128       return handleException(e);
129     }
130   }
131 
132   @POST
133   @Path("moveByIdAndVersion")
134   @Produces(MediaType.TEXT_XML)
135   @RestQuery(name = "moveByIdAndVersion", description = "Move a mediapackage based on its ID and version.",
136       restParameters = {
137           @RestParameter(
138               name = "id",
139               isRequired = true,
140               type = RestParameter.Type.STRING,
141               defaultValue = "",
142               description = "The mediapackage ID to move."),
143           @RestParameter(
144               name = "version",
145               isRequired = true,
146               type = RestParameter.Type.STRING,
147               defaultValue = "",
148               description = "The version to move."),
149           @RestParameter(
150               name = "target",
151               isRequired = true,
152               type = RestParameter.Type.STRING,
153               defaultValue = "",
154               description = "The target storage to move the mediapackage to.")},
155       responses = {
156           @RestResponse(
157               description = "The job created to move the snapshot.",
158               responseCode = SC_OK),
159           @RestResponse(
160               description = "Invalid parameters, and the job was not created",
161               responseCode = SC_BAD_REQUEST),
162           @RestResponse(
163               description = "There has been an internal error, and the job was not created",
164               responseCode = SC_INTERNAL_SERVER_ERROR)},
165       returnDescription = "The Job created")
166   public Response moveByIdAndVersion(
167       @FormParam("id") final String id,
168       @FormParam("version") final String version,
169       @FormParam("target") final String target
170   ) {
171     final String mpid = StringUtils.trimToNull(id);
172     if (null == mpid) {
173       return badRequest("Invalid mediapackage ID: " + mpid);
174     }
175 
176     final VersionImpl v;
177     try {
178       Long versionNumber = Long.parseLong(version);
179       v = new VersionImpl(versionNumber);
180     } catch (NumberFormatException e) {
181       return badRequest("Invalid version number format");
182     }
183 
184     final String trimmedTarget = StringUtils.trimToNull(target);
185     if (null == trimmedTarget) {
186       return badRequest("Invalid target store ID: " + trimmedTarget);
187     } else if (!tsamjp.datastoreExists(trimmedTarget)) {
188       return badRequest("Target store " + trimmedTarget + " not found");
189     }
190 
191     try {
192       Job j = tsamjp.moveByIdAndVersion(v, mpid, trimmedTarget);
193       return ok(new JaxbJob(j));
194     } catch (Exception e) {
195       return handleException(e);
196     }
197   }
198 
199   @POST
200   @Path("moveByDate")
201   @Produces(MediaType.TEXT_XML)
202   @RestQuery(name = "moveByDate", description = "Move all snapshots between two dates.",
203       restParameters = {
204           @RestParameter(
205               name = "start",
206               isRequired = true,
207               type = RestParameter.Type.STRING,
208               defaultValue = "",
209               description = "The start date, in the format yyyy-MM-dd'T'HH:mm:ss'Z'."),
210           @RestParameter(
211               name = "end",
212               isRequired = true,
213               type = RestParameter.Type.STRING,
214               defaultValue = "",
215               description = "The end date, in the format yyyy-MM-dd'T'HH:mm:ss'Z'."),
216           @RestParameter(
217               name = "target",
218               isRequired = true,
219               type = RestParameter.Type.STRING,
220               defaultValue = "",
221               description = "The target storage to move the mediapackage to.")},
222       responses = {
223           @RestResponse(
224               description = "The job created to move the snapshots.",
225               responseCode = SC_OK),
226           @RestResponse(
227               description = "Invalid parameters, and the job was not created",
228               responseCode = SC_BAD_REQUEST),
229           @RestResponse(
230               description = "There has been an internal error, and the job was not created",
231               responseCode = SC_INTERNAL_SERVER_ERROR)},
232       returnDescription = "The Job created")
233   public Response moveByDate(
234       @FormParam("start") final String startString,
235       @FormParam("end") final String endString,
236       @FormParam("target") final String target
237   ) {
238     DateFormat sdf = new SimpleDateFormat(SDF_FORMAT);
239     Date start;
240     Date end;
241     try {
242       start = sdf.parse(startString);
243       end = sdf.parse(endString);
244     } catch (ParseException e) {
245       return badRequest("Invalid start or end date format");
246     }
247 
248     if (end.before(start)) {
249       return badRequest("Start date " + start + " must be before end date " + end);
250     }
251 
252     final String trimmedTarget = StringUtils.trimToNull(target);
253     if (null == trimmedTarget) {
254       return badRequest("Invalid target store ID: " + trimmedTarget);
255     } else if (!tsamjp.datastoreExists(trimmedTarget)) {
256       return badRequest("Target store " + trimmedTarget + " not found");
257     }
258 
259     try {
260       Job j = tsamjp.moveByDate(start, end, trimmedTarget);
261       return ok(new JaxbJob(j));
262     } catch (Exception e) {
263       return handleException(e);
264     }
265   }
266 
267   @POST
268   @Path("moveByIdAndDate")
269   @Produces(MediaType.TEXT_XML)
270   @RestQuery(
271       name = "moveByIdAndDate",
272       description = "Move all snapshots for a given mediapackage taken between two dates.",
273       restParameters = {
274           @RestParameter(
275               name = "id",
276               isRequired = true,
277               type = RestParameter.Type.STRING,
278               defaultValue = "",
279               description = "The mediapackage ID to move."),
280           @RestParameter(
281               name = "start",
282               isRequired = true,
283               type = RestParameter.Type.STRING,
284               defaultValue = "",
285               description = "The start date, in the format yyyy-MM-dd'T'HH:mm:ss'Z'."),
286           @RestParameter(
287               name = "end",
288               isRequired = true,
289               type = RestParameter.Type.STRING,
290               defaultValue = "",
291               description = "The end date, in the format yyyy-MM-dd'T'HH:mm:ss'Z'."),
292           @RestParameter(
293               name = "target",
294               isRequired = true,
295               type = RestParameter.Type.STRING,
296               defaultValue = "",
297               description = "The target storage to move the mediapackage to.")},
298       responses = {
299           @RestResponse(
300               description = "The job created to move the snapshots.",
301               responseCode = SC_OK),
302           @RestResponse(
303               description = "Invalid parameters, and the job was not created",
304               responseCode = SC_BAD_REQUEST),
305           @RestResponse(
306               description = "There has been an internal error, and the job was not created",
307               responseCode = SC_INTERNAL_SERVER_ERROR)},
308       returnDescription = "The Job created")
309   public Response moveByIdAndDate(
310       @FormParam("id") final String id,
311       @FormParam("start") final String startString,
312       @FormParam("end") final String endString,
313       @FormParam("target") final String target
314   ) {
315     DateFormat sdf = new SimpleDateFormat(SDF_FORMAT);
316     final String mpid = StringUtils.trimToNull(id);
317     if (null == mpid) {
318       return badRequest("Invalid mediapackage ID: " + mpid);
319     }
320 
321     Date start;
322     Date end;
323     try {
324       start = sdf.parse(startString);
325       end = sdf.parse(endString);
326     } catch (ParseException e) {
327       return badRequest("Invalid start or end date format");
328     }
329 
330     if (end.before(start)) {
331       return badRequest("Start date " + start + " must be before end date " + end);
332     }
333 
334     final String trimmedTarget = StringUtils.trimToNull(target);
335     if (null == trimmedTarget) {
336       return badRequest("Invalid target store ID: " + trimmedTarget);
337     } else if (!tsamjp.datastoreExists(trimmedTarget)) {
338       return badRequest("Target store " + trimmedTarget + " not found");
339     }
340 
341     try {
342       Job j = tsamjp.moveByIdAndDate(mpid, start, end, trimmedTarget);
343       return ok(new JaxbJob(j));
344     } catch (Exception e) {
345       return handleException(e);
346     }
347   }
348 }