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
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ public class KongConstants {
public static final String KONG_RATELIMIT_ADVANCED_PLUGIN_TYPE = "rate-limiting-advanced";
public static final String KONG_RATELIMIT_PLUGIN_TYPE = "rate-limiting";

// API Types
public static final String API_TYPE_HTTP = "HTTP";
public static final String API_TYPE_WS = "WS";

// Protocols
public static final String PROTOCOL_WS = "ws";
public static final String PROTOCOL_WSS = "wss";

// Transports
public static final String TRANSPORT_HTTP = "http,https";
public static final String TRANSPORT_WS = "ws,wss";

// Commonly used default values and headers
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String BEARER_PREFIX = "Bearer ";
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2026 WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.kong.client.builder;

import java.util.UUID;

import org.wso2.carbon.apimgt.api.APIManagementException;
import org.wso2.carbon.apimgt.api.model.API;
import org.wso2.carbon.apimgt.api.model.APIIdentifier;
import org.wso2.carbon.apimgt.api.model.Environment;
import org.wso2.kong.client.KongConstants;
import org.wso2.kong.client.KongKonnectApi;
import org.wso2.kong.client.util.KongAPIUtil;

/**
* Abstract base class for Kong API builders.
* Contains common Kong-specific logic that applies to all Kong API types.
*
* Subclasses (REST, WebSocket, gRPC, etc.) only need to implement:
* - canHandle(): Which API type they support
* - mapSpecificDetails(): Type-specific mapping logic
*/
public abstract class KongAPIBuilder {
protected KongKonnectApi apiGatewayClient;
protected String controlPlaneId;
protected String organization;

/**
* Constructor with Kong-specific dependencies.
* All Kong builders need these common dependencies.
*/
public KongAPIBuilder(KongKonnectApi apiGatewayClient, String controlPlaneId, String organization) {
this.apiGatewayClient = apiGatewayClient;
this.controlPlaneId = controlPlaneId;
this.organization = organization;
}

/**
* Builds a WSO2 API object from the raw external data.
*
* @param sourceApi The raw data object from the external gateway.
* @param env The environment where the API is discovered.
* @param org The organization context.
* @return The constructed API object.
* @throws APIManagementException If an error occurs during building.
*/
public API build(KongApiBundle sourceApi, Environment env, String org) throws APIManagementException {
// 1. Basic Identification
APIIdentifier apiId = new APIIdentifier(org, getName(sourceApi), getVersion(sourceApi));

API api = new API(apiId);

// 2. Map Common Properties
api.setContext(getContext(sourceApi));
api.setContextTemplate(getContextTemplate(sourceApi));
api.setUuid(UUID.randomUUID().toString());
api.setDescription(getDescription(sourceApi));

// 3. Set Standard WSO2 Flags
api.setOrganization(org);
if (env != null) {
api.setGatewayType(env.getGatewayType());
}
api.setInitiatedFromGateway(true);
api.setRevision(false);
api.setGatewayVendor("external");

// 4. Specific Mapping (Delegated to subclasses)
mapSpecificDetails(api, sourceApi, env);

return api;
}

protected String getName(KongApiBundle sourceApi) {
if (sourceApi.hasApiMetadata()) {
return sourceApi.getApi().getName();
}
return sourceApi.getService().getName();
}

protected String getVersion(KongApiBundle sourceApi) {
if (sourceApi.hasApiMetadata() && sourceApi.getApi().getVersion() != null) {
return sourceApi.getApi().getVersion();
}
return KongConstants.DEFAULT_API_VERSION;
}

protected String getContext(KongApiBundle sourceApi) {
if (sourceApi.hasApiMetadata() && sourceApi.getApi().getSlug() != null) {
return KongAPIUtil.ensureLeadingSlash(sourceApi.getApi().getSlug());
}
return KongAPIUtil.ensureLeadingSlash(sourceApi.getService().getName());
}

protected String getContextTemplate(KongApiBundle sourceApi) {
String context = getContext(sourceApi);
String template = context.startsWith("/") ? context.substring(1) : context;
return template.toLowerCase().replace(" ", "-");
}

protected String getGatewayId(KongApiBundle sourceApi) {
if (sourceApi.hasApiMetadata()) {
return sourceApi.getApi().getId();
}
return sourceApi.getService().getId();
}

protected String getDescription(KongApiBundle sourceApi) {
if (sourceApi.hasApiMetadata() && sourceApi.getApi().getDescription() != null) {
return sourceApi.getApi().getDescription();
}
return "";
}

/**
* Maps type-specific details (protocol, endpoints, definitions, etc.) to the API object.
*
* @param api The WSO2 API object to populate.
* @param sourceApi The raw data object.
* @throws APIManagementException If an error occurs during mapping.
*/
protected abstract void mapSpecificDetails(API api, KongApiBundle sourceApi, Environment env) throws APIManagementException;

/**
* Checks if this builder can handle the given raw data object.
*
* @param sourceApi The raw data object.
* @return True if this builder can handle the object, false otherwise.
*/
public abstract boolean canHandle(KongApiBundle sourceApi);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2026 WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.kong.client.builder;

import java.util.ArrayList;
import java.util.List;

import org.wso2.kong.client.KongKonnectApi;

/**
* Kong-specific implementation of FederatedBuilderFactory.
* Creates and manages builders for different Kong API types (REST, WebSocket, gRPC, etc.).
*
* This factory extends the gateway-agnostic FederatedBuilderFactory and registers
* Kong-specific builders for each API type.
*/
public class KongAPIBuilderFactory {

private final List<KongAPIBuilder> builders;

/**
* Constructor initializes the factory with Kong-specific builders.
*
* @param apiGatewayClient Kong Konnect API client for making API calls
* @param controlPlaneId Kong control plane ID
* @param organization WSO2 organization name
*/
public KongAPIBuilderFactory(KongKonnectApi apiGatewayClient, String controlPlaneId, String organization){
this.builders = new ArrayList<>();
initBuilders(apiGatewayClient, controlPlaneId, organization);
}

private void initBuilders(KongKonnectApi apiGatewayClient, String controlPlaneId, String organization) {
registerBuilder(new KongRestAPIBuilder(apiGatewayClient, controlPlaneId, organization));
registerBuilder(new KongWebSocketAPIBuilder(apiGatewayClient, controlPlaneId, organization));
}

/**
* @param sourceApi The raw API data from the gateway
* @return The builder that can handle this API type, or exception if unsupported
*/
public KongAPIBuilder getBuilder(KongApiBundle sourceApi) {
for (KongAPIBuilder builder : builders) {
if (builder.canHandle(sourceApi)) {
return builder;
}
}
throw new IllegalStateException(
"No registered builder can handle the given API data");
}

/**
* Registers a builder in the factory.
* Subclasses can use this to add builders in their constructor.
*
* @param builder The builder to register
*/
protected void registerBuilder(KongAPIBuilder builder) {
if (builder != null) {
// 1. Check if ANY builder in the list has the same CLASS as the new one
boolean alreadyExists = false;
for (KongAPIBuilder existing : builders) {
if (existing.getClass().equals(builder.getClass())) {
alreadyExists = true;
break;
}
}

if (!alreadyExists) {
builders.add(builder);
}
}
}

/**
* Gets all registered builders.
* Useful for testing and debugging.
*
* @return List of all registered builders
*/
public List<KongAPIBuilder> getRegisteredBuilders() {
return new ArrayList<>(builders); // Return a copy for safety
}

/**
* Gets the count of registered builders.
*
* @return Number of registered builders
*/
public int getBuilderCount() {
return builders.size();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2026 WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.kong.client.builder;

import java.util.List;

import org.wso2.kong.client.model.KongAPI;
import org.wso2.kong.client.model.KongPlugin;
import org.wso2.kong.client.model.KongRoute;
import org.wso2.kong.client.model.KongService;

/**
* Data Transfer Object that combines Kong API metadata with its associated service and routes.
* This allows builders to access all necessary Kong data in one object.
*
* Kong Gateway structure:
* - KongAPI: High-level API metadata (name, version, description, spec)
* - KongService: Backend service configuration (host, port, protocol, path)
* - KongRoutes: Path/routing configuration
* - KongPlugins: Policies and configurations
*/
public class KongApiBundle {
private KongAPI api;
private KongService service;
private List<KongRoute> routes;
private List<KongPlugin> plugins;
private String vhost;

public KongApiBundle() {
}

public KongApiBundle(KongAPI api, KongService service, List<KongRoute> routes,
List<KongPlugin> plugins, String vhost) {
this.api = api;
this.service = service;
this.routes = routes;
this.plugins = plugins;
this.vhost = vhost;
}

public KongAPI getApi() {
return api;
}

public void setApi(KongAPI api) {
this.api = api;
}

public KongService getService() {
return service;
}

public void setService(KongService service) {
this.service = service;
}

public List<KongRoute> getRoutes() {
return routes;
}

public void setRoutes(List<KongRoute> routes) {
this.routes = routes;
}

public List<KongPlugin> getPlugins() {
return plugins;
}

public void setPlugins(List<KongPlugin> plugins) {
this.plugins = plugins;
}

public String getVhost() {
return vhost;
}

public void setVhost(String vhost) {
this.vhost = vhost;
}

/**
* Checks if this DTO has API metadata (vs being a "raw service").
*/
public boolean hasApiMetadata() {
return api != null;
}

}
Loading