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