http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java ---------------------------------------------------------------------- diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java old mode 100644 new mode 100755 index cdc2531..0d6d28d --- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java +++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckModuleAdapter.java @@ -1,151 +1,212 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. package org.apache.tapestry5.internal.plastic.asm.util; import java.util.HashSet; - import org.apache.tapestry5.internal.plastic.asm.ModuleVisitor; import org.apache.tapestry5.internal.plastic.asm.Opcodes; /** + * A {@link ModuleVisitor} that checks that its methods are properly used. + * * @author Remi Forax */ -public final class CheckModuleAdapter extends ModuleVisitor { - private boolean end; - private final boolean isOpen; - - private final HashSet<String> requireNames = new HashSet<String>(); - private final HashSet<String> exportNames = new HashSet<String>(); - private final HashSet<String> openNames = new HashSet<String>(); - private final HashSet<String> useNames = new HashSet<String>(); - private final HashSet<String> provideNames = new HashSet<String>(); - - public CheckModuleAdapter(final ModuleVisitor mv, final boolean isOpen) { - super(Opcodes.ASM6, mv); - this.isOpen = isOpen; +public class CheckModuleAdapter extends ModuleVisitor { + /** Whether the visited module is open. */ + private final boolean isOpen; + + /** The fully qualified names of the dependencies of the visited module. */ + private final NameSet requiredModules = new NameSet("Modules requires"); + + /** The internal names of the packages exported by the visited module. */ + private final NameSet exportedPackages = new NameSet("Module exports"); + + /** The internal names of the packages opened by the visited module. */ + private final NameSet openedPackages = new NameSet("Module opens"); + + /** The internal names of the services used by the visited module. */ + private final NameSet usedServices = new NameSet("Module uses"); + + /** The internal names of the services provided by the visited module. */ + private final NameSet providedServices = new NameSet("Module provides"); + + /** The class version number. */ + int classVersion; + + /** Whether the {@link #visitEnd} method has been called. */ + private boolean visitEndCalled; + + /** + * Constructs a new {@link CheckModuleAdapter}. <i>Subclasses must not use this constructor</i>. + * Instead, they must use the {@link #CheckModuleAdapter(int, ModuleVisitor, boolean)} version. + * + * @param moduleVisitor the module visitor to which this adapter must delegate calls. + * @param isOpen whether the visited module is open. Open modules have their {@link + * Opcodes#ACC_OPEN} access flag set in {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}. + * @throws IllegalStateException If a subclass calls this constructor. + */ + public CheckModuleAdapter(final ModuleVisitor moduleVisitor, final boolean isOpen) { + this(Opcodes.ASM7, moduleVisitor, isOpen); + if (getClass() != CheckModuleAdapter.class) { + throw new IllegalStateException(); } - - @Override - public void visitRequire(String module, int access, String version) { - checkEnd(); - if (module == null) { - throw new IllegalArgumentException("require cannot be null"); - } - checkDeclared("requires", requireNames, module); - CheckClassAdapter.checkAccess(access, Opcodes.ACC_STATIC_PHASE - + Opcodes.ACC_TRANSITIVE + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_MANDATED); - super.visitRequire(module, access, version); + } + + /** + * Constructs a new {@link CheckModuleAdapter}. + * + * @param api the ASM API version implemented by this visitor. Must be one of {@link + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param moduleVisitor the module visitor to which this adapter must delegate calls. + * @param isOpen whether the visited module is open. Open modules have their {@link + * Opcodes#ACC_OPEN} access flag set in {@link org.apache.tapestry5.internal.plastic.asm.ClassVisitor#visitModule}. + */ + protected CheckModuleAdapter( + final int api, final ModuleVisitor moduleVisitor, final boolean isOpen) { + super(api, moduleVisitor); + this.isOpen = isOpen; + } + + @Override + public void visitMainClass(final String mainClass) { + // Modules can only appear in V9 or more classes. + CheckMethodAdapter.checkInternalName(Opcodes.V9, mainClass, "module main class"); + super.visitMainClass(mainClass); + } + + @Override + public void visitPackage(final String packaze) { + CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "module package"); + super.visitPackage(packaze); + } + + @Override + public void visitRequire(final String module, final int access, final String version) { + checkVisitEndNotCalled(); + CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "required module"); + requiredModules.checkNameNotAlreadyDeclared(module); + CheckClassAdapter.checkAccess( + access, + Opcodes.ACC_STATIC_PHASE + | Opcodes.ACC_TRANSITIVE + | Opcodes.ACC_SYNTHETIC + | Opcodes.ACC_MANDATED); + if (classVersion >= Opcodes.V10 + && module.equals("java.base") + && (access & (Opcodes.ACC_STATIC_PHASE | Opcodes.ACC_TRANSITIVE)) != 0) { + throw new IllegalArgumentException( + "Invalid access flags: " + + access + + " java.base can not be declared ACC_TRANSITIVE or ACC_STATIC_PHASE"); } - - @Override - public void visitExport(String packaze, int access, String... modules) { - checkEnd(); - if (packaze == null) { - throw new IllegalArgumentException("packaze cannot be null"); - } - CheckMethodAdapter.checkInternalName(packaze, "package name"); - checkDeclared("exports", exportNames, packaze); - CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC - + Opcodes.ACC_MANDATED); - if (modules != null) { - for (int i = 0; i < modules.length; i++) { - if (modules[i] == null) { - throw new IllegalArgumentException("module at index " + i + " cannot be null"); - } - } - } - super.visitExport(packaze, access, modules); + super.visitRequire(module, access, version); + } + + @Override + public void visitExport(final String packaze, final int access, final String... modules) { + checkVisitEndNotCalled(); + CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "package name"); + exportedPackages.checkNameNotAlreadyDeclared(packaze); + CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED); + if (modules != null) { + for (String module : modules) { + CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "module export to"); + } } - - @Override - public void visitOpen(String packaze, int access, String... modules) { - checkEnd(); - if (isOpen) { - throw new IllegalArgumentException("an open module can not use open directive"); - } - if (packaze == null) { - throw new IllegalArgumentException("packaze cannot be null"); - } - CheckMethodAdapter.checkInternalName(packaze, "package name"); - checkDeclared("opens", openNames, packaze); - CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC - + Opcodes.ACC_MANDATED); - if (modules != null) { - for (int i = 0; i < modules.length; i++) { - if (modules[i] == null) { - throw new IllegalArgumentException("module at index " + i + " cannot be null"); - } - } - } - super.visitOpen(packaze, access, modules); + super.visitExport(packaze, access, modules); + } + + @Override + public void visitOpen(final String packaze, final int access, final String... modules) { + checkVisitEndNotCalled(); + if (isOpen) { + throw new UnsupportedOperationException("An open module can not use open directive"); } - - @Override - public void visitUse(String service) { - checkEnd(); - CheckMethodAdapter.checkInternalName(service, "service"); - checkDeclared("uses", useNames, service); - super.visitUse(service); + CheckMethodAdapter.checkInternalName(Opcodes.V9, packaze, "package name"); + openedPackages.checkNameNotAlreadyDeclared(packaze); + CheckClassAdapter.checkAccess(access, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_MANDATED); + if (modules != null) { + for (String module : modules) { + CheckClassAdapter.checkFullyQualifiedName(Opcodes.V9, module, "module open to"); + } } - - @Override - public void visitProvide(String service, String... providers) { - checkEnd(); - CheckMethodAdapter.checkInternalName(service, "service"); - checkDeclared("provides", provideNames, service); - if (providers == null || providers.length == 0) { - throw new IllegalArgumentException("providers cannot be null or empty"); - } - for (int i = 0; i < providers.length; i++) { - CheckMethodAdapter.checkInternalName(providers[i], "provider"); - } - super.visitProvide(service, providers); + super.visitOpen(packaze, access, modules); + } + + @Override + public void visitUse(final String service) { + checkVisitEndNotCalled(); + CheckMethodAdapter.checkInternalName(Opcodes.V9, service, "service"); + usedServices.checkNameNotAlreadyDeclared(service); + super.visitUse(service); + } + + @Override + public void visitProvide(final String service, final String... providers) { + checkVisitEndNotCalled(); + CheckMethodAdapter.checkInternalName(Opcodes.V9, service, "service"); + providedServices.checkNameNotAlreadyDeclared(service); + if (providers == null || providers.length == 0) { + throw new IllegalArgumentException("Providers cannot be null or empty"); } - - @Override - public void visitEnd() { - checkEnd(); - end = true; - super.visitEnd(); + for (String provider : providers) { + CheckMethodAdapter.checkInternalName(Opcodes.V9, provider, "provider"); } + super.visitProvide(service, providers); + } - private void checkEnd() { - if (end) { - throw new IllegalStateException( - "Cannot call a visit method after visitEnd has been called"); - } + @Override + public void visitEnd() { + checkVisitEndNotCalled(); + visitEndCalled = true; + super.visitEnd(); + } + + private void checkVisitEndNotCalled() { + if (visitEndCalled) { + throw new IllegalStateException("Cannot call a visit method after visitEnd has been called"); + } + } + + private static class NameSet { + + private final String type; + private final HashSet<String> names; + + NameSet(final String type) { + this.type = type; + this.names = new HashSet<String>(); } - - private static void checkDeclared(String directive, HashSet<String> names, String name) { - if (!names.add(name)) { - throw new IllegalArgumentException(directive + " " + name + " already declared"); - } + + void checkNameNotAlreadyDeclared(final String name) { + if (!names.add(name)) { + throw new IllegalArgumentException(type + " " + name + " already declared"); + } } + } }
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/1c71aec7/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java ---------------------------------------------------------------------- diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java old mode 100644 new mode 100755 index bca5dd7..8103a10 --- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java +++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/util/CheckSignatureAdapter.java @@ -1,356 +1,359 @@ -/*** - * ASM: a very small and fast Java bytecode manipulation framework - * Copyright (c) 2000-2011 INRIA, France Telecom - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. package org.apache.tapestry5.internal.plastic.asm.util; +import java.util.EnumSet; import org.apache.tapestry5.internal.plastic.asm.Opcodes; import org.apache.tapestry5.internal.plastic.asm.signature.SignatureVisitor; /** * A {@link SignatureVisitor} that checks that its methods are properly used. - * + * * @author Eric Bruneton */ public class CheckSignatureAdapter extends SignatureVisitor { - /** - * Type to be used to check class signatures. See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) - * CheckSignatureAdapter}. - */ - public static final int CLASS_SIGNATURE = 0; - - /** - * Type to be used to check method signatures. See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) - * CheckSignatureAdapter}. - */ - public static final int METHOD_SIGNATURE = 1; - - /** - * Type to be used to check type signatures.See - * {@link #CheckSignatureAdapter(int, SignatureVisitor) - * CheckSignatureAdapter}. - */ - public static final int TYPE_SIGNATURE = 2; - - private static final int EMPTY = 1; - - private static final int FORMAL = 2; - - private static final int BOUND = 4; - - private static final int SUPER = 8; - - private static final int PARAM = 16; - - private static final int RETURN = 32; - - private static final int SIMPLE_TYPE = 64; - - private static final int CLASS_TYPE = 128; - - private static final int END = 256; - - /** - * Type of the signature to be checked. - */ - private final int type; - - /** - * State of the automaton used to check the order of method calls. - */ - private int state; - - /** - * <tt>true</tt> if the checked type signature can be 'V'. - */ - private boolean canBeVoid; - - /** - * The visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. - */ - private final SignatureVisitor sv; - - /** - * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must - * not use this constructor</i>. Instead, they must use the - * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version. - * - * @param type - * the type of signature to be checked. See - * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and - * {@link #TYPE_SIGNATURE}. - * @param sv - * the visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. - */ - public CheckSignatureAdapter(final int type, final SignatureVisitor sv) { - this(Opcodes.ASM6, type, sv); + /** + * Type to be used to check class signatures. See {@link #CheckSignatureAdapter(int, + * SignatureVisitor)}. + */ + public static final int CLASS_SIGNATURE = 0; + + /** + * Type to be used to check method signatures. See {@link #CheckSignatureAdapter(int, + * SignatureVisitor)}. + */ + public static final int METHOD_SIGNATURE = 1; + + /** + * Type to be used to check type signatures.See {@link #CheckSignatureAdapter(int, + * SignatureVisitor)}. + */ + public static final int TYPE_SIGNATURE = 2; + + /** The valid automaton states for a {@link #visitFormalTypeParameter} method call. */ + private static final EnumSet<State> VISIT_FORMAL_TYPE_PARAMETER_STATES = + EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND); + + /** The valid automaton states for a {@link #visitClassBound} method call. */ + private static final EnumSet<State> VISIT_CLASS_BOUND_STATES = EnumSet.of(State.FORMAL); + + /** The valid automaton states for a {@link #visitInterfaceBound} method call. */ + private static final EnumSet<State> VISIT_INTERFACE_BOUND_STATES = + EnumSet.of(State.FORMAL, State.BOUND); + + /** The valid automaton states for a {@link #visitSuperclass} method call. */ + private static final EnumSet<State> VISIT_SUPER_CLASS_STATES = + EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND); + + /** The valid automaton states for a {@link #visitInterface} method call. */ + private static final EnumSet<State> VISIT_INTERFACE_STATES = EnumSet.of(State.SUPER); + + /** The valid automaton states for a {@link #visitParameterType} method call. */ + private static final EnumSet<State> VISIT_PARAMETER_TYPE_STATES = + EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND, State.PARAM); + + /** The valid automaton states for a {@link #visitReturnType} method call. */ + private static final EnumSet<State> VISIT_RETURN_TYPE_STATES = + EnumSet.of(State.EMPTY, State.FORMAL, State.BOUND, State.PARAM); + + /** The valid automaton states for a {@link #visitExceptionType} method call. */ + private static final EnumSet<State> VISIT_EXCEPTION_TYPE_STATES = EnumSet.of(State.RETURN); + + /** The possible states of the automaton used to check the order of method calls. */ + private enum State { + EMPTY, + FORMAL, + BOUND, + SUPER, + PARAM, + RETURN, + SIMPLE_TYPE, + CLASS_TYPE, + END; + } + + private static final String INVALID = "Invalid "; + + /** The type of the visited signature. */ + private final int type; + + /** The current state of the automaton used to check the order of method calls. */ + private State state; + + /** Whether the visited signature can be 'V'. */ + private boolean canBeVoid; + + /** The visitor to which this adapter must delegate calls. May be {@literal null}. */ + private final SignatureVisitor signatureVisitor; + + /** + * Constructs a new {@link CheckSignatureAdapter}. <i>Subclasses must not use this + * constructor</i>. Instead, they must use the {@link #CheckSignatureAdapter(int, int, + * SignatureVisitor)} version. + * + * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link + * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}. + * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal + * null}. + */ + public CheckSignatureAdapter(final int type, final SignatureVisitor signatureVisitor) { + this(Opcodes.ASM7, type, signatureVisitor); + } + + /** + * Constructs a new {@link CheckSignatureAdapter}. + * + * @param api the ASM API version implemented by this visitor. Must be one of {@link + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7}. + * @param type the type of signature to be checked. See {@link #CLASS_SIGNATURE}, {@link + * #METHOD_SIGNATURE} and {@link #TYPE_SIGNATURE}. + * @param signatureVisitor the visitor to which this adapter must delegate calls. May be {@literal + * null}. + */ + protected CheckSignatureAdapter( + final int api, final int type, final SignatureVisitor signatureVisitor) { + super(api); + this.type = type; + this.state = State.EMPTY; + this.signatureVisitor = signatureVisitor; + } + + // class and method signatures + + @Override + public void visitFormalTypeParameter(final String name) { + if (type == TYPE_SIGNATURE || !VISIT_FORMAL_TYPE_PARAMETER_STATES.contains(state)) { + throw new IllegalStateException(); } - - /** - * Creates a new {@link CheckSignatureAdapter} object. - * - * @param api - * the ASM API version implemented by this visitor. Must be one - * of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. - * @param type - * the type of signature to be checked. See - * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and - * {@link #TYPE_SIGNATURE}. - * @param sv - * the visitor to which this adapter must delegate calls. May be - * <tt>null</tt>. - */ - protected CheckSignatureAdapter(final int api, final int type, - final SignatureVisitor sv) { - super(api); - this.type = type; - this.state = EMPTY; - this.sv = sv; + checkIdentifier(name, "formal type parameter"); + state = State.FORMAL; + if (signatureVisitor != null) { + signatureVisitor.visitFormalTypeParameter(name); } + } - // class and method signatures - - @Override - public void visitFormalTypeParameter(final String name) { - if (type == TYPE_SIGNATURE - || (state != EMPTY && state != FORMAL && state != BOUND)) { - throw new IllegalStateException(); - } - checkIdentifier(name, "formal type parameter"); - state = FORMAL; - if (sv != null) { - sv.visitFormalTypeParameter(name); - } + @Override + public SignatureVisitor visitClassBound() { + if (type == TYPE_SIGNATURE || !VISIT_CLASS_BOUND_STATES.contains(state)) { + throw new IllegalStateException(); } - - @Override - public SignatureVisitor visitClassBound() { - if (state != FORMAL) { - throw new IllegalStateException(); - } - state = BOUND; - SignatureVisitor v = sv == null ? null : sv.visitClassBound(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + state = State.BOUND; + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitClassBound()); + } + + @Override + public SignatureVisitor visitInterfaceBound() { + if (type == TYPE_SIGNATURE || !VISIT_INTERFACE_BOUND_STATES.contains(state)) { + throw new IllegalArgumentException(); } + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitInterfaceBound()); + } - @Override - public SignatureVisitor visitInterfaceBound() { - if (state != FORMAL && state != BOUND) { - throw new IllegalArgumentException(); - } - SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + // class signatures + + @Override + public SignatureVisitor visitSuperclass() { + if (type != CLASS_SIGNATURE || !VISIT_SUPER_CLASS_STATES.contains(state)) { + throw new IllegalArgumentException(); + } + state = State.SUPER; + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitSuperclass()); + } + + @Override + public SignatureVisitor visitInterface() { + if (type != CLASS_SIGNATURE || !VISIT_INTERFACE_STATES.contains(state)) { + throw new IllegalStateException(); } + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitInterface()); + } - // class signatures + // method signatures - @Override - public SignatureVisitor visitSuperclass() { - if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0) { - throw new IllegalArgumentException(); - } - state = SUPER; - SignatureVisitor v = sv == null ? null : sv.visitSuperclass(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + @Override + public SignatureVisitor visitParameterType() { + if (type != METHOD_SIGNATURE || !VISIT_PARAMETER_TYPE_STATES.contains(state)) { + throw new IllegalArgumentException(); } - - @Override - public SignatureVisitor visitInterface() { - if (state != SUPER) { - throw new IllegalStateException(); - } - SignatureVisitor v = sv == null ? null : sv.visitInterface(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + state = State.PARAM; + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitParameterType()); + } + + @Override + public SignatureVisitor visitReturnType() { + if (type != METHOD_SIGNATURE || !VISIT_RETURN_TYPE_STATES.contains(state)) { + throw new IllegalArgumentException(); } - - // method signatures - - @Override - public SignatureVisitor visitParameterType() { - if (type != METHOD_SIGNATURE - || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) { - throw new IllegalArgumentException(); - } - state = PARAM; - SignatureVisitor v = sv == null ? null : sv.visitParameterType(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + state = State.RETURN; + CheckSignatureAdapter checkSignatureAdapter = + new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitReturnType()); + checkSignatureAdapter.canBeVoid = true; + return checkSignatureAdapter; + } + + @Override + public SignatureVisitor visitExceptionType() { + if (type != METHOD_SIGNATURE || !VISIT_EXCEPTION_TYPE_STATES.contains(state)) { + throw new IllegalStateException(); } + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitExceptionType()); + } - @Override - public SignatureVisitor visitReturnType() { - if (type != METHOD_SIGNATURE - || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0) { - throw new IllegalArgumentException(); - } - state = RETURN; - SignatureVisitor v = sv == null ? null : sv.visitReturnType(); - CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v); - cv.canBeVoid = true; - return cv; - } + // type signatures - @Override - public SignatureVisitor visitExceptionType() { - if (state != RETURN) { - throw new IllegalStateException(); - } - SignatureVisitor v = sv == null ? null : sv.visitExceptionType(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + @Override + public void visitBaseType(final char descriptor) { + if (type != TYPE_SIGNATURE || state != State.EMPTY) { + throw new IllegalStateException(); } - - // type signatures - - @Override - public void visitBaseType(final char descriptor) { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - if (descriptor == 'V') { - if (!canBeVoid) { - throw new IllegalArgumentException(); - } - } else { - if ("ZCBSIFJD".indexOf(descriptor) == -1) { - throw new IllegalArgumentException(); - } - } - state = SIMPLE_TYPE; - if (sv != null) { - sv.visitBaseType(descriptor); - } + if (descriptor == 'V') { + if (!canBeVoid) { + throw new IllegalArgumentException(); + } + } else { + if ("ZCBSIFJD".indexOf(descriptor) == -1) { + throw new IllegalArgumentException(); + } } - - @Override - public void visitTypeVariable(final String name) { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - checkIdentifier(name, "type variable"); - state = SIMPLE_TYPE; - if (sv != null) { - sv.visitTypeVariable(name); - } + state = State.SIMPLE_TYPE; + if (signatureVisitor != null) { + signatureVisitor.visitBaseType(descriptor); } + } - @Override - public SignatureVisitor visitArrayType() { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - state = SIMPLE_TYPE; - SignatureVisitor v = sv == null ? null : sv.visitArrayType(); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + @Override + public void visitTypeVariable(final String name) { + if (type != TYPE_SIGNATURE || state != State.EMPTY) { + throw new IllegalStateException(); } - - @Override - public void visitClassType(final String name) { - if (type != TYPE_SIGNATURE || state != EMPTY) { - throw new IllegalStateException(); - } - checkClassName(name, "class name"); - state = CLASS_TYPE; - if (sv != null) { - sv.visitClassType(name); - } + checkIdentifier(name, "type variable"); + state = State.SIMPLE_TYPE; + if (signatureVisitor != null) { + signatureVisitor.visitTypeVariable(name); } + } - @Override - public void visitInnerClassType(final String name) { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - checkIdentifier(name, "inner class name"); - if (sv != null) { - sv.visitInnerClassType(name); - } + @Override + public SignatureVisitor visitArrayType() { + if (type != TYPE_SIGNATURE || state != State.EMPTY) { + throw new IllegalStateException(); + } + state = State.SIMPLE_TYPE; + return new CheckSignatureAdapter( + TYPE_SIGNATURE, signatureVisitor == null ? null : signatureVisitor.visitArrayType()); + } + + @Override + public void visitClassType(final String name) { + if (type != TYPE_SIGNATURE || state != State.EMPTY) { + throw new IllegalStateException(); } + checkClassName(name, "class name"); + state = State.CLASS_TYPE; + if (signatureVisitor != null) { + signatureVisitor.visitClassType(name); + } + } - @Override - public void visitTypeArgument() { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - if (sv != null) { - sv.visitTypeArgument(); - } + @Override + public void visitInnerClassType(final String name) { + if (state != State.CLASS_TYPE) { + throw new IllegalStateException(); + } + checkIdentifier(name, "inner class name"); + if (signatureVisitor != null) { + signatureVisitor.visitInnerClassType(name); } + } - @Override - public SignatureVisitor visitTypeArgument(final char wildcard) { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - if ("+-=".indexOf(wildcard) == -1) { - throw new IllegalArgumentException(); - } - SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard); - return new CheckSignatureAdapter(TYPE_SIGNATURE, v); + @Override + public void visitTypeArgument() { + if (state != State.CLASS_TYPE) { + throw new IllegalStateException(); + } + if (signatureVisitor != null) { + signatureVisitor.visitTypeArgument(); } + } - @Override - public void visitEnd() { - if (state != CLASS_TYPE) { - throw new IllegalStateException(); - } - state = END; - if (sv != null) { - sv.visitEnd(); - } + @Override + public SignatureVisitor visitTypeArgument(final char wildcard) { + if (state != State.CLASS_TYPE) { + throw new IllegalStateException(); } + if ("+-=".indexOf(wildcard) == -1) { + throw new IllegalArgumentException(); + } + return new CheckSignatureAdapter( + TYPE_SIGNATURE, + signatureVisitor == null ? null : signatureVisitor.visitTypeArgument(wildcard)); + } + + @Override + public void visitEnd() { + if (state != State.CLASS_TYPE) { + throw new IllegalStateException(); + } + state = State.END; + if (signatureVisitor != null) { + signatureVisitor.visitEnd(); + } + } - private void checkClassName(final String name, final String msg) { - if (name == null || name.length() == 0) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not be null or empty)"); - } - for (int i = 0; i < name.length(); ++i) { - if (".;[<>:".indexOf(name.charAt(i)) != -1) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not contain . ; [ < > or :): " + name); - } - } + private void checkClassName(final String name, final String message) { + if (name == null || name.length() == 0) { + throw new IllegalArgumentException(INVALID + message + " (must not be null or empty)"); } + for (int i = 0; i < name.length(); ++i) { + if (".;[<>:".indexOf(name.charAt(i)) != -1) { + throw new IllegalArgumentException( + INVALID + message + " (must not contain . ; [ < > or :): " + name); + } + } + } - private void checkIdentifier(final String name, final String msg) { - if (name == null || name.length() == 0) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not be null or empty)"); - } - for (int i = 0; i < name.length(); ++i) { - if (".;[/<>:".indexOf(name.charAt(i)) != -1) { - throw new IllegalArgumentException("Invalid " + msg - + " (must not contain . ; [ / < > or :): " + name); - } - } + private void checkIdentifier(final String name, final String message) { + if (name == null || name.length() == 0) { + throw new IllegalArgumentException(INVALID + message + " (must not be null or empty)"); + } + for (int i = 0; i < name.length(); ++i) { + if (".;[/<>:".indexOf(name.charAt(i)) != -1) { + throw new IllegalArgumentException( + INVALID + message + " (must not contain . ; [ / < > or :): " + name); + } } + } }
