www.pudn.com > cryptix-asn1-0.1.11.zip > XerEncoder.java
/* $Id: XerEncoder.java,v 1.3 2001/05/24 16:52:49 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.encoding; import cryptix.asn1.io.*; import cryptix.asn1.lang.*; import org.apache.log4j.Category; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.math.BigInteger; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.TimeZone; /** * A class to encode ASN.1 specifications according to the XML Encoding Rules.* * @version $Revision: 1.3 $ * @author Raif S. Naffah */ public class XerEncoder extends ASNWriter implements Cloneable { // Constants and vars // ....................................................................... static Category cat = Category.getInstance(XerEncoder.class.getName()); /** * Spaces for each indentation level. */ private static final String INDENTATION = " "; /** * The underlying output stream. */ protected PrintWriter out; /** * The current indentation level. */ protected int level; // Constructor(s) // ....................................................................... /** * Trivial constructor for use by Factory. */ public XerEncoder() { super(); } // Class method(s) // ....................................................................... // Cloneable interface implementation // ....................................................................... public Object clone() { return new XerEncoder(); } // ASNWriter abstract methods implementation // ....................................................................... public void open(OutputStream os) { if (out != null) throw new IllegalStateException(); this.out = os instanceof BufferedOutputStream ? new PrintWriter(os, true) : new PrintWriter(new BufferedOutputStream(os, 10240), true); level = 0; } public void encodeAny(IType obj, Object val) throws IOException { cat.debug("==> encodeAny()"); if (val instanceof Boolean) this.encodeBoolean(obj, (Boolean) val); else if (val instanceof BigInteger) this.encodeInteger(obj, (BigInteger) val); else if (val instanceof String) this.encodeString(Tag.UNIVERSAL_STRING, obj, (String) val); else if (val instanceof Date) this.encodeUTCTime(obj, (Date) val); else if (val instanceof IType) ((IType) val).encode(this); else this.encodeOctetString(obj, (byte[]) val); cat.debug("<== encodeAny()"); } public void encodeObjectIdentifier(IType obj, String val) throws IOException { cat.debug("==> encodeObjectIdentifier()"); String name = obj.name(); cat.info(" name=\""+name+"\""); cat.info(" val=\""+val+"\""); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(val) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeObjectIdentifier()"); } public void encodeNull(IType obj) throws IOException { cat.debug("==> encodeNull()"); String name = obj.name(); cat.info(" name=\""+name+"\""); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append("/>"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeNull()"); } public void encodeBoolean(IType obj, Boolean val) throws IOException { cat.debug("==> encodeBoolean()"); String name = obj.name(); cat.info(" name=\""+name+"\""); cat.info(" val="+String.valueOf(val)); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(val.toString()) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeBoolean()"); } public void encodeInteger(IType obj, BigInteger val) throws IOException { cat.debug("==> encodeInteger()"); String name = obj.name(); cat.info(" name=\""+name+"\""); cat.info(" val="+String.valueOf(val)); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(val.toString()) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeInteger()"); } public void encodeString(int tagValue, IType obj, String val) throws IOException { cat.debug("==> encodeString("+tagValue+")"); String name = obj.name(); cat.info(" name=\""+name+"\""); cat.info(" val="+String.valueOf(val)); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(val) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeString()"); } public void encodeBitString(IType obj, byte[] val) throws IOException { cat.debug("==> encodeBitString()"); String name = obj.name(); cat.info(" name=\""+name+"\""); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(new BigInteger(1, val).toString(2)) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeBitString()"); } public void encodeOctetString(IType obj, byte[] val) throws IOException { cat.debug("==> encodeOctetString()"); String name = obj.name(); cat.info(" name=\""+name+"\""); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append("
") .append(new BigInteger(1, val).toString(16)) .append(" ") .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeOctetString()"); } public void encodeUTCTime(IType obj, Date val) throws IOException { cat.debug("==> encodeUTCTime()"); String name = obj.name(); cat.info(" name=\""+name+"\""); cat.info(" val="+String.valueOf(val)); SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(sdf.format(val)) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeUTCTime()"); } public void encodeGeneralizedTime(IType obj, Date val) throws IOException { cat.debug("==> encodeGeneralizedTime()"); String name = obj.name(); cat.info(" name=\""+name+"\""); cat.info(" val="+String.valueOf(val)); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss.sss'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); if (name == null || name.equals("")) name = "Name"; StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); sb.append("<").append(name).append(">") .append(sdf.format(val)) .append("").append(name).append(">"); synchronized (out) { out.println(sb.toString()); } cat.debug("<== encodeGeneralizedTime()"); } public void encodeStructure(IIterativeType obj) throws IOException { cat.debug("==> encodeStructure()"); String name = obj.name(); cat.info(" name=\""+name+"\""); if (name == null || name.equals("")) name = "Name"; synchronized (out) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < level; i++) sb.append(INDENTATION); String indent = sb.toString(); level++; out.println(indent+"<"+name+">"); for (Iterator it = obj.iterator(); it.hasNext(); ) { Object e = it.next(); // may be either an IType or an ArrayList if (e instanceof IType) { IType t = (Type) e; cat.info("Encoding "+t.getClass().getName()+"..."); t.encode(this); } else if (e instanceof ArrayList) { ArrayList t = (ArrayList) e; cat.info("Encoding a SEQUENCE/SET OF..."); encodeStructureInternal(t.iterator()); } else throw new RuntimeException("Dont know how to encode a "+obj.getClass().getName()); } out.println(indent+""+name+">"); level--; } cat.debug("<== encodeStructure()"); } public void encodeStructureInternal(Iterator it) throws IOException { cat.debug("==> encodeStructureInternal()"); synchronized (out) { while (it.hasNext()) { Object obj = it.next(); // may be either an IType or an ArrayList if (obj instanceof IType) { IType t = (Type) obj; cat.info("Encoding "+t.getClass().getName()+"..."); t.encode(this); } else if (obj instanceof ArrayList) { ArrayList t = (ArrayList) obj; cat.info("Encoding a SEQUENCE/SET OF..."); encodeStructureInternal(t.iterator()); } else throw new RuntimeException("Dont know how to encode a "+obj.getClass().getName()); } } cat.debug("<== encodeStructureInternal()"); } // OutputStream methods implementation // ....................................................................... /** * Writes the specified byte to this output stream. The general contract for * write() is that one byte is written to the output stream. The * byte to be written is the eight low-order bits of the argument b. * The 24 high-order bits of are ignored. * * @param b the byte. * @exception IOException if an I/O error occurs. In particular, an * IOException may be thrown if the output stream has been closed. */ public void write(int b) throws IOException { out.write(b & 0xFF); } /** * Closes the underlying output stream and releases any system resources * associated with it. * * @exception IOException if an I/O error occurs. */ public void close() throws IOException { if (out != null) { // try { out.close(); // } catch (IOException ignored) { // cat.warn("I/O exception while closing the stream: "+ignored.getMessage()); // } out = null; } } /** * Flushes this output stream and forces any buffered output bytes to be * written out. The general contract of flush() is that calling it is * an indication that, if any bytes previously written have been buffered by * the implementation of the output stream, such bytes should immediately be * written to their intended destination. * * @exception IOException if an I/O error occurs. */ public void flush() throws IOException { out.flush(); } }