001: /***
002: * Retrotranslator: a Java bytecode transformer that translates Java classes
003: * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
004: *
005: * Copyright (c) 2005 - 2008 Taras Puchko
006: * All rights reserved.
007: *
008: * Redistribution and use in source and binary forms, with or without
009: * modification, are permitted provided that the following conditions
010: * are met:
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * 3. Neither the name of the copyright holders nor the names of its
017: * contributors may be used to endorse or promote products derived from
018: * this software without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
021: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
022: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
023: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
024: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
025: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
026: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
027: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
028: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
029: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
030: * THE POSSIBILITY OF SUCH DAMAGE.
031: */package net.sf.retrotranslator.transformer;
032:
033: import java.util.*;
034: import net.sf.retrotranslator.runtime.asm.*;
035: import net.sf.retrotranslator.runtime.asm.signature.*;
036: import net.sf.retrotranslator.runtime.impl.RuntimeTools;
037:
038: /**
039: * @author Taras Puchko
040: */
041: class DuplicateInterfacesVisitor extends ClassAdapter {
042:
043: private final SystemLogger logger;
044: private final MethodCounter counter;
045:
046: public DuplicateInterfacesVisitor(ClassVisitor cv,
047: SystemLogger logger, MethodCounter counter) {
048: super (cv);
049: this .logger = logger;
050: this .counter = counter;
051: }
052:
053: public void visit(int version, int access, String name,
054: String signature, String super Name, String[] interfaces) {
055: String[] cleanInterfaces = cleanInterfaces(interfaces);
056: String cleanSignature = cleanInterfaces == interfaces ? signature
057: : cleanSignature(signature);
058: super .visit(version, access, name, cleanSignature, super Name,
059: cleanInterfaces);
060: }
061:
062: public MethodVisitor visitMethod(int access, String name,
063: String desc, String signature, String[] exceptions) {
064: counter.increment(name, desc);
065: return super .visitMethod(access, name, desc, signature,
066: exceptions);
067: }
068:
069: private String[] cleanInterfaces(String[] values) {
070: if (values == null)
071: return null;
072: Set<String> set = new LinkedHashSet<String>();
073: for (String s : values) {
074: if (!set.add(s)) {
075: logger.logForFile(Level.VERBOSE,
076: "Repetitive interface name removed: "
077: + RuntimeTools.getDisplayClassName(s));
078: }
079: }
080: if (set.size() == values.length)
081: return values;
082: return set.toArray(new String[set.size()]);
083: }
084:
085: private String cleanSignature(String signature) {
086: if (signature == null)
087: return null;
088: SignatureWriter writer = new SignatureWriter();
089: new SignatureReader(signature)
090: .accept(new SignatureCleaningVisitor(writer));
091: return writer.toString();
092: }
093:
094: private static class SignatureCleaningVisitor extends
095: SignatureAdapter {
096:
097: private Set<String> interfaces = new HashSet<String>();
098:
099: public SignatureCleaningVisitor(final SignatureVisitor visitor) {
100: super (visitor);
101: }
102:
103: private void addInterface(String signature) {
104: new SignatureReader(signature).acceptType(super
105: .visitInterface());
106: }
107:
108: public SignatureVisitor visitInterface() {
109: final SignatureWriter writer = new SignatureWriter();
110: return new SignatureAdapter(writer) {
111:
112: private String interfaceName;
113:
114: public void visitClassType(String name) {
115: super .visitClassType(name);
116: interfaceName = name;
117: }
118:
119: public void visitEnd() {
120: super.visitEnd();
121: if (interfaces.add(interfaceName)) {
122: addInterface(writer.toString());
123: }
124: }
125:
126: };
127: }
128:
129: }
130:
131: }
|