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