Java tutorial
package se.nrm.mediaserver.resteasy; import com.drew.imaging.ImageMetadataReader; import com.drew.imaging.ImageProcessingException; import com.drew.metadata.Metadata; import java.io.File; import java.io.IOException; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.xml.bind.DatatypeConverter; import org.apache.log4j.Logger; import org.apache.tika.Tika; import org.jboss.resteasy.annotations.providers.multipart.MultipartForm; import org.json.simple.JSONObject; import se.nrm.mediaserver.media3.domain.Attachment; import se.nrm.mediaserver.media3.domain.Image; import se.nrm.mediaserver.media3.domain.Lic; import se.nrm.mediaserver.media3.domain.Link; import se.nrm.mediaserver.media3.domain.Media; import se.nrm.mediaserver.media3.domain.MediaText; import se.nrm.mediaserver.media3.domain.Stream; import se.nrm.mediaserver.resteasy.util.AggregateTags; import se.nrm.mediaserver.resteasy.util.CheckSumFactory; import se.nrm.mediaserver.resteasy.util.ExifExtraction; import se.nrm.mediaserver.resteasy.util.FileUploadForm; import se.nrm.mediaserver.resteasy.util.FileUploadJSON; import se.nrm.mediaserver.resteasy.util.LinkUploadForm; import se.nrm.mediaserver.resteasy.util.SingleLinkUploadForm; import se.nrm.mediaserver.restful.util.FileSystemWriter; import se.nrm.mediaserver.restful.util.JNDIFetchRemote; import se.nrm.mediaserver.restful.util.PathHelper; import se.nrm.mediaserver.restful.util.Writeable; import se.nrm.mediaserver.service.MediaService; import se.nrm.mediaserver.util.AdminProperties; import se.nrm.mediaserver.util.MediaFactory; import se.nrm.mediaserver.util.MediaURL; import se.nrm.mediaserver.util.TagHelper; /** * * @author ingimar */ @Path("/media") @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public class MediaResourceForm { private final MediaService bean = JNDIFetchRemote.outreach(); private final static Logger logger = Logger.getLogger(MediaResourceForm.class); private int dynamic_status = Response.Status.OK.getStatusCode(); private final int STATUS_CONFLICT = Response.Status.CONFLICT.getStatusCode(); private final int STATUS_INTERNAL_SERVER_ERROR = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); public MediaResourceForm() { } /** * ajax cannot call the @DELETE-directly. * * @param mediaUUID */ @GET @Path("/ajax/delete/all/{mediaUUID}") public void ajaxDelete(@PathParam("mediaUUID") String mediaUUID) { boolean deleted = this.deleteAll(mediaUUID); } @DELETE @Path("/delete/all/{mediaUUID}") @Consumes(MediaType.TEXT_PLAIN) public boolean deleteAll(@PathParam("mediaUUID") String mediaUUID) { boolean successfulDeletion = false; try { successfulDeletion = this.deleteMediaMetadata(mediaUUID); } catch (Exception e) { logger.debug("unsuccessful deletion of [".concat(mediaUUID).concat("]")); } if (successfulDeletion) { successfulDeletion = this.deleteFileFromFS(mediaUUID); } return successfulDeletion; } @DELETE @Path("/delete/media/filesystem/{mediaUUID}") @Consumes(MediaType.TEXT_PLAIN) public boolean deleteFileFromFS(@PathParam("mediaUUID") String mediaUUID) { String filePath = PathHelper.getDynamicPathToFile(mediaUUID, ""); String fileName = filePath.concat(mediaUUID); File file = new File(fileName); boolean isFileDeleted = file.delete(); return isFileDeleted; } @DELETE @Path("/delete/media/metadata/{mediaUUID}") @Consumes(MediaType.TEXT_PLAIN) public boolean deleteMediaMetadata(@PathParam("mediaUUID") String mediaUUID) { boolean deleted; deleted = bean.deleteMediaMetadata(mediaUUID); return deleted; } @PUT @Path("/upload-file") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_PLAIN) public Response updateFile(@MultipartForm FileUploadForm form) { String mediaUUID = form.getMediaUUID(); Media media = (Media) bean.get(mediaUUID); String alt = form.getAlt(), access = form.getAccess(), fileName = form.getFileName(); String legend = form.getLegend(), owner = form.getOwner(), tags = form.getTags(); String comment = form.getComment(); String displayOrder = form.getDisplayOrder(); final String licenceType = form.licenceType(); if (alt != null && !alt.equals("")) { media.setAlt(alt); } if (access != null && !access.equals("")) { media.setVisibility(access); } if (fileName != null && !fileName.equals("")) { media.setFilename(fileName); } if (legend != null && !legend.equals("")) { String language = form.getLanguage(); MediaText mediatext = new MediaText(legend, language, media, comment); // kan frenklas . iner:2014-08-26 updateMediatext(mediatext, media); } if (licenceType != null && !licenceType.equals("")) { updateLicense(licenceType, media); } if (owner != null && !owner.equals("")) { media.setOwner(owner); } if (tags != null && !tags.equals("")) { media.setTaggar(tags); } if (media instanceof Image) { Boolean export = form.isExport(); if (export != null) { Image image = (Image) media; image.setIsExported(export); media = image; } } else if (media instanceof Stream) { String startTime = form.getStartTime(), endTime = form.getEndTime(); Stream stream = (Stream) media; if (startTime != null && !startTime.equals("")) { stream.setStartTime(Integer.parseInt(startTime)); } if (endTime != null && !endTime.equals("")) { stream.setStartTime(Integer.parseInt(endTime)); } media = stream; } else if (media instanceof Attachment) { } writeToDatabase(media); int sortOrder = Integer.parseInt(displayOrder); String taxonUUID = media.getFirstDetermination().getTagValue(); DeterminationResourceFetch up = new DeterminationResourceFetch(); up.changeSortOrder(taxonUUID, mediaUUID, sortOrder); return null; } /** * @param form * @return a unique UUID that identifies the file in the database&FS * @throws java.io.IOException */ @POST @Path("/upload-file") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.TEXT_PLAIN) public Response createNewFile(@MultipartForm FileUploadForm form) throws IOException { String mimeType = "unknown", hashChecksum = "unknown"; final String NOT_APPLICABLE = "N/A"; String displayOrder = form.getDisplayOrder(); final byte[] fileData = form.getFileData(); if (null == fileData || fileData.length == 0) { String msg = "attribute 'fileData' is null or empty \n"; logger.info(msg); return Response.status(STATUS_INTERNAL_SERVER_ERROR).entity(msg).build(); } String fileUUID = generateRandomUUID(); String uploadedFileLocation = getAbsolutePathToFile(fileUUID); if (uploadedFileLocation.isEmpty()) { String msg = "could not create a directory for the mediafile \n"; logger.info(msg); return Response.status(STATUS_INTERNAL_SERVER_ERROR).entity(msg).build(); } writeToFile(form, uploadedFileLocation); Tika tika = new Tika(); mimeType = tika.detect(fileData); Media media = null; switch (mimeType) { case "image/tiff": logger.info("mediatype - image/tiff"); case "image/png": case "image/jpeg": case "image/gif": { boolean exportImage = form.isExport(); String exifJSON = NOT_APPLICABLE; boolean isExif = AdminProperties.getIsExif(); if (isExif) { try { exifJSON = extractExif(uploadedFileLocation, exifJSON); } catch (ImageProcessingException ex) { logger.info(ex); } } media = MediaFactory.createImage2(exportImage, exifJSON); break; } case "video/quicktime": case "video/mp4": { String startTime = form.getStartTime(), endTime = form.getEndTime(); media = MediaFactory.createVideo(checkStartEndTime(startTime), checkStartEndTime(endTime)); break; } case "audio/mpeg": case "audio/vorbis": case "audio/ogg": { String startTime = form.getStartTime(), endTime = form.getEndTime(); media = MediaFactory.createSound(checkStartEndTime(startTime), checkStartEndTime(endTime)); break; } case "application/pdf": { media = MediaFactory.createAttachement(); break; } } if (null == media) { String msg = String.format("Mimetype [ %s ] is not supported \n", mimeType); logger.info("[media is null]: " + msg); return Response.status(STATUS_INTERNAL_SERVER_ERROR).entity(msg).build(); } hashChecksum = CheckSumFactory.createMD5ChecksumFromBytestream(fileData); MediaURL url = new MediaURL(); String pathToMedia = url.getPathToStream(); media.setUuid(fileUUID); media.setOwner(form.getOwner()); media.setFilename(form.getFileName()); media.setMimetype(mimeType); media.setVisibility(form.getAccess()); media.setHash(hashChecksum); media.setMediaURL(pathToMedia.concat(fileUUID)); AggregateTags aggr = new AggregateTags(); String tagsConcatenated = aggr.aggregateTags(form); if (tagsConcatenated != null || !tagsConcatenated.isEmpty()) { addingTags(media, tagsConcatenated); } if (form.getLegend() == null || form.getLegend().isEmpty()) { form.setLegend(NOT_APPLICABLE); } if (form.getLegend() != null && !form.getLegend().isEmpty()) { MediaText mediaText; String comment = form.getComment(); if (comment != null) { mediaText = new MediaText(form.getLegend(), form.getLanguage(), media, comment); } else { mediaText = new MediaText(form.getLegend(), form.getLanguage(), media); } media.addMediaText(mediaText); } final String licenceType = form.licenceType(); if (licenceType != null) { Lic license = fetchFromDB(licenceType); media.getLics().add(license); } writeToDatabase(media); String responseOutput = fileUUID; Response build = Response.status(dynamic_status).header("mediaUUID", responseOutput).entity(responseOutput) .build(); return build; } /** * Sortorder-updated. * * @param form * @return */ @POST @Path("/upload-coupling") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response createNewCoupling(@MultipartForm SingleLinkUploadForm form) { Integer sortOrder = null; String taxonUUID = form.getTaxonUUID(); String mediaUUID = form.getMediaUUID(); if (null == form.getSortOrder()) { sortOrder = 999; } else { sortOrder = Integer.parseInt(form.getSortOrder()); } Link link = Link.newInstanceWithSortOrder(form.getTypeOfSystem(), taxonUUID, form.getNameOfSystem(), form.getSystemURL(), mediaUUID, sortOrder); Response resp = createNewCoupling(link); DeterminationResourceFetch up = new DeterminationResourceFetch(); up.changeSortOrder(taxonUUID, mediaUUID, sortOrder); int st = resp.getStatus(); return Response.status(st).build(); } @POST @Path("/upload-batch-coupling") @Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.TEXT_PLAIN) public Response coupling(@MultipartForm LinkUploadForm form) { return this.createNewCouplingParams(form); } /** * Skyttner used this when importing media from NF to here: curl -i -X POST * -H 'Content-Type: application/json' -d * '{"typeOfSystem":"NF_TAXON","taxonUUID":"taxon-nr","nameOfSystem":"NF_SYSTEM","systemURL":"NF_URL","mediaList":["e4a3cf7d-add4-4949-a6ce-0f5594e61970","ebb45da5-bd25-45af-8a04-3470d38523d1"]}' * http://172.16.23.62:8080/MediaServerResteasy/media/postJSONWithLIsta * * Should be an atomic transaction, either it succeeds or it fails. better * return-message : 200 would suffice * * sortOrder : Defaults settings with counter, starting from 1. * * @param form * @return */ @POST @Path("/postJSONWithLIsta") @Consumes({ MediaType.APPLICATION_JSON }) @Produces(MediaType.TEXT_PLAIN) public Response createNewCouplingParams(@MultipartForm LinkUploadForm form) { String taxonUUID = form.getTaxonUUID(); Link link = new Link(form.getTypeOfSystem(), taxonUUID, form.getNameOfSystem(), form.getSystemURL()); String[] mediaList = form.getMediaList(); int counter = 1; for (String mediaUUID : mediaList) { link.setSortOrder(counter); link.setMediaUUID(mediaUUID); Response resp = createNewCoupling(link); dynamic_status = resp.getStatus(); counter++; } return Response.status(dynamic_status).build(); } @POST @Path("/post") public Response createNewCoupling(Link link) { if (link == null) { return Response.status(STATUS_CONFLICT).build(); } try { bean.save(link); } catch (Exception ex) { logger.info("" + ex); return Response.status(STATUS_CONFLICT).build(); } return Response.status(dynamic_status).entity(link).build(); } /** * 2014-10-23 : temporary fix. Created for migration of NRM-data, problem * with UTF-8 * * @param form * @return * @throws java.io.IOException */ @POST @Path("/upload-file/base64") @Consumes("application/json") // @Interceptors(ContentTypeSetterPreProcessorInterceptor.class) public Response createNewMediaFile_JSON(FileUploadJSON form) throws IOException { String mimeType = "unknown", hashChecksum = "unknown"; final byte[] fileData = DatatypeConverter.parseBase64Binary(form.getFileDataBase64()); if (null == fileData || fileData.length == 0) { String msg = "attribute 'fileData' is null or empty \n"; logger.info(msg); return Response.status(STATUS_INTERNAL_SERVER_ERROR).entity(msg).build(); } String fileUUID = generateRandomUUID(); String uploadedFileLocation = getAbsolutePathToFile(fileUUID); writeBase64ToFile(fileData, uploadedFileLocation); Tika tika = new Tika(); mimeType = tika.detect(fileData); Media media = null; switch (mimeType) { case "image/tiff": logger.info("mediatype - image/tiff"); case "image/png": case "image/jpeg": case "image/gif": { boolean exportImage = form.getExport(); String exifJSON = "N/A"; boolean isExif = AdminProperties.getIsExif(); if (isExif) { try { exifJSON = extractExif(uploadedFileLocation, exifJSON); } catch (ImageProcessingException ex) { logger.info(ex); } } media = MediaFactory.createImage2(exportImage, exifJSON); break; // boolean exportImage = form.getExport(); // media = MediaFactory.createImage(exportImage); // break; } case "video/quicktime": case "video/mp4": { String startTime = form.getStartTime(), endTime = form.getEndTime(); media = MediaFactory.createVideo(checkStartEndTime(startTime), checkStartEndTime(endTime)); break; } case "audio/mpeg": case "audio/vorbis": case "audio/ogg": { String startTime = form.getStartTime(), endTime = form.getEndTime(); media = MediaFactory.createSound(checkStartEndTime(startTime), checkStartEndTime(endTime)); break; } case "application/pdf": { media = MediaFactory.createAttachement(); break; } } if (null == media) { String msg = String.format("Mimetype [ %s ] is not supported \n", mimeType); logger.info("media is null: "); return Response.status(STATUS_INTERNAL_SERVER_ERROR).entity(msg).build(); } hashChecksum = CheckSumFactory.createMD5ChecksumFromBytestream(fileData); MediaURL url = new MediaURL(); String pathToMedia = url.getPathToStream(); media.setUuid(fileUUID); media.setOwner(form.getOwner()); media.setFilename(form.getFileName()); media.setMimetype(mimeType); media.setVisibility(form.getAccess()); media.setHash(hashChecksum); media.setMediaURL(pathToMedia.concat(fileUUID)); if (form.getTags() != null) { String tags = form.getTags(); if (!tags.equals("")) { addingTags(media, tags); } } if (form.getLegend() == null || form.getLegend().equals("")) { form.setLegend("N/A"); } if (form.getLegend() != null && !form.getLegend().equals("")) { MediaText mediaText; String comment = form.getComment(); if (comment != null) { mediaText = new MediaText(form.getLegend(), form.getLanguage(), media, comment); } else { mediaText = new MediaText(form.getLegend(), form.getLanguage(), media); } media.addMediaText(mediaText); } final String licenceType = form.getLicenseType(); if (licenceType != null) { Lic license = fetchFromDB(licenceType); media.getLics().add(license); } writeToDatabase(media); String responseOutput = fileUUID; Response build = Response.status(dynamic_status).header("mediaUUID", responseOutput).entity(responseOutput) .build(); return build; } private String extractExif(String location, String exifJSON) throws ImageProcessingException, IOException { Metadata metadata = ImageMetadataReader.readMetadata(new File(location)); JSONObject jsonObject = packageEXIF_IN_JSON(metadata, true); exifJSON = jsonObject.toJSONString(); final String prefix = "<![CDATA["; final String suffix = "]]>"; exifJSON = prefix.concat(exifJSON).concat(suffix); return exifJSON; } /** * @TODO JUnit gives java.util.ConcurrentModificationException - must use * iterator and it.remove(); to handle this. * * @param updatedMediaText * @param media * @return */ protected Media updateMediatext(final MediaText updatedMediaText, final Media media) { final String locale = updatedMediaText.getLang(); final Set<MediaText> mediatextList = media.getTexts(); String comment = ""; try { Iterator<MediaText> it = mediatextList.iterator(); while (it.hasNext()) { MediaText mediaText = it.next(); comment = mediaText.getComment().trim(); if (mediaText.getLang().equals(locale)) { bean.delete(mediaText); it.remove(); } } if (!comment.isEmpty()) { if (comment.equals(updatedMediaText.getComment().trim())) { updatedMediaText.setComment(comment); } } media.addMediaText(updatedMediaText); } catch (ConcurrentModificationException ex) { logger.info(ex); throw new ConcurrentModificationException("probz with MEDIA_TEXT", ex); } return media; } /** * Only one Licensetype for a media-file. That Constraint is in this method * * @param licenceType * @param media * @return */ protected Media updateLicense(final String licenceType, Media media) { Lic updateLicense = fetchFromDB(licenceType); media.getLics().clear(); media.getLics().add(updateLicense); return media; } private List<String> addingTags(Media media, String inTags) { TagHelper helper = new TagHelper(); List<String> tags = helper.addingTags(media, inTags); return tags; } /** * @TODO Add some regexp later, change String to timedate * * @param time * @return */ private int checkStartEndTime(String time) { if (null == time || time.equals("")) { time = "0"; } return Integer.parseInt(time); } private String generateRandomUUID() { final String uuIdFilename = UUID.randomUUID().toString(); return uuIdFilename; } private String getAbsolutePathToFile(String uuid) { String basePath = AdminProperties.getImagesFilePath(); return PathHelper.getEmptyOrAbsolutePathToFile(uuid, basePath); } private void writeToFile(FileUploadForm form, String location) { //@TODO boolean isSuffix = AdminProperties.getIsSuffix(); Writeable writer = new FileSystemWriter(); writer.writeBytesTo(form.getFileData(), location); } private void writeBase64ToFile(byte[] parseBase64Binary, String location) { Writeable writer = new FileSystemWriter(); writer.writeBytesTo(parseBase64Binary, location); } private <T> void writeToDatabase(T media) { bean.save(media); } private Lic fetchFromDB(String abbrevation) { String trimmedAbbrevation = abbrevation.trim(); Lic license = (Lic) bean.getLicenseByAbbr(trimmedAbbrevation); return license; } /** * Removes 'tags' with key= 'Unknown' * * @param metadata * @param isFiltered * @return */ private JSONObject packageEXIF_IN_JSON(Metadata metadata, boolean isFiltered) { ExifExtraction extract = new ExifExtraction(); return extract.packageEXIF_IN_JSON(metadata, isFiltered); } @GET @Path("/testing/{name}") @Produces(MediaType.TEXT_PLAIN) public String getTest(@PathParam("name") String name) { logger.info("first info and the debug ?"); logger.debug("DEBUG - testing log4j - : Incoming -> : " + name); String toUpperCase = name.toUpperCase(); logger.debug("debug - testing log4j - : Outgoing -> : " + toUpperCase); return toUpperCase; } }