Skip to content
Snippets Groups Projects
Commit 940611e3 authored by Ioannis Chatzis's avatar Ioannis Chatzis
Browse files

Implementation Commit

parent f06ce0c9
No related branches found
No related tags found
2 merge requests!3Develop,!2Resolve "Provision of code and readme file for Service Specification exporting utility"
pom.xml 0 → 100644
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.etsi.osl.util</groupId>
<artifactId>servicespecificationfetcher</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- Specify the Java version you're using -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- Jackson JSON Processor -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.8</version>
</dependency>
<!-- Google Gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<!-- Your custom library dependency -->
<dependency>
<groupId>org.etsi.osl</groupId>
<artifactId>org.etsi.osl.model.tmf</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven Compiler Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>org.osl.etsi.util.ServiceSpecificationFetcher</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<transformers>
<!-- Ensures that the manifest specifies the main class -->
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.osl.etsi.util.ServiceSpecificationFetcher</mainClass> <!-- Fully Qualified Name -->
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package org.osl.etsi.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Properties;
public class KeycloakAuthenticator {
private static final Logger logger = LoggerFactory.getLogger(KeycloakAuthenticator.class.getName());
private final Properties config;
private final HttpClient client;
private final ObjectMapper objectMapper;
private String currentToken;
private long tokenExpiryTime;
private long tokenRefreshBufferSeconds;
/**
* Constructs a KeycloakAuthenticator with the specified configuration file path.
*
* @param configFilePath The file path to the configuration properties file.
* @throws IOException If there is an error loading the configuration file.
*/
public KeycloakAuthenticator(Properties config) throws IOException {
this.config = config;
this.client = HttpClient.newHttpClient();
this.objectMapper = new ObjectMapper();
setTokenRefreshBufferSeconds();
}
/**
* Loads the configuration properties from the specified file path.
*
* @param configFilePath The file path to the configuration properties file.
* @return The token refresh buffer time in seconds.
* @throws IOException If the configuration file cannot be read.
*/
private void setTokenRefreshBufferSeconds() throws IOException {
// Load the token refresh buffer time, defaulting to 60 seconds if not specified
String bufferSecondsStr = this.config.getProperty("token.refresh.buffer.seconds", "60");
long bufferSeconds;
try {
bufferSeconds = Long.parseLong(bufferSecondsStr);
if (bufferSeconds < 0) {
throw new NumberFormatException("Buffer seconds cannot be negative.");
}
} catch (NumberFormatException ex) {
logger.warn("Invalid token.refresh.buffer.seconds value: " + bufferSecondsStr + ". Using default of 60 seconds.");
bufferSeconds = 60;
}
logger.info("Token refresh buffer set to " + bufferSeconds + " seconds.");
this.tokenRefreshBufferSeconds=bufferSeconds;
}
/**
* Retrieves a valid access token. If the current token is expired or not present,
* it authenticates with Keycloak to obtain a new one.
*
* @return A valid access token as a String.
* @throws IOException If an I/O error occurs during authentication.
* @throws InterruptedException If the HTTP request is interrupted.
*/
public synchronized String getToken() throws IOException, InterruptedException {
long currentEpochSeconds = Instant.now().getEpochSecond();
if (currentToken != null && currentEpochSeconds < (tokenExpiryTime - tokenRefreshBufferSeconds)) {
logger.info("Using cached token. Token expires at " + Instant.ofEpochSecond(tokenExpiryTime));
return currentToken;
} else {
logger.info("Cached token is missing or nearing expiration. Authenticating to obtain a new token.");
return authenticateAndGetToken();
}
}
/**
* Authenticates with Keycloak and retrieves a new access token.
*
* @return The new access token as a String.
* @throws IOException If the authentication request fails.
* @throws InterruptedException If the HTTP request is interrupted.
*/
private String authenticateAndGetToken() throws IOException, InterruptedException {
String keycloakUrl = config.getProperty("keycloak.url");
String clientId = config.getProperty("client.id");
String clientSecret = config.getProperty("client.secret");
String username = config.getProperty("username");
String password = config.getProperty("password");
// Validate required properties
if (keycloakUrl == null || clientId == null || username == null || password == null) {
String errorMsg = "Missing required configuration properties.";
logger.error(errorMsg);
throw new IOException(errorMsg);
}
// Build the form data with URL encoding
String form = buildFormData(clientId, clientSecret, username, password);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(keycloakUrl))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(form))
.build();
logger.info("Sending authentication request to Keycloak.");
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
JsonNode responseJson = objectMapper.readTree(response.body());
currentToken = responseJson.get("access_token").asText();
long expiresIn = responseJson.get("expires_in").asLong();
tokenExpiryTime = Instant.now().getEpochSecond() + expiresIn;
logger.info("Authentication successful. Token obtained. Token expires in " + expiresIn + " seconds.");
return currentToken;
} else {
String errorMsg = "Authentication failed: HTTP status " + response.statusCode() + ": " + response.body();
logger.error(errorMsg);
throw new IOException(errorMsg);
}
}
/**
* Builds the URL-encoded form data for the authentication request.
*
* @param clientId The client ID.
* @param clientSecret The client secret (optional).
* @param username The username.
* @param password The password.
* @return The URL-encoded form data as a String.
* @throws IOException If URL encoding fails.
*/
private String buildFormData(String clientId, String clientSecret, String username, String password) throws IOException {
StringBuilder form = new StringBuilder();
form.append("client_id=").append(urlEncode(clientId));
if (clientSecret != null && !clientSecret.isEmpty()) {
form.append("&client_secret=").append(urlEncode(clientSecret));
}
form.append("&username=").append(urlEncode(username));
form.append("&password=").append(urlEncode(password));
form.append("&grant_type=password");
return form.toString();
}
/**
* URL-encodes a string using UTF-8 encoding.
*
* @param value The string to encode.
* @return The URL-encoded string.
* @throws IOException If UTF-8 encoding is not supported.
*/
private String urlEncode(String value) throws IOException {
try {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
} catch (Exception ex) {
logger.error("URL encoding failed for value: " + value, ex);
throw new IOException("URL encoding failed.", ex);
}
}
}
package org.osl.etsi.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.util.*;
import org.etsi.osl.tmf.common.model.AttachmentRef;
import org.etsi.osl.tmf.common.model.AttachmentRefOrValue;
import org.etsi.osl.tmf.common.model.service.ServiceSpecificationRef;
import org.etsi.osl.tmf.lcm.model.LCMRuleSpecification;
import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification;
import org.etsi.osl.tmf.rcm634.model.PhysicalResourceSpecification;
import org.etsi.osl.tmf.rcm634.model.ResourceSpecification;
import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationRef;
import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationRelationship;
import org.etsi.osl.tmf.scm633.model.ServiceSpecRelationship;
import org.etsi.osl.tmf.scm633.model.ServiceSpecification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServiceSpecificationFetcher {
private static final Logger logger = LoggerFactory.getLogger(ServiceSpecificationFetcher.class);
private static final HttpClient client = HttpClient.newHttpClient();
private static final ObjectMapper objectMapper = new ObjectMapper();
private static String apiEndpoint=null;
private static KeycloakAuthenticator keycloakAuthenticator = null;
private static final Properties config = new Properties();
private static String configFilePath = null;
public static void main(String[] args) throws IOException {
String serviceSpecUUid = null;
// Parse command-line arguments
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "--configfile":
if (i + 1 < args.length) {
configFilePath = args[++i];
logger.info("Config file path set to: " + configFilePath);
try (InputStream input = new FileInputStream(configFilePath)) {
config.load(input);
apiEndpoint = config.getProperty("sourceApiEndpoint.url");
logger.info("Configuration loaded successfully from " + configFilePath);
} catch (IOException ex) {
logger.error("Failed to load configuration from " + configFilePath, ex);
throw ex;
}
keycloakAuthenticator= new KeycloakAuthenticator(config);
} else {
logger.error("Missing value for --configfile");
printUsageAndExit();
}
break;
case "--servicespecuuid":
if (i + 1 < args.length) {
serviceSpecUUid = args[++i];
logger.info("Service spec uuid set to: " + serviceSpecUUid);
} else {
logger.error("Missing value for --servicespecuuid");
printUsageAndExit();
}
break;
default:
logger.error("Unknown argument: " + args[i]);
printUsageAndExit();
}
}
// Validate required arguments
if (configFilePath == null || serviceSpecUUid == null) {
logger.error("Missing required arguments.");
printUsageAndExit();
}
// Continue with the rest of your application logic
logger.info("Application started successfully with provided configurations.");
try {
fetchServiceSpecification(serviceSpecUUid, null);
logger.info("All data has been fetched and saved hierarchically.");
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
/**
* Prints usage instructions and exits the application.
*/
private static void printUsageAndExit() {
String usage = "Usage:\n" +
" java -jar servicespecificationfetcher.jar --configfile /path/to/config.yaml --servicespecuuid servicespecuuid\n\n" +
"Parameters:\n" +
" --configfile Path to the configuration file.\n" +
" --servicespecuuid Path to the service specification uuid.";
logger.info(usage);
System.exit(1);
}
private static void loadConfig() {
try (InputStream input = ServiceSpecificationFetcher.class.getClassLoader().getResourceAsStream("config.properties")) {
if (input == null) {
throw new IOException("Unable to find config.properties");
}
config.load(input);
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static ServiceSpecification fetchServiceSpecification(String uuid, File parentDirectory) throws IOException, InterruptedException {
String url = apiEndpoint + "/serviceCatalogManagement/v4/serviceSpecification/" + uuid;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("Failed to get a valid response for "+url+". HTTP status code: " + response.statusCode());
}
if (response.body() == null || response.body().isEmpty()) {
logger.error("No content to map for URL: " + url);
return null;
}
ServiceSpecification serviceSpecification = objectMapper.readValue(response.body(), ServiceSpecification.class);
if (serviceSpecification != null && serviceSpecification.getId() != null) {
logger.info("ServiceSpecification found. Creating folder " + serviceSpecification.getId());
File serviceSpecificationFolder = new File(parentDirectory, serviceSpecification.getId());
if (!serviceSpecificationFolder.exists()) {
serviceSpecificationFolder.mkdirs();
}
saveJsonToFile(serviceSpecification, serviceSpecificationFolder, serviceSpecification.getId() + ".json");
fetchAndSaveAttachments(serviceSpecification, serviceSpecificationFolder);
fetchLCMRuleSpecification(uuid, serviceSpecificationFolder);
File relationshipDir = new File(serviceSpecificationFolder, "serviceSpecificationServiceRelationships");
if (!relationshipDir.exists()) {
relationshipDir.mkdirs();
}
if (serviceSpecification.getServiceSpecRelationship() != null) {
for (ServiceSpecRelationship serviceRelationship : serviceSpecification.getServiceSpecRelationship()) {
fetchServiceSpecification(serviceRelationship.getId(), relationshipDir);
}
}
logger.info("Creating serviceSpecificationResourceRelationships folder for "+serviceSpecification.getId());
File resourceRelationshipDir = new File(serviceSpecificationFolder, "serviceSpecificationResourceRelationships");
if (!resourceRelationshipDir.exists()) {
resourceRelationshipDir.mkdirs();
}
if (serviceSpecification.getResourceSpecification()!= null) {
logger.info("Resource Relationships for "+serviceSpecification.getId()+" found!");
for (ResourceSpecificationRef resourceRelationship : serviceSpecification.getResourceSpecification()) {
String relatedUrl = apiEndpoint + "/resourceCatalogManagement/v4/resourceSpecification/" + resourceRelationship.getId(); // Now using getId()
logger.info("Fetching from "+relatedUrl);
fetchResourceSpecification(relatedUrl, resourceRelationshipDir);
}
}
else
{
logger.info("Resource Relationships for "+serviceSpecification.getId()+" NOT found!");
}
}
return serviceSpecification;
}
private static void fetchLCMRuleSpecification(String serviceSpecId, File parentDirectory) throws IOException, InterruptedException {
String url = apiEndpoint + "/lcmrulesmanagement/v1/lcmRuleSpecification/serviceSpec/" + serviceSpecId;
String token = keycloakAuthenticator.getToken();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + token)
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("Failed to get a valid response for "+url+". HTTP status code: " + response.statusCode());
}
File lcmRulesDirectory = new File(parentDirectory, "serviceSpecificationLcmRules");
if (!lcmRulesDirectory.exists()) {
lcmRulesDirectory.mkdirs();
}
try {
List<String> ruleIds = parseJsonForIds(response.body());
if (ruleIds != null && !ruleIds.isEmpty()) {
// Save a list of rule IDs to a file, assuming this is still required
//saveJsonToFile(ruleIds, new File(parentDirectory, serviceSpecId + "-lcmRuleIds.json"));
saveJsonToFile(response.body(), new File(parentDirectory, serviceSpecId + "-lcmRuleIds.json"));
// Iterate over each ID to fetch and save detailed rule information
for (String ruleId : ruleIds) {
fetchAndSaveDetailedRule(ruleId, lcmRulesDirectory);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void fetchAndSaveDetailedRule(String ruleId, File parentDirectory) throws IOException, InterruptedException {
String ruleUrl = apiEndpoint + "/lcmrulesmanagement/v1/lcmRuleSpecification/" + ruleId;
String token = keycloakAuthenticator.getToken();
HttpRequest detailedRequest = HttpRequest.newBuilder()
.uri(URI.create(ruleUrl))
.header("Authorization", "Bearer " + token)
.GET()
.build();
HttpResponse<String> detailedResponse = client.send(detailedRequest, HttpResponse.BodyHandlers.ofString());
if (detailedResponse.statusCode() != 200) {
logger.error("Failed to get a valid response for rule ID: " + ruleId + " HTTP status code: " + detailedResponse.statusCode());
return;
}
LCMRuleSpecification detailedRule = objectMapper.readValue(detailedResponse.body(), LCMRuleSpecification.class);
detailedRule.setServiceSpecs(new HashSet<ServiceSpecificationRef>());
File ruleFile = new File(parentDirectory, ruleId + ".json");
saveJsonToFile(detailedRule, ruleFile);
}
private static ResourceSpecification fetchResourceSpecification(String url, File parentDirectory) throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new IOException("Failed to get a valid response. HTTP status code: " + response.statusCode());
}
if (response.body() == null || response.body().isEmpty()) {
logger.error("No content to map for URL: " + url);
return null;
}
ResourceSpecification resSpec = null;
try {
JsonNode rootNode = objectMapper.readTree(response.body());
JsonNode typeNode = rootNode.get("@type");
if (typeNode != null) {
String type = typeNode.asText();
ObjectMapper objectMapper = new ObjectMapper();
if ("LogicalResourceSpecification".equals(type)) {
resSpec = objectMapper.readValue(response.body(), LogicalResourceSpecification.class);
logger.info("The JSON contains a LogicalResourceSpecification.");
} else if ("PhysicalResourceSpecification".equals(type)) {
resSpec = objectMapper.readValue(response.body(), PhysicalResourceSpecification.class);
logger.info("The JSON contains a PhysicalResourceSpecification.");
} else {
logger.info("The JSON contains an unknown type: " + type);
}
} else {
logger.info("The JSON does not contain a @type field.");
}
} catch (IOException e) {
e.printStackTrace();
}
if (resSpec != null && resSpec.getId() != null) {
logger.info("Creating "+resSpec.getId()+" folder!");
//logger.info("Creating "+resSpec.getName()+" folder!");
File resourceSpecificationFolder = new File(parentDirectory, resSpec.getId());
//File resourceSpecificationFolder = new File(parentDirectory, resSpec.getName());
if (!resourceSpecificationFolder.exists()) {
resourceSpecificationFolder.mkdirs();
}
saveResourceSpecificationJsonToFile(resSpec, resourceSpecificationFolder, resSpec.getId() + ".json");
//saveResourceSpecificationJsonToFile(resSpec, resourceSpecificationFolder, resSpec.getName() + ".json");
fetchAndSaveAttachments(resSpec, resourceSpecificationFolder);
File relationshipDir = new File(resourceSpecificationFolder, "resourceSpecificationResourceRelationships");
if (!relationshipDir.exists()) {
relationshipDir.mkdirs();
}
if (resSpec.getResourceSpecRelationship()!= null) {
logger.info("Resource Relationships for "+resSpec.getId()+" found!");
//logger.info("Resource Relationships for "+resSpec.getName()+" found!");
for (ResourceSpecificationRelationship relationship : resSpec.getResourceSpecRelationship()) {
String relatedUrl = apiEndpoint + "/resourceCatalogManagement/v4/resourceSpecification/" + relationship.getId(); // Now using getId()
fetchResourceSpecification(relatedUrl, relationshipDir);
}
}
else
{
logger.info("Resource Relationships for "+resSpec.getId()+" NOT found!");
}
}
else
{
logger.info("resSpec != null && resSpec.getId() != null");
}
return resSpec;
}
// Method for ServiceSpecifications
private static void fetchAndSaveAttachments(ServiceSpecification spec, File parentFolder) throws IOException, InterruptedException {
if (spec.getAttachment() != null) {
for (AttachmentRef attachment : spec.getAttachment()) {
String attachmentUrl = attachment.getUrl();
HttpRequest attachmentRequest = HttpRequest.newBuilder()
.uri(URI.create(apiEndpoint + attachmentUrl)) // Assuming the base URL needs to be prefixed
.GET()
.build();
HttpResponse<byte[]> attachmentResponse = client.send(attachmentRequest, HttpResponse.BodyHandlers.ofByteArray());
if (attachmentResponse.statusCode() == 200) {
String relativePath = extractRelativePath(attachmentUrl);
File attachmentDir = new File(parentFolder, relativePath.substring(0, relativePath.lastIndexOf('/')));
if (!attachmentDir.exists()) {
attachmentDir.mkdirs(); // Make sure the directory structure exists
}
File attachmentFile = new File(attachmentDir, relativePath.substring(relativePath.lastIndexOf('/') + 1));
Files.write(attachmentFile.toPath(), attachmentResponse.body());
logger.info("Attachment saved to " + attachmentFile.getPath());
} else {
logger.info("Failed to fetch attachment at " + attachmentUrl);
}
}
}
}
// Overloaded method for ResourceSpecifications
private static void fetchAndSaveAttachments(ResourceSpecification spec, File parentFolder) throws IOException, InterruptedException {
if (spec.getAttachment() != null) {
for (AttachmentRefOrValue attachment : spec.getAttachment()) {
String attachmentUrl = attachment.getUrl();
HttpRequest attachmentRequest = HttpRequest.newBuilder()
.uri(URI.create(apiEndpoint + attachmentUrl)) // Assuming the base URL needs to be prefixed
.GET()
.build();
HttpResponse<byte[]> attachmentResponse = client.send(attachmentRequest, HttpResponse.BodyHandlers.ofByteArray());
if (attachmentResponse.statusCode() == 200) {
String relativePath = extractRelativePath(attachmentUrl);
File attachmentDir = new File(parentFolder, relativePath.substring(0, relativePath.lastIndexOf('/')));
if (!attachmentDir.exists()) {
attachmentDir.mkdirs(); // Make sure the directory structure exists
}
File attachmentFile = new File(attachmentDir, relativePath.substring(relativePath.lastIndexOf('/') + 1));
Files.write(attachmentFile.toPath(), attachmentResponse.body());
logger.info("Attachment saved to " + attachmentFile.getPath());
} else {
logger.info("Failed to fetch attachment at " + attachmentUrl);
}
}
}
}
public static List<String> parseJsonForIds(String json) throws IOException {
// Parse the JSON string into a JsonNode
JsonNode rootNode = objectMapper.readTree(json);
List<String> ids = new ArrayList<>();
// Check if the root node is an array and iterate over it
if (rootNode.isArray()) {
for (JsonNode node : rootNode) {
// Extract the id from each object in the array
String id = node.get("id").asText();
ids.add(id);
}
}
return ids;
}
private static String extractRelativePath(String url) {
URI uri = URI.create(url);
String path = uri.getPath();
return path.substring(path.indexOf("/attachment/") + 1); // Extract the path after "/serviceSpecification/"
}
private static String extractFilename(String url) {
URI uri = URI.create(url);
String path = uri.getPath();
return path.substring(path.lastIndexOf('/') + 1);
}
private static void saveJsonToFile(ServiceSpecification spec, File parentFolder, String filename) throws IOException {
File file = new File(parentFolder, filename);
objectMapper.writerWithDefaultPrettyPrinter().writeValue(file, spec);
logger.info("Saved JSON to " + file.getPath());
}
private static void saveJsonToFile(Object data, File file) throws IOException {
objectMapper.writerWithDefaultPrettyPrinter().writeValue(file, data);
logger.info("Saved JSON to " + file.getPath());
}
private static void saveResourceSpecificationJsonToFile(ResourceSpecification spec, File parentFolder, String filename) throws IOException {
File file = new File(parentFolder, filename);
objectMapper.writerWithDefaultPrettyPrinter().writeValue(file, spec);
logger.info("Saved JSON to " + file.getPath());
}
}
# Select a base image with Java installed
FROM openjdk:17-slim
# Set the working directory
WORKDIR /app
# Copy the executable jar file of the application to the image
COPY servicespecificationfetcher-0.0.1-SNAPSHOT.jar /app/servicespecificationfetcher.jar
# Set the command that will run when the container starts
# Note: Pass the data folder path as an environment variable or argument during runtime.
# Example command to pass data folder as a runtime argument:
# docker run -v /local/path/to/config.properties:/app/config.properties -v /local/path/to/your-data-folder:/app/data-folder your-image uuid
# Updated CMD to accept runtime arguments for data folder
ENTRYPOINT ["sh", "-c", "java -jar /app/servicespecificationfetcher.jar --configfile /app/config.properties --servicespecuuid $0"]
\ No newline at end of file
keycloak.url=http://keycloak:8080/auth/realms/openslice/protocol/openid-connect/token
client.id=osapiWebClientId
client.secret=admin
username=admin
password=admin
sourceApiEndpoint.url=http://localhost/tmf-api
serviceSpecification.uuid=487b9377-460d-4498-a8f3-a23cd7595b06
\ No newline at end of file
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<append>true</append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment