View Javadoc
1   /*
2    * Copyright (C) 2005-2015 Schlichtherle IT Services.
3    * All rights reserved. Use is subject to license terms.
4    */
5   package net.java.truevfs.access;
6   
7   import java.lang.annotation.*;
8   import static java.lang.annotation.ElementType.*;
9   import java.util.Locale;
10  import net.java.truevfs.kernel.spec.*;
11  
12  /**
13   * Indicates a feature which requires a certain experience level for safe use.
14   * In most cases, using an expert feature is a code smell and you should
15   * refactor your code to avoid it in order to stay safe.
16   * However, some valid use cases exist for an expert feature
17   * (otherwise it should have been {@code @Deprecated}).
18   * These use cases are not explained here because a true expert will know them!
19   * <p>
20   * As of TrueVFS 0.10, using an expert feature is not checked.
21   * However, future versions of TrueVFS might include tools to issue a warning
22   * whenever an expert feature is unintentionally used - similar to the way
23   * {@code javac} treats the {@code @Deprecated} annotation.
24   *
25   * @since  TrueVFS 0.10
26   * @author Christian Schlichtherle
27   */
28  @Documented
29  @Inherited
30  @Target({ CONSTRUCTOR, METHOD })
31  public @interface ExpertFeature {
32  
33      /** Returns the experience level required to safely use this feature. */
34      Level level() default Level.MASTER;
35  
36      /** Returns the reasons why this feature should only be used by an expert. */
37      Reason[] value();
38  
39      /**
40       * Returns a warning message for future use, for example in static code
41       * analysis.
42       */
43      String warning() default "Using this %s requires %s experience because %s!";
44  
45      /** The experience level required to safely use an expert feature. */
46      enum Level {
47          INTERMEDIATE, MASTER;
48  
49          @Override
50          public String toString() {
51              return name().toLowerCase(Locale.ROOT).replace('_', ' ');
52          }
53      }
54  
55      /** The reason why a feature should only be used by an expert. */
56      enum Reason {
57  
58          /**
59           * Injecting a different archive detector for the same virtual file
60           * system path may cause data corruption.
61           * This is because the behavior of the virtual file system is not only
62           * a pure function of the operation parameters, but also depends on the
63           * {@linkplain TConfig#current() current configuration}, the state
64           * of the virtual file system and ultimately the state of the
65           * underlying host or network file system.
66           * <p>
67           * The state of the virtual file system very much depends on the
68           * archive detector which has been previously used to access the same
69           * virtual file system path.
70           * If there is a mismatch between the injected archive detector and the
71           * previously used archive detector, then the result of an operation
72           * is hard to predict but you can expect to see spurious
73           * <strong>false positive</strong> or
74           * <strong>false negative</strong> archive file detection or even
75           * <strong>data corruption</strong> up to the point of
76           * <strong>total data loss</strong>!
77           * <p>
78           * This is particularly true for multithreaded applications: If a
79           * thread changes the archive detector which is associated with a given
80           * virtual file system path, then another thread may get an unexpected
81           * result when accessing the same virtual file system path, with all
82           * the after effects described above.
83           * <p>
84           * Now that you have been warned, here is a high-level strategy for
85           * effectively associating a different archive detector to a given
86           * virtual file system path:
87           * <ol>
88           * <li>Lock out any other thread from concurrently accessing the
89           *     virtual file system path.
90           * <li>Totally clear the state associated with the virtual file system
91           *     path in the Kernel by calling the method {@link TVFS#umount()}.
92           *     Your best choice is the umount method with no parameters.
93           *     However, if you have to do this selectively, make sure the
94           *     filter parameter really covers the virtual file system path you
95           *     want to access and the effective options are
96           *     {@link FsSyncOptions#UMOUNT}.
97           * <li>Now access the virtual file system path with the new archive
98           *     detector.
99           *     Depending on the particular archive detector, this will trigger
100          *     mounting the archive file system by the Kernel.
101          *     The new archive detector is then associated with the given file
102          *     system path.
103          * <li>Depending on which operation you have performed and whether the
104          *     change of the archive detector shall be persistent or not, you
105          *     may need to repeat the second step.
106          * <li>Unlock access to the virtual file system path for other threads
107          *     to see the result.
108          *     Mind you that these threads may still be using the old archive
109          *     detector.
110          * </ol>
111          * <p>
112          * I leave it up to you to figure the details - again, this is an
113          * expert feature!
114          *
115          * @see <a href="http://truezip.java.net/truezip-file/usage.html#Third_Party_Access">Third Party Access</a>
116          */
117         INJECTING_A_DIFFERENT_DETECTOR_FOR_THE_SAME_PATH_MAY_CORRUPT_DATA,
118 
119         /**
120          * The presence or absence of some synchronization options may yield
121          * unwanted side effects.
122          * For example, if the {@link FsSyncOption#CLEAR_CACHE} is absent, then
123          * the selective entry cache doesn' get cleared and hence the state
124          * associated with a particular file system path may not get totally
125          * cleared.
126          * On the other hand, the presence of the
127          * {@link FsSyncOption#FORCE_CLOSE_IO} will forcibly close any open
128          * streams and channels (after some timeout), regardless if they are
129          * currently used by other threads or not.
130          */
131         THE_PRESENCE_OR_ABSENCE_OF_SOME_OPTIONS_MAY_YIELD_UNWANTED_SIDE_EFFECTS;
132 
133         @Override
134         public String toString() {
135             return name().toLowerCase(Locale.ROOT).replace('_', ' ');
136         }
137     }
138 }