DE ♦ EN

IBAN-BIC.com (Theano GmbH)  » Web Service  » Documentation  » Sample Clients  » Beispiel: Java

Forgot password?

Contact
us

New customer? Register

Using SOAP with Java

The main challenge to overcome is the fact that our "Extended Validation" SSL certificate comes from a certification authority which is not by default recognized by Java.

Mr. Hillbrecht of cantamen provided the following solution:

Sample Code

  1. // $Id $
  2. // (C) cantamen/Dirk Hillbrecht 2013. Released under the LGPL 2.0 or higher.
  3. // Version: 2013-10-23-02
  4. // For more information, contact info@cantamen.de or dh@cantamen.de. See http://www.cantamen.de
  5. package ENTER-PACKAGE-HERE;
  6.  
  7. import java.io.*;
  8. import java.net.HttpURLConnection;
  9. import java.net.URL;
  10. import java.security.*;
  11. import java.security.cert.*;
  12. import java.security.cert.Certificate;
  13.  
  14. import javax.net.ssl.*;
  15. import javax.xml.parsers.DocumentBuilderFactory;
  16.  
  17. import org.w3c.dom.*;
  18.  
  19. /** Connector to IBAN conversion service from Theano GmbH/IBAN-BIC.com.
  20. *
  21. * This is a Java-6-SE-only class which connects to the IBAN conversion service of Theano GmbH as described on www.iban-bic.com.
  22. * It hides all the implementation of the connection behind some nice Java classes which do the dirty work.
  23. * <p>
  24. * Use this by creating one instance of the connector per thread and then calling generateIBAN() or another of the top level public
  25. * methods. The methods run synchronously and return either one of the defined result object (e.g. IBANReply) or throw an
  26. * IBANConverterException. Assuming the existance of some "BankAccountData" data type, a typical usage could be like this:
  27. *
  28. * <code>
  29. IBANConverterServiceConnector connector=new IBANConverterServiceConnector("username","secret");
  30. for (BankAccountData accountdata:getSomeBankAccountData(...whatever...)) {
  31.   try {
  32.     IBANConverterServiceConnector.IBANReply ibanreply=connector.generateIBAN(accountdata.getCountryCode(),accountdata.getBankCode(),accountdata.getAccountNumber());
  33.     if (ibanreply.isPassed() && ibanreply.getResultCode()==0)
  34.       accountdata.setIBAN(ibanreply.getIBAN());
  35.     else {
  36.       accountdata.setProbableIBAN(ibanreply.getIBAN());
  37.       accountdata.setIBANResultCode(ibanreply.getResultCode());
  38.     }
  39.   }
  40.   catch (IBANConverterException ice) {
  41.     accountdata.setIBANConversionProblem(ice);
  42.   }
  43. }</code>
  44. *
  45. * The class contains some static helper classes for result and exception transport. It is fully self-contained with no other external references but the Java 6 SE
  46. * runtime environment.
  47. * <p>
  48. * Internally, IBANConverterServiceConnector connects to the service via its HTTP-based interface. It passes the information through URL parameters and receives
  49. * the reply as XML string in the HTTP query response. That one is converted into a DOM tree from where the reply data is extracted and stored in the reply class.
  50. * The class does not use any SOAP or other frameworks above the W3C DOM system.
  51. *
  52. * @author (C) cantamen/Dirk Hillbrecht 2013. Released under the LGPL 2.0 or higher. For more information, contact info@cantamen.de or dh@cantamen.de. See http://www.cantamen.de
  53. * @version $Id $
  54. */
  55. public class IBANConverterServiceConnector {
  56.  
  57.   // **************************************************
  58.   // *** Public interface and public helper classes ***
  59.   // **************************************************
  60.  
  61.   /** Global flag to set this into debug mode.
  62.    *
  63.    * If set to true, the whole connector does <em>not</em> query the conversion service over the web, but simply returns a precompiled answer.
  64.    * Set this to true during development and debugging so that you do not call the service everytime you run your tests. In production environments,
  65.    * this should always be set to false.
  66.    */
  67.   private static final boolean DEBUG=false;
  68.  
  69.   /** Instantiate a service connector for the IBAN conversion.
  70.    *
  71.    * Converters are single-threaded! It takes the username/password information which are used for all ongoing queries.
  72.    *
  73.    * @param usernamex Username to use for the IBAN conversion service
  74.    * @param passwordx Passwort for authenticating to the IBAN conversion service
  75.    */
  76.   public IBANConverterServiceConnector(String usernamex,String passwordx) {
  77.     username=usernamex;
  78.     password=passwordx;
  79.     /* - This is for password hashing which does not seem to work on Java
  80.     try {
  81.       md5 = MessageDigest.getInstance("MD5");
  82.     }
  83.     catch (NoSuchAlgorithmException e) {
  84.       throw new IllegalStateException("error.nomd5digesterfound",e);
  85.     }
  86.     */
  87.     dbf=DocumentBuilderFactory.newInstance();
  88.     dbf.setValidating(false);
  89.     dbf.setIgnoringComments(false);
  90.     dbf.setIgnoringElementContentWhitespace(true);
  91.     dbf.setNamespaceAware(true);
  92.     // dbf.setCoalescing(true);
  93.     // dbf.setExpandEntityReferences(true);
  94.  
  95.   }
  96.  
  97.   /** Special exception class for signalling problems with the IBAN conversion.
  98.    *
  99.    * This exception is thrown if something goes severely wrong with the IBAN conversion. It is only thrown if the service is cannot be connected
  100.    * or returns syntactically unexpected replies. If the IBAN was incontructible from the given data, no exception is thrown but instead a reply
  101.    * is returned which describes the problems.
  102.    * <p>
  103.    * This exceptions is derived from RuntimeException so that you might more or less "ignore" it while coding. You should not do, however, as such
  104.    * behaviour will always bite you and your project when you do not expect it.
  105.    */
  106.   public static class IBANConverterException extends RuntimeException {
  107.     public IBANConverterException(String s) { super(s); }
  108.     public IBANConverterException(String s,Throwable c) { super(s,c); }
  109.   }
  110.  
  111.   /** Reply class for IBAN query results.
  112.    *
  113.    * This class is returned by generateIBAN() and friends. It contains the - probably - generated IBAN and other values as they are returned by the
  114.    * IBAN conversion web service. An instance of this class is immutable.
  115.    */
  116.   public static class IBANReply {
  117.     private final String iban;
  118.     private final boolean passed;
  119.     private final int resultcode;
  120.     private final int balance;
  121.     public IBANReply(String ibanx,boolean passedx,int resultcodex,int balancex) {
  122.       iban=ibanx;passed=passedx;resultcode=resultcodex;balance=balancex;
  123.     }
  124.     /** Return the IBAN as created by the service. */
  125.     public String getIBAN() { return iban; }
  126.     /** Return whether the IBAN generation passed or failed ("result" value of the IBAN creation service) */
  127.     public boolean isPassed() { return passed; }
  128.     /** Return the result code as generated by the IBAN creation service. */
  129.     public int getResultCode() { return resultcode; }
  130.     /** Returns the account balance information from the IBAN creation service. */
  131.     public int getBalance() { return balance; }
  132.     /** Return a string representation. */
  133.     @Override
  134.     public String toString() { return "{IBANReply, passed: "+passed+", result code: "+resultcode+", IBAN: "+iban+", balance: "+balance+"}"; }
  135.   }
  136.  
  137.   /** Builder for the IBANReply class. */
  138.   private static class IBANReplyBuilder {
  139.     private String iban=""; public IBANReplyBuilder setIBAN(String ibanx) { iban=ibanx; return this; }
  140.     private boolean passed=false; public IBANReplyBuilder setResult(String resultstring) { passed="passed".equalsIgnoreCase(resultstring); return this; }
  141.     private int resultcode=-1; public IBANReplyBuilder setResultCode(String resultcodestring) { resultcode=Integer.parseInt(resultcodestring); return this; }
  142.     private int balance=-1; public IBANReplyBuilder setBalance(String balancestring) { balance=Integer.parseInt(balancestring); return this; }
  143.     public IBANReply build() { return new IBANReply(iban,passed,resultcode,balance); }
  144.   }
  145.  
  146.   /** Convert a legacy German bankcode/account pair to an IBAN.
  147.    *
  148.    * This method gets a german bank account at a German bank and returns the IBAN for this account. The result also contains result and error codes of
  149.    * the conversion.
  150.    *
  151.    * @param bankcode Bank code of the account to convert
  152.    * @param account Account number
  153.    * @returns IBANReply instance with the generated IBAN or the appropriate error information if no IBAN was created.
  154.    */
  155.   public IBANReply generateGermanIBAN(String bankcode,String account) throws IBANConverterException {
  156.     return generateIBAN("DE",bankcode,account);
  157.   }
  158.  
  159.   /** Convert a legacy bankcode/account pair to an IBAN.
  160.    *
  161.    * This method gets a bank account at a bank in the country given by the country code and returns the IBAN for this account.
  162.    * The result also contains result and error codes of the conversion.
  163.    *
  164.    * @param countrycode 2-character ISO country code of the account's and bank's country
  165.    * @param bankcode Bank code of the account to convert
  166.    * @param account Account number
  167.    * @returns IBANReply instance with the generated IBAN or the appropriate error information if no IBAN was created.
  168.    */
  169.   public IBANReply generateIBAN(String countrycode,String bankcode,String account) throws IBANConverterException {
  170.     try {
  171.       Document reply;
  172.       if (DEBUG) {
  173.         System.err.println("IBAN converter in DEBUG MODE!!!");
  174.         reply=dbf.newDocumentBuilder().parse(new ByteArrayInputStream(debugresult.getBytes()));
  175.       }
  176.       else {
  177.         URL url = new URL(generateCalculateIBANURL(countrycode,bankcode,account));
  178.         HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
  179.         try {
  180.           // Here we set the special socket factory for accessing the IBAN service
  181.           con.setSSLSocketFactory(ibanrechnersslcontext.getSocketFactory());
  182.           if (con.getResponseCode()!=HttpURLConnection.HTTP_OK)
  183.             throw new IllegalStateException("error.httpnotok|"+con.getResponseCode()+"|"+con.getResponseMessage());
  184.           // We have to remove any leading empty lines from the body as this confuses the DOM parser. So, eat up characters until "<" appears.
  185.           PushbackInputStream pbis=new PushbackInputStream(con.getInputStream());
  186.           int ch;
  187.           while ((ch=pbis.read())=='\n'){}
  188.           pbis.unread(ch);
  189.           reply=dbf.newDocumentBuilder().parse(pbis);
  190.         }
  191.         finally {
  192.           con.disconnect();
  193.         }
  194.       }
  195.       if (reply==null)
  196.         throw new IllegalStateException("error.noreply");
  197.       Node result=reply.getFirstChild();
  198.       if (result==null)
  199.         throw new IllegalStateException("error.noresultnode");
  200.       if (!"result".equals(result.getNodeName()))
  201.         throw new IllegalStateException("error.resultnodename|"+result.getNodeName());
  202.  
  203.       IBANReplyBuilder builder=new IBANReplyBuilder();
  204.       NodeList nl=result.getChildNodes();
  205.       for (int i=0;i<nl.getLength();i++) {
  206.         Node n=nl.item(i);
  207.         //System.out.println("Node "+i+": "+nl.item(i).getNodeName());
  208.         if ("iban".equals(n.getNodeName())) builder.setIBAN(n.getFirstChild().getNodeValue());
  209.         else if ("result".equals(n.getNodeName())) builder.setResult(n.getFirstChild().getNodeValue());
  210.         else if ("return_code".equals(n.getNodeName())) builder.setResultCode(n.getFirstChild().getNodeValue());
  211.         else if ("balance".equals(n.getNodeName())) builder.setBalance(n.getFirstChild().getNodeValue());
  212.       }
  213.       return builder.build();
  214.     }
  215.     catch (Exception e) {
  216.       throw new IBANConverterException("Access problem occurred",e);
  217.     }
  218.  
  219.   }
  220.  
  221.   // *********************************************
  222.   // *** Static internal operation environment ***
  223.   // *********************************************
  224.  
  225.   /** Specially crafted result returned in debug mode regardless of account data given for IBAN conversion. */
  226.   private static final String debugresult="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
  227.           "<result><iban>DE74250501800012345678</iban><result>passed</result><return_code>0</ret"+
  228.           "urn_code><ibanrueck_return_code></ibanrueck_return_code><checks-list><checks>length</"+
  229.           "checks><checks>bank_code</checks><checks>account_number</checks></checks-list><bic_ca"+
  230.           "ndidates-list><bic_candidates><bic>SPKHDE2HXXX</bic><zip>30001</zip><city>Hannover</c"+
  231.           "ity><wwwcount>0</wwwcount><sampleurl></sampleurl></bic_candidates></bic_candidates-li"+
  232.           "st><country>DE</country><bank_code>25050180</bank_code><alternative_bank_code></alter"+
  233.           "native_bank_code><bank>Sparkasse Hannover</bank><bank_address></bank_address><bank_ur"+
  234.           "l></bank_url><branch></branch><branch_code></branch_code><in_scl_directory>yes</in_sc"+
  235.           "l_directory><sct>yes</sct><sdd>yes</sdd><b2b>yes</b2b><account_number>12345678</accou"+
  236.           "nt_number><alternative_account_number></alternative_account_number><account_validatio"+
  237.           "n_method>A3</account_validation_method><account_validation>Methode 10, Konto 00123456"+
  238.           "78, BLZ 25050180, Prüfziffer 7 steht an Position 10, erwartete Prüfziffer: 7. Überbli"+
  239.           "ck über die Berechnung: Nimm die Ziffern auf den Positionen 1 bis 9 - hier: 001234567"+
  240.           " -, multipliziere sie von rechts nach links mit den Gewichten 2,3,4,5,6,7,8,9,10, add"+
  241.           "iere die Produkte, bilde den Rest der Division durch 11, ziehe das Ergebnis von 11 ab"+
  242.           ",  und das Ergebnis modulo 11 ist die erwartete Prüfziffer.</account_validation><leng"+
  243.           "th_check>passed</length_check><account_check>passed</account_check><bank_code_check>p"+
  244.           "assed</bank_code_check><bic_plausibility_check></bic_plausibility_check><data_age>201"+
  245.           "30805</data_age><IBANformat>DEkk BBBB BBBB CCCC CCCC CC</IBANformat><formatcomment>B "+
  246.           "= sort code (BLZ), C = account No.</formatcomment><balance>0</balance></result>";
  247.  
  248.   /** Trust manager for https://ssl.ibanrechner.de
  249.    *
  250.    * That system, which implements the IBAN conversion service, uses a certificate which is not signed by a CA known to the Java Runtime Environment.
  251.    * So, we implement our own trust manager which trusts only exactly one certificate: That one of ssl.ibanrechner.de.
  252.    */
  253.   private static class IBANRechnerTrustManager implements X509TrustManager {
  254.  
  255.     /** The certificate has been loaded directly from ssl.ibanrechner.de. */
  256.     private static String ibanservercertstring="-----BEGIN CERTIFICATE-----\n"+
  257.             "MIIJqjCCCJKgAwIBAgICBeUwDQYJKoZIhvcNAQEFBQAwgYExCzAJBgNVBAYTAklM\n"+
  258.             "MRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSkwJwYDVQQLEyBTdGFydENvbSBDZXJ0\n"+
  259.             "aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmU3RhcnRDb20gRXh0ZW5kZWQg\n"+
  260.             "VmFsaWRhdGlvbiBTZXJ2ZXIgQ0EwHhcNMTIwNzAxMDIyNzI2WhcNMTQwNzAzMDUy\n"+
  261.             "NTEwWjCCAV0xGTAXBgNVBA0TEEs5TGIzMDJtS1Z5UVM1TVgxCzAJBgNVBAYTAkRF\n"+
  262.             "MRYwFAYDVQQIEw1OaWVkZXJzYWNoc2VuMRIwEAYDVQQHEwlIYXNiZXJnZW4xDjAM\n"+
  263.             "BgNVBBETBTQ5MjA1MRUwEwYDVQQJEwxLaWVmZXJud2VnIDgxFDASBgNVBAoTC1Ro\n"+
  264.             "ZWFubyBHbWJIMRswGQYDVQQDExJzc2wuaWJhbnJlY2huZXIuZGUxKDAmBgkqhkiG\n"+
  265.             "9w0BCQEWGXBvc3RtYXN0ZXJAaWJhbnJlY2huZXIuZGUxEzARBgNVBAUTCkhSQiAy\n"+
  266.             "MDU0MzYxHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRowGAYLKwYBBAGC\n"+
  267.             "NzwCAQEUCU9zbmFicvxjazEeMBwGCysGAQQBgjc8AgECEw1OaWVkZXJzYWNoc2Vu\n"+
  268.             "MRMwEQYLKwYBBAGCNzwCAQMTAkRFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"+
  269.             "CgKCAQEApNXKYi+/ifySs2swAb6PaLQ1gO2SkdJwF5rks81TEQMRCgBeC+oCNJ/6\n"+
  270.             "e+nNHu8v8nybIH3liFnAhpkjYUkQMz9Z3CsBETtfkOVB0alOcSqpOwRmojZ/NruZ\n"+
  271.             "sfuGcnrNhAs0l8bwFCEMOH9YGxP4O28QXlN/9kPvEGc7WynamNNlXfFqsNMFdixu\n"+
  272.             "DdEMWO2PkDHxfY+ZbgHVtYxYgaPP/gDLBFov23WDAOz2mkSwvgykg9MK2myaluq6\n"+
  273.             "3MhWRbR8z6uTJTEQ0oir+28BK59EBuzgEWKlWwe3xBo171MFYgXL00IVUAP0lDd6\n"+
  274.             "LImD9srrY6BeV+03QX+1HP/KjiHGdQIDAQABo4IFSzCCBUcwCQYDVR0TBAIwADAL\n"+
  275.             "BgNVHQ8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1Ud\n"+
  276.             "DgQWBBSFgs0yimIu/GZxNQ5r3TaZmtL2DTAfBgNVHSMEGDAWgBSh4Z5FJXlNBtkC\n"+
  277.             "F5KC1TCJciUUoDCCAWsGA1UdEQSCAWIwggFeghJzc2wuaWJhbnJlY2huZXIuZGWC\n"+
  278.             "DmliYW5yZWNobmVyLmRlggxpYmFuLWJpYy5jb22CEWJhazEuaWJhbi1iaWMuY29t\n"+
  279.             "ghFiYWsyLmliYW4tYmljLmNvbYIJdGhlYW5vLmRlgg1zc2wudGhlYW5vLmRlghBk\n"+
  280.             "ZXYuaWJhbi1iaWMuY29tghBzc2wuaWJhbi1iaWMuY29tghJpYmFuY2FsY3VsYXRv\n"+
  281.             "ci5jb22CFnNzbC5pYmFuY2FsY3VsYXRvci5jb22CD2liYW4tcmVjaG5lci5kZYIT\n"+
  282.             "c3NsLmliYW4tcmVjaG5lci5kZYIUbm9jaGJpbGxpZ2VyZmF4ZW4uZGWCGHd3dy5u\n"+
  283.             "b2NoYmlsbGlnZXJmYXhlbi5kZYIMc2VwYXRvb2xzLmV1ghFiYWsxLnNlcGF0b29s\n"+
  284.             "cy5ldYIRYmFrMi5zZXBhdG9vbHMuZXWCEHNzbC5zZXBhdG9vbHMuZXUwggJwBgNV\n"+
  285.             "HSAEggJnMIICYzALBgkrBgEEAYG1NwIwDQYLKwYBBAGBtTcBAQEwggJDBgsrBgEE\n"+
  286.             "AYG1NwECAjCCAjIwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29t\n"+
  287.             "L3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t\n"+
  288.             "L2ludGVybWVkaWF0ZS5wZGYwMAYIKwYBBQUHAgEWJGh0dHA6Ly93d3cuc3RhcnRz\n"+
  289.             "c2wuY29tL2V4dGVuZGVkLnBkZjCB+AYIKwYBBQUHAgIwgeswJxYgU3RhcnRDb20g\n"+
  290.             "Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwAwIBARqBv1RoaXMgY2VydGlmaWNhdGUg\n"+
  291.             "d2FzIGlzc3VlZCBhY2NvcmRpbmcgdG8gdGhlIEV4dGVuZGVkIFZhbGlkYXRpb24g\n"+
  292.             "cmVxdWlyZW1lbnRzIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNl\n"+
  293.             "IG9ubHkgZm9yIHRoZSBpbnRlbmRlZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2Yg\n"+
  294.             "dGhlIHJlbHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMIGcBggrBgEFBQcCAjCBjzAn\n"+
  295.             "FiBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTADAgECGmRMaWFiaWxp\n"+
  296.             "dHkgYW5kIHdhcnJhbnRpZXMgYXJlIGxpbWl0ZWQhIFNlZSBzZWN0aW9uICJMZWdh\n"+
  297.             "bCBhbmQgTGltaXRhdGlvbnMiIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3kuMDUG\n"+
  298.             "A1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL2NydDQtY3Js\n"+
  299.             "LmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcwAYYtaHR0cDovL29jc3Au\n"+
  300.             "c3RhcnRzc2wuY29tL3N1Yi9jbGFzczQvc2VydmVyL2NhMEIGCCsGAQUFBzAChjZo\n"+
  301.             "dHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3M0LnNlcnZlci5j\n"+
  302.             "YS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFydHNzbC5jb20vMA0GCSqG\n"+
  303.             "SIb3DQEBBQUAA4IBAQCF4VcMd0hbSOUPPKfAnBzAOAIC/Vboe/CX+txikFhx2Thv\n"+
  304.             "i7GY2W7GfYAbS6ZgmFTwXN1RwUKmQi0e1x9dKRK7iT45R1r7qMBXFAYUnzidlx+0\n"+
  305.             "tHVbdS3UvOa+1SoInEKogR9hxxnVO3x4zVJCRsMzFVwj8rRxeKsNT15+SUNRC26s\n"+
  306.             "j67cqtRWZk3b71xssl0ZjYtH3x5sOvpZOb6gelGZ1cSscoIeCIjPm8/nCvgTspNu\n"+
  307.             "BfFmhb73VSTm9/25GA2FMtd7Lx6qGJwofxFPCZx+oLQjpjYK+qMeijOTdQGAV1QM\n"+
  308.             "gnyL5ADQPfQoIBolCEB6XGN614r0ydM8wh6QgIib\n"+
  309.             "-----END CERTIFICATE-----\n";
  310.  
  311.     private X509TrustManager pkixTrustManager;
  312.  
  313.     public IBANRechnerTrustManager() throws CertificateException, KeyStoreException, NoSuchAlgorithmException, IOException {
  314.  
  315.       // This code is ruthlessly borrowed from StackOverflow, http://stackoverflow.com/questions/3247746/java-loading-ssl-keystore-via-a-resource
  316.  
  317.       Certificate ibanrechnercert = CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(ibanservercertstring.getBytes()));
  318.  
  319.       KeyStore keyStore = KeyStore.getInstance("JKS");
  320.       keyStore.load(null, "".toCharArray());
  321.       keyStore.setCertificateEntry("ibanrechner.de", ibanrechnercert);
  322.  
  323.       TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
  324.       trustManagerFactory.init(keyStore);
  325.  
  326.       TrustManager trustManagers[] = trustManagerFactory.getTrustManagers();
  327.  
  328.       for(TrustManager trustManager : trustManagers) {
  329.         if(trustManager instanceof X509TrustManager) {
  330.           pkixTrustManager = (X509TrustManager) trustManager;
  331.           return;
  332.         }
  333.       }
  334.  
  335.       throw new IllegalStateException("error.couldnotinit"); // Must not happen
  336.     }
  337.  
  338.     public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { pkixTrustManager.checkServerTrusted(chain, authType); }
  339.     public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { pkixTrustManager.checkServerTrusted(chain, authType); }
  340.     public X509Certificate[] getAcceptedIssuers() { return pkixTrustManager.getAcceptedIssuers(); }
  341.   }
  342.  
  343.   /** SSL context for establishing a connection to the service. */
  344.   private static SSLContext ibanrechnersslcontext;
  345.  
  346.   static {
  347.     // Instantiate the SSL context once and for all
  348.     try {
  349.       ibanrechnersslcontext = SSLContext.getInstance("SSL");
  350.       ibanrechnersslcontext.init(null, new TrustManager[] { new IBANRechnerTrustManager() }, null);
  351.     }
  352.     catch (Exception e) {
  353.       e.printStackTrace();
  354.     }
  355.   }
  356.  
  357.   /** Common first part of URL to access IBAN conversion service. */
  358.   private static final String URLBASE="https://ssl.ibanrechner.de/http.html?";
  359.  
  360.   // *******************************************
  361.   // *** Internal helper classes and methods ***
  362.   // *******************************************
  363.  
  364.   /** Username for talking to the IBAN conversion service. */
  365.   private final String username;
  366.  
  367.   /** Passwort for authentication against the IBAN conversion service. */
  368.   private final String password;
  369.  
  370.   // /** Common digester for creating the password hash for the queries. */
  371.   // private final MessageDigest md5;  - This does not seem to work
  372.  
  373.   /** XML document builder factory for the Java DOM framework */
  374.   private final DocumentBuilderFactory dbf;
  375.  
  376.   /** Generate the URL for querying an IBAN from a bankcode and a bank account number. */
  377.   private String generateCalculateIBANURL(String countrycode,String bankcode,String account) {
  378.     // This does not seem to work with Java's md5() function.
  379.     //String pwhash=DatatypeConverter.printHexBinary(md5.digest(new StringBuilder().append("calculate_iban").append(username).append(account).append(password).toString().getBytes()));
  380.     return URLBASE+"function=calculate_iban&country="+countrycode+"&bankcode="+bankcode+"&account="+account+"&user="+username+"&password="+password;
  381.   }
  382.  
  383.   // **************************
  384.   // *** Debug main program ***
  385.   // **************************
  386.  
  387.   /** Test main program. To be removed once everything is working. */
  388.   public static void main(String[] args) {
  389.     if (args.length<5)
  390.       System.out.println("Usage: "+IBANConverterServiceConnector.class.getName()+" country_code bank_code account_number username password");
  391.     else
  392.       System.out.println(new IBANConverterServiceConnector(args[3],args[4]).generateIBAN(args[0],args[1],args[2]).toString());
  393.   }
  394.  
  395. }
  396.  
  397. // end of file
  398.