Skip to content
Open
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 .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
20 changes: 5 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
FROM eclipse-temurin:25-jdk AS build
WORKDIR /workspace
FROM eclipse-temurin:21-jdk

RUN apt-get update \
&& apt-get install -y --no-install-recommends maven \
&& rm -rf /var/lib/apt/lists/*
&& apt-get install -y maven \
&& rm -rf /var/lib/apt/lists/*

COPY pom.xml .
COPY src ./src

RUN mvn -q -DskipTests package

FROM eclipse-temurin:25-jre
WORKDIR /app

COPY --from=build /workspace/target/*.jar app.jar
COPY methodologist-setup-service-0.0.1-SNAPSHOT.jar /app/app.jar

EXPOSE 8090

ENTRYPOINT ["java", "-jar", "/app/app.jar"]

ENTRYPOINT ["java", "-jar", "/app/app.jar"]
13 changes: 11 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.6</version>
<relativePath/> <!-- lookup parent from repository -->
<relativePath/>
</parent>
<groupId>tools.vitruv</groupId>
<artifactId>methodologist-setup-service</artifactId>
Expand All @@ -28,8 +28,17 @@
</scm>
<properties>
<java.version>21</java.version>

<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.organization>vitruv-tools</sonar.organization>
<sonar.projectKey>vitruv-tools_Methodologist-SetupService</sonar.projectKey>

</properties>
<dependencies>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
Expand Down Expand Up @@ -109,7 +118,7 @@
<configuration>
<java>
<googleJavaFormat>
<version>1.22.0</version>
<version>1.28.0</version>
<style>GOOGLE</style>
</googleJavaFormat>
</java>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tools.vitruv.methodologist.setup.config;

import java.net.URL;
import java.net.URLClassLoader;

/** The CustomClassLoader class is used to load classes from a custom classpath. */
public class CustomClassLoader extends URLClassLoader {
/**
* The constructor of the CustomClassLoader class.
*
* @param urls The URLs of the classpath.
* @param parent The parent class loader.
*/
public CustomClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}

/**
* Adds a JAR file to the classpath.
*
* @param url The URL of the JAR file.
*/
public void addJar(URL url) {
this.addURL(url);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tools.vitruv.methodologist.setup.config;

import java.nio.file.NoSuchFileException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -69,6 +70,30 @@ public ResponseEntity<ErrorResponseDTO> handleGenmodelException(
return new ResponseEntity<>(errorResponse, HttpStatus.UNPROCESSABLE_ENTITY);
}

/**
* Handles NoSuchFileException raised when an expected build artifact is missing.
*
* @param ex the exception
* @param request the web request
* @return error response with bad request status
*/
@ExceptionHandler(NoSuchFileException.class)
public ResponseEntity<ErrorResponseDTO> handleNoSuchFileException(
NoSuchFileException ex, WebRequest request) {
log.error("NoSuchFileException occurred: {}", ex.getMessage(), ex);

ErrorResponseDTO errorResponse =
ErrorResponseDTO.builder()
.errorCode("VSUM_ARTIFACT_NOT_FOUND")
.message(ex.getMessage())
.status(HttpStatus.BAD_REQUEST.value())
.timestamp(System.currentTimeMillis())
.path(request.getDescription(false).replace("uri=", ""))
.build();

return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}

/**
* Handles all other exceptions.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package tools.vitruv.methodologist.setup.config;

import java.io.File;

/**
* The MetamodelLocation class is used to store the location of a metamodel and its corresponding
* genmodel.
*/
public record MetamodelLocation(
File metamodel, File genmodel, String genmodelUri, String modelDirectory) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package tools.vitruv.methodologist.setup.config;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.emf.codegen.ecore.genmodel.GenModel;
import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

/** The VitruvConfiguration class is used to store the configuration of the Vitruv CLI. */
@Slf4j
public class VitruvConfiguration {

/** -- GETTER -- Returns the model names. */
@Getter private final List<String> modelNames = new ArrayList<>();

private final List<MetamodelLocation> metamodelLocations = new ArrayList<>();

/** -- GETTER -- Returns the reaction file locations used by the CLI. */
@Getter private final List<Path> reactionLocations = new ArrayList<>();

/**
* -- SETTER -- Sets the local path of the configuration.
*
* <p>-- GETTER -- Returns the local path of the configuration.
*/
@Getter @Setter private Path localPath;

/** -- GETTER -- Returns the package name. */
@Getter private String packageName;

/**
* -- SETTER -- Sets the workflow of the configuration.
*
* <p>-- GETTER -- Returns the workflow of the configuration.
*/
@Getter @Setter private File workflow;

/**
* Removes the last segment of a string.
*
* @param input The input string.
* @return The input string without the last segment.
*/
public static String removeLastSegment(String input) {
int lastDotIndex = input.lastIndexOf('.');
if (lastDotIndex == -1) {
return input;
}
return input.substring(0, lastDotIndex);
}

/**
* Adds a metamodel location to the configuration.
*
* @param metamodelLocation The metamodel location to add.
*/
public void addMetamodelLocations(MetamodelLocation metamodelLocation) {
this.metamodelLocations.add(metamodelLocation);
}

/**
* Sets the reaction file locations used by the CLI.
*
* @param reactionLocations list of paths to reaction files.
*/
public void setReactionLocations(List<Path> reactionLocations) {
this.reactionLocations.clear();
if (reactionLocations != null) {
this.reactionLocations.addAll(reactionLocations);
}
}

/**
* Returns the metamodel locations.
*
* @return The metamodel locations.
*/
public List<MetamodelLocation> getMetaModelLocations() {
return this.metamodelLocations;
}

/**
* Sets the metamodel locations using a semicolon-separated list of {@code ecore,genmodel} pairs.
*
* @param paths The metamodel argument string.
*/
public void setMetaModelLocations(String paths) {
Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
reg.getExtensionToFactoryMap().put("ecore", new XMIResourceFactoryImpl());
reg.getExtensionToFactoryMap().put("genmodel", new XMIResourceFactoryImpl());

GenModelPackage.eINSTANCE.eClass();

for (String modelPaths : paths.split(";")) {
String metamodelPath = modelPaths.split(",")[0];
String genmodelPath = modelPaths.split(",")[1];

File metamodel = new File(metamodelPath);
File genmodel = new File(genmodelPath);

String localModelDirectory = "";

ResourceSet resourceSet = new ResourceSetImpl();
URI uri = URI.createFileURI(metamodel.getAbsolutePath().trim());
Resource resource = resourceSet.getResource(uri, true);
String nsUri = "";
if (!resource.getContents().isEmpty()
&& resource.getContents().get(0) instanceof EPackage ePackage) {
URI genmodelURI = URI.createFileURI(genmodel.getAbsolutePath());
nsUri = genmodelURI.toString();
Resource genmodelResource = resourceSet.getResource(genmodelURI, true);
modelNames.add(ePackage.getName());
if (!genmodelResource.getContents().isEmpty()
&& genmodelResource.getContents().get(0) instanceof GenModel genModel) {
String packageString = removeLastSegment(genModel.getModelPluginID());
log.info("--------------------->>>> " + packageString);
this.setPackageName(packageString);
localModelDirectory = genModel.getModelDirectory();
}
}

this.addMetamodelLocations(
new MetamodelLocation(metamodel, genmodel, nsUri, localModelDirectory));
}
}

/**
* Sets the package name.
*
* @param packageName The package name.
*/
public void setPackageName(String packageName) {
this.packageName = packageName.replace("\\s", "");
}
}
Loading