Package de.willuhn.jameica.hbci.passports.ddv

Source Code of de.willuhn.jameica.hbci.passports.ddv.DDVConfigFactory

/**********************************************************************
* $Source: /cvsroot/hibiscus/hibiscus/src/de/willuhn/jameica/hbci/passports/ddv/DDVConfigFactory.java,v $
* $Revision: 1.9 $
* $Date: 2011/09/06 11:54:25 $
* $Author: willuhn $
*
* Copyright (c) by willuhn - software & services
* All rights reserved
*
**********************************************************************/

package de.willuhn.jameica.hbci.passports.ddv;

import java.io.File;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;

import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;

import org.apache.commons.lang.StringUtils;
import org.kapott.hbci.manager.HBCIUtils;
import org.kapott.hbci.passport.AbstractHBCIPassport;
import org.kapott.hbci.passport.HBCIPassportChipcard;

import de.willuhn.jameica.hbci.HBCI;
import de.willuhn.jameica.hbci.passport.PassportHandle;
import de.willuhn.jameica.hbci.passports.ddv.rmi.Reader;
import de.willuhn.jameica.hbci.passports.ddv.rmi.Reader.Type;
import de.willuhn.jameica.hbci.passports.ddv.server.CustomReader;
import de.willuhn.jameica.hbci.passports.ddv.server.PassportHandleImpl;
import de.willuhn.jameica.hbci.rmi.Konto;
import de.willuhn.jameica.services.BeanService;
import de.willuhn.jameica.system.Application;
import de.willuhn.jameica.system.BackgroundTask;
import de.willuhn.jameica.system.OperationCanceledException;
import de.willuhn.jameica.system.Platform;
import de.willuhn.jameica.system.Settings;
import de.willuhn.logging.Logger;
import de.willuhn.util.ApplicationException;
import de.willuhn.util.ClassFinder;
import de.willuhn.util.I18N;
import de.willuhn.util.ProgressMonitor;

/**
* Eine Factory zum Laden, Erstellen und Aendern von Kartenleser-Konfigurationen.
*/
public class DDVConfigFactory
{
  private final static I18N i18n = Application.getPluginLoader().getPlugin(HBCI.class).getResources().getI18N();
  private final static Settings settings = new Settings(DDVConfigFactory.class);
 
  private static List<Reader> presets = null;
 
  /**
   * Liefert eine Liste der vorhandenen Kartenleser-Konfigurationen.
   * @return eine Liste der vorhandenen Kartenleser-Konfigurationen.
   */
  public static List<DDVConfig> getConfigs()
  {
    String[] ids = settings.getList("config",new String[0]);
    List<DDVConfig> configs = new ArrayList<DDVConfig>();
    for (String id:ids)
    {
      configs.add(new DDVConfig(id));
    }
    return configs;
  }
 
  /**
   * Liefert eine Liste mit bekannten Reader-Presets.
   * @return Liste mit bekannten Reader-Presets.
   */
  public static synchronized List<Reader> getReaderPresets()
  {
    if (presets != null)
      return presets;

    presets = new ArrayList<Reader>();
    try
    {
      Logger.info("searching for reader presets");
      BeanService service = Application.getBootLoader().getBootable(BeanService.class);
      ClassFinder finder = Application.getPluginLoader().getPlugin(HBCI.class).getManifest().getClassLoader().getClassFinder();
      Class<Reader>[] found = finder.findImplementors(Reader.class);
      for (Class<Reader> r:found)
      {
        try
        {
          presets.add(service.get(r));
        }
        catch (Exception e)
        {
          Logger.error("unable to load reader preset " + r + " - skipping",e);
        }
      }
    }
    catch (ClassNotFoundException e)
    {
      Logger.error("no reader presets found");
      // Dann nehmen wir wenigstens den "Benutzerdefinierten Leser" in die Liste
      presets.add(new CustomReader());
    }

    // Alphabetisch sortieren
    Collections.sort(presets,new Comparator<Reader>() {
      public int compare(Reader r1, Reader r2)
      {
        return r1.getName().compareTo(r2.getName());
      }
    });
    return presets;
  }

