com.axway.apim.api.export.APIExportConfigAdapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of axway-swagger-promote-export Show documentation
Show all versions of axway-swagger-promote-export Show documentation
Exports existing APIs from a running API-Manager to get the required Swagger-Promote assets.
package com.axway.apim.api.export;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.axway.apim.api.export.jackson.serializer.AIPQuotaSerializerModifier;
import com.axway.apim.api.export.lib.ExportCommandParameters;
import com.axway.apim.lib.AppException;
import com.axway.apim.lib.ErrorCode;
import com.axway.apim.lib.ErrorState;
import com.axway.apim.manager.Proxies;
import com.axway.apim.swagger.APIManagerAdapter;
import com.axway.apim.swagger.api.properties.APIDefintion;
import com.axway.apim.swagger.api.properties.APIImage;
import com.axway.apim.swagger.api.properties.cacerts.CaCert;
import com.axway.apim.swagger.api.properties.outboundprofiles.OutboundProfile;
import com.axway.apim.swagger.api.properties.quota.APIQuota;
import com.axway.apim.swagger.api.state.ActualAPI;
import com.axway.apim.swagger.api.state.DesiredAPI;
import com.axway.apim.swagger.api.state.IAPI;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
public class APIExportConfigAdapter {
private static Logger LOG = LoggerFactory.getLogger(APIExportConfigAdapter.class);
/** Which APIs should be exported identified by the path */
private String exportApiPath = null;
/** Is set if APIs only with that V-Host should be exported */
private String exportVhost = null;
/** Where to store the exported API-Definition */
private String givenExportFolder = null;
APIManagerAdapter apiManager;
ExportCommandParameters params;
public APIExportConfigAdapter(String exportApiPath, String givenExportFolder, String exportVhost) throws AppException {
super();
this.exportApiPath = exportApiPath;
this.exportVhost = (exportVhost!=null && !exportVhost.equals("NOT_SET")) ? exportVhost : null;
this.givenExportFolder = (givenExportFolder==null) ? "." : givenExportFolder;
LOG.debug("Constructed ExportConfigAdapter: [exportApiPath: '"+exportApiPath+"', givenExportFolder: '"+givenExportFolder+"', exportVhost: '"+exportVhost+"']");
apiManager = APIManagerAdapter.getInstance();
params = (ExportCommandParameters)ExportCommandParameters.getInstance();
}
public void exportAPIs() throws AppException {
List exportAPIs = getAPIsToExport();
for (ExportAPI exportAPI : exportAPIs) {
try {
saveAPILocally(exportAPI);
} catch (AppException e) {
LOG.error("Can't export API: " + e.getMessage() + " Please check in API-Manager UI the API is valid.", e);
}
}
}
private List getAPIsToExport() throws AppException {
List exportAPIList = new ArrayList();
if (!this.exportApiPath.contains("*")) { // Direct access with a specific API exposure path
JsonNode mgrAPI = new Proxies.Builder(APIManagerAdapter.TYPE_FRONT_END).hasApiPath(this.exportApiPath).hasVHost(exportVhost).build().getAPI(true);
if(mgrAPI==null) {
ErrorState.getInstance().setError("No API found for: '" + this.exportApiPath + "'", ErrorCode.UNKNOWN_API, false);
throw new AppException("No API found for: '" + this.exportApiPath + "'", ErrorCode.UNKNOWN_API);
}
exportAPIList.add(getExportAPI(mgrAPI));
} else if(APIManagerAdapter.hasAPIManagerVersion("7.7") // Wild-Card search on API-Manager >7.7 filtering directly
&& (this.exportApiPath.startsWith("*") || this.exportApiPath.endsWith("*"))) {
List filters = new ArrayList();
filters.add(new BasicNameValuePair("field", "path"));
filters.add(new BasicNameValuePair("op", "like"));
if(exportApiPath.equals("*")) {
LOG.info("Using '*' to export all APIs from API-Manager.");
filters.add(new BasicNameValuePair("value", "/"));
} else {
LOG.info("Using wildcard pattern: '"+exportApiPath+"' to export APIs from API-Manager.");
filters.add(new BasicNameValuePair("value", exportApiPath.replace("*", "")));
}
List foundAPIs = new Proxies.Builder(APIManagerAdapter.TYPE_FRONT_END).useFilter(filters).hasVHost(exportVhost).build().getAPIs(false);
for(JsonNode mgrAPI : foundAPIs) {
exportAPIList.add(getExportAPI(mgrAPI));
}
} else { // Get all APIs and filter them out manually
Pattern pattern = Pattern.compile(exportApiPath.replace("*", ".*"));
List foundAPIs = new Proxies.Builder(APIManagerAdapter.TYPE_FRONT_END).hasVHost(exportVhost).build().getAPIs(false);
if(foundAPIs.size()>20) LOG.info("Loading actual API state from API-Manager. This may take a while. Please wait.\n");
for(JsonNode mgrAPI : foundAPIs) {
String apiPath = mgrAPI.get("path").asText();
Matcher matcher = pattern.matcher(apiPath);
if(matcher.matches()) {
LOG.debug("Adding API with path: '"+apiPath+"' based on requested path: '"+exportApiPath+"' to the export list.");
exportAPIList.add(getExportAPI(mgrAPI));
}
}
}
return exportAPIList;
}
private ExportAPI getExportAPI(JsonNode mgrAPI) throws AppException {
IAPI actualAPI = apiManager.getAPIManagerAPI(mgrAPI, getAPITemplate());
handleCustomProperties(actualAPI);
APIManagerAdapter.getInstance().translateMethodIds(actualAPI.getInboundProfiles(), actualAPI, true);
APIManagerAdapter.getInstance().translateMethodIds(actualAPI.getOutboundProfiles(), actualAPI, true);
return new ExportAPI(actualAPI);
}
private void saveAPILocally(ExportAPI exportAPI) throws AppException {
String apiPath = getAPIExportFolder(exportAPI.getPath());
File localFolder = new File(this.givenExportFolder +File.separator+ getVHost(exportAPI) + apiPath);
LOG.info("Going to export API into folder: " + localFolder);
if(localFolder.exists()) {
if(params.deleteLocalFolder()) {
LOG.debug("Existing local export folder: " + localFolder + " already exists and will be deleted.");
try {
FileUtils.deleteDirectory(localFolder);
} catch (IOException e) {
throw new AppException("Error deleting local folder", ErrorCode.UNXPECTED_ERROR, e);
}
} else {
LOG.warn("Local export folder: " + localFolder + " already exists. API will not be exported. (You may set -df true)");
return;
}
}
if (!localFolder.mkdirs()) {
throw new AppException("Cant create export folder: " + localFolder, ErrorCode.UNXPECTED_ERROR);
}
APIDefintion apiDef = exportAPI.getAPIDefinition();
String targetFile = null;
try {
targetFile = localFolder.getCanonicalPath() + "/" + exportAPI.getName()+".json";
writeBytesToFile(apiDef.getAPIDefinitionContent(), targetFile);
exportAPI.getAPIDefinition().setAPIDefinitionFile(exportAPI.getName()+".json");
} catch (IOException e) {
throw new AppException("Can't save API-Definition locally to file: " + targetFile,
ErrorCode.UNXPECTED_ERROR, e);
}
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule().setSerializerModifier(new AIPQuotaSerializerModifier()));
mapper.setSerializationInclusion(Include.NON_NULL);
FilterProvider filters = new SimpleFilterProvider()
.addFilter("IgnoreImportFields",
SimpleBeanPropertyFilter.filterOutAllExcept(new String[] {"inbound", "outbound", "certFile" }))
.addFilter("IgnoreApplicationFields",
SimpleBeanPropertyFilter.filterOutAllExcept(new String[] {"name", "oauthClientId", "extClientId", "apiKey" }));
mapper.setFilterProvider(filters);
try {
prepareToSave(exportAPI);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.writeValue(new File(localFolder.getCanonicalPath() + "/api-config.json"), exportAPI);
} catch (Exception e) {
throw new AppException("Can't write API-Configuration file for API: '"+exportAPI.getName()+"' exposed on path: '"+exportAPI.getPath()+"'.", ErrorCode.UNXPECTED_ERROR, e);
}
APIImage image = exportAPI.getAPIImage();
if(image!=null) {
writeBytesToFile(image.getImageContent(), localFolder+File.separator + image.getBaseFilename()+image.getFileExtension());
}
if(exportAPI.getCaCerts()!=null && !exportAPI.getCaCerts().isEmpty()) {
storeCaCerts(localFolder, exportAPI.getCaCerts());
}
LOG.info("Successfully export API to folder: " + localFolder);
if(!APIManagerAdapter.hasAdminAccount()) {
LOG.warn("Export has been done with an Org-Admin account only. Export is restricted by the following: ");
LOG.warn("- No Quotas has been exported for the API");
LOG.warn("- No Client-Organizations");
LOG.warn("- Only subscribed applications from the Org-Admins organization");
}
}
private String getVHost(ExportAPI exportAPI) throws AppException {
if(exportAPI.getVhost()!=null) return exportAPI.getVhost() + File.separator;
String orgVHost = apiManager.getOrg(exportAPI.getOrganizationId()).getVirtualHost();
if(orgVHost!=null) return orgVHost+File.separator;
return "";
}
private void storeCaCerts(File localFolder, List caCerts) throws AppException {
for(CaCert caCert : caCerts) {
if (caCert.getCertBlob() == null) {
LOG.warn("- Ignoring cert export for null certBlob for alias: {}", caCert.getAlias());
} else {
String filename = caCert.getCertFile();
Base64.Encoder encoder = Base64.getMimeEncoder(64, System.getProperty("line.separator").getBytes());
Base64.Decoder decoder = Base64.getDecoder();
final String encodedCertText = new String(encoder.encode(decoder.decode(caCert.getCertBlob())));
byte[] certContent = ("-----BEGIN CERTIFICATE-----\n" + encodedCertText + "\n-----END CERTIFICATE-----").getBytes();
try {
writeBytesToFile(certContent, localFolder + "/" + filename);
} catch (AppException e) {
throw new AppException("Can't write certificate to disc", ErrorCode.UNXPECTED_ERROR, e);
}
}
}
}
private static void writeBytesToFile(byte[] bFile, String fileDest) throws AppException {
try (FileOutputStream fileOuputStream = new FileOutputStream(fileDest)) {
fileOuputStream.write(bFile);
} catch (IOException e) {
throw new AppException("Can't write file", ErrorCode.UNXPECTED_ERROR, e);
}
}
private String getAPIExportFolder(String apiExposurePath) {
if (apiExposurePath.startsWith("/"))
apiExposurePath = apiExposurePath.replaceFirst("/", "");
if (apiExposurePath.endsWith("/"))
apiExposurePath = apiExposurePath.substring(0, apiExposurePath.length() - 1);
apiExposurePath = apiExposurePath.replace("/", "-");
return apiExposurePath;
}
/**
* We need this template to enforce loading of all properties for the actual
* API, without that API-ManagerAdapter will skip not defined properties.
*
* @return
* @throws AppException
*/
private IAPI getAPITemplate() throws AppException {
IAPI apiTemplate = new DesiredAPI();
apiTemplate.setState(IAPI.STATE_PUBLISHED);
apiTemplate.setClientOrganizations(new ArrayList());
// Required to force loading of actual quota!
((DesiredAPI)apiTemplate).setApplicationQuota(new APIQuota());
((DesiredAPI)apiTemplate).setSystemQuota(new APIQuota());
// Given a NOT-KNOWN organization to force the API-Manager Adapter to set the correct orgName in the actual API
((DesiredAPI)apiTemplate).setOrganizationId("NOT-KNOWN");
return apiTemplate;
}
private void handleCustomProperties(IAPI actualAPI) throws AppException {
JsonNode customPropconfig = APIManagerAdapter.getCustomPropertiesConfig().get("api");
if(customPropconfig == null) return; // No custom properties configured
Map customProperties = new LinkedHashMap();
JsonNode actualApiConfig = ((ActualAPI)actualAPI).getApiConfiguration();
// Check if Custom-Properties are configured
Iterator customPropKeys = customPropconfig.fieldNames();
while(customPropKeys.hasNext()) {
String key = customPropKeys.next();
if(actualApiConfig.has(key)) {
JsonNode value = actualApiConfig.get(key);
if(value==null) continue;
customProperties.put(key, value.asText());
}
}
if(customProperties.size()>0) {
((ActualAPI)actualAPI).setCustomProperties(customProperties);
}
}
private void prepareToSave(ExportAPI exportAPI) throws AppException {
// Clean-Up some internal fields in Outbound-Profiles
if(exportAPI.getOutboundProfiles()==null) return;
OutboundProfile profile = exportAPI.getOutboundProfiles().get("_default");
profile.setApiId(null);
profile.setApiMethodId(null);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy