View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.vfs2;
18  
19  import java.util.Arrays;
20  import java.util.Iterator;
21  import java.util.Map;
22  import java.util.SortedMap;
23  import java.util.TreeMap;
24  
25  /**
26   * Configures file systems individually with these options.
27   * <p>
28   * To configure a file system, you set properties on a {@link FileSystemOptions} object. Most file systems provide a
29   * {@link FileSystemConfigBuilder} with specific options for that file system.
30   * </p>
31   * <p>
32   * To use the options, pass them to {@link FileSystemManager#resolveFile(String,FileSystemOptions)}. From there, the
33   * options apply to all files that are resolved relative to that file.
34   * </p>
35   *
36   * @see org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder
37   * @see org.apache.commons.vfs2.provider.ftp.FtpFileSystemConfigBuilder
38   * @see org.apache.commons.vfs2.provider.ftps.FtpsFileSystemConfigBuilder
39   * @see org.apache.commons.vfs2.provider.hdfs.HdfsFileSystemConfigBuilder
40   * @see org.apache.commons.vfs2.provider.http.HttpFileSystemConfigBuilder
41   * @see org.apache.commons.vfs2.provider.ram.RamFileSystemConfigBuilder
42   * @see org.apache.commons.vfs2.provider.res.ResourceFileSystemConfigBuilder
43   * @see org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder
44   * @see org.apache.commons.vfs2.provider.zip.ZipFileSystemConfigBuilder
45   *
46   */
47  public final class FileSystemOptions implements Cloneable {
48  
49      /** The options */
50      private final Map<FileSystemOptionKey, Object> options;
51  
52      /**
53       * Creates a new instance.
54       */
55      public FileSystemOptions() {
56          this(new TreeMap<>());
57      }
58  
59      protected FileSystemOptions(final Map<FileSystemOptionKey, Object> options) {
60          this.options = options;
61      }
62  
63      /**
64       * Keys in the options Map.
65       */
66      private static final class FileSystemOptionKey implements Comparable<FileSystemOptionKey> {
67          /** Constant used to create hashcode */
68          private static final int HASH = 29;
69  
70          /** The FileSystem class */
71          private final Class<? extends FileSystem> fileSystemClass;
72  
73          /** The option name */
74          private final String name;
75  
76          // TODO: the parameter name suggests that the class should only be a
77          // a FileSystem, however some of the tests pass in DefaultFileSystemConfigBuilder
78          private FileSystemOptionKey(final Class<? extends FileSystem> fileSystemClass, final String name) {
79              this.fileSystemClass = fileSystemClass;
80              this.name = name;
81          }
82  
83          @Override
84          public int compareTo(final FileSystemOptionKey o) {
85              final int ret = fileSystemClass.getName().compareTo(o.fileSystemClass.getName());
86              if (ret != 0) {
87                  return ret;
88              }
89              return name.compareTo(o.name);
90          }
91  
92          @Override
93          public boolean equals(final Object o) {
94              if (this == o) {
95                  return true;
96              }
97              if (o == null || getClass() != o.getClass()) {
98                  return false;
99              }
100 
101             final FileSystemOptionKey that = (FileSystemOptionKey) o;
102 
103             if (!fileSystemClass.equals(that.fileSystemClass)) {
104                 return false;
105             }
106             return name.equals(that.name);
107         }
108 
109         @Override
110         public int hashCode() {
111             int result;
112             result = fileSystemClass.hashCode();
113             result = HASH * result + name.hashCode();
114             return result;
115         }
116 
117         @Override
118         public String toString() {
119             return fileSystemClass.getName() + "." + name;
120         }
121     }
122 
123     void setOption(final Class<? extends FileSystem> fileSystemClass, final String name, final Object value) {
124         options.put(new FileSystemOptionKey(fileSystemClass, name), value);
125     }
126 
127     <T> T getOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
128         final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
129         return (T) options.get(key);
130     }
131 
132     boolean hasOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
133         final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
134         return options.containsKey(key);
135     }
136 
137     public int compareTo(final FileSystemOptions other) {
138         if (this == other) {
139             // the same instance
140             return 0;
141         }
142 
143         final int propsSz = options == null ? 0 : options.size();
144         final int propsFkSz = other.options == null ? 0 : other.options.size();
145         if (propsSz < propsFkSz) {
146             return -1;
147         }
148         if (propsSz > propsFkSz) {
149             return 1;
150         }
151         if (propsSz == 0) {
152             // props empty
153             return 0;
154         }
155 
156         // ensure proper sequence of options
157         final SortedMap<FileSystemOptionKey, Object> myOptions = options instanceof SortedMap
158                 ? (SortedMap<FileSystemOptionKey, Object>) options
159                 : new TreeMap<>(options);
160         final SortedMap<FileSystemOptionKey, Object> theirOptions = other.options instanceof SortedMap
161                 ? (SortedMap<FileSystemOptionKey, Object>) other.options
162                 : new TreeMap<>(other.options);
163         final Iterator<FileSystemOptionKey> optKeysIter = myOptions.keySet().iterator();
164         final Iterator<FileSystemOptionKey> otherKeysIter = theirOptions.keySet().iterator();
165         while (optKeysIter.hasNext()) {
166             final int comp = optKeysIter.next().compareTo(otherKeysIter.next());
167             if (comp != 0) {
168                 return comp;
169             }
170         }
171 
172         final int hash = Arrays.deepHashCode(myOptions.values().toArray());
173         final int hashFk = Arrays.deepHashCode(theirOptions.values().toArray());
174         return Integer.compare(hash, hashFk);
175 
176         // TODO: compare Entry by Entry ??
177     }
178 
179     @Override
180     public int hashCode() {
181         final int prime = 31;
182         int result = 1;
183         if (options == null) {
184             result = prime * result;
185         } else {
186             final SortedMap<FileSystemOptionKey, Object> myOptions = options instanceof SortedMap
187                     ? (SortedMap<FileSystemOptionKey, Object>) options
188                     : new TreeMap<>(options);
189             result = prime * result + myOptions.keySet().hashCode();
190             result = prime * result + Arrays.deepHashCode(myOptions.values().toArray());
191         }
192         return result;
193     }
194 
195     @Override
196     public boolean equals(final Object obj) {
197         if (this == obj) {
198             return true;
199         }
200         if (obj == null) {
201             return false;
202         }
203         if (getClass() != obj.getClass()) {
204             return false;
205         }
206         final FileSystemOptions./org/apache/commons/vfs2/FileSystemOptions.html#FileSystemOptions">FileSystemOptions other = (FileSystemOptions) obj;
207         return compareTo(other) == 0;
208     }
209 
210     /**
211      * {@inheritDoc}
212      *
213      * @since 2.0
214      */
215     @Override
216     public Object clone() {
217         return new FileSystemOptions(new TreeMap<>(options));
218     }
219 
220     @Override
221     public String toString() {
222         return options.toString();
223     }
224 }