  /**
   * Speichert die Config.
   * @param config die zu speichernde Config.
   */
  public static void store(DDVConfig config)
  {
    if (config == null)
      return;
   
    // Wir holen uns erstmal die Liste der Konfigurationen
    String[] ids = settings.getList("config",new String[0]);
    List<String> newIds = new ArrayList<String>();

    // Jetzt checken wir, ob wir die ID schon haben
    boolean found = false;
    for (String id:ids)
    {
      if (id == null || id.length() == 0)
        continue; // ignorieren
      found |= id.equals(config.getId());
      newIds.add(id);
    }
   
    if (!found)
      newIds.add(config.getId());
   
    // Speichern der aktualisierten Liste
    settings.setAttribute("config",newIds.toArray(new String[newIds.size()]));
  }
 
  /**
   * Loescht die angegebene Config.
   * @param config die zu loeschende Config.
   * @throws ApplicationException
   */
  public static void delete(DDVConfig config) throws ApplicationException
  {
    if (config == null)
      throw new ApplicationException(i18n.tr("Bitte w�hlen Sie die zu l�schende Konfiguration aus"));

    // Loeschen der Einstellungen aus der Config
    config.deleteProperties();

    // Aus der Liste der Konfigurationen entfernen
    String[] ids = settings.getList("config",new String[0]);
    List<String> newIds = new ArrayList<String>();

    for (String id:ids)
    {
      if (id == null || id.length() == 0)
        continue; // ignorieren
      if (!id.equals(config.getId())) // wir ueberspringen die zu loeschende
        newIds.add(id);
    }
   
    // Speichern der aktualisierten Liste
    settings.setAttribute("config",newIds.toArray(new String[newIds.size()]));
  }
 
