| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.flex.abc; |
| |
| import org.apache.flex.abc.instructionlist.InstructionList; |
| import org.apache.flex.abc.semantics.ClassInfo; |
| import org.apache.flex.abc.semantics.ExceptionInfo; |
| import org.apache.flex.abc.semantics.InstanceInfo; |
| import org.apache.flex.abc.semantics.Instruction; |
| import org.apache.flex.abc.semantics.Label; |
| import org.apache.flex.abc.semantics.Metadata; |
| import org.apache.flex.abc.semantics.MethodBodyInfo; |
| import org.apache.flex.abc.semantics.MethodInfo; |
| import org.apache.flex.abc.semantics.Name; |
| import org.apache.flex.abc.semantics.Namespace; |
| import org.apache.flex.abc.semantics.Nsset; |
| import org.apache.flex.abc.semantics.ScriptInfo; |
| import org.apache.flex.abc.semantics.Trait; |
| import org.apache.flex.abc.semantics.Traits; |
| import org.apache.flex.abc.visitors.IABCVisitor; |
| import org.apache.flex.abc.visitors.IClassVisitor; |
| import org.apache.flex.abc.visitors.IMetadataVisitor; |
| import org.apache.flex.abc.visitors.IMethodBodyVisitor; |
| import org.apache.flex.abc.visitors.IMethodVisitor; |
| import org.apache.flex.abc.visitors.IScriptVisitor; |
| import org.apache.flex.abc.visitors.ITraitVisitor; |
| import org.apache.flex.abc.visitors.ITraitsVisitor; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * This class implements an IABCVisitor which will simply collect |
| * all of the structures of an ABC block, such as constant pools, method |
| * infos, class infos, etc into various pools so they can be processed later |
| * in a different order than the IABCVisitor events are received in. |
| */ |
| public class PoolingABCVisitor implements IABCVisitor |
| { |
| public PoolingABCVisitor () |
| { |
| } |
| |
| public void visit (int majorVersion, int minorVersion) |
| { |
| this.majorVersion = majorVersion; |
| this.minorVersion = minorVersion; |
| } |
| |
| public IScriptVisitor visitScript () |
| { |
| return new ScriptVisitor(); |
| } |
| |
| public IClassVisitor visitClass (InstanceInfo iinfo, ClassInfo cinfo) |
| { |
| return new ClassVisitor(iinfo, cinfo); |
| } |
| |
| public IMethodVisitor visitMethod (MethodInfo minfo) |
| { |
| return new MethodVisitor(minfo); |
| } |
| |
| @Override |
| public void visitPooledDouble (Double d) |
| { |
| this.doublePool.add(d); |
| } |
| |
| @Override |
| public void visitPooledInt (Integer i) |
| { |
| this.intPool.add(i); |
| } |
| |
| @Override |
| public void visitPooledMetadata (Metadata md) |
| { |
| this.metadataPool.add(md); |
| } |
| |
| @Override |
| public void visitPooledName (Name n) |
| { |
| this.namePool.add(n); |
| } |
| |
| @Override |
| public void visitPooledNamespace (Namespace ns) |
| { |
| this.nsPool.add(ns); |
| |
| if (ns != null) |
| visitPooledString(ns.getVersionedName()); |
| } |
| |
| @Override |
| public void visitPooledNsSet (Nsset nss) |
| { |
| this.nssetPool.add(nss); |
| |
| if (nss != null) |
| { |
| for (Namespace ns : nss) |
| { |
| visitPooledNamespace(ns); |
| } |
| } |
| } |
| |
| @Override |
| public void visitPooledString (String s) |
| { |
| this.stringPool.add(s); |
| } |
| |
| @Override |
| public void visitPooledUInt (Long l) |
| { |
| this.uintPool.add(l); |
| } |
| |
| private int majorVersion; |
| |
| private int minorVersion; |
| |
| |
| private final Pool<Name> namePool = new Pool<Name>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<String> stringPool = new Pool<String>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<Integer> intPool = new Pool<Integer>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<Long> uintPool = new Pool<Long>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<Double> doublePool = new Pool<Double>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<Namespace> nsPool = new Pool<Namespace>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<Nsset> nssetPool = new Pool<Nsset>(Pool.DefaultType.HasDefaultZero); |
| |
| private final Pool<Metadata> metadataPool = new Pool<Metadata>(Pool.DefaultType.NoDefaultZero); |
| |
| private List<ScriptInfo> scriptInfos = new ArrayList<ScriptInfo>(); |
| private List<MethodBodyInfo> methodBodies = new ArrayList<MethodBodyInfo>(); |
| private EntryOrderedStore<MethodInfo> methodInfos = new EntryOrderedStore<MethodInfo>(); |
| private List<ClassVisitor> definedClasses = new ArrayList<ClassVisitor>(); |
| private Map<MethodInfo, MethodBodyInfo> methodMap = new HashMap<MethodInfo, MethodBodyInfo>(); |
| |
| /** |
| * Major version of the ABC |
| */ |
| public int getMajorVersion () |
| { |
| return majorVersion; |
| } |
| |
| /** |
| * Minor version of the ABC |
| */ |
| public int getMinorVersion () |
| { |
| return minorVersion; |
| } |
| |
| /** |
| * Name pool, has default zero entry. |
| */ |
| public Pool<Name> getNamePool () |
| { |
| return namePool; |
| } |
| |
| /** |
| * String pool, has default zero entry. |
| */ |
| public Pool<String> getStringPool () |
| { |
| return stringPool; |
| } |
| |
| /** |
| * int pool, has default zero entry. |
| */ |
| public Pool<Integer> getIntPool () |
| { |
| return intPool; |
| } |
| |
| /** |
| * uint pool, has default zero entry. |
| */ |
| public Pool<Long> getUintPool () |
| { |
| return uintPool; |
| } |
| |
| /** |
| * double pool, has default zero entry. |
| */ |
| public Pool<Double> getDoublePool () |
| { |
| return doublePool; |
| } |
| |
| /** |
| * namespace pool, has default zero entry. |
| */ |
| public Pool<Namespace> getNsPool () |
| { |
| return nsPool; |
| } |
| |
| /** |
| * namespace set pool, has default zero entry. |
| */ |
| public Pool<Nsset> getNssetPool () |
| { |
| return nssetPool; |
| } |
| |
| /** |
| * metadata pool, does not have default zero entry. |
| */ |
| public Pool<Metadata> getMetadataPool () |
| { |
| return metadataPool; |
| } |
| |
| /** |
| * Get a list of the ScriptInfos |
| */ |
| public List<ScriptInfo> getScriptInfos () |
| { |
| return scriptInfos; |
| } |
| |
| /** |
| * Get a list of the method bodies |
| */ |
| public List<MethodBodyInfo> getMethodBodies () |
| { |
| return methodBodies; |
| } |
| |
| /** |
| * Get a list of the method infos |
| */ |
| public EntryOrderedStore<MethodInfo> getMethodInfos () |
| { |
| return methodInfos; |
| } |
| |
| /** |
| * Get a list of the defined classes |
| */ |
| public List<ClassVisitor> getDefinedClasses () |
| { |
| return definedClasses; |
| } |
| |
| /** |
| * Script visitor that adds its ScriptInfo to the |
| * list of ScriptInfos |
| */ |
| private class ScriptVisitor implements IScriptVisitor |
| { |
| ScriptVisitor () |
| { |
| this.si = new ScriptInfo(); |
| } |
| |
| final ScriptInfo si; |
| |
| @Override |
| public void visit () |
| { |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| scriptInfos.add(this.si); |
| } |
| |
| @Override |
| public void visitInit (MethodInfo init_method) |
| { |
| si.setInit(init_method); |
| } |
| |
| @Override |
| public ITraitsVisitor visitTraits () |
| { |
| return new TraitsVisitor(si.getTraits()); |
| } |
| } |
| |
| /** |
| * Class Visitor that adds itself to the list |
| * of defined classes |
| */ |
| protected class ClassVisitor implements IClassVisitor |
| { |
| ClassVisitor (InstanceInfo iinfo, ClassInfo cinfo) |
| { |
| this.classInfo = cinfo; |
| if (null == cinfo.classTraits) |
| cinfo.classTraits = new Traits(); |
| this.classTraits = cinfo.classTraits; |
| |
| this.instanceInfo = iinfo; |
| |
| if (null == iinfo.traits) |
| iinfo.traits = new Traits(); |
| this.instanceTraits = iinfo.traits; |
| if (null == iinfo.interfaceNames) |
| iinfo.interfaceNames = new Name[0]; |
| } |
| |
| ClassInfo classInfo; |
| Traits classTraits; |
| InstanceInfo instanceInfo; |
| Traits instanceTraits; |
| |
| @Override |
| public void visit () |
| { |
| } |
| |
| @Override |
| public ITraitsVisitor visitClassTraits () |
| { |
| return new TraitsVisitor(this.classTraits); |
| } |
| |
| @Override |
| public ITraitsVisitor visitInstanceTraits () |
| { |
| return new TraitsVisitor(this.instanceTraits); |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| definedClasses.add(this); |
| } |
| |
| public InstanceInfo getInstanceInfo () |
| { |
| return this.instanceInfo; |
| } |
| } |
| |
| /** |
| * Traits Visitor that populates a Traits object |
| */ |
| private class TraitsVisitor implements ITraitsVisitor |
| { |
| TraitsVisitor (Traits traits) |
| { |
| this.traits = traits; |
| } |
| |
| Traits traits; |
| |
| @Override |
| public ITraitVisitor visitClassTrait (int kind, Name name, int slot_id, ClassInfo clazz) |
| { |
| Trait t = createTrait(kind, name); |
| if (slot_id != 0) |
| t.addAttr(Trait.TRAIT_SLOT, slot_id); |
| t.addAttr(Trait.TRAIT_CLASS, clazz); |
| |
| return new TraitVisitor(t); |
| } |
| |
| @Override |
| public ITraitVisitor visitMethodTrait (int kind, Name name, int dispId, MethodInfo method) |
| { |
| Trait t = createTrait(kind, name); |
| t.addAttr(Trait.TRAIT_METHOD, method); |
| if (dispId != 0) |
| t.addAttr(Trait.TRAIT_DISP, dispId); |
| return new TraitVisitor(t); |
| } |
| |
| @Override |
| public ITraitVisitor visitSlotTrait (int kind, Name name, int slotId, Name slotType, Object slotValue) |
| { |
| Trait t = createTrait(kind, name); |
| t.addAttr(Trait.TRAIT_SLOT, slotId); |
| t.addAttr(Trait.TRAIT_TYPE, slotType); |
| t.addAttr(Trait.SLOT_VALUE, slotValue); |
| if (slotType != null) |
| visitPooledName(slotType); |
| return new TraitVisitor(t); |
| } |
| |
| @Override |
| public void visit () |
| { |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| } |
| |
| @Override |
| public Traits getTraits () |
| { |
| return this.traits; |
| } |
| |
| private Trait createTrait (int kind, Name name) |
| { |
| Trait t = new Trait(kind, name); |
| traits.add(t); |
| return t; |
| } |
| } |
| |
| /** |
| * Trait Visitor that creates a Trait object |
| */ |
| private class TraitVisitor implements ITraitVisitor |
| { |
| TraitVisitor (Trait t) |
| { |
| this.t = t; |
| } |
| |
| Trait t; |
| |
| @Override |
| public IMetadataVisitor visitMetadata (int count) |
| { |
| return new IMetadataVisitor() |
| { |
| |
| @Override |
| public void visit (Metadata md) |
| { |
| t.addMetadata(md); |
| } |
| }; |
| } |
| |
| @Override |
| public void visitAttribute (String attr_name, Object attr_value) |
| { |
| this.t.addAttr(attr_name, attr_value); |
| } |
| |
| @Override |
| public void visitStart () |
| { |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| } |
| } |
| |
| /** |
| * Method Body Visitor that adds its MethodBodyInfo to the list of method bodies |
| */ |
| private class MethodBodyVisitor implements IMethodBodyVisitor |
| { |
| MethodBodyVisitor (org.apache.flex.abc.semantics.MethodBodyInfo mbinfo) |
| { |
| this.mbi = mbinfo; |
| } |
| |
| MethodBodyInfo mbi; |
| |
| @Override |
| public void visit () |
| { |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| methodBodies.add(mbi); |
| methodMap.put(mbi.getMethodInfo(), mbi); |
| } |
| |
| @Override |
| public void visitInstruction (int opcode) |
| { |
| this.mbi.insn(opcode); |
| } |
| |
| @Override |
| public void visitInstruction (int opcode, int immediate_operand) |
| { |
| this.mbi.insn(opcode, immediate_operand); |
| } |
| |
| @Override |
| public void visitInstruction (int opcode, Object single_operand) |
| { |
| this.mbi.insn(opcode, single_operand); |
| } |
| |
| @Override |
| public void visitInstruction (int opcode, Object[] operands) |
| { |
| this.mbi.insn(opcode, operands); |
| } |
| |
| @Override |
| public void visitInstruction (Instruction insn) |
| { |
| this.mbi.insn(insn); |
| } |
| |
| @Override |
| public ITraitsVisitor visitTraits () |
| { |
| return new TraitsVisitor(this.mbi.getTraits()); |
| } |
| |
| @Override |
| public int visitException (Label from, Label to, Label target, Name ex_type, Name ex_var) |
| { |
| return mbi.addExceptionInfo(new ExceptionInfo(from, to, target, ex_type, ex_var)); |
| } |
| |
| @Override |
| public void visitInstructionList (InstructionList new_list) |
| { |
| mbi.setInstructionList(new_list); |
| } |
| |
| @Override |
| public void labelCurrent (Label l) |
| { |
| mbi.labelCurrent(l); |
| } |
| |
| @Override |
| public void labelNext (Label l) |
| { |
| mbi.labelNext(l); |
| } |
| } |
| |
| /** |
| * Method Visitor that adds its MethodInfo to the list of MethodInfos |
| */ |
| private class MethodVisitor implements IMethodVisitor |
| { |
| MethodVisitor (MethodInfo mi) |
| { |
| assert (mi != null); |
| this.mi = mi; |
| } |
| |
| final MethodInfo mi; |
| |
| @Override |
| public void visit () |
| { |
| methodInfos.add(mi); |
| } |
| |
| @Override |
| public IMethodBodyVisitor visitBody (MethodBodyInfo mbi) |
| { |
| return new MethodBodyVisitor(mbi); |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| } |
| } |
| |
| /** |
| * @return the class ID of the given ClassInfo. |
| * @throws IllegalArgumentException if the class is not found. |
| */ |
| protected int getClassId (ClassInfo info) |
| { |
| int id_index = 0; |
| for (ClassVisitor candidate : this.definedClasses) |
| { |
| if (candidate.classInfo == info) |
| return id_index; |
| else |
| id_index++; |
| } |
| |
| throw new IllegalArgumentException("Unable to find ClassInfo index for " + info); |
| } |
| |
| /** |
| * Get the corresponding MethodBodyInfo for a given MethodInfo |
| * @param mi the MethodInfo you want the body for |
| * @return the MethodBodyInfo which is the body of the given MethodInfo |
| */ |
| protected MethodBodyInfo getMethodBodyForMethodInfo (MethodInfo mi) |
| { |
| return methodMap.get(mi); |
| } |
| |
| @Override |
| public void visitEnd () |
| { |
| } |
| } |