use of org.opencastproject.util.doc.rest.RestQuery in project opencast by opencast.
the class IngestRestService method addMediaPackage.
@POST
@Produces(MediaType.TEXT_XML)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("addMediaPackage/{wdID}")
@RestQuery(name = "addMediaPackage", description = "<p>Create and ingest media package from media tracks with additional Dublin Core metadata. It is " + "mandatory to set a title for the recording. This can be done with the 'title' form field or by supplying a DC " + "catalog with a title included. The identifier of the newly created media package will be taken from the " + "<em>identifier</em> field or the episode DublinCore catalog (deprecated<sup>*</sup>). If no identifier is " + "set, a newa randumm UUIDv4 will be generated. This endpoint is not meant to be used by capture agents for " + "scheduled recordings. It's primary use is for manual ingests with command line tools like curl.</p> " + "<p>Multiple tracks can be ingested by using multiple form fields. It's important, however, to always set the " + "flavor of the next media file <em>before</em> sending the media file itself.</p>" + "<b>(*)</b> The special treatment of the identifier field is deprecated any may be removed in future versions " + "without further notice in favor of a random UUID generation to ensure uniqueness of identifiers. " + "<h3>Example curl command:</h3>" + "<p>Ingest one video file:</p>" + "<p><pre>\n" + "curl -f -i --digest -u opencast_system_account:CHANGE_ME -H 'X-Requested-Auth: Digest' \\\n" + " http://localhost:8080/ingest/addMediaPackage/fast -F creator='John Doe' -F title='Test Recording' \\\n" + " -F 'flavor=presentation/source' -F 'BODY=@test-recording.mp4' \n" + "</pre></p>" + "<p>Ingest two video files:</p>" + "<p><pre>\n" + "curl -f -i --digest -u opencast_system_account:CHANGE_ME -H 'X-Requested-Auth: Digest' \\\n" + " http://localhost:8080/ingest/addMediaPackage/fast -F creator='John Doe' -F title='Test Recording' \\\n" + " -F 'flavor=presentation/source' -F 'BODY=@test-recording-vga.mp4' \\\n" + " -F 'flavor=presenter/source' -F 'BODY=@test-recording-camera.mp4' \n" + "</pre></p>", pathParameters = { @RestParameter(description = "Workflow definition id", isRequired = true, name = "wdID", type = RestParameter.Type.STRING) }, restParameters = { @RestParameter(description = "The kind of media track. This has to be specified prior to each media track", isRequired = true, name = "flavor", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "abstract", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "accessRights", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "available", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "contributor", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "coverage", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "created", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "creator", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "date", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "description", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "extent", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "format", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "identifier", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "isPartOf", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "isReferencedBy", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "isReplacedBy", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "language", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "license", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "publisher", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "relation", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "replaces", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "rights", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "rightsHolder", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "source", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "spatial", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "subject", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "temporal", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "title", type = RestParameter.Type.STRING), @RestParameter(description = "Episode metadata value", isRequired = false, name = "type", type = RestParameter.Type.STRING), @RestParameter(description = "URL of episode DublinCore Catalog", isRequired = false, name = "episodeDCCatalogUri", type = RestParameter.Type.STRING), @RestParameter(description = "Episode DublinCore Catalog", isRequired = false, name = "episodeDCCatalog", type = RestParameter.Type.STRING), @RestParameter(description = "URL of series DublinCore Catalog", isRequired = false, name = "seriesDCCatalogUri", type = RestParameter.Type.STRING), @RestParameter(description = "Series DublinCore Catalog", isRequired = false, name = "seriesDCCatalog", type = RestParameter.Type.STRING), @RestParameter(description = "URL of a media track file", isRequired = false, name = "mediaUri", type = RestParameter.Type.STRING) }, bodyParameter = @RestParameter(description = "The media track file", isRequired = true, name = "BODY", type = RestParameter.Type.FILE), reponses = { @RestResponse(description = "Ingest successfull. Returns workflow instance as XML", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "Ingest failed due to invalid requests.", responseCode = HttpServletResponse.SC_BAD_REQUEST), @RestResponse(description = "Ingest failed. Something went wrong internally. Please have a look at the log files", responseCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR) }, returnDescription = "")
public Response addMediaPackage(@Context HttpServletRequest request, @PathParam("wdID") String wdID) {
logger.trace("add mediapackage as multipart-form-data with workflow definition id: {}", wdID);
MediaPackageElementFlavor flavor = null;
try {
MediaPackage mp = ingestService.createMediaPackage();
DublinCoreCatalog dcc = null;
Map<String, String> workflowProperties = new HashMap<>();
int seriesDCCatalogNumber = 0;
int episodeDCCatalogNumber = 0;
boolean hasMedia = false;
if (ServletFileUpload.isMultipartContent(request)) {
for (FileItemIterator iter = new ServletFileUpload().getItemIterator(request); iter.hasNext(); ) {
FileItemStream item = iter.next();
if (item.isFormField()) {
String fieldName = item.getFieldName();
String value = Streams.asString(item.openStream(), "UTF-8");
logger.trace("form field {}: {}", fieldName, value);
/* Ignore empty fields */
if ("".equals(value)) {
continue;
}
/* “Remember” the flavor for the next media. */
if ("flavor".equals(fieldName)) {
flavor = MediaPackageElementFlavor.parseFlavor(value);
/* Fields for DC catalog */
} else if (dcterms.contains(fieldName)) {
if ("identifier".equals(fieldName)) {
/* Use the identifier for the mediapackage */
mp.setIdentifier(new IdImpl(value));
}
EName en = new EName(DublinCore.TERMS_NS_URI, fieldName);
if (dcc == null) {
dcc = dublinCoreService.newInstance();
}
dcc.add(en, value);
/* Episode metadata by URL */
} else if ("episodeDCCatalogUri".equals(fieldName)) {
try {
URI dcurl = new URI(value);
updateMediaPackageID(mp, dcurl);
ingestService.addCatalog(dcurl, MediaPackageElements.EPISODE, mp);
episodeDCCatalogNumber += 1;
} catch (java.net.URISyntaxException e) {
/* Parameter was not a valid URL: Return 400 Bad Request */
logger.warn(e.getMessage(), e);
return Response.serverError().status(Status.BAD_REQUEST).build();
}
/* Episode metadata DC catalog (XML) as string */
} else if ("episodeDCCatalog".equals(fieldName)) {
InputStream is = new ByteArrayInputStream(value.getBytes("UTF-8"));
updateMediaPackageID(mp, is);
is.reset();
String fileName = "episode" + episodeDCCatalogNumber + ".xml";
episodeDCCatalogNumber += 1;
ingestService.addCatalog(is, fileName, MediaPackageElements.EPISODE, mp);
/* Series by URL */
} else if ("seriesDCCatalogUri".equals(fieldName)) {
try {
URI dcurl = new URI(value);
ingestService.addCatalog(dcurl, MediaPackageElements.SERIES, mp);
} catch (java.net.URISyntaxException e) {
/* Parameter was not a valid URL: Return 400 Bad Request */
logger.warn(e.getMessage(), e);
return Response.serverError().status(Status.BAD_REQUEST).build();
}
/* Series DC catalog (XML) as string */
} else if ("seriesDCCatalog".equals(fieldName)) {
String fileName = "series" + seriesDCCatalogNumber + ".xml";
seriesDCCatalogNumber += 1;
InputStream is = new ByteArrayInputStream(value.getBytes("UTF-8"));
ingestService.addCatalog(is, fileName, MediaPackageElements.SERIES, mp);
/* Add media files by URL */
} else if ("mediaUri".equals(fieldName)) {
if (flavor == null) {
/* A flavor has to be specified in the request prior the media file */
return Response.serverError().status(Status.BAD_REQUEST).build();
}
URI mediaUrl;
try {
mediaUrl = new URI(value);
} catch (java.net.URISyntaxException e) {
/* Parameter was not a valid URL: Return 400 Bad Request */
logger.warn(e.getMessage(), e);
return Response.serverError().status(Status.BAD_REQUEST).build();
}
ingestService.addTrack(mediaUrl, flavor, mp);
hasMedia = true;
} else {
/* Tread everything else as workflow properties */
workflowProperties.put(fieldName, value);
}
/* Media files as request parameter */
} else {
if (flavor == null) {
/* A flavor has to be specified in the request prior the video file */
logger.debug("A flavor has to be specified in the request prior to the content BODY");
return Response.serverError().status(Status.BAD_REQUEST).build();
}
ingestService.addTrack(item.openStream(), item.getName(), flavor, mp);
hasMedia = true;
}
}
/* Check if we got any media. Fail if not. */
if (!hasMedia) {
logger.warn("Rejected ingest without actual media.");
return Response.serverError().status(Status.BAD_REQUEST).build();
}
/* Add episode mediapackage if metadata were send separately */
if (dcc != null) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
dcc.toXml(out, true);
InputStream in = new ByteArrayInputStream(out.toByteArray());
ingestService.addCatalog(in, "dublincore.xml", MediaPackageElements.EPISODE, mp);
/* Check if we have metadata for the episode */
} else if (episodeDCCatalogNumber == 0) {
logger.warn("Rejected ingest without episode metadata. At least provide a title.");
return Response.serverError().status(Status.BAD_REQUEST).build();
}
WorkflowInstance workflow = (wdID == null) ? ingestService.ingest(mp) : ingestService.ingest(mp, wdID, workflowProperties);
return Response.ok(workflow).build();
}
return Response.serverError().status(Status.BAD_REQUEST).build();
} catch (Exception e) {
logger.warn(e.getMessage(), e);
return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
}
}
use of org.opencastproject.util.doc.rest.RestQuery in project opencast by opencast.
the class WorkingFileRepositoryRestEndpoint method restPutURLEncoded.
@POST
@Produces(MediaType.TEXT_HTML)
@Path(WorkingFileRepository.MEDIAPACKAGE_PATH_PREFIX + "{mediaPackageID}/{mediaPackageElementID}/{filename}")
@RestQuery(name = "putWithFilename", description = "Store a file in working repository under ./mediaPackageID/mediaPackageElementID/filename", returnDescription = "The URL to access the stored file", pathParameters = { @RestParameter(name = "mediaPackageID", description = "the mediapackage identifier", isRequired = true, type = STRING), @RestParameter(name = "mediaPackageElementID", description = "the mediapackage element identifier", isRequired = true, type = STRING), @RestParameter(name = "filename", description = "the filename", isRequired = true, type = FILE) }, reponses = { @RestResponse(responseCode = SC_OK, description = "OK, file stored") })
public Response restPutURLEncoded(@Context HttpServletRequest request, @PathParam("mediaPackageID") String mediaPackageID, @PathParam("mediaPackageElementID") String mediaPackageElementID, @PathParam("filename") String filename, @FormParam("content") String content) throws Exception {
String encoding = request.getCharacterEncoding();
if (encoding == null)
encoding = "utf-8";
URI url = this.put(mediaPackageID, mediaPackageElementID, filename, IOUtils.toInputStream(content, encoding));
return Response.ok(url.toString()).build();
}
use of org.opencastproject.util.doc.rest.RestQuery in project opencast by opencast.
the class FileUploadRestService method getNewJob.
// </editor-fold>
@POST
@Produces(MediaType.TEXT_PLAIN)
@Path("newjob")
@RestQuery(name = "newjob", description = "Creates a new upload job and returns the jobs ID.", restParameters = { @RestParameter(description = "The name of the file that will be uploaded", isRequired = false, name = REQUESTFIELD_FILENAME, type = RestParameter.Type.STRING), @RestParameter(description = "The size of the file that will be uploaded", isRequired = false, name = REQUESTFIELD_FILESIZE, type = RestParameter.Type.STRING), @RestParameter(description = "The size of the chunks that will be uploaded", isRequired = false, name = REQUESTFIELD_CHUNKSIZE, type = RestParameter.Type.STRING), @RestParameter(description = "The flavor of this track", isRequired = false, name = REQUESTFIELD_FLAVOR, type = RestParameter.Type.STRING), @RestParameter(description = "The mediapackage the file should belong to", isRequired = false, name = REQUESTFIELD_MEDIAPACKAGE, type = RestParameter.Type.TEXT) }, reponses = { @RestResponse(description = "job was successfully created", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "upload service gave an error", responseCode = HttpServletResponse.SC_NO_CONTENT) }, returnDescription = "The ID of the newly created upload job")
public Response getNewJob(@FormParam(REQUESTFIELD_FILENAME) String filename, @FormParam(REQUESTFIELD_FILESIZE) long filesize, @FormParam(REQUESTFIELD_CHUNKSIZE) int chunksize, @FormParam(REQUESTFIELD_MEDIAPACKAGE) String mediapackage, @FormParam(REQUESTFIELD_FLAVOR) String flav) {
try {
if (StringUtils.isBlank(filename)) {
filename = "john.doe";
}
if (filesize < 1) {
filesize = -1;
}
if (chunksize < 1) {
chunksize = -1;
}
MediaPackage mp = null;
if (StringUtils.isNotBlank(mediapackage)) {
mp = factory.newMediaPackageBuilder().loadFromXml(mediapackage);
}
MediaPackageElementFlavor flavor = null;
if (StringUtils.isNotBlank(flav)) {
flavor = new MediaPackageElementFlavor(flav.split("/")[0], flav.split("/")[1]);
}
FileUploadJob job = uploadService.createJob(filename, filesize, chunksize, mp, flavor);
return Response.ok(job.getId()).build();
} catch (FileUploadException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.NO_CONTENT).entity(e.getMessage()).build();
} catch (Exception e) {
log.error(e.getMessage(), e);
return Response.serverError().entity(buildUnexpectedErrorMessage(e)).build();
}
}
use of org.opencastproject.util.doc.rest.RestQuery in project opencast by opencast.
the class FileUploadRestService method postPayload.
@POST
@Produces(MediaType.APPLICATION_XML)
@Path("job/{jobID}")
@RestQuery(name = "newjob", description = "Appends the next chunk of data to the file on the server.", pathParameters = { @RestParameter(description = "The ID of the upload job", isRequired = false, name = "jobID", type = RestParameter.Type.STRING) }, restParameters = { @RestParameter(description = "The number of the current chunk", isRequired = false, name = "chunknumber", type = RestParameter.Type.STRING), @RestParameter(description = "The payload", isRequired = false, name = "filedata", type = RestParameter.Type.FILE) }, reponses = { @RestResponse(description = "the chunk data was successfully appended to file on server", responseCode = HttpServletResponse.SC_OK), @RestResponse(description = "the upload job was not found", responseCode = HttpServletResponse.SC_NOT_FOUND), @RestResponse(description = "the request was malformed", responseCode = HttpServletResponse.SC_BAD_REQUEST) }, returnDescription = "The XML representation of the updated upload job")
public Response postPayload(@PathParam("jobID") String jobId, @Context HttpServletRequest request) {
try {
if (!ServletFileUpload.isMultipartContent(request)) {
// make sure request is "multipart/form-data"
throw new FileUploadException("Request is not of type multipart/form-data");
}
if (uploadService.hasJob(jobId)) {
// testing for existence of job here already so we can generate a 404 early
long chunkNum = 0;
FileUploadJob job = uploadService.getJob(jobId);
ServletFileUpload upload = new ServletFileUpload();
for (FileItemIterator iter = upload.getItemIterator(request); iter.hasNext(); ) {
FileItemStream item = iter.next();
if (item.isFormField()) {
String name = item.getFieldName();
if (REQUESTFIELD_CHUNKNUM.equalsIgnoreCase(name)) {
chunkNum = Long.parseLong(Streams.asString(item.openStream()));
}
} else if (REQUESTFIELD_DATA.equalsIgnoreCase(item.getFieldName())) {
uploadService.acceptChunk(job, chunkNum, item.openStream());
return Response.ok(job).build();
}
}
throw new FileUploadException("No payload!");
} else {
log.warn("Upload job not found: " + jobId);
return Response.status(Response.Status.NOT_FOUND).build();
}
} catch (FileUploadException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
log.error(e.getMessage(), e);
return Response.serverError().entity(buildUnexpectedErrorMessage(e)).build();
}
}
use of org.opencastproject.util.doc.rest.RestQuery in project opencast by opencast.
the class SeriesServiceRemoteImpl method getSeriesAsJson.
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("series.json")
@RestQuery(name = "listSeriesAsJson", description = "Returns the series matching the query parameters", returnDescription = "Returns the series search results as JSON", restParameters = { @RestParameter(name = "q", isRequired = false, description = "Free text search", type = STRING), @RestParameter(name = "edit", isRequired = false, description = "Whether this query should return only series that are editable", type = BOOLEAN), @RestParameter(name = "fuzzyMatch", isRequired = false, description = "Whether a partial match on series id is allowed, default is false", type = BOOLEAN), @RestParameter(name = "seriesId", isRequired = false, description = "The series identifier", type = STRING), @RestParameter(name = "seriesTitle", isRequired = false, description = "The series title", type = STRING), @RestParameter(name = "creator", isRequired = false, description = "The series creator", type = STRING), @RestParameter(name = "contributor", isRequired = false, description = "The series contributor", type = STRING), @RestParameter(name = "publisher", isRequired = false, description = "The series publisher", type = STRING), @RestParameter(name = "rightsholder", isRequired = false, description = "The series rights holder", type = STRING), @RestParameter(name = "createdfrom", isRequired = false, description = "Filter results by created from (yyyy-MM-dd'T'HH:mm:ss'Z')", type = STRING), @RestParameter(name = "createdto", isRequired = false, description = "Filter results by created to (yyyy-MM-dd'T'HH:mm:ss'Z')", type = STRING), @RestParameter(name = "language", isRequired = false, description = "The series language", type = STRING), @RestParameter(name = "license", isRequired = false, description = "The series license", type = STRING), @RestParameter(name = "subject", isRequired = false, description = "The series subject", type = STRING), @RestParameter(name = "abstract", isRequired = false, description = "The series abstract", type = STRING), @RestParameter(name = "description", isRequired = false, description = "The series description", type = STRING), @RestParameter(name = "sort", isRequired = false, description = "The sort order. May include any of the following: TITLE, SUBJECT, CREATOR, PUBLISHER, CONTRIBUTOR, ABSTRACT, DESCRIPTION, CREATED, AVAILABLE_FROM, AVAILABLE_TO, LANGUAGE, RIGHTS_HOLDER, SPATIAL, TEMPORAL, IS_PART_OF, REPLACES, TYPE, ACCESS, LICENCE. Add '_DESC' to reverse the sort order (e.g. TITLE_DESC).", type = STRING), @RestParameter(name = "startPage", isRequired = false, description = "The page offset", type = STRING), @RestParameter(name = "count", isRequired = false, description = "Results per page (max 100)", type = STRING) }, reponses = { @RestResponse(responseCode = SC_OK, description = "The access control list."), @RestResponse(responseCode = SC_UNAUTHORIZED, description = "If the current user is not authorized to perform this action") })
public // CHECKSTYLE:OFF
Response getSeriesAsJson(@QueryParam("q") String text, @QueryParam("seriesId") String seriesId, @QueryParam("edit") Boolean edit, @QueryParam("fuzzyMatch") Boolean fuzzyMatch, @QueryParam("seriesTitle") String seriesTitle, @QueryParam("creator") String creator, @QueryParam("contributor") String contributor, @QueryParam("publisher") String publisher, @QueryParam("rightsholder") String rightsHolder, @QueryParam("createdfrom") String createdFrom, @QueryParam("createdto") String createdTo, @QueryParam("language") String language, @QueryParam("license") String license, @QueryParam("subject") String subject, @QueryParam("abstract") String seriesAbstract, @QueryParam("description") String description, @QueryParam("sort") String sort, @QueryParam("startPage") String startPage, @QueryParam("count") String count) throws UnauthorizedException {
// CHECKSTYLE:ON
try {
SeriesQuery seriesQuery = getSeries(text, seriesId, edit, seriesTitle, creator, contributor, publisher, rightsHolder, createdFrom, createdTo, language, license, subject, seriesAbstract, description, sort, startPage, count, fuzzyMatch);
DublinCoreCatalogList result = getSeries(seriesQuery);
return Response.ok(result.getResultsAsJson()).build();
} catch (UnauthorizedException e) {
throw e;
} catch (Exception e) {
logger.warn("Could not perform search query: {}", e.getMessage());
}
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
Aggregations