package org.bouncycastle.asn1;

import org.bouncycastle.util.Arrays;

import java.io.IOException;

/**
 * Base class for an application specific object
 */
public class DERApplicationSpecific 
    extends ASN1Object
{
    private boolean   isConstructed;
    private int       tag;
    private byte[]    octets;

    DERApplicationSpecific(
        boolean isConstructed,
        int     tag,
        byte[]  octets)
    {
        this.isConstructed = isConstructed;
        this.tag = tag;
        this.octets = octets;
    }

    public DERApplicationSpecific(
        int    tag,
        byte[] octets)
    {
        this(false, tag, octets);
    }

    public DERApplicationSpecific(
        int                  tag, 
        DEREncodable         object) 
        throws IOException 
    {
        this(true, tag, object);
    }

    public DERApplicationSpecific(
        boolean      explicit,
        int          tag,
        DEREncodable object)
        throws IOException
    {
        if (tag >= 0x1f)
        {
            throw new IOException("unsupported tag number");
        }

        byte[] data = object.getDERObject().getDEREncoded();

        this.isConstructed = explicit;
        this.tag = tag;

        if (explicit)
        {
            this.octets = data;
        }
        else
        {
            int lenBytes = getLengthOfLength(data);
            byte[] tmp = new byte[data.length - lenBytes];
            System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
            this.octets = tmp;
        }
    }

    private int getLengthOfLength(byte[] data)
    {
        int count = 2;               // TODO: assumes only a 1 byte tag number

        while((data[count - 1] & 0x80) != 0)
        {
            count++;
        }

        return count;
    }

    public boolean isConstructed()
    {
        return isConstructed;
    }
    
    public byte[] getContents()
    {
        return octets;
    }
    
    public int getApplicationTag() 
    {
        return tag;
    }
     
    public DERObject getObject() 
        throws IOException 
    {
        return new ASN1InputStream(getContents()).readObject();
    }

    /**
     * Return the enclosed object assuming implicit tagging.
     *
     * @param derTagNo the type tag that should be applied to the object's contents.
     * @return  the resulting object
     * @throws IOException if reconstruction fails.
     */
    public DERObject getObject(int derTagNo)
        throws IOException
    {
        if (tag >= 0x1f)
        {
            throw new IOException("unsupported tag number");
        }
                
        byte[] tmp = this.getEncoded();

        tmp[0] = (byte)derTagNo;
        
        return new ASN1InputStream(tmp).readObject();
    }
    
    /* (non-Javadoc)
     * @see org.bouncycastle.asn1.DERObject#encode(org.bouncycastle.asn1.DEROutputStream)
     */
    void encode(DEROutputStream out) throws IOException
    {
        int classBits = DERTags.APPLICATION;
        if (isConstructed)
        {
            classBits |= DERTags.CONSTRUCTED; 
        }

        if (tag < 31)
        {
            out.writeEncoded(classBits | tag, octets);
        }
        else
        {
            out.writeEncodedHigh(classBits | 0x1f, tag, octets);
        }
    }
    
    boolean asn1Equals(
        DERObject o)
    {
        if (!(o instanceof DERApplicationSpecific))
        {
            return false;
        }

        DERApplicationSpecific other = (DERApplicationSpecific)o;

        return isConstructed == other.isConstructed
            && tag == other.tag
            && Arrays.areEqual(octets, other.octets);
    }

    public int hashCode()
    {
        return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets);
    }
}

@@ -3093,169 +3093,34 @@
     
-if (tag %3C 31)%0A        %7B%0A            out.writeEncoded(classBits %7C tag, octets);%0A        %7D%0A        else%0A        %7B%0A            out.writeEncodedHigh(classBits %7C 0x1f
+out.writeEncoded(classBits
 , ta
@@ -3131,26 +3131,16 @@
 ctets);%0A
-        %7D%0A
     %7D%0A  

Apply high tag number fix from main source tree