/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nl.b3p.viewer.stripes;

import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.MimeUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.http.HttpServletResponse;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ErrorResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.action.StrictBinding;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.validation.Validate;
import nl.b3p.viewer.components.ComponentRegistry;
import nl.b3p.viewer.components.ViewerComponent;
import nl.b3p.web.stripes.ErrorMessageResolution;
import org.apache.commons.io.IOUtils;

/** 
 * ActionBean to get the resource of a (3rd party component).
 * The resource is in the same directory (or a child) as the component class.
 * @author Roy Braam
 * @author Meine Toonen
 */

@UrlBinding("/action/componentresource")
@StrictBinding
public class ComponentResourceActionBean implements ActionBean{
    private ActionBeanContext context;

    @Validate
    private String className;
    @Validate
    private String resource;
    
    public Resolution resource() throws IOException{
        if (className==null || getResource() == null){         
            return new ErrorMessageResolution("Both 'className' and 'resource' is required.");
        }
        ViewerComponent comp = ComponentRegistry.getInstance().getViewerComponent(className);
        String path = comp.getPath();
        path+=File.separator+getResource();
        
        final File file = new File(path);
        if (!file.canRead()){
            return new ErrorResolution(HttpServletResponse.SC_NOT_FOUND,"Resource not found");
        }
        //check if the file requested is in the path of the component
        String check = file.getCanonicalPath();        
        if (!check.startsWith(comp.getPath())){
            return new ErrorResolution(HttpServletResponse.SC_FORBIDDEN,"Not allowed to access file");
        }
        
        String contentType=getContentType(file);
        return new StreamingResolution(contentType) {
            @Override
            protected void stream(HttpServletResponse response) throws IOException {
                IOUtils.copy(new FileInputStream(file), response.getOutputStream());                
            }
        };
    }
    private String getContentType(File f){
        MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
        MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.ExtensionMimeDetector");
        MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.OpendesktopMimeDetector");
        Collection mimeTypes = MimeUtil.getMimeTypes(f);
        if (!mimeTypes.isEmpty()) {
            Object[] mimeArray = mimeTypes.toArray();
            MimeType mime = (MimeType) mimeArray[0];
            return mime.toString();
        } else {
            return "plain/text";
        }
    }
    //<editor-fold defaultstate="collapsed" desc="Getters/setters">
    public ActionBeanContext getContext() {
        return context;
    }

    public void setContext(ActionBeanContext context) {
        this.context = context;
    }
    
    public String getClassName() {
        return className;
    }
    
    public void setClassName(String className) {
        this.className = className;
    }

    public String getResource() {
        return resource;
    }

    public void setResource(String resource) {
        this.resource = resource;
    }
    
}
//</editor-fold>

@@ -197,16 +197,162 @@
 meUtil;%0A
+import eu.medsea.mimeutil.MimeUtil2;%0Aimport eu.medsea.mimeutil.detector.MimeDetector;%0Aimport eu.medsea.mimeutil.detector.OpendesktopMimeDetector;%0A
 import j
@@ -1118,17 +1118,16 @@
 ls;%0A%0A/**
- 
 %0A * Acti
@@ -1556,20 +1556,16 @@
 source;%0A
-    
 %0A    pub
@@ -1664,25 +1664,16 @@
 = null)%7B
-         
 %0A       
@@ -1946,24 +1946,16 @@
 urce();%0A
-        
 %0A       
@@ -2241,24 +2241,16 @@
 lPath();
-        
 %0A       
@@ -2403,24 +2403,16 @@
       %7D%0A
-        
 %0A       
@@ -2698,32 +2698,16 @@
 ream());
-                
 %0A       
@@ -2773,16 +2773,354 @@
 ile f)%7B%0A
+        if(MimeUtil.getMimeDetector(%22eu.medsea.mimeutil.detector.MagicMimeMimeDetector%22) == null) %7B%0A            // First one will probably not fail (3rd one does when there is no mime.cache at /usr/share/mime), so only register when MagicMimeMimeDetector is not yet registered thus preventing multiple registrations of the detectors.%0A    
         
@@ -3195,32 +3195,36 @@
 MimeDetector%22);%0A
+    
         MimeUtil
@@ -3299,32 +3299,36 @@
 ctor%22);%0A        
+   
+ 
 MimeUtil.registe
@@ -3389,32 +3389,42 @@
 MimeDetector%22);%0A
+        %7D%0A
         Collecti
@@ -3938,36 +3938,32 @@
  context;%0A    %7D%0A
-    
 %0A    public Stri
@@ -4014,20 +4014,16 @@
 ;%0A    %7D%0A
-    
 %0A    pub
@@ -4260,20 +4260,16 @@
 ;%0A    %7D%0A
-    
 %0A%7D%0A//%3C/e

Check to prevent multiple registrations of mimedetectors. Fixes #291