⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generator.java

📁 JAVA的加密库之一
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/* $Id: Generator.java,v 1.4 2001/06/30 01:56:55 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.lang.NodeInfo;
import cryptix.asn1.node.*;

import org.apache.log4j.Category;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * A class to interpret ASN.1 specifications and generate Java source code.
 *
 * @version $Revision: 1.4 $
 * @author  Raif S. Naffah
 */
public class Generator extends DepthFirstAdapter {

	// Constants and vars
	// -------------------------------------------------------------------------

	private static Category cat = Category.getInstance(Generator.class);

	private static final int NOT_GENERATING = 0;
	private static final int GENERATING =     1;
	private static final int REFERENCE_ONLY = 2;

	/** The output stream where code is generated. */
	private PrintWriter pw;

	Interpreter ast;
	int indent = 0;
	int state;
	String moduleName; // name of the package wehere class belongs
	String pkgName; // name (dotted string) of mapped package wehere class belongs
	String className; // name of the class we're generating
	LinkedList data; // vector of element data objects
	String lower; // sequence/set element name
	String type; // sequence/set element type
	String tag; // tag constructor for a sequence/set element

	// Constructor(s)
	// -------------------------------------------------------------------------

	/**
	 * Constructs a code generator for a designated language operating on the
	 * designated AST.
	 *
	 * @param ast the parsed AST of the ASN.1 definitions as a
	 * <tt>cryptix.asn1.tools.Interpreter</tt>.
	 * @param languageID the constant defining a programming language in which
	 * to generate the source objects that will map to the ASN.1 constructs.
	 */
	public Generator(Interpreter ast) {
		this.ast = ast;
		data = new LinkedList();
	}

	// Class methods
	// -------------------------------------------------------------------------

   public static final String toJava(String name) {
      cat.debug("==> toJava("+String.valueOf(name)+")");

      if (name != null) {
         // 1. replace multiple hyphens with 1 hyphen
         int i = name.indexOf("--");
         while (i > -1) {
            name = name.substring(0, i) + name.substring(i+1);
            i = name.indexOf("--");
         }

         // 2. replace hyphen-character with uppercase character
         i = name.indexOf("-");
         while (i > -1) {
            name = name.substring(0, i) + toProper(name.substring(i+1));
            i = name.indexOf("-");
         }
      }

      cat.debug("<== toJava() --> "+String.valueOf(name));
      return name;
   }

   private static final String toProper(String name) {
      if (name.equals(""))
         return name;

      return name.substring(0, 1).toUpperCase() + name.substring(1);
   }

	// Instance methods
	// -------------------------------------------------------------------------

	/**
	 * Generates Java code for all components in all modules interpreted so
	 * far by the underlying Interpreter.<p>
	 *
	 * Gets all modules from the underlying Interpreter, and repeatedly invokes
	 * the method with same name and 3 arguments.
	 *
	 * @param destination the directory where generated files will be stored.
	 * @param dict a <tt>java.util.Map</tt> that maps package names to ASN.1
	 * module names. If a module name is not found in this map, then the same
	 * name string will be used as the name of its enclosing package.
	 * @exception IOException if an I/O error occurs during (a) the creation of
	 * a new file (that will contain generated code) or its parent directory,
	 * (b) the construction of a FileWriter object wrapping a new file, or
	 * (c) the process of generating the code per-se.
	 */
	public void generate(File destination, Map dict)
	throws IOException {
		Map modules = ast.getModules();
		Set keys = modules.keySet();
		Object[] moduleNames = keys.toArray();
		int limit = moduleNames.length;
		for (int i = 0; i < limit; i++)
			generate(destination, (String) moduleNames[i], dict);
	}

	/**
	 * Generates code for all constructs of a designated ASN.1 module, including
	 * a convenience <tt>Module</tt> Java interface which shall group all OIDs
	 * defined in that designated ASN.1 module.<p>
	 *
	 * If any file at the same path location as any one that should be
	 * generated already exists, it is over-written.
	 *
	 * @param destination the directory where generated files will be stored.
	 * @param module the name of the ASN.1 module, which will become the name of
	 * the package containg the new classes.
	 * @param dict a <tt>java.util.Map</tt> that maps package names to ASN.1
	 * module names. If a module name is not found in this map, then the same
	 * name string will be used as the name of its enclosing package.
	 * @exception IOException if an I/O error occurs during (a) the creation of
	 * a new file (that will contain generated code) or its parent directory,
	 * (b) the construction of a FileWriter object wrapping a new file, or
	 * (c) the process of generating the code per-se.
	 */
	public void generate(File destination, String module, Map dict)
	throws IOException {
		Map moduleTypes = ast.getComponents(module);
		Set types = moduleTypes.keySet();
	   cat.debug("Types defined in module "+String.valueOf(module)+":\n"+String.valueOf(moduleTypes));
		Object[] typeNames = types.toArray();
		for (int i = 0, limit = typeNames.length; i < limit; i++) {
			String type = (String) typeNames[i];
			if (isPermissibleType(type)) {
				Node n = (Node) moduleTypes.get(type);
				generate(destination, module, dict, toJava(type), n);
			}
		}

		generateModule(destination, module, dict);
	}