  /**
   * Startet eine automatische Suche nach einem Kartenleser.
   * @param monitor ein Monitor, mit dem der Scan-Fortschritt verfolgt werden kann.
   * @param task ueber den Task koennen wir erkennen, ob wir abbrechen sollen.
   * @return der gefundene Kartenleser oder NULL wenn keiner gefunden wurde.
   */
  public static DDVConfig scan(ProgressMonitor monitor, BackgroundTask task)
  {
    // wir nehmen hier nicht die Create-Funktion, weil wir
    // sonst (wegen der UUID) mit den Scans die DDVConfig.properties
    // mit Testparametern zumuellen wuerden. Auf diese Weise
    // ist es immer nur die eine.
    DDVConfig temp = new DDVConfig("__scan__");
   
    try
    {
      List<Reader> list = DDVConfigFactory.getReaderPresets();
      int factor = 100 / (list.size() * DDVConfig.PORTS.length);
           
      for (Reader reader:list)
      {
        if (task.isInterrupted())
          throw new OperationCanceledException();
       
        monitor.setStatusText(i18n.tr("Teste {0}",reader.getName()));

        // Testen, ob der Kartenleser ueberhaupt unterstuetzt wird
        if (!reader.isSupported())
        {
          monitor.log("  " + i18n.tr("�berspringe Kartenleser, wird von Ihrem System nicht unterst�tzt"));
          continue;
        }

        // Checken, ob der CTAPI-Treiber existiert.
        String s = StringUtils.trimToNull(reader.getCTAPIDriver());
        Type type = reader.getType();
        if (type.isCTAPI())
        {
          if (s == null)
          {
            monitor.log("  " + i18n.tr("�berspringe Kartenleser, kein CTAPI-Treiber definiert."));
            continue;
          }
          File f = new File(s);
          if (!f.exists())
          {
            monitor.log("  " + i18n.tr("�berspringe Kartenleser, CTAPI-Treiber {0} existiert nicht.",f.getAbsolutePath()));
            continue;
          }
        }

        int ctNumber = reader.getCTNumber();
        temp.setCTNumber(ctNumber == -1 ? 0 : ctNumber);
        temp.setEntryIndex(1);
        temp.setReaderPreset(reader);
        temp.setSoftPin(reader.useSoftPin());
        temp.setCTAPIDriver(s);
        temp.setHBCIVersion(reader.getDefaultHBCIVersion());

        // PC/SC-Kartenleser suchen
        if (type.isPCSC())
        {
          try
          {
            List<CardTerminal> terminals = TerminalFactory.getDefault().terminals().list();
            // Eigentlich koennen wir hier pauschal den ersten gefundenen nehmen
            if (terminals != null && terminals.size() > 0)
            {
              CardTerminal terminal = terminals.get(0);
              String name = terminal.getName();
              temp.setPCSCName(name);
              PassportHandle handle = new PassportHandleImpl(temp);
              handle.open();
              handle.close(); // nein, nicht im finally, denn wenn das Oeffnen

              // Passport liess sich oeffnen und schliessen. Dann haben
              // wir den Kartenleser gefunden.
              monitor.log("  " + name + " " + i18n.tr("gefunden"));
              monitor.setStatusText(i18n.tr("OK. Kartenleser \"{0}\" gefunden",name));
              monitor.setStatus(ProgressMonitor.STATUS_DONE);
              monitor.setPercentComplete(100);
             
              // Wir kopieren die temporaere Config noch in eine richtige
              DDVConfig config = temp.copy();
              config.setName(name);
              return config;
            }
          }
          catch (ApplicationException ae)
          {
            monitor.log("  " + ae.getMessage());
          }
          catch (Exception e)
          {
            Logger.error("unable to create ddv config",e);
          }
          finally
          {
            temp.setPCSCName(null); // muessen wir wieder zuruecksetzen
          }
         
          // Wir haben wohl nichts via PC/SC gefunden
          monitor.log("  " + i18n.tr("  nicht gefunden"));
          continue;
        }

        // Wir probieren alle Ports durch
        for (String port:DDVConfig.PORTS)
        {
          if (task.isInterrupted())
            throw new OperationCanceledException();
         
          monitor.addPercentComplete(factor);
          monitor.log("  " + i18n.tr("Port {0}",port));
               
          temp.setPort(port);

          try
          {
            PassportHandle handle = new PassportHandleImpl(temp);
            handle.open();
            handle.close(); // nein, nicht im finally, denn wenn das Oeffnen
                            // fehlschlaegt, ist nichts zum Schliessen da ;)

            // Passport liess sich oeffnen und schliessen. Dann haben
            // wir den Kartenleser gefunden.
            monitor.log("  " + i18n.tr("gefunden"));
            monitor.setStatusText(i18n.tr("OK. Kartenleser gefunden"));
            monitor.setStatus(ProgressMonitor.STATUS_DONE);
            monitor.setPercentComplete(100);
           
            // Wir kopieren die temporaere Config noch in eine richtige
            DDVConfig config = temp.copy();
            config.setName(i18n.tr("Neue Kartenleser-Konfiguration"));
            return config;
          }
          catch (ApplicationException ae)
          {
            monitor.log("  " + ae.getMessage());
          }
          catch (Exception e)
          {
            monitor.log("  " + i18n.tr("  nicht gefunden"));
          }
        }
      }
      monitor.setStatusText(i18n.tr("Kein Kartenleser gefunden. Bitte manuell konfigurieren"));
      monitor.setStatus(ProgressMonitor.STATUS_ERROR);
      monitor.setPercentComplete(100);
      return null;
    }
    catch (OperationCanceledException oce)
    {
      monitor.setStatus(ProgressMonitor.STATUS_CANCEL);
      monitor.setStatusText(i18n.tr("Abgebrochen"));
      monitor.setPercentComplete(100);
      return null;
    }
    finally
    {
      // temporaere Config wieder loeschen
      try
      {
        temp.delete();
      }
      catch (Exception e)
      {
        Logger.error("unable to delete temp-config",e);
      }
    }
  }
 
