001package de.deepamehta.plugins.images; 002 003import java.util.logging.Logger; 004 005import javax.ws.rs.Consumes; 006import javax.ws.rs.GET; 007import javax.ws.rs.POST; 008import javax.ws.rs.Path; 009import javax.ws.rs.Produces; 010import javax.ws.rs.QueryParam; 011import javax.ws.rs.WebApplicationException; 012import javax.ws.rs.core.Context; 013import javax.ws.rs.core.MediaType; 014import javax.ws.rs.core.UriInfo; 015 016import de.deepamehta.core.osgi.PluginActivator; 017import de.deepamehta.core.service.Inject; 018import de.deepamehta.core.service.ResultList; 019import de.deepamehta.core.service.Transactional; 020import de.deepamehta.plugins.files.DirectoryListing.FileItem; 021import de.deepamehta.plugins.files.StoredFile; 022import de.deepamehta.plugins.files.UploadedFile; 023import de.deepamehta.plugins.files.service.FilesService; 024import java.util.ArrayList; 025 026/** 027 * CKEditor compatible resources for image upload and browse. 028 */ 029@Path("/images") 030public class ImagePlugin extends PluginActivator { 031 032 private static Logger log = Logger.getLogger(ImagePlugin.class.getName()); 033 034 public static final String FILEREPO_BASE_URI_NAME = "filerepo"; 035 public static final String FILEREPO_IMAGES_SUBFOLDER = "images"; 036 public static final String FILE_REPOSITORY_PATH = System.getProperty("dm4.filerepo.path"); 037 038 @Inject 039 private FilesService fileService; 040 041 @Context 042 private UriInfo uriInfo; 043 044 /** 045 * CKEditor image upload integration, see 046 * CKEDITOR.config.filebrowserImageBrowseUrl 047 * 048 * @param image 049 * Uploaded file resource. 050 * @param func 051 * CKEDITOR function number to call. 052 * @param cookie 053 * Actual cookie. 054 * @return JavaScript snippet that calls CKEditor 055 */ 056 @POST 057 @Path("/upload") 058 @Consumes(MediaType.MULTIPART_FORM_DATA) 059 @Produces(MediaType.TEXT_HTML) 060 @Transactional 061 public String upload(// 062 UploadedFile image,// 063 @QueryParam("CKEditorFuncNum") Long func) { 064 log.info("upload image " + image.getName()); 065 try { 066 StoredFile file = fileService.storeFile(image, FILEREPO_IMAGES_SUBFOLDER); 067 String path = "/" + FILEREPO_IMAGES_SUBFOLDER + "/" + file.getFileName(); 068 return getCkEditorCall(func, getRepoUri(path), ""); 069 } catch (Exception e) { 070 return getCkEditorCall(func, "", e.getMessage()); 071 } 072 } 073 074 /** 075 * Returns a set of all image source URLs. 076 * 077 * @return all image sources 078 */ 079 @GET 080 @Path("/browse") 081 @Produces(MediaType.APPLICATION_JSON) 082 public ResultList<Image> browse() { 083 log.info("browse images"); 084 try { 085 ArrayList<Image> images = new ArrayList<Image>(); 086 for (FileItem image : fileService.getDirectoryListing(FILEREPO_IMAGES_SUBFOLDER).getFileItems()) { 087 String src = getRepoUri(image.getPath()); 088 images.add(new Image(src, image.getMediaType(), 089 image.getSize(), image.getName())); 090 } 091 return new ResultList<Image>(images.size(), images); 092 } catch (WebApplicationException e) { // fileService.getDirectoryListing 093 throw e; // do not wrap it again 094 } catch (Exception e) { 095 throw new WebApplicationException(e); 096 } 097 } 098 099 /** 100 * Returns a in-line JavaScript snippet that calls the parent CKEditor. 101 * 102 * @param func 103 * CKEDITOR function number. 104 * @param uri 105 * Resource URI. 106 * @param error 107 * Error message. 108 * @return JavaScript snippet that calls CKEditor 109 */ 110 private String getCkEditorCall(Long func, String uri, String error) { 111 return "<script type='text/javascript'>" + "window.parent.CKEDITOR.tools.callFunction(" 112 + func + ", '" + uri + "', '" + error + "')" + "</script>"; 113 } 114 115 /** 116 * Returns an external accessible file repository URI of path based on 117 * actual request URI. 118 * 119 * @param path 120 * Relative path of a file repository resource. 121 * @return URI 122 */ 123 private String getRepoUri(String path) { 124 // ### in some cases the uriInfo (Context) may be empty! 125 return uriInfo.getBaseUri() + FILEREPO_BASE_URI_NAME + path; 126 } 127}