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.FileSystemException;
029import org.apache.commons.vfs2.FileType;
030import org.apache.commons.vfs2.provider.AbstractFileName;
031import org.apache.commons.vfs2.provider.AbstractFileObject;
032import org.apache.commons.vfs2.provider.URLFileName;
033
034/**
035 * A {@link org.apache.commons.vfs2.FileObject FileObject}
036 * implementation backed by a {@link URL}.
037 * <p>
038 * TODO - Implement set lastModified and get/set attribute
039 * <p>
040 * TODO - Implement getOutputStream().
041 */
042public class UrlFileObject extends AbstractFileObject<UrlFileSystem>
043{
044    private URL url;
045
046    protected UrlFileObject(final UrlFileSystem fs,
047                            final AbstractFileName fileName)
048    {
049        super(fileName, fs);
050    }
051
052    /**
053     * Attaches this file object to its file resource.  This method is called
054     * before any of the doBlah() or onBlah() methods.  Sub-classes can use
055     * this method to perform lazy initialisation.
056     */
057    @Override
058    protected void doAttach() throws Exception
059    {
060        if (url == null)
061        {
062            // url = new URL(getName().getURI());
063            url = createURL(getName());
064        }
065    }
066
067    protected URL createURL(final FileName name) throws MalformedURLException, FileSystemException, URIException
068    {
069        if (name instanceof URLFileName)
070        {
071            final URLFileName urlName = (URLFileName) getName();
072
073            // TODO: charset
074            return new URL(urlName.getURIEncoded(null));
075        }
076        return new URL(getName().getURI());
077    }
078
079    /**
080     * Determines the type of the file.
081     */
082    @Override
083    protected FileType doGetType() throws Exception
084    {
085        try
086        {
087            // Attempt to connect & check status
088            final URLConnection conn = url.openConnection();
089            final InputStream in = conn.getInputStream();
090            try
091            {
092                if (conn instanceof HttpURLConnection)
093                {
094                    final int status = ((HttpURLConnection) conn).getResponseCode();
095                    // 200 is good, maybe add more later...
096                    if (HttpURLConnection.HTTP_OK != status)
097                    {
098                        return FileType.IMAGINARY;
099                    }
100                }
101
102                return FileType.FILE;
103            }
104            finally
105            {
106                in.close();
107            }
108        }
109        catch (final FileNotFoundException e)
110        {
111            return FileType.IMAGINARY;
112        }
113    }
114
115    /**
116     * Returns the size of the file content (in bytes).
117     */
118    @Override
119    protected long doGetContentSize() throws Exception
120    {
121        final URLConnection conn = url.openConnection();
122        final InputStream in = conn.getInputStream();
123        try
124        {
125            return conn.getContentLength();
126        }
127        finally
128        {
129            in.close();
130        }
131    }
132
133    /**
134     * Returns the last modified time of this file.
135     */
136    @Override
137    protected long doGetLastModifiedTime()
138        throws Exception
139    {
140        final URLConnection conn = url.openConnection();
141        final InputStream in = conn.getInputStream();
142        try
143        {
144            return conn.getLastModified();
145        }
146        finally
147        {
148            in.close();
149        }
150    }
151
152    /**
153     * Lists the children of the file.
154     */
155    @Override
156    protected String[] doListChildren() throws Exception
157    {
158        throw new FileSystemException("Not implemented.");
159    }
160
161    /**
162     * Creates an input stream to read the file content from.
163     */
164    @Override
165    protected InputStream doGetInputStream() throws Exception
166    {
167        return url.openStream();
168    }
169}