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.util;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.OutputStream;
022import java.nio.charset.Charset;
023import java.util.Properties;
024
025import org.apache.commons.vfs2.FileContent;
026import org.apache.commons.vfs2.FileObject;
027import org.apache.commons.vfs2.FileSystemException;
028import org.apache.commons.vfs2.impl.DecoratedFileObject;
029import org.apache.commons.vfs2.provider.AbstractFileObject;
030
031/**
032 * Utility methods for {@link FileObject}.
033 */
034public final class FileObjectUtils {
035
036    /**
037     * Null-safe call to {@link FileObject#exists()}.
038     *
039     * @param fileObject the file object to test, may be null.
040     * @return false if {@code fileObject} is null, otherwise, see {@link FileObject#exists()}.
041     * @throws FileSystemException On error determining if this file exists.
042     * @since 2.4
043     */
044    public static boolean exists(final FileObject fileObject) throws FileSystemException {
045        return fileObject != null && fileObject.exists();
046    }
047
048    /**
049     * Gets access to the base object even if decorated.
050     *
051     * @param fileObject The FileObject.
052     * @return The decorated FileObject or null.
053     * @throws FileSystemException if an error occurs.
054     */
055    public static AbstractFileObject getAbstractFileObject(final FileObject fileObject) throws FileSystemException {
056        Object searchObject = fileObject;
057        while (searchObject instanceof DecoratedFileObject) {
058            searchObject = ((DecoratedFileObject) searchObject).getDecoratedFileObject();
059        }
060        if (searchObject instanceof AbstractFileObject) {
061            return (AbstractFileObject) searchObject;
062        }
063        if (searchObject == null) {
064            return null;
065        }
066
067        throw new FileSystemException("vfs.util/find-abstract-file-object.error",
068                fileObject.getClass().getName());
069    }
070
071    /**
072     * Gets the content of a file object, as a byte array.
073     *
074     * @param file Gets the contents of this file object.
075     * @return The content as a byte array.
076     * @throws IOException if the file content cannot be accessed.
077     * @since 2.6.0
078     */
079    public static byte[] getContentAsByteArray(final FileObject file) throws IOException {
080        synchronized (file.getFileSystem()) {
081            try (FileContent content = file.getContent()) {
082                return content.getByteArray();
083            }
084        }
085    }
086
087    /**
088     * Gets the content of a file as a String.
089     *
090     * @param file Gets the contents of this file object.
091     * @param charset The file character set, may be null.
092     * @return The content as a string.
093     * @throws IOException if the file content cannot be accessed.
094     * @since 2.4
095     */
096    public static String getContentAsString(final FileObject file, final Charset charset) throws IOException {
097        synchronized (file.getFileSystem()) {
098            try (FileContent content = file.getContent()) {
099                return content.getString(charset);
100            }
101        }
102    }
103
104    /**
105     * Returns the content of a file as a String.
106     *
107     * @param file Gets the contents of this file object.
108     * @param charset The file character set, may be null.
109     * @return The content as a string.
110     * @throws IOException if the file content cannot be accessed.
111     * @since 2.4
112     */
113    public static String getContentAsString(final FileObject file, final String charset) throws IOException {
114        synchronized (file.getFileSystem()) {
115            try (FileContent content = file.getContent()) {
116                return content.getString(charset);
117            }
118        }
119    }
120
121    /**
122     * Checks if the given FileObject is instance of given class argument.
123     *
124     * @param fileObject The FileObject.
125     * @param wantedClass The Class to check.
126     * @return true if fileObject is an instance of the specified Class.
127     * @throws FileSystemException if an error occurs.
128     */
129    public static boolean isInstanceOf(final FileObject fileObject, final Class<?> wantedClass)
130        throws FileSystemException {
131        Object searchObject = fileObject;
132        while (searchObject instanceof DecoratedFileObject) {
133            if (wantedClass.isInstance(searchObject)) {
134                return true;
135            }
136
137            searchObject = ((DecoratedFileObject) searchObject).getDecoratedFileObject();
138        }
139
140        return wantedClass.isInstance(searchObject);
141    }
142
143    /**
144     * Reads the given file into a new {@link Properties}.
145     *
146     * @param fileObject the file to read
147     * @return a new {@link Properties}.
148     * @throws IOException On error getting this file's content.
149     * @throws FileSystemException On error getting this file's content.
150     * @throws IOException On error getting this file's content.
151     * @since 2.4
152     */
153    public static Properties readProperties(final FileObject fileObject) throws FileSystemException, IOException {
154        return readProperties(fileObject, new Properties());
155    }
156
157    /**
158     * Reads the given file into a new given {@link Properties}.
159     *
160     * @param fileObject the file to read
161     * @param properties the destination
162     * @return a new {@link Properties}.
163     * @throws FileSystemException On error getting this file's content.
164     * @throws IOException On error getting this file's content.
165     * @since 2.4
166     */
167    public static Properties readProperties(final FileObject fileObject, final Properties properties)
168        throws FileSystemException, IOException {
169        if (fileObject == null) {
170            return properties;
171        }
172        try (InputStream inputStream = fileObject.getContent().getInputStream()) {
173            properties.load(inputStream);
174        }
175        return properties;
176    }
177
178    /**
179     * Writes the content from a source file to a destination file.
180     *
181     * @param srcFile The source FileObject.
182     * @param destFile The target FileObject
183     * @throws IOException If an error occurs copying the file.
184     * @see FileContent#write(FileObject)
185     * @since 2.6.0
186     */
187    public static void writeContent(final FileObject srcFile, final FileObject destFile) throws IOException {
188        try (FileContent content = srcFile.getContent()) {
189            content.write(destFile);
190        }
191    }
192
193    /**
194     * Writes the content of a file to an OutputStream.
195     *
196     * @param file The FileObject to write.
197     * @param output The OutputStream to write to.
198     * @throws IOException if an error occurs writing the file.
199     * @see FileContent#write(OutputStream)
200     * @since 2.6.0
201     */
202    public static void writeContent(final FileObject file, final OutputStream output) throws IOException {
203        try (FileContent content = file.getContent()) {
204            content.write(output);
205        }
206    }
207
208    private FileObjectUtils() {
209        // noop
210    }
211}