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.local;
018
019import org.apache.commons.vfs2.FileName;
020import org.apache.commons.vfs2.FileSystemException;
021import org.apache.commons.vfs2.FileType;
022import org.apache.commons.vfs2.provider.AbstractFileName;
023import org.apache.commons.vfs2.provider.UriParser;
024
025/**
026 * A local file URI.
027 */
028public class LocalFileName extends AbstractFileName {
029    // URI Characters that are possible in local filenames, but must be escaped
030    // for proper URI handling.
031    //
032    // How reserved URI chars were selected:
033    //
034    // URIs can contain :, /, ?, #, @
035    // See http://download.oracle.com/javase/6/docs/api/java/net/URI.html
036    // http://tools.ietf.org/html/rfc3986#section-2.2
037    //
038    // Since : and / occur before the path, only chars after path are escaped (i.e., # and ?)
039    // ? is a reserved filesystem character for Windows and Unix, so can't be part of a filename.
040    // Therefore only # is a reserved char in a URI as part of the path that can be in the filename.
041    private static final char[] RESERVED_URI_CHARS = { '#' };
042
043    private final String rootFile;
044
045    protected LocalFileName(final String scheme, final String rootFile, final String path, final FileType type) {
046        super(scheme, path, type);
047        this.rootFile = rootFile;
048    }
049
050    /**
051     * Returns the root file for this file.
052     *
053     * @return The root file name.
054     */
055    public String getRootFile() {
056        return rootFile;
057    }
058
059    /**
060     * Factory method for creating name instances.
061     *
062     * @param path The file path.
063     * @param type The file type.
064     * @return The FileName.
065     */
066    @Override
067    public FileName createName(final String path, final FileType type) {
068        return new LocalFileName(getScheme(), rootFile, path, type);
069    }
070
071    /**
072     * Returns the absolute URI of the file.
073     *
074     * @return The absolute URI of the file.
075     */
076    @Override
077    public String getURI() {
078        String uri = super.getURI();
079
080        if (uri != null && uri.length() > 0) {
081            try {
082                // VFS-325: Handle URI special characters in filename
083                // Decode the base uri and re-encode with URI special characters
084                uri = UriParser.decode(uri);
085
086                uri = UriParser.encode(uri, RESERVED_URI_CHARS);
087            } catch (final FileSystemException e) {
088                // Default to base uri value
089            }
090        }
091
092        return uri;
093    }
094
095    /**
096     * returns a "friendly path", this is a path without a password.
097     *
098     * @return The "friendly" URI.
099     */
100    @Override
101    public String getFriendlyURI() {
102        String uri = super.getFriendlyURI();
103
104        if (uri != null && uri.length() > 0) {
105            try {
106                // VFS-325: Handle URI special characters in filename
107                // Decode the base uri and re-encode with URI special characters
108                uri = UriParser.decode(uri);
109
110                uri = UriParser.encode(uri, RESERVED_URI_CHARS);
111            } catch (final FileSystemException e) {
112                // Default to base uri value
113            }
114        }
115
116        return uri;
117    }
118
119    /**
120     * Returns the decoded URI of the file.
121     *
122     * @return the FileName as a URI.
123     */
124    @Override
125    public String toString() {
126        try {
127            return UriParser.decode(super.getURI());
128        } catch (final FileSystemException e) {
129            return super.getURI();
130        }
131    }
132
133    /**
134     * Builds the root URI for this file name.
135     */
136    @Override
137    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
138        buffer.append(getScheme());
139        buffer.append("://");
140        buffer.append(rootFile);
141    }
142}