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.logging.log4j.core.util;
018
019 import java.io.File;
020 import java.io.IOException;
021 import java.io.UnsupportedEncodingException;
022 import java.net.MalformedURLException;
023 import java.net.URI;
024 import java.net.URISyntaxException;
025 import java.net.URL;
026 import java.net.URLDecoder;
027 import java.util.regex.Pattern;
028
029 import org.apache.logging.log4j.Logger;
030 import org.apache.logging.log4j.status.StatusLogger;
031
032 /**
033 * File utilities.
034 */
035 public final class FileUtils {
036
037 /** Constant for the file URL protocol.*/
038 private static final String PROTOCOL_FILE = "file";
039
040 private static final String JBOSS_FILE = "vfsfile";
041
042 private static final Logger LOGGER = StatusLogger.getLogger();
043 private static final Pattern WINDOWS_DIRECTORY_SEPARATOR = Pattern.compile("\\\\+");
044
045 private FileUtils() {
046 }
047
048 /**
049 * Tries to convert the specified URI to a file object. If this fails,
050 * <b>null</b> is returned.
051 *
052 * @param uri the URI
053 * @return the resulting file object
054 */
055 public static File fileFromUri(URI uri) {
056 // There MUST be a better way to do this. TODO Search other ASL projects...
057 if (uri == null
058 || (uri.getScheme() != null && (!PROTOCOL_FILE.equals(uri.getScheme()) && !JBOSS_FILE.equals(uri
059 .getScheme())))) {
060 return null;
061 }
062 if (uri.getScheme() == null) {
063 File file = new File(uri.toString());
064 if (file.exists()) {
065 return file;
066 }
067 try {
068 final String path = uri.getPath();
069 file = new File(path);
070 if (file.exists()) {
071 return file;
072 }
073 uri = new File(path).toURI();
074 } catch (final Exception ex) {
075 LOGGER.warn("Invalid URI {}", uri);
076 return null;
077 }
078 }
079 final String charsetName = Constants.UTF_8.name();
080 try {
081 String fileName = uri.toURL().getFile();
082 if (new File(fileName).exists()) { // LOG4J2-466
083 return new File(fileName); // allow files with '+' char in name
084 }
085 fileName = URLDecoder.decode(fileName, charsetName);
086 return new File(fileName);
087 } catch (final MalformedURLException ex) {
088 LOGGER.warn("Invalid URL {}", uri, ex);
089 } catch (final UnsupportedEncodingException uee) {
090 LOGGER.warn("Invalid encoding: {}", charsetName, uee);
091 }
092 return null;
093 }
094
095 public static boolean isFile(final URL url) {
096 return url != null && (url.getProtocol().equals(PROTOCOL_FILE) || url.getProtocol().equals(JBOSS_FILE));
097 }
098
099 /**
100 * Asserts that the given directory exists and creates it if necessary.
101 * @param dir the directory that shall exist
102 * @param createDirectoryIfNotExisting specifies if the directory shall be created if it does not exist.
103 * @throws java.io.IOException thrown if the directory could not be created.
104 */
105 public static void mkdir(final File dir, final boolean createDirectoryIfNotExisting ) throws IOException {
106 // commons io FileUtils.forceMkdir would be useful here, we just want to omit this dependency
107 if (!dir.exists()) {
108 if(!createDirectoryIfNotExisting) {
109 throw new IOException("The directory " + dir.getAbsolutePath() + " does not exist.");
110 }
111 if(!dir.mkdirs()) {
112 throw new IOException("Could not create directory " + dir.getAbsolutePath());
113 }
114 }
115 if (!dir.isDirectory()) {
116 throw new IOException("File " + dir + " exists and is not a directory. Unable to create directory.");
117 }
118 }
119
120 /**
121 * Takes a given URI string which may contain backslashes (illegal in URIs) in it due to user input or variable
122 * substitution and returns a URI with the backslashes replaced with forward slashes.
123 *
124 * @param uri The URI string
125 * @return the URI.
126 * @throws URISyntaxException if instantiating the URI threw a {@code URISyntaxException}.
127 */
128 public static URI getCorrectedFilePathUri(final String uri) throws URISyntaxException {
129 return new URI(WINDOWS_DIRECTORY_SEPARATOR.matcher(uri).replaceAll("/"));
130 }
131 }