/*
*/
/**
*
* @author sebastien riou
*/
package uk.co.nimp.scard;
import com.atolsystems.atolutilities.AFileUtilities;
import com.atolsystems.atolutilities.StopRequestFromUserException;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.smartcardio.*;
import javax.swing.JOptionPane;
//TODO: remove, should be private
public class Utilities {
final static String DEFAULT_CARD_READER_MANAGER_ENV_NAME = "DEFAULT_CARD_READER_MANAGER";
final static String EXIT_CMD = "exit\n";
static void startDefaultCardManager() throws IOException {
ArrayList<String> command = new ArrayList<String>();
try {
String target = System.getenv(DEFAULT_CARD_READER_MANAGER_ENV_NAME);
if (target == null) {
throw new RuntimeException("rmiregistry and or card reader manager are not running\n" + "Set environment variable \"" + DEFAULT_CARD_READER_MANAGER_ENV_NAME + "\" to allow auto start");
}
String[] tokens = target.split("\\*");
for (int i = 0; i < tokens.length; i++) {
command.add(tokens[i]);
}
/*File targetAsAFile = new File(command.get(0));
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(targetAsAFile.getParentFile());
processBuilder.redirectErrorStream(true);
//Process p=processBuilder.start();*/
String[] cmd = {"cmd.exe", "/C", "start"};//, "java.exe" };
List<String> l = new ArrayList<String>(Arrays.asList(cmd));
l.addAll(command);
cmd = l.toArray(cmd);
Process p = Runtime.getRuntime().exec(cmd);
} catch (Exception ex) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, ex);
System.exit(0);
}
System.out.println("Start default card reader manager:" + command);
System.out.println("Card reader manager was not detected. Please press 'A' " + "to abort or any other key to continue with the default card reader manager");
while (System.in.available() == 0) {
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (System.in.read() == 'A') {
System.exit(0);
}
}
public static void executeTaskWithDefaultCardManager(SmartCardTask task, boolean allowDummySC, String helloMsg, boolean requireConfirmationToDisconnect) throws IOException, CardException, StopRequestFromUserException, Throwable {
executeTaskWithDefaultCardManager(task, allowDummySC, helloMsg, requireConfirmationToDisconnect, false);
}
public static void executeTaskWithDefaultCardManager(SmartCardTask task, boolean allowDummySC, String helloMsg, boolean requireConfirmationToDisconnect, boolean useOldCommandLineStyle) throws IOException, CardException, StopRequestFromUserException, Throwable {
StopRequestFromUserException ex = null;
BasicCardReaderTaskExecutor executor = new BasicCardReaderTaskExecutor(allowDummySC, useOldCommandLineStyle);
try{
executor.enableAuxLogging(true, helloMsg);
try {
//System.out.println("exec stage");
executor.executeTask(task);
if(requireConfirmationToDisconnect){
int choice=JOptionPane.showConfirmDialog(null, "Disconnect from card ?", "Disconnect ?", JOptionPane.YES_NO_OPTION);
if(JOptionPane.OK_OPTION==choice)
executor.disconnect();
}
} catch (StopRequestFromUserException e) {
ex = e;
} catch (Throwable e){
executor.log(e);
throw e;
}finally {
executor.closeMonitoringWindow(false);
}
}catch (StopRequestFromUserException e) {
ex = e;
} catch (Throwable e){
//System.out.println(e);
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, e);
//throw e;
} finally{
}
if (null != ex) {
throw ex;
}
}
public static void executeTask(SmartCardTask task, Class theClass, String aResourceInTheSamePackage, boolean allowDummySC, String helloMsg, boolean requireConfirmationToDisconnect) throws StopRequestFromUserException, IOException, CardException, Exception, Throwable {
executeTask(task, theClass, aResourceInTheSamePackage, allowDummySC, helloMsg, requireConfirmationToDisconnect, false);
}
public static void executeTask(SmartCardTask task, Class theClass, String aResourceInTheSamePackage, boolean allowDummySC, String helloMsg, boolean requireConfirmationToDisconnect, boolean useOldCommandLineStyle) throws StopRequestFromUserException, IOException, CardException, Exception, Throwable {
SmartCardTaskProcessor reader = null;
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
/*System.out.println("No security manager installed");
System.out.println("-->start default card reader manager in this process\n");
executeTaskWithDefaultCardManager(task, allowDummySC);
return;*/
}
try {
if (System.getProperty("java.rmi.server.codebase") == null) {
String codebase = AFileUtilities.getRmiCodeBase(theClass, aResourceInTheSamePackage);
System.out.println("set codebase to: " + codebase);
System.setProperty("java.rmi.server.codebase", codebase);
}
} catch (java.security.AccessControlException e) {
System.out.println(e.getMessage());
System.out.println("-->start default card reader manager in this process\n");
executeTaskWithDefaultCardManager(task, allowDummySC, helloMsg, useOldCommandLineStyle);
return;
}
System.out.println("codebase: " + System.getProperty("java.rmi.server.codebase"));
String serverAddress = InetAddress.getLocalHost().getHostAddress();
Registry registry = LocateRegistry.getRegistry(serverAddress);
try {
//list bounded name in this registry: if rmiregistry is not running, this will throw an exception
String[] a = registry.list();
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
} catch (Exception e) { //need to start card reader manager
System.out.println(e.getMessage());
//start basic card reader manager in this process
System.out.println("-->start default card reader manager in this process\n");
executeTaskWithDefaultCardManager(task, allowDummySC, helloMsg, requireConfirmationToDisconnect, useOldCommandLineStyle);
return;
//start it as rmi server
/*System.out.println("start default card manager");
startDefaultCardManager();
registry = LocateRegistry.getRegistry(serverAddress);*/
}
try {
reader = (SmartCardTaskProcessor) registry.lookup(SmartCardTaskProcessor.registryId);
reader.exist();//if card reader manager is not running, this will throw an exception
} catch (Exception ex) {
System.out.println("Exception: " + ex.getMessage());
System.out.println("start default card manager\n");
startDefaultCardManager();
try {
reader = (SmartCardTaskProcessor) registry.lookup(SmartCardTaskProcessor.registryId);
} catch (RemoteException ex1) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, ex1);
} catch (NotBoundException ex1) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, ex1);
}
}
System.out.println("start task");
reader.executeTask(task);
}
/**
* return the first PCSC terminal where a card is detected.
* @return the first terminal where a card is detected.
*/
public static GenericTerminal getTerminal() throws StopRequestFromUserException {
return getTerminal(System.out, false);
}
/**
* return the first PCSC terminal where a card is detected.
* @param allowDummySC allow the DummySC target (for debug when no reader is connected)
* @return the first terminal where a card is detected.
*/
public static GenericTerminal getTerminal(PrintStream outStream, boolean allowDummySC) throws StopRequestFromUserException {
GenericTerminal terminal = null;
List<GenericTerminal> terminals = new LinkedList<GenericTerminal>();
try {
outStream.println("Wait until at least one terminal is present");
do {
terminals.clear();
//factory = TerminalFactory.getDefault();
//terminals.addAll(factory.terminals().list());
//factory = NimpTerminalFactory.getInstance("NimpTestPC/SC", null, new NimpTestPCSC());
//terminals.addAll(factory.terminals().list());
//PcScTerminalManager.initContext();
terminals.addAll((new PcScTerminalManager()).list());
if (allowDummySC) {
//factory = TerminalFactory.getInstance("Dummy/SC", null, new NimpDummySC());
//terminals.addAll(factory.terminals().list());
}
} while (terminals.isEmpty());
outStream.println("Number of terminals: " + terminals.size());
outStream.println("Terminals: " + terminals);
outStream.println("Wait until a card is found in any terminal");
terminal=terminalChooser(terminals);
outStream.println("Terminal: " + terminal + " selected");
} catch (StopRequestFromUserException e) {
throw e;
} catch (Exception ex) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, ex);
}
return terminal;
}
static public GenericTerminal terminalChooser(List<GenericTerminal> terminals) throws ScardException, StopRequestFromUserException{
GenericTerminal terminal=null;
while (true) {
ArrayList<GenericTerminal> candidates = new ArrayList<GenericTerminal>(terminals.size());
StringBuilder sb=new StringBuilder();
for (int i = 0; i < terminals.size(); i++) {
terminal = terminals.get(i);
sb.append(" - ");
sb.append(terminal.getName());
sb.append("\n");
if (terminal.isCardPresent()) {
candidates.add(terminal);
}
}
if(0==candidates.size()){
String msg = "No card has been detected, please insert a card in one of following terminals:\n";
msg+=sb.toString();
int choice = JOptionPane.showConfirmDialog(null, msg, "Waiting for card", JOptionPane.OK_CANCEL_OPTION);
if (JOptionPane.OK_OPTION == choice) {
//nothing to do
}
if (JOptionPane.CANCEL_OPTION == choice) {
throw new StopRequestFromUserException("Operation cancelled by user.");
}
}
if (1 == candidates.size()) {
terminal = candidates.get(0);
break;
}
if (1 < candidates.size()) {
Object[] names = new Object[candidates.size()];
for (int i = 0; i < candidates.size(); i++) {
names[i] = candidates.get(i).getName();
}
String s = (String) JOptionPane.showInputDialog(
null,
"Please select a terminal",
"Terminal selection",
JOptionPane.PLAIN_MESSAGE,
null,
names,
names[0]);
if (s == null) {
throw new StopRequestFromUserException();
}
for (int i = 0; i < candidates.size(); i++) {
if (candidates.get(i).getName().equals(s)) {
terminal = candidates.get(i);
break;
}
}
break;
}
}
return terminal;
}
/**
* return selected PCSC terminal(s).
* @return a list of terminals.
*/
/* public static GenericTerminal getTerminals(PrintStream outStream) throws StopRequestFromUserException {
GenericTerminal terminal = null;
List<GenericTerminal> terminals = new LinkedList<GenericTerminal>();
try {
outStream.println("Wait until at least one terminal is present");
do {
terminals.clear();
PcScTerminalManager.initContext();
terminals.addAll((new PcScTerminalManager()).list());
} while (terminals.isEmpty());
outStream.println("Number of terminals: " + terminals.size());
outStream.println("Terminals: " + terminals);
outStream.println("Wait until a card is found in any terminal");
while (true) {
ArrayList<GenericTerminal> candidates = new ArrayList<GenericTerminal>(terminals.size());
for (int i = 0; i < terminals.size(); i++) {
terminal = terminals.get(i);
if (terminal.isCardPresent()) {
candidates.add(terminal);
}
}
if (1 == candidates.size()) {
terminal = candidates.get(0);
break;
}
if (1 < candidates.size()) {
Object[] names = new Object[candidates.size()];
for (int i = 0; i < candidates.size(); i++) {
names[i] = candidates.get(i).getName();
}
String s = (String) JOptionPane.showInputDialog(
null,
"Please select one or more terminal",
"Terminal selection",
JOptionPane.PLAIN_MESSAGE,
null,
names,
names[0]);
if (s == null) {
throw new StopRequestFromUserException();
}
for (int i = 0; i < candidates.size(); i++) {
if (candidates.get(i).getName().equals(s)) {
terminal = candidates.get(i);
break;
}
}
break;
}
}
outStream.println("Terminal: " + terminal + " selected");
} catch (StopRequestFromUserException e) {
throw e;
} catch (Exception ex) {
Logger.getLogger(Utilities.class.getName()).log(Level.SEVERE, null, ex);
}
return terminals;
}*/
}