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     */
017    package org.apache.commons.vfs2.provider.url;
018    
019    import java.io.FileNotFoundException;
020    import java.io.InputStream;
021    import java.net.HttpURLConnection;
022    import java.net.MalformedURLException;
023    import java.net.URL;
024    import java.net.URLConnection;
025    
026    import org.apache.commons.httpclient.URIException;
027    import org.apache.commons.vfs2.FileName;
028    import org.apache.commons.vfs2.FileObject;
029    import org.apache.commons.vfs2.FileSystemException;
030    import org.apache.commons.vfs2.FileType;
031    import org.apache.commons.vfs2.provider.AbstractFileName;
032    import org.apache.commons.vfs2.provider.AbstractFileObject;
033    import org.apache.commons.vfs2.provider.URLFileName;
034    
035    /**
036     * A {@link FileObject} implementation backed by a {@link URL}.
037     *
038     * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
039     * @todo Implement set lastModified and get/set attribute
040     * @todo Implement getOutputStream()
041     */
042    public class UrlFileObject extends AbstractFileObject implements FileObject
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                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    }