| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.wss4j.dom.message; |
| |
| import java.io.IOException; |
| import java.security.spec.AlgorithmParameterSpec; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.crypto.BadPaddingException; |
| import javax.crypto.Cipher; |
| import javax.crypto.IllegalBlockSizeException; |
| import javax.crypto.SecretKey; |
| import javax.security.auth.callback.Callback; |
| import javax.security.auth.callback.CallbackHandler; |
| import javax.security.auth.callback.UnsupportedCallbackException; |
| |
| import org.apache.wss4j.common.WSEncryptionPart; |
| import org.apache.wss4j.common.ext.Attachment; |
| import org.apache.wss4j.common.ext.AttachmentRequestCallback; |
| import org.apache.wss4j.common.ext.AttachmentResultCallback; |
| import org.apache.wss4j.common.ext.WSSecurityException; |
| import org.apache.wss4j.common.util.AttachmentUtils; |
| import org.apache.wss4j.common.util.XMLUtils; |
| import org.apache.wss4j.dom.WSConstants; |
| import org.apache.wss4j.dom.WSDocInfo; |
| import org.apache.wss4j.dom.WsuIdAllocator; |
| import org.apache.wss4j.dom.callback.CallbackLookup; |
| import org.apache.wss4j.dom.callback.DOMCallbackLookup; |
| import org.apache.wss4j.dom.util.WSSecurityUtil; |
| import org.apache.xml.security.algorithms.JCEMapper; |
| import org.apache.xml.security.encryption.AbstractSerializer; |
| import org.apache.xml.security.encryption.EncryptedData; |
| import org.apache.xml.security.encryption.Serializer; |
| import org.apache.xml.security.encryption.TransformSerializer; |
| import org.apache.xml.security.encryption.XMLCipher; |
| import org.apache.xml.security.encryption.XMLCipherUtil; |
| import org.apache.xml.security.encryption.XMLEncryptionException; |
| import org.apache.xml.security.keys.KeyInfo; |
| import org.apache.xml.security.stax.ext.XMLSecurityConstants; |
| import org.apache.xml.security.utils.EncryptionConstants; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| /** |
| * A class to encrypt references. |
| */ |
| public class Encryptor { |
| |
| private Document doc; |
| private WSSecHeader securityHeader; |
| private WsuIdAllocator idAllocator; |
| private CallbackLookup callbackLookup; |
| private CallbackHandler attachmentCallbackHandler; |
| private boolean storeBytesInAttachment; |
| private Serializer encryptionSerializer; |
| private boolean expandXopInclude; |
| private WSDocInfo wsDocInfo; |
| |
| public List<String> doEncryption( |
| KeyInfo keyInfo, |
| SecretKey secretKey, |
| String encryptionAlgorithm, |
| List<WSEncryptionPart> references, |
| List<Element> attachmentEncryptedDataElements |
| ) throws WSSecurityException { |
| |
| XMLCipher xmlCipher = null; |
| try { |
| if (encryptionSerializer != null) { |
| xmlCipher = XMLCipher.getInstance(encryptionSerializer, encryptionAlgorithm); |
| } else { |
| xmlCipher = XMLCipher.getInstance(encryptionAlgorithm); |
| } |
| } catch (XMLEncryptionException ex) { |
| throw new WSSecurityException( |
| WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, ex |
| ); |
| } |
| |
| List<String> encDataRef = new ArrayList<>(); |
| WSEncryptionPart attachmentEncryptionPart = null; |
| for (int part = 0; part < references.size(); part++) { |
| WSEncryptionPart encPart = references.get(part); |
| |
| if (encPart.getId() != null && encPart.getId().startsWith("cid:")) { |
| attachmentEncryptionPart = encPart; |
| continue; |
| } |
| |
| // |
| // Get the data to encrypt. |
| // |
| if (callbackLookup == null) { |
| callbackLookup = new DOMCallbackLookup(doc); |
| } |
| List<Element> elementsToEncrypt = |
| WSSecurityUtil.findElements(encPart, callbackLookup, doc); |
| if (elementsToEncrypt == null || elementsToEncrypt.isEmpty()) { |
| if (!encPart.isRequired()) { |
| continue; |
| } |
| throw new WSSecurityException( |
| WSSecurityException.ErrorCode.FAILURE, |
| "noEncElement", |
| new Object[] {"{" + encPart.getNamespace() + "}" + encPart.getName()}); |
| } |
| |
| if (expandXopInclude) { |
| for (Element elementToEncrypt : elementsToEncrypt) { |
| Element encrElement = elementToEncrypt; |
| |
| // Look for xop:Include Nodes |
| List<Element> includeElements = |
| XMLUtils.findElements(elementToEncrypt.getFirstChild(), "Include", WSConstants.XOP_NS); |
| if (includeElements != null && !includeElements.isEmpty()) { |
| // See if we already have an expanded Element available (from Signature) that matches the current Element |
| Element matchingElement = findMatchingExpandedElement(encrElement); |
| if (matchingElement != null && matchingElement != encrElement) { |
| // If so then replace the existing Element to encrypt in the SOAP Envelope |
| encrElement.getParentNode().replaceChild(matchingElement, encrElement); |
| encrElement = matchingElement; |
| |
| // We already have an expanded Element, but might need to delete the attachments |
| for (Element includeElement : includeElements) { |
| String xopURI = includeElement.getAttributeNS(null, "href"); |
| if (xopURI != null) { |
| // Delete the attachment |
| |
| AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback(); |
| attachmentRequestCallback.setAttachmentId(WSSecurityUtil.getAttachmentId(xopURI)); |
| |
| try { |
| attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback}); |
| } catch (UnsupportedCallbackException | IOException e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, e); |
| } |
| } |
| } |
| } else { |
| // Here we didn't find an already expanded Element, so inline the attachment bytes |
| WSSecurityUtil.inlineAttachments(includeElements, attachmentCallbackHandler, true); |
| } |
| } |
| |
| if (storeBytesInAttachment) { |
| try { |
| String id = |
| encryptElementInAttachment(keyInfo, secretKey, encryptionAlgorithm, encPart, encrElement); |
| encPart.setEncId(id); |
| encDataRef.add("#" + id); |
| } catch (Exception ex) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex); |
| } |
| } else { |
| String id = |
| encryptElement(encrElement, encPart.getEncModifier(), xmlCipher, secretKey, keyInfo); |
| encPart.setEncId(id); |
| encDataRef.add("#" + id); |
| } |
| } |
| } else if (storeBytesInAttachment) { |
| for (Element elementToEncrypt : elementsToEncrypt) { |
| try { |
| String id = |
| encryptElementInAttachment(keyInfo, secretKey, encryptionAlgorithm, encPart, elementToEncrypt); |
| encPart.setEncId(id); |
| encDataRef.add("#" + id); |
| } catch (Exception ex) { |
| throw new WSSecurityException( |
| WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex |
| ); |
| } |
| } |
| } else { |
| for (Element elementToEncrypt : elementsToEncrypt) { |
| String id = |
| encryptElement(elementToEncrypt, encPart.getEncModifier(), xmlCipher, secretKey, keyInfo); |
| encPart.setEncId(id); |
| encDataRef.add("#" + id); |
| } |
| } |
| } |
| |
| if (attachmentEncryptionPart != null) { |
| encryptAttachment(keyInfo, secretKey, encryptionAlgorithm, attachmentEncryptionPart, encDataRef, |
| attachmentEncryptedDataElements); |
| } |
| |
| return encDataRef; |
| } |
| |
| private Element findMatchingExpandedElement(Element element) { |
| Element matchingElement = null; |
| |
| if (element.hasAttributeNS(WSConstants.WSU_NS, "Id")) { |
| String id = element.getAttributeNS(WSConstants.WSU_NS, "Id"); |
| matchingElement = wsDocInfo.getTokenElement(id); |
| } |
| |
| if (matchingElement == null && element.hasAttributeNS(null, "Id")) { |
| String id = element.getAttributeNS(null, "Id"); |
| matchingElement = wsDocInfo.getTokenElement(id); |
| } |
| |
| // Check the Elements are the same |
| if (matchingElement != null && matchingElement.getNamespaceURI().equals(element.getNamespaceURI()) |
| && matchingElement.getLocalName().equals(element.getLocalName())) { |
| return matchingElement; |
| } |
| |
| return null; |
| } |
| |
| private String encryptElementInAttachment( |
| KeyInfo keyInfo, |
| SecretKey secretKey, |
| String encryptionAlgorithm, |
| WSEncryptionPart encryptionPart, |
| Element elementToEncrypt |
| ) throws Exception { |
| |
| String type = EncryptionConstants.TYPE_ELEMENT; |
| if ("Content".equals(encryptionPart.getEncModifier())) { |
| type = EncryptionConstants.TYPE_CONTENT; |
| } |
| |
| final String attachmentId = idAllocator.createId("", doc); |
| String encEncryptedDataId = idAllocator.createId("ED-", attachmentId); |
| |
| if ("Header".equals(encryptionPart.getEncModifier()) |
| && elementToEncrypt.getParentNode().equals(WSSecurityUtil.getSOAPHeader(doc))) { |
| createEncryptedHeaderElement(securityHeader, elementToEncrypt, idAllocator); |
| } |
| |
| Element encryptedData = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptedData"); |
| encryptedData.setAttributeNS(null, "Id", encEncryptedDataId); |
| encryptedData.setAttributeNS(null, "Type", type); |
| |
| Element encryptionMethod = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptionMethod"); |
| encryptionMethod.setAttributeNS(null, "Algorithm", encryptionAlgorithm); |
| |
| encryptedData.appendChild(encryptionMethod); |
| encryptedData.appendChild(WSSecurityUtil.cloneElement(doc, keyInfo.getElement())); |
| |
| Element cipherData = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherData"); |
| Element cipherValue = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherValue"); |
| cipherData.appendChild(cipherValue); |
| encryptedData.appendChild(cipherData); |
| |
| Cipher cipher = createCipher(encryptionAlgorithm, secretKey); |
| |
| // Serialize and encrypt the element |
| AbstractSerializer serializer = new TransformSerializer(true); |
| |
| byte[] serializedOctets = null; |
| if (type.equals(EncryptionConstants.TYPE_CONTENT)) { |
| NodeList children = elementToEncrypt.getChildNodes(); |
| if (null != children) { |
| serializedOctets = serializer.serializeToByteArray(children); |
| } else { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, |
| "Element has no content."); |
| } |
| } else { |
| serializedOctets = serializer.serializeToByteArray(elementToEncrypt); |
| } |
| |
| byte[] encryptedBytes = null; |
| try { |
| encryptedBytes = cipher.doFinal(serializedOctets); |
| } catch (IllegalBlockSizeException ibse) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ibse); |
| } catch (BadPaddingException bpe) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, bpe); |
| } |
| |
| // Now build up to a properly XML Encryption encoded octet stream |
| byte[] iv = cipher.getIV(); |
| byte[] finalEncryptedBytes = new byte[iv.length + encryptedBytes.length]; |
| System.arraycopy(iv, 0, finalEncryptedBytes, 0, iv.length); |
| System.arraycopy(encryptedBytes, 0, finalEncryptedBytes, iv.length, encryptedBytes.length); |
| |
| if ("Content".equals(encryptionPart.getEncModifier())) { |
| Node child = elementToEncrypt.getFirstChild(); |
| while (child != null) { |
| Node sibling = child.getNextSibling(); |
| elementToEncrypt.removeChild(child); |
| child = sibling; |
| } |
| elementToEncrypt.appendChild(encryptedData); |
| } else { |
| elementToEncrypt.getParentNode().replaceChild(encryptedData, elementToEncrypt); |
| } |
| |
| AttachmentUtils.storeBytesInAttachment(cipherValue, doc, attachmentId, |
| finalEncryptedBytes, attachmentCallbackHandler); |
| |
| return encEncryptedDataId; |
| } |
| |
| private void encryptAttachment( |
| KeyInfo keyInfo, |
| SecretKey secretKey, |
| String encryptionAlgorithm, |
| WSEncryptionPart attachmentEncryptionPart, |
| List<String> encDataRef, |
| List<Element> attachmentEncryptedDataElements |
| ) throws WSSecurityException { |
| if (attachmentCallbackHandler == null) { |
| throw new WSSecurityException( |
| WSSecurityException.ErrorCode.FAILURE, |
| "empty", new Object[] {"no attachment callbackhandler supplied"} |
| ); |
| } |
| |
| AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback(); |
| String id = AttachmentUtils.getAttachmentId(attachmentEncryptionPart.getId()); |
| attachmentRequestCallback.setAttachmentId(id); |
| try { |
| attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback}); |
| } catch (Exception e) { |
| throw new WSSecurityException( |
| WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e |
| ); |
| } |
| String attachmentEncryptedDataType = WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY; |
| if ("Element".equals(attachmentEncryptionPart.getEncModifier())) { |
| attachmentEncryptedDataType = WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE; |
| } |
| |
| for (Attachment attachment : attachmentRequestCallback.getAttachments()) { |
| |
| final String attachmentId = attachment.getId(); |
| String encEncryptedDataId = idAllocator.createId("ED-", attachmentId); |
| encDataRef.add("#" + encEncryptedDataId); |
| |
| Element encryptedData = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptedData"); |
| encryptedData.setAttributeNS(null, "Id", encEncryptedDataId); |
| encryptedData.setAttributeNS(null, "MimeType", attachment.getMimeType()); |
| encryptedData.setAttributeNS(null, "Type", attachmentEncryptedDataType); |
| |
| Element encryptionMethod = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":EncryptionMethod"); |
| encryptionMethod.setAttributeNS(null, "Algorithm", encryptionAlgorithm); |
| |
| encryptedData.appendChild(encryptionMethod); |
| encryptedData.appendChild(WSSecurityUtil.cloneElement(doc, keyInfo.getElement())); |
| |
| Element cipherData = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherData"); |
| Element cipherReference = |
| doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":CipherReference"); |
| cipherReference.setAttributeNS(null, "URI", "cid:" + attachmentId); |
| |
| Element transforms = doc.createElementNS(WSConstants.ENC_NS, WSConstants.ENC_PREFIX + ":Transforms"); |
| Element transform = doc.createElementNS(WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":Transform"); |
| transform.setAttributeNS(null, "Algorithm", WSConstants.SWA_ATTACHMENT_CIPHERTEXT_TRANS); |
| transforms.appendChild(transform); |
| |
| cipherReference.appendChild(transforms); |
| cipherData.appendChild(cipherReference); |
| encryptedData.appendChild(cipherData); |
| |
| attachmentEncryptedDataElements.add(encryptedData); |
| |
| Attachment resultAttachment = new Attachment(); |
| resultAttachment.setId(attachmentId); |
| resultAttachment.setMimeType("application/octet-stream"); |
| |
| Cipher cipher = createCipher(encryptionAlgorithm, secretKey); |
| |
| Map<String, String> headers = new HashMap<>(attachment.getHeaders()); |
| resultAttachment.setSourceStream( |
| AttachmentUtils.setupAttachmentEncryptionStream( |
| cipher, "Element".equals(attachmentEncryptionPart.getEncModifier()), |
| attachment, headers |
| ) |
| ); |
| resultAttachment.addHeaders(headers); |
| |
| AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback(); |
| attachmentResultCallback.setAttachmentId(attachmentId); |
| attachmentResultCallback.setAttachment(resultAttachment); |
| try { |
| attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback}); |
| } catch (Exception e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e); |
| } |
| } |
| } |
| |
| private Cipher createCipher(String encryptionAlgorithm, SecretKey secretKey) |
| throws WSSecurityException { |
| String jceAlgorithm = JCEMapper.translateURItoJCEID(encryptionAlgorithm); |
| try { |
| Cipher cipher = Cipher.getInstance(jceAlgorithm); |
| |
| int ivLen = JCEMapper.getIVLengthFromURI(encryptionAlgorithm) / 8; |
| byte[] iv = XMLSecurityConstants.generateBytes(ivLen); |
| AlgorithmParameterSpec paramSpec = |
| XMLCipherUtil.constructBlockCipherParameters(encryptionAlgorithm, iv); |
| cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec); |
| |
| return cipher; |
| } catch (Exception e) { |
| throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e); |
| } |
| } |
| |
| /** |
| * Encrypt an element. |
| */ |
| private String encryptElement( |
| Element elementToEncrypt, |
| String modifier, |
| XMLCipher xmlCipher, |
| SecretKey secretKey, |
| KeyInfo keyInfo |
| ) throws WSSecurityException { |
| |
| boolean content = "Content".equals(modifier); |
| // |
| // Encrypt data, and set necessary attributes in xenc:EncryptedData |
| // |
| String xencEncryptedDataId = idAllocator.createId("ED-", elementToEncrypt); |
| try { |
| if ("Header".equals(modifier)) { |
| String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement()); |
| if (elementToEncrypt.getParentNode().getNamespaceURI().equals(soapNamespace) |
| && WSConstants.ELEM_HEADER.equals(elementToEncrypt.getParentNode().getLocalName())) { |
| createEncryptedHeaderElement(securityHeader, elementToEncrypt, idAllocator); |
| } |
| } |
| |
| xmlCipher.init(XMLCipher.ENCRYPT_MODE, secretKey); |
| EncryptedData encData = xmlCipher.getEncryptedData(); |
| encData.setId(xencEncryptedDataId); |
| encData.setKeyInfo(keyInfo); |
| xmlCipher.doFinal(doc, elementToEncrypt, content); |
| return xencEncryptedDataId; |
| } catch (Exception ex) { |
| throw new WSSecurityException( |
| WSSecurityException.ErrorCode.FAILED_ENCRYPTION, ex |
| ); |
| } |
| } |
| |
| private static void createEncryptedHeaderElement( |
| WSSecHeader securityHeader, |
| Element elementToEncrypt, |
| WsuIdAllocator idAllocator |
| ) { |
| Element elem = |
| elementToEncrypt.getOwnerDocument().createElementNS( |
| WSConstants.WSSE11_NS, "wsse11:" + WSConstants.ENCRYPTED_HEADER |
| ); |
| XMLUtils.setNamespace(elem, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX); |
| String wsuPrefix = |
| XMLUtils.setNamespace(elem, WSConstants.WSU_NS, WSConstants.WSU_PREFIX); |
| String headerId = idAllocator.createId("EH-", elementToEncrypt); |
| elem.setAttributeNS( |
| WSConstants.WSU_NS, wsuPrefix + ":Id", headerId |
| ); |
| |
| // |
| // Add the EncryptedHeader node to the element to be encrypted's parent |
| // (i.e. the SOAP header). Add the element to be encrypted to the Encrypted |
| // Header node as well |
| // |
| Node parent = elementToEncrypt.getParentNode(); |
| elementToEncrypt = (Element)parent.replaceChild(elem, elementToEncrypt); |
| elem.appendChild(elementToEncrypt); |
| |
| if (securityHeader != null) { |
| NamedNodeMap map = securityHeader.getSecurityHeaderElement().getAttributes(); |
| for (int i = 0; i < map.getLength(); i++) { |
| Attr attr = (Attr)map.item(i); |
| if (WSConstants.URI_SOAP11_ENV.equals(attr.getNamespaceURI()) |
| || WSConstants.URI_SOAP12_ENV.equals(attr.getNamespaceURI())) { |
| String soapEnvPrefix = |
| XMLUtils.setNamespace( |
| elem, attr.getNamespaceURI(), WSConstants.DEFAULT_SOAP_PREFIX |
| ); |
| elem.setAttributeNS( |
| attr.getNamespaceURI(), |
| soapEnvPrefix + ":" + attr.getLocalName(), |
| attr.getValue() |
| ); |
| } |
| } |
| } |
| |
| } |
| |
| public Document getDoc() { |
| return doc; |
| } |
| |
| public void setDoc(Document doc) { |
| this.doc = doc; |
| } |
| |
| public WSSecHeader getSecurityHeader() { |
| return securityHeader; |
| } |
| |
| public void setSecurityHeader(WSSecHeader securityHeader) { |
| this.securityHeader = securityHeader; |
| } |
| |
| public WsuIdAllocator getIdAllocator() { |
| return idAllocator; |
| } |
| |
| public void setIdAllocator(WsuIdAllocator idAllocator) { |
| this.idAllocator = idAllocator; |
| } |
| |
| public CallbackLookup getCallbackLookup() { |
| return callbackLookup; |
| } |
| |
| public void setCallbackLookup(CallbackLookup callbackLookup) { |
| this.callbackLookup = callbackLookup; |
| } |
| |
| public CallbackHandler getAttachmentCallbackHandler() { |
| return attachmentCallbackHandler; |
| } |
| |
| public void setAttachmentCallbackHandler(CallbackHandler attachmentCallbackHandler) { |
| this.attachmentCallbackHandler = attachmentCallbackHandler; |
| } |
| |
| public boolean isStoreBytesInAttachment() { |
| return storeBytesInAttachment; |
| } |
| |
| public void setStoreBytesInAttachment(boolean storeBytesInAttachment) { |
| this.storeBytesInAttachment = storeBytesInAttachment; |
| } |
| |
| public Serializer getEncryptionSerializer() { |
| return encryptionSerializer; |
| } |
| |
| public void setEncryptionSerializer(Serializer encryptionSerializer) { |
| this.encryptionSerializer = encryptionSerializer; |
| } |
| |
| public boolean isExpandXopInclude() { |
| return expandXopInclude; |
| } |
| |
| public void setExpandXopInclude(boolean expandXopInclude) { |
| this.expandXopInclude = expandXopInclude; |
| } |
| |
| public WSDocInfo getWsDocInfo() { |
| return wsDocInfo; |
| } |
| |
| public void setWsDocInfo(WSDocInfo wsDocInfo) { |
| this.wsDocInfo = wsDocInfo; |
| } |
| |
| } |