www.pudn.com > cryptix-asn1-0.1.11.zip > Interpreter.java
/* $Id: Interpreter.java,v 1.2 2001/06/02 02:46:40 raif Exp $ * * Copyright (C) 1997-2001 The Cryptix Foundation Limited. All rights reserved. * * Use, modification, copying and distribution of this software is subject to * the terms and conditions of the Cryptix General Licence. You should have * received a copy of the Cryptix General Licence along with this library; if * not, you can download a copy from http://www.cryptix.org/ */ package cryptix.asn1.tool; import cryptix.asn1.analysis.DepthFirstAdapter; import cryptix.asn1.node.*; import org.apache.log4j.Category; import java.io.PrintWriter; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedList; import java.util.Map; /** * A class to interpret ASN.1 specifications.* * @version $Revision: 1.2 $ * @author Raif S. Naffah */ public class Interpreter extends DepthFirstAdapter { // Constants and vars // ------------------------------------------------------------------------- static Category cat = Category.getInstance(Interpreter.class.getName()); /** * Hashtable to hold parsed ASN.1 modules data. */ private Hashtable modules = new Hashtable(); /** * Hashtable to hold OID values resolved in a specifications input file. Each * entry in this table is keyed by an ASN.1 identifier and has as its value a * dotted string representation * of the components. */ private Hashtable oids; /** * Hashtable to hold Types defined in a specifications input file. Each entry * in this table is keyed by an ASN.1 type identifier and has as its value a * reference to the SableCC AST sub-tree. */ private Hashtable types; /** Stack for runtime interpretation of OID values. */ private String[] stack; /** The stack's top pointer. */ private int top; /** Prefix for component names of constructed types. */ private String prefix; // Constructor(s) // ------------------------------------------------------------------------- // implicit no-arguments constructor // Class methods // ------------------------------------------------------------------------- // Overriden DepthFirstAdapter methods // ------------------------------------------------------------------------- public void defaultOut(Node node) { cat.debug("node: "+node.getClass().getName()+"="+node); } public void inAModuleDefinition(AModuleDefinition node) { oids = new Hashtable(); types = new Hashtable(); stack = new String[64]; top = -1; prefix = ""; } public void outAModuleDefinition(AModuleDefinition node) { Hashtable module = new Hashtable(); module.put("OID", oids); module.put("TYPE", types); Node t = node.getTagging(); boolean implicitTaggingByDefault = false; // explicit tagging by default if (t != null) { Node tt = ((ATagging) t).getTagDefault(); if (tt instanceof AExplicitTagDefault) implicitTaggingByDefault = false; else implicitTaggingByDefault = true; } module.put("IMPLICIT_TAGGING", new Boolean(implicitTaggingByDefault)); String moduleName = ((AModuleIdentifier) node.getModuleIdentifier()).getUpper().getText(); modules.put(moduleName, module); oids = null; types = null; stack = null; top = -1; prefix = null; } public void outAObjIdCompLst(AObjIdCompLst node) { // pop stack and assemble String oid = ""; if (top > -1) oid = stack[top--]; while (top > -1) oid = stack[top--]+"."+oid; stack[++top] = oid; cat.debug("outAObjIdCompLst(): Assembled OID: "+oid); } public void outANumericObjIdComponent(ANumericObjIdComponent node) { cat.debug("node: "+node.getClass().getName()+"="+node); String image = node.getNumber().getText().trim(); stack[++top] = image; // put on top of rt stack cat.info("outANumericObjIdComponent(): Pushed \""+image+"\""); } public void outALowerObjIdComponent(ALowerObjIdComponent node) { cat.debug("node: "+node.getClass().getName()+"="+node); String id = node.getLower().getText().trim(); Node class_attr = node.getClassAttr(); if (class_attr == null) resolveOID(id); else { Node class_number = ((AClassAttr) class_attr).getClassNumber(); String oid = class_number.toString().trim(); cat.info("outALowerObjIdComponent(): Assembled OID: "+id+"=\""+oid+"\""); oids.put(id, oid); } } public void outANumericClassNumber(ANumericClassNumber node) { cat.debug("node: "+node.getClass().getName()+"="+node); String image = node.getNumber().getText().trim(); stack[++top] = image; // push on rt stack cat.info("outANumericClassNumber(): Pushed \""+image+"\""); } public void inATypeAssignment(ATypeAssignment node) { String upper = node.getUpper().getText().trim(); Node type = node.getType(); cat.info("inATypeAssignment():"); cat.info(" upper::"+upper); cat.info(" type::"+type.getClass().getName()+"=\""+type+"\""); prefix = upper; } public void outATypeAssignment(ATypeAssignment node) { cat.debug("node: "+node.getClass().getName()+"="+node); String upper = node.getUpper().getText().trim(); Node type = node.getType(); cat.info("outATypeAssignment():"); cat.info(" upper::"+upper); cat.info(" type::"+type.getClass().getName()+"=\""+type+"\""); types.put(upper, type); cat.info("Defined \""+upper+"\""); prefix = ""; // reset prefix } public void outAValueAssignment(AValueAssignment node) { cat.debug("node: "+node.getClass().getName()+"="+node); String id = node.getLower().getText().trim(); Node type = node.getType(); Node value = node.getValue(); cat.info("outAValueAssignment():"); cat.info(" identifier::"+id); cat.info(" type::"+type.getClass().getName()+"=\""+type+"\""); cat.info(" value::"+value.getClass().getName()+"=\""+value+"\""); if (type.toString().trim().equals("OBJECT IDENTIFIER")) { // pop stack+assemble String oid = ""; if (top > -1) oid = stack[top--]; while (top > -1) oid = stack[top--]+"."+oid; cat.info("outAValueAssignment(): Assembled OID=\""+oid+"\""); oids.put(id, oid); } } public void outALowerBetBraces(ALowerBetBraces node) { cat.debug("node: "+node.getClass().getName()+"="+node); String id = node.getLower().getText().trim(); Node aux_bet1 = node.getAuxBet1(); cat.info("outALowerBetBraces():"); cat.info(" lower::"+id); cat.info(" aux_bet1::"+aux_bet1.getClass().getName()+"=\""+aux_bet1+"\""); if (aux_bet1 == null) return; if (aux_bet1 instanceof ALParenAuxBet1) { Node class_number = ((ALParenAuxBet1) aux_bet1).getClassNumber(); String oid = class_number.toString().trim(); cat.info("outALowerBetBraces(): Assembled OID: "+id+"=\""+oid+"\""); oids.put(id, oid); } else if (aux_bet1 instanceof APositiveAuxBet1) { resolveOID(id); // resolve identifier String image = ((APositiveAuxBet1) aux_bet1).getNumber().getText().trim(); stack[++top] = image; // put on top of rt stack cat.info("outALowerBetBraces(): Pushed \""+image+"\""); } else if (aux_bet1 instanceof ALowerAuxBet1) updateStack(id); } public void inAPositiveBetBraces(APositiveBetBraces node) { cat.debug("node: "+node.getClass().getName()+"="+node); String nbr = node.getNumber().getText().trim(); Node aux_bet3 = node.getAuxBet3(); cat.info("inAPositiveBetBraces():"); cat.info(" number::"+nbr); cat.info(" aux_bet3::"+aux_bet3.getClass().getName()+"=\""+aux_bet3+"\""); stack[++top] = nbr; // push on rt stack cat.info("inAPositiveBetBraces(): Pushed \""+nbr+"\""); } public void outALowerAuxBet1(ALowerAuxBet1 node) { cat.debug("node: "+node.getClass().getName()+"="+node); String id = node.getLower().getText().trim(); Node aux_bet11 = node.getAuxBet11(); cat.info("outALowerAuxBet1():"); cat.info(" lower::"+id); cat.info(" aux_bet11::"+aux_bet11.getClass().getName()+"=\""+aux_bet11+"\""); if (aux_bet11 == null) updateStack(id); else if (aux_bet11 instanceof AOidAuxBet11) updateStack(id); } public void outALowerNamedType(ALowerNamedType node) { cat.debug("node: "+node.getClass().getName()+"="+node); String id = node.getLower().getText().trim(); Node less = node.getLess(); Node type = node.getType(); cat.info("outALowerNamedType():"); cat.info(" lower::"+id); if (less != null) cat.info(" less::"+less.getClass().getName()+"=\""+less+"\""); cat.info(" type::"+type.getClass().getName()+"=\""+type+"\""); id = prefix+"."+id; types.put(id, type); cat.info("Defined \""+id+"\""); } // Other instance methods // ------------------------------------------------------------------------- private String resolveOID(String id) { String result = (String) oids.get(id); cat.debug("resolveOID("+id+") --> "+result); if (result == null) throw new RuntimeException("Forward reference to \""+id+"\"..."); stack[++top] = result; cat.info("Pushed \""+result+"\""); return result; } private String updateStack(String id) { String oid = ""; if (top > -1) oid = stack[top--]; while (top > -1) oid = stack[top--]+"."+oid; resolveOID(id); // re-assemble String result = stack[top]+"."+oid; stack[top] = result; cat.debug("top --> [STACK]="+id+"."+oid+", or \""+result+"\""); return result; } /** * Dumps all the data relevant to a designated module. */ public void dump(String module) { Hashtable moduleData = (Hashtable) modules.get(module); Enumeration keys; Hashtable moduleOIDs = (Hashtable) moduleData.get("OID"); if (moduleOIDs.size() != 0) { System.out.println(); System.out.println("OIDs defined in module "+module+"..."); keys = moduleOIDs.keys(); while (keys.hasMoreElements()) { String aKey = (String) keys.nextElement(); String value = (String) moduleOIDs.get(aKey); System.out.println(" "+aKey+"=\""+value+"\""); } } Hashtable moduleTypes = (Hashtable) moduleData.get("TYPE"); if (moduleTypes.size() != 0) { System.out.println(); System.out.println("Types defined in module "+module+"..."); keys = moduleTypes.keys(); Node result; while (keys.hasMoreElements()) { String k = (String) keys.nextElement(); result = (Node) moduleTypes.get(k); System.out.println(" "+k+"="+result); } } } /** * Returns the AST of a defined type designated by id in the module * designated by module; or null if it is not defined. * * @return an AST for a given type in a given interpreted module. */ public Node getComponent(String module, String id) { Hashtable moduleData = (Hashtable) modules.get(module); Hashtable moduleTypes = (Hashtable) moduleData.get("TYPE"); Node result = (Node) moduleTypes.get(id); cat.debug("getComponent(\""+module+"\", \""+id+"\") --> "+result); return result; } /** * Returns the ASTs of all defined types in an ASN.1 module designated by * module; or null if it is not defined. * * @module the name of an ASN.1 module already parsed by this Interpreter. * @return a mapping of types (keys) to their ASTs (values) defined in the * designated module. */ public Map getComponents(String module) { Hashtable moduleData = (Hashtable) modules.get(module); Hashtable result = (Hashtable) moduleData.get("TYPE"); return result; } /** * Returns the OIDs of all defined OBJECT IDENTIFIERs in a designated ASN.1 * module; or null if such a module is not defined. * * @module the name of an ASN.1 module already parsed by this Interpreter. * @return a mapping of types (keys) to their ASTs (values) defined in the * designated module. */ public Map getOIDs(String module) { Hashtable moduleData = (Hashtable) modules.get(module); Hashtable result = (Hashtable) moduleData.get("OID"); return result; } /** * Returns whether or not tagging for the designated module is EXPLICIT * (false) or IMPLICIT (true). * * @module the name of an ASN.1 module already parsed by this Interpreter. * @return boolean false if the tagging of components in this module * is EXPLICIT, otherwise return true if tagging is IMPLICIT. */ public boolean getImplicitTagging(String module) { Hashtable moduleData = (Hashtable) modules.get(module); Boolean result = (Boolean) moduleData.get("IMPLICIT_TAGGING"); return result.booleanValue(); } /** * Returns true if the designated type identifier/name is among those * declared in the EXPORT statement of the designated module. False otherwise. * * @return true or false depending on the fact that the designated ID is * among those EXPORTed by the designated module. */ public boolean isPublic(String module, String id) { // TODO // Hashtable moduleData = (Hashtable) modules.get(module); LinkedList moduleExports = (LinkedList) moduleData.get("EXPORT"); if (moduleExports == null) return true; return moduleExports.contains(id); } /** * Returns the Map of all defined modules interpreted so far. * * @return a Hashtable of all module-dependent information for all * modules interpreted so far by this instance of the Interpreter. */ public Map getModules() { return modules; } }