001    /*
002     * ============================================================================
003     * GNU Lesser General Public License
004     * ============================================================================
005     *
006     * Beanlet - JSE Application Container.
007     * Copyright (C) 2006  Leon van Zantvoort
008     * 
009     * This library is free software; you can redistribute it and/or
010     * modify it under the terms of the GNU Lesser General Public
011     * License as published by the Free Software Foundation; either
012     * version 2.1 of the License, or (at your option) any later version.
013     * 
014     * This library is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
017     * Lesser General Public License for more details.
018     * 
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
022     * 
023     * Leon van Zantvoort
024     * 243 Acalanes Drive #11
025     * Sunnyvale, CA 94086
026     * USA
027     *
028     * zantvoort@users.sourceforge.net
029     * http://beanlet.org
030     */
031    package org.beanlet;
032    
033    import java.lang.annotation.ElementType;
034    import java.lang.annotation.Retention;
035    import java.lang.annotation.RetentionPolicy;
036    import java.lang.annotation.Target;
037    
038    /**
039     * <p>Declares a list of interceptors. The order in which the interceptors are 
040     * executed is equal to the order in which they are specified by this 
041     * annotation. Interceptors can be specified at both class-level and 
042     * method-level. Class-level interceptors are applied to all business methods
043     * of a beanlet, except for business methods that are marked with the 
044     * {@link ExcludeClassInterceptors} annotation. Logically, method-level 
045     * interceptors are only applied to the method at which they are specified.</p>
046     * 
047     * <p><h3>Interceptor Execution Order</h3>
048     * Class-level interceptors are placed in front of method-level interceptors.
049     * The interceptor chain does not allow the same interceptor class more than
050     * once. The classes specified by {@link #value} MUST therefore not specify 
051     * duplicate classes. If the class-level and method-level interceptor 
052     * declaration share classes, the duplicate class-level interceptors are 
053     * discarded. This allows the method-level annotation to override the order 
054     * specified at class-level. This situation is demonstrated at example (A).
055     * 
056     * <p><h3>Interceptor Instance Scope</h3>
057     * New interceptor instances are created for every beanlet instance that is 
058     * constructed. These instances are always associated with this particular 
059     * beanlet instance.
060     * A new interceptor chain is assembled for every single interceptor-enabled 
061     * method of this beanlet instance. This interceptor chain is composed of the
062     * previously created interceptor instances. The applicability of an interceptor 
063     * to more than one business method of a beanlet does not affect the 
064     * relationship between the interceptor instance and the beanlet instance. Only
065     * a single instance of the interceptor class is created per beanlet instance.
066     * </p>
067     * 
068     * <p><h3>Examples</h3>
069     * <b>(A)</b> Example of a beanlet with duplicate interceptor 
070     * ({@code InterceptorB}) declarations. The order in which these interceptors
071     * are executed for method {@code sum(int[])} is:
072     * {@code InterceptorA}, {@code InterceptorC}, {@code InterceptorB} and finally 
073     * {@code InterceptorD}.
074     * The order for {@code subtract(int, int)} is: {@code InterceptorB} 
075     * and {@code InterceptorA}. Class-level interceptor {@code InterceptorC} is not
076     * installed for this method, because the {@code ExcludeClassInterceptors} 
077     * annotation excludes class-level interceptors.
078     * 
079     * <pre>
080     * &#64;Interceptors({InterceptorA.class, InterceptorB.class, InterceptorC.class})
081     * public class ExampleBeanlet {
082     *     
083     *     &#64;Interceptors({InterceptorB.class, InterceptorD.class})
084     *     &#64;Operation 
085     *     public int add(int... values) {
086     *         int sum = 0;
087     *         for (int value : values) {
088     *             sum += value;
089     *         }
090     *         return sum;
091     *     }
092     * 
093     *     &#64;ExcludeClassInterceptors
094     *     &#64;Interceptors({InterceptorB.class, InterceptorA.class})
095     *     &#64;Operation 
096     *     public int subtract(int arg0, int arg1) {
097     *         return arg0 - arg1;
098     *     }
099     * }
100     * </pre>
101     * 
102     * <b>(B)</b> Interceptor instance scope example. Only two interceptor
103     * instances are created for an instance of beanlet {@code "example"}, namely
104     * an instance of {@code InterceptorA} and an instance of {@code InterceptorB}.
105     * Hence, method {@code doIt()}, {@code doThis(String)} and 
106     * {@code doThat(String)} share an instance of {@code InterceptorA}. 
107     * {@code InterceptorB} is shared by {@code doThis(String)} and 
108     * {@code doThat(String)}.
109     * 
110     * <pre>
111     * &#64;Interceptors({InterceptorA.class})
112     * public class ExampleBeanlet {
113     *     
114     *     &#64;Run 
115     *     public void doIt() {
116     *     }
117     * 
118     *     &#64;Interceptors(InterceptorB.class)
119     *     &#64;Operation 
120     *     public void doThis(String this) {
121     *     }
122     * 
123     *     &#64;Interceptors(InterceptorB.class)
124     *     &#64;Operation 
125     *     public void doThat(String that) {
126     *     }
127     * }
128     * </pre>
129     * </p>
130     * 
131     * <p><h3>XML Representation</h3>The following xml-fragment shows how to express this annotation in xml.<br><pre><tt>&lt;beanlets xmlns="http://beanlet.org/schema/beanlet"
132     *          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
133     *          xsi:schemaLocation="http://beanlet.org/schema/beanlet http://beanlet.org/schema/beanlet/beanlet_1_0.xsd"&gt;
134     *  &lt;beanlet name="foo" type="com.acme.Foo"&gt;
135     *    <b>&lt;interceptors type="com.acme.InterceptorA"/&gt;</b>
136     *  &lt;/beanlet&gt;
137     *&lt;/beanlets&gt;</tt></pre></p>
138     * Or alternatively:
139     * <p><pre><tt>&lt;beanlets xmlns="http://beanlet.org/schema/beanlet"
140     *          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
141     *          xsi:schemaLocation="http://beanlet.org/schema/beanlet http://beanlet.org/schema/beanlet/beanlet_1_0.xsd"&gt;
142     *  &lt;beanlet name="foo" type="com.acme.Foo"&gt;
143     *    <b>&lt;interceptors&gt;
144     *      &lt;class type="com.acme.InterceptorA"/&gt;
145     *      &lt;class type="com.acme.InterceptorB"/&gt;
146     *    &lt;/interceptors&gt;</b>
147     *  &lt;/beanlet&gt;
148     *&lt;/beanlets&gt;</tt></pre></p>
149     * @author Leon van Zantvoort
150     * @see AroundInvoke
151     * @see Interceptor
152     * @see ExcludeClassInterceptors
153     */
154    @Retention(RetentionPolicy.RUNTIME)
155    @Target({ElementType.TYPE, ElementType.METHOD})
156    public @interface Interceptors {
157        
158        /**
159         * Specifies interceptor classes. These classes are executed in the order
160         * they are specified.
161         */
162        Class<?>[] value();
163    }