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}