	/**
	 * Generates code for a designated ASN.1 construct.<p>
	 *
	 * If a file at the same path location as the one that should be generated
	 * already exists, it is over-written.
	 *
	 * @param destination the directory where generated files will be stored.
	 * @param module the name of the ASN.1 module, which will become the name of
	 * the package containg the new class.
	 * @param type the name of the defined ASN.1 type within the designated
	 * module, which will become the name of the Java Class (or other language
	 * equivalent) --defined within the designated package-- to generate.
	 * @param dict a <tt>java.util.Map</tt> that maps package names to ASN.1
	 * module names. If a module name is not found in this map, then the same
	 * name string will be used as the name of its enclosing package.
	 * @exception IOException if an I/O error occurs during (a) the creation of
	 * the new file (that will contain the generated code) or its parent
	 * directory, (b) the construction of a FileWriter object wrapping this new
	 * file, or (c) the process of generating the code per-se.
	 * @exception IllegalArgumentException if the type string does not start with
	 * an uppercase, or contains a dot.
	 */
	public void generate(File destination, String module, String type, Map dict)
	throws IOException {
		if (!isPermissibleType(type))
			throw new IllegalArgumentException();
		Node n = ast.getComponent(module, type);
		generate(destination, module, dict, type, n);
	}

	// Overriden DepthFirstAdapter methods
	// -------------------------------------------------------------------------

	public void defaultIn(Node node) {
		indent++;
		String indentation = "";
		for (int i = 0; i < indent; i++)
			indentation += "   ";

		cat.debug(indentation+"--> "+node.getClass().getName());
	}

	public void defaultOut(Node node) {
		String indentation = "";
		for (int i = 0; i < indent; i++)
			indentation += "   ";

		cat.debug(indentation+"<-- "+node.getClass().getName()+": "+node);
		indent--;
	}

	public void inAIntegerBuiltInType(AIntegerBuiltInType node) {
		defaultIn(node);
		switch (state) {
		case GENERATING:
			boolean isPublic = ast.isPublic(moduleName, className);
			outBuiltInClass(isPublic, className, "INTEGER");
			state = REFERENCE_ONLY;
			break;
		}
	}

	public void outAIntegerBuiltInType(AIntegerBuiltInType node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			type = "INTEGER";
			break;
		}
	}

	public void outANamedNumber(ANamedNumber node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			String var = node.getLower().getText().trim();
			Node n = node.getAuxNamedNum();
			StringBuffer args = new StringBuffer("new ASNInteger(");
			args.append("\"").append(className).append(".").append(var).append("\", ");
			if (n instanceof APositiveAuxNamedNum) {
				APositiveAuxNamedNum pann = (APositiveAuxNamedNum) n;
				args.append("\"")
				.append(pann.getNumber().getText().trim())
				.append("\"");
			} else if (n instanceof ANegativeAuxNamedNum) {
				ANegativeAuxNamedNum nann = (ANegativeAuxNamedNum) n;
				args.append("\"-")
				.append(nann.getNumber().getText().trim())
				.append("\"");
			} else if (n instanceof ALowerAuxNamedNum) {
				ALowerAuxNamedNum lann = (ALowerAuxNamedNum) n;
				args.append(lann.getLower().getText().trim());
			} else if (n instanceof AUpperAuxNamedNum) {
				AUpperAuxNamedNum uann = (AUpperAuxNamedNum) n;
				args.append(uann.getUpper().getText().trim())
				.append(".")
				.append(uann.getLower().getText().trim());
			}

			args.append(")");

			outAttribute(className, var, args.toString());
			break;
		}
	}

	public void outANullType(ANullType node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			type = "NULL";
			break;
		}
	}

	public void inABooleanBuiltInType(ABooleanBuiltInType node) {
		defaultIn(node);
		switch (state) {
		case GENERATING:
			boolean isPublic = ast.isPublic(moduleName, className);
			outBuiltInClass(isPublic, className, "BOOLEAN");
			state = REFERENCE_ONLY;
			break;
		}
	}

	public void outABooleanBuiltInType(ABooleanBuiltInType node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			type = "BOOLEAN";
			break;
		}
	}

	public void inABitBuiltInType(ABitBuiltInType node) {
		defaultIn(node);
		switch (state) {
		case GENERATING:
			boolean isPublic = ast.isPublic(moduleName, className);
			outBuiltInClass(isPublic, className, "BIT_STRING");
			state = REFERENCE_ONLY;
			break;
		}
	}

	public void outABitBuiltInType(ABitBuiltInType node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			type = "BIT_STRING";
			break;
		}
	}

	public void inAOctetBuiltInType(AOctetBuiltInType node) {
		defaultIn(node);
		switch (state) {
		case GENERATING:
			boolean isPublic = ast.isPublic(moduleName, className);
			outBuiltInClass(isPublic, className, "OCTET_STRING");
			state = REFERENCE_ONLY;
			break;
		}
	}

	public void outAOctetBuiltInType(AOctetBuiltInType node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			type = "OCTET_STRING";
			break;
		}
	}

	public void inAAnyBuiltInType(AAnyBuiltInType node) {
		defaultIn(node);
		switch (state) {
		case GENERATING:
			boolean isPublic = ast.isPublic(moduleName, className);
			outBuiltInClass(isPublic, className, "ANY");
			state = REFERENCE_ONLY;
			break;
		}
	}

	public void outAAnyBuiltInType(AAnyBuiltInType node) {
		defaultOut(node);
		switch (state) {
		case GENERATING:
			break;
		case REFERENCE_ONLY:
			type = "ANY";
			break;
		}
	}

	public void inAOidBuiltInType(AOidBuiltInType node) {
		defaultIn(node);
		switch (state) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -