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 URL 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 if (uri == null || (uri.getScheme() != null && 057 (!PROTOCOL_FILE.equals(uri.getScheme()) && !JBOSS_FILE.equals(uri.getScheme())))) { 058 return null; 059 } 060 if (uri.getScheme() == null) { 061 try { 062 uri = new File(uri.getPath()).toURI(); 063 } catch (final Exception ex) { 064 LOGGER.warn("Invalid URI {}", uri); 065 return null; 066 } 067 } 068 try { 069 String fileName = uri.toURL().getFile(); 070 if (new File(fileName).exists()) { // LOG4J2-466 071 return new File(fileName); // allow files with '+' char in name 072 } 073 return new File(URLDecoder.decode(fileName, "UTF8")); 074 } catch (final MalformedURLException ex) { 075 LOGGER.warn("Invalid URL {}", uri, ex); 076 } catch (final UnsupportedEncodingException uee) { 077 LOGGER.warn("Invalid encoding: UTF8", uee); 078 } 079 return null; 080 } 081 082 public static boolean isFile(final URL url) { 083 return url != null && (url.getProtocol().equals(PROTOCOL_FILE) || url.getProtocol().equals(JBOSS_FILE)); 084 } 085 086 /** 087 * Asserts that the given directory exists and creates it if necessary. 088 * @param dir the directory that shall exist 089 * @param createDirectoryIfNotExisting specifies if the directory shall be created if it does not exist. 090 * @throws java.io.IOException thrown if the directory could not be created. 091 */ 092 public static void mkdir(final File dir, final boolean createDirectoryIfNotExisting ) throws IOException { 093 // commons io FileUtils.forceMkdir would be useful here, we just want to omit this dependency 094 if (!dir.exists()) { 095 if(!createDirectoryIfNotExisting) { 096 throw new IOException("The directory " + dir.getAbsolutePath() + " does not exist."); 097 } 098 if(!dir.mkdirs()) { 099 throw new IOException("Could not create directory " + dir.getAbsolutePath()); 100 } 101 } 102 if (!dir.isDirectory()) { 103 throw new IOException("File " + dir + " exists and is not a directory. Unable to create directory."); 104 } 105 } 106 107 /** 108 * Takes a given URI string which may contain backslashes (illegal in URIs) in it due to user input or variable 109 * substitution and returns a URI with the backslashes replaced with forward slashes. 110 * 111 * @param uri The URI string 112 * @return the URI. 113 * @throws URISyntaxException if instantiating the URI threw a {@code URISyntaxException}. 114 */ 115 public static URI getCorrectedFilePathUri(String uri) throws URISyntaxException { 116 return new URI(WINDOWS_DIRECTORY_SEPARATOR.matcher(uri).replaceAll("/")); 117 } 118 }