reference file names normalization

This commit is contained in:
Radek Davidek 2025-12-15 16:13:11 +01:00
parent 39588039f2
commit f50e3ae7d4
5 changed files with 78 additions and 145 deletions

View File

@ -1,16 +1,22 @@
package cz.trask.migration; package cz.trask.migration;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.security.KeyStore; import java.security.KeyStore;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
@ -26,15 +32,18 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import cz.trask.migration.config.ConfigManager; import cz.trask.migration.config.ConfigManager;
import cz.trask.migration.model.APIInfo;
import cz.trask.migration.model.APIList; import cz.trask.migration.model.APIList;
import cz.trask.migration.model.ApplicationConfig; import cz.trask.migration.model.ApplicationConfig;
import cz.trask.migration.model.ApplicationConfig.Wso2Endpoints; import cz.trask.migration.model.ApplicationConfig.Wso2Endpoints;
import cz.trask.migration.model.HttpResponse; import cz.trask.migration.model.HttpResponse;
import cz.trask.migration.model.RegisterResponse; import cz.trask.migration.model.RegisterResponse;
import cz.trask.migration.model.TokenResponse; import cz.trask.migration.model.TokenResponse;
import cz.trask.migration.model.ZipEntryData;
import io.apicurio.registry.rest.client.RegistryClient; import io.apicurio.registry.rest.client.RegistryClient;
import io.apicurio.registry.rest.client.RegistryClientFactory; import io.apicurio.registry.rest.client.RegistryClientFactory;
import io.apicurio.registry.rest.v2.beans.ArtifactMetaData; import io.apicurio.registry.rest.v2.beans.ArtifactMetaData;
import io.apicurio.registry.rest.v2.beans.ArtifactReference;
import io.apicurio.registry.rest.v2.beans.EditableMetaData; import io.apicurio.registry.rest.v2.beans.EditableMetaData;
import io.apicurio.registry.rest.v2.beans.Rule; import io.apicurio.registry.rest.v2.beans.Rule;
import io.apicurio.registry.types.RuleType; import io.apicurio.registry.types.RuleType;
@ -479,10 +488,10 @@ public abstract class AbstractProcess {
return resp; return resp;
} }
protected void setArtifactMetaData(ArtifactMetaData meta, Map<String, String> props) { protected void setArtifactMetaData(ArtifactMetaData meta, String name, String description, Map<String, String> props) {
EditableMetaData metaData = new EditableMetaData(); EditableMetaData metaData = new EditableMetaData();
metaData.setName(meta.getName()); metaData.setName(name);
metaData.setDescription(meta.getDescription()); metaData.setDescription(description);
if (props != null) if (props != null)
metaData.setProperties(props); metaData.setProperties(props);
@ -516,4 +525,61 @@ public abstract class AbstractProcess {
"Basic ".concat(Base64.getEncoder().encodeToString(username.concat(":").concat(password).getBytes()))); "Basic ".concat(Base64.getEncoder().encodeToString(username.concat(":").concat(password).getBytes())));
return httpHeaders; return httpHeaders;
} }
protected void addEndpointsToProps(Map<String, String> props, Map<String, Object> apiMap) {
if (apiMap == null || !apiMap.containsKey("endpointURLs"))
return;
@SuppressWarnings("unchecked")
List<Map<String, Object>> envs = (List<Map<String, Object>>) apiMap.get("endpointURLs");
for (Map<String, Object> env : envs) {
@SuppressWarnings("unchecked")
Map<String, String> urls = (Map<String, String>) env.get("URLs");
if (urls == null)
continue;
urls.forEach((k, v) -> {
if (v != null)
props.put(k + " Endpoint", v);
});
}
}
protected void addTagsToProps(Map<String, String> props, List<String> tags) {
if (tags != null && !tags.isEmpty()) {
props.put("tags", String.join(", ", tags));
}
}
protected List<ArtifactReference> createReferencesFromZip(List<ZipEntryData> zipEntries, APIInfo api)
throws IOException {
List<ArtifactReference> references = new ArrayList<>();
for (ZipEntryData entry : zipEntries) {
String artifactId = convertToAscii(api.getName() + "/" + api.getVersion() + "/" + entry.getName());
log.debug("Creating artifact reference for entry: {} with artifactId: {}", entry.getName(), artifactId);
try (ByteArrayInputStream is = new ByteArrayInputStream(entry.getContent())) {
ArtifactMetaData meta = client.createArtifactWithVersion(entry.getType().toString(), artifactId, api.getVersion(), is);
Map<String, String> props = new LinkedHashMap<>();
props.put(PARAM_SOURCE_APIM, VERSION_32);
setArtifactMetaData(meta, entry.getName(), null, props);
}
ArtifactReference ref = new ArtifactReference();
ref.setName(entry.getName());
ref.setGroupId(entry.getType().toString());
ref.setArtifactId(artifactId);
ref.setVersion(api.getVersion());
references.add(ref);
}
return references;
}
private String convertToAscii(String input) {
if (input == null) {
return null;
}
String normalized = Normalizer.normalize(input, Normalizer.Form.NFD);
return normalized.replaceAll("[^\\x00-\\x7F]", "").replace(" ", "_");
}
} }

