001/**
002 *
003 * Copyright the original author or authors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * 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.jivesoftware.smack.util;
018
019import java.io.BufferedReader;
020import java.io.File;
021import java.io.FileInputStream;
022import java.io.FileNotFoundException;
023import java.io.FileOutputStream;
024import java.io.FileReader;
025import java.io.FileWriter;
026import java.io.IOException;
027import java.io.InputStream;
028import java.io.InputStreamReader;
029import java.io.Reader;
030import java.net.MalformedURLException;
031import java.net.URI;
032import java.net.URL;
033import java.nio.charset.StandardCharsets;
034import java.util.ArrayList;
035import java.util.List;
036import java.util.Set;
037import java.util.logging.Level;
038import java.util.logging.Logger;
039
040public final class FileUtils {
041
042    private static final Logger LOGGER = Logger.getLogger(FileUtils.class.getName());
043
044    public static InputStream getStreamForClasspathFile(String path, ClassLoader loader) throws IOException {
045        // Get an array of class loaders to try loading the providers files from.
046        List<ClassLoader> classLoaders = getClassLoaders();
047        if (loader != null) {
048            classLoaders.add(0, loader);
049        }
050        for (ClassLoader classLoader : classLoaders) {
051            InputStream is = classLoader.getResourceAsStream(path);
052
053            if (is != null) {
054                return is;
055            }
056        }
057        throw new IOException("Unable to get '" + path + "' from classpath. Tried ClassLoaders:" + classLoaders);
058    }
059
060    public static InputStream getStreamForUri(URI uri, ClassLoader loader) throws IOException {
061        String protocol = uri.getScheme();
062        if (protocol.equals("classpath")) {
063            String path = uri.getSchemeSpecificPart();
064            return getStreamForClasspathFile(path, loader);
065        }
066
067        URL url = uri.toURL();
068        return url.openStream();
069    }
070
071    /**
072     * Returns default classloaders.
073     *
074     * @return a List of ClassLoader instances.
075     */
076    public static List<ClassLoader> getClassLoaders() {
077        ClassLoader[] classLoaders = new ClassLoader[2];
078        classLoaders[0] = FileUtils.class.getClassLoader();
079        classLoaders[1] = Thread.currentThread().getContextClassLoader();
080
081        // Clean up possible null values. Note that #getClassLoader may return a null value.
082        List<ClassLoader> loaders = new ArrayList<ClassLoader>(classLoaders.length);
083        for (ClassLoader classLoader : classLoaders) {
084            if (classLoader != null) {
085                loaders.add(classLoader);
086            }
087        }
088        return loaders;
089    }
090
091    public static boolean addLines(String uriString, Set<String> set) throws MalformedURLException, IOException {
092        URI uri = URI.create(uriString);
093        InputStream is = getStreamForUri(uri, null);
094        InputStreamReader sr = new InputStreamReader(is, StandardCharsets.UTF_8);
095        BufferedReader br = new BufferedReader(sr);
096        try {
097            String line;
098            while ((line = br.readLine()) != null) {
099                set.add(line);
100            }
101        }
102        finally {
103            br.close();
104        }
105        return true;
106    }
107
108    /**
109     * Reads the contents of a File.
110     *
111     * @param file TODO javadoc me please
112     * @return the content of file or null in case of an error
113     * @throws IOException if an I/O error occurred.
114     */
115    @SuppressWarnings("DefaultCharset")
116    public static String readFileOrThrow(File file) throws IOException {
117        try (Reader reader = new FileReader(file)) {
118            char[] buf = new char[8192];
119            int len;
120            StringBuilder s = new StringBuilder();
121            while ((len = reader.read(buf)) >= 0) {
122                s.append(buf, 0, len);
123            }
124            return s.toString();
125        }
126    }
127
128    public static String readFile(File file) {
129        try {
130            return readFileOrThrow(file);
131        } catch (FileNotFoundException e) {
132            LOGGER.log(Level.FINE, "readFile", e);
133        } catch (IOException e) {
134            LOGGER.log(Level.WARNING, "readFile", e);
135        }
136        return null;
137    }
138
139    @SuppressWarnings("DefaultCharset")
140    public static void writeFileOrThrow(File file, CharSequence content) throws IOException {
141        FileWriter writer = new FileWriter(file, false);
142        try {
143            writer.write(content.toString());
144        } finally {
145            writer.close();
146        }
147    }
148
149    public static boolean writeFile(File file, CharSequence content) {
150        try {
151            writeFileOrThrow(file, content);
152            return true;
153        }
154        catch (IOException e) {
155            LOGGER.log(Level.WARNING, "writeFile", e);
156            return false;
157        }
158    }
159
160    public static FileOutputStream prepareFileOutputStream(File file) throws IOException {
161        if (!file.exists()) {
162
163            // Create parent directory
164            File parent = file.getParentFile();
165            if (!parent.exists() && !parent.mkdirs()) {
166                throw new IOException("Cannot create directory " + parent.getAbsolutePath());
167            }
168
169            // Create file
170            if (!file.createNewFile()) {
171                throw new IOException("Cannot create file " + file.getAbsolutePath());
172            }
173        }
174
175        if (file.isDirectory()) {
176            throw new AssertionError("File " + file.getAbsolutePath() + " is not a file!");
177        }
178
179        return new FileOutputStream(file);
180    }
181
182    public static FileInputStream prepareFileInputStream(File file) throws IOException {
183        if (file.exists()) {
184            if (file.isFile()) {
185                return new FileInputStream(file);
186            } else {
187                throw new IOException("File " + file.getAbsolutePath() + " is not a file!");
188            }
189        } else {
190            throw new FileNotFoundException("File " + file.getAbsolutePath() + " not found.");
191        }
192    }
193
194    public static void maybeDeleteFileOrThrow(File file) throws IOException {
195        if (!file.exists()) {
196            return;
197        }
198
199        boolean successfullyDeleted = file.delete();
200        if (!successfullyDeleted) {
201            throw new IOException("Could not delete file " + file);
202        }
203    }
204
205    public static void maybeCreateFileWithParentDirectories(File file) throws IOException {
206        File parent = file.getParentFile();
207        if (!parent.exists() && !parent.mkdirs()) {
208            throw new IOException("Cannot create directory " + parent);
209        }
210
211        if (file.isFile()) {
212            return;
213        }
214
215        if (!file.exists()) {
216            if (file.createNewFile()) {
217                return;
218            }
219            throw new IOException("Cannot create file " + file);
220        }
221
222        if (file.isDirectory()) {
223            throw new IOException("File " + file + " exists, but is a directory.");
224        } else {
225            throw new IOException("File " + file + " exists, but is neither a file nor a directory");
226        }
227    }
228}