Java tutorial
/* * * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed 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.carbon.apimgt.importexport.utils; import org.wso2.carbon.apimgt.importexport.APIExportException; import org.wso2.carbon.apimgt.importexport.APIImportExportConstants; import org.wso2.carbon.apimgt.importexport.APIImportException; import org.wso2.carbon.apimgt.importexport.APIService; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.apimgt.api.APIManagementException; import org.wso2.carbon.apimgt.api.APIProvider; import org.wso2.carbon.apimgt.api.FaultGatewaysException; import org.wso2.carbon.apimgt.api.model.API; import org.wso2.carbon.apimgt.api.model.APIIdentifier; import org.wso2.carbon.apimgt.api.model.Documentation; import org.wso2.carbon.apimgt.api.model.ResourceFile; import org.wso2.carbon.apimgt.api.model.Tier; import org.wso2.carbon.apimgt.impl.APIConstants; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.registry.api.Registry; import org.wso2.carbon.registry.core.Resource; import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.InputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.util.Enumeration; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; /** * This class provides the functions utilized to import an API from an API archive. */ public final class APIImportUtil { private static final Log log = LogFactory.getLog(APIService.class); static APIProvider provider; /** * This method initializes the Provider when there is a direct request to import an API * * @param currentUserName the current logged in user * @throws APIExportException if provider cannot be initialized */ public static void initializeProvider(String currentUserName) throws APIExportException { provider = APIExportUtil.getProvider(currentUserName); } /** * This method uploads a given file to specified location * * @param uploadedInputStream input stream of the file * @param newFileName name of the file to be created * @param storageLocation destination of the new file * @throws APIImportException if the file transfer fails */ public static void transferFile(InputStream uploadedInputStream, String newFileName, String storageLocation) throws APIImportException { FileOutputStream outFileStream = null; try { outFileStream = new FileOutputStream(new File(storageLocation, newFileName)); int read = 0; byte[] bytes = new byte[1024]; while ((read = uploadedInputStream.read(bytes)) != -1) { outFileStream.write(bytes, 0, read); } } catch (IOException e) { String errorMessage = "Error in transferring files."; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } finally { IOUtils.closeQuietly(outFileStream); } } /** * This method decompresses API the archive * * @param sourceFile The archive containing the API * @param destination location of the archive to be extracted * @return Name of the extracted directory * @throws APIImportException If the decompressing fails */ public static String extractArchive(File sourceFile, String destination) throws APIImportException { BufferedInputStream inputStream = null; InputStream zipInputStream = null; FileOutputStream outputStream = null; ZipFile zip = null; String archiveName = null; try { zip = new ZipFile(sourceFile); Enumeration zipFileEntries = zip.entries(); int index = 0; // Process each entry while (zipFileEntries.hasMoreElements()) { // grab a zip file entry ZipEntry entry = (ZipEntry) zipFileEntries.nextElement(); String currentEntry = entry.getName(); //This index variable is used to get the extracted folder name; that is root directory if (index == 0) { archiveName = currentEntry.substring(0, currentEntry.indexOf(File.separatorChar)); --index; } File destinationFile = new File(destination, currentEntry); File destinationParent = destinationFile.getParentFile(); // create the parent directory structure if (destinationParent.mkdirs()) { log.info("Creation of folder is successful. Directory Name : " + destinationParent.getName()); } if (!entry.isDirectory()) { zipInputStream = zip.getInputStream(entry); inputStream = new BufferedInputStream(zipInputStream); // write the current file to the destination outputStream = new FileOutputStream(destinationFile); IOUtils.copy(inputStream, outputStream); } } return archiveName; } catch (IOException e) { String errorMessage = "Failed to extract archive file "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } finally { IOUtils.closeQuietly(zipInputStream); IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } } /** * This method imports an API * * @param pathToArchive location of the extracted folder of the API * @param currentUser the current logged in user * @param isDefaultProviderAllowed decision to keep or replace the provider * @throws APIImportException if there is an error in importing an API */ public static void importAPI(String pathToArchive, String currentUser, boolean isDefaultProviderAllowed) throws APIImportException { API importedApi; // If the original provider is preserved, if (isDefaultProviderAllowed) { FileInputStream inputStream = null; BufferedReader bufferedReader = null; try { inputStream = new FileInputStream(pathToArchive + APIImportExportConstants.JSON_FILE_LOCATION); bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); importedApi = new Gson().fromJson(bufferedReader, API.class); } catch (FileNotFoundException e) { String errorMessage = "Error in locating api.json file. "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(bufferedReader); } } else { String pathToJSONFile = pathToArchive + APIImportExportConstants.JSON_FILE_LOCATION; try { String jsonContent = FileUtils.readFileToString(new File(pathToJSONFile)); JsonElement configElement = new JsonParser().parse(jsonContent); JsonObject configObject = configElement.getAsJsonObject(); //locate the "providerName" within the "id" and set it as the current user JsonObject apiId = configObject.getAsJsonObject(APIImportExportConstants.ID_ELEMENT); apiId.addProperty(APIImportExportConstants.PROVIDER_ELEMENT, APIUtil.replaceEmailDomain(currentUser)); importedApi = new Gson().fromJson(configElement, API.class); } catch (IOException e) { String errorMessage = "Error in setting API provider to logged in user. "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } } Set<Tier> allowedTiers; Set<Tier> unsupportedTiersList; try { allowedTiers = provider.getTiers(); } catch (APIManagementException e) { String errorMessage = "Error in retrieving tiers of the provider. "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } if (!(allowedTiers.isEmpty())) { unsupportedTiersList = Sets.difference(importedApi.getAvailableTiers(), allowedTiers); //If at least one unsupported tier is found, it should be removed before adding API if (!(unsupportedTiersList.isEmpty())) { for (Tier unsupportedTier : unsupportedTiersList) { //Process is continued with a warning and only supported tiers are added to the importer API log.warn("Tier name : " + unsupportedTier.getName() + " is not supported."); } //Remove the unsupported tiers before adding the API importedApi.removeAvailableTiers(unsupportedTiersList); } } try { provider.addAPI(importedApi); addSwaggerDefinition(importedApi.getId(), pathToArchive); } catch (APIManagementException e) { //Error is logged and APIImportException is thrown because adding API and swagger are mandatory steps String errorMessage = "Error in adding API to the provider. "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } //Since Image, documents, sequences and WSDL are optional, exceptions are logged and ignored in implementation addAPIImage(pathToArchive, importedApi); addAPIDocuments(pathToArchive, importedApi); addAPISequences(pathToArchive, importedApi, currentUser); addAPISpecificSequences(pathToArchive, importedApi, currentUser); addAPIWsdl(pathToArchive, importedApi, currentUser); } /** * This method adds the icon to the API which is to be displayed at the API store. * * @param pathToArchive location of the extracted folder of the API * @param importedApi the imported API object */ private static void addAPIImage(String pathToArchive, API importedApi) { //Adding image icon to the API if there is any File imageFolder = new File(pathToArchive + APIImportExportConstants.IMAGE_FILE_LOCATION); File[] fileArray = imageFolder.listFiles(); FileInputStream inputStream = null; try { if (imageFolder.isDirectory() && fileArray != null) { //This loop locates the icon of the API for (File imageFile : fileArray) { if (imageFile != null && imageFile.getName().contains(APIImportExportConstants.IMAGE_FILE_NAME)) { String mimeType = URLConnection.guessContentTypeFromName(imageFile.getName()); inputStream = new FileInputStream(imageFile.getAbsolutePath()); ResourceFile apiImage = new ResourceFile(inputStream, mimeType); String thumbPath = APIUtil.getIconPath(importedApi.getId()); String thumbnailUrl = provider.addResourceFile(thumbPath, apiImage); importedApi.setThumbnailUrl( APIUtil.prependTenantPrefix(thumbnailUrl, importedApi.getId().getProviderName())); APIUtil.setResourcePermissions(importedApi.getId().getProviderName(), null, null, thumbPath); provider.updateAPI(importedApi); //the loop is terminated after successfully locating the icon break; } } } } catch (FileNotFoundException e) { //This is logged and process is continued because icon is optional for an API log.error("Icon for API is not found. ", e); } catch (APIManagementException e) { //This is logged and process is continued because icon is optional for an API log.error("Failed to add icon to the API. ", e); } catch (FaultGatewaysException e) { //This is logged and process is continued because icon is optional for an API log.error("Failed to update API after adding icon. ", e); } finally { IOUtils.closeQuietly(inputStream); } } /** * This method adds the documents to the imported API * * @param pathToArchive location of the extracted folder of the API * @param importedApi the imported API object */ private static void addAPIDocuments(String pathToArchive, API importedApi) { String docFileLocation = pathToArchive + APIImportExportConstants.DOCUMENT_FILE_LOCATION; FileInputStream inputStream = null; BufferedReader bufferedReader = null; APIIdentifier apiIdentifier = importedApi.getId(); try { if (checkFileExistence(docFileLocation)) { inputStream = new FileInputStream(docFileLocation); bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); Documentation[] documentations = new Gson().fromJson(bufferedReader, Documentation[].class); //For each type of document separate action is performed for (Documentation doc : documentations) { if (APIImportExportConstants.INLINE_DOC_TYPE.equalsIgnoreCase(doc.getSourceType().toString())) { provider.addDocumentation(apiIdentifier, doc); provider.addDocumentationContent(importedApi, doc.getName(), doc.getSummary()); } else if (APIImportExportConstants.URL_DOC_TYPE .equalsIgnoreCase(doc.getSourceType().toString())) { provider.addDocumentation(apiIdentifier, doc); } else if (APIImportExportConstants.FILE_DOC_TYPE .equalsIgnoreCase(doc.getSourceType().toString())) { inputStream = new FileInputStream(pathToArchive + doc.getFilePath()); String docExtension = FilenameUtils.getExtension(pathToArchive + doc.getFilePath()); ResourceFile apiDocument = new ResourceFile(inputStream, docExtension); String visibleRolesList = importedApi.getVisibleRoles(); String[] visibleRoles = new String[0]; if (visibleRolesList != null) { visibleRoles = visibleRolesList.split(","); } String filePathDoc = APIUtil.getDocumentationFilePath(apiIdentifier, doc.getName()); APIUtil.setResourcePermissions(importedApi.getId().getProviderName(), importedApi.getVisibility(), visibleRoles, filePathDoc); doc.setFilePath(provider.addResourceFile(filePathDoc, apiDocument)); provider.addDocumentation(apiIdentifier, doc); } } } } catch (FileNotFoundException e) { //this error is logged and ignored because documents are optional in an API log.error("Failed to locate the document files of the API.", e); } catch (APIManagementException e) { //this error is logged and ignored because documents are optional in an API log.error("Failed to add Documentations to API.", e); } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(bufferedReader); } } /** * This method adds API sequences to the imported API. If the sequence is a newly defined one, it is added. * * @param pathToArchive location of the extracted folder of the API * @param importedApi the imported API object * @param currentUser current logged in username */ private static void addAPISequences(String pathToArchive, API importedApi, String currentUser) { Registry registry = APIExportUtil.getRegistry(currentUser); String inSequenceFileName = importedApi.getInSequence() + APIImportExportConstants.XML_EXTENSION; String inSequenceFileLocation = pathToArchive + APIImportExportConstants.IN_SEQUENCE_LOCATION + inSequenceFileName; String regResourcePath = APIConstants.API_CUSTOM_SEQUENCE_LOCATION + File.separator; //Adding in-sequence, if any if (checkFileExistence(inSequenceFileLocation)) { regResourcePath = APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN + File.separator + inSequenceFileName; addSequenceToRegistry(registry, inSequenceFileLocation, regResourcePath); } String outSequenceFileName = importedApi.getOutSequence() + APIImportExportConstants.XML_EXTENSION; String outSequenceFileLocation = pathToArchive + APIImportExportConstants.OUT_SEQUENCE_LOCATION + outSequenceFileName; //Adding out-sequence, if any if (checkFileExistence(outSequenceFileLocation)) { regResourcePath = APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT + File.separator + outSequenceFileName; addSequenceToRegistry(registry, outSequenceFileLocation, regResourcePath); } String faultSequenceFileName = importedApi.getFaultSequence() + APIImportExportConstants.XML_EXTENSION; String faultSequenceFileLocation = pathToArchive + APIImportExportConstants.FAULT_SEQUENCE_LOCATION + faultSequenceFileName; //Adding fault-sequence, if any if (checkFileExistence(faultSequenceFileLocation)) { regResourcePath = APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT + File.separator + faultSequenceFileName; addSequenceToRegistry(registry, faultSequenceFileLocation, regResourcePath); } } /** * This method adds API Specific sequences added through the store to the imported API. * * @param pathToArchive location of the extracted folder of the API * @param importedApi the imported API object * @param currentUser current logged in username */ private static void addAPISpecificSequences(String pathToArchive, API importedApi, String currentUser) { Registry registry = APIExportUtil.getRegistry(currentUser); String inSequenceFileName = importedApi.getInSequence(); String inSequenceFileLocation = pathToArchive + APIImportExportConstants.IN_SEQUENCE_LOCATION + "custom" + File.separator + inSequenceFileName; String regResourcePath = APIConstants.API_ROOT_LOCATION + File.separator + importedApi.getId().getProviderName() + File.separator + importedApi.getId().getApiName() + File.separator + importedApi.getId().getVersion() + File.separator; //Adding in-sequence, if any if (checkFileExistence(inSequenceFileLocation)) { regResourcePath = regResourcePath + APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN + File.separator + inSequenceFileName; addSequenceToRegistry(registry, inSequenceFileLocation, regResourcePath); } String outSequenceFileName = importedApi.getOutSequence(); String outSequenceFileLocation = pathToArchive + APIImportExportConstants.OUT_SEQUENCE_LOCATION + "custom" + File.separator + outSequenceFileName; //Adding out-sequence, if any if (checkFileExistence(outSequenceFileLocation)) { regResourcePath = regResourcePath + APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT + File.separator + outSequenceFileName; addSequenceToRegistry(registry, outSequenceFileLocation, regResourcePath); } String faultSequenceFileName = importedApi.getFaultSequence(); String faultSequenceFileLocation = pathToArchive + APIImportExportConstants.FAULT_SEQUENCE_LOCATION + "custom" + File.separator + outSequenceFileName; //Adding fault-sequence, if any if (checkFileExistence(faultSequenceFileLocation)) { regResourcePath = regResourcePath + APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT + File.separator + faultSequenceFileName; addSequenceToRegistry(registry, faultSequenceFileLocation, regResourcePath); } } /** * This method adds the sequence files to the registry. * @param registry the registry instance * @param sequenceFileLocation location of the sequence file */ private static void addSequenceToRegistry(Registry registry, String sequenceFileLocation, String regResourcePath) { InputStream inSeqStream = null; try { if (registry.resourceExists(regResourcePath)) { if (log.isDebugEnabled()) { log.debug("Defined sequences have already been added to the registry"); } } else { if (log.isDebugEnabled()) { log.debug("Adding defined sequences to the registry."); } File sequenceFile = new File(sequenceFileLocation); inSeqStream = new FileInputStream(sequenceFile); byte[] inSeqData = IOUtils.toByteArray(inSeqStream); Resource inSeqResource = (Resource) registry.newResource(); inSeqResource.setContent(inSeqData); registry.put(regResourcePath, inSeqResource); } } catch (org.wso2.carbon.registry.api.RegistryException e) { //this is logged and ignored because sequences are optional log.error("Failed to add sequences into the registry : " + regResourcePath, e); } catch (IOException e) { //this is logged and ignored because sequences are optional log.error("I/O error while writing sequence data to the registry : " + regResourcePath, e); } finally { IOUtils.closeQuietly(inSeqStream); } } /** * This method adds the WSDL to the registry, if there is a WSDL associated with the API * * @param pathToArchive location of the extracted folder of the API * @param importedApi the imported API object * @param currentUser current logged in username */ private static void addAPIWsdl(String pathToArchive, API importedApi, String currentUser) { String wsdlFileName = importedApi.getId().getApiName() + "-" + importedApi.getId().getVersion() + APIImportExportConstants.WSDL_EXTENSION; String wsdlPath = pathToArchive + APIImportExportConstants.WSDL_LOCATION + wsdlFileName; if (checkFileExistence(wsdlPath)) { try { URL wsdlFileUrl = new File(wsdlPath).toURI().toURL(); importedApi.setWsdlUrl(wsdlFileUrl.toString()); Registry registry = APIExportUtil.getRegistry(currentUser); APIUtil.createWSDL((org.wso2.carbon.registry.core.Registry) registry, importedApi); } catch (MalformedURLException e) { //this exception is logged and ignored since WSDL is optional for an API log.error("Error in getting WSDL URL. ", e); } catch (org.wso2.carbon.registry.core.exceptions.RegistryException e) { //this exception is logged and ignored since WSDL is optional for an API log.error("Error in putting the WSDL resource to registry. ", e); } catch (APIManagementException e) { //this exception is logged and ignored since WSDL is optional for an API log.error("Error in creating the WSDL resource in the registry. ", e); } } } /** * This method adds Swagger API definition to registry * * @param apiId Identifier of the imported API * @param archivePath File path where API archive stored * @throws APIImportException if there is an error occurs when adding Swagger definition */ private static void addSwaggerDefinition(APIIdentifier apiId, String archivePath) throws APIImportException { try { String swaggerContent = FileUtils .readFileToString(new File(archivePath + APIImportExportConstants.SWAGGER_DEFINITION_LOCATION)); provider.saveSwagger20Definition(apiId, swaggerContent); } catch (APIManagementException e) { String errorMessage = "Error in adding Swagger definition for the API. "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } catch (IOException e) { String errorMessage = "Error in importing Swagger definition for the API. "; log.error(errorMessage, e); throw new APIImportException(errorMessage, e); } } /** * This method checks whether a given file exists in a given location * * @param fileLocation location of the file * @return true if the file exists, false otherwise */ private static boolean checkFileExistence(String fileLocation) { File testFile = new File(fileLocation); return testFile.exists(); } }