Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVP of Logginghouse extension (0.2) #19

Merged
merged 5 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build-and-publish-edc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ jobs:
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629
with:
arguments: build
env:
USERNAME: ${{ github.actor }}
TOKEN: ${{ github.token }}
- name: Publish package
if: ${{ github.ref == 'refs/heads/main' }}
uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.DS_Store
.idea/
/**/.classpath
/**/.settings
/**/.project

# Ignore Gradle project-specific cache directory
.gradle
Expand Down
10 changes: 10 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ allprojects {
repositories {
mavenCentral()
mavenLocal()
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/ids-basecamp/ids-infomodel-java")
credentials {
username = System.getenv("USERNAME")
password = System.getenv("TOKEN")
}
}
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ assertj=3.23.1
jupiterVersion=5.8.2
mockitoVersion=4.8.0
okHttpVersion=4.10.0
jsonVersion=20230618
jsonVersion=20231013
jettyGroup=org.eclipse.jetty
jettyVersion=11.0.15

Expand Down
5 changes: 5 additions & 0 deletions logging-house-client/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ val jsonVersion: String by project

dependencies {
implementation("${edcGroup}:control-plane-core:${edcVersion}")
implementation("${edcGroup}:http-spi:${edcVersion}")

implementation("com.squareup.okhttp3:okhttp:${okHttpVersion}")
implementation("org.json:json:${jsonVersion}")
implementation("org.glassfish.jersey.media:jersey-media-multipart:3.1.3")

implementation("de.fraunhofer.iais.eis.ids.infomodel:infomodel-java:1.0.2-basecamp")
implementation("de.fraunhofer.iais.eis.ids.infomodel:infomodel-util:1.0.2-basecamp")

testImplementation("org.assertj:assertj-core:${assertj}")
testImplementation("org.junit.jupiter:junit-jupiter-api:${jupiterVersion}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2024 truzzt GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* truzzt GmbH - initial API and implementation
*
*/

package com.truzzt.extension.logginghouse.client;

import org.eclipse.edc.spi.types.domain.message.RemoteMessage;

import java.net.URI;
import java.net.URL;
import java.util.List;

public record CreateProcessMessage(
URL clearingHouseLogUrl,
URI connectorBaseUrl,
String processId,
List<String> processOwners
) implements RemoteMessage {

@Override
public String getProtocol() {
return ExtendedMessageProtocolClearing.IDS_EXTENDED_PROTOCOL_CLEARING;
}

@Override
public String getCounterPartyAddress() {
return clearingHouseLogUrl.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2024 truzzt GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* truzzt GmbH - initial API and implementation
*
*/

package com.truzzt.extension.logginghouse.client;

import com.truzzt.extension.logginghouse.client.ids.jsonld.JsonLd;
import com.truzzt.extension.logginghouse.client.ids.multipart.CalendarUtil;
import com.truzzt.extension.logginghouse.client.ids.multipart.IdsConstants;
import com.truzzt.extension.logginghouse.client.ids.multipart.IdsMultipartParts;
import com.truzzt.extension.logginghouse.client.ids.multipart.MultipartResponse;
import com.truzzt.extension.logginghouse.client.ids.multipart.MultipartSenderDelegate;
import com.truzzt.extension.logginghouse.client.ids.multipart.ResponseUtil;
import de.fraunhofer.iais.eis.DynamicAttributeToken;
import de.fraunhofer.iais.eis.LogMessageBuilder;
import de.fraunhofer.iais.eis.Message;
import de.fraunhofer.iais.eis.MessageProcessedNotificationMessageImpl;
import org.json.JSONObject;

import java.util.List;

public class CreateProcessMessageSender implements MultipartSenderDelegate<CreateProcessMessage, String> {

public CreateProcessMessageSender() {
}

@Override
public Message buildMessageHeader(CreateProcessMessage createProcessMessage, DynamicAttributeToken token) {
return new LogMessageBuilder()
._modelVersion_(IdsConstants.INFORMATION_MODEL_VERSION)
._issued_(CalendarUtil.gregorianNow())
._securityToken_(token)
._issuerConnector_(createProcessMessage.connectorBaseUrl())
._senderAgent_(createProcessMessage.connectorBaseUrl())
.build();
}

@Override
public String buildMessagePayload(CreateProcessMessage createProcessMessage) {
var jo = new JSONObject();
jo.put("owners", createProcessMessage.processOwners());
return jo.toString();
}

@Override
public MultipartResponse<String> getResponseContent(IdsMultipartParts parts) throws Exception {
return ResponseUtil.parseMultipartStringResponse(parts, JsonLd.getObjectMapper());
}

@Override
public List<Class<? extends Message>> getAllowedResponseTypes() {
return List.of(MessageProcessedNotificationMessageImpl.class);
}

@Override
public Class<CreateProcessMessage> getMessageType() {
return CreateProcessMessage.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2022 sovity GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* sovity GmbH - initial API and implementation
*
*/

package com.truzzt.extension.logginghouse.client;

public final class ExtendedMessageProtocolClearing {

private static final String EXTENDED_SUFFIX = "-extended-clearing";
public static final String IDS_MULTIPART = "ids-multipart";
public static final String IDS_EXTENDED_PROTOCOL_CLEARING = String.format("%s%s", IDS_MULTIPART, EXTENDED_SUFFIX);

private ExtendedMessageProtocolClearing() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2022 sovity GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* sovity GmbH - initial API and implementation
*
*/

package com.truzzt.extension.logginghouse.client;

import org.eclipse.edc.connector.contract.spi.event.contractnegotiation.ContractNegotiationFinalized;
import org.eclipse.edc.connector.contract.spi.negotiation.store.ContractNegotiationStore;
import org.eclipse.edc.connector.contract.spi.types.agreement.ContractAgreement;
import org.eclipse.edc.connector.transfer.spi.event.TransferProcessTerminated;
import org.eclipse.edc.connector.transfer.spi.store.TransferProcessStore;
import org.eclipse.edc.connector.transfer.spi.types.TransferProcess;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.event.Event;
import org.eclipse.edc.spi.event.EventEnvelope;
import org.eclipse.edc.spi.event.EventSubscriber;
import org.eclipse.edc.spi.message.RemoteMessageDispatcherRegistry;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.system.Hostname;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class IdsClearingHouseServiceImpl implements EventSubscriber {

private final RemoteMessageDispatcherRegistry dispatcherRegistry;
private final URI connectorBaseUrl;
private final URL clearingHouseLogUrl;
private final ContractNegotiationStore contractNegotiationStore;
private final TransferProcessStore transferProcessStore;
private final Monitor monitor;

public IdsClearingHouseServiceImpl(
RemoteMessageDispatcherRegistry dispatcherRegistry,
Hostname hostname,
URL clearingHouseLogUrl,
ContractNegotiationStore contractNegotiationStore,
TransferProcessStore transferProcessStore,
Monitor monitor) {
this.dispatcherRegistry = dispatcherRegistry;
this.clearingHouseLogUrl = clearingHouseLogUrl;
this.contractNegotiationStore = contractNegotiationStore;
this.transferProcessStore = transferProcessStore;
this.monitor = monitor;

try {
connectorBaseUrl = getConnectorBaseUrl(hostname);
} catch (URISyntaxException e) {
throw new EdcException("Could not create connectorBaseUrl. Hostname can be set using:" +
" edc.hostname", e);
}
}

public void createProcess(ContractAgreement contractAgreement, URL clearingHouseLogUrl) {
// Create PID
List<String> processOwners = new ArrayList<>();
processOwners.add(contractAgreement.getConsumerId());
processOwners.add(contractAgreement.getProviderId());

monitor.info("Creating Process in LoggingHouse");
var logMessage = new CreateProcessMessage(clearingHouseLogUrl, connectorBaseUrl, contractAgreement.getId(), processOwners);
dispatcherRegistry.dispatch(Object.class, logMessage);
}

public void logContractAgreement(ContractAgreement contractAgreement, URL clearingHouseLogUrl) {
monitor.info("Logging contract agreement to LoggingHouse");
var logMessage = new LogMessage(clearingHouseLogUrl, connectorBaseUrl, contractAgreement);
dispatcherRegistry.dispatch(Object.class, logMessage);
}

public void logTransferProcess(TransferProcess transferProcess, URL clearingHouseLogUrl) {
monitor.info("Logging transferprocess to LoggingHouse");
var logMessage = new LogMessage(clearingHouseLogUrl, connectorBaseUrl, transferProcess);
dispatcherRegistry.dispatch(Object.class, logMessage);
}

@Override
public <E extends Event> void on(EventEnvelope<E> event) {
try {
if (event.getPayload() instanceof ContractNegotiationFinalized contractNegotiationFinalized) {
var contractAgreement = resolveContractAgreement(contractNegotiationFinalized);
var pid = contractAgreement.getId();
var extendedUrl = new URL(clearingHouseLogUrl + "/" + pid);

createProcess(contractAgreement, clearingHouseLogUrl);
logContractAgreement(contractAgreement, extendedUrl);
} else if (event.getPayload() instanceof TransferProcessTerminated transferProcessTerminated) {
var transferProcess = resolveTransferProcess(transferProcessTerminated);
var pid = transferProcess.getContractId();
var extendedUrl = new URL(clearingHouseLogUrl + "/" + pid);
logTransferProcess(transferProcess, extendedUrl);
}
} catch (Exception e) {
throw new EdcException("Could not create extended clearinghouse url.");
}
}

private ContractAgreement resolveContractAgreement(ContractNegotiationFinalized contractNegotiationFinalized) throws NullPointerException {
var contractNegotiationId = contractNegotiationFinalized.getContractNegotiationId();
var contractNegotiation = contractNegotiationStore.findById(contractNegotiationId);
return Objects.requireNonNull(contractNegotiation).getContractAgreement();
}

private TransferProcess resolveTransferProcess(TransferProcessTerminated transferProcessTerminated) {
var transferProcessId = transferProcessTerminated.getTransferProcessId();
return transferProcessStore.findById(transferProcessId);
}

private URI getConnectorBaseUrl(Hostname hostname) throws URISyntaxException {
return new URI(String.format("https://%s/", hostname.get()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2022 sovity GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* sovity GmbH - initial API and implementation
*
*/

package com.truzzt.extension.logginghouse.client;

import com.truzzt.extension.logginghouse.client.ids.multipart.IdsMultipartRemoteMessageDispatcher;
import com.truzzt.extension.logginghouse.client.ids.multipart.IdsMultipartSender;

public class IdsMultipartClearingRemoteMessageDispatcher extends IdsMultipartRemoteMessageDispatcher {

public IdsMultipartClearingRemoteMessageDispatcher(IdsMultipartSender idsMultipartSender) {
super(idsMultipartSender);
}

@Override
public String protocol() {
return ExtendedMessageProtocolClearing.IDS_EXTENDED_PROTOCOL_CLEARING;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 sovity GmbH
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* sovity GmbH - initial API and implementation
*
*/

package com.truzzt.extension.logginghouse.client;

import org.eclipse.edc.spi.types.domain.message.RemoteMessage;

import java.net.URI;
import java.net.URL;

public record LogMessage(URL clearingHouseLogUrl,
URI connectorBaseUrl,
Object eventToLog) implements RemoteMessage {
@Override
public String getProtocol() {
return ExtendedMessageProtocolClearing.IDS_EXTENDED_PROTOCOL_CLEARING;
}

@Override
public String getCounterPartyAddress() {
return clearingHouseLogUrl.toString();
}
}
Loading
Loading