swagger as yaml from exported zip

This commit is contained in:
Radek Davidek 2025-10-01 18:48:22 +02:00
parent ca01fb657f
commit d3eaa644b3
4 changed files with 26 additions and 46 deletions

View File

@ -33,6 +33,11 @@
<artifactId>gson</artifactId> <artifactId>gson</artifactId>
<version>2.13.1</version> <version>2.13.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.4</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -16,6 +16,7 @@ import javax.net.ssl.HttpsURLConnection;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.yaml.snakeyaml.Yaml;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -32,12 +33,16 @@ public abstract class AbstractProcess {
protected Gson gson; protected Gson gson;
protected Yaml yaml;
protected ConfigManager config = ConfigManager.getInstance(); protected ConfigManager config = ConfigManager.getInstance();
protected AbstractProcess() { protected AbstractProcess() {
gson = new GsonBuilder().create(); gson = new GsonBuilder().create();
yaml = new Yaml();
setTrustStoreCredentials(); setTrustStoreCredentials();
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() { javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {

View File

@ -24,7 +24,7 @@ public class ApiSync {
if (sp.getCommand().equalsIgnoreCase("import")) { if (sp.getCommand().equalsIgnoreCase("import")) {
log.info("Import command selected."); log.info("Import command selected.");
Import imp = new Import(sp); Import imp = new Import();
imp.process(); imp.process();
} }
} }

View File

@ -18,15 +18,14 @@ import org.apache.logging.log4j.Logger;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import cz.trask.apioperator.AbstractProcess; import cz.trask.apioperator.AbstractProcess;
import cz.trask.apioperator.model.APIInfo; import cz.trask.apioperator.model.APIInfo;
import cz.trask.apioperator.model.APIList; import cz.trask.apioperator.model.APIList;
import cz.trask.apioperator.model.FileType;
import cz.trask.apioperator.model.HttpResponse; import cz.trask.apioperator.model.HttpResponse;
import cz.trask.apioperator.model.RegisterResponse; import cz.trask.apioperator.model.RegisterResponse;
import cz.trask.apioperator.model.StartParameters;
import cz.trask.apioperator.model.TokenResponse; import cz.trask.apioperator.model.TokenResponse;
import cz.trask.apioperator.model.ZipEntryData; import cz.trask.apioperator.model.ZipEntryData;
import cz.trask.apioperator.utils.ZipExtractor; import cz.trask.apioperator.utils.ZipExtractor;
@ -40,22 +39,6 @@ import io.apicurio.registry.rest.v2.beans.Rule;
import io.apicurio.registry.rest.v2.beans.VersionSearchResults; import io.apicurio.registry.rest.v2.beans.VersionSearchResults;
import io.apicurio.registry.types.RuleType; import io.apicurio.registry.types.RuleType;
/**
* Import class reads APIs from WSO2 APIM and publishes them to Apicurio.
*
* <p>
* All major improvements from the original code:
* <ul>
* <li>Threadsafe counter using {@link AtomicInteger}</li>
* <li>Parameterized Log4j messages</li>
* <li>Safe JSON deserialization with {@code TypeToken}</li>
* <li>Trywithresources for all streams</li>
* <li>Artifact creation references first, then parent</li>
* <li>Cleaner metadata handling (no trailing spaces)</li>
* <li>Specific exception handling and wrapping in a runtime exception</li>
* </ul>
* </p>
*/
public class Import extends AbstractProcess { public class Import extends AbstractProcess {
private static final Logger log = LogManager.getLogger(Import.class); private static final Logger log = LogManager.getLogger(Import.class);
@ -63,11 +46,9 @@ public class Import extends AbstractProcess {
private final AtomicInteger apiCounter = new AtomicInteger(1); private final AtomicInteger apiCounter = new AtomicInteger(1);
private final Gson gson = new Gson(); private final Gson gson = new Gson();
private final StartParameters sp;
private final RegistryClient client; private final RegistryClient client;
public Import(StartParameters sp) throws Exception { public Import() throws Exception {
this.sp = sp;
this.client = RegistryClientFactory.create(config.getApicurioApiUrl()); this.client = RegistryClientFactory.create(config.getApicurioApiUrl());
} }
@ -143,8 +124,6 @@ public class Import extends AbstractProcess {
Map<String, String> httpHeaders = Collections.singletonMap("Authorization", Map<String, String> httpHeaders = Collections.singletonMap("Authorization",
"Bearer " + tokenResponse.getAccess_token()); "Bearer " + tokenResponse.getAccess_token());
String type = mapApiType(api.getType());
// 1) Retrieve basic information // 1) Retrieve basic information
HttpResponse apiInfoResp = makeRequest("GET", config.getSourceDevportalApiUrl() + "/apis/" + api.getId(), HttpResponse apiInfoResp = makeRequest("GET", config.getSourceDevportalApiUrl() + "/apis/" + api.getId(),
httpHeaders, Collections.emptyMap()); httpHeaders, Collections.emptyMap());
@ -153,10 +132,6 @@ public class Import extends AbstractProcess {
config.getSourcePublisherApiUrl() + "/subscriptions?apiId=" + api.getId(), httpHeaders, config.getSourcePublisherApiUrl() + "/subscriptions?apiId=" + api.getId(), httpHeaders,
Collections.emptyMap()); Collections.emptyMap());
HttpResponse swaggerResp = makeRequest("GET",
config.getSourcePublisherApiUrl() + "/apis/" + api.getId() + "/swagger", httpHeaders,
Collections.emptyMap());
// 2) Export the API as a zip // 2) Export the API as a zip
HttpResponse exportedZip = makeRequest("GET", HttpResponse exportedZip = makeRequest("GET",
config.getSourcePublisherApiUrl() + "/apis/export?apiId=" + api.getId(), httpHeaders, config.getSourcePublisherApiUrl() + "/apis/export?apiId=" + api.getId(), httpHeaders,
@ -164,6 +139,16 @@ public class Import extends AbstractProcess {
List<ZipEntryData> zipEntries = ZipExtractor.extractFilesFromZip(exportedZip.getResponseBytes()); List<ZipEntryData> zipEntries = ZipExtractor.extractFilesFromZip(exportedZip.getResponseBytes());
String swagger = null;
for (ZipEntryData e : zipEntries) {
if (e.getType().toString().equals(FileType.OPENAPI.toString())) {
log.debug("Found main API definition file: {}", e.getName());
swagger = new String(e.getContent());
break;
}
}
// 3) Deserialize JSON responses // 3) Deserialize JSON responses
TypeToken<Map<String, Object>> mapType = new TypeToken<>() { TypeToken<Map<String, Object>> mapType = new TypeToken<>() {
}; };
@ -190,7 +175,8 @@ public class Import extends AbstractProcess {
+ devPortUrl; + devPortUrl;
// 6) Update the swagger with the description and servers // 6) Update the swagger with the description and servers
JsonObject swaggerObj = JsonParser.parseString(swaggerResp.getResponse()).getAsJsonObject(); Map<String, Object> swaggerMap = yaml.load(swagger);
JsonObject swaggerObj = gson.toJsonTree(swaggerMap).getAsJsonObject();
updateSwagger(swaggerObj, apiMap, fullDesc); updateSwagger(swaggerObj, apiMap, fullDesc);
// 7) Prepare artifact creation/update // 7) Prepare artifact creation/update
@ -258,22 +244,6 @@ public class Import extends AbstractProcess {
/* Helper methods */ /* Helper methods */
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
private String mapApiType(String type) {
// Java 11 does not support switchexpressions
switch (type) {
case "HTTP":
return "OPENAPI";
case "GRAPHQL":
return "GRAPHQL";
case "WS":
return "ASYNCAPI";
case "SOAP":
return "WSDL";
default:
return type;
}
}
private void updateSwagger(JsonObject swagger, Map<String, Object> apiMap, String description) { private void updateSwagger(JsonObject swagger, Map<String, Object> apiMap, String description) {
JsonObject info = swagger.getAsJsonObject("info"); JsonObject info = swagger.getAsJsonObject("info");
if (info != null) { if (info != null) {