aboutsummaryrefslogtreecommitdiff
path: root/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java
diff options
context:
space:
mode:
Diffstat (limited to 'modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java')
-rw-r--r--modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java479
1 files changed, 479 insertions, 0 deletions
diff --git a/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java
new file mode 100644
index 00000000..8c294c97
--- /dev/null
+++ b/modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/clients/szr/SzrClient.java
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2018 A-SIT Plus GmbH
+ * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ,
+ * A-SIT Plus GmbH, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "License");
+ * You may not use this work except in compliance with the License.
+ * You may obtain a copy of the License at:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * 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.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ */
+
+package at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.szr;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Dispatch;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.xpath.XPathAPI;
+import org.springframework.stereotype.Service;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.AbstractSoapClient;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.clients.AbstractSoapClient.HttpClientConfig.HttpClientConfigBuilder;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.MatchedPersonResult;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.dao.SimpleEidasData;
+import at.asitplus.eidas.specific.modules.auth.eidas.v2.exception.SzrCommunicationException;
+import at.gv.e_government.reference.namespace.persondata._20020228.AlternativeNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.IdentificationType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PersonNameType;
+import at.gv.e_government.reference.namespace.persondata._20020228.PhysicalPersonType;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.XmlNamespaceConstants;
+import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException;
+import at.gv.egiz.eaaf.core.impl.utils.DomUtils;
+import lombok.extern.slf4j.Slf4j;
+import szrservices.GetBPK;
+import szrservices.GetBPKResponse;
+import szrservices.GetIdentityLinkEidas;
+import szrservices.GetIdentityLinkEidasResponse;
+import szrservices.IdentityLinkType;
+import szrservices.JwsHeaderParam;
+import szrservices.ObjectFactory;
+import szrservices.PersonInfoType;
+import szrservices.SZR;
+import szrservices.SZRException_Exception;
+import szrservices.SignContent;
+import szrservices.SignContentEntry;
+import szrservices.SignContentResponseType;
+import szrservices.TravelDocumentType;
+
+
+@Slf4j
+@Service("SZRClientForeIDAS")
+public class SzrClient extends AbstractSoapClient {
+
+ private static final String CLIENT_DEFAULT = "DefaultClient";
+ private static final String CLIENT_RAW = "RawClient";
+
+ private static final String ATTR_NAME_VSZ = "urn:eidgvat:attributes.vsz.value";
+ private static final String ATTR_NAME_PUBKEYS = "urn:eidgvat:attributes.user.pubkeys";
+ private static final String ATTR_NAME_STATUS = "urn:eidgvat:attributes.eid.status";
+ private static final String KEY_BC_BIND = "bcBindReq";
+ private static final String JOSE_HEADER_USERCERTPINNING_TYPE = "urn:at.gv.eid:bindtype";
+ private static final String JOSE_HEADER_USERCERTPINNING_EIDASBIND = "urn:at.gv.eid:eidasBind";
+ public static final String ATTR_NAME_MDS = "urn:eidgvat:mds";
+
+ // client for anything, without identitylink
+ private SZR szr = null;
+
+ // RAW client is needed for identitylink
+ private Dispatch<Source> dispatch = null;
+
+ final ObjectMapper mapper = new ObjectMapper();
+
+
+ /**
+ * Get IdentityLink of a person.
+ *
+ *
+ * @param matchedPersonData eID information of an already matched person.
+ * @return IdentityLink
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public IdentityLinkType getIdentityLinkInRawMode(MatchedPersonResult matchedPersonData)
+ throws SzrCommunicationException {
+ try {
+ final GetIdentityLinkEidas getIdl = new GetIdentityLinkEidas();
+ getIdl.setPersonInfo(generateSzrRequest(matchedPersonData));
+
+ return getIdentityLinkGeneric(getIdl);
+
+ } catch (final Exception e) {
+ log.warn("SZR communication FAILED for operation: {} Reason: {}",
+ "GetIdentityLinkEidas", e.getMessage(), e);
+ throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);
+
+ }
+ }
+
+ /**
+ * Get bPK of person.
+ *
+ *
+ * @param eidData Minimum dataset of person
+ * @param target requested bPK target
+ * @param vkz Verfahrenskennzeichen
+ * @return bPK for this person
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public List<String> getBpk(SimpleEidasData eidData, String target, String vkz)
+ throws SzrCommunicationException {
+ try {
+ final GetBPK parameters = new GetBPK();
+ parameters.setPersonInfo(generateSzrRequest(eidData));
+ parameters.getBereichsKennung().add(target);
+ parameters.setVKZ(vkz);
+ final GetBPKResponse result = this.szr.getBPK(parameters);
+
+ return result.getGetBPKReturn();
+
+ } catch (final SZRException_Exception e) {
+ log.warn("SZR communication FAILED for operation: {} Reason: {}",
+ "GetBPK", e.getMessage(), e);
+ throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ }
+
+ /**
+ * Request a encrypted baseId from SZR.
+ *
+ * @param matchedPersonData eID information of an already matched person.
+ * @return encrypted baseId
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public String getEncryptedStammzahl(MatchedPersonResult matchedPersonData) throws SzrCommunicationException {
+ final String resp;
+ try {
+ resp = this.szr.getStammzahlEncrypted(generateSzrRequest(matchedPersonData), false);
+
+ } catch (SZRException_Exception e) {
+ throw new SzrCommunicationException("ernb.02", new Object[]{e.getMessage()}, e);
+
+ }
+
+ if (StringUtils.isEmpty(resp)) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"Stammzahl response empty"}); // TODO error handling
+
+ }
+
+ return resp;
+ }
+
+ /**
+ * Sign an eidasBind data-structure that combines vsz with user's pubKey and E-ID status.
+ *
+ * @param vsz encrypted baseId
+ * @param bindingPubKey binding PublicKey as PKCS1# (ASN.1) container
+ * @param eidStatus Status of the E-ID
+ * @param eidData eID information that was used for ERnP registration
+ * @return bPK for this person
+ * @throws SzrCommunicationException In case of a SZR error
+ */
+ public String getEidasBind(final String vsz, final String bindingPubKey, final String eidStatus,
+ SimpleEidasData eidData)throws SzrCommunicationException {
+
+ final Map<String, Object> eidsaBindMap = new HashMap<>();
+ eidsaBindMap.put(ATTR_NAME_VSZ, vsz);
+ eidsaBindMap.put(ATTR_NAME_STATUS, eidStatus);
+ eidsaBindMap.put(ATTR_NAME_PUBKEYS, Collections.singletonList(bindingPubKey));
+ eidsaBindMap.put(PvpAttributeDefinitions.EID_ISSUING_NATION_NAME, eidData.getCitizenCountryCode());
+ injectMdsIfAvailableAndActive(eidsaBindMap, eidData);
+
+ try {
+ final String serializedEidasBind = mapper.writeValueAsString(eidsaBindMap);
+ final SignContent req = new SignContent();
+ final SignContentEntry eidasBindInfo = new SignContentEntry();
+ eidasBindInfo.setKey(KEY_BC_BIND);
+ eidasBindInfo.setValue(serializedEidasBind);
+ req.getIn().add(eidasBindInfo);
+ req.setAppendCert(false);
+ final JwsHeaderParam eidasBindJoseHeader = new JwsHeaderParam();
+ eidasBindJoseHeader.setKey(JOSE_HEADER_USERCERTPINNING_TYPE);
+ eidasBindJoseHeader.setValue(JOSE_HEADER_USERCERTPINNING_EIDASBIND);
+ req.getJWSHeaderParam().add(eidasBindJoseHeader);
+
+ log.trace("Requesting SZR to sign bcBind datastructure ... ");
+ final SignContentResponseType resp = szr.signContent(req.isAppendCert(), req.getJWSHeaderParam(), req.getIn());
+ log.trace("Receive SZR response on bcBind siging operation ");
+
+ if (resp == null || resp.getOut() == null
+ || resp.getOut().isEmpty()
+ || StringUtils.isEmpty(resp.getOut().get(0).getValue())) {
+ throw new SzrCommunicationException("ernb.01", new Object[]{"BcBind response empty"});
+ }
+
+ return resp.getOut().get(0).getValue();
+
+ } catch (final JsonProcessingException | SZRException_Exception e) {
+ log.warn("SZR communication FAILED for operation: {} Reason: {}",
+ "SignContent", e.getMessage(), e);
+ throw new SzrCommunicationException("ernb.02",
+ new Object[]{e.getMessage()}, e);
+ }
+ }
+
+ private PersonInfoType generateSzrRequest(MatchedPersonResult matchedPersonData) {
+ log.trace("Starting connecting SZR Gateway");
+ final PersonInfoType personInfo = new PersonInfoType();
+ final PersonNameType personName = new PersonNameType();
+ final PhysicalPersonType naturalPerson = new PhysicalPersonType();
+ IdentificationType bpk = new IdentificationType();
+
+ naturalPerson.setName(personName);
+ personInfo.setPerson(naturalPerson);
+ naturalPerson.setIdentification(bpk);
+
+ // person information
+ personName.setFamilyName(matchedPersonData.getFamilyName());
+ personName.setGivenName(matchedPersonData.getGivenName());
+ naturalPerson.setDateOfBirth(matchedPersonData.getDateOfBirth());
+ bpk.setValue(matchedPersonData.getBpk());
+ bpk.setType(EaafConstants.URN_PREFIX_CDID + "ZP");
+
+ return personInfo;
+ }
+
+ private PersonInfoType generateSzrRequest(SimpleEidasData eidData) {
+ log.trace("Starting connecting SZR Gateway");
+ final PersonInfoType personInfo = new PersonInfoType();
+ final PersonNameType personName = new PersonNameType();
+ final PhysicalPersonType naturalPerson = new PhysicalPersonType();
+ final TravelDocumentType eDocument = new TravelDocumentType();
+
+ naturalPerson.setName(personName);
+ personInfo.setPerson(naturalPerson);
+ personInfo.setTravelDocument(eDocument);
+
+ // person information
+ personName.setFamilyName(eidData.getFamilyName());
+ personName.setGivenName(eidData.getGivenName());
+ naturalPerson.setDateOfBirth(eidData.getDateOfBirth());
+
+ //TODO: need to be updated to new eIDAS document interface!!!!
+ eDocument.setIssuingCountry(eidData.getCitizenCountryCode());
+ eDocument.setDocumentNumber(eidData.getPseudonym());
+
+ // eID document information
+ String documentType = basicConfig
+ .getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_EDOCUMENTTYPE,
+ Constants.SZR_CONSTANTS_DEFAULT_DOCUMENT_TYPE);
+ eDocument.setDocumentType(documentType);
+
+ // set PlaceOfBirth if available
+ if (eidData.getPlaceOfBirth() != null) {
+ log.trace("Find 'PlaceOfBirth' attribute: " + eidData.getPlaceOfBirth());
+ boolean setPlaceOfBirth = basicConfig
+ .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETPLACEOFBIRTHIFAVAILABLE, true);
+ if (setPlaceOfBirth) {
+ naturalPerson.setPlaceOfBirth(eidData.getPlaceOfBirth());
+ log.trace("Adding 'PlaceOfBirth' to ERnB request ... ");
+ }
+ }
+
+ // set BirthName if available
+ if (eidData.getBirthName() != null) {
+ log.trace("Find 'BirthName' attribute: " + eidData.getBirthName());
+ boolean setBirthName = basicConfig
+ .getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_PARAMS_SETBIRTHNAMEIFAVAILABLE, true);
+ if (setBirthName) {
+ final AlternativeNameType alternativeName = new AlternativeNameType();
+ naturalPerson.setAlternativeName(alternativeName);
+ alternativeName.setFamilyName(eidData.getBirthName());
+ log.trace("Adding 'BirthName' to ERnB request ... ");
+ }
+ }
+
+ return personInfo;
+ }
+
+ private IdentityLinkType getIdentityLinkGeneric(GetIdentityLinkEidas getIdl) throws Exception {
+ final JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
+ final Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ jaxbMarshaller.marshal(getIdl, outputStream);
+ outputStream.flush();
+
+ final Source source = new StreamSource(new ByteArrayInputStream(outputStream.toByteArray()));
+ outputStream.close();
+
+ log.trace("Requesting SZR ... ");
+ final Source response = dispatch.invoke(source);
+ log.trace("Receive RAW response from SZR");
+
+ final byte[] szrResponse = sourceToByteArray(response);
+ final GetIdentityLinkEidasResponse jaxbElement = (GetIdentityLinkEidasResponse) jaxbContext
+ .createUnmarshaller().unmarshal(new ByteArrayInputStream(szrResponse));
+
+ // build response
+ log.trace(new String(szrResponse, StandardCharsets.UTF_8));
+
+ // ok, we have success
+ final Document doc = DomUtils.parseDocument(
+ new ByteArrayInputStream(szrResponse),
+ true,
+ XmlNamespaceConstants.ALL_SCHEMA_LOCATIONS + " " + Constants.SZR_SCHEMA_LOCATIONS,
+ null, null);
+ final String xpathExpression = "//saml:Assertion";
+ final Element nsNode = doc.createElementNS("urn:oasis:names:tc:SAML:1.0:assertion", "saml:NSNode");
+
+ log.trace("Selecting signed doc " + xpathExpression);
+ final Element documentNode = (Element) XPathAPI.selectSingleNode(doc,
+ xpathExpression, nsNode);
+ log.trace("Signed document: " + DomUtils.serializeNode(documentNode));
+
+ final IdentityLinkType idl = new IdentityLinkType();
+ idl.setAssertion(documentNode);
+ idl.setPersonInfo(jaxbElement.getGetIdentityLinkReturn().getPersonInfo());
+
+ return idl;
+
+ }
+
+ @PostConstruct
+ private void initialize() throws EaafConfigurationException {
+ log.info("Starting SZR-Client initialization .... ");
+ final URL url = SzrClient.class.getResource("/wsdl/szr_client/SZR_v4.0.wsdl");
+
+ final boolean useTestSzr = basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_USETESTSERVICE,
+ true);
+
+ SzrService szrService;
+ QName qname;
+ String szrUrl;
+ if (useTestSzr) {
+ log.debug("Initializing SZR test environment configuration.");
+ qname = SzrService.SZRTestumgebung;
+ szrService = new SzrService(url, new QName("urn:SZRServices", "SZRService"));
+ szr = szrService.getSzrTestumgebung();
+ szrUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_TEST);
+
+ } else {
+ log.debug("Initializing SZR productive configuration.");
+ qname = SzrService.SZRProduktionsumgebung;
+ szrService = new SzrService(url, new QName("urn:SZRServices", "SZRService"));
+ szr = szrService.getSzrProduktionsumgebung();
+ szrUrl = basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_ENDPOINT_PROD);
+
+ }
+
+ // create raw client;
+ dispatch = szrService.createDispatch(qname, Source.class, javax.xml.ws.Service.Mode.PAYLOAD);
+
+ if (StringUtils.isEmpty(szrUrl)) {
+ log.error("No SZR service-URL found. SZR-Client initalisiation failed.");
+ throw new RuntimeException("No SZR service URL found. SZR-Client initalisiation failed.");
+
+ }
+
+ // check if Clients can be initialized
+ if (szr == null) {
+ log.error("SZR " + CLIENT_DEFAULT + " is 'NULL'. Something goes wrong");
+ throw new RuntimeException("SZR " + CLIENT_DEFAULT + " is 'NULL'. Something goes wrong");
+
+ }
+ if (dispatch == null) {
+ log.error("SZR " + CLIENT_RAW + " is 'NULL'. Something goes wrong");
+ throw new RuntimeException("SZR " + CLIENT_RAW + " is 'NULL'. Something goes wrong");
+
+ }
+
+ // inject handler
+ log.info("Use SZR service-URL: " + szrUrl);
+ injectBindingProvider((BindingProvider) szr, CLIENT_DEFAULT, szrUrl,
+ basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_TRACEMESSAGES, false));
+ injectBindingProvider(dispatch, CLIENT_RAW, szrUrl,
+ basicConfig.getBasicConfigurationBoolean(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_DEBUG_TRACEMESSAGES, false));
+
+ // inject http parameters and SSL context
+ log.debug("Inject HTTP client settings ... ");
+ HttpClientConfigBuilder httpClientBuilder = HttpClientConfig.builder()
+ .clientName("SZR Client")
+ .clientUrl(szrUrl)
+ .connectionTimeout(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_CONNECTION,
+ Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_CONNECTION))
+ .responseTimeout(basicConfig.getBasicConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_TIMEOUT_RESPONSE,
+ Constants.HTTP_CLIENT_DEFAULT_TIMEOUT_RESPONSE))
+ .keyStoreConfig(buildKeyStoreConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_TYPE,
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PATH,
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_PASSWORD,
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYSTORE_NAME,
+ "SZR SSL Client-Authentication KeyStore"))
+ .keyAlias(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEYS_ALIAS))
+ .keyPassword(basicConfig.getBasicConfiguration(Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_KEY_PASSWORD))
+ .trustAll(false)
+ .trustStoreConfig(buildKeyStoreConfiguration(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_TYPE,
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PATH,
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_PASSWORD,
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SSL_TRUSTSTORE_NAME,
+ "SZR SSL Client-Authentication KeyStore"));
+
+ injectHttpClient(szr, httpClientBuilder.clientType(CLIENT_DEFAULT).build());
+ injectHttpClient(dispatch, httpClientBuilder.clientType(CLIENT_RAW).build());
+
+ log.info("SZR-Client initialization successfull");
+ }
+
+ private void injectMdsIfAvailableAndActive(Map<String, Object> eidsaBindMap, SimpleEidasData eidData) {
+ if (basicConfig.getBasicConfigurationBoolean(
+ Constants.CONIG_PROPS_EIDAS_SZRCLIENT_SET_MDS_TO_EIDASBIND, false)) {
+ log.info("Injecting MDS into eidasBind ... ");
+ final Map<String, Object> mds = new HashMap<>();
+ mds.put(PvpAttributeDefinitions.PRINCIPAL_NAME_NAME, eidData.getFamilyName());
+ mds.put(PvpAttributeDefinitions.GIVEN_NAME_NAME, eidData.getGivenName());
+ mds.put(PvpAttributeDefinitions.BIRTHDATE_NAME, eidData.getDateOfBirth());
+ eidsaBindMap.put(ATTR_NAME_MDS, mds);
+
+ }
+ }
+
+ private byte[] sourceToByteArray(Source result) throws TransformerException {
+ final TransformerFactory factory = TransformerFactory.newInstance();
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ final Transformer transformer = factory.newTransformer();
+ transformer.setOutputProperty("omit-xml-declaration", "yes");
+ transformer.setOutputProperty("method", "xml");
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ final StreamResult streamResult = new StreamResult();
+ streamResult.setOutputStream(out);
+ transformer.transform(result, streamResult);
+ return out.toByteArray();
+ }
+
+}