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; 018 019import java.io.IOException; 020import java.util.regex.Matcher; 021import java.util.regex.Pattern; 022 023import org.apache.commons.lang3.ArrayUtils; 024import org.apache.commons.vfs2.util.Messages; 025 026/** 027 * Thrown for file system errors. 028 */ 029public class FileSystemException extends IOException { 030 031 /** 032 * serialVersionUID format is YYYYMMDD for the date of the last binary change. 033 */ 034 private static final long serialVersionUID = 20101208L; 035 036 /** URL pattern */ 037 private static final Pattern URL_PATTERN = Pattern.compile("[a-z]+://.*"); 038 039 /** Password pattern */ 040 private static final Pattern PASSWORD_PATTERN = Pattern.compile(":(?:[^/]+)@"); 041 042 /** 043 * Throws a FileSystemException when the given object is null. 044 * 045 * @param obj 046 * the object reference to check for null. 047 * @param code 048 * message used when {@code 049 * FileSystemException} is thrown 050 * @param <T> 051 * the type of the reference 052 * @return {@code obj} if not {@code null} 053 * @throws FileSystemException 054 * if {@code obj} is {@code null} 055 * @since 2.3 056 */ 057 public static <T> T requireNonNull(final T obj, final String code) throws FileSystemException { 058 if (obj == null) { 059 throw new FileSystemException(code); 060 } 061 return obj; 062 } 063 064 /** 065 * Throws a FileSystemException when the given object is null. 066 * 067 * @param obj 068 * the object reference to check for null. 069 * @param code 070 * message used when {@code 071 * FileSystemException} is thrown 072 * @param info 073 * one context information. 074 * @param <T> 075 * the type of the reference 076 * @return {@code obj} if not {@code null} 077 * @throws FileSystemException 078 * if {@code obj} is {@code null} 079 * @since 2.3 080 */ 081 public static <T> T requireNonNull(final T obj, final String code, final Object... info) throws FileSystemException { 082 if (obj == null) { 083 throw new FileSystemException(code, info); 084 } 085 return obj; 086 } 087 088 /** 089 * Array of complementary info (context). 090 */ 091 private final String[] info; 092 093 /** 094 * Constructs exception with the specified detail message. 095 * 096 * @param code the error code of the message. 097 */ 098 public FileSystemException(final String code) { 099 this(code, null, (Object[]) null); 100 } 101 102 /** 103 * Constructs exception with the specified detail message. 104 * 105 * @param code the error code of the message. 106 * @param info one context information. 107 */ 108 public FileSystemException(final String code, final Object info) { 109 this(code, null, new Object[] {info}); 110 } 111 112 /** 113 * Constructs exception with the specified detail message. 114 * 115 * @param code the error code of the message. 116 * @param info array of complementary info (context). 117 */ 118 public FileSystemException(final String code, final Object... info) { 119 this(code, null, info); 120 } 121 122 /** 123 * Constructs exception with the specified detail message and cause. 124 * 125 * @param code the error code of the message. 126 * @param info one context information. 127 * @param cause the cause. 128 */ 129 public FileSystemException(final String code, final Object info, final Throwable cause) { 130 this(code, cause, info); 131 } 132 133 /** 134 * Constructs exception with the specified detail message. 135 * 136 * @param code the error code of the message. 137 * @param info array of complementary info (context). 138 * @param cause the cause. 139 * @deprecated Use instead {@link #FileSystemException(String, Throwable, Object[])}. Will be removed in 3.0. 140 */ 141 @Deprecated 142 public FileSystemException(final String code, final Object[] info, final Throwable cause) { 143 this(code, cause, info); 144 } 145 146 /** 147 * Constructs exception with the specified detail message. 148 * 149 * @param code the error code of the message. 150 * @param cause the original cause 151 */ 152 public FileSystemException(final String code, final Throwable cause) { 153 this(code, cause, (Object[]) null); 154 } 155 156 /** 157 * Constructs exception with the specified detail message. 158 * 159 * @param code the error code of the message. 160 * @param info array of complementary info (context). 161 * @param cause the cause. 162 */ 163 public FileSystemException(final String code, final Throwable cause, final Object... info) { 164 super(code, cause); 165 166 if (info == null) { 167 this.info = ArrayUtils.EMPTY_STRING_ARRAY; 168 } else { 169 this.info = new String[info.length]; 170 for (int i = 0; i < info.length; i++) { 171 String value = String.valueOf(info[i]); 172 // mask passwords (VFS-169) 173 final Matcher urlMatcher = URL_PATTERN.matcher(value); 174 if (urlMatcher.find()) { 175 value = PASSWORD_PATTERN.matcher(value).replaceFirst(":***@"); 176 } 177 this.info[i] = value; 178 } 179 } 180 } 181 182 /** 183 * Constructs wrapper exception. 184 * 185 * @param cause the root cause to wrap. 186 */ 187 public FileSystemException(final Throwable cause) { 188 this(cause.getMessage(), cause, (Object[]) null); 189 } 190 191 /** 192 * Retrieves error code of the exception. Could be used as key for internationalization. 193 * 194 * @return the code. 195 */ 196 public String getCode() { 197 return super.getMessage(); 198 } 199 200 /** 201 * Retrieves array of complementary info (context). Could be used as parameter for internationalization. 202 * 203 * @return the context info. 204 */ 205 public String[] getInfo() { 206 return info; 207 } 208 209 /** 210 * Retrieves message from bundle. 211 * 212 * @return The exception message. 213 */ 214 @Override 215 public String getMessage() { 216 return Messages.getString(super.getMessage(), (Object[]) getInfo()); 217 } 218}