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.commons.io; 018 019 import java.io.Serializable; 020 021 /** 022 * Enumeration of IO case sensitivity. 023 * <p> 024 * Different filing systems have different rules for case-sensitivity. 025 * Windows is case-insensitive, Unix is case-sensitive. 026 * <p> 027 * This class captures that difference, providing an enumeration to 028 * control how filename comparisons should be performed. It also provides 029 * methods that use the enumeration to perform comparisons. 030 * <p> 031 * Wherever possible, you should use the <code>check</code> methods in this 032 * class to compare filenames. 033 * 034 * @author Stephen Colebourne 035 * @version $Id: IOCase.java 1003647 2010-10-01 20:53:59Z niallp $ 036 * @since Commons IO 1.3 037 */ 038 public final class IOCase implements Serializable { 039 040 /** 041 * The constant for case sensitive regardless of operating system. 042 */ 043 public static final IOCase SENSITIVE = new IOCase("Sensitive", true); 044 045 /** 046 * The constant for case insensitive regardless of operating system. 047 */ 048 public static final IOCase INSENSITIVE = new IOCase("Insensitive", false); 049 050 /** 051 * The constant for case sensitivity determined by the current operating system. 052 * Windows is case-insensitive when comparing filenames, Unix is case-sensitive. 053 * <p> 054 * <strong>Note:</strong> This only caters for Windows and Unix. Other operating 055 * systems (e.g. OSX and OpenVMS) are treated as case sensitive if they use the 056 * Unix file separator and case-insensitive if they use the Windows file separator 057 * (see {@link java.io.File#separatorChar}). 058 * <p> 059 * If you derialize this constant of Windows, and deserialize on Unix, or vice 060 * versa, then the value of the case-sensitivity flag will change. 061 */ 062 public static final IOCase SYSTEM = new IOCase("System", !FilenameUtils.isSystemWindows()); 063 064 /** Serialization version. */ 065 private static final long serialVersionUID = -6343169151696340687L; 066 067 /** The enumeration name. */ 068 private final String name; 069 070 /** The sensitivity flag. */ 071 private final transient boolean sensitive; 072 073 //----------------------------------------------------------------------- 074 /** 075 * Factory method to create an IOCase from a name. 076 * 077 * @param name the name to find 078 * @return the IOCase object 079 * @throws IllegalArgumentException if the name is invalid 080 */ 081 public static IOCase forName(String name) { 082 if (IOCase.SENSITIVE.name.equals(name)){ 083 return IOCase.SENSITIVE; 084 } 085 if (IOCase.INSENSITIVE.name.equals(name)){ 086 return IOCase.INSENSITIVE; 087 } 088 if (IOCase.SYSTEM.name.equals(name)){ 089 return IOCase.SYSTEM; 090 } 091 throw new IllegalArgumentException("Invalid IOCase name: " + name); 092 } 093 094 //----------------------------------------------------------------------- 095 /** 096 * Private constructor. 097 * 098 * @param name the name 099 * @param sensitive the sensitivity 100 */ 101 private IOCase(String name, boolean sensitive) { 102 this.name = name; 103 this.sensitive = sensitive; 104 } 105 106 /** 107 * Replaces the enumeration from the stream with a real one. 108 * This ensures that the correct flag is set for SYSTEM. 109 * 110 * @return the resolved object 111 */ 112 private Object readResolve() { 113 return forName(name); 114 } 115 116 //----------------------------------------------------------------------- 117 /** 118 * Gets the name of the constant. 119 * 120 * @return the name of the constant 121 */ 122 public String getName() { 123 return name; 124 } 125 126 /** 127 * Does the object represent case sensitive comparison. 128 * 129 * @return true if case sensitive 130 */ 131 public boolean isCaseSensitive() { 132 return sensitive; 133 } 134 135 //----------------------------------------------------------------------- 136 /** 137 * Compares two strings using the case-sensitivity rule. 138 * <p> 139 * This method mimics {@link String#compareTo} but takes case-sensitivity 140 * into account. 141 * 142 * @param str1 the first string to compare, not null 143 * @param str2 the second string to compare, not null 144 * @return true if equal using the case rules 145 * @throws NullPointerException if either string is null 146 */ 147 public int checkCompareTo(String str1, String str2) { 148 if (str1 == null || str2 == null) { 149 throw new NullPointerException("The strings must not be null"); 150 } 151 return sensitive ? str1.compareTo(str2) : str1.compareToIgnoreCase(str2); 152 } 153 154 /** 155 * Compares two strings using the case-sensitivity rule. 156 * <p> 157 * This method mimics {@link String#equals} but takes case-sensitivity 158 * into account. 159 * 160 * @param str1 the first string to compare, not null 161 * @param str2 the second string to compare, not null 162 * @return true if equal using the case rules 163 * @throws NullPointerException if either string is null 164 */ 165 public boolean checkEquals(String str1, String str2) { 166 if (str1 == null || str2 == null) { 167 throw new NullPointerException("The strings must not be null"); 168 } 169 return sensitive ? str1.equals(str2) : str1.equalsIgnoreCase(str2); 170 } 171 172 /** 173 * Checks if one string starts with another using the case-sensitivity rule. 174 * <p> 175 * This method mimics {@link String#startsWith(String)} but takes case-sensitivity 176 * into account. 177 * 178 * @param str the string to check, not null 179 * @param start the start to compare against, not null 180 * @return true if equal using the case rules 181 * @throws NullPointerException if either string is null 182 */ 183 public boolean checkStartsWith(String str, String start) { 184 return str.regionMatches(!sensitive, 0, start, 0, start.length()); 185 } 186 187 /** 188 * Checks if one string ends with another using the case-sensitivity rule. 189 * <p> 190 * This method mimics {@link String#endsWith} but takes case-sensitivity 191 * into account. 192 * 193 * @param str the string to check, not null 194 * @param end the end to compare against, not null 195 * @return true if equal using the case rules 196 * @throws NullPointerException if either string is null 197 */ 198 public boolean checkEndsWith(String str, String end) { 199 int endLen = end.length(); 200 return str.regionMatches(!sensitive, str.length() - endLen, end, 0, endLen); 201 } 202 203 /** 204 * Checks if one string contains another starting at a specific index using the 205 * case-sensitivity rule. 206 * <p> 207 * This method mimics parts of {@link String#indexOf(String, int)} 208 * but takes case-sensitivity into account. 209 * 210 * @param str the string to check, not null 211 * @param strStartIndex the index to start at in str 212 * @param search the start to search for, not null 213 * @return the first index of the search String, 214 * -1 if no match or <code>null</code> string input 215 * @throws NullPointerException if either string is null 216 * @since Commons IO 2.0 217 */ 218 public int checkIndexOf(String str, int strStartIndex, String search) { 219 int endIndex = str.length() - search.length(); 220 if (endIndex >= strStartIndex) { 221 for (int i = strStartIndex; i <= endIndex; i++) { 222 if (checkRegionMatches(str, i, search)) { 223 return i; 224 } 225 } 226 } 227 return -1; 228 } 229 230 /** 231 * Checks if one string contains another at a specific index using the case-sensitivity rule. 232 * <p> 233 * This method mimics parts of {@link String#regionMatches(boolean, int, String, int, int)} 234 * but takes case-sensitivity into account. 235 * 236 * @param str the string to check, not null 237 * @param strStartIndex the index to start at in str 238 * @param search the start to search for, not null 239 * @return true if equal using the case rules 240 * @throws NullPointerException if either string is null 241 */ 242 public boolean checkRegionMatches(String str, int strStartIndex, String search) { 243 return str.regionMatches(!sensitive, strStartIndex, search, 0, search.length()); 244 } 245 246 //----------------------------------------------------------------------- 247 /** 248 * Gets a string describing the sensitivity. 249 * 250 * @return a string describing the sensitivity 251 */ 252 @Override 253 public String toString() { 254 return name; 255 } 256 257 }