View File

@ -170,7 +170,7 @@ public class Wso2v32ToApicurio extends AbstractProcess {
api.getName(), fullDesc, null, null, null, api.getName(), fullDesc, null, null, null,
new ByteArrayInputStream(swaggerObj.toString().getBytes()), references); new ByteArrayInputStream(swaggerObj.toString().getBytes()), references);
setArtifactMetaData(meta, props); setArtifactMetaData(meta, api.getName(), fullDesc,props);
// Create the three required rules // Create the three required rules
createRule(meta, "NONE", RuleType.COMPATIBILITY); createRule(meta, "NONE", RuleType.COMPATIBILITY);
createRule(meta, "NONE", RuleType.VALIDITY); createRule(meta, "NONE", RuleType.VALIDITY);
@ -193,7 +193,7 @@ public class Wso2v32ToApicurio extends AbstractProcess {
ArtifactMetaData meta = client.updateArtifact(group, mainArtifactId, api.getVersion(), ArtifactMetaData meta = client.updateArtifact(group, mainArtifactId, api.getVersion(),
api.getName(), fullDesc, new ByteArrayInputStream(swaggerObj.toString().getBytes()), api.getName(), fullDesc, new ByteArrayInputStream(swaggerObj.toString().getBytes()),
references); references);
setArtifactMetaData(meta, props); setArtifactMetaData(meta, api.getName(), fullDesc, props);
} else { } else {
// Version already exists no action needed // Version already exists no action needed
log.warn("API {} with version {} already exists. Skipping import.", api.getContext(), log.warn("API {} with version {} already exists. Skipping import.", api.getContext(),
@ -263,54 +263,6 @@ public class Wso2v32ToApicurio extends AbstractProcess {
} }
} }
private void addEndpointsToProps(Map<String, String> props, Map<String, Object> apiMap) {
if (apiMap == null || !apiMap.containsKey("endpointURLs"))
return;
@SuppressWarnings("unchecked")
List<Map<String, Object>> envs = (List<Map<String, Object>>) apiMap.get("endpointURLs");
for (Map<String, Object> env : envs) {
@SuppressWarnings("unchecked")
Map<String, String> urls = (Map<String, String>) env.get("URLs");
if (urls == null)
continue;
urls.forEach((k, v) -> {
if (v != null)
props.put(k + " Endpoint", v);
});
}
}
private void addTagsToProps(Map<String, String> props, List<String> tags) {
if (tags != null && !tags.isEmpty()) {
props.put("tags", String.join(", ", tags));
}
}
private List<ArtifactReference> createReferencesFromZip(List<ZipEntryData> zipEntries, APIInfo api)
throws IOException {
List<ArtifactReference> references = new ArrayList<>();
for (ZipEntryData entry : zipEntries) {
String artifactId = api.getName() + "/" + api.getVersion() + "/" + entry.getName();
try (ByteArrayInputStream is = new ByteArrayInputStream(entry.getContent())) {
ArtifactMetaData meta = client.createArtifactWithVersion(entry.getType().toString(), artifactId,
api.getVersion(), is);
Map<String, String> props = new LinkedHashMap<>();
props.put(PARAM_SOURCE_APIM, VERSION_32);
setArtifactMetaData(meta, props);
}
ArtifactReference ref = new ArtifactReference();
ref.setName(entry.getName());
ref.setGroupId(entry.getType().toString());
ref.setArtifactId(artifactId);
ref.setVersion(api.getVersion());
references.add(ref);
}
return references;
}
private void addSubscriptionsToReferences(List<ArtifactReference> references, Subscriptions subs, APIInfo api) private void addSubscriptionsToReferences(List<ArtifactReference> references, Subscriptions subs, APIInfo api)
throws Exception { throws Exception {
if (subs == null || subs.getList() == null || subs.getList().isEmpty()) if (subs == null || subs.getList() == null || subs.getList().isEmpty())
@ -325,7 +277,7 @@ public class Wso2v32ToApicurio extends AbstractProcess {
api.getVersion(), is); api.getVersion(), is);
Map<String, String> props = new LinkedHashMap<>(); Map<String, String> props = new LinkedHashMap<>();
props.put(PARAM_SOURCE_APIM, VERSION_32); props.put(PARAM_SOURCE_APIM, VERSION_32);
setArtifactMetaData(meta, props); setArtifactMetaData(meta, artifactId, null, props);
} }
ArtifactReference ref = new ArtifactReference(); ArtifactReference ref = new ArtifactReference();

