diff --git a/src/main/java/cz/trask/migration/AbstractProcess.java b/src/main/java/cz/trask/migration/AbstractProcess.java index 1d8ca05..18cf186 100644 --- a/src/main/java/cz/trask/migration/AbstractProcess.java +++ b/src/main/java/cz/trask/migration/AbstractProcess.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import cz.trask.migration.config.ConfigManager; import cz.trask.migration.model.APIList; +import cz.trask.migration.model.ApplicationConfig; import cz.trask.migration.model.HttpResponse; import cz.trask.migration.model.RegisterResponse; import cz.trask.migration.model.TokenResponse; @@ -40,7 +41,7 @@ public abstract class AbstractProcess { public static ObjectMapper mapper; public static ObjectMapper mapperYaml; - protected ConfigManager config = ConfigManager.getInstance(); + protected ApplicationConfig config; protected AbstractProcess() { mapper = new ObjectMapper(); @@ -51,6 +52,8 @@ public abstract class AbstractProcess { yamlFactory.configure(YAMLGenerator.Feature.SPLIT_LINES, false); mapperYaml = new ObjectMapper(yamlFactory); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + config = ConfigManager.getInstance().getConfig(); setTrustStoreCredentials(); @@ -62,18 +65,18 @@ public abstract class AbstractProcess { } protected void setTrustStoreCredentials() { - log.info("Setting truststore: " + config.getTruststorePath()); - System.setProperty("javax.net.ssl.trustStore", config.getTruststorePath()); - System.setProperty("javax.net.ssl.trustStorePassword", config.getTruststorePassword()); + log.info("Setting truststore: " + config.getTrustStore().getPath()); + System.setProperty("javax.net.ssl.trustStore", config.getTrustStore().getPath()); + System.setProperty("javax.net.ssl.trustStorePassword", config.getTrustStore().getPassword()); } protected TokenResponse authenticateToWso2AndGetToken() throws Exception { - RegisterResponse register = register(config.getSourceRegistrationApiUrl(), config.getSourceWso2User()); + RegisterResponse register = register(config.getSource().getRegistrationApiUrl(), config.getSource().getWso2User()); String clientId = register.getClientId(); log.info("Registered with clientId: {}", clientId); - TokenResponse token = getToken(config.getSourcePublisherTokenUrl(), config.getSourceWso2User(), register, + TokenResponse token = getToken(config.getSource().getPublisherTokenUrl(), config.getSource().getWso2User(), register, "apim:api_view apim:api_create apim:api_manage apim:api_delete apim:api_publish " + "apim:subscription_view apim:subscription_block apim:subscription_manage apim:external_services_discover " + "apim:threat_protection_policy_create apim:threat_protection_policy_manage apim:document_create apim:document_manage " diff --git a/src/main/java/cz/trask/migration/config/ConfigManager.java b/src/main/java/cz/trask/migration/config/ConfigManager.java index 04d1996..eb444e1 100644 --- a/src/main/java/cz/trask/migration/config/ConfigManager.java +++ b/src/main/java/cz/trask/migration/config/ConfigManager.java @@ -3,85 +3,19 @@ package cz.trask.migration.config; import java.io.File; import java.io.InputStream; import java.nio.file.Files; -import java.util.Properties; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import cz.trask.migration.AbstractProcess; +import cz.trask.migration.model.ApplicationConfig; +import lombok.extern.log4j.Log4j2; +@Log4j2 public final class ConfigManager { - /* -------------------------------------------------------------------- */ - /* LOGIC & CONSTANTS */ - /* -------------------------------------------------------------------- */ - - private static final Logger log = LogManager.getLogger(ConfigManager.class); - - private static final String PROPERTY_FILENAME = "apicurio-migrator.properties"; - - // SOURCE - public static final String PROP_SOURCE_REGISTRATION_API_URL = "SOURCE_REGISTRATION_API_URL"; - public static final String PROP_SOURCE_PUBLISHER_API_URL = "SOURCE_PUBLISHER_API_URL"; - public static final String PROP_SOURCE_DEVPORTAL_API_URL = "SOURCE_DEVPORTAL_API_URL"; - public static final String PROP_SOURCE_PUBLISHER_TOKEN_URL = "SOURCE_PUBLISHER_TOKEN_URL"; - public static final String PROP_SOURCE_WSO2_USER = "SOURCE_WSO2_USER"; - - // TARGET - public static final String PROP_TARGET_REGISTRATION_API_URL = "TARGET_REGISTRATION_API_URL"; - public static final String PROP_TARGET_PUBLISHER_API_URL = "TARGET_PUBLISHER_API_URL"; - public static final String PROP_TARGET_DEVPORTAL_API_URL = "TARGET_DEVPORTAL_API_URL"; - public static final String PROP_TARGET_PUBLISHER_TOKEN_URL = "TARGET_PUBLISHER_TOKEN_URL"; - public static final String PROP_TARGET_WSO2_USER = "TARGET_WSO2_USER"; - - // TRUSTSTORE - public static final String PROP_TRUSTSTORE_PATH = "TRUSTSTORE_PATH"; - public static final String PROP_TRUSTSTORE_PASSWORD = "TRUSTSTORE_PASSWORD"; - - // URL PATTERNS - public static final String PROP_PUBLISHER_URL_PATTERN = "PUBLISHER_URL_PATTERN"; - public static final String PROP_DEVPORTAL_URL_PATTERN = "DEVPORTAL_URL_PATTERN"; - - // APICURIO & GROUP - public static final String PROP_APICURIO_API_URL = "APICURIO_API_URL"; - public static final String PROP_DEFAULT_API_GROUP = "DEFAULT_API_GROUP"; - - // MAX THREADS - public static final String PROP_MAX_THREADS = "MAX_THREADS"; - - /* -------------------------------------------------------------------- */ - /* CONFIGURATION FIELDS */ - /* -------------------------------------------------------------------- */ - - private final String sourceRegistrationApiUrl; - private final String sourcePublisherApiUrl; - private final String sourceDevportalApiUrl; - private final String sourcePublisherTokenUrl; - private final String sourceWso2User; - - private final String targetRegistrationApiUrl; - private final String targetPublisherApiUrl; - private final String targetDevportalApiUrl; - private final String targetPublisherTokenUrl; - private final String targetWso2User; - - private final String truststorePath; - private final String truststorePassword; - - private final String publisherUrlPattern; - private final String devportalUrlPattern; - - private final String apicurioApiUrl; - private final String defaultApiGroup; - - private final int maxThreads; + private static final String PROPERTY_FILENAME = "apicurio-migrator.yaml"; private static volatile ConfigManager INSTANCE; - /** Všechny načtené hodnoty. */ - private final Properties props = new Properties(); - - /* -------------------------------------------------------------------- */ - /* SINGLETON – lazy‑initialization‑on-demand holder */ - /* -------------------------------------------------------------------- */ + private static ApplicationConfig config = new ApplicationConfig(); private ConfigManager() { @@ -116,7 +50,7 @@ public final class ConfigManager { try (InputStream input = in) { if (input != null) { - props.load(input); + config = AbstractProcess.mapperYaml.readValue(input, ApplicationConfig.class); log.info("Property file loaded successfully."); } else { log.warn("No property source available; proceeding with defaults where possible."); @@ -124,29 +58,6 @@ public final class ConfigManager { } catch (Exception e) { log.error("Cannot load property file.", e); } - - sourceRegistrationApiUrl = getRequired(PROP_SOURCE_REGISTRATION_API_URL); - sourcePublisherApiUrl = getRequired(PROP_SOURCE_PUBLISHER_API_URL); - sourceDevportalApiUrl = getRequired(PROP_SOURCE_DEVPORTAL_API_URL); - sourcePublisherTokenUrl = getRequired(PROP_SOURCE_PUBLISHER_TOKEN_URL); - sourceWso2User = getRequired(PROP_SOURCE_WSO2_USER); - - targetRegistrationApiUrl = getRequired(PROP_TARGET_REGISTRATION_API_URL); - targetPublisherApiUrl = getRequired(PROP_TARGET_PUBLISHER_API_URL); - targetDevportalApiUrl = getRequired(PROP_TARGET_DEVPORTAL_API_URL); - targetPublisherTokenUrl = getRequired(PROP_TARGET_PUBLISHER_TOKEN_URL); - targetWso2User = getRequired(PROP_TARGET_WSO2_USER); - - truststorePath = getRequired(PROP_TRUSTSTORE_PATH); - truststorePassword = getRequired(PROP_TRUSTSTORE_PASSWORD); - - publisherUrlPattern = getRequired(PROP_PUBLISHER_URL_PATTERN); - devportalUrlPattern = getRequired(PROP_DEVPORTAL_URL_PATTERN); - - apicurioApiUrl = getRequired(PROP_APICURIO_API_URL); - defaultApiGroup = getRequired(PROP_DEFAULT_API_GROUP); - - maxThreads = Integer.parseInt(props.getProperty(PROP_MAX_THREADS, "10")); } public static ConfigManager getInstance() { @@ -160,83 +71,7 @@ public final class ConfigManager { return INSTANCE; } - private String getRequired(String key) { - String value = props.getProperty(key); - if (value == null) { - throw new IllegalStateException("Missing required property: " + key); - } - return value.trim(); - } - - /* -------------------------------------------------------------------- */ - /* PUBLIC GETTERS */ - /* -------------------------------------------------------------------- */ - - public String getSourceRegistrationApiUrl() { - return sourceRegistrationApiUrl; - } - - public String getSourcePublisherApiUrl() { - return sourcePublisherApiUrl; - } - - public String getSourceDevportalApiUrl() { - return sourceDevportalApiUrl; - } - - public String getSourcePublisherTokenUrl() { - return sourcePublisherTokenUrl; - } - - public String getSourceWso2User() { - return sourceWso2User; - } - - public String getTargetRegistrationApiUrl() { - return targetRegistrationApiUrl; - } - - public String getTargetPublisherApiUrl() { - return targetPublisherApiUrl; - } - - public String getTargetDevportalApiUrl() { - return targetDevportalApiUrl; - } - - public String getTargetPublisherTokenUrl() { - return targetPublisherTokenUrl; - } - - public String getTargetWso2User() { - return targetWso2User; - } - - public String getTruststorePath() { - return truststorePath; - } - - public String getTruststorePassword() { - return truststorePassword; - } - - public String getPublisherUrlPattern() { - return publisherUrlPattern; - } - - public String getDevportalUrlPattern() { - return devportalUrlPattern; - } - - public String getApicurioApiUrl() { - return apicurioApiUrl; - } - - public String getDefaultApiGroup() { - return defaultApiGroup; - } - - public int getMaxThreads() { - return maxThreads; + public ApplicationConfig getConfig() { + return config; } } diff --git a/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java b/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java index 5326723..cd7e647 100644 --- a/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java +++ b/src/main/java/cz/trask/migration/impl/v32/ImportToApicurio.java @@ -44,7 +44,7 @@ public class ImportToApicurio extends AbstractProcess { private final RegistryClient client; public ImportToApicurio() throws Exception { - this.client = RegistryClientFactory.create(config.getApicurioApiUrl()); + this.client = RegistryClientFactory.create(config.getApicurio().getApiUrl()); } /** @@ -58,7 +58,7 @@ public class ImportToApicurio extends AbstractProcess { TokenResponse token = authenticateToWso2AndGetToken(); - APIList apis = getList(config.getSourcePublisherApiUrl(), token); + APIList apis = getList(config.getSource().getPublisherApiUrl(), token); if (apis == null || apis.getList() == null || apis.getList().length == 0) { throw new IllegalStateException( "No APIs to export that match your criteria! Check the name of the API you want to export."); @@ -105,16 +105,16 @@ public class ImportToApicurio extends AbstractProcess { "Bearer " + tokenResponse.getAccess_token()); // 1) Retrieve basic information - HttpResponse apiInfoResp = makeRequest("GET", config.getSourceDevportalApiUrl() + "/apis/" + api.getId(), + HttpResponse apiInfoResp = makeRequest("GET", config.getSource().getDevPortalApiUrl() + "/apis/" + api.getId(), httpHeaders, Collections.emptyMap()); HttpResponse subsResp = makeRequest("GET", - config.getSourcePublisherApiUrl() + "/subscriptions?apiId=" + api.getId(), httpHeaders, + config.getSource().getPublisherApiUrl() + "/subscriptions?apiId=" + api.getId(), httpHeaders, Collections.emptyMap()); // 2) Export the API as a zip HttpResponse exportedZip = makeRequest("GET", - config.getSourcePublisherApiUrl() + "/apis/export?apiId=" + api.getId(), httpHeaders, + config.getSource().getPublisherApiUrl() + "/apis/export?apiId=" + api.getId(), httpHeaders, Collections.emptyMap(), true); List zipEntries = ZipUtils.extractFilesFromZip(exportedZip.getResponseBytes()); @@ -147,8 +147,8 @@ public class ImportToApicurio extends AbstractProcess { // 5) Build the description that contains the publisher & devportal URLs String baseDesc = api.getDescription() != null ? api.getDescription() : ""; - String pubUrl = config.getPublisherUrlPattern().replace("{API_ID}", api.getId()); - String devPortUrl = config.getDevportalUrlPattern().replace("{API_ID}", api.getId()); + String pubUrl = config.getPatterns().getPublisherUrlPattern().replace("{API_ID}", api.getId()); + String devPortUrl = config.getPatterns().getDevPortalUrlPattern().replace("{API_ID}", api.getId()); String fullDesc = baseDesc + " ***** PUBLISHER URL ***** " + pubUrl + " ***** DEVPORTAL URL ***** " + devPortUrl; @@ -159,7 +159,7 @@ public class ImportToApicurio extends AbstractProcess { updateSwagger(swaggerObj, apiMap, fullDesc); // 7) Prepare artifact creation/update - String group = config.getDefaultApiGroup(); + String group = config.getApicurio().getDefaultApiGroup(); String mainArtifactId = api.getName() + api.getContext(); VersionSearchResults existingArtifacts; diff --git a/src/main/java/cz/trask/migration/impl/v45/ExportToWso2FromV32.java b/src/main/java/cz/trask/migration/impl/v45/ExportToWso2FromV32.java index a5fca2a..8baf7b6 100644 --- a/src/main/java/cz/trask/migration/impl/v45/ExportToWso2FromV32.java +++ b/src/main/java/cz/trask/migration/impl/v45/ExportToWso2FromV32.java @@ -48,7 +48,7 @@ public class ExportToWso2FromV32 extends AbstractProcess { private final RegistryClient client; public ExportToWso2FromV32() throws Exception { - this.client = RegistryClientFactory.create(config.getApicurioApiUrl()); + this.client = RegistryClientFactory.create(config.getApicurio().getApiUrl()); } /** @@ -62,7 +62,7 @@ public class ExportToWso2FromV32 extends AbstractProcess { TokenResponse token = authenticateToWso2AndGetToken(); - ArtifactSearchResults apis = client.searchArtifacts(config.getDefaultApiGroup(), null, null, null, null, + ArtifactSearchResults apis = client.searchArtifacts(config.getApicurio().getDefaultApiGroup(), null, null, null, null, null, null, null, null); log.info("Found {} APIs", apis.getCount()); @@ -92,12 +92,12 @@ public class ExportToWso2FromV32 extends AbstractProcess { try { log.info("Processing API {} of {}", index, total); - VersionSearchResults versions = client.listArtifactVersions(config.getDefaultApiGroup(), api.getId(), null, + VersionSearchResults versions = client.listArtifactVersions(config.getApicurio().getDefaultApiGroup(), api.getId(), null, null); for (SearchedVersion ver : versions.getVersions()) { log.info(" - Found version: {}", ver.getVersion()); - List ref = client.getArtifactReferencesByCoordinates(config.getDefaultApiGroup(), + List ref = client.getArtifactReferencesByCoordinates(config.getApicurio().getDefaultApiGroup(), api.getId(), ver.getVersion()); if (ref != null && !ref.isEmpty()) { log.info("Artifact has {} references", ref.size()); @@ -135,7 +135,7 @@ public class ExportToWso2FromV32 extends AbstractProcess { private int publishApiToWso2(String fileName, byte[] data, TokenResponse tokenResponse) { int responseCode = -1; try { - String url = config.getTargetPublisherApiUrl() + String url = config.getTarget().getPublisherApiUrl() .concat(String.format("?preserveProvider=false&overwrite=true")); log.info("API Import URL: " + url); diff --git a/src/main/java/cz/trask/migration/model/ApplicationConfig.java b/src/main/java/cz/trask/migration/model/ApplicationConfig.java new file mode 100644 index 0000000..3880002 --- /dev/null +++ b/src/main/java/cz/trask/migration/model/ApplicationConfig.java @@ -0,0 +1,75 @@ +package cz.trask.migration.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Data; + +@Data +public class ApplicationConfig { + + @JsonProperty("source") + private Source source; + @JsonProperty("target") + private Target target; + @JsonProperty("truststore") + private TrustStore trustStore; + @JsonProperty("patterns") + private Patterns patterns; + @JsonProperty("apicurio") + private Apicurio apicurio; + @JsonProperty("max_threads") + private int maxThreads; + + @Data + public static class Source { + @JsonProperty("registration_api_url") + private String registrationApiUrl; + @JsonProperty("publisher_api_url") + private String publisherApiUrl; + @JsonProperty("devportal_api_url") + private String devPortalApiUrl; + @JsonProperty("publisher_token_url") + private String publisherTokenUrl; + @JsonProperty("wso2_user") + private String wso2User; + + } + + @Data + public static class TrustStore { + @JsonProperty("path") + private String path; + @JsonProperty("password") + private String password; + } + + @Data + public static class Patterns { + @JsonProperty("publisher_url_pattern") + private String publisherUrlPattern; + @JsonProperty("devportal_url_pattern") + private String devPortalUrlPattern; + } + + @Data + public static class Apicurio { + @JsonProperty("api_url") + private String apiUrl; + @JsonProperty("default_api_group") + private String defaultApiGroup; + } + + @Data + public static class Target { + @JsonProperty("registration_api_url") + private String registrationApiUrl; + @JsonProperty("publisher_api_url") + private String publisherApiUrl; + @JsonProperty("devportal_api_url") + private String devPortalApiUrl; + @JsonProperty("publisher_token_url") + private String publisherTokenUrl; + @JsonProperty("wso2_user") + private String wso2User; + } +} diff --git a/src/main/resources/apicurio-migrator.properties b/src/main/resources/apicurio-migrator.properties deleted file mode 100644 index be3f6fe..0000000 --- a/src/main/resources/apicurio-migrator.properties +++ /dev/null @@ -1,25 +0,0 @@ -# Source WSO2 API Manager v3.2.0 -SOURCE_REGISTRATION_API_URL = https://localhost:9443/client-registration/v0.17/register -SOURCE_PUBLISHER_API_URL = https://localhost:9443/api/am/publisher -SOURCE_DEVPORTAL_API_URL = https://localhost:9443/api/am/store -SOURCE_PUBLISHER_TOKEN_URL = https://localhost:9443/oauth2/token -SOURCE_WSO2_USER = YWRtaW46YWRtaW4= - -# Target WSO2 API Manager v4.5.0 -TARGET_REGISTRATION_API_URL = https://localhost:9443/client-registration/v0.17/register -TARGET_PUBLISHER_API_URL = https://localhost:9443/api/am/publisher/v4/apis/import -TARGET_DEVPORTAL_API_URL = https://localhost:9443/api/am/devportal -TARGET_PUBLISHER_TOKEN_URL = https://localhost:9443/oauth2/token -TARGET_WSO2_USER = YWRtaW46YWRtaW4= - -TRUSTSTORE_PATH = client-truststore.jks -TRUSTSTORE_PASSWORD = wso2carbon - -PUBLISHER_URL_PATTERN = https://api-developers.dev.koop.appl.services/publisher/apis/{API_ID}/overview -DEVPORTAL_URL_PATTERN = https://api-developers.dev.koop.appl.services/devportal/apis/{API_ID}/overview - -#APICURIO_API_URL = http://10.0.0.190:8080/apis/registry/v2 -APICURIO_API_URL = http://apicurio:8095/apis/registry/v2 -DEFAULT_API_GROUP = api - -MAX_THREADS = 1 \ No newline at end of file diff --git a/src/main/resources/apicurio-migrator.yaml b/src/main/resources/apicurio-migrator.yaml new file mode 100644 index 0000000..860ade7 --- /dev/null +++ b/src/main/resources/apicurio-migrator.yaml @@ -0,0 +1,27 @@ +source: + registration_api_url: https://localhost:9443/client-registration/v0.17/register + publisher_api_url: https://localhost:9443/api/am/publisher + devportal_api_url: https://localhost:9443/api/am/store + publisher_token_url: https://localhost:9443/oauth2/token + wso2_user: YWRtaW46YWRtaW4= + +target: + registration_api_url: https://localhost:9443/client-registration/v0.17/register + publisher_api_url: https://localhost:9443/api/am/publisher/v4/apis/import + devportal_api_url: https://localhost:9443/api/am/devportal + publisher_token_url: https://localhost:9443/oauth2/token + wso2_user: YWRtaW46YWRtaW4= + +truststore: + path: client-truststore.jks + password: wso2carbon + +patterns: + publisher_url_pattern: https://api-developers.dev.koop.appl.services/publisher/apis/{API_ID}/overview + devportal_url_pattern: https://api-developers.dev.koop.appl.services/devportal/apis/{API_ID}/overview + +apicurio: + api_url: http://apicurio:8095/apis/registry/v2 + default_api_group: api + +max_threads: 1 \ No newline at end of file