Skip to content

Commit

Permalink
Merge pull request #425 from eclipse-basyx/development
Browse files Browse the repository at this point in the history
1.5.1 Release
  • Loading branch information
FrankSchnicke authored Feb 5, 2024
2 parents b1bd2b6 + a8ae3d7 commit fcbb80a
Show file tree
Hide file tree
Showing 21 changed files with 385 additions and 93 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/maven-publish-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'adopt'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/maven-run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'adopt'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM openjdk:11-slim-bullseye
FROM amazoncorretto:17

# Install dependency for wait-for-it-env.sh & wget for health check
RUN apt update && apt install -y jq && apt clean
RUN apt install -y wget
RUN yum -y update && yum -y install jq && yum -y clean all
RUN yum -y install wget

# Copy built jar to image using the jar name specified in the pom.xml (JAR_FILE)
ARG JAR_FILE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.docker</artifactId>
<version>1.5.0</version>
<version>1.5.1</version>
</parent>

<artifactId>basyx.components.AASServer</artifactId>
Expand Down Expand Up @@ -80,14 +80,14 @@
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.10.2</version>
<version>4.11.1</version>
</dependency>

<!-- Use Spring Data MongoDB for db data management -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.4.15</version>
<version>3.4.18</version>
</dependency>

<!-- Adds additional classes of the BaSys SDK for tests -->
Expand Down Expand Up @@ -121,14 +121,14 @@
<dependency>
<groupId>org.eclipse.basyx</groupId>
<artifactId>basyx.components.registry</artifactId>
<version>1.5.0</version>
<version>1.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.tngtech.keycloakmock</groupId>
<artifactId>mock</artifactId>
<scope>test</scope>
<version>0.15.2</version>
<version>0.16.0</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,22 +251,12 @@ public void startComponent() {

loadAASServerFeaturesFromConfig();
initializeAASServerFeatures();

BaSyxContext context = contextConfig.createBaSyxContext();
context.addServletMapping("/*", createAggregatorServlet());
addAASServerFeaturesToContext(context);

// An initial AAS has been loaded from the drive?
if (aasBundles != null) {
createBasyxResourceDirectoryIfNotExists();

addAasxFilesResourceServlet(context);

// 2. Fix the file paths according to the servlet configuration
modifyFilePaths(contextConfig.getHostname(), contextConfig.getPort(), getRootFilePathWithContext(contextConfig.getContextPath()));
initializeAasBundles(context);

registerWhitelistedSubmodels();
}
context.addServletMapping("/*", createAggregatorServlet());
addAASServerFeaturesToContext(context);

logger.info("Start the server");
server = new BaSyxHTTPServer(context);
Expand Down Expand Up @@ -523,6 +513,24 @@ private void initializeAASServerFeatures() {
}
}

private void initializeAasBundles(BaSyxContext context) {
loadAASBundles();

if (aasBundles == null)
return;

logger.info("Initializing AAS Bundles");

createBasyxResourceDirectoryIfNotExists();

addAasxFilesResourceServlet(context);

// 2. Fix the file paths according to the servlet configuration
modifyFilePaths(contextConfig.getHostname(), contextConfig.getPort(), getRootFilePathWithContext(contextConfig.getContextPath()));

registerWhitelistedSubmodels();
}

