001package runwar.undertow;
002
003import java.io.File;
004import java.io.IOException;
005import java.net.MalformedURLException;
006import java.util.HashMap;
007import java.util.HashSet;
008
009import runwar.logging.Logger;
010import io.undertow.server.handlers.resource.FileResource;
011import io.undertow.server.handlers.resource.FileResourceManager;
012import io.undertow.server.handlers.resource.Resource;
013
014public class MappedResourceManager extends FileResourceManager {
015
016    private static Logger log = Logger.getLogger("RunwarLogger");
017    private HashMap<String, File> aliasMap = new HashMap<String, File>();
018    private File[] cfmlDirsFiles;
019    private File WEBINF = null;
020
021    public MappedResourceManager(File base, long transferMinSize, String cfmlDirList) {
022        super(base, transferMinSize);
023        processMappings(cfmlDirList);
024    }
025
026    public MappedResourceManager(File base, long transferMinSize, String cfmlDirList, File file) {
027        this(base, transferMinSize, cfmlDirList);
028        WEBINF = file;
029        if (!WEBINF.exists()) {
030            throw new RuntimeException("The specified WEB-INF does not exist: " + WEBINF.getAbsolutePath());
031        }
032    }
033
034    private void processMappings(String cfmlDirList) {
035        HashSet<File> dirs = new HashSet<File>();
036        String[] dirList = cfmlDirList.split(",");
037        for (int x = 0; x < dirList.length; x++) {
038            File dir;
039            String[] splitted = dirList[x].split("=");
040            if (splitted.length == 1) {
041                dir = new File(dirList[x].trim());
042                dirs.add(dir);
043            } else {
044                String virtual = splitted[0].trim();
045                virtual = virtual.startsWith("/") ? virtual : "/" + virtual;
046                virtual = virtual.endsWith("/") ? virtual.substring(0, virtual.length()-1) : virtual;
047                dir = new File(splitted[1].trim());
048                aliasMap.put(virtual, dir);
049            }
050            if (!dir.exists()) {
051                log.error("Does not exist, cannot serve content: " + dir.getAbsolutePath());
052            } else {
053                log.info("Serving content from " + dir.getAbsolutePath());
054            }
055        }
056        cfmlDirsFiles = dirs.toArray(new File[dirs.size()]);
057    };
058    
059    public Resource getResource(String path) {
060        // log.debug("* requested:" + path);
061        File reqFile = null;
062        try {
063            if (WEBINF != null && (path.startsWith("/WEB-INF") || path.startsWith("./WEB-INF"))) {
064                if (path.equals("/WEB-INF") || path.equals("./WEB-INF")) {
065                    reqFile = WEBINF;
066                }
067                reqFile = new File(WEBINF, path.replaceAll(".+WEB-INF", ""));
068            } else if (path.startsWith(WEBINF.getPath())) {
069                reqFile = new File(WEBINF, path.replace(WEBINF.getPath(), ""));
070            } else if (path.startsWith("/CFIDE")) {
071                reqFile = new File(WEBINF.getParentFile(), path);
072            } else if (!path.startsWith("/WEB-INF")) {
073                reqFile = new File(getBase(), path);
074                if (!reqFile.exists()) {
075                    reqFile = getAliasedFile(aliasMap, path);
076                }
077                if (reqFile != null) {
078                    for (int x = 0; x < cfmlDirsFiles.length; x++) {
079                        String absPath = cfmlDirsFiles[x].getCanonicalPath();
080                        reqFile = new File(cfmlDirsFiles[x], path.replace(absPath, ""));
081                        // log.debugf("checking:%s = %s",absPath,reqFile.getAbsolutePath());
082                        if (reqFile.exists()) {
083                            break;
084                        }
085                    }
086                }
087            }
088            if (reqFile != null && reqFile.exists()) {
089                // log.debugf("path mapped to:%s", reqFile.getAbsolutePath());
090                return new FileResource(reqFile, this, path);
091            } else {
092                // log.debugf("no mapped resoruce for:%s",path);
093                return super.getResource(path);
094            }
095        } catch (MalformedURLException e) {
096            log.error(e.getMessage());
097        } catch (IOException e) {
098            log.error(e.getMessage());
099        }
100        return null;
101    }
102
103    public static File getAliasedFile(HashMap<String, File> aliasMap, String path) {
104        String pathDir = path.startsWith("/") ? path : "/" + path;
105        File file = aliasMap.get(pathDir);
106        if(file != null) {
107            return new File(file.getPath());
108        }
109        while (pathDir.lastIndexOf('/') > 0) {
110            pathDir = pathDir.substring(0, pathDir.lastIndexOf('/'));
111            if (aliasMap.containsKey(pathDir)) {
112                file = new File(aliasMap.get(pathDir), path.replace(pathDir, ""));
113                if(file.getPath().indexOf('\\') > 0){
114                    file = new File(file.getPath().replace('/', '\\'));
115                }
116                return file;
117            }
118        }
119        return null;
120    }
121    
122    public HashMap<String, File> getAliasMap() {
123        return aliasMap;
124    }
125}