/* * * 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 () { } }