class ASN1DERTag extends BodyTagSupport {

    private byte[] value; // ASN.1 DER-encoded value

    public byte[] getValue() {
        return value;
    }

    public void setValue(byte[] value) {
        this.value = value;
    }

    @Override
    public int doEndTag() throws JspException {

        try (final ASN1InputStream decoder = new ASN1InputStream(value)){
            ASN1Primitive primitive = decoder.readObject();
            while (primitive != null && !(primitive instanceof ASN1Null)) {
                pageContext.getOut().write(doPrimitive(primitive));
                primitive = decoder.readObject();
            }
        } catch (Exception ex) {
            throw new JspException(ex.getMessage());
        }

        return super.doEndTag();
    }

    private String doPrimitive(ASN1Primitive primitive) throws IOException {<FILL_FUNCTION_BODY>}

    private String doCollection(ASN1Encodable[] asn1Encodables) throws IOException {
        switch (asn1Encodables.length) {
            case 1:
                // one row, one column
                return "<table><tr><td colspan='2'>" + doPrimitive(asn1Encodables[0].toASN1Primitive()) + "</td></tr></table>";

            case 2:
                // one row, two columns
                return "<table><tr><td>" + doPrimitive(asn1Encodables[0].toASN1Primitive()) + "</td>"
                        + "<td>" + doPrimitive(asn1Encodables[1].toASN1Primitive()) + "</td></tr></table>";

            default:
                // a row per per item
                final StringBuilder sb = new StringBuilder();
                for (ASN1Encodable asn1Encodable : asn1Encodables) {
                    sb.append("<table><tr><td colspan='2'>").append(doPrimitive(asn1Encodable.toASN1Primitive())).append("</td></tr></table>");
                }
                return sb.toString();
        }
    }

    private String asString(ASN1Primitive primitive) {
        if (primitive == null || primitive instanceof ASN1Null) {
            return "";
        }
        if (primitive instanceof ASN1String) {
            return ((ASN1String) primitive).getString();
        }
        if (primitive instanceof DERUTCTime) {
            return ((DERUTCTime) primitive).getAdjustedTime();
        }
        if (primitive instanceof DERGeneralizedTime) {
            return ((DERGeneralizedTime) primitive).getTime();
        }
        if (primitive instanceof ASN1ObjectIdentifier) {
            switch (((ASN1ObjectIdentifier) primitive).getId()) {
                case "1.3.6.1.5.5.7.8.5":
                    return "xmppAddr";
                default:
                    return primitive.toString();
            }
        }
        return primitive.toString();
    }
}

        if (primitive == null || primitive instanceof ASN1Null) {
            return "";
        } else if (primitive instanceof ASN1Sequence) {
            return doCollection(((ASN1Sequence) primitive).toArray());
        } else if (primitive instanceof ASN1Set) {
            return doCollection(((ASN1Set) primitive).toArray());
        } else if (primitive instanceof DERTaggedObject) {
            final DERTaggedObject tagged = ((DERTaggedObject) primitive);
            return "<table><tr><td>" + /* tagged.getTagNo() + */ "</td><td>" + doPrimitive(tagged.getBaseUniversal(false, tagged.getTagNo())) + "</td></tr></table>";
        } else {
            return "<table><tr><td colspan='2'>" + asString(primitive) + "</td></tr></table>";
        }
    
<no_super_class>