/*
 * $Revision: 220 $ $Date: 2007-07-16 19:32:15 +0900 $
 * Copyright (C) 2005 SUGIMOTO Ken-ichi
 * 作成日： 2004/4/4
 */

package feat2.config;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

/**
 * ClassLoaderでロードできるリソースファイルの位置を表現するためのクラス。
 */
public class ClassLoaderFileLocator implements FileLocator {

    private ClassLoaderFileLocator root;
    private ClassLoader ctx;
    private URI path;

    /**
     *
     * @param path
     * @param ctx
     * @throws URISyntaxException パスの形式に間違いがある
     * @throws IllegalArgumentException 引数がnull
     */
    public ClassLoaderFileLocator(String path, ClassLoader ctx) throws URISyntaxException, IllegalArgumentException {
        if ( path == null )
            throw new IllegalArgumentException("path:null");
        if ( ctx == null )
            throw new IllegalArgumentException("ctx:null");

        this.ctx = ctx;
        this.path = new URI(path);
        this.root = this;
    }

    private ClassLoaderFileLocator(URI path, ClassLoader ctx, ClassLoaderFileLocator root) {
        this.ctx = ctx;
        this.path = path;
        this.root = root;
    }

    public InputStream openInputStream() throws IOException {
        return ctx.getResourceAsStream(path.getPath());
    }

    public String getURL() {
        URL url = getURL_();
        if ( url == null )
            return null;
        else
            return url.toExternalForm();
    }

    private URL getURL_() {
        String name = path.getPath();
        return ctx.getResource(name);
    }

    public String getURIString() {
        return getURL();
    }

    public boolean exists() {
        return getURL_() != null;
    }

    public String getFilename() {
        String pathstr = path.getPath();

        // 最後が'/'だったらディレクトリ
        if ( pathstr.endsWith("/") ) {
            return null;
        }

        // 最後の'/'以降の名前がファイル名
        int slashIndex = pathstr.lastIndexOf('/');
        if ( slashIndex == -1 )
            return pathstr;
        else
            return pathstr.substring(slashIndex+1);
    }

    /**
     * このメソッドは常に0を返す。
     * @see FileLocator#getLastModified()
     */
    public long getLastModified() throws IOException {
        return 0L;
    }

    public FileLocator newLocation(String relativePath) throws IllegalArgumentException {
        if ( relativePath != null ) {
            if ( relativePath.startsWith("/") )
                throw new IllegalArgumentException("\""+relativePath+"\" '/'で始まるパスは指定できない");
            if ( relativePath.startsWith(".") )
                throw new IllegalArgumentException("\""+relativePath+"\" ディレクトリ名の先頭に'.'は使用できない");
            if ( relativePath.indexOf("..") > -1 )
                throw new IllegalArgumentException("\""+relativePath+"\" 上位のディレクトリは指定できない");

            //URI current = new URI(path.toExternalForm());
            URI newUri = path.resolve(relativePath);
            return new ClassLoaderFileLocator(newUri, ctx, root);
        }
        else
            return this;
    }

    public FileLocator rootLocation() {
        return root;
    }

    public String toString() {
        return path.getPath();
    }

    public boolean equals(Object o) {
        ClassLoaderFileLocator loc = (ClassLoaderFileLocator)o;
        boolean ret = path.getPath().equals(loc.path.getPath());
        if ( root != this )
            ret = ret && root.equals(loc.root);
        return ret;
    }
}