View File

@ -4,6 +4,7 @@ import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.text.Normalizer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -13,7 +14,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import cz.trask.migration.AbstractProcess; import cz.trask.migration.AbstractProcess;
@ -21,9 +21,6 @@ import cz.trask.migration.model.APIInfo;
import cz.trask.migration.model.FileType; import cz.trask.migration.model.FileType;
import cz.trask.migration.model.ZipEntryData; import cz.trask.migration.model.ZipEntryData;
import cz.trask.migration.model.v32.ApiDefinition32; import cz.trask.migration.model.v32.ApiDefinition32;
import cz.trask.migration.model.v32.Subscriptions;
import cz.trask.migration.model.v32.Subscriptions.ApplicationInfo;
import cz.trask.migration.model.v32.Subscriptions.Subscription;
import io.apicurio.registry.rest.client.exception.VersionAlreadyExistsException; import io.apicurio.registry.rest.client.exception.VersionAlreadyExistsException;
import io.apicurio.registry.rest.v2.beans.ArtifactMetaData; import io.apicurio.registry.rest.v2.beans.ArtifactMetaData;
import io.apicurio.registry.rest.v2.beans.ArtifactReference; import io.apicurio.registry.rest.v2.beans.ArtifactReference;
@ -135,7 +132,6 @@ public class Wso2v32ToApicurioFromDir extends AbstractProcess {
+ devPortUrl; + devPortUrl;
ObjectNode swaggerObj = mapperYaml.valueToTree(swaggerMap); ObjectNode swaggerObj = mapperYaml.valueToTree(swaggerMap);
updateSwagger(swaggerObj, apiDef, fullDesc);
String group = config.getApicurio().getDefaultApiGroup(); String group = config.getApicurio().getDefaultApiGroup();
String mainArtifactId = api.getName() + api.getContext(); String mainArtifactId = api.getName() + api.getContext();
@ -160,7 +156,7 @@ public class Wso2v32ToApicurioFromDir extends AbstractProcess {
api.getName(), fullDesc, null, null, null, api.getName(), fullDesc, null, null, null,
new ByteArrayInputStream(swaggerObj.toString().getBytes()), references); new ByteArrayInputStream(swaggerObj.toString().getBytes()), references);
setArtifactMetaData(meta, props); setArtifactMetaData(meta, api.getName(), fullDesc, props);
// Create the three required rules // Create the three required rules
createRule(meta, "NONE", RuleType.COMPATIBILITY); createRule(meta, "NONE", RuleType.COMPATIBILITY);
createRule(meta, "NONE", RuleType.VALIDITY); createRule(meta, "NONE", RuleType.VALIDITY);
@ -185,7 +181,7 @@ public class Wso2v32ToApicurioFromDir extends AbstractProcess {
api.getVersion(), api.getVersion(),
api.getName(), fullDesc, new ByteArrayInputStream(swaggerObj.toString().getBytes()), api.getName(), fullDesc, new ByteArrayInputStream(swaggerObj.toString().getBytes()),
references); references);
setArtifactMetaData(meta, props); setArtifactMetaData(meta, api.getName(), fullDesc,props);
} else { } else {
// Version already exists no action needed // Version already exists no action needed
log.warn("API {} with version {} already exists. Skipping import.", log.warn("API {} with version {} already exists. Skipping import.",
@ -206,86 +202,4 @@ public class Wso2v32ToApicurioFromDir extends AbstractProcess {
} }
} }
/* --------------------------------------------------------------------- */
/* Helper methods */
/* --------------------------------------------------------------------- */
private void updateSwagger(ObjectNode swagger, ApiDefinition32 apiDef, String description) {
// Update "info.description"
ObjectNode info = (ObjectNode) swagger.get("info");
if (info != null) {
info.put("description", description);
}
// Build "servers" array
ArrayNode servers = mapper.createArrayNode();
Map<String, Object> endpoints = apiDef.getEndpointConfig();
if (endpoints != null) {
Map<String, Object> prodEps = (Map<String, Object>) endpoints.get("production_endpoints");
Map<String, Object> sandEps = (Map<String, Object>) endpoints.get("sandbox_endpoints");
ObjectNode server = mapper.createObjectNode();
if (k.equals("https") || k.equals("wss")) {
server.put("url", v);
}
server.put("description", "Gateway: " + env.getOrDefault("environmentName", ""));
servers.add(server);
}
}
// Replace "servers" node
swagger.set("servers",servers);
}
private void addEndpointsToProps(Map<String, String> props, Map<String, Object> apiMap) {
if (apiMap == null || !apiMap.containsKey("endpointURLs"))
return;
@SuppressWarnings("unchecked")
List<Map<String, Object>> envs = (List<Map<String, Object>>) apiMap.get("endpointURLs");
for (Map<String, Object> env : envs) {
@SuppressWarnings("unchecked")
Map<String, String> urls = (Map<String, String>) env.get("URLs");
if (urls == null)
continue;
urls.forEach((k, v) -> {
if (v != null)
props.put(k + " Endpoint", v);
});
}
}
private void addTagsToProps(Map<String, String> props, List<String> tags) {
if (tags != null && !tags.isEmpty()) {
props.put("tags", String.join(", ", tags));
}
}
private List<ArtifactReference> createReferencesFromZip(List<ZipEntryData> zipEntries, APIInfo api)
throws IOException {
List<ArtifactReference> references = new ArrayList<>();
for (ZipEntryData entry : zipEntries) {
String artifactId = api.getName() + "/" + api.getVersion() + "/" + entry.getName();
try (ByteArrayInputStream is = new ByteArrayInputStream(entry.getContent())) {
ArtifactMetaData meta = client.createArtifactWithVersion(entry.getType().toString(), artifactId,
api.getVersion(), is);
Map<String, String> props = new LinkedHashMap<>();
props.put(PARAM_SOURCE_APIM, VERSION_32);
setArtifactMetaData(meta, props);
}
ArtifactReference ref = new ArtifactReference();
ref.setName(entry.getName());
ref.setGroupId(entry.getType().toString());
ref.setArtifactId(artifactId);
ref.setVersion(api.getVersion());
references.add(ref);
}
return references;
}
} }

