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
019/**
020 * Abstract class which has the right to fill FileSystemOptions.
021 */
022public abstract class FileSystemConfigBuilder {
023    /** Default prefix to use when resolving system properties */
024    private static final String PREFIX = "vfs.";
025
026    /** The root uri of the file system */
027    private static final String ROOTURI = "rootURI";
028
029    /** The prefix to use when resolving system properties */
030    private final String prefix;
031
032    /**
033     * Construct builder with default prefix.
034     *
035     * @since 1.0
036     */
037    protected FileSystemConfigBuilder() {
038        this.prefix = PREFIX;
039    }
040
041    /**
042     * Construct builder with specified component name.
043     *
044     * @param component component name to be used in prefix
045     *
046     * @since 2.0
047     */
048    protected FileSystemConfigBuilder(final String component) {
049        this.prefix = PREFIX + component;
050    }
051
052    /**
053     * The root URI of the file system.
054     *
055     * @param opts the file system options to modify
056     * @param rootURI The creator name to be associated with the file.
057     *
058     * @since 2.0
059     */
060    public void setRootURI(final FileSystemOptions opts, final String rootURI) {
061        setParam(opts, ROOTURI, rootURI);
062    }
063
064    /**
065     * Return the root URI of the file system.
066     *
067     * @param opts file system options to work with
068     * @return The root URI
069     *
070     * @since 2.0
071     */
072    public String getRootURI(final FileSystemOptions opts) {
073        return getString(opts, ROOTURI);
074    }
075
076    /**
077     * Set named parameter.
078     *
079     * @param opts the file system options to modify
080     * @param name set option with this name
081     * @param value boolean value to set
082     *
083     * @since 2.1
084     */
085    protected void setParam(final FileSystemOptions opts, final String name, final boolean value) {
086        setParam(opts, name, Boolean.valueOf(value));
087    }
088
089    /**
090     * Set named parameter.
091     *
092     * @param opts the file system options to modify
093     * @param name set option with this name
094     * @param value object value to set
095     *
096     * @since 1.0
097     */
098    protected void setParam(final FileSystemOptions opts, final String name, final Object value) {
099        opts.setOption(getConfigClass(), name, value);
100    }
101
102    /**
103     * Get named parameter.
104     *
105     * @param opts file system options to work with
106     * @param name get option with this name
107     * @return the named option or null
108     *
109     * @since 1.0
110     */
111    protected Object getParam(final FileSystemOptions opts, final String name) {
112        if (opts == null) {
113            return null;
114        }
115
116        return opts.getOption(getConfigClass(), name);
117    }
118
119    /**
120     * Check if option exists.
121     *
122     * @param opts file system options to work with
123     * @param name the name to look up in {@code opts}
124     * @return true if opts have the named parameter
125     *
126     * @since 1.0
127     */
128    protected boolean hasParam(final FileSystemOptions opts, final String name) {
129        return opts != null && opts.hasOption(getConfigClass(), name);
130    }
131
132    /**
133     * Is named setting specified.
134     *
135     * @param opts file system options to work with
136     * @param name the option to check in {@code opts} or system properties
137     * @return true if option exists
138     *
139     * @since 2.0
140     */
141    protected boolean hasObject(final FileSystemOptions opts, final String name) {
142        return hasParam(opts, name) || System.getProperties().containsKey(toPropertyKey(name));
143    }
144
145    /**
146     * Get named option as boolean.
147     *
148     * @param opts file system options to work with
149     * @param name the option name
150     * @return the option in {@code opts} or system properties, otherwise null
151     * @see #getBoolean(FileSystemOptions, String, Boolean)
152     *
153     * @since 2.0
154     */
155    protected Boolean getBoolean(final FileSystemOptions opts, final String name) {
156        return getBoolean(opts, name, null);
157    }
158
159    /**
160     * Get named option as boolean.
161     *
162     * @param opts file system options to work with
163     * @param name the option name
164     * @param defaultValue value to return if option is not present
165     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
166     * @see #getBoolean(FileSystemOptions, String, Boolean)
167     *
168     * @since 2.0
169     */
170    protected boolean getBoolean(final FileSystemOptions opts, final String name, final boolean defaultValue) {
171        return getBoolean(opts, name, Boolean.valueOf(defaultValue)).booleanValue();
172    }
173
174    /**
175     * Get named option as boolean.
176     *
177     * @param opts file system options to work with
178     * @param name the option name
179     * @param defaultValue value to return if option is not present
180     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
181     * @see #getBoolean(FileSystemOptions, String, Boolean)
182     *
183     * @since 2.0
184     */
185    protected Boolean getBoolean(final FileSystemOptions opts, final String name, final Boolean defaultValue) {
186        Boolean value = (Boolean) getParam(opts, name);
187        if (value == null) {
188            final String str = getProperty(name);
189            if (str == null) {
190                return defaultValue;
191            }
192            value = Boolean.valueOf(str);
193        }
194        return value;
195    }
196
197    /**
198     * Get named option as byte.
199     *
200     * @param opts file system options to work with
201     * @param name the option name
202     * @return the option in {@code opts} or system properties, otherwise null
203     * @see #getByte(FileSystemOptions, String, Byte)
204     *
205     * @since 2.0
206     */
207    protected Byte getByte(final FileSystemOptions opts, final String name) {
208        return getByte(opts, name, null);
209    }
210
211    /**
212     * Get named option as byte.
213     *
214     * @param opts file system options to work with
215     * @param name the option name
216     * @param defaultValue value to return if option is not present
217     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
218     * @see #getByte(FileSystemOptions, String, Byte)
219     *
220     * @since 2.0
221     */
222    protected byte getByte(final FileSystemOptions opts, final String name, final byte defaultValue) {
223        return getByte(opts, name, Byte.valueOf(defaultValue)).byteValue();
224    }
225
226    /**
227     * Get named option as byte.
228     *
229     * @param opts file system options to work with
230     * @param name the option name
231     * @param defaultValue value to return if option is not present
232     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
233     *
234     * @since 2.0
235     */
236    protected Byte getByte(final FileSystemOptions opts, final String name, final Byte defaultValue) {
237        Byte value = (Byte) getParam(opts, name);
238        if (value == null) {
239            final String str = getProperty(name);
240            if (str == null) {
241                return defaultValue;
242            }
243            value = Byte.valueOf(str);
244        }
245        return value;
246    }
247
248    /**
249     * Get named option as character.
250     *
251     * @param opts file system options to work with
252     * @param name the option name
253     * @return the option in {@code opts} or system properties, otherwise null
254     * @see #getCharacter(FileSystemOptions, String, Character)
255     *
256     * @since 2.0
257     */
258    protected Character getCharacter(final FileSystemOptions opts, final String name) {
259        return getCharacter(opts, name, null);
260    }
261
262    /**
263     * Get named option as character.
264     *
265     * @param opts file system options to work with
266     * @param name the option name
267     * @param defaultValue value to return if option is not present
268     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
269     * @see #getCharacter(FileSystemOptions, String, Character)
270     *
271     * @since 2.0
272     */
273    protected char getCharacter(final FileSystemOptions opts, final String name, final char defaultValue) {
274        return getCharacter(opts, name, new Character(defaultValue)).charValue();
275    }
276
277    /**
278     * Get named option as character.
279     *
280     * @param opts file system options to work with
281     * @param name the option name
282     * @param defaultValue value to return if option is not present
283     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
284     *
285     * @since 2.0
286     */
287    protected Character getCharacter(final FileSystemOptions opts, final String name, final Character defaultValue) {
288        Character value = (Character) getParam(opts, name);
289        if (value == null) {
290            final String str = getProperty(name);
291            if (str == null || str.length() <= 0) {
292                return defaultValue;
293            }
294            value = new Character(str.charAt(0));
295        }
296        return value;
297    }
298
299    /**
300     * Get named option as double.
301     *
302     * @param opts file system options to work with
303     * @param name the option name
304     * @return the option in {@code opts} or system properties, otherwise null
305     * @see #getDouble(FileSystemOptions, String, Double)
306     *
307     * @since 2.0
308     */
309    protected Double getDouble(final FileSystemOptions opts, final String name) {
310        return getDouble(opts, name, null);
311    }
312
313    /**
314     * Get named option as double.
315     *
316     * @param opts file system options to work with
317     * @param name the option name
318     * @param defaultValue value to return if option is not present
319     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
320     * @see #getDouble(FileSystemOptions, String, Double)
321     *
322     * @since 2.0
323     */
324    protected double getDouble(final FileSystemOptions opts, final String name, final double defaultValue) {
325        return getDouble(opts, name, new Double(defaultValue)).doubleValue();
326    }
327
328    /**
329     * Get named option as double.
330     *
331     * @param opts file system options to work with
332     * @param name the option name
333     * @param defaultValue value to return if option is not present
334     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
335     *
336     * @since 2.0
337     */
338    protected Double getDouble(final FileSystemOptions opts, final String name, final Double defaultValue) {
339        Double value = (Double) getParam(opts, name);
340        if (value == null) {
341            final String str = getProperty(name);
342            if (str == null || str.length() <= 0) {
343                return defaultValue;
344            }
345            value = Double.valueOf(str);
346        }
347        return value;
348    }
349
350    /**
351     * Get named option as enumeration.
352     *
353     * @param <E> enumeration type
354     * @param enumClass class of enumeration type
355     * @param opts file system options to work with
356     * @param name the option name *
357     * @return the option in {@code opts} or system properties, otherwise null
358     * @see #getEnum(Class, FileSystemOptions, String, Enum)
359     * @throws IllegalArgumentException if option value is not a known enumeration.
360     *
361     * @since 2.1
362     */
363    protected <E extends Enum<E>> E getEnum(final Class<E> enumClass, final FileSystemOptions opts, final String name) {
364        return this.<E>getEnum(enumClass, opts, name, null);
365    }
366
367    /**
368     * Get named option as enumeration.
369     *
370     * @param <E> enumeration type
371     * @param enumClass class of enumeration type
372     * @param opts file system options to work with
373     * @param name the option name
374     * @param defaultValue value to return if option is not present
375     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
376     * @see #getEnum(Class, FileSystemOptions, String, Enum)
377     * @throws IllegalArgumentException if option value is not a known enumeration.
378     *
379     * @since 2.1
380     */
381    protected <E extends Enum<E>> E getEnum(final Class<E> enumClass, final FileSystemOptions opts, final String name,
382            final E defaultValue) {
383        @SuppressWarnings("unchecked")
384        E value = (E) getParam(opts, name);
385        if (value == null) {
386            final String str = getProperty(name);
387            if (str == null) {
388                return defaultValue;
389            }
390            value = Enum.valueOf(enumClass, str);
391        }
392        return value;
393    }
394
395    /**
396     * Get named option as float.
397     *
398     * @param opts file system options to work with
399     * @param name the option name
400     * @return the option in {@code opts} or system properties, otherwise null
401     * @see #getFloat(FileSystemOptions, String, Float)
402     * @throws NumberFormatException if option value is not a valid float.
403     *
404     * @since 2.0
405     */
406    protected Float getFloat(final FileSystemOptions opts, final String name) {
407        return getFloat(opts, name, null);
408    }
409
410    /**
411     * Get named option as float.
412     *
413     * @param opts file system options to work with
414     * @param name the option name
415     * @param defaultValue value to return if option is not present
416     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
417     * @see #getFloat(FileSystemOptions, String, Float)
418     * @throws NumberFormatException if option value is not a valid float.
419     *
420     * @since 2.0
421     */
422    protected float getFloat(final FileSystemOptions opts, final String name, final float defaultValue) {
423        return getFloat(opts, name, new Float(defaultValue)).floatValue();
424    }
425
426    /**
427     * Get named option as float.
428     *
429     * @param opts file system options to work with
430     * @param name the option name
431     * @param defaultValue value to return if option is not present
432     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
433     * @throws NumberFormatException if option value is not a valid float.
434     *
435     * @since 2.0
436     */
437    protected Float getFloat(final FileSystemOptions opts, final String name, final Float defaultValue) {
438        Float value = (Float) getParam(opts, name);
439        if (value == null) {
440            final String str = getProperty(name);
441            if (str == null || str.length() <= 0) {
442                return defaultValue;
443            }
444            value = Float.valueOf(str);
445        }
446        return value;
447    }
448
449    /**
450     * Get named option as integer.
451     *
452     * @param opts file system options to work with
453     * @param name the option name
454     * @return the option in {@code opts} or system properties, otherwise null
455     * @see #getInteger(FileSystemOptions, String, Integer)
456     * @throws NumberFormatException if option value is not a valid integer.
457     *
458     * @since 2.0
459     */
460    protected Integer getInteger(final FileSystemOptions opts, final String name) {
461        return getInteger(opts, name, null);
462    }
463
464    /**
465     * Get named option as integer.
466     *
467     * @param opts file system options to work with
468     * @param name the option name
469     * @param defaultValue value to return if option is not present
470     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
471     * @see #getInteger(FileSystemOptions, String, Integer)
472     * @throws NumberFormatException if option value is not a valid integer.
473     *
474     * @since 2.0
475     */
476    protected int getInteger(final FileSystemOptions opts, final String name, final int defaultValue) {
477        return getInteger(opts, name, Integer.valueOf(defaultValue)).intValue();
478    }
479
480    /**
481     * Get named option as integer.
482     *
483     * @param opts file system options to work with
484     * @param name the option name
485     * @param defaultValue value to return if option is not present
486     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
487     * @throws NumberFormatException if option value is not a valid integer.
488     *
489     * @since 2.0
490     */
491    protected Integer getInteger(final FileSystemOptions opts, final String name, final Integer defaultValue) {
492        Integer value = (Integer) getParam(opts, name);
493        if (value == null) {
494            final String str = getProperty(name);
495            if (str == null) {
496                return defaultValue;
497            }
498            value = Integer.valueOf(str);
499        }
500        return value;
501    }
502
503    /**
504     * Get named option as long.
505     *
506     * @param opts file system options to work with
507     * @param name the option name
508     * @return the option in {@code opts} or system properties, otherwise null
509     * @see #getLong(FileSystemOptions, String, Long)
510     * @throws NumberFormatException if option value is not a valid long.
511     *
512     * @since 2.0
513     */
514    protected Long getLong(final FileSystemOptions opts, final String name) {
515        return getLong(opts, name, null);
516    }
517
518    /**
519     * Get named option as long.
520     *
521     * @param opts file system options to work with
522     * @param name the option name
523     * @param defaultValue value to return if option is not present
524     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
525     * @see #getLong(FileSystemOptions, String, Long)
526     * @throws NumberFormatException if option value is not a valid long.
527     *
528     * @since 2.0
529     */
530    protected long getLong(final FileSystemOptions opts, final String name, final long defaultValue) {
531        return getLong(opts, name, Long.valueOf(defaultValue)).longValue();
532    }
533
534    /**
535     * Get named option as long.
536     *
537     * @param opts file system options to work with
538     * @param name the option name
539     * @param defaultValue value to return if option is not present
540     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
541     * @throws NumberFormatException if option value is not a valid long.
542     *
543     * @since 2.0
544     */
545    protected Long getLong(final FileSystemOptions opts, final String name, final Long defaultValue) {
546        Long value = (Long) getParam(opts, name);
547        if (value == null) {
548            final String str = getProperty(name);
549            if (str == null) {
550                return defaultValue;
551            }
552            value = Long.valueOf(str);
553        }
554        return value;
555    }
556
557    /**
558     * Get named option as short.
559     *
560     * @param opts file system options to work with
561     * @param name the option name
562     * @return the option in {@code opts} or system properties, otherwise null
563     * @see #getShort(FileSystemOptions, String, Short)
564     * @throws NumberFormatException if option value is not a valid short.
565     *
566     * @since 2.0
567     */
568    protected Short getShort(final FileSystemOptions opts, final String name) {
569        return getShort(opts, name, null);
570    }
571
572    /**
573     * Get named option as short.
574     *
575     * @param opts file system options to work with
576     * @param name the option name
577     * @param defaultValue value to return if option is not present
578     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
579     * @see #getShort(FileSystemOptions, String, Short)
580     * @throws NumberFormatException if option value is not a valid short
581     *
582     * @since 2.0
583     */
584    protected short getShort(final FileSystemOptions opts, final String name, final short defaultValue) {
585        return getShort(opts, name, Short.valueOf(defaultValue)).shortValue();
586    }
587
588    /**
589     * Get named option as short.
590     *
591     * @param opts file system options to work with
592     * @param name the option name
593     * @param defaultValue value to return if option is not present
594     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
595     * @throws NumberFormatException if option value is not a valid short
596     *
597     * @since 2.0
598     */
599    protected Short getShort(final FileSystemOptions opts, final String name, final Short defaultValue) {
600        Short value = (Short) getParam(opts, name);
601        if (value == null) {
602            final String str = getProperty(name);
603            if (str == null) {
604                return defaultValue;
605            }
606            value = Short.valueOf(str);
607        }
608        return value;
609    }
610
611    /**
612     * Get named option as String.
613     *
614     * @param opts file system options to work with
615     * @param name the option name
616     * @return the option in {@code opts} or system properties, otherwise null
617     * @see #getString(FileSystemOptions, String, String)
618     *
619     * @since 2.0
620     */
621    protected String getString(final FileSystemOptions opts, final String name) {
622        return getString(opts, name, null);
623    }
624
625    /**
626     * Get named option as String.
627     *
628     * @param opts file system options to work with
629     * @param name the option name
630     * @param defaultValue value to return if option is not present
631     * @return the option in {@code opts} or system properties, otherwise {@code defaultValue}
632     *
633     * @since 2.0
634     */
635    protected String getString(final FileSystemOptions opts, final String name, final String defaultValue) {
636        String value = (String) getParam(opts, name);
637        if (value == null) {
638            value = getProperty(name);
639            if (value == null) {
640                return defaultValue;
641            }
642        }
643        return value;
644    }
645
646    /**
647     * Get the target of this configuration.
648     *
649     * @return the specific file system class
650     *
651     * @since 1.0
652     */
653    protected abstract Class<? extends FileSystem> getConfigClass();
654
655    /**
656     * Converts the given name into a System property key.
657     *
658     * @param name a name to combine with the builder prefix
659     * @return name of system property
660     *
661     * @since 2.1
662     */
663    private String toPropertyKey(final String name) {
664        return this.prefix + name;
665    }
666
667    /**
668     * Get the system property for the given name.
669     *
670     * @param name The name to lookup combined with the prefix.
671     * @return a system property or null
672     *
673     * @since 2.1
674     */
675    private String getProperty(final String name) {
676        return System.getProperty(toPropertyKey(name));
677    }
678
679}