public void parseImpl(String configFileName)
      throws FileNotFoundException, ConfigXMLParsingException {
    InputStream is = null;
    try {
      is = new FileInputStream(configFileName);

      Document configDoc = XMLUtils.parse(is);

      NodeList nodes = configDoc.getElementsByTagName("SAMLFilterConfig").item(0).getChildNodes();
      int nodes_length = nodes.getLength();
      for (int i = 0; i < nodes_length; i++) {
        Node child = nodes.item(i);

        if (child.getNodeName().equals("LOCAL_ENTITY_ID")) {
          localEntityId = child.getFirstChild().getNodeValue();
        } else if (child.getNodeName().equals("SAML_POST_ATTRIBUTE_NAME")) {
          postAttrSAML = child.getFirstChild().getNodeValue();
        } else if (child.getNodeName().equals("MY_URI")) {
          myURI = child.getFirstChild().getNodeValue();
        } else if (child.getNodeName().equals("ASSERTION_SIGNATURE_VERIFICATION")) {
          try {
            verifySignature = VerifySignatureType.valueOf(child.getFirstChild().getNodeValue());
          } catch (IllegalArgumentException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid value specified for ASSERTION_SIGNATURE_VERIFICATION", e);
          }
        } else if (child.getNodeName().equals("REPLAY_MINUTES")) {
          try {
            replayMinutes = Integer.valueOf(child.getFirstChild().getNodeValue());
          } catch (NumberFormatException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            replayMinutes = 5;
          }
        } else if (child.getNodeName().equals("SAML_TOKEN_ENCRYPTION ")) {
          SAMLTokenEncryptedValue = XMLUtils.getAttribute(child, "ENABLED");
          SAMLTokenEncrypted = SAMLTokenEncryptedValue.equalsIgnoreCase("true");
          if (SAMLTokenEncrypted) {
            String algorithm = XMLUtils.getAttribute(child, "ALGORITHM");
            String init = XMLUtils.getAttribute(child, "INIT");
            String key = XMLUtils.getAttribute(child, "KEY");
            String mode = XMLUtils.getAttribute(child, "MODE");
            String padding = XMLUtils.getAttribute(child, "PADDING");
            SAMLTokenDecryptionKey = new SimpleKeyProperties();
            SAMLTokenDecryptionKey.setAlgorithm(algorithm);
            SAMLTokenDecryptionKey.setInit(init);
            SAMLTokenDecryptionKey.setKey(key);
            if (mode != null) {
              SAMLTokenDecryptionKey.setMode(mode);
            }
            if (padding != null) {
              SAMLTokenDecryptionKey.setPadding(padding);
            }
          }
        } else if (child.getNodeName().equals("SAML_ENCRYPTED_ASSERTION_DECRYPTOR")) {
          String decryptorClass = XMLUtils.getAttribute(child, "DecryptorClass");
          String keystore = XMLUtils.getAttribute(child, "KEYSTORE");
          String type = XMLUtils.getAttribute(child, "TYPE");
          String password = XMLUtils.getAttribute(child, "PASSWORD");
          String alias = XMLUtils.getAttribute(child, "ALIAS");
          String keyPassword = XMLUtils.getAttribute(child, "KEY_PASSWORD");
          decryptionKey = new KeyProperties();
          KeyStoreProperties props = new KeyStoreProperties();
          URL keyStoreURL = null;
          try {
            if (keystore != null && keystore.length() > 0) {
              keyStoreURL = new URL(keystore);
            }
          } catch (MalformedURLException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid URL specified in 'SAML_ENCRYPTED_ASSERTION_DECRYPTOR': " + keystore, e);
          }
          try {
            props.setPed(decryptorClass);
          } catch (ClassNotFoundException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid value specified for decryptorClass in SAML_ENCRYPTED_ASSERTION_DECRYPTOR",
                e);
          } catch (IllegalAccessException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid value specified for decryptorClass in SAML_ENCRYPTED_ASSERTION_DECRYPTOR",
                e);
          } catch (InstantiationException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid value specified for decryptorClass in SAML_ENCRYPTED_ASSERTION_DECRYPTOR",
                e);
          }
          props.setKeystore(keyStoreURL);
          try {
            props.setPassword(password);
          } catch (PasswordEncryptionDecryptionException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Could not decrypt password using decryptorClass in SAML_ENCRYPTED_ASSERTION_DECRYPTOR",
                e);
          }
          props.setType(type);
          props.setAlias(alias);
          try {
            props.setKeyPassword(keyPassword);
          } catch (PasswordEncryptionDecryptionException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Could not decrypt password using decryptorClass in SAML_ENCRYPTED_ASSERTION_DECRYPTOR",
                e);
          }
          decryptionKey.setKeystore(props);
        }
        /**
         * ** else if ( child.getNodeName().equals("SAML_SIGNATURE_VERIFIER")) { String entityId =
         * child,"ENTITYID"); String keystore = child,"KEYSTORE"); String type = child,"TYPE");
         * String password = child,"PASSWORD"); String alias = child,"ALIAS"); signingKey = new
         * KeyProperties(); signingKey.setEntityId(entityId); KeyStoreProperties props = new
         * KeyStoreProperties(); URL keyStoreURL = null; try { if (keystore != null &&
         * keystore.length() > 0) { keyStoreURL = new URL(keystore); } } catch
         * (MalformedURLException e) { throw new ConfigXMLParsingException("Invalid URL specified in
         * 'SAML_SIGNATURE_VERIFIER': " + keystore, e); } props.setKeystore(keyStoreURL);
         * props.setPassword(password); props.setType(type); props.setAlias(alias);
         * signingKey.setKeystore(props); }**
         */
        else if (child.getNodeName().equals("SAML_METADATA_PROVIDER")) {
          metadataProvider = child.getFirstChild().getNodeValue();
        } else if (child.getNodeName().equals("CONTEXT_DATA")) {
          try {
            contextDataExtractor =
                (ContextDataExtractor)
                    Class.forName(XMLUtils.getAttribute(child, "EXTRACTCLASS")).newInstance();
          } catch (DOMException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'EXTRACTCLASS' attribute in 'CONTEXT_DATA'", e);
          } catch (IllegalAccessException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'EXTRACTCLASS' attribute in 'CONTEXT_DATA'", e);
          } catch (InstantiationException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'EXTRACTCLASS' attribute in 'CONTEXT_DATA'", e);
          } catch (ClassNotFoundException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'EXTRACTCLASS' attribute in 'CONTEXT_DATA'", e);
          } catch (ClassCastException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'EXTRACTCLASS' attribute in 'CONTEXT_DATA'", e);
          }
          contextDataExtractorInitParam = XMLUtils.getAttribute(child, "EXTRACTCLASSINITPARAM");
          if (contextDataExtractorInitParam != null) {
            contextDataExtractor.init(contextDataExtractorInitParam);
          }
          try {
            contextDataStore =
                ContextDataStoreType.valueOf(XMLUtils.getAttribute(child, "STOREINTO"));
          } catch (IllegalArgumentException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException("Invalid value specified for STOREINTO", e);
          }
          contextDataStoreParam = XMLUtils.getAttribute(child, "STOREAS");
        } else if (child.getNodeName().equals("INVALID_SESSION_HANDLER")) {
          try {
            invalidSessionHandler =
                (InvalidSessionHandler)
                    Class.forName(child.getFirstChild().getNodeValue()).newInstance();
          } catch (DOMException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (IllegalAccessException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (InstantiationException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (ClassNotFoundException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (ClassCastException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          }
          String invalidSessionHandlerInitParam = XMLUtils.getAttribute(child, "INIT");
          if (invalidSessionHandlerInitParam != null) {
            invalidSessionHandler.init(invalidSessionHandlerInitParam);
          }
        } else if (child.getNodeName().equals("ERROR_HANDLER")) {
          try {
            errorHandler =
                (ErrorHandler) Class.forName(child.getFirstChild().getNodeValue()).newInstance();
          } catch (DOMException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (IllegalAccessException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (InstantiationException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (ClassNotFoundException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          } catch (ClassCastException e) {
            logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

            throw new ConfigXMLParsingException(
                "Invalid Class specified in 'INVALID_SESSION_HANDLER' attribute in 'CONTEXT_DATA'",
                e);
          }
          String errorHandlerInitParam = XMLUtils.getAttribute(child, "INIT");
          if (errorHandlerInitParam != null) {
            errorHandler.init(errorHandlerInitParam);
          }
        } else if (child.getNodeName().equals("IDP_URL")) {
          idpURL = child.getFirstChild().getNodeValue();
        } else if (child.getNodeName().equals("POST_FILTER")) {
          NodeList nodes_2 = child.getChildNodes();
          int nodes_length_2 = nodes_2.getLength();
          for (int j = 0; j < nodes_length_2; j++) {
            Node child_2 = nodes_2.item(j);

            if (child_2.getNodeName().equals("COPY")) {
              String request = XMLUtils.getAttribute(child_2, "REQUEST");
              String session = XMLUtils.getAttribute(child_2, "SESSION");
              if (request != null) {
                if (session == null) {
                  session = request;
                }
                CopyParameter param = new CopyParameter();
                param.setFrom(request);
                param.setTo(session);
                copies.add(param);
              }
            } else if (child_2.getNodeName().equals("CALL")) {
              String className = XMLUtils.getAttribute(child_2, "CLASS");
              if (className == null) {
                throw new ConfigXMLParsingException("Attribute 'CLASS' specified in 'CALL'");
              }
              String configName = XMLUtils.getAttribute(child_2, "CLASSCONFIGFILE");
              if (configName == null) {
                throw new ConfigXMLParsingException(
                    "Attribute 'CLASSCONFIGFILE' specified in 'CALL'");
              }
              PostCallInterface caller = null;
              try {
                Class clazz = Class.forName(className);
                caller = (PostCallInterface) clazz.newInstance();
                caller.init(configName);

              } catch (ClassNotFoundException e) {
                throw new ConfigXMLParsingException(
                    "Invalid class name under 'CLASS' attribute specified in 'CALL'", e);
              } catch (IllegalAccessException e) {
                throw new ConfigXMLParsingException(
                    "Invalid class name under 'CLASS' attribute specified in 'CALL'", e);
              } catch (InstantiationException e) {
                throw new ConfigXMLParsingException(
                    "Invalid class name under 'CLASS' attribute specified in 'CALL'", e);
              }
              postCallers.add(caller);
            }
          }
        }
      }

      validateConfig();
      if (!noInit) {
        initSAML2();
      }

    } catch (IOException e) {
      logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

      throw new ConfigXMLParsingException("IOException received.", e);
    } catch (ConfigurationException e) {
      logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

      throw new ConfigXMLParsingException(
          "Error initializing SAML 2.0 bootstrap using configuration.", e);
    } catch (MetadataProviderException e) {
      logger.error("SAMLConfiguration(String, boolean)", e); // $NON-NLS-1$

      throw new ConfigXMLParsingException("Error initializing SAML 2.0 Metadata Provider.", e);
    } finally {
      try {
        if (is != null) is.close();
      } catch (IOException e) {
        logger.warn("SAMLConfiguration(String, boolean) - exception ignored", e); // $NON-NLS-1$
      }
    }
  }