package at.gv.egovernment.moa.id.auth; import iaik.pki.PKIException; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.w3c.dom.Element; import at.gv.egovernment.moa.id.AuthenticationException; import at.gv.egovernment.moa.id.BuildException; import at.gv.egovernment.moa.id.ParseException; import at.gv.egovernment.moa.id.ServiceException; import at.gv.egovernment.moa.id.auth.builder.AuthenticationBlockAssertionBuilder; import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataAssertionBuilder; import at.gv.egovernment.moa.id.auth.builder.CertInfoVerifyXMLSignatureRequestBuilder; import at.gv.egovernment.moa.id.auth.builder.CreateXMLSignatureRequestBuilder; import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; import at.gv.egovernment.moa.id.auth.builder.GetIdentityLinkFormBuilder; import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilder; import at.gv.egovernment.moa.id.auth.builder.PersonDataBuilder; import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder; import at.gv.egovernment.moa.id.auth.builder.SelectBKUFormBuilder; import at.gv.egovernment.moa.id.auth.builder.VPKBuilder; import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse; import at.gv.egovernment.moa.id.auth.data.IdentityLink; import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser; import at.gv.egovernment.moa.id.auth.parser.InfoboxReadResponseParser; import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser; import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser; import at.gv.egovernment.moa.id.auth.servlet.AuthServlet; import at.gv.egovernment.moa.id.auth.validator.CreateXMLSignatureResponseValidator; import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator; import at.gv.egovernment.moa.id.auth.validator.ValidateException; import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator; import at.gv.egovernment.moa.id.config.ConfigurationException; import at.gv.egovernment.moa.id.config.ConfigurationProvider; import at.gv.egovernment.moa.id.config.ConnectionParameter; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.id.util.SSLUtils; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.DOMUtils; import at.gv.egovernment.moa.util.DateTimeUtils; import at.gv.egovernment.moa.util.FileUtils; /** * API for MOA ID Authentication Service.
* {@link AuthenticationSession} is stored in a session store and retrieved * by giving the session ID. * * @author Paul Ivancsics * @version $Id$ */ public class AuthenticationServer implements MOAIDAuthConstants { /** single instance */ private static AuthenticationServer instance; /** session data store (session ID -> AuthenticationSession) */ private static Map sessionStore = new HashMap(); /** authentication data store (assertion handle -> AuthenticationData) */ private static Map authenticationDataStore = new HashMap(); /** * time out in milliseconds used by {@link cleanup} for session store */ private long sessionTimeOut = 10*60*1000; // default 10 minutes /** * time out in milliseconds used by {@link cleanup} for authentication data store */ private long authDataTimeOut = 2*60*1000; // default 2 minutes /** * Returns the single instance of AuthenticationServer. * * @return the single instance of AuthenticationServer */ public static AuthenticationServer getInstance() { if (instance == null) instance = new AuthenticationServer(); return instance; } /** * Constructor for AuthenticationServer. */ public AuthenticationServer() { super(); } /** * Processes request to select a BKU. *
Processing depends on value of {@link AuthConfigurationProvider#getBKUSelectionType}. *
For bkuSelectionType==HTMLComplete, a returnURI for the * "BKU Auswahl" service is returned. *
For bkuSelectionType==HTMLSelect, an HTML form for BKU selection is returned. * @param authURL base URL of MOA-ID Auth component * @param target "Geschäftsbereich" * @param oaURL online application URL requested * @param bkuSelectionTemplateURL template for BKU selection form to be used * in case of HTMLSelect; may be null * @param templateURL URL providing an HTML template for the HTML form to be used * for call startAuthentication * @return for bkuSelectionType==HTMLComplete, the returnURI for the * "BKU Auswahl" service; * for bkuSelectionType==HTMLSelect, an HTML form for BKU selection * @throws WrongParametersException upon missing parameters * @throws AuthenticationException when the configured BKU selection service cannot be reached, * and when the given bkuSelectionTemplateURL cannot be reached * @throws ConfigurationException on missing configuration data * @throws BuildException while building the HTML form */ public String selectBKU( String authURL, String target, String oaURL, String bkuSelectionTemplateURL, String templateURL) throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException { if (isEmpty(authURL)) throw new WrongParametersException("StartAuthentication", "AuthURL"); if (isEmpty(target)) throw new WrongParametersException("StartAuthentication", PARAM_TARGET); if (isEmpty(oaURL)) throw new WrongParametersException("StartAuthentication", PARAM_OA); if (! authURL.startsWith("https:")) throw new AuthenticationException("auth.07", null); ConnectionParameter bkuConnParam = AuthConfigurationProvider.getInstance().getBKUConnectionParameter(); if (bkuConnParam == null) throw new ConfigurationException("config.08", new Object[] {"BKUSelection/ConnectionParameter"}); OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL); if (oaParam == null) throw new AuthenticationException("auth.00", new Object[] {oaURL}); AuthenticationSession session = newSession(); Logger.info("MOASession " + session.getSessionID() + " angelegt"); session.setTarget(target); session.setOAURLRequested(oaURL); session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix()); session.setAuthURL(authURL); session.setTemplateURL(templateURL); String returnURL = new DataURLBuilder().buildDataURL(authURL, REQ_START_AUTHENTICATION, session.getSessionID()); String bkuSelectionType = AuthConfigurationProvider.getInstance().getBKUSelectionType(); if (bkuSelectionType.equals(AuthConfigurationProvider.BKU_SELECTION_TYPE_HTMLCOMPLETE)) { // bkuSelectionType==HTMLComplete String redirectURL = bkuConnParam.getUrl() + "?" + AuthServlet.PARAM_RETURN + "=" + returnURL; return redirectURL; } else { // bkuSelectionType==HTMLSelect String bkuSelectTag; try { bkuSelectTag = readBKUSelectTag(AuthConfigurationProvider.getInstance(), bkuConnParam); } catch (Throwable ex) { throw new AuthenticationException("auth.03", new Object[] {bkuConnParam.getUrl(), ex.toString()}, ex); } String bkuSelectionTemplate = null; if (bkuSelectionTemplateURL != null) { try { bkuSelectionTemplate = new String(FileUtils.readURL(bkuSelectionTemplateURL)); } catch (IOException ex) { throw new AuthenticationException("auth.03", new Object[] {bkuSelectionTemplateURL, ex.toString()}, ex); } } String htmlForm = new SelectBKUFormBuilder().build(bkuSelectionTemplate, returnURL, bkuSelectTag); return htmlForm; } } /** * Method readBKUSelectTag. * @param conf the ConfigurationProvider * @param connParam the ConnectionParameter for that connection * @return String * @throws ConfigurationException on config-errors * @throws PKIException on PKI errors * @throws IOException on any data error * @throws GeneralSecurityException on security errors */ private String readBKUSelectTag(ConfigurationProvider conf, ConnectionParameter connParam) throws ConfigurationException, PKIException, IOException, GeneralSecurityException { if (connParam.isHTTPSURL()) return new String(SSLUtils.readHttpsURL(conf, connParam)); else return new String(FileUtils.readURL(connParam.getUrl())); } /** * Processes the beginning of an authentication session. * * @param authURL URL of the servlet to be used as data URL * @param target "Geschäftsbereich" of the online application requested * @param oaURL online application URL requested * @param bkuURL URL of the "Bürgerkartenumgebung" to be used; * may be null; in this case, the default location will be used * @param templateURL URL providing an HTML template for the HTML form generated * @return HTML form * @throws AuthenticationException * @see GetIdentityLinkFormBuilder * @see InfoboxReadRequestBuilder */ public String startAuthentication( String authURL, String target, String oaURL, String templateURL, String bkuURL, String sessionID) throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException { if (isEmpty(sessionID)) { if (isEmpty(authURL)) throw new WrongParametersException("StartAuthentication", "AuthURL"); if (! authURL.startsWith("https:")) throw new AuthenticationException("auth.07", null); if (isEmpty(target)) throw new WrongParametersException("StartAuthentication", PARAM_TARGET); if (isEmpty(oaURL)) throw new WrongParametersException("StartAuthentication", PARAM_OA); } AuthenticationSession session; if (sessionID != null) session = getSession(sessionID); else { OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL); if (oaParam == null) throw new AuthenticationException("auth.00", new Object[] {oaURL}); session = newSession(); Logger.info("MOASession " + session.getSessionID() + " angelegt"); session.setTarget(target); session.setOAURLRequested(oaURL); session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix()); session.setAuthURL(authURL); session.setTemplateURL(templateURL); } String infoboxReadRequest = new InfoboxReadRequestBuilder().build(); String dataURL = new DataURLBuilder().buildDataURL( session.getAuthURL(), REQ_VERIFY_IDENTITY_LINK, session.getSessionID()); String template = null; if (session.getTemplateURL() != null) { try { template = new String(FileUtils.readURL(session.getTemplateURL())); } catch (IOException ex) { throw new AuthenticationException("auth.03", new Object[] {session.getTemplateURL(), ex.toString()}, ex); } } String certInfoRequest = new CertInfoVerifyXMLSignatureRequestBuilder().build(); String certInfoDataURL = new DataURLBuilder().buildDataURL( session.getAuthURL(), REQ_START_AUTHENTICATION, session.getSessionID()); String htmlForm = new GetIdentityLinkFormBuilder().build( template, bkuURL, infoboxReadRequest, dataURL, certInfoRequest, certInfoDataURL); return htmlForm; } /** * Processes an <InfoboxReadResponse> sent by the * security layer implementation.
* * * @param sessionID ID of associated authentication session data * @param xmlInfoboxReadResponse String representation of the * <InfoboxReadResponse> * @return String representation of the <CreateXMLSignatureRequest> */ public String verifyIdentityLink (String sessionID, String xmlInfoboxReadResponse) throws AuthenticationException, ParseException, ConfigurationException, ValidateException, ServiceException, WrongParametersException { if (isEmpty(sessionID)) throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID); if (isEmpty(xmlInfoboxReadResponse)) throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE); AuthenticationSession session = getSession(sessionID); if (session.getTimestampIdentityLink() != null) throw new AuthenticationException("auth.01", new Object[] {sessionID}); session.setTimestampIdentityLink(); AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance(); // parses the IdentityLink identityLink = new InfoboxReadResponseParser(xmlInfoboxReadResponse). parseIdentityLink(); // validates the identity link IdentityLinkValidator.getInstance().validate(identityLink); // builds a for a call of MOA-SP Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder().build( identityLink, authConf.getMoaSpIdentityLinkTrustProfileID()); // debug output debugOutputXMLFile("VerifyIdentityLinkRequest.xml", domVerifyXMLSignatureRequest); // invokes the call Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker(). verifyXMLSignature(domVerifyXMLSignatureRequest); // parses the VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(domVerifyXMLSignatureResponse).parseData(); // debug output debugOutputXMLFile("VerifyIdentityLinkResponse.xml", domVerifyXMLSignatureResponse); // validates the VerifyXMLSignatureResponseValidator.getInstance().validate( verifyXMLSignatureResponse, authConf.getIdentityLinkX509SubjectNames(), VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK); session.setIdentityLink(identityLink); // builds the AUTH-block String authBlock = buildAuthenticationBlock(session); session.setAuthBlock(authBlock); // builds the String[] transformInfos = authConf.getTransformsInfos(); String createXMLSignatureRequest = new CreateXMLSignatureRequestBuilder(). build(authBlock, transformInfos); return createXMLSignatureRequest; } /** * Builds an authentication block <saml:Assertion> from given session data. * @param session authentication session * @return <saml:Assertion> as a String */ private String buildAuthenticationBlock(AuthenticationSession session) { IdentityLink identityLink = session.getIdentityLink(); String issuer = identityLink.getGivenName() + " " + identityLink.getFamilyName(); String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance()); String authURL = session.getAuthURL(); String target = session.getTarget(); String oaURL = session.getPublicOAURLPrefix(); String authBlock = new AuthenticationBlockAssertionBuilder(). build(issuer, issueInstant, authURL, target, oaURL); return authBlock; } /** * Processes a <CreateXMLSignatureResponse> sent by the * security layer implementation.
*
    *
  • Validates given <CreateXMLSignatureResponse>
  • *
  • Parses <CreateXMLSignatureResponse> for error codes
  • *
  • Parses authentication block enclosed in * <CreateXMLSignatureResponse>
  • *
  • Verifies authentication block by calling the MOA SP component
  • *
  • Creates authentication data
  • *
  • Creates a corresponding SAML artifact
  • *
  • Stores authentication data in the authentication data store * indexed by the SAML artifact
  • *
  • Deletes authentication session
  • *
  • Returns the SAML artifact, encoded BASE64
  • *
* * @param sessionID session ID of the running authentication session * @param xmlCreateXMLSignatureReadResponse String representation of the * <CreateXMLSignatureResponse> * @return SAML artifact needed for retrieving authentication data, encoded BASE64 */ public String verifyAuthenticationBlock( String sessionID, String xmlCreateXMLSignatureReadResponse) throws AuthenticationException, BuildException, ParseException, ConfigurationException, ServiceException, ValidateException, WrongParametersException { if (isEmpty(sessionID)) throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID); if (isEmpty(xmlCreateXMLSignatureReadResponse)) throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE); AuthenticationSession session = getSession(sessionID); AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance(); // parses CreateXMLSignatureResponse csresp = new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureReadResponse).parseResponse(); // validates new CreateXMLSignatureResponseValidator().validate(csresp, session.getTarget(), session.getPublicOAURLPrefix()); // builds a for a MOA-SPSS call String[] vtids = authConf.getMoaSpAuthBlockVerifyTransformsInfoIDs(); String tpid = authConf.getMoaSpAuthBlockTrustProfileID(); Element domVsreq = new VerifyXMLSignatureRequestBuilder().build(csresp, vtids, tpid); // debug output AuthenticationServer.debugOutputXMLFile("VerifyAuthenticationBlockRequest.xml", domVsreq); // invokes the call Element domVsresp = new SignatureVerificationInvoker().verifyXMLSignature(domVsreq); // parses the VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponseParser(domVsresp).parseData(); // debug output AuthenticationServer.debugOutputXMLFile("VerifyAuthenticationBlockResponse.xml", domVsresp); // validates the VerifyXMLSignatureResponseValidator.getInstance().validate( vsresp, null,VerifyXMLSignatureResponseValidator.CHECK_AUTH_BLOCK); // compares the public keys from the identityLink with the AuthBlock VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(vsresp, session.getIdentityLink()); // builds authentication data and stores it together with a SAML artifact AuthenticationData authData = buildAuthenticationData(session, vsresp); String samlArtifact = new SAMLArtifactBuilder().build(session.getAuthURL(), session.getSessionID()); storeAuthenticationData(samlArtifact, authData); // invalidates the authentication session sessionStore.remove(sessionID); Logger.info("Anmeldedaten zu MOASession " + sessionID + " angelegt, SAML Artifakt " + samlArtifact); return samlArtifact; } /** * Builds the AuthenticationData object together with the * corresponding <saml:Assertion> * @param session authentication session * @param verifyXMLSigResp VerifyXMLSignatureResponse from MOA-SP * @return AuthenticationData object * @throws ConfigurationException while accessing configuration data * @throws BuildException while building the <saml:Assertion> */ private AuthenticationData buildAuthenticationData( AuthenticationSession session, VerifyXMLSignatureResponse verifyXMLSigResp) throws ConfigurationException, BuildException { IdentityLink identityLink = session.getIdentityLink(); AuthenticationData authData = new AuthenticationData(); authData.setMajorVersion(1); authData.setMinorVersion(0); authData.setAssertionID(Random.nextRandom()); authData.setIssuer(session.getAuthURL()); authData.setIssueInstant(DateTimeUtils.buildDateTime(Calendar.getInstance())); String vpkBase64 = new VPKBuilder().buildVPK( identityLink.getIdentificationValue(), identityLink.getDateOfBirth(), session.getTarget()); authData.setVPK(vpkBase64); authData.setGivenName(identityLink.getGivenName()); authData.setFamilyName(identityLink.getFamilyName()); authData.setDateOfBirth(identityLink.getDateOfBirth()); authData.setQualifiedCertificate(verifyXMLSigResp.isQualifiedCertificate()); authData.setPublicAuthority(verifyXMLSigResp.isPublicAuthority()); authData.setPublicAuthorityCode(verifyXMLSigResp.getPublicAuthorityCode()); OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter( session.getPublicOAURLPrefix()); String prPerson = new PersonDataBuilder().build( identityLink, oaParam.getProvideZMRZahl()); try { String ilAssertion = oaParam.getProvideIdentityLink() ? DOMUtils.serializeNode(identityLink.getSamlAssertion()) : ""; String authBlock = oaParam.getProvideAuthBlock() ? session.getAuthBlock() : ""; String samlAssertion = new AuthenticationDataAssertionBuilder().build( authData, prPerson, authBlock, ilAssertion); authData.setSamlAssertion(samlAssertion); return authData; } catch (Throwable ex) { throw new BuildException( "builder.00", new Object[] { "AuthenticationData", ex.toString() }, ex); } } /** * Retrieves AuthenticationData indexed by the SAML artifact. * The AuthenticationData is deleted from the store upon end of this call. * * @return AuthenticationData */ public AuthenticationData getAuthenticationData(String samlArtifact) throws AuthenticationException { String assertionHandle; try { assertionHandle = new SAMLArtifactParser(samlArtifact).parseAssertionHandle(); } catch (ParseException ex) { throw new AuthenticationException("1205", new Object[] {samlArtifact, ex.toString()}); } AuthenticationData authData = null; synchronized (authenticationDataStore) { authData = (AuthenticationData)authenticationDataStore.get(assertionHandle); if (authData == null) { Logger.error("Assertion not found for SAML Artifact: " + samlArtifact); throw new AuthenticationException("1206", new Object[] {samlArtifact}); } authenticationDataStore.remove(assertionHandle); } long now = new Date().getTime(); if (now - authData.getTimestamp().getTime() > authDataTimeOut) throw new AuthenticationException("1207", new Object[] {samlArtifact}); Logger.debug("Assertion delivered for SAML Artifact: " + samlArtifact); return authData; } /** * Stores authentication data indexed by the assertion handle contained in the * given saml artifact. * @param samlArtifact SAML artifact * @param authData authentication data * @throws AuthenticationException when SAML artifact is invalid */ private void storeAuthenticationData(String samlArtifact, AuthenticationData authData) throws AuthenticationException { try { SAMLArtifactParser parser = new SAMLArtifactParser(samlArtifact); // check type code 0x0001 byte[] typeCode = parser.parseTypeCode(); if (typeCode[0] != 0 || typeCode[1] != 1) throw new AuthenticationException("auth.06", new Object[] {samlArtifact}); String assertionHandle = parser.parseAssertionHandle(); synchronized(authenticationDataStore) { Logger.debug("Assertion stored for SAML Artifact: " + samlArtifact); authenticationDataStore.put(assertionHandle, authData); } } catch (AuthenticationException ex) { throw ex; } catch (Throwable ex) { throw new AuthenticationException("auth.06", new Object[] {samlArtifact}); } } /** * Creates a new session and puts it into the session store. * * @param id Session ID * @return AuthenticationSession created * @exception AuthenticationException * thrown when an AuthenticationSession is running * already for the given session ID */ private static AuthenticationSession newSession() throws AuthenticationException { String sessionID = Random.nextRandom(); AuthenticationSession newSession = new AuthenticationSession(sessionID); synchronized (sessionStore) { AuthenticationSession session = (AuthenticationSession)sessionStore.get(sessionID); if (session != null) throw new AuthenticationException("auth.01", new Object[] { sessionID }); sessionStore.put(sessionID, newSession); } return newSession; } /** * Retrieves a session from the session store. * * @param id session ID * @return AuthenticationSession stored with given session ID, * null if session ID unknown */ public static AuthenticationSession getSession(String id) throws AuthenticationException { AuthenticationSession session = (AuthenticationSession)sessionStore.get(id); if (session == null) throw new AuthenticationException("auth.02", new Object[] { id }); return session; } /** * Cleans up expired session and authentication data stores. */ public void cleanup() { long now = new Date().getTime(); synchronized(sessionStore) { Set keys = new HashSet(sessionStore.keySet()); for (Iterator iter = keys.iterator(); iter.hasNext(); ) { String sessionID = (String) iter.next(); AuthenticationSession session = (AuthenticationSession) sessionStore.get(sessionID); if (now - session.getTimestampStart().getTime() > sessionTimeOut) { Logger.info(MOAIDMessageProvider.getInstance().getMessage("cleaner.02", new Object[] {sessionID})); sessionStore.remove(sessionID); } } } synchronized(authenticationDataStore) { Set keys = new HashSet(authenticationDataStore.keySet()); for (Iterator iter = keys.iterator(); iter.hasNext(); ) { String samlArtifact = (String) iter.next(); AuthenticationData authData = (AuthenticationData) authenticationDataStore.get(samlArtifact); if (now - authData.getTimestamp().getTime() > authDataTimeOut) { Logger.info(MOAIDMessageProvider.getInstance().getMessage("cleaner.03", new Object[] {samlArtifact})); authenticationDataStore.remove(samlArtifact); } } } } /** * Sets the sessionTimeOut. * @param sessionTimeOut time out in seconds */ public void setSecondsSessionTimeOut(long seconds) { sessionTimeOut = 1000 * seconds; } /** * Sets the authDataTimeOut. * @param authDataTimeOut time out in seconds */ public void setSecondsAuthDataTimeOut(long seconds) { authDataTimeOut = 1000 * seconds; } /** * Checks a parameter. * @param param parameter * @return true if the parameter is null or empty */ private boolean isEmpty(String param) { return param == null || param.length() == 0; } /** * Writes an XML structure to file for debugging purposes, encoding UTF-8. * * @param filename file name * @param rootElem root element in DOM tree */ public static void debugOutputXMLFile(String filename, Element rootElem) { if (Logger.isDebugEnabled(DEBUG_OUTPUT_HIERARCHY)) { try { String xmlString = new String(DOMUtils.serializeNode(rootElem)); debugOutputXMLFile(filename, xmlString); } catch (Exception ex) { ex.printStackTrace(); } } } /** * Writes an XML structure to file for debugging purposes, encoding UTF-8. * * @param filename file name * @param xmlString XML string */ public static void debugOutputXMLFile(String filename, String xmlString) { if (Logger.isDebugEnabled(DEBUG_OUTPUT_HIERARCHY)) { try { java.io.OutputStream fout = new java.io.FileOutputStream(filename); byte[] xmlData = xmlString.getBytes("UTF-8"); fout.write(xmlData); fout.close(); } catch (Exception ex) { ex.printStackTrace(); } } } }