diff --git a/src/main/java/de/ozgcloud/xta/client/XtaClient.java b/src/main/java/de/ozgcloud/xta/client/XtaClient.java index feb624291095450b208c27e9e786673167e9754a..214c195b1c44a6657ec496f6ef4f8eb0593bafa2 100644 --- a/src/main/java/de/ozgcloud/xta/client/XtaClient.java +++ b/src/main/java/de/ozgcloud/xta/client/XtaClient.java @@ -2,17 +2,35 @@ package de.ozgcloud.xta.client; import org.apache.commons.lang3.NotImplementedException; +import de.ozgcloud.xta.client.config.XtaClientConfig; +import de.ozgcloud.xta.client.core.MsgBoxServiceClient; +import de.ozgcloud.xta.client.exception.ClientInitializationException; import de.ozgcloud.xta.client.model.XtaMessage; import de.ozgcloud.xta.client.model.XtaMessageId; import de.ozgcloud.xta.client.model.XtaMessageMetaDatasAndHeader; public class XtaClient { - public XtaMessageMetaDatasAndHeader getMessagesMetadata(String selfIdentifier) { + private MsgBoxServiceClient msgBoxServiceClient; + + public XtaClient(final XtaClientConfig config) throws ClientInitializationException { + // MsgPort initialisieren + if (config.getMsgBoxServiceUrl() != null) { + msgBoxServiceClient = MsgBoxServiceClient.builder(config.getMsgBoxServiceUrl()) + .setClientCertKeystore(config.getClientCertKeystore()) + .setTrustCertKeystore(config.getTrustCertKeystore()) + .setHttpProxy(config.getHttpProxy()).setSoapRequestLogging(config.isLogSoapRequest()) + .setSoapResponseLogging(config.isLogSoapResponse()).setValidation(config.isValidation()) + .setHttpClientPolicy(config.getHttpClientPolicy()) + .build(); + } + } + + public XtaMessageMetaDatasAndHeader getMessagesMetadata(String xtaIdentifier) { throw new NotImplementedException(""); } - public XtaMessageMetaDatasAndHeader getNextMessagesMetadata(String selfIdentifier, String msgBoxRequestId) { + public XtaMessageMetaDatasAndHeader getNextMessagesMetadata(String xtaIdentifier, String msgBoxRequestId) { throw new NotImplementedException(""); } diff --git a/src/main/java/de/ozgcloud/xta/client/codes/BusinessScenario.java b/src/main/java/de/ozgcloud/xta/client/codes/BusinessScenario.java new file mode 100644 index 0000000000000000000000000000000000000000..46bd4247bceaab4aa30f1b1a394e078d729cf110 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/codes/BusinessScenario.java @@ -0,0 +1,76 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.codes; + +import lombok.Getter; + +/** + * Einige vordefinierte Werte für "business.scenario" (Fachkontext/Verfahren). Werte die nicht auftauchen können über den + * Stringsetter gesetzt werden. + * + * @see <a href="https://www.xrepository.de/details/urn:de:xta:codeliste:business.scenario">business.scenario</a> + */ +@Getter +public enum BusinessScenario { + + /** + * Fachkontext XBAULEITPLANUNG. + */ + XBAULEITPLANUNG_DATA("XBAULEITPLANUNG_DATA"), + + /** + * Fachkontext XDOMEAREG. + */ + XDOMEAREG_DATA("XDOMEAREG_DATA"), + + /** + * Fachkontext XInneres. + */ + XINNERES_DATA("XINNERES_DATA"), + + /** + * Fachkontext XAusländer. + */ + XAUSLAENDER_DATA("XAUSLAENDER_DATA"), + + /** + * Fachkontext OSCI-XMeld. + */ + XMELD_DATA("XMELD_DATA"), + + /** + * Fachkontext XPersonenstand. + */ + XPERSONENSTAND_DATA("XPERSONENSTAND_DATA"), + + /** + * Fachkontext XhD. + */ + XHD_DATA("XHD_DATA"), + + /** + * Fachkontext XGewerbeanzeige. + */ + GEWERBE_DATA("GEWERBE_DATA"); + + private String code; + + BusinessScenario(String code) { + this.code = code; + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/codes/IdentifierType.java b/src/main/java/de/ozgcloud/xta/client/codes/IdentifierType.java new file mode 100644 index 0000000000000000000000000000000000000000..7b80214807430ef96ed0af1f915e38a247c8e716 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/codes/IdentifierType.java @@ -0,0 +1,48 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.codes; + +import lombok.Getter; + +/** + * Einige vordefinierte Werte für "type.of.party.identifier". Werte die nicht auftauchen können über den Stringsetter gestzt werden * {@link + * Identifier (final String, String)} + * + * @see <a href"https://www.xrepository.de/details/urn:de:xta:codeliste:type.of.party.identifier">type.of.party.identifier</a> + */ +@Getter +public enum IdentifierType { + + /** + * XÖV-DVDV-Infrastruktur: Identifizierungsschema gemäß DVDV-Behördenschlüssel Nach den Regeln dieses Identifizierungsschemas + * ist z.B. die Kennung "psw:01002110" aufgebaut. + */ + XOEV("xoev"), + + /** + * SAFE-Infrastruktur des Justizressorts: Identifizierungsschema gemäß SAFE Nach den Regeln dieses Identifizierungsschemas ist + * z.B. die Kennung "safe-1363359638330-001060793" aufgebaut. + */ + JUSTIZ("justiz"); + + private String code; + + IdentifierType(String code) { + this.code = code; + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/config/HttpClientPolicy.java b/src/main/java/de/ozgcloud/xta/client/config/HttpClientPolicy.java new file mode 100644 index 0000000000000000000000000000000000000000..661f99ddbe3517ed022abd293b3c7772266c3884 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/config/HttpClientPolicy.java @@ -0,0 +1,36 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.config; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +/** + * Model-Klasse für eine HttpClientPolicy + */ +@Getter +@Builder +@ToString +public class HttpClientPolicy { + + private Integer connectionTimeout; + private Boolean allowChunking; + private Integer receiveTimeOut; + +} diff --git a/src/main/java/de/ozgcloud/xta/client/config/HttpProxy.java b/src/main/java/de/ozgcloud/xta/client/config/HttpProxy.java new file mode 100644 index 0000000000000000000000000000000000000000..c4fb5141150efc32287089aec46585ffd69aba2d --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/config/HttpProxy.java @@ -0,0 +1,36 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.config; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +/** + * Model-Klasse für einen HttpProxy + */ +@Getter +@Builder +@ToString(exclude = {"username", "password"}) +public class HttpProxy { + + private String host; + private Integer port; + private String username; + private String password; +} diff --git a/src/main/java/de/ozgcloud/xta/client/config/Keystore.java b/src/main/java/de/ozgcloud/xta/client/config/Keystore.java new file mode 100644 index 0000000000000000000000000000000000000000..4bb2aa66ec21f58eec3a02afa9eb0882964719b0 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/config/Keystore.java @@ -0,0 +1,35 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.config; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +/** + * Model-Klasse für einen Keystore + */ +@Builder +@Getter +@ToString(exclude = {"password"}) +public class Keystore { + + private String path; + private String password; + +} diff --git a/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java b/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..846e6630f5cb263a853a984e778ac63b01e84556 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/config/XtaClientConfig.java @@ -0,0 +1,130 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.config; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import de.ozgcloud.xta.client.exception.ClientException; +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import de.ozgcloud.xta.client.model.Identifier; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +/** + * Config-Holder for the Xta-Client. + */ +@Getter +@RequiredArgsConstructor +@Setter(value = AccessLevel.PROTECTED) +public class XtaClientConfig { + + private List<Identifier> clientIdentifiers; + + private URL managementServiceUrl; + private URL sendServiceUrl; + private URL msgBoxServiceUrl; + private HttpClientPolicy httpClientPolicy; + private HttpProxy httpProxy; + private Keystore clientCertKeystore; + private Keystore trustCertKeystore; + + private boolean validation; + private boolean logSoapRequest; + private boolean logSoapResponse; + + + public static class XtaClientConfigBuilder { + + private XtaClientConfig config = new XtaClientConfig(); + + public XtaClientConfigBuilder withValidation() { + config.setValidation(true); + return this; + } + + public XtaClientConfigBuilder withSoapLogging() { + config.setLogSoapRequest(true); + config.setLogSoapResponse(true); + return this; + } + + public XtaClientConfigBuilder withHttpClientPolicy(final HttpClientPolicy policy) { + config.setHttpClientPolicy(policy); + return this; + } + + public XtaClientConfigBuilder withHttpProxy(final HttpProxy proxy) { + config.setHttpProxy(proxy); + return this; + } + + public XtaClientConfig build() { + return this.config; + } + + } + + public static XtaClientConfigBuilder create(final URL manangementServiceUrl, final URL sendServiceUrl, + final URL msgBoxServiceUrl, final List<Identifier> clientIdentifiers, final String clientCertKeystore, + final String clientCertKeyStorePassword, final String trustCertKeystore, final String trustCertKeyStorePassword) { + + final XtaClientConfigBuilder builder = new XtaClientConfigBuilder(); + + builder.config.setMsgBoxServiceUrl(msgBoxServiceUrl); + builder.config.setManagementServiceUrl(manangementServiceUrl); + builder.config.setSendServiceUrl(sendServiceUrl); + builder.config.setClientIdentifiers(clientIdentifiers); + builder.config + .setClientCertKeystore(Keystore.builder().path(clientCertKeystore).password(clientCertKeyStorePassword).build()); + builder.config.setTrustCertKeystore(Keystore.builder().path(trustCertKeystore).password(trustCertKeyStorePassword).build()); + + return builder; + } + + public static XtaClientConfigBuilder create(final XtaClientSettings settings) throws ClientException { + return create(List.of(Identifier.from(settings)), settings); + } + + public static XtaClientConfigBuilder create(final List<Identifier> clientIdentifiers, final XtaClientSettings settings) throws ClientException { + try { + // Endpoint-URLs + final URL manangementServiceUrl = URI.create(settings.get(XtaClientSettings.BROKER_MANAGEMENT_SERVICE_ENDPONIT)).toURL(); + final URL sendServiceUrl = URI.create(settings.get(XtaClientSettings.BROKER_SEND_SERVICE_ENDPOINT)).toURL(); + final URL msgBoxServiceUrl = URI.create(settings.get(XtaClientSettings.BROKER_MSGBOX_SERVICE_ENDPOINT)).toURL(); + + // Clientcert + final String clientCertKeystore = settings.get(XtaClientSettings.CLIENT_KEYSTORE_CERT_PATH); + final String clientCertKeyStorePassword = settings.get(XtaClientSettings.CLIENT_KEYSTORE_CERT_PASSPHRASE); + + // Servercert + final String trustCertKeystore = settings.get(XtaClientSettings.BROKER_KEYSTORE_TRUSTCERT_PATH); + final String trustCertKeyStorePassword = settings.get(XtaClientSettings.BROKER_KEYSTORE_TRUSTCERT_PASSPHRASE); + + return create(manangementServiceUrl, sendServiceUrl, msgBoxServiceUrl, clientIdentifiers, clientCertKeystore, + clientCertKeyStorePassword, trustCertKeystore, trustCertKeyStorePassword); + + } catch (MalformedURLException e) { + throw new ClientInitializationException("Some URLs could not be parsed: " + e.getMessage(), e); + } + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/config/XtaClientSettings.java b/src/main/java/de/ozgcloud/xta/client/config/XtaClientSettings.java new file mode 100644 index 0000000000000000000000000000000000000000..159dd0d47a3a956d89e845eac07e1caf6d871351 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/config/XtaClientSettings.java @@ -0,0 +1,62 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.config; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; + +/** + * Klasse zum Laden der Settings über eine Propertie-Datei. + */ +public final class XtaClientSettings { + + public final static String BROKER_MANAGEMENT_SERVICE_ENDPONIT = "broker.manangement-service.endpoint"; + public final static String BROKER_SEND_SERVICE_ENDPOINT = "broker.send-service.endpoint"; + public final static String BROKER_MSGBOX_SERVICE_ENDPOINT = "broker.msgbox-service.endpoint"; + public final static String BROKER_KEYSTORE_TRUSTCERT_PATH = "broker.keystore.trustcert.path"; + public final static String BROKER_KEYSTORE_TRUSTCERT_PASSPHRASE = "broker.keystore.trustcert.passphrase"; + + public final static String CLIENT_KEYSTORE_CERT_PATH = "client.keystore.cert.path"; + public final static String CLIENT_KEYSTORE_CERT_PASSPHRASE = "client.keystore.cert.passphrase"; + + public final static String CLIENT_IDENTIFIER_ID_KEY = "client.identifier.id"; + public final static String CLIENT_IDENTIFIER_TYPE_KEY = "client.identifier.type"; + public final static String CLIENT_IDENTIFIER_CATEGORY_KEY = "client.identifier.category"; + public final static String CLIENT_IDENTIFIER_NAME_KEY = "client.identifier.name"; + + + private Properties props = new Properties(); + + public XtaClientSettings(final InputStream is) throws ClientInitializationException { + try { + props.load(is); + if (props.size() == 0) { + throw new ClientInitializationException("Properties sind nicht initialisiert."); + } + } catch (final IOException e) { + throw new ClientInitializationException("Properties konnten nicht geladen werden."); + } + } + + public String get(String key) { + return (String) props.get(key); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/EmptyNamespaceMessageOutInterceptor.java b/src/main/java/de/ozgcloud/xta/client/core/EmptyNamespaceMessageOutInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..40560e14a3740f1024a1589c282df55cbb8d552f --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/EmptyNamespaceMessageOutInterceptor.java @@ -0,0 +1,114 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor; +import org.apache.cxf.io.CachedOutputStream; +import org.apache.cxf.message.Message; +import org.apache.cxf.phase.AbstractPhaseInterceptor; +import org.apache.cxf.phase.Phase; + +import lombok.extern.slf4j.Slf4j; + +/** + * Klasse um leere Namespace-Angaben zu entfernen. + */ +@Slf4j +class EmptyNamespaceMessageOutInterceptor extends AbstractPhaseInterceptor<Message> { + + public EmptyNamespaceMessageOutInterceptor() { + super(Phase.PRE_STREAM); + addBefore(SoapPreProtocolOutInterceptor.class.getName()); + } + + public void handleMessage(Message message) { + + OutputStream os = message.getContent(OutputStream.class); + CachedStream cs = new CachedStream(); + message.setContent(OutputStream.class, cs); + message.getInterceptorChain().doIntercept(message); + + try { + cs.flush(); + closeQuietly(cs); + CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class); + + String currentEnvelopeMessage = IOUtils + .toString(csnew.getInputStream(), "UTF-8"); + + csnew.flush(); + closeQuietly(csnew); + + if (log.isDebugEnabled()) { + log.debug("Outbound message: " + currentEnvelopeMessage); + } + + String res = changeOutboundMessage(currentEnvelopeMessage); + if (res != null) { + if (log.isDebugEnabled()) { + log.debug("Outbound message has been changed: " + res); + } + } + res = res != null ? res : currentEnvelopeMessage; + + InputStream replaceInStream = IOUtils + .toInputStream(res, "UTF-8"); + + IOUtils.copy(replaceInStream, os); + replaceInStream.close(); + closeQuietly(replaceInStream); + + os.flush(); + message.setContent(OutputStream.class, os); + closeQuietly(os); + + } catch (IOException ioe) { + log.error("Unable to perform change.", ioe); + throw new RuntimeException(ioe); + } + } + + protected String changeOutboundMessage(String currentEnvelope) { + currentEnvelope = currentEnvelope.replace("xmlns=\"\"", ""); + return currentEnvelope; + } + + private static class CachedStream extends CachedOutputStream { + + public CachedStream() { + super(); + } + } + + // WA - closeQuietly aus IOUtils ist veraltet, daher hier eine eigene Iplementierung + private static void closeQuietly(final Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (final IOException ioe) { + // ignore + } + } +} \ No newline at end of file diff --git a/src/main/java/de/ozgcloud/xta/client/core/ManagementServiceClient.java b/src/main/java/de/ozgcloud/xta/client/core/ManagementServiceClient.java new file mode 100644 index 0000000000000000000000000000000000000000..0e7dea010ba5c6c655b59553982885de8a8785ca --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/ManagementServiceClient.java @@ -0,0 +1,79 @@ +/** + * XTA-Client Java Library Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import org.apache.cxf.ws.addressing.AttributedURIType; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import genv3.de.xoev.transport.xta.x211.CancelDeniedException; +import genv3.de.xoev.transport.xta.x211.InvalidMessageIDException; +import genv3.de.xoev.transport.xta.x211.LookupServiceRequest; +import genv3.de.xoev.transport.xta.x211.LookupServiceResponse; +import genv3.de.xoev.transport.xta.x211.ManagementPortType; +import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException; +import genv3.de.xoev.transport.xta.x211.PermissionDeniedException; +import genv3.de.xoev.transport.xta.x211.TransportReport; +import genv3.de.xoev.transport.xta.x211.XTAService; +import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException; +import genv3.eu.osci.ws.x2014.x10.transport.PartyType; +import lombok.extern.slf4j.Slf4j; + +/** + * gewrapte Serviceklasse für den ManagementServcice eines Brokers + */ +@Slf4j +public class ManagementServiceClient extends WsClient<ManagementPortType> { + + public static ManagementServiceClientBuilder builder(final URL serviceUrl) { + return new ManagementServiceClientBuilder(serviceUrl); + } + + public ManagementServiceClient(final WsClientConfig conf) throws ClientInitializationException { + this.clientConfiguration = conf; + ManagementServiceClient.log.info(VersionInfo.getInfo()); + ManagementServiceClient.log.info(this.clientConfiguration.toString()); + this.initializeService(); + } + + @Override + void initializePort(final URL url) { + final XTAService service = new XTAService(url); + port = service.getManagementPort(); + } + + public void checkAccountActive(final PartyType authorIdentifier) + throws PermissionDeniedException, XTAWSTechnicalProblemException { + port.checkAccountActive(authorIdentifier); + } + + public TransportReport getTransportReport(final AttributedURIType messageID, final PartyType authorIdentifier) + throws PermissionDeniedException, XTAWSTechnicalProblemException, InvalidMessageIDException { + return port.getTransportReport(messageID, authorIdentifier); + } + + public void cancelMessage(final AttributedURIType messageID, final PartyType authorIdentifier) + throws XTAWSTechnicalProblemException, PermissionDeniedException, CancelDeniedException, ParameterIsNotValidException { + port.cancelMessage(messageID, authorIdentifier); + } + + public LookupServiceResponse lookupService(final LookupServiceRequest lookupServiceRequest, final PartyType authorIdentifier) + throws ParameterIsNotValidException, PermissionDeniedException, XTAWSTechnicalProblemException { + return port.lookupService(lookupServiceRequest, authorIdentifier); + } + + public AttributedURIType createMessageId(final PartyType authorIdentifier) + throws PermissionDeniedException, XTAWSTechnicalProblemException { + return port.createMessageId(authorIdentifier); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/ManagementServiceClientBuilder.java b/src/main/java/de/ozgcloud/xta/client/core/ManagementServiceClientBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..6612aa8d03eab8da1d54d7f25766b461f2b6aee3 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/ManagementServiceClientBuilder.java @@ -0,0 +1,55 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Konstruiert eine Instanz des {@link WsClient}. + */ +@Getter(AccessLevel.PACKAGE) +@Slf4j +public class ManagementServiceClientBuilder extends ServiceBuilder<ManagementServiceClient> { + + /** + * Initialisiert einen {@link ServiceBuilder} mit ServiceUrl-Host und ServiceUrl-Port. + * + * @param serviceUrl URL des Endpoints + */ + ManagementServiceClientBuilder(final URL serviceUrl) { + super(serviceUrl); + } + + /** + * Erstellt eine Instanz vom Typ AnlieferungServiceClient + * + * @return ManagementServiceClient + * @throws ClientInitializationException {@link ClientInitializationException} + */ + + @Override + public ManagementServiceClient build() throws ClientInitializationException { + this.validateConfiguration(); + return new ManagementServiceClient(this.clientConfiguration); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/MsgBoxServiceClient.java b/src/main/java/de/ozgcloud/xta/client/core/MsgBoxServiceClient.java new file mode 100644 index 0000000000000000000000000000000000000000..4db3dbe9b77f06cdcf7ced04c2997e204fc4301a --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/MsgBoxServiceClient.java @@ -0,0 +1,86 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import jakarta.xml.ws.Holder; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import genv3.de.xoev.transport.xta.x211.*; +import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxCloseRequestType; +import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxFetchRequest; +import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxGetNextRequestType; +import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxResponseType; +import genv3.eu.osci.ws.x2008.x05.transport.MsgBoxStatusListRequestType; +import genv3.eu.osci.ws.x2008.x05.transport.MsgStatusListType; +import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData; +import genv3.eu.osci.ws.x2014.x10.transport.PartyType; +import lombok.extern.slf4j.Slf4j; + +/** + * gewrapte Serviceklasse für den MsgBoxServcice eines Brokers + */ +@Slf4j +public class MsgBoxServiceClient extends WsClient<MsgBoxPortType> { + + public static MsgBoxServiceClientBuilder builder(final URL serviceUrl) { + return new MsgBoxServiceClientBuilder(serviceUrl); + } + + public MsgBoxServiceClient(final WsClientConfig conf) throws ClientInitializationException { + + this.clientConfiguration = conf; + MsgBoxServiceClient.log.info(VersionInfo.getInfo()); + MsgBoxServiceClient.log.info(this.clientConfiguration.toString()); + this.initializeService(); + } + + @Override + void initializePort(final URL url) { + final XTAService service = new XTAService(url); + port = service.getMsgBoxPort(); + } + + public GenericContentContainer getMessage(final MsgBoxFetchRequest fetchRequest, final PartyType authorIdentifier, + final Holder<MessageMetaData> messageMetaData, final Holder<MsgBoxResponseType> fetchResponseHeader) + throws InvalidMessageIDException, PermissionDeniedException, XTAWSTechnicalProblemException { + return port.getMessage(fetchRequest, authorIdentifier, messageMetaData, fetchResponseHeader); + } + + public MsgStatusListType getStatusList(final MsgBoxStatusListRequestType fetchRequest, final PartyType authorIdentifier, + final Holder<MsgBoxResponseType> fetchResponseHeader) throws PermissionDeniedException, XTAWSTechnicalProblemException { + return port.getStatusList(fetchRequest, authorIdentifier, fetchResponseHeader); + } + + public GenericContentContainer getNextMessage(final MsgBoxGetNextRequestType fetchRequest, final PartyType authorIdentifier, + final Holder<MessageMetaData> messageMetaData, final Holder<MsgBoxResponseType> fetchResponseHeader) + throws InvalidMessageIDException, PermissionDeniedException, XTAWSTechnicalProblemException { + return port.getNextMessage(fetchRequest, authorIdentifier, messageMetaData, fetchResponseHeader); + } + + public MsgStatusListType getNextStatusList(final MsgBoxGetNextRequestType fetchRequest, final PartyType authorIdentifier, + final Holder<MsgBoxResponseType> fetchResponseHeader) throws PermissionDeniedException, XTAWSTechnicalProblemException { + return port.getNextStatusList(fetchRequest, authorIdentifier, fetchResponseHeader); + } + + public void close(final MsgBoxCloseRequestType fetchRequest, final PartyType authorIdentifier) + throws InvalidMessageIDException, PermissionDeniedException, XTAWSTechnicalProblemException { + port.close(fetchRequest, authorIdentifier); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/MsgBoxServiceClientBuilder.java b/src/main/java/de/ozgcloud/xta/client/core/MsgBoxServiceClientBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..bc4641461fc389a687b7fc25f8782e1999810b7c --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/MsgBoxServiceClientBuilder.java @@ -0,0 +1,54 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Konstruiert eine Instanz des {@link WsClient}. + */ +@Getter(AccessLevel.PACKAGE) +@Slf4j +public class MsgBoxServiceClientBuilder extends ServiceBuilder<MsgBoxServiceClient> { + + /** + * Initialisiert einen {@link ServiceBuilder} mit ServiceUrl-Host und ServiceUrl-Port. + * + * @param serviceUrl URL des Endpoints + */ + MsgBoxServiceClientBuilder(final URL serviceUrl) { + super(serviceUrl); + } + + /** + * Erstellt eine Instanz vom Typ AnlieferungServiceClient + * + * @return ManagementServiceClient + * @throws ClientInitializationException {@link ClientInitializationException} + */ + @Override + public MsgBoxServiceClient build() throws ClientInitializationException { + this.validateConfiguration(); + return new MsgBoxServiceClient(this.clientConfiguration); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/SendServiceClient.java b/src/main/java/de/ozgcloud/xta/client/core/SendServiceClient.java new file mode 100644 index 0000000000000000000000000000000000000000..c5c182561aff63a61c317f32d69744a4ad9e0ce5 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/SendServiceClient.java @@ -0,0 +1,73 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import jakarta.xml.ws.Holder; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import genv3.de.xoev.transport.xta.x211.GenericContentContainer; +import genv3.de.xoev.transport.xta.x211.MessageSchemaViolationException; +import genv3.de.xoev.transport.xta.x211.MessageVirusDetectionException; +import genv3.de.xoev.transport.xta.x211.ParameterIsNotValidException; +import genv3.de.xoev.transport.xta.x211.PermissionDeniedException; +import genv3.de.xoev.transport.xta.x211.SendPortType; +import genv3.de.xoev.transport.xta.x211.SyncAsyncException; +import genv3.de.xoev.transport.xta.x211.XTAService; +import genv3.de.xoev.transport.xta.x211.XTAWSTechnicalProblemException; +import genv3.eu.osci.ws.x2008.x05.transport.X509TokenContainerType; +import genv3.eu.osci.ws.x2014.x10.transport.MessageMetaData; +import lombok.extern.slf4j.Slf4j; + +/** + * gewrapte Serviceklasse für den SendServcice eines Brokers + */ +@Slf4j +public class SendServiceClient extends WsClient<SendPortType> { + + public static SendServiceClientBuilder builder(final URL serviceUrl) { + return new SendServiceClientBuilder(serviceUrl); + } + + public SendServiceClient(final WsClientConfig conf) throws ClientInitializationException { + this.clientConfiguration = conf; + SendServiceClient.log.info(VersionInfo.getInfo()); + SendServiceClient.log.info(this.clientConfiguration.toString()); + this.initializeService(); + } + + @Override + void initializePort(final URL url) { + final XTAService service = new XTAService(url); + port = service.getSendXtaPort(); + } + + public void sendMessage(final GenericContentContainer genericContainer, final MessageMetaData messageMetaData, + final X509TokenContainerType x509TokenContainer) + throws PermissionDeniedException, XTAWSTechnicalProblemException, MessageSchemaViolationException, MessageVirusDetectionException, + ParameterIsNotValidException, SyncAsyncException { + port.sendMessage(genericContainer, messageMetaData, x509TokenContainer); + } + + public void sendMessageSync(final Holder<GenericContentContainer> genericContainer, + final Holder<MessageMetaData> messageMetaData, final Holder<X509TokenContainerType> x509TokenContainer) + throws PermissionDeniedException, XTAWSTechnicalProblemException, MessageSchemaViolationException, MessageVirusDetectionException, ParameterIsNotValidException, SyncAsyncException { + port.sendMessageSync(genericContainer, messageMetaData, x509TokenContainer); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/SendServiceClientBuilder.java b/src/main/java/de/ozgcloud/xta/client/core/SendServiceClientBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..8de3e05e60df87722b1f3919803203e8f461183d --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/SendServiceClientBuilder.java @@ -0,0 +1,55 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Konstruiert eine Instanz des {@link WsClient}. + */ +@Getter(AccessLevel.PACKAGE) +@Slf4j +public class SendServiceClientBuilder extends ServiceBuilder<SendServiceClient> { + + /** + * Initialisiert einen {@link ServiceBuilder} mit ServiceUrl-Host und ServiceUrl-Port. + * + * @param serviceUrl URL des Endpoints + */ + SendServiceClientBuilder(final URL serviceUrl) { + super(serviceUrl); + } + + /** + * Erstellt eine Instanz vom Typ AnlieferungServiceClient + * + * @return ManagementServiceClient + * @throws ClientInitializationException {@link ClientInitializationException} + */ + + @Override + public SendServiceClient build() throws ClientInitializationException { + this.validateConfiguration(); + return new SendServiceClient(this.clientConfiguration); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/ServiceBuilder.java b/src/main/java/de/ozgcloud/xta/client/core/ServiceBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..aa9efc3efaf215c58008884ea87502f0b6e31a5f --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/ServiceBuilder.java @@ -0,0 +1,176 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; + +import de.ozgcloud.xta.client.config.HttpClientPolicy; +import de.ozgcloud.xta.client.config.HttpProxy; +import de.ozgcloud.xta.client.config.Keystore; +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Konstruiert eine Instanz des {@link WsClient}. + */ +@Getter(AccessLevel.PACKAGE) +@Slf4j +public abstract class ServiceBuilder<T extends WsClient> { + + @Getter(AccessLevel.NONE) + final WsClientConfig clientConfiguration; + + /** + * Initialisiert einen {@link ServiceBuilder} mit ServiceUrl-Host und ServiceUrl-Port. + * + * @param serviceUrl URL des Endpoints + */ + ServiceBuilder(final URL serviceUrl) { + this.clientConfiguration = new WsClientConfig(); + this.clientConfiguration.setServiceUrl(serviceUrl); + } + + /** + * Sezt Trust-Keystore des {@link WsClient}s. + * + * @param keystore Trust-Keystore + * @return {@link ServiceBuilder} + */ + public ServiceBuilder<T> setTrustCertKeystore(final Keystore keystore) { + this.clientConfiguration.setTrustCertKeystore(keystore); + return this; + } + + /** + * Setzt den Client-Keystore des {@link WsClient}s. + * + * @param keystore Client-Keystore + * @return {@link ServiceBuilder} + */ + public ServiceBuilder<T> setClientCertKeystore(final Keystore keystore) { + this.clientConfiguration.setClientCertKeystore(keystore); + return this; + } + + /** + * Setzt den Proxy Host. + * + * @param proxy Proxy Host + * @return {@link ServiceBuilder} + */ + public ServiceBuilder<T> setHttpProxy(final HttpProxy proxy) { + this.clientConfiguration.setHttpProxy(proxy); + return this; + } + + /** + * Setzt XSD Validation + * + * @return {@link ServiceBuilder} + */ + public ServiceBuilder<T> setValidation(final boolean validation) { + this.clientConfiguration.setValidation(validation); + return this; + } + + public ServiceBuilder<T> enableValidation() { + setValidation(true); + return this; + } + + public ServiceBuilder<T> enableSoapLogging() { + setSoapRequestLogging(true); + setSoapResponseLogging(true); + return this; + } + + /** + * Setzt SoapRequest Logging + * + * @return {@link ServiceBuilder} + */ + public ServiceBuilder<T> setSoapRequestLogging(final boolean logging) { + this.clientConfiguration.setLogSoapRequest(logging); + return this; + } + + /** + * Setzt SoapResponse Logging + * + * @return {@link ServiceBuilder} + */ + public ServiceBuilder<T> setSoapResponseLogging(final boolean logging) { + this.clientConfiguration.setLogSoapResponse(logging); + return this; + } + + /** + * Setzt eine HttpClient-Policy + * + * @param policy HttpClientPolicy + * @return {@link ServiceBuilder} + */ + + public ServiceBuilder<T> setHttpClientPolicy(final HttpClientPolicy policy) { + this.clientConfiguration.setHttpClientPolicy(policy); + return this; + } + + void validateConfiguration() { + final List<String> errorMsgs = Lists.newArrayList(); + ServiceBuilder.checkNotNull("Service-URL", this.clientConfiguration.getServiceUrl(), errorMsgs); + + // Entweder beide Angaben leer oder beide gesetzt + if (this.clientConfiguration.getHttpProxy() != null) { + if (this.clientConfiguration.getHttpProxy().getHost() == null ^ this.clientConfiguration.getHttpProxy().getPort() == 0) { + errorMsgs.add("Angaben zum Proxy (Host, Port) müssen vollständig gesetzt sein"); + } + } + + this.checkKeystoreFile("Client-Keystore", this.clientConfiguration.getClientCertKeystore(), errorMsgs); + this.checkKeystoreFile("Trust-Keystore", this.clientConfiguration.getTrustCertKeystore(), errorMsgs); + + if (errorMsgs != null && !errorMsgs.isEmpty()) { + throw new IllegalArgumentException(Joiner.on("\n").join(errorMsgs)); + } + } + + private static void checkNotNull(final String identifier, final Object value, final List<String> errorMsgs) { + if (value == null) { + errorMsgs.add(identifier + ": Wert muss gesetzt sein"); + } + } + + private void checkKeystoreFile(final String keyStoreIdentifier, final Keystore keyStore, + final List<String> errorMsgs) { + if (StringUtils.isEmpty(keyStore.getPath())) { + errorMsgs.add(keyStoreIdentifier + ": Pfad muss gesetzt sein"); + } + ServiceBuilder.checkNotNull(keyStoreIdentifier + " Passwort", keyStore.getPassword(), errorMsgs); + } + + public abstract T build() throws ClientInitializationException; +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/VersionInfo.java b/src/main/java/de/ozgcloud/xta/client/core/VersionInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..b7119928d09c35e9024fec89184a033e87f65741 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/VersionInfo.java @@ -0,0 +1,61 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * Klasse mit VersionInfo + */ +@Slf4j +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public final class VersionInfo { + + private static String build; + + private static String buildTimestamp; + + private static String version; + + public static String getInfo() { + return String.format("VersionInfo: version: %s, build: %s, timestamp: %s", VersionInfo.version, VersionInfo.build, + VersionInfo.buildTimestamp); + } + + static { + final Properties p = new Properties(); + try (final InputStream in = VersionInfo.class.getClassLoader().getResourceAsStream("version.properties")) { + + p.load(in); + + VersionInfo.build = p.getProperty("bamboo_buildNumber"); + VersionInfo.buildTimestamp = p.getProperty("build_creation_timestamp"); + VersionInfo.version = p.getProperty("project_version"); + + } catch (final IOException e) { + log.error(e.getMessage(), e); + throw new IllegalStateException("Can not initialize version information"); + } + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/WsClient.java b/src/main/java/de/ozgcloud/xta/client/core/WsClient.java new file mode 100644 index 0000000000000000000000000000000000000000..2b65bf499fe6f3bb9b0333e79e97e54f3482a62b --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/WsClient.java @@ -0,0 +1,266 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import jakarta.xml.ws.BindingProvider; + +import org.apache.cxf.common.util.StringUtils; +import org.apache.cxf.configuration.jsse.TLSClientParameters; +import org.apache.cxf.endpoint.Client; +import org.apache.cxf.ext.logging.LoggingInInterceptor; +import org.apache.cxf.ext.logging.LoggingOutInterceptor; +import org.apache.cxf.frontend.ClientProxy; +import org.apache.cxf.transport.http.HTTPConduit; +import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; + +import de.ozgcloud.xta.client.config.HttpClientPolicy; +import de.ozgcloud.xta.client.config.HttpProxy; +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import de.ozgcloud.xta.client.util.KeyStoreUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * Basisklasse für gewrapte Serviceklassen + */ +@Slf4j +abstract class WsClient<T> { + + WsClientConfig clientConfiguration; + + T port; + + abstract void initializePort(final URL url); + + void initializeService() throws ClientInitializationException { + + final String logMessage = + "JarInfo: " + this.getClass().getName() + ",\nConfiguration: " + this.clientConfiguration + "," + "\ninitializeService"; + + try { + final String serviceUrl = this.clientConfiguration.getServiceUrl().toString(); + WsClient.log.debug("Initialize Service {}", serviceUrl); + final URL url = this.getClass().getClassLoader().getResource("wsdl/XTA.wsdl"); + WsClient.log.debug("url: {}", url); + this.initializeServiceEndpoint(url); + this.initializeTransportSecurity(); + this.initializeHttpClientPolicy(); + this.initializeProxy(); + WsClient.log.info("{} sucessfully.", logMessage); + } catch (final Exception ex) { + WsClient.log.error("{} failed. Reason: {}", logMessage, ex.getMessage()); + throw new ClientInitializationException(ex.getMessage(), ex); + } + } + + private void initializeServiceEndpoint(final URL url) { + initializePort(url); + final BindingProvider bp = (BindingProvider) this.port; + + bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, this.clientConfiguration.getServiceUrl().toString()); + + WsClient.log.debug("Set EnpointUrl to: {}", this.clientConfiguration.getServiceUrl().toString()); + + // Empty xmlns="" entfernen -> XSD-Modellierung Annonymous Inner Type + // ClientProxy.getClient(port).getOutInterceptors().add(new EmptyNamespaceMessageOutInterceptor()); + + initializeValidation(); + + if (this.clientConfiguration.isLogSoapRequest()) { + LoggingOutInterceptor loi = new LoggingOutInterceptor(); + loi.setPrettyLogging(true); + ClientProxy.getClient(port).getOutInterceptors().add(loi); + WsClient.log.debug("Set SoapReqeust-Logging: {}", clientConfiguration.isLogSoapRequest()); + } + + if (this.clientConfiguration.isLogSoapResponse()) { + LoggingInInterceptor lii = new LoggingInInterceptor(); + lii.setPrettyLogging(true); + ClientProxy.getClient(port).getInInterceptors().add(lii); + WsClient.log.debug("Set SoapResponse-Logging: {}", clientConfiguration.isLogSoapResponse()); + } + } + + private void initializeHttpClientPolicy() { + final HttpClientPolicy policy = this.clientConfiguration.getHttpClientPolicy(); + if (policy != null) { + final Client client = ClientProxy.getClient(this.port); + final HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); + final HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); + if (policy.getConnectionTimeout() != null) { + httpClientPolicy.setConnectionTimeout(policy.getConnectionTimeout()); + } + if (policy.getAllowChunking() != null) { + httpClientPolicy.setAllowChunking(policy.getAllowChunking()); + } + if (policy.getReceiveTimeOut() != null) { + httpClientPolicy.setReceiveTimeout(policy.getReceiveTimeOut()); + } + httpConduit.setClient(httpClientPolicy); + WsClient.log.debug("Intitialize HttpClientPolicy"); + } + } + + private void initializeTransportSecurity() throws ClientInitializationException { + if (this.clientConfiguration.getClientCertKeystore() != null) { + final Client client = ClientProxy.getClient(this.port); + final HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); + final TLSClientParameters parameters = new TLSClientParameters(); + parameters.setSSLSocketFactory(this.createSSLContext().getSocketFactory()); + httpConduit.setTlsClientParameters(parameters); + WsClient.log.debug("Intitialize TransportSecurity"); + } + } + + private void initializeProxy() { + final HttpProxy proxy = this.clientConfiguration.getHttpProxy(); + if (proxy != null) { + final Client client = ClientProxy.getClient(this.port); + final HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); + if (!StringUtils.isEmpty(proxy.getHost())) { + httpConduit.getClient().setProxyServer(proxy.getHost()); + } + if (proxy.getPort() != null) { + httpConduit.getClient().setProxyServerPort(proxy.getPort()); + } + if (!StringUtils.isEmpty(proxy.getUsername())) { + httpConduit.getProxyAuthorization().setUserName(proxy.getUsername()); + } + if (!StringUtils.isEmpty(proxy.getPassword())) { + httpConduit.getProxyAuthorization().setPassword(proxy.getPassword()); + } + WsClient.log.debug("Intitialize Proxy"); + } + } + + private SSLContext createSSLContext() throws ClientInitializationException { + try { + + // Server + final KeyStore trustStore = KeyStoreUtil + .load(this.clientConfiguration.getTrustCertKeystore().getPath(), + this.clientConfiguration.getTrustCertKeystore().getPassword()); + + // client + final KeyStore keyStore = KeyStoreUtil + .load(this.clientConfiguration.getClientCertKeystore().getPath(), + this.clientConfiguration.getClientCertKeystore().getPassword()); + + //Client-Lib Truststore + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(trustStore); + + //Default JDK Truststore + final TrustManagerFactory defaultTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + defaultTmf.init((KeyStore) null); + + //Client-Lib-Keystore + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + kmf.init(keyStore, this.clientConfiguration.getClientCertKeystore().getPassword().toCharArray()); + + final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + + CustomTruststoreManager customTruststoreManager = new CustomTruststoreManager(getX509TrustMananger(defaultTmf), + getX509TrustMananger(tmf)); + + sslContext.init(kmf.getKeyManagers(), new TrustManager[]{customTruststoreManager}, new SecureRandom()); + + return sslContext; + } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { + throw new ClientInitializationException("Exception in createSSLContext: " + e.getMessage(), e); + } + } + + private X509TrustManager getX509TrustMananger(TrustManagerFactory tmf) { + for (TrustManager tm : tmf.getTrustManagers()) { + if (tm instanceof X509TrustManager) { + return (X509TrustManager) tm; + } + } + + return null; + } + + public void enableValidation() { + clientConfiguration.setValidation(true); + initializeValidation(); + } + + public void disableValidation() { + clientConfiguration.setValidation(false); + initializeValidation(); + } + + private void initializeValidation() { + final BindingProvider bp = (BindingProvider) this.port; + + if (this.clientConfiguration.isValidation()) { + bp.getRequestContext().put("schema-validation-enabled", true); + } else { + bp.getRequestContext().put("schema-validation-enabled", false); + } + + WsClient.log.debug("Set Enpoint-Validation: {}", clientConfiguration.isValidation()); + } + + @RequiredArgsConstructor + private class CustomTruststoreManager implements X509TrustManager { + + final X509TrustManager defaultTm; + final X509TrustManager myTm; + + @Override + public X509Certificate[] getAcceptedIssuers() { + // If you're planning to use client-cert auth, + // merge results from "defaultTm" and "myTm". + return defaultTm.getAcceptedIssuers(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + myTm.checkServerTrusted(chain, authType); + } catch (CertificateException e) { + defaultTm.checkServerTrusted(chain, authType); + } + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // If you're planning to use client-cert auth, + // do the same as checking the server. + defaultTm.checkClientTrusted(chain, authType); + } + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/core/WsClientConfig.java b/src/main/java/de/ozgcloud/xta/client/core/WsClientConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..cb4666402c271bc98bccbf7c2820478fa5547853 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/core/WsClientConfig.java @@ -0,0 +1,49 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.core; + +import java.net.URL; + +import de.ozgcloud.xta.client.config.HttpClientPolicy; +import de.ozgcloud.xta.client.config.HttpProxy; +import de.ozgcloud.xta.client.config.Keystore; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * Konfigurationsparameter für den {@link WsClient}. + */ + +@Setter(AccessLevel.PACKAGE) +@Getter(AccessLevel.PACKAGE) +@ToString +class WsClientConfig { + + private URL serviceUrl; + private Keystore clientCertKeystore; + private Keystore trustCertKeystore; + private HttpProxy httpProxy; + private HttpClientPolicy httpClientPolicy; + + private boolean validation = false; + private boolean logSoapRequest = false; + private boolean logSoapResponse = false; + +} diff --git a/src/main/java/de/ozgcloud/xta/client/exception/ClientException.java b/src/main/java/de/ozgcloud/xta/client/exception/ClientException.java new file mode 100644 index 0000000000000000000000000000000000000000..0b898337a04b230eb57d217e42f025a854de6eda --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/exception/ClientException.java @@ -0,0 +1,33 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.exception; + + +/** + * Allgemeiner Fehler zum signalisieren von clientseitigen Problemen. + */ +public class ClientException extends Exception { + + public ClientException(final String message, final Throwable cause) { + super(message, cause); + } + + public ClientException(final String message) { + super(message); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/exception/ClientInitializationException.java b/src/main/java/de/ozgcloud/xta/client/exception/ClientInitializationException.java new file mode 100644 index 0000000000000000000000000000000000000000..5a1b2a792bf7e5f7ba5c823ec790facbf0dca490 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/exception/ClientInitializationException.java @@ -0,0 +1,34 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.exception; + +/** + * Spezieller Fehler zum signalisieren von clientseitigen Problemen während der Initialisierung. + * + * @author hmaterny + */ +public class ClientInitializationException extends ClientException { + + public ClientInitializationException(final String message, final Throwable cause) { + super(message, cause); + } + + public ClientInitializationException(final String message) { + super(message); + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/model/Identifier.java b/src/main/java/de/ozgcloud/xta/client/model/Identifier.java new file mode 100644 index 0000000000000000000000000000000000000000..0f10654f94f3ab8e0a32308cf15fd9ea1b45b317 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/model/Identifier.java @@ -0,0 +1,130 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.model; + +import org.apache.commons.lang3.StringUtils; + +import de.ozgcloud.xta.client.codes.IdentifierType; +import de.ozgcloud.xta.client.config.XtaClientSettings; +import de.ozgcloud.xta.client.exception.ClientException; +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * Modelklasse, repräsentiert einen Kommunikationspartner, bestehend aus Kennung, Typ, Kategorie (optinal) und einen + * benutzerfreundlichen Namen (optional). Diese Klasse definiert nicht die (technische) Rolle des Partners wie Leser oder Autor, + * bzw. Sender oder Empfänger, sondern kann für beides stehen. + */ +@Getter +@NoArgsConstructor(access = AccessLevel.PUBLIC) +public class Identifier { + + // Pflichtfeld: die Kennung, üblich <Prefix>:<Kennung> + private String id; + + // Pflichtfeld: Typ der Kennung, z.B.: XOEV oder JUSTIZ + private String type; + + // Optional: benutzerfreundlicher Name, "Anzeigename" + private String name; + + // Optional: Konkretesiert die fachliche Rolle eines Partners genauer (e.g. "buyer", "Meldehörde", "Standesamt"...) + private String category; + + /** + * Erzeugen eines Identifier mit seinen minimalen Pflichtfeldern. + * + * @param id die ("technische") Kennung des Kommunikationspartners, zb. xdo:11009991 + * @param type Typ des Kommunikationspartners, zb. XOEV + */ + public Identifier(final String id, String type) throws ClientInitializationException { + this.id = id; + this.type = type; + + assertIsValid(this, "Constructor"); + } + + /** + * Erzeugen eines Identifier mit seinen minimalen Pflichtfeldern. + * + * @param id die ("technische") Kennung des Kommunikationspartners, zb. xdo:11009991 + * @param type Typ des Kommunikationspartners, zb. XOEV, {@link IdentifierType} + */ + public Identifier(final String id, IdentifierType type) throws ClientInitializationException { + this(id, type.getCode()); + } + + /** + * Statische Fabrik-Methode zum Erzeugen einer Identifier-Instanz aus den Einstellungen (settings.properties). Typischerweise + * ist dies die Identität des XtaClients selbst. + * + * @return eine Identifier-Instanz gefüllt mit den Daten der Einstellungen. + * @throws ClientException wenn die erzeugte Instans nicht valide ist oder es probleme mit dem Settingfile gibt (IO) + */ + public static Identifier from(final XtaClientSettings settings) throws ClientException { + Identifier target = new Identifier(); + target.id = settings.get(XtaClientSettings.CLIENT_IDENTIFIER_ID_KEY); + target.type = settings.get(XtaClientSettings.CLIENT_IDENTIFIER_TYPE_KEY); + target.category = settings.get(XtaClientSettings.CLIENT_IDENTIFIER_CATEGORY_KEY); + target.name = settings.get(XtaClientSettings.CLIENT_IDENTIFIER_NAME_KEY); + + assertIsValid(target, "Settings"); + return target; + } + + /** + * Mit einem optionalen "Nutzerfreundlichen", zb. "Heiko Materny" + * + * @param name der Name + * @return Identifier-Instanz ("sich selbst"") gefüllt mit dem Namen. + */ + public Identifier withUserFriendlyName(String name) { + this.name = name; + return this; + } + + /** + * Mit einer optionalen Kategorie, zb. "Standesamt" + * + * @param category die Kategorie, e.g. Standesamt + * @return Identifier-Instanz ("sich selbst"") gefüllt mit der Kategorie. + */ + public Identifier withCategory(String category) { + this.name = category; + return this; + } + + private static void assertIsValid(Identifier toCheck, String errMsg) throws ClientInitializationException { + if (StringUtils.isEmpty(toCheck.id)) { + throw new ClientInitializationException("construction from " + errMsg + " failed, reason: id is empty"); + } + + if (StringUtils.isEmpty(toCheck.type)) { + throw new ClientInitializationException("construction from " + errMsg + " failed, reason: type is empty"); + } + } + + /** + * Enum zur Auswahl der Kommunikationsrolle (spielt nur eine Rolle wenn der innere Nachrichtenkopf verarbeitet wird.) + */ + public enum CommunicationRole { + AUTHOR, READER, REPLYTO + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/util/FileUtil.java b/src/main/java/de/ozgcloud/xta/client/util/FileUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..e9b35d123fc0062534f74ecc1dc8dff7817b24af --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/util/FileUtil.java @@ -0,0 +1,43 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * Utility-Klasse für File-Operationen + */ +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") +@NoArgsConstructor(access = AccessLevel.NONE) +public final class FileUtil { + + public static InputStream loadByName(String name) throws IOException { + final File f = new File(name); + if (f.isFile()) { + return new FileInputStream(f); + } else { + return FileUtil.class.getClassLoader().getResourceAsStream(name); + } + } +} diff --git a/src/main/java/de/ozgcloud/xta/client/util/KeyStoreUtil.java b/src/main/java/de/ozgcloud/xta/client/util/KeyStoreUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..88396b0d3490967590b418bb21a2a04b7f171b63 --- /dev/null +++ b/src/main/java/de/ozgcloud/xta/client/util/KeyStoreUtil.java @@ -0,0 +1,97 @@ +/** + * XTA-Client Java Library + * Copyright (C) 2021 Koordinierungsstelle für IT-Standards (KoSIT) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ +package de.ozgcloud.xta.client.util; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.HashMap; +import java.util.Map; + +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; + +import org.apache.commons.lang3.StringUtils; + +import de.ozgcloud.xta.client.exception.ClientInitializationException; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** + * Hilfsklasse für KeyStore-Handling. + */ +@SuppressWarnings("checkstyle:HideUtilityClassConstructor") +@NoArgsConstructor(access = AccessLevel.NONE) +public final class KeyStoreUtil { + + private static Map<String, String> mapping = new HashMap<>(); + + static { + mapping.put("p12", "PKCS12"); + mapping.put("jceks", "JCEKS"); + mapping.put("jks", "JKS"); + } + + /** + * Läd und liefert einen KeyStrore. + * <p> + * Unterstützte Formate (bisher): .p12 (Typ: PKCS12) und .jceks (Typ: JCEKS) + * + * @param path der Dateienpfad zur Store-Datei + * @param passPhrase Passwort des Stores + * @return der durch den Pfad referenzierte KeyStore + * @throws ClientInitializationException bei zum Beispiel nicht unterstützen Typen oder wenn die KeyStore-Datei nicht gefunden + * wurde + */ + public static KeyStore load(final String path, final String passPhrase) throws ClientInitializationException { + + try { + final KeyStore keyStore = KeyStore.getInstance(getType(path)); + try (final InputStream is = new FileInputStream(path)) { + keyStore.load(is, passPhrase.toCharArray()); + } catch (FileNotFoundException e) { + // relativ zum Classpath: Fallback for testing + try (final InputStream is = KeyStoreUtil.class.getClassLoader().getResourceAsStream(path)) { + keyStore.load(is, passPhrase.toCharArray()); + } + } + return keyStore; + } catch (IOException | NoSuchAlgorithmException | CertificateException | KeyStoreException e) { + throw new ClientInitializationException("Exception in createSSLContext: " + e.getMessage(), e); + } + } + + private static String getType(final String path) throws ClientInitializationException { + if (!StringUtils.isEmpty(path)) { + String key = path.substring(path.lastIndexOf(".") + 1).toUpperCase(); + return mapping.get(key.toLowerCase()); + } + return KeyStore.getDefaultType(); + } + + public static SecretKey generateSecretKey() throws NoSuchAlgorithmException { + KeyGenerator keygen = KeyGenerator.getInstance("AES"); + keygen.init(128); + return keygen.generateKey(); + } +} diff --git a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java index e7e673b17da04d65e11fee27be1a36114d5a68e5..3fbb3175b457355db632e8a3db2532cc4e0be448 100644 --- a/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java +++ b/src/test/java/de/ozgcloud/xta/client/XtaClientTest.java @@ -2,16 +2,32 @@ package de.ozgcloud.xta.client; import static org.junit.jupiter.api.Assertions.*; +import java.net.URI; +import java.util.List; + import org.apache.commons.lang3.NotImplementedException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import de.ozgcloud.xta.client.codes.IdentifierType; +import de.ozgcloud.xta.client.config.XtaClientConfig; +import de.ozgcloud.xta.client.model.Identifier; import genv3.eu.osci.ws.x2014.x10.transport.PartyIdentifierType; import genv3.eu.osci.ws.x2014.x10.transport.PartyType; +import lombok.SneakyThrows; class XtaClientTest { + final String managementServiceUrl = "https://../managementPort.svc"; + final String sendServiceUrl = "https://../sendPort.svc"; + final String msgBoxServiceUrl = "https://../msgBoxPort.svc"; + + final String clientCertKeystore = "certs/client.jceks"; + final String clientCertKeystorePassword = "*pass*"; + final String trustCertKeystore = "certs/trust.jceks"; + final String trustCertKeystorePassword = "*pass*"; + @DisplayName("get messages metadata") @Nested class TestGetMessagesMetadata { @@ -26,10 +42,23 @@ class XtaClientTest { assertThrows(NotImplementedException.class, () -> client.getMessagesMetadata("selfIdentifier")); } + } + @SneakyThrows private XtaClient createClient() { - return new XtaClient(); + var identifier1 = new Identifier("identifier1", IdentifierType.XOEV); + var config = XtaClientConfig.create( + URI.create(managementServiceUrl).toURL(), + URI.create(sendServiceUrl).toURL(), + null, // URI.create(msgBoxServiceUrl).toURL(), // TODO + List.of(identifier1), + clientCertKeystore, + clientCertKeystorePassword, + trustCertKeystore, + trustCertKeystorePassword + ).build(); + return new XtaClient(config); } } \ No newline at end of file