View File

@ -55,9 +55,10 @@ public class ZipUtils {
return FileType.POLICY_FAULT; return FileType.POLICY_FAULT;
} else if (lowerFileName.endsWith("/meta-information/endpoint_certificates.yaml")) { } else if (lowerFileName.endsWith("/meta-information/endpoint_certificates.yaml")) {
return FileType.CERTIFICATE; return FileType.CERTIFICATE;
} else if (lowerFileName.contains("/docs/filecontents/")) {
return FileType.DOCUMENTATION_FILE;
} else if (lowerFileName.contains("/docs/")) { } else if (lowerFileName.contains("/docs/")) {
return FileType.DOCUMENTATION; return FileType.DOCUMENTATION;
} }
return FileType.UNKNOWN; return FileType.UNKNOWN;
} }

View File

@ -1,5 +1,5 @@
package cz.trask.migration.model; package cz.trask.migration.model;
public enum FileType { public enum FileType {
APIDEF, OPENAPI, WSDL, POLICY_IN, POLICY_OUT, POLICY_FAULT, CERTIFICATE, SUBSCRIPTIONS, DOCUMENTATION, UNKNOWN APIDEF, OPENAPI, WSDL, POLICY_IN, POLICY_OUT, POLICY_FAULT, CERTIFICATE, SUBSCRIPTIONS, DOCUMENTATION, DOCUMENTATION_FILE, UNKNOWN
} }