  /**
   * Liefert die zum uebergebenen Konto gehoerende PIN/Tan-Config oder <code>null</code> wenn keine gefunden wurde.
   * @param konto Konto, fuer das die Config gesucht wird.
   * @return Pin/Tan-config des Kontos oder null wenn keine gefunden wurde.
   * @throws RemoteException
   * @throws ApplicationException
   */
  public static synchronized DDVConfig findByKonto(Konto konto) throws RemoteException, ApplicationException
  {

    List<DDVConfig> list = getConfigs();
    if (list.size() == 0)
      throw new ApplicationException(i18n.tr("Bitte legen Sie zuerst eine Kartenleser-Konfiguration an"));

    Logger.info("searching config for konto " + konto.getKontonummer() + ", blz: " + konto.getBLZ());

    for (DDVConfig c:list)
    {
      List<Konto> verdrahtet = c.getKonten();
      if (konto != null && verdrahtet != null && verdrahtet.size() > 0)
      {
        for (Konto k:verdrahtet)
        {
          if (konto.equals(k))
          {
            Logger.info("found config via account. name: " + c.getName());
            return c;
          }
        }
      }
    }

    // Wir haben nur eine Config, dann nehmen wir gleich die
    if (list.size() == 1)
    {
      DDVConfig config = (DDVConfig) list.get(0);
      Logger.info("using config : " + config.getName());
      return config;
    }
   
    // Wir haben mehrere zur Auswahl. Lassen wir den User entscheiden.
    SelectConfigDialog d = new SelectConfigDialog(SelectConfigDialog.POSITION_CENTER);
    try
    {
      return (DDVConfig) d.open();
    }
    catch (OperationCanceledException oce)
    {
      throw oce;
    }
    catch (Exception e)
    {
      Logger.error("error while choosing config",e);
      throw new ApplicationException(i18n.tr("Fehler bei der Auswahl der Kartenleser-Konfiguration: {0}",e.getMessage()));
    }
  }

  /**
   * Erzeugt eine neue DDV-Config.
   * @return die neue DDV-Config.
   */
  public static DDVConfig create()
  {
    return new DDVConfig(UUID.randomUUID().toString());
  }
 
  /**
   * Erstellt ein Passport-Objekt aus der Config.
   * @param config die Config.
   * @return das Passport-Objekt.
   * @throws ApplicationException
   * @throws RemoteException
   */
  public static HBCIPassportChipcard createPassport(DDVConfig config) throws ApplicationException, RemoteException
  {
    if (config == null)
      throw new ApplicationException(i18n.tr("Keine Konfiguration ausgew�hlt"));

    Type type = config.getReaderPreset().getType();
   
    if (type.isPCSC())
    {
      String pcscName = config.getPCSCName();
      Logger.info("  pcsc name: " + pcscName);
      if (StringUtils.trimToNull(pcscName) != null)
      {
        HBCIUtils.setParam(PassportParameter.get(type,PassportParameter.NAME),pcscName);
      }
    }
    else
    {
      //////////////////////////////////////////////////////////////////////////
      // JNI-Treiber
      String jni = getJNILib().getAbsolutePath();
      Logger.info("  jni lib: " + jni);
      HBCIUtils.setParam("client.passport.DDV.libname.ddv", jni);
      //
      //////////////////////////////////////////////////////////////////////////

      //////////////////////////////////////////////////////////////////////////
      // CTAPI-Treiber
      String ctapiDriver = config.getCTAPIDriver();
      if (ctapiDriver == null || ctapiDriver.length() == 0)
        throw new ApplicationException(i18n.tr("Kein CTAPI-Treiber in der Kartenleser-Konfiguration angegeben"));

      File ctapi = new File(ctapiDriver);
      if (!ctapi.exists() || !ctapi.isFile() || !ctapi.canRead())
        throw new ApplicationException(i18n.tr("CTAPI-Treiber-Datei \"{0}\" nicht gefunden oder nicht lesbar",ctapiDriver));

      Logger.info("  ctapi driver: " + ctapiDriver);
      HBCIUtils.setParam(PassportParameter.get(type,PassportParameter.CTAPI), ctapiDriver);
      //
      //////////////////////////////////////////////////////////////////////////
    }

    //////////////////////////////////////////////////////////////////////////
    // Passport-Verzeichnis
    File f = new File(de.willuhn.jameica.hbci.Settings.getWorkPath() + "/passports/");
    if (!f.exists())
      f.mkdirs();
   
    String headerName = type == Type.RDH_PCSC ? "RSA" : "DDV"; // siehe HBCIPassport[RSA/DDV], Konstruktor, "setParamHeader"
    HBCIUtils.setParam("client.passport." + headerName + ".path",de.willuhn.jameica.hbci.Settings.getWorkPath() + "/passports/");
    //
    //////////////////////////////////////////////////////////////////////////


    if (type.isCTAPI())
    {
      String port = Integer.toString(DDVConfig.getPortForName(config.getPort()));
      Logger.info("  port: " + config.getPort() + " [ID: " + port + "]");
      HBCIUtils.setParam(PassportParameter.get(type,PassportParameter.PORT), port);

      Logger.info("  ctnumber: " + config.getCTNumber());
      HBCIUtils.setParam(PassportParameter.get(type,PassportParameter.CTNUMBER), Integer.toString(config.getCTNumber()));
    }

    Logger.info("  soft pin: " + config.useSoftPin());
    HBCIUtils.setParam(PassportParameter.get(type,PassportParameter.SOFTPIN), config.useSoftPin() ? "1" : "0");

    Logger.info("  entry index: " + config.getEntryIndex());
    HBCIUtils.setParam(PassportParameter.get(type,PassportParameter.ENTRYIDX), Integer.toString(config.getEntryIndex()));

    String id = type.getIdentifier();
    Logger.info("  passport type: " + id);
    return (HBCIPassportChipcard) AbstractHBCIPassport.getInstance(id);
  }

 
  /**
   * Liefert die zu verwendende JNI-Lib.
   * @return die zu verwendende JNI-Lib.
   * @throws ApplicationException
   */
  private static File getJNILib() throws ApplicationException
  {
    String file = null;
   
    switch (Application.getPlatform().getOS())
    {
      case Platform.OS_LINUX:
        file = "libhbci4java-card-linux-32.so";
        break;
       
      case Platform.OS_LINUX_64:
        file = "libhbci4java-card-linux-64.so";
        break;
       
      case Platform.OS_WINDOWS:
        file = "hbci4java-card-win32.dll";
        break;

      case Platform.OS_WINDOWS_64:
        file = "hbci4java-card-win32_x86-64.dll";
        break;
       
      case Platform.OS_MAC:
        String arch = System.getProperty("os.arch");
        if (arch != null && arch.contains("64"))
          file = "libhbci4java-card-mac-os-x-10.6.jnilib"; // BUGZILLA 965
        else
          file = "libhbci4java-card-mac.jnilib";
        break;

      case Platform.OS_FREEBSD_64:
        file = "libhbci4java-card-freebsd-64.so";
        break;
    }
   
    if (file == null)
      throw new ApplicationException(i18n.tr("Hibiscus unterst�tzt leider keine Chipkartenleser f�r Ihr Betriebssystem"));

    File f = new File(de.willuhn.jameica.hbci.Settings.getLibPath(),file);
    if (!f.exists())
      throw new ApplicationException(i18n.tr("Treiber {0} nicht gefunden",f.getAbsolutePath()));

    if (!f.isFile() || !f.canRead())
      throw new ApplicationException(i18n.tr("Treiber {0} nicht lesbar",f.getAbsolutePath()));

    return f;
  }

 
}



