Java tutorial
/********************************************************************** * * Copyright (c) 2004 Olaf Willuhn * All rights reserved. * * This software is copyrighted work licensed under the terms of the * Jameica License. Please consult the file "LICENSE" for details. * **********************************************************************/ package de.willuhn.jameica.hbci.passports.pintan.server; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.ArrayList; import org.apache.commons.lang.StringUtils; import org.kapott.hbci.callback.HBCICallback; import org.kapott.hbci.manager.HBCIHandler; import org.kapott.hbci.manager.HBCIVersion; import org.kapott.hbci.passport.AbstractHBCIPassport; import org.kapott.hbci.passport.AbstractPinTanPassport; import org.kapott.hbci.passport.HBCIPassport; import de.willuhn.datasource.GenericIterator; import de.willuhn.jameica.hbci.HBCI; import de.willuhn.jameica.hbci.HBCICallbackSWT; import de.willuhn.jameica.hbci.gui.DialogFactory; import de.willuhn.jameica.hbci.gui.action.PassportProcessCode3072; import de.willuhn.jameica.hbci.passport.PassportHandle; import de.willuhn.jameica.hbci.passports.pintan.ChipTANDialog; import de.willuhn.jameica.hbci.passports.pintan.PhotoTANDialog; import de.willuhn.jameica.hbci.passports.pintan.PinTanConfigFactory; import de.willuhn.jameica.hbci.passports.pintan.PtSecMech; import de.willuhn.jameica.hbci.passports.pintan.PtSecMechDialog; import de.willuhn.jameica.hbci.passports.pintan.SelectConfigDialog; import de.willuhn.jameica.hbci.passports.pintan.TANDialog; import de.willuhn.jameica.hbci.passports.pintan.TanMediaDialog; import de.willuhn.jameica.hbci.passports.pintan.rmi.PinTanConfig; import de.willuhn.jameica.hbci.rmi.HibiscusDBObject; import de.willuhn.jameica.hbci.rmi.Konto; import de.willuhn.jameica.hbci.server.Converter; import de.willuhn.jameica.hbci.server.hbci.HBCIContext; import de.willuhn.jameica.messaging.StatusBarMessage; import de.willuhn.jameica.plugin.AbstractPlugin; import de.willuhn.jameica.system.Application; import de.willuhn.jameica.system.OperationCanceledException; import de.willuhn.logging.Logger; import de.willuhn.util.ApplicationException; import de.willuhn.util.I18N; /** * Implementierung des Passports vom Typ "Chipkarte" (DDV). */ public class PassportHandleImpl extends UnicastRemoteObject implements PassportHandle { private final static I18N i18n = Application.getPluginLoader().getPlugin(HBCI.class).getResources().getI18N(); private HBCIPassport hbciPassport = null; private HBCIHandler handler = null; private PassportImpl passport = null; private PinTanConfig config = null; /** * ct. * @param passport * @throws RemoteException */ public PassportHandleImpl(PassportImpl passport) throws RemoteException { super(); this.passport = passport; } /** * @param config * @throws RemoteException */ public PassportHandleImpl(PinTanConfig config) throws RemoteException { super(); this.config = config; } /** * @see de.willuhn.jameica.hbci.passport.PassportHandle#open() */ public HBCIHandler open() throws RemoteException, ApplicationException { if (isOpen()) return handler; Logger.info("open pin/tan passport"); try { if (config == null && this.passport == null) throw new ApplicationException(i18n.tr("Keine Konfiguration oder Konto ausgewhlt")); if (config == null && this.passport != null && this.passport.getKonto() != null) config = PinTanConfigFactory.findByKonto(this.passport.getKonto()); // Mh, nichts da zum Laden, dann fragen wir mal den User if (config == null) { GenericIterator list = PinTanConfigFactory.getConfigs(); if (list == null || list.size() == 0) throw new ApplicationException(i18n.tr("Bitte legen Sie zuerst eine PIN/TAN-Konfiguration an")); // Wir haben nur eine Config, dann brauchen wir den User nicht fragen if (list.size() == 1) { config = (PinTanConfig) list.next(); } else { SelectConfigDialog d = new SelectConfigDialog(SelectConfigDialog.POSITION_CENTER, list); try { config = (PinTanConfig) 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 PIN/TAN-Konfiguration")); } } } if (config == null) throw new ApplicationException(i18n.tr("Keine PIN/TAN-Konfiguration fr dieses Konto definiert")); Logger.debug("using passport file " + config.getFilename()); AbstractPlugin plugin = Application.getPluginLoader().getPlugin(HBCI.class); HBCICallback callback = ((HBCI) plugin).getHBCICallback(); if (callback != null && (callback instanceof HBCICallbackSWT)) ((HBCICallbackSWT) callback).setCurrentHandle(this); hbciPassport = config.getPassport(); { AbstractHBCIPassport ap = (AbstractHBCIPassport) hbciPassport; // Wir speichern die verwendete PIN/TAN-Config im Passport. Dann wissen wir // spaeter in den HBCI-Callbacks noch, aus welcher Config der Passport // erstellt wurde. Wird z.Bsp. vom Payment-Server benoetigt. ap.setPersistentData(CONTEXT_CONFIG, config); String cannationalacc = config.getCustomProperty("cannationalacc"); if (cannationalacc != null) ap.setPersistentData("cannationalacc", cannationalacc); } String hbciVersion = config.getHBCIVersion(); if (hbciVersion == null || hbciVersion.length() == 0) hbciVersion = HBCIVersion.HBCI_300.getId(); Logger.info("[PIN/TAN] url : " + config.getURL()); Logger.info("[PIN/TAN] blz : " + config.getBLZ()); Logger.info("[PIN/TAN] filter : " + config.getFilterType()); Logger.info("[PIN/TAN] HBCI version: " + hbciVersion); ////////////////////// // BUGZILLA 831 // Siehe auch Stefans Mail vom 10.03.2010 - Betreff "Re: [hbci4java] Speicherung des TAN-Verfahrens im PIN/TAN-Passport-File?" PtSecMech mech = config.getStoredSecMech(); String secmech = mech != null ? StringUtils.trimToNull(mech.getId()) : null; Logger.info("[PIN/TAN] using stored tan sec mech: " + (mech != null ? mech.toString() : "<ask-user>")); ((AbstractPinTanPassport) hbciPassport).setCurrentTANMethod(secmech); ////////////////////// handler = new HBCIHandler(hbciVersion, hbciPassport); return handler; } catch (RemoteException re) { close(); throw re; } catch (ApplicationException ae) { close(); throw ae; } catch (OperationCanceledException oce) { close(); throw oce; } catch (Exception e) { close(); Logger.error("error while opening pin/tan passport", e); throw new RemoteException("error while opening pin/tan passport", e); } } /** * @see de.willuhn.jameica.hbci.passport.PassportHandle#isOpen() */ public boolean isOpen() throws RemoteException { return handler != null && hbciPassport != null; } /** * @see de.willuhn.jameica.hbci.passport.PassportHandle#close() */ public void close() throws RemoteException { if (hbciPassport == null && handler == null) return; try { this.handleCode3072(); } finally { try { Logger.info("closing pin/tan passport"); handler.close(); } catch (Exception e) { /*useless*/} hbciPassport = null; handler = null; AbstractPlugin plugin = Application.getPluginLoader().getPlugin(HBCI.class); HBCICallback callback = ((HBCI) plugin).getHBCICallback(); if (callback != null && (callback instanceof HBCICallbackSWT)) ((HBCICallbackSWT) callback).setCurrentHandle(null); Logger.info("pin/tan passport closed"); } } /** * Behandelt die GAD-spezifische Rueckmeldung zur Aenderung der Kundenkennung */ private void handleCode3072() { if (hbciPassport == null) return; try { new PassportProcessCode3072().handleAction(hbciPassport); } catch (Exception e) { Logger.error("error while applying new user-/customer data", e); Application.getMessagingFactory() .sendMessage(new StatusBarMessage( i18n.tr("Fehler beim bernehmen der genderten Zugangsdaten: {0}", e.getMessage()), StatusBarMessage.TYPE_ERROR)); } } /** * @see de.willuhn.jameica.hbci.passport.PassportHandle#getKonten() */ public Konto[] getKonten() throws RemoteException, ApplicationException { Logger.info("reading accounts from pin/tan passport"); try { open(); org.kapott.hbci.structures.Konto[] konten = hbciPassport.getAccounts(); if (konten == null || konten.length == 0) { Logger.info("no accounts found"); return new Konto[] {}; } ArrayList result = new ArrayList(); Konto k = null; for (int i = 0; i < konten.length; ++i) { k = Converter.HBCIKonto2HibiscusKonto(konten[i], PassportImpl.class); Logger.debug("found account " + k.getKontonummer()); result.add(k); } return (Konto[]) result.toArray(new Konto[result.size()]); } finally { try { close(); } catch (RemoteException e2) { /*useless*/} } } /** * @see de.willuhn.jameica.hbci.passport.PassportHandle#callback(org.kapott.hbci.passport.HBCIPassport, int, java.lang.String, int, java.lang.StringBuffer) */ public boolean callback(HBCIPassport passport, int reason, String msg, int datatype, StringBuffer retData) throws Exception { switch (reason) { case HBCICallback.NEED_PT_PIN: { retData.replace(0, retData.length(), DialogFactory.getPIN(passport)); return true; } case HBCICallback.NEED_PT_PHOTOTAN: { Logger.debug("got phototan code, using phototan dialog"); TANDialog dialog = new PhotoTANDialog(config, retData.toString()); dialog.setContext(this.getContext(passport)); dialog.setText(msg); retData.replace(0, retData.length(), (String) dialog.open()); return true; } case HBCICallback.NEED_PT_TAN: { TANDialog dialog = null; String flicker = retData.toString(); if (flicker != null && flicker.length() > 0) { Logger.debug("got flicker code " + flicker); // Wir haben einen Flicker-Code. Also zeigen wir den Flicker-Dialog statt // dem normalen TAN-Dialog an Logger.info("using chiptan OPTIC/USB"); dialog = new ChipTANDialog(config, flicker); } // regulaerer TAN-Dialog if (dialog == null) { Logger.info("using chiptan MANUAL"); Logger.debug("using regular tan dialog"); dialog = new TANDialog(config); } dialog.setContext(this.getContext(passport)); dialog.setText(msg); retData.replace(0, retData.length(), (String) dialog.open()); return true; } // BUGZILLA 200 case HBCICallback.NEED_PT_SECMECH: { if (config != null) { PtSecMech mech = config.getStoredSecMech(); String type = mech != null ? StringUtils.trimToNull(mech.getId()) : null; if (type != null) { // Wir checken vorher noch, ob es das TAN-Verfahren ueberhaupt noch gibt PtSecMech m = PtSecMech.contains(retData.toString(), type); if (m != null) { // Jepp, gibts noch retData.replace(0, retData.length(), type); return true; } } } PtSecMechDialog ptd = new PtSecMechDialog(config, retData.toString()); retData.replace(0, retData.length(), (String) ptd.open()); return true; } // BUGZILLA 827 case HBCICallback.NEED_PT_TANMEDIA: { // Wenn wir eine Medienbezeichnung von HBCI4Java gekriegt haben und das genau // eine einzige ist. Dann uebernehmen wir diese ohne Rueckfrage. Der User // hat hier sonst eh keine andere Wahl. String media = retData.toString(); if (media.length() > 0 && !media.contains("|")) { Logger.info("having exactly one TAN media name (provided by institute) - automatically using this: " + media); retData.replace(0, retData.length(), media); return true; } // Falls wir eine PIN/TAN-Config haben, in der die Medienbezeichnung // hinterlegt ist, dann nehmen wir die. if (config != null) { media = config.getTanMedia(); if (media != null && media.length() > 0) { Logger.info("having a stored TAN media name (provided by user) - automatically using this: " + media); retData.replace(0, retData.length(), media); return true; } } Logger.info("asking user for TAN media (options provided by institute: " + media + ")"); TanMediaDialog tmd = new TanMediaDialog(config, retData.toString()); retData.replace(0, retData.length(), (String) tmd.open()); return true; } } return false; } /** * Versucht den zugehoerigen Auftrag zu ermitteln. * @param passport der Passport. * @return der Auftrag oder NULL, wenn er nicht ermittelbar war. */ private HibiscusDBObject getContext(HBCIPassport passport) { String externalId = null; try { if (!(passport instanceof AbstractHBCIPassport)) return null; externalId = (String) ((AbstractHBCIPassport) passport).getPersistentData("externalid"); return HBCIContext.unserialize(externalId); } catch (Exception e) { Logger.error("unable to load transfer for external id: " + externalId, e); } return null; } }