| <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../.resources/report.css" type="text/css"/><link rel="shortcut icon" href="../.resources/report.gif" type="image/gif"/><title>BindingBuilder.java</title><link rel="stylesheet" href="../.resources/prettify.css" type="text/css"/><script type="text/javascript" src="../.resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="right"><a href="../.sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Coverage Report</a> > <a href="index.html" class="el_package">org.apache.rampart.builder</a> > <span class="el_source">BindingBuilder.java</span></div><h1>BindingBuilder.java</h1><pre class="source lang-java linenums">/* |
| * Copyright 2004,2005 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.rampart.builder; |
| |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axis2.client.Options; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.rahas.EncryptedKeyToken; |
| import org.apache.rahas.SimpleTokenStore; |
| import org.apache.rahas.TrustException; |
| import org.apache.rampart.RampartException; |
| import org.apache.rampart.RampartMessageData; |
| import org.apache.rampart.policy.RampartPolicyData; |
| import org.apache.rampart.policy.SupportingPolicyData; |
| import org.apache.rampart.policy.model.RampartConfig; |
| import org.apache.rampart.util.RampartUtil; |
| import org.apache.ws.secpolicy.Constants; |
| import org.apache.ws.secpolicy.SPConstants; |
| import org.apache.ws.secpolicy.model.AlgorithmSuite; |
| import org.apache.ws.secpolicy.model.IssuedToken; |
| import org.apache.ws.secpolicy.model.SecureConversationToken; |
| import org.apache.ws.secpolicy.model.SupportingToken; |
| import org.apache.ws.secpolicy.model.Token; |
| import org.apache.ws.secpolicy.model.UsernameToken; |
| import org.apache.ws.secpolicy.model.X509Token; |
| import org.apache.ws.security.WSConstants; |
| import org.apache.ws.security.WSEncryptionPart; |
| import org.apache.ws.security.WSPasswordCallback; |
| import org.apache.ws.security.WSSecurityEngineResult; |
| import org.apache.ws.security.WSSecurityException; |
| import org.apache.ws.security.conversation.ConversationConstants; |
| import org.apache.ws.security.conversation.ConversationException; |
| import org.apache.ws.security.handler.WSHandlerConstants; |
| import org.apache.ws.security.handler.WSHandlerResult; |
| import org.apache.ws.security.message.WSSecDKSign; |
| import org.apache.ws.security.message.WSSecEncryptedKey; |
| import org.apache.ws.security.message.WSSecSignature; |
| import org.apache.ws.security.message.WSSecSignatureConfirmation; |
| import org.apache.ws.security.message.WSSecTimestamp; |
| import org.apache.ws.security.message.WSSecUsernameToken; |
| import org.apache.ws.security.message.token.SecurityTokenReference; |
| import org.apache.ws.security.util.WSSecurityUtil; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| import javax.security.auth.callback.CallbackHandler; |
| import javax.security.auth.callback.UnsupportedCallbackException; |
| import javax.xml.crypto.dsig.Reference; |
| |
| import java.io.IOException; |
| import java.util.*; |
| import java.util.Map.Entry; |
| |
| <span class="fc" id="L69">public abstract class BindingBuilder {</span> |
| <span class="fc" id="L70"> private static Log log = LogFactory.getLog(BindingBuilder.class);</span> |
| |
| private Element insertionLocation; |
| |
| <span class="fc" id="L74"> protected String mainSigId = null;</span> |
| |
| <span class="fc" id="L76"> protected ArrayList<String> encryptedTokensIdList = new ArrayList<String>();</span> |
| |
| protected Element timestampElement; |
| |
| protected Element mainRefListElement; |
| |
| |
| /** |
| * @param rmd |
| */ |
| protected void addTimestamp(RampartMessageData rmd) { |
| <span class="fc" id="L87"> log.debug("Adding timestamp");</span> |
| |
| <span class="fc" id="L89"> WSSecTimestamp timestampBuilder = new WSSecTimestamp();</span> |
| <span class="fc" id="L90"> timestampBuilder.setWsConfig(rmd.getConfig());</span> |
| |
| <span class="fc" id="L92"> timestampBuilder.setTimeToLive(RampartUtil.getTimeToLive(rmd));</span> |
| |
| // add the Timestamp to the SOAP Enevelope |
| |
| <span class="fc" id="L96"> timestampBuilder.build(rmd.getDocument(), rmd</span> |
| .getSecHeader()); |
| |
| <span class="pc bpc" id="L99" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L100"> log.debug("Timestamp id: " + timestampBuilder.getId());</span> |
| } |
| <span class="fc" id="L102"> rmd.setTimestampId(timestampBuilder.getId());</span> |
| |
| <span class="fc" id="L104"> this.timestampElement = timestampBuilder.getElement();</span> |
| <span class="fc" id="L105"> log.debug("Adding timestamp: DONE");</span> |
| <span class="fc" id="L106"> }</span> |
| |
| /** |
| * Add a UsernameToken to the security header |
| * @param rmd |
| * @return The <code>WSSecUsernameToken</code> instance |
| * @throws RampartException |
| */ |
| protected WSSecUsernameToken addUsernameToken(RampartMessageData rmd, UsernameToken token) throws RampartException { |
| |
| <span class="fc" id="L116"> log.debug("Adding a UsernameToken");</span> |
| |
| <span class="fc" id="L118"> RampartPolicyData rpd = rmd.getPolicyData();</span> |
| |
| //Get the user |
| //First try options |
| <span class="fc" id="L122"> Options options = rmd.getMsgContext().getOptions();</span> |
| <span class="fc" id="L123"> String user = options.getUserName();</span> |
| <span class="pc bpc" id="L124" title="1 of 4 branches missed."> if(user == null || user.length() == 0) {</span> |
| //Then try RampartConfig |
| <span class="pc bpc" id="L126" title="1 of 2 branches missed."> if(rpd.getRampartConfig() != null) {</span> |
| <span class="fc" id="L127"> user = rpd.getRampartConfig().getUser();</span> |
| } |
| } |
| |
| <span class="pc bpc" id="L131" title="2 of 4 branches missed."> if(user != null && !"".equals(user)) {</span> |
| <span class="pc bpc" id="L132" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L133"> log.debug("User : " + user);</span> |
| } |
| |
| // If NoPassword property is set we don't need to set the password |
| <span class="fc bfc" id="L137" title="All 2 branches covered."> if (token.isNoPassword()) {</span> |
| <span class="fc" id="L138"> WSSecUsernameToken utBuilder = new WSSecUsernameToken();</span> |
| <span class="fc" id="L139"> utBuilder.setUserInfo(user, null);</span> |
| <span class="fc" id="L140"> utBuilder.setPasswordType(null);</span> |
| <span class="pc bpc" id="L141" title="1 of 2 branches missed."> if (rmd.getConfig() != null) {</span> |
| <span class="fc" id="L142"> utBuilder.setWsConfig(rmd.getConfig());</span> |
| } |
| <span class="fc" id="L144"> return utBuilder;</span> |
| } |
| |
| //Get the password |
| |
| //First check options object for a password |
| <span class="fc" id="L150"> String password = options.getPassword();</span> |
| |
| <span class="pc bpc" id="L152" title="1 of 4 branches missed."> if(password == null || password.length() == 0) {</span> |
| |
| //Then try to get the password from the given callback handler |
| <span class="fc" id="L155"> CallbackHandler handler = RampartUtil.getPasswordCB(rmd);</span> |
| |
| <span class="pc bpc" id="L157" title="1 of 2 branches missed."> if(handler == null) {</span> |
| //If the callback handler is missing |
| <span class="nc" id="L159"> throw new RampartException("cbHandlerMissing");</span> |
| } |
| |
| <span class="fc" id="L162"> WSPasswordCallback[] cb = { new WSPasswordCallback(user,</span> |
| WSPasswordCallback.USERNAME_TOKEN) }; |
| try { |
| <span class="fc" id="L165"> handler.handle(cb);</span> |
| <span class="nc" id="L166"> } catch (Exception e) {</span> |
| <span class="nc" id="L167"> throw new RampartException("errorInGettingPasswordForUser", </span> |
| new String[]{user}, e); |
| <span class="fc" id="L169"> }</span> |
| |
| //get the password |
| <span class="fc" id="L172"> password = cb[0].getPassword();</span> |
| } |
| |
| <span class="pc bpc" id="L175" title="2 of 4 branches missed."> if(password != null && !"".equals(password)) {</span> |
| //If the password is available then build the token |
| |
| <span class="fc" id="L178"> WSSecUsernameToken utBuilder = new WSSecUsernameToken();</span> |
| <span class="pc bpc" id="L179" title="1 of 2 branches missed."> if(rmd.getConfig() != null) {</span> |
| <span class="fc" id="L180"> utBuilder.setWsConfig(rmd.getConfig());</span> |
| } |
| <span class="fc bfc" id="L182" title="All 2 branches covered."> if (token.isHashPassword()) {</span> |
| <span class="fc" id="L183"> utBuilder.setPasswordType(WSConstants.PASSWORD_DIGEST); </span> |
| } else { |
| <span class="fc" id="L185"> utBuilder.setPasswordType(WSConstants.PASSWORD_TEXT);</span> |
| } |
| |
| <span class="fc" id="L188"> utBuilder.setUserInfo(user, password);</span> |
| |
| <span class="fc" id="L190"> return utBuilder;</span> |
| } else { |
| //If there's no password then throw an exception |
| <span class="nc" id="L193"> throw new RampartException("noPasswordForUser", </span> |
| new String[]{user}); |
| } |
| |
| } else { |
| <span class="nc" id="L198"> log.debug("No user value specified in the configuration");</span> |
| <span class="nc" id="L199"> throw new RampartException("userMissing");</span> |
| } |
| |
| } |
| |
| |
| /** |
| * @param rmd |
| * @param token |
| * @return |
| * @throws WSSecurityException |
| * @throws RampartException |
| */ |
| protected WSSecEncryptedKey getEncryptedKeyBuilder(RampartMessageData rmd, Token token) throws RampartException { |
| |
| <span class="fc" id="L214"> RampartPolicyData rpd = rmd.getPolicyData();</span> |
| <span class="fc" id="L215"> Document doc = rmd.getDocument();</span> |
| |
| <span class="fc" id="L217"> WSSecEncryptedKey encrKey = new WSSecEncryptedKey();</span> |
| |
| try { |
| <span class="fc" id="L220"> RampartUtil.setKeyIdentifierType(rmd, encrKey, token);</span> |
| <span class="fc" id="L221"> RampartUtil.setEncryptionUser(rmd, encrKey);</span> |
| |
| //TODO we do not need to pass keysize as it is taken from algorithm it self - verify |
| <span class="fc" id="L224"> encrKey.setKeyEncAlgo(rpd.getAlgorithmSuite().getAsymmetricKeyWrap());</span> |
| |
| <span class="fc" id="L226"> encrKey.prepare(doc, RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), rmd.getCustomClassLoader()));</span> |
| |
| <span class="fc" id="L228"> return encrKey;</span> |
| <span class="nc" id="L229"> } catch (WSSecurityException e) {</span> |
| <span class="nc" id="L230"> throw new RampartException("errorCreatingEncryptedKey", e);</span> |
| } |
| } |
| |
| //Deprecated after 1.5 release |
| @Deprecated |
| protected WSSecSignature getSignatureBuider(RampartMessageData rmd, |
| Token token) throws RampartException { |
| <span class="nc" id="L238"> return getSignatureBuilder(rmd, token, null);</span> |
| } |
| |
| //Deprecated after 1.5 release |
| @Deprecated |
| protected WSSecSignature getSignatureBuider(RampartMessageData rmd, Token token, |
| String userCertAlias) throws RampartException { |
| <span class="nc" id="L245"> return getSignatureBuilder(rmd, token, userCertAlias);</span> |
| } |
| |
| protected WSSecSignature getSignatureBuilder(RampartMessageData rmd, |
| Token token)throws RampartException { |
| <span class="fc" id="L250"> return getSignatureBuilder(rmd, token, null);</span> |
| } |
| |
| protected WSSecSignature getSignatureBuilder(RampartMessageData rmd, Token token, |
| String userCertAlias) throws RampartException { |
| |
| <span class="fc" id="L256"> RampartPolicyData rpd = rmd.getPolicyData();</span> |
| |
| <span class="fc" id="L258"> WSSecSignature sig = new WSSecSignature();</span> |
| <span class="fc" id="L259"> checkForX509PkiPath(sig, token);</span> |
| <span class="fc" id="L260"> sig.setWsConfig(rmd.getConfig());</span> |
| |
| <span class="pc bpc" id="L262" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L263"> log.debug("Token inclusion: " + token.getInclusion());</span> |
| } |
| |
| <span class="fc" id="L266"> RampartUtil.setKeyIdentifierType(rmd, sig, token);</span> |
| |
| <span class="fc" id="L268"> String user = null;</span> |
| |
| <span class="fc bfc" id="L270" title="All 2 branches covered."> if (userCertAlias != null) {</span> |
| <span class="fc" id="L271"> user = userCertAlias;</span> |
| } |
| |
| // Get the user - First check whether userCertAlias present |
| <span class="fc" id="L275"> RampartConfig rampartConfig = rpd.getRampartConfig();</span> |
| <span class="pc bpc" id="L276" title="1 of 2 branches missed."> if(rampartConfig == null) {</span> |
| <span class="nc" id="L277"> throw new RampartException("rampartConfigMissing");</span> |
| } |
| |
| <span class="fc bfc" id="L280" title="All 2 branches covered."> if (user == null) {</span> |
| <span class="fc" id="L281"> user = rampartConfig.getUserCertAlias();</span> |
| } |
| |
| // If userCertAlias is not present, use user property as Alias |
| |
| <span class="fc bfc" id="L286" title="All 2 branches covered."> if (user == null) {</span> |
| <span class="fc" id="L287"> user = rampartConfig.getUser();</span> |
| } |
| |
| <span class="fc" id="L290"> String password = null;</span> |
| |
| <span class="pc bpc" id="L292" title="2 of 4 branches missed."> if(user != null && !"".equals(user)) {</span> |
| <span class="pc bpc" id="L293" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L294"> log.debug("User : " + user);</span> |
| } |
| |
| //Get the password |
| <span class="fc" id="L298"> CallbackHandler handler = RampartUtil.getPasswordCB(rmd);</span> |
| |
| <span class="pc bpc" id="L300" title="1 of 2 branches missed."> if(handler == null) {</span> |
| //If the callback handler is missing |
| <span class="nc" id="L302"> throw new RampartException("cbHandlerMissing");</span> |
| } |
| |
| <span class="fc" id="L305"> WSPasswordCallback[] cb = { new WSPasswordCallback(user,</span> |
| WSPasswordCallback.SIGNATURE) }; |
| |
| try { |
| <span class="fc" id="L309"> handler.handle(cb);</span> |
| <span class="pc bpc" id="L310" title="2 of 4 branches missed."> if(cb[0].getPassword() != null && !"".equals(cb[0].getPassword())) {</span> |
| <span class="fc" id="L311"> password = cb[0].getPassword();</span> |
| <span class="pc bpc" id="L312" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L313"> log.debug("Password : " + password);</span> |
| } |
| } else { |
| //If there's no password then throw an exception |
| <span class="nc" id="L317"> throw new RampartException("noPasswordForUser", </span> |
| new String[]{user}); |
| } |
| <span class="nc" id="L320"> } catch (IOException e) {</span> |
| <span class="nc" id="L321"> throw new RampartException("errorInGettingPasswordForUser", </span> |
| new String[]{user}, e); |
| <span class="nc" id="L323"> } catch (UnsupportedCallbackException e) {</span> |
| <span class="nc" id="L324"> throw new RampartException("errorInGettingPasswordForUser", </span> |
| new String[]{user}, e); |
| <span class="fc" id="L326"> }</span> |
| |
| <span class="fc" id="L328"> } else {</span> |
| <span class="nc" id="L329"> log.debug("No user value specified in the configuration");</span> |
| <span class="nc" id="L330"> throw new RampartException("userMissing");</span> |
| } |
| |
| <span class="fc" id="L333"> sig.setUserInfo(user, password);</span> |
| <span class="fc" id="L334"> AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite();</span> |
| <span class="fc" id="L335"> sig.setSignatureAlgorithm(algorithmSuite.getAsymmetricSignature());</span> |
| <span class="fc" id="L336"> sig.setSigCanonicalization(algorithmSuite.getInclusiveC14n());</span> |
| <span class="fc" id="L337"> sig.setDigestAlgo(algorithmSuite.getDigest());</span> |
| |
| try { |
| <span class="fc" id="L340"> sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rampartConfig, rmd.getCustomClassLoader()), </span> |
| rmd.getSecHeader()); |
| <span class="nc" id="L342"> } catch (WSSecurityException e) {</span> |
| <span class="nc" id="L343"> throw new RampartException("errorInSignatureWithX509Token", e);</span> |
| <span class="fc" id="L344"> }</span> |
| |
| <span class="fc" id="L346"> return sig;</span> |
| } |
| |
| /** |
| * @param rmd |
| * @param suppTokens |
| * @throws RampartException |
| */ |
| protected HashMap handleSupportingTokens(RampartMessageData rmd, SupportingToken suppTokens) |
| throws RampartException { |
| |
| //Create the list to hold the tokens |
| // TODO putting different types of objects. Need to figure out a way to add single types of objects |
| <span class="fc" id="L359"> HashMap endSuppTokMap = new HashMap();</span> |
| |
| <span class="pc bpc" id="L361" title="1 of 6 branches missed."> if(suppTokens != null && suppTokens.getTokens() != null &&</span> |
| suppTokens.getTokens().size() > 0) { |
| <span class="fc" id="L363"> log.debug("Processing supporting tokens");</span> |
| |
| <span class="fc" id="L365"> ArrayList tokens = suppTokens.getTokens();</span> |
| <span class="fc bfc" id="L366" title="All 2 branches covered."> for (Object objectToken : tokens) {</span> |
| <span class="fc" id="L367"> Token token = (Token) objectToken;</span> |
| <span class="fc" id="L368"> org.apache.rahas.Token endSuppTok = null;</span> |
| <span class="pc bpc" id="L369" title="1 of 4 branches missed."> if (token instanceof IssuedToken && rmd.isInitiator()) {</span> |
| <span class="fc" id="L370"> String id = RampartUtil.getIssuedToken(rmd, (IssuedToken) token);</span> |
| try { |
| <span class="fc" id="L372"> endSuppTok = rmd.getTokenStorage().getToken(id);</span> |
| <span class="nc" id="L373"> } catch (TrustException e) {</span> |
| <span class="nc" id="L374"> throw new RampartException("errorInRetrievingTokenId",</span> |
| new String[]{id}, e); |
| <span class="fc" id="L376"> }</span> |
| |
| <span class="pc bpc" id="L378" title="1 of 2 branches missed."> if (endSuppTok == null) {</span> |
| <span class="nc" id="L379"> throw new RampartException("errorInRetrievingTokenId",</span> |
| new String[]{id}); |
| } |
| |
| //Add the token to the header |
| <span class="fc" id="L384"> Element siblingElem = RampartUtil</span> |
| .insertSiblingAfter(rmd, this.getInsertionLocation(), |
| (Element) endSuppTok.getToken()); |
| <span class="fc" id="L387"> this.setInsertionLocation(siblingElem);</span> |
| |
| <span class="pc bpc" id="L389" title="1 of 2 branches missed."> if (suppTokens.isEncryptedToken()) {</span> |
| <span class="nc" id="L390"> this.encryptedTokensIdList.add(endSuppTok.getId());</span> |
| } |
| |
| //Add the extracted token |
| <span class="fc" id="L394"> endSuppTokMap.put(token, endSuppTok);</span> |
| |
| <span class="fc bfc" id="L396" title="All 2 branches covered."> } else if (token instanceof X509Token) {</span> |
| |
| //We have to use a cert |
| //Prepare X509 signature |
| <span class="fc" id="L400"> WSSecSignature sig = this.getSignatureBuilder(rmd, token);</span> |
| <span class="fc" id="L401"> Element bstElem = sig.getBinarySecurityTokenElement();</span> |
| <span class="pc bpc" id="L402" title="1 of 2 branches missed."> if (bstElem != null) {</span> |
| <span class="fc" id="L403"> bstElem = RampartUtil.insertSiblingAfter(rmd,</span> |
| this.getInsertionLocation(), bstElem); |
| <span class="fc" id="L405"> this.setInsertionLocation(bstElem);</span> |
| |
| <span class="fc" id="L407"> SupportingPolicyData supportingPolcy = new SupportingPolicyData();</span> |
| <span class="fc" id="L408"> supportingPolcy.build(suppTokens);</span> |
| <span class="fc" id="L409"> supportingPolcy.setSignatureToken(token);</span> |
| <span class="fc" id="L410"> supportingPolcy.setEncryptionToken(token);</span> |
| <span class="fc" id="L411"> rmd.getPolicyData().addSupportingPolicyData(supportingPolcy);</span> |
| |
| <span class="fc bfc" id="L413" title="All 2 branches covered."> if (suppTokens.isEncryptedToken()) {</span> |
| <span class="fc" id="L414"> this.encryptedTokensIdList.add(sig.getBSTTokenId());</span> |
| } |
| } |
| <span class="fc" id="L417"> endSuppTokMap.put(token, sig);</span> |
| |
| <span class="pc bpc" id="L419" title="1 of 2 branches missed."> } else if (token instanceof UsernameToken) {</span> |
| <span class="fc" id="L420"> WSSecUsernameToken utBuilder = addUsernameToken(rmd, (UsernameToken) token);</span> |
| |
| <span class="fc" id="L422"> utBuilder.prepare(rmd.getDocument());</span> |
| |
| //Add the UT |
| <span class="fc" id="L425"> Element elem = utBuilder.getUsernameTokenElement();</span> |
| <span class="fc" id="L426"> elem = RampartUtil.insertSiblingAfter(rmd, this.getInsertionLocation(), elem);</span> |
| |
| <span class="fc bfc" id="L428" title="All 2 branches covered."> if (suppTokens.isEncryptedToken()) {</span> |
| <span class="fc" id="L429"> encryptedTokensIdList.add(utBuilder.getId());</span> |
| } |
| |
| //Move the insert location to the next element |
| <span class="fc" id="L433"> this.setInsertionLocation(elem);</span> |
| <span class="fc" id="L434"> Date now = new Date();</span> |
| try { |
| <span class="fc" id="L436"> org.apache.rahas.Token tempTok = new org.apache.rahas.Token(</span> |
| utBuilder.getId(), (OMElement) elem, now, |
| new Date(now.getTime() + 300000)); |
| <span class="fc" id="L439"> endSuppTokMap.put(token, tempTok);</span> |
| <span class="nc" id="L440"> } catch (TrustException e) {</span> |
| <span class="nc" id="L441"> throw new RampartException("errorCreatingRahasToken", e);</span> |
| <span class="fc" id="L442"> }</span> |
| } |
| <span class="fc" id="L444"> }</span> |
| } |
| |
| <span class="fc" id="L447"> return endSuppTokMap;</span> |
| } |
| /** |
| * @param tokenMap |
| * @param sigParts |
| * @throws RampartException |
| */ |
| protected List<WSEncryptionPart> addSignatureParts(HashMap tokenMap, List<WSEncryptionPart> sigParts) |
| throws RampartException { |
| |
| <span class="fc" id="L457"> Set entrySet = tokenMap.entrySet();</span> |
| |
| <span class="fc bfc" id="L459" title="All 2 branches covered."> for (Object anEntrySet : entrySet) {</span> |
| <span class="fc" id="L460"> Object tempTok = ((Entry) anEntrySet).getValue();</span> |
| <span class="fc" id="L461"> WSEncryptionPart part = null;</span> |
| |
| <span class="fc bfc" id="L463" title="All 2 branches covered."> if (tempTok instanceof org.apache.rahas.Token) {</span> |
| |
| <span class="fc" id="L465"> part = new WSEncryptionPart(</span> |
| ((org.apache.rahas.Token) tempTok).getId()); |
| |
| <span class="pc bpc" id="L468" title="1 of 2 branches missed."> } else if (tempTok instanceof WSSecSignature) {</span> |
| <span class="fc" id="L469"> WSSecSignature tempSig = (WSSecSignature) tempTok;</span> |
| <span class="pc bpc" id="L470" title="1 of 2 branches missed."> if (tempSig.getBSTTokenId() != null) {</span> |
| <span class="fc" id="L471"> part = new WSEncryptionPart(tempSig.getBSTTokenId());</span> |
| } |
| <span class="fc" id="L473"> } else {</span> |
| |
| <span class="nc" id="L475"> throw new RampartException("UnsupportedTokenInSupportingToken");</span> |
| } |
| <span class="fc" id="L477"> sigParts.add(part);</span> |
| <span class="fc" id="L478"> }</span> |
| |
| <span class="fc" id="L480"> return sigParts;</span> |
| } |
| |
| |
| public Element getInsertionLocation() { |
| <span class="fc" id="L485"> return insertionLocation;</span> |
| } |
| |
| public void setInsertionLocation(Element insertionLocation) { |
| <span class="fc" id="L489"> this.insertionLocation = insertionLocation;</span> |
| <span class="fc" id="L490"> }</span> |
| |
| |
| protected List<byte[]> doEndorsedSignatures(RampartMessageData rmd, HashMap tokenMap) throws RampartException { |
| |
| <span class="fc" id="L495"> Set tokenSet = tokenMap.keySet();</span> |
| |
| <span class="fc" id="L497"> List<byte[]> sigValues = new ArrayList<byte[]>();</span> |
| |
| <span class="fc bfc" id="L499" title="All 2 branches covered."> for (Object aTokenSet : tokenSet) {</span> |
| |
| <span class="fc" id="L501"> Token token = (Token) aTokenSet;</span> |
| |
| <span class="fc" id="L503"> Object tempTok = tokenMap.get(token);</span> |
| |
| // Migrating to a list |
| <span class="fc" id="L506"> List<WSEncryptionPart> sigParts = new ArrayList<WSEncryptionPart>();</span> |
| <span class="fc" id="L507"> sigParts.add(new WSEncryptionPart(this.mainSigId));</span> |
| |
| <span class="pc bpc" id="L509" title="1 of 2 branches missed."> if (tempTok instanceof org.apache.rahas.Token) {</span> |
| <span class="nc" id="L510"> org.apache.rahas.Token tok = (org.apache.rahas.Token) tempTok;</span> |
| <span class="nc bnc" id="L511" title="All 2 branches missed."> if (rmd.getPolicyData().isTokenProtection()) {</span> |
| <span class="nc" id="L512"> sigParts.add(new WSEncryptionPart(tok.getId()));</span> |
| } |
| |
| <span class="nc" id="L515"> this.doSymmSignature(rmd, token, (org.apache.rahas.Token) tempTok, sigParts);</span> |
| |
| <span class="pc bpc" id="L517" title="1 of 2 branches missed."> } else if (tempTok instanceof WSSecSignature) {</span> |
| <span class="fc" id="L518"> WSSecSignature sig = (WSSecSignature) tempTok;</span> |
| <span class="pc bpc" id="L519" title="3 of 4 branches missed."> if (rmd.getPolicyData().isTokenProtection() &&</span> |
| sig.getBSTTokenId() != null) { |
| <span class="nc" id="L521"> sigParts.add(new WSEncryptionPart(sig.getBSTTokenId()));</span> |
| } |
| |
| try { |
| |
| |
| <span class="fc" id="L527"> List<Reference> referenceList</span> |
| = sig.addReferencesToSign(sigParts, rmd.getSecHeader()); |
| |
| /** |
| * Before migration it was - this.setInsertionLocation(RampartUtil.insertSiblingAfter(rmd, this |
| * .getInsertionLocation(), supportingSignatureElement)); |
| * |
| * In this case we need to append <Signature>..</Signature> element to |
| * current insertion location |
| */ |
| |
| <span class="fc" id="L538"> sig.computeSignature(referenceList, false, this.getInsertionLocation());</span> |
| |
| <span class="fc" id="L540"> this.setInsertionLocation(sig.getSignatureElement());</span> |
| |
| <span class="nc" id="L542"> } catch (WSSecurityException e) {</span> |
| <span class="nc" id="L543"> throw new RampartException("errorInSignatureWithX509Token", e);</span> |
| <span class="fc" id="L544"> }</span> |
| <span class="fc" id="L545"> sigValues.add(sig.getSignatureValue());</span> |
| } |
| <span class="fc" id="L547"> } </span> |
| |
| <span class="fc" id="L549"> return sigValues;</span> |
| |
| } |
| |
| |
| protected byte[] doSymmSignature(RampartMessageData rmd, Token policyToken, org.apache.rahas.Token tok, |
| List<WSEncryptionPart> sigParts) throws RampartException { |
| |
| <span class="fc" id="L557"> Document doc = rmd.getDocument();</span> |
| |
| <span class="fc" id="L559"> RampartPolicyData rpd = rmd.getPolicyData();</span> |
| |
| <span class="fc" id="L561"> AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite();</span> |
| <span class="fc bfc" id="L562" title="All 2 branches covered."> if(policyToken.isDerivedKeys()) {</span> |
| try { |
| <span class="fc" id="L564"> WSSecDKSign dkSign = new WSSecDKSign(); </span> |
| |
| //Check whether it is security policy 1.2 and use the secure conversation accordingly |
| <span class="fc bfc" id="L567" title="All 2 branches covered."> if (SPConstants.SP_V12 == policyToken.getVersion()) {</span> |
| <span class="fc" id="L568"> dkSign.setWscVersion(ConversationConstants.VERSION_05_12);</span> |
| } |
| |
| //Check for whether the token is attached in the message or not |
| <span class="fc" id="L572"> boolean attached = false;</span> |
| |
| <span class="pc bpc" id="L574" title="2 of 8 branches missed."> if (SPConstants.INCLUDE_TOEKN_ALWAYS == policyToken.getInclusion() ||</span> |
| SPConstants.INCLUDE_TOKEN_ONCE == policyToken.getInclusion() || |
| (rmd.isInitiator() && SPConstants.INCLUDE_TOEKN_ALWAYS_TO_RECIPIENT |
| == policyToken.getInclusion())) { |
| <span class="fc" id="L578"> attached = true;</span> |
| } |
| |
| // Setting the AttachedReference or the UnattachedReference according to the flag |
| OMElement ref; |
| <span class="fc bfc" id="L583" title="All 2 branches covered."> if (attached) {</span> |
| <span class="fc" id="L584"> ref = tok.getAttachedReference();</span> |
| } else { |
| <span class="fc" id="L586"> ref = tok.getUnattachedReference();</span> |
| } |
| |
| <span class="fc bfc" id="L589" title="All 2 branches covered."> if(ref != null) {</span> |
| <span class="fc" id="L590"> dkSign.setExternalKey(tok.getSecret(), (Element) </span> |
| doc.importNode((Element) ref, true)); |
| <span class="pc bpc" id="L592" title="1 of 4 branches missed."> } else if (!rmd.isInitiator() && policyToken.isDerivedKeys()) { </span> |
| |
| // If the Encrypted key used to create the derived key is not |
| // attached use key identifier as defined in WSS1.1 section |
| // 7.7 Encrypted Key reference |
| <span class="fc" id="L597"> SecurityTokenReference tokenRef = new SecurityTokenReference(doc);</span> |
| <span class="pc bpc" id="L598" title="1 of 2 branches missed."> if(tok instanceof EncryptedKeyToken) {</span> |
| <span class="fc" id="L599"> tokenRef.setKeyIdentifierEncKeySHA1(((EncryptedKeyToken)tok).getSHA1());;</span> |
| } |
| <span class="fc" id="L601"> dkSign.setExternalKey(tok.getSecret(), tokenRef.getElement());</span> |
| <span class="fc" id="L602"> tokenRef.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE); // TODO check this</span> |
| |
| <span class="fc" id="L604"> } else {</span> |
| <span class="fc" id="L605"> dkSign.setExternalKey(tok.getSecret(), tok.getId());</span> |
| } |
| |
| //Set the algo info |
| <span class="fc" id="L609"> dkSign.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature());</span> |
| <span class="fc" id="L610"> dkSign.setDerivedKeyLength(algorithmSuite.getSignatureDerivedKeyLength()/8);</span> |
| // dkSign.setDigestAlgorithm(algorithmSuite.getDigest()); //uncomment when wss4j version is updated |
| <span class="fc bfc" id="L612" title="All 2 branches covered."> if(tok instanceof EncryptedKeyToken) {</span> |
| //Set the value type of the reference |
| <span class="fc" id="L614"> dkSign.setCustomValueType(WSConstants.SOAPMESSAGE_NS11 + "#"</span> |
| + WSConstants.ENC_KEY_VALUE_TYPE); |
| } |
| |
| <span class="fc" id="L618"> dkSign.prepare(doc, rmd.getSecHeader());</span> |
| |
| <span class="pc bpc" id="L620" title="1 of 2 branches missed."> if(rpd.isTokenProtection()) {</span> |
| |
| //Hack to handle reference id issues |
| //TODO Need a better fix |
| <span class="nc" id="L624"> String sigTokId = tok.getId();</span> |
| <span class="nc bnc" id="L625" title="All 2 branches missed."> if(sigTokId.startsWith("#")) {</span> |
| <span class="nc" id="L626"> sigTokId = sigTokId.substring(1);</span> |
| } |
| <span class="nc" id="L628"> sigParts.add(new WSEncryptionPart(sigTokId));</span> |
| } |
| |
| <span class="fc" id="L631"> dkSign.setParts(sigParts);</span> |
| |
| <span class="fc" id="L633"> List<Reference> referenceList</span> |
| = dkSign.addReferencesToSign(sigParts, rmd.getSecHeader()); |
| |
| //Add elements to header |
| //Do signature |
| <span class="pc bpc" id="L638" title="1 of 4 branches missed."> if (rpd.getProtectionOrder().equals(SPConstants.ENCRYPT_BEFORE_SIGNING) &&</span> |
| this.mainRefListElement != null ) { |
| |
| /** |
| * <xenc:ReferenceList> |
| * <xenc:DataReference URI="#EncDataId-2"/> |
| * </xenc:ReferenceList> |
| * If there is a reference list as above we need to first prepend reference list |
| * with the new derived key. Then we need to prepend Signature to newly added derived key. |
| */ |
| |
| // Add DeriveKey before ReferenceList |
| <span class="fc" id="L650"> RampartUtil.insertSiblingBefore(rmd, this.mainRefListElement, dkSign.getdktElement());</span> |
| |
| // Insert signature before DerivedKey |
| <span class="fc" id="L653"> dkSign.computeSignature(referenceList, true, dkSign.getdktElement());</span> |
| <span class="fc" id="L654"> this.setInsertionLocation(this.mainRefListElement);</span> |
| } else { |
| |
| /** |
| * Add <wsc:DerivedKeyToken>..</wsc:DerivedKeyToken> to security |
| * header. |
| */ |
| <span class="fc" id="L661"> dkSign.appendDKElementToHeader(rmd.getSecHeader());</span> |
| |
| <span class="fc" id="L663"> this.setInsertionLocation(dkSign.getdktElement());</span> |
| |
| /** |
| * In this case we need to insert <Signature>..</Signature> element |
| * before this.mainRefListElement element. In other words we need to |
| * prepend <Signature>...</Signature> element to this.mainRefListElement. |
| */ |
| <span class="fc" id="L670"> dkSign.computeSignature(referenceList, false, this.getInsertionLocation());</span> |
| <span class="fc" id="L671"> this.setInsertionLocation(dkSign.getSignatureElement());</span> |
| } |
| |
| <span class="fc" id="L674"> return dkSign.getSignatureValue();</span> |
| |
| <span class="nc" id="L676"> } catch (ConversationException e) {</span> |
| <span class="nc" id="L677"> throw new RampartException(</span> |
| "errorInDerivedKeyTokenSignature", e); |
| <span class="nc" id="L679"> } catch (WSSecurityException e) {</span> |
| <span class="nc" id="L680"> throw new RampartException(</span> |
| "errorInDerivedKeyTokenSignature", e); |
| } |
| } else { |
| try { |
| <span class="fc" id="L685"> WSSecSignature sig = new WSSecSignature();</span> |
| <span class="fc" id="L686"> sig.setWsConfig(rmd.getConfig());</span> |
| |
| // If a EncryptedKeyToken is used, set the correct value type to |
| // be used in the wsse:Reference in ds:KeyInfo |
| <span class="pc bpc" id="L690" title="1 of 2 branches missed."> if (policyToken instanceof X509Token) {</span> |
| <span class="fc bfc" id="L691" title="All 2 branches covered."> if (rmd.isInitiator()) {</span> |
| <span class="fc" id="L692"> sig.setCustomTokenValueType(WSConstants.SOAPMESSAGE_NS11 + "#"</span> |
| + WSConstants.ENC_KEY_VALUE_TYPE); |
| <span class="fc" id="L694"> sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);</span> |
| } else { |
| // the tok has to be an EncryptedKey token |
| <span class="fc" id="L697"> sig.setEncrKeySha1value(((EncryptedKeyToken) tok).getSHA1());</span> |
| <span class="fc" id="L698"> sig.setKeyIdentifierType(WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER);</span> |
| } |
| |
| <span class="nc bnc" id="L701" title="All 2 branches missed."> } else if (policyToken instanceof IssuedToken) {</span> |
| |
| <span class="nc" id="L703"> sig.setCustomTokenValueType(RampartUtil.getSAML10AssertionNamespace());</span> |
| <span class="nc" id="L704"> sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);</span> |
| } |
| |
| String sigTokId; |
| |
| <span class="pc bpc" id="L709" title="1 of 2 branches missed."> if ( policyToken instanceof SecureConversationToken) {</span> |
| <span class="nc" id="L710"> sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);</span> |
| <span class="nc" id="L711"> OMElement ref = tok.getAttachedReference();</span> |
| <span class="nc bnc" id="L712" title="All 2 branches missed."> if(ref == null) {</span> |
| <span class="nc" id="L713"> ref = tok.getUnattachedReference();</span> |
| } |
| |
| <span class="nc bnc" id="L716" title="All 2 branches missed."> if (ref != null) {</span> |
| <span class="nc" id="L717"> sigTokId = SimpleTokenStore.getIdFromSTR(ref);</span> |
| } else { |
| <span class="nc" id="L719"> sigTokId = tok.getId();</span> |
| } |
| <span class="nc" id="L721"> } else {</span> |
| <span class="fc" id="L722"> sigTokId = tok.getId();</span> |
| } |
| |
| //Hack to handle reference id issues |
| //TODO Need a better fix |
| <span class="pc bpc" id="L727" title="1 of 2 branches missed."> if(sigTokId.startsWith("#")) {</span> |
| <span class="nc" id="L728"> sigTokId = sigTokId.substring(1);</span> |
| } |
| |
| <span class="fc" id="L731"> sig.setCustomTokenId(sigTokId);</span> |
| <span class="fc" id="L732"> sig.setSecretKey(tok.getSecret());</span> |
| <span class="fc" id="L733"> sig.setSignatureAlgorithm(algorithmSuite.getAsymmetricSignature()); // TODO what is the correct algorith ? For sure one is redundant</span> |
| <span class="fc" id="L734"> sig.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature());</span> |
| <span class="fc" id="L735"> sig.setDigestAlgo(algorithmSuite.getDigest());</span> |
| <span class="fc" id="L736"> sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rpd</span> |
| .getRampartConfig(), rmd.getCustomClassLoader()), |
| rmd.getSecHeader()); |
| |
| <span class="fc" id="L740"> sig.setParts(sigParts);</span> |
| <span class="fc" id="L741"> List<Reference> referenceList</span> |
| = sig.addReferencesToSign(sigParts, rmd.getSecHeader()); |
| |
| //Do signature |
| <span class="pc bpc" id="L745" title="1 of 4 branches missed."> if (rpd.getProtectionOrder().equals(SPConstants.ENCRYPT_BEFORE_SIGNING)</span> |
| && this.mainRefListElement != null) { |
| |
| /** |
| * In this case we need to insert <Signature>..</Signature> element |
| * before this.mainRefListElement element. In other words we need to |
| * prepend <Signature>...</Signature> element to this.mainRefListElement. |
| * this.mainRefListElement is equivalent to |
| * <xenc:ReferenceList> |
| * <xenc:DataReference URI="#EncDataId-2"/> |
| * </xenc:ReferenceList> |
| */ |
| <span class="fc" id="L757"> sig.computeSignature(referenceList, true, this.mainRefListElement);</span> |
| <span class="fc" id="L758"> this.setInsertionLocation(this.mainRefListElement);</span> |
| } else { |
| |
| /** |
| * In this case we need to append <Signature>..</Signature> element to |
| * current insertion location. |
| */ |
| <span class="fc" id="L765"> sig.computeSignature(referenceList, false, this.getInsertionLocation());</span> |
| <span class="fc" id="L766"> this.setInsertionLocation(sig.getSignatureElement());</span> |
| } |
| |
| |
| <span class="fc" id="L770"> return sig.getSignatureValue();</span> |
| |
| <span class="nc" id="L772"> } catch (WSSecurityException e) {</span> |
| <span class="nc" id="L773"> throw new RampartException("errorInSignatureWithACustomToken", e);</span> |
| } |
| |
| } |
| } |
| |
| |
| /** |
| * Get hold of the token from the token storage |
| * @param rmd |
| * @param tokenId |
| * @return token from the token storage |
| * @throws RampartException |
| */ |
| protected org.apache.rahas.Token getToken(RampartMessageData rmd, |
| String tokenId) throws RampartException { |
| org.apache.rahas.Token tok; |
| try { |
| <span class="fc" id="L791"> tok = rmd.getTokenStorage().getToken(tokenId);</span> |
| <span class="nc" id="L792"> } catch (TrustException e) {</span> |
| <span class="nc" id="L793"> throw new RampartException("errorInRetrievingTokenId", </span> |
| new String[]{tokenId}, e); |
| <span class="fc" id="L795"> }</span> |
| |
| <span class="pc bpc" id="L797" title="1 of 2 branches missed."> if(tok == null) {</span> |
| <span class="nc" id="L798"> throw new RampartException("errorInRetrievingTokenId", </span> |
| new String[]{tokenId}); |
| } |
| <span class="fc" id="L801"> return tok;</span> |
| } |
| |
| |
| protected void addSignatureConfirmation(RampartMessageData rmd, List<WSEncryptionPart> sigParts) { |
| |
| <span class="fc bfc" id="L807" title="All 2 branches covered."> if(!rmd.getPolicyData().isSignatureConfirmation()) {</span> |
| |
| //If we don't require sig confirmation simply go back :-) |
| <span class="fc" id="L810"> return;</span> |
| } |
| |
| <span class="fc" id="L813"> Document doc = rmd.getDocument();</span> |
| |
| <span class="fc" id="L815"> List<WSHandlerResult> results</span> |
| = (List<WSHandlerResult>)rmd.getMsgContext().getProperty(WSHandlerConstants.RECV_RESULTS); |
| /* |
| * loop over all results gathered by all handlers in the chain. For each |
| * handler result get the various actions. After that loop we have all |
| * signature results in the signatureActions list. |
| */ |
| <span class="fc" id="L822"> List<WSSecurityEngineResult> signatureActions = new ArrayList<WSSecurityEngineResult>();</span> |
| <span class="fc bfc" id="L823" title="All 2 branches covered."> for (Object result : results) {</span> |
| <span class="fc" id="L824"> WSHandlerResult wshResult = (WSHandlerResult) result;</span> |
| |
| <span class="fc" id="L826"> WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),</span> |
| WSConstants.SIGN, signatureActions); |
| <span class="fc" id="L828"> WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),</span> |
| WSConstants.ST_SIGNED, signatureActions); |
| <span class="fc" id="L830"> WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),</span> |
| WSConstants.UT_SIGN, signatureActions); |
| <span class="fc" id="L832"> }</span> |
| |
| // prepare a SignatureConfirmation token |
| <span class="fc" id="L835"> WSSecSignatureConfirmation wsc = new WSSecSignatureConfirmation();</span> |
| <span class="pc bpc" id="L836" title="1 of 2 branches missed."> if (signatureActions.size() > 0) {</span> |
| <span class="pc bpc" id="L837" title="1 of 2 branches missed."> if (log.isDebugEnabled()) {</span> |
| <span class="nc" id="L838"> log.debug("Signature Confirmation: number of Signature results: "</span> |
| + signatureActions.size()); |
| } |
| <span class="fc bfc" id="L841" title="All 2 branches covered."> for (WSSecurityEngineResult signatureAction : signatureActions) {</span> |
| <span class="fc" id="L842"> byte[] sigVal = (byte[]) signatureAction.get(WSSecurityEngineResult.TAG_SIGNATURE_VALUE);</span> |
| <span class="fc" id="L843"> wsc.setSignatureValue(sigVal);</span> |
| <span class="fc" id="L844"> wsc.prepare(doc);</span> |
| <span class="fc" id="L845"> RampartUtil.appendChildToSecHeader(rmd, wsc.getSignatureConfirmationElement());</span> |
| <span class="pc bpc" id="L846" title="1 of 2 branches missed."> if (sigParts != null) {</span> |
| <span class="fc" id="L847"> sigParts.add(new WSEncryptionPart(wsc.getId()));</span> |
| } |
| <span class="fc" id="L849"> }</span> |
| } else { |
| //No Sig value |
| <span class="nc" id="L852"> wsc.prepare(doc);</span> |
| <span class="nc" id="L853"> RampartUtil.appendChildToSecHeader(rmd, wsc.getSignatureConfirmationElement());</span> |
| <span class="nc bnc" id="L854" title="All 2 branches missed."> if(sigParts != null) {</span> |
| <span class="nc" id="L855"> sigParts.add(new WSEncryptionPart(wsc.getId()));</span> |
| } |
| } |
| <span class="fc" id="L858"> }</span> |
| private void checkForX509PkiPath(WSSecSignature sig, Token token){ |
| <span class="pc bpc" id="L860" title="1 of 2 branches missed."> if (token instanceof X509Token) {</span> |
| <span class="fc" id="L861"> X509Token x509Token = (X509Token) token;</span> |
| <span class="pc bpc" id="L862" title="2 of 4 branches missed."> if (x509Token.getTokenVersionAndType().equals(Constants.WSS_X509_PKI_PATH_V1_TOKEN10)</span> |
| || x509Token.getTokenVersionAndType().equals(Constants.WSS_X509_PKI_PATH_V1_TOKEN11)) { |
| <span class="nc" id="L864"> sig.setUseSingleCertificate(false);</span> |
| } |
| } |
| <span class="fc" id="L867"> }</span> |
| |
| |
| } |
| </pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.6.1.201212231917</span></div></body></html> |