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.tree;
031
032import io.ebean.enhance.asm.ClassVisitor;
033import io.ebean.enhance.asm.ModuleVisitor;
034import io.ebean.enhance.asm.Opcodes;
035
036import java.util.ArrayList;
037import java.util.List;
038
039/**
040 * A node that represents a module declaration.
041 * 
042 * @author Remi Forax
043 */
044public class ModuleNode extends ModuleVisitor {
045    /**
046     * Module name
047     */
048    public String name;
049    
050    /**
051     * Module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
052     *            and {@code ACC_MANDATED}.
053     */
054    public int access;
055    
056    /**
057     * Version of the module.
058     * May be <tt>null</tt>.
059     */
060    public String version;
061    
062    /**
063     * Name of the main class in internal form
064     * May be <tt>null</tt>.
065     */
066    public String mainClass;
067    
068    /**
069     * A list of packages that are declared by the current module.
070     * May be <tt>null</tt>.
071     */
072    public List<String> packages;
073    
074    /**
075     * A list of modules can are required by the current module.
076     * May be <tt>null</tt>.
077     */
078    public List<ModuleRequireNode> requires;
079    
080    /**
081     * A list of packages that are exported by the current module.
082     * May be <tt>null</tt>.
083     */
084    public List<ModuleExportNode> exports;
085    
086    /**
087     * A list of packages that are opened by the current module.
088     * May be <tt>null</tt>.
089     */
090    public List<ModuleOpenNode> opens;
091    
092    /**
093     * A list of classes in their internal forms that are used
094     * as a service by the current module. May be <tt>null</tt>.
095     */
096    public List<String> uses;
097   
098    /**
099     * A list of services along with their implementations provided
100     * by the current module. May be <tt>null</tt>.
101     */
102    public List<ModuleProvideNode> provides;
103
104    public ModuleNode(final String name, final int access,
105            final String version) {
106        super(Opcodes.ASM6);
107        this.name = name;
108        this.access = access;
109        this.version = version;
110    }
111    
112    public ModuleNode(final int api,
113      final String name,
114      final int access,
115      final String version,
116      final List<ModuleRequireNode> requires,
117      final List<ModuleExportNode> exports,
118      final List<ModuleOpenNode> opens,
119      final List<String> uses,
120      final List<ModuleProvideNode> provides) {
121        super(api);
122        this.name = name;
123        this.access = access;
124        this.version = version;
125        this.requires = requires;
126        this.exports = exports;
127        this.opens = opens;
128        this.uses = uses;
129        this.provides = provides;
130        if (getClass() != ModuleNode.class) {
131            throw new IllegalStateException();
132        }
133    }
134    
135    @Override
136    public void visitMainClass(String mainClass) {
137        this.mainClass = mainClass;
138    }
139    
140    @Override
141    public void visitPackage(String packaze) {
142        if (packages == null) {
143            packages = new ArrayList<String>(5);
144        }
145        packages.add(packaze);
146    }
147    
148    @Override
149    public void visitRequire(String module, int access, String version) {
150        if (requires == null) {
151            requires = new ArrayList<ModuleRequireNode>(5);
152        }
153        requires.add(new ModuleRequireNode(module, access, version));
154    }
155    
156    @Override
157    public void visitExport(String packaze, int access, String... modules) {
158        if (exports == null) {
159            exports = new ArrayList<ModuleExportNode>(5);
160        }
161        List<String> moduleList = null;
162        if (modules != null) {
163            moduleList = new ArrayList<String>(modules.length);
164            for (int i = 0; i < modules.length; i++) {
165                moduleList.add(modules[i]);
166            }
167        }
168        exports.add(new ModuleExportNode(packaze, access, moduleList));
169    }
170    
171    @Override
172    public void visitOpen(String packaze, int access, String... modules) {
173        if (opens == null) {
174            opens = new ArrayList<ModuleOpenNode>(5);
175        }
176        List<String> moduleList = null;
177        if (modules != null) {
178            moduleList = new ArrayList<String>(modules.length);
179            for (int i = 0; i < modules.length; i++) {
180                moduleList.add(modules[i]);
181            }
182        }
183        opens.add(new ModuleOpenNode(packaze, access, moduleList));
184    }
185    
186    @Override
187    public void visitUse(String service) {
188        if (uses == null) {
189            uses = new ArrayList<String>(5);
190        }
191        uses.add(service);
192    }
193    
194    @Override
195    public void visitProvide(String service, String... providers) {
196        if (provides == null) {
197            provides = new ArrayList<ModuleProvideNode>(5);
198        }
199        ArrayList<String> providerList =
200                new ArrayList<String>(providers.length);
201        for (int i = 0; i < providers.length; i++) {
202                providerList.add(providers[i]);
203        }
204        provides.add(new ModuleProvideNode(service, providerList));
205    }
206    
207    @Override
208    public void visitEnd() {
209    }
210    
211    public void accept(final ClassVisitor cv) {
212        ModuleVisitor mv = cv.visitModule(name, access, version);
213        if (mv == null) {
214            return;
215        }
216        if (mainClass != null) {
217            mv.visitMainClass(mainClass);
218        }
219        if (packages != null) {
220            for (int i = 0; i < packages.size(); i++) {
221                mv.visitPackage(packages.get(i));
222            }
223        }
224        
225        if (requires != null) {
226            for (int i = 0; i < requires.size(); i++) {
227                requires.get(i).accept(mv);
228            }
229        }
230        if (exports != null) {
231            for (int i = 0; i < exports.size(); i++) {
232                exports.get(i).accept(mv);
233            }
234        }
235        if (opens != null) {
236            for (int i = 0; i < opens.size(); i++) {
237                opens.get(i).accept(mv);
238            }
239        }
240        if (uses != null) {
241            for (int i = 0; i < uses.size(); i++) {
242                mv.visitUse(uses.get(i));
243            }
244        }
245        if (provides != null) {
246            for (int i = 0; i < provides.size(); i++) {
247                provides.get(i).accept(mv);
248            }
249        }
250    }
251}