/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.infotechservice.smartcard.service;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.smartcardio.CardException;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import org.infotechservice.smartcard.utils.CardFrameworkException;
import org.infotechservice.smartcard.utils.Messages;
/**
* Абстрактный объект сервиса смарткарты.
* Все действия со смарткартой осуществляются через сервисные объекты, которые
* являются потомками данного класса и вызываеют его методы для низкоуровнего общения
* с картой
* @author Axe
*/
public abstract class CardService {
private SmartCard smartcard;
public CardService(SmartCard card) {
if (card == null) {
throw new IllegalArgumentException("Card can't be null");
}
this.smartcard = card;
}
/**
* Выполняет указанную команду на карте
* @param command
* @param errorMesssage Сообщение об ошибке, кторое будет отображено если будет ошибка
* @return
* @throws CardException
*/
protected ResponseAPDU exec(CommandAPDU command, String errorMesssage) throws CardException {
ResponseAPDU responce = smartcard.getCard().getBasicChannel().transmit(command);
Messages msg = Messages.findMessage(responce);
if (msg.isError()) {
if (errorMesssage == null) {
throw new CardFrameworkException(msg);
} else {
throw new CardFrameworkException(errorMesssage, msg);
}
}
return responce;
}
/**
* Выполняет указзанный набор команд на карте
* @param script
* @param errorMesssage Сообщение об ошибке, кторое будет отображено если будет ошибка
* @throws CardException
*/
protected void execScript(CommandAPDU[] script, String errorMesssage) throws CardException {
for (CommandAPDU commandAPDU : script) {
exec(commandAPDU, errorMesssage);
}
}
protected static int getFile(int file) {
return (byte)((file << 3) | 4);
}
protected byte[] readTag(byte[] tag, byte[] response, int offset) {
boolean found = false;
byte dataLength = 0;
int dataBeginAt = 0;
for (int i = offset; i < (response.length - tag.length); i++) {
if (response[i] == tag[0]) {
found = true;
for (int j = 1; j < tag.length; j++) {
if (response[i + j] != tag[j]) {
found = false;
break;
}
}
if (found) {
dataLength = response[i + tag.length];
dataBeginAt = i + tag.length + 1;
break;
}
}
}
if (found) {
byte[] temp = new byte[dataLength];
for (int i = 0; i < dataLength; i++) {
temp[i] = response[dataBeginAt + i];
}
return temp;
}
return null;
}
protected class SF {
public final int length;
public final String delimiter;
public SF(int length, String delimiter) {
this.length = length;
this.delimiter = delimiter;
}
}
protected String format(String value, SF[] format) {
String formatted = "";
int pos = 0;
for(SF f: format) {
formatted += value.substring(pos, pos + f.length) + f.delimiter;
pos += f.length;
}
if(pos < value.length()) {
formatted += value.substring(pos);
}
return formatted;
}
protected Date bcdToDate(byte value[], int offset) {
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.YEAR, hexToDec(value[0 + offset])*100 + hexToDec(value[1 + offset]));
cal.set(Calendar.MONTH, hexToDec(value[2 + offset]) - 1);
cal.set(Calendar.DAY_OF_MONTH, hexToDec(value[3 + offset]));
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
private int hexToDec(byte value) {
return (value >> 4)*10 + (value & 0xF);
}
}