ATR.java revision 10444:f08705540498
1/* 2 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package javax.smartcardio; 27 28import java.util.*; 29 30/** 31 * A Smart Card's answer-to-reset bytes. A Card's ATR object can be obtained 32 * by calling {@linkplain Card#getATR}. 33 * This class does not attempt to verify that the ATR encodes a semantically 34 * valid structure. 35 * 36 * <p>Instances of this class are immutable. Where data is passed in or out 37 * via byte arrays, defensive cloning is performed. 38 * 39 * @see Card#getATR 40 * 41 * @since 1.6 42 * @author Andreas Sterbenz 43 * @author JSR 268 Expert Group 44 */ 45public final class ATR implements java.io.Serializable { 46 47 private static final long serialVersionUID = 6695383790847736493L; 48 49 private byte[] atr; 50 51 private transient int startHistorical, nHistorical; 52 53 /** 54 * Constructs an ATR from a byte array. 55 * 56 * @param atr the byte array containing the answer-to-reset bytes 57 * @throws NullPointerException if <code>atr</code> is null 58 */ 59 public ATR(byte[] atr) { 60 this.atr = atr.clone(); 61 parse(); 62 } 63 64 private void parse() { 65 if (atr.length < 2) { 66 return; 67 } 68 if ((atr[0] != 0x3b) && (atr[0] != 0x3f)) { 69 return; 70 } 71 int t0 = (atr[1] & 0xf0) >> 4; 72 int n = atr[1] & 0xf; 73 int i = 2; 74 while ((t0 != 0) && (i < atr.length)) { 75 if ((t0 & 1) != 0) { 76 i++; 77 } 78 if ((t0 & 2) != 0) { 79 i++; 80 } 81 if ((t0 & 4) != 0) { 82 i++; 83 } 84 if ((t0 & 8) != 0) { 85 if (i >= atr.length) { 86 return; 87 } 88 t0 = (atr[i++] & 0xf0) >> 4; 89 } else { 90 t0 = 0; 91 } 92 } 93 int k = i + n; 94 if ((k == atr.length) || (k == atr.length - 1)) { 95 startHistorical = i; 96 nHistorical = n; 97 } 98 } 99 100 /** 101 * Returns a copy of the bytes in this ATR. 102 * 103 * @return a copy of the bytes in this ATR. 104 */ 105 public byte[] getBytes() { 106 return atr.clone(); 107 } 108 109 /** 110 * Returns a copy of the historical bytes in this ATR. 111 * If this ATR does not contain historical bytes, an array of length 112 * zero is returned. 113 * 114 * @return a copy of the historical bytes in this ATR. 115 */ 116 public byte[] getHistoricalBytes() { 117 byte[] b = new byte[nHistorical]; 118 System.arraycopy(atr, startHistorical, b, 0, nHistorical); 119 return b; 120 } 121 122 /** 123 * Returns a string representation of this ATR. 124 * 125 * @return a String representation of this ATR. 126 */ 127 public String toString() { 128 return "ATR: " + atr.length + " bytes"; 129 } 130 131 /** 132 * Compares the specified object with this ATR for equality. 133 * Returns true if the given object is also an ATR and its bytes are 134 * identical to the bytes in this ATR. 135 * 136 * @param obj the object to be compared for equality with this ATR 137 * @return true if the specified object is equal to this ATR 138 */ 139 public boolean equals(Object obj) { 140 if (this == obj) { 141 return true; 142 } 143 if (obj instanceof ATR == false) { 144 return false; 145 } 146 ATR other = (ATR)obj; 147 return Arrays.equals(this.atr, other.atr); 148 } 149 150 /** 151 * Returns the hash code value for this ATR. 152 * 153 * @return the hash code value for this ATR. 154 */ 155 public int hashCode() { 156 return Arrays.hashCode(atr); 157 } 158 159 private void readObject(java.io.ObjectInputStream in) 160 throws java.io.IOException, ClassNotFoundException { 161 atr = (byte[])in.readUnshared(); 162 parse(); 163 } 164 165} 166