/**********************************************************************
* $Log: DDVConfigFactory.java,v $
* Revision 1.9  2011/09/06 11:54:25  willuhn
* @C JavaReader in PCSCReader umbenannt - die PIN-Eingabe fehlt noch
*
* Revision 1.8  2011-09-01 12:16:08  willuhn
* @N Kartenleser-Suche kann jetzt abgebrochen werden
* @N Erster Code fuer javax.smartcardio basierend auf dem OCF-Code aus HBCI4Java 2.5.8
*
* Revision 1.7  2011-09-01 09:40:53  willuhn
* @R Biometrie-Support bei Kartenlesern entfernt - wurde nie benutzt
*
* Revision 1.6  2011-06-17 08:49:19  willuhn
* @N Contextmenu im Tree mit den Bank-Zugaengen
* @N Loeschen von Bank-Zugaengen direkt im Tree
*
* Revision 1.5  2011-02-06 23:34:21  willuhn
* @N BUGZILLA 965
*
* Revision 1.4  2010-10-17 21:58:56  willuhn
* @C Aendern der Bankdaten auf der Karte auch dann moeglich, wenn auf dem Slot ungueltige Daten stehen
*
* Revision 1.3  2010-09-08 10:16:00  willuhn
* @N Wenn nur eine DDV-Config vorhanden ist, dann die automatisch nehmen
*
* Revision 1.2  2010-09-08 10:08:50  willuhn
* *** empty log message ***
*
* Revision 1.1  2010-09-07 15:28:05  willuhn
* @N BUGZILLA 391 - Kartenleser-Konfiguration komplett umgebaut. Damit lassen sich jetzt beliebig viele Kartenleser und Konfigurationen parellel einrichten
*
**********************************************************************/
TOP

Related Classes of de.willuhn.jameica.hbci.passports.ddv.DDVConfigFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.