001/***
002 * ASM: a very small and fast Java bytecode manipulation framework
003 * Copyright (c) 2000-2011 INRIA, France Telecom
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions
008 * are met:
009 * 1. Redistributions of source code must retain the above copyright
010 *    notice, this list of conditions and the following disclaimer.
011 * 2. Redistributions in binary form must reproduce the above copyright
012 *    notice, this list of conditions and the following disclaimer in the
013 *    documentation and/or other materials provided with the distribution.
014 * 3. Neither the name of the copyright holders nor the names of its
015 *    contributors may be used to endorse or promote products derived from
016 *    this software without specific prior written permission.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028 * THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package io.ebean.enhance.asm;
031
032/**
033 * A visitor to visit a Java module. The methods of this class must be called in
034 * the following order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> |
035 * <tt>visitRequire</tt> | <tt>visitExport</tt> | <tt>visitOpen</tt> |
036 * <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
037 * 
038 * The methods {@link #visitRequire(String, int, String)}, {@link #visitExport(String, int, String...)},
039 * {@link #visitOpen(String, int, String...)} and {@link #visitPackage(String)}
040 * take as parameter a package name or a module name. Unlike the other names which are internal names
041 * (names separated by slash), module and package names are qualified names (names separated by dot).
042 * 
043 * @author Remi Forax
044 */
045public abstract class ModuleVisitor {
046    /**
047     * The ASM API version implemented by this visitor. The value of this field
048     * must be {@link Opcodes#ASM6}.
049     */
050    protected final int api;
051    
052    /**
053     * The module visitor to which this visitor must delegate method calls. May
054     * be null.
055     */
056    protected ModuleVisitor mv;
057    
058    /**
059     * Constructs a new {@link ModuleVisitor}.
060     * 
061     * @param api
062     *            the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
063     */
064    public ModuleVisitor(final int api) {
065        this(api, null);
066    }
067
068    /**
069     * Constructs a new {@link ModuleVisitor}.
070     * 
071     * @param api
072     *            the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
073     * @param mv
074     *            the module visitor to which this visitor must delegate method
075     *            calls. May be null.
076     */
077    public ModuleVisitor(final int api, final ModuleVisitor mv) {
078        if (api != Opcodes.ASM6) {
079            throw new IllegalArgumentException();
080        }
081        this.api = api;
082        this.mv = mv;
083    }
084    
085    /**
086     * Visit the main class of the current module.
087     * 
088     * @param mainClass the internal name of the main class of the current module.
089     */
090    public void visitMainClass(String mainClass) {
091        if (mv != null) {
092            mv.visitMainClass(mainClass);
093        }
094    }
095    
096    /**
097     * Visit a package of the current module.
098     * 
099     * @param packaze the qualified name of a package.
100     */
101    public void visitPackage(String packaze) {
102        if (mv != null) {
103            mv.visitPackage(packaze);
104        }
105    }
106    
107    /**
108     * Visits a dependence of the current module.
109     * 
110     * @param module the qualified name of the dependence.
111     * @param access the access flag of the dependence among
112     *        ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
113     *        and ACC_MANDATED.
114     * @param version the module version at compile time or null.
115     */
116    public void visitRequire(String module, int access, String version) {
117        if (mv != null) {
118            mv.visitRequire(module, access, version);
119        }
120    }
121    
122    /**
123     * Visit an exported package of the current module.
124     * 
125     * @param packaze the qualified name of the exported package.
126     * @param access the access flag of the exported package,
127     *        valid values are among {@code ACC_SYNTHETIC} and
128     *        {@code ACC_MANDATED}.
129     * @param modules the qualified names of the modules that can access to
130     *        the public classes of the exported package or
131     *        <tt>null</tt>.
132     */
133    public void visitExport(String packaze, int access, String... modules) {
134        if (mv != null) {
135            mv.visitExport(packaze, access, modules);
136        }
137    }
138    
139    /**
140     * Visit an open package of the current module.
141     * 
142     * @param packaze the qualified name of the opened package.
143     * @param access the access flag of the opened package,
144     *        valid values are among {@code ACC_SYNTHETIC} and
145     *        {@code ACC_MANDATED}.
146     * @param modules the qualified names of the modules that can use deep
147     *        reflection to the classes of the open package or
148     *        <tt>null</tt>.
149     */
150    public void visitOpen(String packaze, int access, String... modules) {
151        if (mv != null) {
152            mv.visitOpen(packaze, access, modules);
153        }
154    }
155    
156    /**
157     * Visit a service used by the current module.
158     * The name must be the internal name of an interface or a class.
159     * 
160     * @param service the internal name of the service.
161     */
162    public void visitUse(String service) {
163        if (mv != null) {
164            mv.visitUse(service);
165        }
166    }
167    
168    /**
169     * Visit an implementation of a service.
170     * 
171     * @param service the internal name of the service
172     * @param providers the internal names of the implementations
173     *        of the service (there is at least one provider).
174     */
175    public void visitProvide(String service, String... providers) {
176        if (mv != null) {
177            mv.visitProvide(service, providers);
178        }
179    }
180    
181    /**
182     * Visits the end of the module. This method, which is the last one to be
183     * called, is used to inform the visitor that everything have been visited.
184     */
185    public void visitEnd() {
186        if (mv != null) {
187            mv.visitEnd();
188        }
189    }
190}