/** * Licensed to The Apereo Foundation under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * * The Apereo Foundation licenses this file to you under the Educational * Community License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License * at: * * http://opensource.org/licenses/ecl2.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * */ package org.opencastproject.smil.endpoint; import org.opencastproject.mediapackage.MediaPackage; import org.opencastproject.mediapackage.MediaPackageElementParser; import org.opencastproject.mediapackage.MediaPackageException; import org.opencastproject.mediapackage.MediaPackageParser; import org.opencastproject.mediapackage.Track; import org.opencastproject.smil.api.SmilException; import org.opencastproject.smil.api.SmilResponse; import org.opencastproject.smil.api.SmilService; import org.opencastproject.util.doc.rest.RestParameter; import org.opencastproject.util.doc.rest.RestQuery; import org.opencastproject.util.doc.rest.RestResponse; import org.opencastproject.util.doc.rest.RestService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; /** * Implement {@link SmilService} as REST Endpoint. */ @Path("/") @RestService(name = "smil", title = "SmilService Rest Endpoint", abstractText = "SmilRestService provide other services to create and modify Smil objects.", notes = {"All paths above are relative to the REST endpoint base (something like http://your.server/smil)"}) public class SmilServiceRest { /** * Logger */ private static final Logger logger = LoggerFactory.getLogger(SmilServiceRest.class); /** * SmilService to interact with */ private SmilService smilService; @POST @Path("create") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "create", description = "Create new SMIL. Add some MediaPackage metadata.", restParameters = { @RestParameter(name = "mediaPackage", description = "MediaPackage for metadata.", isRequired = false, type = RestParameter.Type.TEXT)}, returnDescription = "Returns new SmilResponse with SMIL document inside.", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Create new SMIL successfull"), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "Given mediaPackage is not valid") }) public Response createNewSmil(@FormParam("mediaPackage") String mediaPackage) { SmilResponse smilResponse = null; try { if (mediaPackage != null && !mediaPackage.isEmpty()) { MediaPackage mp = MediaPackageParser.getFromXml(mediaPackage); smilResponse = smilService.createNewSmil(mp); } else { smilResponse = smilService.createNewSmil(); } return Response.ok(smilResponse).build(); } catch (MediaPackageException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("MediaPackage not valid.").build(); } } @POST @Path("addPar") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "addPar", description = "Add an parallel element to SMIL (into SMIL body or an element with given parentId).", restParameters = { @RestParameter(name = "smil", description = "SMIL document where to add a par-element.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "parentId", description = "An element Id, were to add new parallel.", isRequired = false, type = RestParameter.Type.STRING)}, returnDescription = "Returns SmilResponse with a parallel element inside " + "(the new par will be returned as response entity).", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Add par to SMIL successfull."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document not valid."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document doesn't contain an element with given parentId.") }) public Response addParallel(@FormParam("smil") String smil, @FormParam("parentId") String parentId) { SmilResponse smilResponse = null; try { smilResponse = smilService.fromXml(smil); } catch (SmilException ex) { return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document invalid.").build(); } try { if (parentId != null && !parentId.isEmpty()) { smilResponse = smilService.addParallel(smilResponse.getSmil(), parentId); } else { smilResponse = smilService.addParallel(smilResponse.getSmil()); } return Response.ok(smilResponse).build(); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document doesn't contain an element with given parentId.").build(); } } @POST @Path("addSeq") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "addSeq", description = "Add an sequence element to SMIL (into SMIL body or an element with given parentId).", restParameters = { @RestParameter(name = "smil", description = "SMIL document where to add a seq-element.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "parentId", description = "An element Id, were to add new sequence.", isRequired = false, type = RestParameter.Type.STRING)}, returnDescription = "Returns SmilResponse with a sequence element inside " + "(the new seq will be returned as response entity).", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Add seq to SMIL successfull"), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document not valid"), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document doesn't contain an element with given parentId") }) public Response addSequence(@FormParam("smil") String smil, @FormParam("parentId") String parentId) { SmilResponse smilResponse = null; try { smilResponse = smilService.fromXml(smil); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document invalid.").build(); } try { if (parentId != null && !parentId.isEmpty()) { smilResponse = smilService.addSequence(smilResponse.getSmil(), parentId); } else { smilResponse = smilService.addSequence(smilResponse.getSmil()); } return Response.ok(smilResponse).build(); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document doesn't contain an element with given parentId.").build(); } } @POST @Path("addClip") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "addClip", description = "Add new media element based on given Track information and start / duration parameters. " + "ParentId specifies where to put the new media element.", restParameters = { @RestParameter(name = "smil", description = "SMIL document where to add new media element.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "parentId", description = "An element Id, were to add new media.", isRequired = false, type = RestParameter.Type.STRING), @RestParameter(name = "track", description = "Track (MediaPackageElement) to add as media element. " + "Some information like Track source and flavor will be stored in ParamGroup (in SMIL Head) " + "and referenced by paramGroup media element attribute.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "start", description = "Track start position in milliseconds.", isRequired = true, type = RestParameter.Type.INTEGER), @RestParameter(name = "duration", description = "Clip duration in milliseconds (should be positive).", isRequired = true, type = RestParameter.Type.INTEGER)}, returnDescription = "Returns new Smil with an media element inside " + "(the new media and metadata elements will be returned as response entities).", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Add media element to SMIL successfull."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document not valid."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "Track not valid."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document doesn't contain an element with given parentId."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "Start plus duration is bigger than Track length.") }) public Response addClip(@FormParam("smil") String smil, @FormParam("parentId") String parentId, @FormParam("track") String track, @FormParam("start") long start, @FormParam("duration") long duration) { SmilResponse smilResponse = null; Track trackObj = null; try { smilResponse = smilService.fromXml(smil); trackObj = (Track) MediaPackageElementParser.getFromXml(track); } catch (SmilException ex) { return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document invalid.").build(); } catch (MediaPackageException ex) { return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("Track is not valid.").build(); } try { smilResponse = smilService.addClip(smilResponse.getSmil(), parentId, trackObj, start, duration); return Response.ok(smilResponse).build(); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document doesn't contain an element with given parentId.").build(); } } @POST @Path("addClips") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "addClips", description = "Add new media elements based on given Tracks information and start / duration parameters. " + "ParentId specifies where to put the new media.", restParameters = { @RestParameter(name = "smil", description = "SMIL document where to add new media elements.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "parentId", description = "An element Id, were to add new media. ", isRequired = false, type = RestParameter.Type.STRING), @RestParameter(name = "tracks", description = "Tracks (MediaPackageElements) to add as media elements." + "Some information like Track source and flavor will be stored in ParamGroup (in SMIL Head) " + "and referenced by paramGroup media element attribute.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "start", description = "Track start position in milliseconds. " + "The start position will be applied to each media element.", isRequired = true, type = RestParameter.Type.INTEGER), @RestParameter(name = "duration", description = "Clip duration in milliseconds (should be positive). " + "The duration will be applied to each media element.", isRequired = true, type = RestParameter.Type.INTEGER)}, returnDescription = "Returns new Smil with new media elements inside " + "(the new media and metadata elements will be returned as response entities).", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Add media elements to SMIL successfull."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document not valid."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "Tracks are not valid."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document doesn't contain an element with given parentId."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "Start plus duration is bigger than Track length.") }) public Response addClips(@FormParam("smil") String smil, @FormParam("parentId") String parentId, @FormParam("tracks") String tracks, @FormParam("start") long start, @FormParam("duration") long duration) { SmilResponse smilResponse = null; List<Track> tracksList = null; try { smilResponse = smilService.fromXml(smil); tracksList = (List<Track>) MediaPackageElementParser.getArrayFromXml(tracks); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document invalid.").build(); } catch (MediaPackageException ex) { logger.error(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("Tracks are not valid.").build(); } Track[] tracksArr = tracksList.toArray(new Track[tracksList.size()]); try { smilResponse = smilService.addClips(smilResponse.getSmil(), parentId, tracksArr, start, duration); return Response.ok(smilResponse).build(); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document doesn't contain an element with given parentId.").build(); } } @POST @Path("addMeta") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "addMeta", description = "Add a meta element to SMIL head.", restParameters = { @RestParameter(name = "smil", description = "SMIL document where to add an meta element.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "name", description = "Value of meta name attribute.", isRequired = true, type = RestParameter.Type.STRING), @RestParameter(name = "content", description = "Value of meta content attribute.", isRequired = true, type = RestParameter.Type.STRING)}, returnDescription = "Returns SmilResponse with a new meta element inside " + "(the new meta will be returned as response entity).", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Add par to SMIL successfull."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document not valid.") }) public Response addMeta(@FormParam("smil") String smil, @FormParam("name") String metaName, @FormParam("content") String metaContent) { SmilResponse smilResponse = null; try { smilResponse = smilService.fromXml(smil); } catch (SmilException ex) { return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document invalid.").build(); } smilResponse = smilService.addMeta(smilResponse.getSmil(), metaName, metaContent); return Response.ok(smilResponse).build(); } @POST @Path("remove") @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_XML}) @RestQuery(name = "remove", description = "Remove an element with given Id from SMIL.", restParameters = { @RestParameter(name = "smil", description = "SMIL document.", isRequired = true, type = RestParameter.Type.TEXT), @RestParameter(name = "elementId", description = "Id of element to remove.", isRequired = true, type = RestParameter.Type.STRING)}, returnDescription = "Returns SMIL document without an element with given Id " + "(if SMIL document contains an element with given Id, this will be returned as entity).", reponses = { @RestResponse(responseCode = HttpServletResponse.SC_OK, description = "Removing element from SMIL successfull."), @RestResponse(responseCode = HttpServletResponse.SC_BAD_REQUEST, description = "SMIL document not valid.") }) public Response removeSmilElement(@FormParam("smil") String smil, @FormParam("elementId") String elementId) { SmilResponse smilResponse = null; try { smilResponse = smilService.fromXml(smil); smilResponse = smilService.removeSmilElement(smilResponse.getSmil(), elementId); return Response.ok(smilResponse).build(); } catch (SmilException ex) { logger.info(ex.getMessage(), ex); return Response.status(HttpServletResponse.SC_BAD_REQUEST).entity("SMIL document invalid.").build(); } } /** * Set {@link SmilService}. * * @param smilService {@link SmilService} to set */ public void setSmilService(SmilService smilService) { this.smilService = smilService; } }