/*
 * $Id: URLFileLocator.java,v 1.4 2005/04/24 04:31:23 sugimotokenichi Exp $
 * Copyright (C) 2005 SUGIMOTO Ken-ichi
 * 作成日: 2005/04/03
 */
package feat.v1.config;

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

/**
 * URLを使って実装したFileLocator。
 * @author SUGIMOTO Ken-ichi
 */
public class URLFileLocator implements FileLocator {

    private URL path;
    private URLFileLocator root;

    /**
     *
     * @param path
     * @throws IllegalArgumentException 引数がbullのとき
     */
    public URLFileLocator(URL path) throws IllegalArgumentException {
        if ( path == null )
            throw new IllegalArgumentException("path:"+path);
        this.path = path;
        root = this;
    }

    URLFileLocator(URL path, URLFileLocator root) {
        this.path = path;
        this.root = root;
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#openInputStream()
     */
    public InputStream openInputStream() throws IOException {
        return path.openStream();
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#getURL()
     */
    public String getURL() throws MalformedURLException {
        return path.toExternalForm();
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#getURIString()
     */
    public String getURIString() {
        try {
            return new URI(path.toExternalForm()).toASCIIString();
        }
        catch (URISyntaxException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#exists()
     */
    public boolean exists() {
        try {
            URLConnection con = path.openConnection();
            con.connect();
            int len = con.getContentLength();
            return len > 0;
        }
        catch(IOException ex) {
            return false;
        }
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#getFilename()
     */
    public String getFilename() {
        return path.getFile();
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#getLastModified()
     */
    public long getLastModified() throws IOException {
        long ret = -1L;
        URLConnection con = path.openConnection();
        con.connect();
        ret = con.getLastModified();
        return ret;
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#newLocation(java.lang.String)
     */
    public FileLocator newLocation(String relativePath)
            throws IllegalArgumentException {

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

                URI current = new URI(path.toExternalForm());
                URI newUri = current.resolve(relativePath);
                return new URLFileLocator(newUri.toURL(), root);
            }
            catch (MalformedURLException ex) {
                ex.printStackTrace();
            }
            catch (URISyntaxException ex) {
                ex.printStackTrace();
            }
        }
        else
            return this;

        return null;
    }

    /* (非 Javadoc)
     * @see feat.v1.config.FileLocator#rootLocation()
     */
    public FileLocator rootLocation() {
        return root;
    }

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

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

}