private void cleanUpAASServerFeatures() {
for (IAASServerFeature aasServerFeature : aasServerFeatureList) {
aasServerFeature.cleanUp();
Expand Down Expand Up @@ -585,7 +593,6 @@ private Collection<AASBundle> getFlatAASBundles() {

private VABHTTPInterface<?> createAggregatorServlet() {
aggregator = createAASAggregator();
loadAASBundles();

if (aasBundles != null) {
try (final var ignored = ElevatedCodeAuthentication.enterElevatedCodeAuthenticationArea()) {
Expand Down Expand Up @@ -844,5 +851,6 @@ private void createBasyxResourceDirectoryIfNotExists() {

directory.mkdir();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ public java.io.File getSubmodelElementFile(String idShortPath) {
public void uploadSubmodelElementFile(String idShortPath, InputStream fileStream) {
VABSubmodelAPI api = new VABSubmodelAPI(new VABLambdaProvider(getSubmodel()));
ISubmodelElement element = api.getSubmodelElement(idShortPath);
String fileName = storageApi.writeFile(idShortPath, getSubmodel().getIdentification().getId(), fileStream, element);
updateSubmodelElement(idShortPath, fileName);
storageApi.writeFile(idShortPath, getSubmodel().getIdentification().getId(), fileStream, element);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import org.eclipse.basyx.submodel.metamodel.map.Submodel;
import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPI;
import org.eclipse.basyx.submodel.restapi.api.ISubmodelAPIFactory;
import org.eclipse.basyx.submodel.restapi.vab.VABSubmodelAPIFactory;
import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;

import com.mongodb.client.MongoClient;
Expand Down Expand Up @@ -159,12 +158,12 @@ public ISubmodel getSubmodelbyIdShort(String idShort) throws ResourceNotFoundExc
@Override
public ISubmodelAPI getSubmodelAPIById(IIdentifier identifier) throws ResourceNotFoundException {
Submodel submodel = (Submodel) getSubmodel(identifier);
return new VABSubmodelAPIFactory().create(submodel);
return submodelApiFactory.create(submodel);
}

@Override
public ISubmodelAPI getSubmodelAPIByIdShort(String idShort) throws ResourceNotFoundException {
Submodel submodel = (Submodel) getSubmodelbyIdShort(idShort);
return new VABSubmodelAPIFactory().create(submodel);
return submodelApiFactory.create(submodel);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
package org.eclipse.basyx.regression.AASServer;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
Expand All @@ -36,6 +41,14 @@
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.eclipse.basyx.aas.aggregator.restapi.AASAggregatorProvider;
import org.eclipse.basyx.aas.manager.ConnectedAssetAdministrationShellManager;
import org.eclipse.basyx.aas.metamodel.connected.ConnectedAssetAdministrationShell;
import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor;
Expand All @@ -44,25 +57,28 @@
import org.eclipse.basyx.aas.metamodel.map.descriptor.SubmodelDescriptor;
import org.eclipse.basyx.aas.registration.api.IAASRegistry;
import org.eclipse.basyx.aas.registration.memory.InMemoryRegistry;
import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
import org.eclipse.basyx.submodel.metamodel.api.ISubmodel;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElement;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.ISubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.api.submodelelement.dataelement.IFile;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.ConnectedSubmodelElementCollection;
import org.eclipse.basyx.submodel.metamodel.connected.submodelelement.dataelement.ConnectedFile;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.protocol.api.IConnectorFactory;
import org.eclipse.basyx.vab.protocol.http.connector.HTTPConnectorFactory;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;

/**
* Suite for testing that the XMLAAS servlet is set up correctly. The tests here
* can be used by the servlet test itself and the integration test
*
* @author schnicke, espen
* @author schnicke, espen, mateusmolina
*
*/
public abstract class AASXSuite {
Expand All @@ -86,6 +102,7 @@ public abstract class AASXSuite {
protected static final String fileShortIdPath = "file";

// Has to be individualized by each test inheriting from this suite
// Default configuration is provided by buildEnpoints method
protected static String aasEndpoint;
protected static String smEndpoint;
protected static String aasAEndpoint;
Expand Down Expand Up @@ -137,37 +154,26 @@ public void testGetSingleSubmodel() throws Exception {

@Test
public void testGetSingleModule() throws Exception {
final String FILE_ENDING = "basyx-temp/aasx0/files/aasx/Nameplate/marking_rcm.jpg";
final String FILE_PATH = rootEndpoint + "basyx-temp/aasx0/files/aasx/Nameplate/marking_rcm.jpg";
checkFile(FILE_PATH);
final String FILE_ENDING = VABPathTools.buildPath(new String[] { "basyx-temp", "aasx0", "files", "aasx", "Nameplate", "marking_rcm.jpg" }, 0);
checkFile(VABPathTools.concatenatePaths(rootEndpoint, FILE_ENDING));

// Get the submdoel nameplate
ISubmodel nameplate = manager.retrieveSubmodel(aasId, smId);
// Get the submodel element collection marking_rcm
ConnectedSubmodelElementCollection marking_rcm = (ConnectedSubmodelElementCollection) nameplate.getSubmodelElements().get("Marking_RCM");
Collection<ISubmodelElement> values = marking_rcm.getValue();

// navigate to the File element
Iterator<ISubmodelElement> iter = values.iterator();
while (iter.hasNext()) {
ISubmodelElement element = iter.next();
if (element instanceof ConnectedFile) {
ConnectedFile connectedFile = (ConnectedFile) element;
// get value of the file element
ConnectedFile fileSE = retrieveFileSEFromCollection(marking_rcm);

String fileurl = connectedFile.getValue();
assertTrue(fileurl.endsWith(FILE_ENDING));
}
}
assertTrue(fileSE.getValue().endsWith(FILE_ENDING));
}

@Test
public void testCollidingFiles() throws Exception {
final String FILE_ENDING_A = "basyx-temp/aasx1/files/aasx/files/text.txt";
final String FILE_ENDING_B = "basyx-temp/aasx2/files/aasx/files/text.txt";
final String FILE_ENDING_A = VABPathTools.buildPath(new String[] { "basyx-temp", "aasx1", "files", "aasx", "files", "text.txt" }, 0);
final String FILE_ENDING_B = VABPathTools.buildPath(new String[] { "basyx-temp", "aasx2", "files", "aasx", "files", "text.txt" }, 0);

checkFile(rootEndpoint + FILE_ENDING_A);
checkFile(rootEndpoint + FILE_ENDING_B);
checkFile(VABPathTools.concatenatePaths(rootEndpoint, FILE_ENDING_A));
checkFile(VABPathTools.concatenatePaths(rootEndpoint, FILE_ENDING_B));

ISubmodel smA = manager.retrieveSubmodel(aasAId, smAId);
ISubmodel smB = manager.retrieveSubmodel(aasBId, smBId);
Expand All @@ -194,6 +200,63 @@ public void testAllFiles() throws Exception {

}

@Test
public void fileValueIsCorrectlyUpdated_whenFileIsUpdated() throws Exception {
final String UPLOAD_ENDPOINT = VABPathTools.concatenatePaths(smEndpoint, "submodelElements", "Marking_CRUUS", "File", "upload");

ISubmodel nameplate = manager.retrieveSubmodel(aasId, smId);
ConnectedSubmodelElementCollection marking_cruus = (ConnectedSubmodelElementCollection) nameplate.getSubmodelElements().get("Marking_CRUUS");
ConnectedFile fileSE = retrieveFileSEFromCollection(marking_cruus);

String fileEndpointBefore = fileSE.getValue();
checkFile(fileEndpointBefore);

CloseableHttpResponse response = uploadDummyFileToSubmodelElement(UPLOAD_ENDPOINT, getFileFromResources("BaSyx.png"), ContentType.IMAGE_PNG);
try {
int statusCode = response.getStatusLine().getStatusCode();

assertEquals(HttpStatus.CREATED.value(), statusCode);

String fileEndpointAfter = fileSE.getValue();

assertNotEquals(fileEndpointBefore, fileEndpointAfter);
checkFile(fileEndpointAfter);

} finally {
response.close();
}
}

private ConnectedFile retrieveFileSEFromCollection(ConnectedSubmodelElementCollection marking_rcm) throws Exception {
Collection<ISubmodelElement> values = marking_rcm.getValue();

Iterator<ISubmodelElement> iter = values.iterator();
while (iter.hasNext()) {
ISubmodelElement element = iter.next();
if (element instanceof ConnectedFile) {
return (ConnectedFile) element;
}
}
throw new RuntimeException("No File SubmodelElement found in " + marking_rcm.getIdShort());
}

protected static void buildEndpoints(BaSyxContextConfiguration contextConfig) {
rootEndpoint = VABPathTools.stripSlashes(contextConfig.getUrl());

aasEndpoint = VABPathTools.concatenatePaths(rootEndpoint, AASAggregatorProvider.PREFIX, aasId.getEncodedURN(), "aas");
smEndpoint = VABPathTools.concatenatePaths(aasEndpoint, "submodels", smIdShort, "submodel");

String encodedAasAId = VABPathTools.encodePathElement(aasAId.getId());
aasAEndpoint = VABPathTools.concatenatePaths(rootEndpoint, AASAggregatorProvider.PREFIX, encodedAasAId, "aas");
smAEndpoint = VABPathTools.concatenatePaths(aasAEndpoint, "submodels", smAIdShort, "submodel");

String encodedAasBId = VABPathTools.encodePathElement(aasBId.getId());
aasBEndpoint = VABPathTools.concatenatePaths(rootEndpoint, AASAggregatorProvider.PREFIX, encodedAasBId, "aas");
smBEndpoint = VABPathTools.concatenatePaths(aasBEndpoint, "submodels", smBIdShort, "submodel");

logger.info("AAS URL for servlet test: " + aasEndpoint);
}

private void checkElementCollectionFiles(Collection<ISubmodelElement> elements) {
for (ISubmodelElement element : elements) {
if (element instanceof IFile) {
Expand Down Expand Up @@ -226,4 +289,23 @@ private void checkFile(String absolutePath) {
private ConnectedAssetAdministrationShell getConnectedAssetAdministrationShell() throws Exception {
return manager.retrieveAAS(aasId);
}

private File getFileFromResources(String filename) throws IOException, URISyntaxException {
URL resource = getClass().getClassLoader().getResource(filename);
if (resource == null)
throw new IllegalArgumentException("File not found!");

return new File(resource.toURI());

}

private CloseableHttpResponse uploadDummyFileToSubmodelElement(String endpoint, File file, ContentType contentType) throws IOException {
CloseableHttpClient client = HttpClients.createDefault();

HttpEntity fileEntity = MultipartEntityBuilder.create().addBinaryBody("file", file, contentType, file.getName()).build();
HttpPost postRequest = new HttpPost(endpoint);
postRequest.setEntity(fileEntity);

return client.execute(postRequest);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public abstract class MqttV2AASServerSuite extends AASServerSuite {
protected static AASServerComponent component;
protected static Server mqttBroker;
protected MqttTestListener listener;
private static final String AAS_SERVER_ID = "aas-server";
protected static final String AAS_SERVER_ID = "aas-server";

@Override
protected String getURL() {
Expand Down
Loading

0 comments on commit fcbb80a

Please sign in to comment.