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