001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.provider.url;
018
019import java.io.FileNotFoundException;
020import java.io.InputStream;
021import java.net.HttpURLConnection;
022import java.net.MalformedURLException;
023import java.net.URL;
024import java.net.URLConnection;
025
026import org.apache.commons.httpclient.URIException;
027import org.apache.commons.vfs2.FileName;
028import org.apache.commons.vfs2.FileObject;
029import org.apache.commons.vfs2.FileSystemException;
030import org.apache.commons.vfs2.FileType;
031import org.apache.commons.vfs2.provider.AbstractFileName;
032import org.apache.commons.vfs2.provider.AbstractFileObject;
033import org.apache.commons.vfs2.provider.URLFileName;
034
035/**
036 * A {@link FileObject} implementation backed by a {@link URL}.
037 *
038 * @todo Implement set lastModified and get/set attribute
039 * @todo Implement getOutputStream()
040 */
041public class UrlFileObject extends AbstractFileObject<UrlFileSystem>
042{
043    private URL url;
044
045    protected UrlFileObject(final UrlFileSystem fs,
046                            final AbstractFileName fileName)
047    {
048        super(fileName, fs);
049    }
050
051    /**
052     * Attaches this file object to its file resource.  This method is called
053     * before any of the doBlah() or onBlah() methods.  Sub-classes can use
054     * this method to perform lazy initialisation.
055     */
056    @Override
057    protected void doAttach() throws Exception
058    {
059        if (url == null)
060        {
061            // url = new URL(getName().getURI());
062            url = createURL(getName());
063        }
064    }
065
066    protected URL createURL(final FileName name) throws MalformedURLException, FileSystemException, URIException
067    {
068        if (name instanceof URLFileName)
069        {
070            final URLFileName urlName = (URLFileName) getName();
071
072            // TODO: charset
073            return new URL(urlName.getURIEncoded(null));
074        }
075        return new URL(getName().getURI());
076    }
077
078    /**
079     * Determines the type of the file.
080     */
081    @Override
082    protected FileType doGetType() throws Exception
083    {
084        try
085        {
086            // Attempt to connect & check status
087            final URLConnection conn = url.openConnection();
088            final InputStream in = conn.getInputStream();
089            try
090            {
091                if (conn instanceof HttpURLConnection)
092                {
093                    final int status = ((HttpURLConnection) conn).getResponseCode();
094                    // 200 is good, maybe add more later...
095                    if (HttpURLConnection.HTTP_OK != status)
096                    {
097                        return FileType.IMAGINARY;
098                    }
099                }
100
101                return FileType.FILE;
102            }
103            finally
104            {
105                in.close();
106            }
107        }
108        catch (final FileNotFoundException e)
109        {
110            return FileType.IMAGINARY;
111        }
112    }
113
114    /**
115     * Returns the size of the file content (in bytes).
116     */
117    @Override
118    protected long doGetContentSize() throws Exception
119    {
120        final URLConnection conn = url.openConnection();
121        final InputStream in = conn.getInputStream();
122        try
123        {
124            return conn.getContentLength();
125        }
126        finally
127        {
128            in.close();
129        }
130    }
131
132    /**
133     * Returns the last modified time of this file.
134     */
135    @Override
136    protected long doGetLastModifiedTime()
137        throws Exception
138    {
139        final URLConnection conn = url.openConnection();
140        final InputStream in = conn.getInputStream();
141        try
142        {
143            return conn.getLastModified();
144        }
145        finally
146        {
147            in.close();
148        }
149    }
150
151    /**
152     * Lists the children of the file.
153     */
154    @Override
155    protected String[] doListChildren() throws Exception
156    {
157        throw new FileSystemException("Not implemented.");
158    }
159
160    /**
161     * Creates an input stream to read the file content from.
162     */
163    @Override
164    protected InputStream doGetInputStream() throws Exception
165    {
166        return url.openStream();
167    }
168}