package opencard.opt.util;
import opencard.core.terminal.CommandAPDU;
import opencard.core.terminal.ResponseAPDU;
import opencard.core.terminal.CardTerminalException;
import opencard.core.service.SmartCard;
import opencard.core.service.CardChannel;
import opencard.core.service.CardService;
import opencard.core.service.CardServiceScheduler;
import opencard.core.service.CardServiceException;
import opencard.core.service.CardServiceInvalidParameterException;
/**
* A card service for low level communication with smartcards.
* It allows to send application-provided command APDUs to the card and
* returns the response APDUs. The factory that creates this service is
* <tt>PassThruCardServiceFactory</tt>.
* <br>
* This class serves as an example how a card service can be implemented.
* However, it contradicts the idea of card services. The responsibility
* for composing the APDUs sent to the card and interpreting the responses
* lies with the card services, not with the application.
* Since most people start getting familiar with smartcards by building
* APDUs themselves, this service is provided here as a "quick starter"
* for some test programs. Nevertheless, it's use is strongly discouraged
* when implementing real applications.
* <br>
* OpenCard applications should <b>never</b> build APDUs, since APDUs are
* card specific. The same applies to interpreting the responses received
* from the smartcard. Instead, they should use high-level interfaces that
* can be implemented for different cards. These interfaces can be standard
* interfaces, like <tt>FileAccessCardService</tt> for ISO compatible, file
* system based smartcards, or they can be defined by an application.
*
* <p>
* When designing an application that supports smartcards, there will
* typically be a need for two kinds of card specific code. First, the
* ATR sent by a smartcard has to be interpreted to make sure that the
* card inserted is supported by the application. An OCF application
* should put the respective code into a card service factory, or use an
* existing factory that knows the ATR(s).
* <br>
* The second part of the card specific code will build command APDUs and
* interpret responses to these commands. This part of the code can provide
* rather general operations, like <i>select a file</i> or <i>read some
* data from a file</i>. In this case, a standard interface should be used.
* On the other hand, this part of the code can also provide specialized
* functionality, like <i>read the serial number</i> or <i>read the card
* holder's name</i>. In this case, the application should define it's own
* interface, and a card service implementing this interface has to be
* developed.
* <br>
* Later on, if another card with different APDUs and responses has to be
* supported by the same application, just a service for that new card has
* to be developed, implementing the same interface as the first one. The
* factory used to create the first service will be extended, so it can
* decide which service to use, depending on a smartcard's ATR. The
* application itself does not have to be changed at all.
*
*
* @author Thomas Schaeck (schaeck@de.ibm.com)
* @author Roland Weber (rolweber@de.ibm.com)
*
* @version $Id: PassThruCardService.java,v 1.2 1998/08/12 13:28:30 cvsusers Exp $
*
* @see PassThruCardServiceFactory
* @see opencard.opt.iso.fs.FileAccessCardService
*/
public class PassThruCardService extends CardService {
/**
* Creates a new low level card service that is not yet initialized.
* Initialization is done by invoking <tt>initialize</tt> in the base class.
*
* @see opencard.core.service.CardService#initialize
*/
public PassThruCardService() {
super();
}
/**
* Sends a <tt>CommandAPDU</tt> to the smart card.
* @param command The <tt>CommandAPDU</tt> to send.
* @return The resulting <tt>ResponseAPDU</tt> as
* received from the card.
*
* @exception CardTerminalException
* if the terminal encountered an error while
* trying to communicate with the smartcard
*/
public ResponseAPDU sendCommandAPDU(CommandAPDU command)
throws CardTerminalException {
// first, some static checking is done on the parameters
if (command == null) {
throw new CardServiceInvalidParameterException("command = null");
}
// this variable is needed to store the return value
ResponseAPDU response = null;
// Here is the actual implementation of this service method:
// - allocate a channel to the smartcard
// - prepare the APDU to be sent (of course not in this trivial service)
// - send the command and receive the response, using the allocated channel
// - evaluate the response (of course not in this trivial service)
// - release the allocated channel, even if an error occurred
// Optionally, the preparation of the APDU can be done before allocating
// the channel. Likewise, postprocessing of the response can be delayed
// until the channel has been freed.
try {
allocateCardChannel();
response = getCardChannel().sendCommandAPDU(command);
}
finally {
releaseCardChannel();
}
return response;
} // sendCommandAPDU
} // class PassThruCardService