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.configuration2.io; 018 019import java.net.URL; 020 021import org.apache.commons.lang3.StringUtils; 022import org.apache.commons.lang3.builder.EqualsBuilder; 023import org.apache.commons.lang3.builder.HashCodeBuilder; 024import org.apache.commons.lang3.builder.ToStringBuilder; 025 026/** 027 * <p> 028 * A class describing the location of a file. 029 * </p> 030 * <p> 031 * An instance of this class provides information for locating and accessing a 032 * file. The file location can be defined 033 * </p> 034 * <ul> 035 * <li>as a URL; this identifies a file in a unique way</li> 036 * <li>as a combination of base path and file name; if this variant is used, 037 * there may be an additional location step required in order to identify the 038 * referenced file (for instance, the file name may be interpreted as the name 039 * of a resource to be loaded from class path).</li> 040 * </ul> 041 * <p> 042 * In addition, other properties are available which are also needed for loading 043 * or saving a file, like the underlying {@link FileSystem}. The encoding to be 044 * used when accessing the represented data is also part of the data contained 045 * in an instance; if no encoding is set explicitly, the platform's default 046 * encoding is used. 047 * <p> 048 * Instances of this class are immutable and thus can be safely shared between 049 * arbitrary components. {@link FileHandler} also uses an instance to reference 050 * the associated file. Instances are created using a <em>builder</em>. 051 * {@link FileLocatorUtils} offers convenience methods for obtaining such a 052 * builder. 053 * </p> 054 * 055 * @version $Id: FileLocator.java 1679788 2015-05-16 17:47:55Z oheger $ 056 * @since 2.0 057 */ 058public final class FileLocator 059{ 060 /** The file name. */ 061 private final String fileName; 062 063 /** The base path. */ 064 private final String basePath; 065 066 /** The source URL. */ 067 private final URL sourceURL; 068 069 /** The encoding. */ 070 private final String encoding; 071 072 /** The file system. */ 073 private final FileSystem fileSystem; 074 075 /** The file location strategy. */ 076 private final FileLocationStrategy locationStrategy; 077 078 /** 079 * Creates a new instance of {@code FileLocatorImpl} and initializes it from 080 * the given builder instance 081 * 082 * @param builder the builder 083 */ 084 public FileLocator(FileLocatorBuilder builder) 085 { 086 fileName = builder.fileName; 087 basePath = builder.basePath; 088 sourceURL = builder.sourceURL; 089 encoding = builder.encoding; 090 fileSystem = builder.fileSystem; 091 locationStrategy = builder.locationStrategy; 092 } 093 094 /** 095 * Returns the file name stored in this locator or <b>null</b> if it is 096 * undefined. 097 * 098 * @return the file name 099 */ 100 public String getFileName() 101 { 102 return fileName; 103 } 104 105 /** 106 * Returns the base path stored in this locator or <b>null</b> if it is 107 * undefined. 108 * 109 * @return the base path 110 */ 111 public String getBasePath() 112 { 113 return basePath; 114 } 115 116 /** 117 * Returns the URL pointing to the referenced source file or <b>null</b> if 118 * it is undefined. 119 * 120 * @return the source URL 121 */ 122 public URL getSourceURL() 123 { 124 return sourceURL; 125 } 126 127 /** 128 * Returns the encoding stored in this locator or <b>null</b> if it is 129 * undefined. 130 * 131 * @return the encoding 132 */ 133 public String getEncoding() 134 { 135 return encoding; 136 } 137 138 /** 139 * Returns the {@code FileSystem} to be used for accessing the file 140 * referenced by this locator or <b>null</b> if it is undefined. 141 * 142 * @return the {@code FileSystem} 143 */ 144 public FileSystem getFileSystem() 145 { 146 return fileSystem; 147 } 148 149 /** 150 * Returns the {@code FileLocationStrategy} to be used for locating the 151 * referenced file. If no specific {@code FileLocationStrategy} has been 152 * set, result is <b>null</b>. This means that the default strategy should 153 * be used. 154 * 155 * @return the {@code FileLocationStrategy} to be used 156 */ 157 public FileLocationStrategy getLocationStrategy() 158 { 159 return locationStrategy; 160 } 161 162 /** 163 * Returns a hash code for this object. 164 * 165 * @return a hash code for this object 166 */ 167 @Override 168 public int hashCode() 169 { 170 return new HashCodeBuilder().append(getFileName()) 171 .append(getBasePath()).append(sourceURLAsString()) 172 .append(getEncoding()).append(getFileSystem()) 173 .append(getLocationStrategy()).toHashCode(); 174 } 175 176 /** 177 * Compares this object with another one. Two instances of 178 * {@code FileLocatorImpl} are considered equal if all of their properties 179 * are equal. 180 * 181 * @param obj the object to compare to 182 * @return a flag whether these objects are equal 183 */ 184 @Override 185 public boolean equals(Object obj) 186 { 187 if (this == obj) 188 { 189 return true; 190 } 191 if (!(obj instanceof FileLocator)) 192 { 193 return false; 194 } 195 196 FileLocator c = (FileLocator) obj; 197 return new EqualsBuilder().append(getFileName(), c.getFileName()) 198 .append(getBasePath(), c.getBasePath()) 199 .append(sourceURLAsString(), c.sourceURLAsString()) 200 .append(getEncoding(), c.getEncoding()) 201 .append(getFileSystem(), c.getFileSystem()) 202 .append(getLocationStrategy(), c.getLocationStrategy()) 203 .isEquals(); 204 } 205 206 /** 207 * Returns a string representation of this object. This string contains the 208 * values of all properties. 209 * 210 * @return a string for this object 211 */ 212 @Override 213 public String toString() 214 { 215 return new ToStringBuilder(this).append("fileName", getFileName()) 216 .append("basePath", getBasePath()) 217 .append("sourceURL", sourceURLAsString()) 218 .append("encoding", getEncoding()) 219 .append("fileSystem", getFileSystem()) 220 .append("locationStrategy", getLocationStrategy()).toString(); 221 } 222 223 /** 224 * Returns the source URL as a string. Result is never null. Comparisons are 225 * done on this string to avoid blocking network calls. 226 * 227 * @return the source URL as a string (not null) 228 */ 229 private String sourceURLAsString() 230 { 231 return (sourceURL != null) ? sourceURL.toExternalForm() 232 : StringUtils.EMPTY; 233 } 234 235 /** 236 * A typical <em>builder</em> implementation for creating 237 * {@code FileLocator} objects. An instance of this class is returned by the 238 * {@code fileLocator()} method of {link FileLocatorUtils}. It can be used 239 * to define the various components of the {@code FileLocator} object. By 240 * calling {@code create()} the new immutable {@code FileLocator} instance 241 * is created. 242 */ 243 public static final class FileLocatorBuilder 244 { 245 /** The file name. */ 246 private String fileName; 247 248 /** The base path. */ 249 private String basePath; 250 251 /** The source URL. */ 252 private URL sourceURL; 253 254 /** The encoding. */ 255 private String encoding; 256 257 /** The file system. */ 258 private FileSystem fileSystem; 259 260 /** The location strategy. */ 261 private FileLocationStrategy locationStrategy; 262 263 /** 264 * Creates a new instance of {@code FileLocatorBuilder} and initializes 265 * the builder's properties from the passed in {@code FileLocator} 266 * object. 267 * 268 * @param src the source {@code FileLocator} (may be <b>null</b>) 269 */ 270 FileLocatorBuilder(FileLocator src) 271 { 272 if (src != null) 273 { 274 initBuilder(src); 275 } 276 } 277 278 /** 279 * Specifies the encoding of the new {@code FileLocator}. 280 * 281 * @param enc the encoding 282 * @return a reference to this builder for method chaining 283 */ 284 public FileLocatorBuilder encoding(String enc) 285 { 286 encoding = enc; 287 return this; 288 } 289 290 /** 291 * Specifies the {@code FileSystem} of the new {@code FileLocator}. 292 * 293 * @param fs the {@code FileSystem} 294 * @return a reference to this builder for method chaining 295 */ 296 public FileLocatorBuilder fileSystem(FileSystem fs) 297 { 298 fileSystem = fs; 299 return this; 300 } 301 302 /** 303 * Specifies the base path of the new {@code FileLocator}. 304 * 305 * @param path the base path 306 * @return a reference to this builder for method chaining 307 */ 308 public FileLocatorBuilder basePath(String path) 309 { 310 basePath = path; 311 return this; 312 } 313 314 /** 315 * Specifies the file name of the new {@code FileLocator}. 316 * 317 * @param name the file name 318 * @return a reference to this builder for method chaining 319 */ 320 public FileLocatorBuilder fileName(String name) 321 { 322 fileName = name; 323 return this; 324 } 325 326 /** 327 * Specifies the source URL of the new {@code FileLocator}. 328 * 329 * @param url the source URL 330 * @return a reference to this builder for method chaining 331 */ 332 public FileLocatorBuilder sourceURL(URL url) 333 { 334 sourceURL = url; 335 return this; 336 } 337 338 /** 339 * Specifies the {@code FileLocationStrategy} to be used when the 340 * referenced file is to be located. 341 * 342 * @param strategy the {@code FileLocationStrategy} 343 * @return a reference to this builder for method chaining 344 */ 345 public FileLocatorBuilder locationStrategy(FileLocationStrategy strategy) 346 { 347 locationStrategy = strategy; 348 return this; 349 } 350 351 /** 352 * Creates a new immutable {@code FileLocatorImpl} object based on the 353 * properties set so far for this builder. 354 * 355 * @return the newly created {@code FileLocator} object 356 */ 357 public FileLocator create() 358 { 359 return new FileLocator(this); 360 } 361 362 /** 363 * Initializes the properties of this builder from the passed in locator 364 * object. 365 * 366 * @param src the source {@code FileLocator} 367 */ 368 private void initBuilder(FileLocator src) 369 { 370 basePath = src.getBasePath(); 371 fileName = src.getFileName(); 372 sourceURL = src.getSourceURL(); 373 encoding = src.getEncoding(); 374 fileSystem = src.getFileSystem(); 375 locationStrategy = src.getLocationStrategy(); 376 } 377 } 378}