diff --git a/config/api-manager.xml b/config/api-manager.xml index 0312bfa176..c26b3aff54 100644 --- a/config/api-manager.xml +++ b/config/api-manager.xml @@ -12,32 +12,6 @@ false - - - - - - - - - - - + false + org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageDataBridgeDataPublisher + + + {tcp://localhost:7612/} + + + admin + + + admin + - + + + + 4.0.0 + + org.wso2.carbon.apimgt + api-import-export + 1.0-SNAPSHOT + + JAX-RS API Import Export + war + + + + + maven-compiler-plugin + + 1.5 + 1.5 + + 2.3.2 + + + maven-war-plugin + 2.2 + + WEB-INF/lib/*.jar + ${project.artifactId} + + + + maven-eclipse-plugin + 2.9 + + + org.eclipse.jdt.core.javabuilder + + + org.wso2.developerstudio.eclipse.jaxrs.project.nature + org.eclipse.jdt.core.javanature + + + + + + + + + deploy + + compile + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + compile + + run + + + + + + + + + + + + + + + + + + + client + + test + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + test + + java + + + demo.jaxrs.client.Client + + + http://localhost:9763/services + + + + + + + + + + + + + commons-httpclient + commons-httpclient + 3.1 + + + org.apache.cxf + cxf-rt-transports-http + 2.6.1 + + + org.apache.cxf + cxf-rt-frontend-jaxrs + 2.6.1 + + + javax.ws.rs + jsr311-api + 1.1.1 + + + org.wso2.carbon.apimgt + org.wso2.carbon.apimgt.impl + 1.2.4-SNAPSHOT + + + org.wso2.carbon.apimgt + org.wso2.carbon.apimgt.api + 1.2.4-SNAPSHOT + + + org.codehaus.jackson + jackson-mapper-asl + 1.8.5 + + + com.google.code.gson + gson + 1.7.1 + + + com.google.guava + guava + 18.0 + + + + + codehaus + http://repository.codehaus.org/org/codehaus + + + wso2-nexus + WSO2 internal Repository + http://maven.wso2.org/nexus/content/groups/wso2-public/ + + true + daily + warn + + + + wso2.releases + WSO2 internal Repository + http://maven.wso2.org/nexus/content/repositories/releases/ + + true + daily + ignore + + + + \ No newline at end of file diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/APIExportException.java b/modules/api-import-export/src/main/java/apim/restful/importexport/APIExportException.java new file mode 100644 index 0000000000..265e7c459f --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/APIExportException.java @@ -0,0 +1,38 @@ +/* + * + * 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 apim.restful.importexport; + +/** + * This class is used for handling exceptions occur in API export + */ +public class APIExportException extends Exception { + + public APIExportException(String msg) { + super(msg); + } + + public APIExportException(String msg, Throwable e) { + super(msg, e); + } + + public APIExportException(Throwable throwable) { + super(throwable); + } +} + diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/APIImportException.java b/modules/api-import-export/src/main/java/apim/restful/importexport/APIImportException.java new file mode 100644 index 0000000000..4ed47c01fa --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/APIImportException.java @@ -0,0 +1,41 @@ +/* + * + * 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 apim.restful.importexport; + +/** + * This is the class to represent APIImportException. This exception is used to indicate the + * exceptions that might be occurred during API import process. + */ +public class APIImportException extends Exception { + + String errorDescription; + + public APIImportException(String errorMessage) { + this.errorDescription = errorMessage; + } + + /** + * This method returns the error description to the caller. + * + * @return errorDescription a string which contains the error + */ + public String getErrorDescription() { + return this.errorDescription; + } +} diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/APIImportExportConstants.java b/modules/api-import-export/src/main/java/apim/restful/importexport/APIImportExportConstants.java new file mode 100644 index 0000000000..38b0a1f645 --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/APIImportExportConstants.java @@ -0,0 +1,77 @@ +/* + * + * 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 apim.restful.importexport; + +import java.io.File; + +/** + * This class contains all the constants required for API Import and Export + */ +public final class APIImportExportConstants { + + //system dependent default path separator character, represented as a string + public static final String DIRECTORY_SEPARATOR = File.separator; + //string representing the false state when preserving the provider + public static final String STATUS_FALSE = "FALSE"; + //length of the name of the temporary directory + public static final int TEMP_FILENAME_LENGTH = 5; + //system property for default temporary directory + public static final String TEMP_DIR = "java.io.tmpdir"; + //name of the uploaded zip file + public static final String UPLOAD_FILE_NAME = "APIArchive.zip"; + //location of the api JSON file + public static final String JSON_FILE_LOCATION = DIRECTORY_SEPARATOR + "Meta-information" + DIRECTORY_SEPARATOR + + "api.json"; + //name of the id element tag of the api.json file + public static final String ID_ELEMENT = "id"; + //name of the id element tag of the api.json file + public static final String PROVIDER_ELEMENT = "providerName"; + //location of the api swagger definition file + public static final String SWAGGER_DEFINITION_LOCATION = DIRECTORY_SEPARATOR + "Meta-information" + + DIRECTORY_SEPARATOR + "swagger.json"; + //location of the image + public static final String IMAGE_FILE_LOCATION = DIRECTORY_SEPARATOR + "Image" + DIRECTORY_SEPARATOR; + //name of the image + public static final String IMAGE_FILE_NAME = "icon"; + //location of the documents JSON file + public static final String DOCUMENT_FILE_LOCATION = DIRECTORY_SEPARATOR + "Docs" + DIRECTORY_SEPARATOR + + "docs.json"; + //name of the inline file type + public static final String INLINE_DOC_TYPE = "INLINE"; + //name of the url file type + public static final String URL_DOC_TYPE = "URL"; + //name of the physical file type + public static final String FILE_DOC_TYPE = "FILE"; + //location of the in sequence + public static final String IN_SEQUENCE_LOCATION = DIRECTORY_SEPARATOR + "Sequences" + DIRECTORY_SEPARATOR + + "in-sequence" + DIRECTORY_SEPARATOR; + //location of the out sequence + public static final String OUT_SEQUENCE_LOCATION = DIRECTORY_SEPARATOR + "Sequences" + DIRECTORY_SEPARATOR + + "out-sequence" + DIRECTORY_SEPARATOR; + //location of the fault sequence + public static final String FAULT_SEQUENCE_LOCATION = DIRECTORY_SEPARATOR + "Sequences" + DIRECTORY_SEPARATOR + + "fault-sequence" + DIRECTORY_SEPARATOR; + //extension of xml files + public static final String XML_EXTENSION = ".xml"; + //location of the wsdl file + public static final String WSDL_LOCATION = DIRECTORY_SEPARATOR + "WSDL" + DIRECTORY_SEPARATOR; + //extension of wsdl files + public static final String WSDL_EXTENSION = ".wsdl"; + +} diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/APIService.java b/modules/api-import-export/src/main/java/apim/restful/importexport/APIService.java new file mode 100644 index 0000000000..71b94afde6 --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/APIService.java @@ -0,0 +1,214 @@ +/* + * + * 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 apim.restful.importexport; + + +import com.google.gson.Gson; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.POST; +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import java.io.File; +import java.io.InputStream; + +import apim.restful.importexport.utils.APIExportUtil; +import apim.restful.importexport.utils.APIImportUtil; +import apim.restful.importexport.utils.ArchiveGeneratorUtil; +import apim.restful.importexport.utils.AuthenticatorUtil; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.cxf.jaxrs.ext.multipart.Multipart; + +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.api.model.APIIdentifier; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + +/** + * This class provides JAX-RS services for exporting and importing APIs. + * These services provides functionality for exporting and importing single API at a time. + */ +@Path("/") +public class APIService { + + private static final Log log = LogFactory.getLog(APIService.class); + + /** + * This service exports an API from API Manager for a given API ID + * Meta information, API icon, documentation, WSDL and sequences are exported + * This service generates a zipped archive which contains all the above mentioned resources + * for a given API + * + * @param name Name of the API that needs to be exported + * @param version Version of the API that needs to be exported + * @param providerName Provider name of the API that needs to be exported + * @return Zipped API as the response to the service call + */ + @GET + @Path("/export-api") + @Produces("application/zip") + public Response exportAPI(@QueryParam("name") String name, @QueryParam("version") String version, + @QueryParam("provider") String providerName, @Context HttpHeaders httpHeaders) { + + String userName; + if (name == null || version == null || providerName == null) { + log.error("Invalid API Information "); + + return Response.status(Response.Status.BAD_REQUEST).entity("Invalid API Information") + .type(MediaType.APPLICATION_JSON).build(); + } + log.info("Retrieving API for API-Id : " + name + "-" + version + "-" + providerName); + APIIdentifier apiIdentifier; + try { + + Response authorizationResponse = AuthenticatorUtil.authorizeUser(httpHeaders); + if (!(Response.Status.OK.getStatusCode() == authorizationResponse.getStatus())) { + return authorizationResponse; + } + + userName = AuthenticatorUtil.getAuthenticatedUserName(); + //provider names with @ signs are only accepted + String apiDomain = MultitenantUtils.getTenantDomain(providerName); + String apiRequesterDomain = MultitenantUtils.getTenantDomain(userName); + //Allows to export APIs created only in current tenant domain + if (!apiDomain.equals(apiRequesterDomain)) { + //not authorized to export requested API + log.error("Not authorized to " + + "export API :" + name + "-" + version + "-" + providerName); + return Response.status(Response.Status.FORBIDDEN).entity("Not authorized to export API :" + + name + "-" + version + "-" + providerName).type(MediaType.APPLICATION_JSON).build(); + } + + apiIdentifier = new APIIdentifier(APIUtil.replaceEmailDomain(providerName), name, version); + + //create temp location for storing API data to generate archive + String currentDirectory = System.getProperty(APIImportExportConstants.TEMP_DIR); + String createdFolders = File.separator + RandomStringUtils. + randomAlphanumeric(APIImportExportConstants.TEMP_FILENAME_LENGTH) + File.separator; + File exportFolder = new File(currentDirectory + createdFolders); + APIExportUtil.createDirectory(exportFolder.getPath()); + String archiveBasePath = exportFolder.toString(); + + APIExportUtil.setArchiveBasePath(archiveBasePath); + + Response apiResourceRetrievalResponse = APIExportUtil.retrieveApiToExport(apiIdentifier, userName); + + //Retrieve resources : thumbnail, meta information, wsdl, sequences and documents + // available for the exporting API + if (!(Response.Status.OK.getStatusCode() == apiResourceRetrievalResponse.getStatus())) { + return apiResourceRetrievalResponse; + } + + ArchiveGeneratorUtil.archiveDirectory(archiveBasePath); + + log.info("API" + name + "-" + version + " exported successfully"); + + File file = new File(archiveBasePath + ".zip"); + Response.ResponseBuilder response = Response.ok(file); + response.header("Content-Disposition", "attachment; filename=\"" + file.getName() + + "\""); + return response.build(); + + } catch (APIExportException e) { + log.error("APIExportException occurred while exporting ", e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Internal Server Error") + .type(MediaType.APPLICATION_JSON).build(); + } + + } + + /** + * This is the service which is used to import an API. All relevant API data will be included upon the creation of + * the API. Depending on the choice of the user, provider of the imported API will be preserved or modified. + * + * @param uploadedInputStream uploadedInputStream input stream from the REST request + * @param defaultProviderStatus user choice to keep or replace the API provider + * @param httpHeaders HTTP headers for the authentication mechanism + * @return response for the API process + */ + @POST + @Path("/import-api") + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces(MediaType.APPLICATION_JSON) + public Response importAPI(@Multipart("file") InputStream uploadedInputStream, @QueryParam("preserveProvider") + String defaultProviderStatus, @Context HttpHeaders httpHeaders) { + + boolean isProviderPreserved = true; + + //Check if the URL parameter value is specified, otherwise the default value "true" is used + if (APIImportExportConstants.STATUS_FALSE.equalsIgnoreCase(defaultProviderStatus)) { + isProviderPreserved = false; + } + + try { + Response authorizationResponse = AuthenticatorUtil.authorizeUser(httpHeaders); + + //Process continues only if the user is authorized + if (Response.Status.OK.getStatusCode() == authorizationResponse.getStatus()) { + + String currentUser = AuthenticatorUtil.getAuthenticatedUserName(); + APIImportUtil.initializeProvider(currentUser); + + //Temporary directory is used to create the required folders + String currentDirectory = System.getProperty(APIImportExportConstants.TEMP_DIR); + String createdFolders = File.separator + + RandomStringUtils.randomAlphanumeric(APIImportExportConstants.TEMP_FILENAME_LENGTH) + + File.separator; + File importFolder = new File(currentDirectory + createdFolders); + boolean folderCreateStatus = importFolder.mkdirs(); + + //API import process starts only if the required folder is created successfully + if (folderCreateStatus) { + + String uploadFileName = APIImportExportConstants.UPLOAD_FILE_NAME; + String absolutePath = currentDirectory + createdFolders; + APIImportUtil.transferFile(uploadedInputStream, uploadFileName, absolutePath); + + String extractedFolderName = APIImportUtil.extractArchive( + new File(absolutePath + uploadFileName), absolutePath); + + APIImportUtil.importAPI(absolutePath + extractedFolderName, currentUser, isProviderPreserved); + + importFolder.deleteOnExit(); + return Response.status(Status.CREATED).entity("API imported successfully.\n").build(); + } else { + return Response.status(Status.BAD_REQUEST).build(); + } + } else { + return Response.status(Status.UNAUTHORIZED).entity("Not authorized to import API.\n").build(); + } + } catch (APIExportException e) { + return Response.status(Status.INTERNAL_SERVER_ERROR).entity("Error in initializing API provider.\n").build(); + } catch (APIImportException e) { + String errorDetail = new Gson().toJson(e.getErrorDescription()); + return Response.serverError().entity(errorDetail).build(); + } + } +} diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/utils/APIExportUtil.java b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/APIExportUtil.java new file mode 100644 index 0000000000..e26acf59f9 --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/APIExportUtil.java @@ -0,0 +1,630 @@ +/* + * + * 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 apim.restful.importexport.utils; + +import apim.restful.importexport.APIExportException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.apache.axiom.om.OMElement; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.api.APIDefinition; +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.api.APIProvider; +import org.wso2.carbon.apimgt.api.model.API; +import org.wso2.carbon.apimgt.api.model.APIIdentifier; +import org.wso2.carbon.apimgt.api.model.APIStatus; +import org.wso2.carbon.apimgt.api.model.Documentation; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.APIManagerFactory; +import org.wso2.carbon.apimgt.impl.definitions.APIDefinitionFromSwagger20; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.context.RegistryType; +import org.wso2.carbon.registry.api.Registry; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.api.Resource; +import org.wso2.carbon.registry.core.RegistryConstants; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringReader; + +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This is the util class which consists of all the functions for exporting API + */ +public class APIExportUtil { + + private static final Log log = LogFactory.getLog(APIExportUtil.class); + private static String archiveBasePath = null; + + private APIExportUtil() { + } + + /** + * Set base path where exporting archive should be generated + * + * @param path Temporary directory location + */ + public static void setArchiveBasePath(String path) { + archiveBasePath = path; + } + + /** + * Retrieve API provider + * + * @param userName User name + * @return APIProvider Provider of the supplied user name + * @throws APIExportException If an error occurs while retrieving the provider + */ + public static APIProvider getProvider(String userName) throws APIExportException { + APIProvider provider; + try { + provider = APIManagerFactory.getInstance().getAPIProvider(userName); + + if (log.isDebugEnabled()) { + log.debug("Current provider retrieved successfully"); + } + + return provider; + + } catch (APIManagementException e) { + log.error("Error while retrieving provider" + e.getMessage()); + throw new APIExportException("Error while retrieving current provider", e); + } + + } + + /** + * Retrieve registry for the current tenant + * + * @param userName user name of the tenant + * @return Registry registry of the current tenant + */ + public static Registry getRegistry(String userName) { + boolean isTenantFlowStarted = false; + String tenantDomain = MultitenantUtils.getTenantDomain(userName); + try { + if (tenantDomain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) { + isTenantFlowStarted = true; + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + } + Registry registry = CarbonContext.getThreadLocalCarbonContext(). + getRegistry(RegistryType.SYSTEM_GOVERNANCE); + + if (log.isDebugEnabled()) { + log.debug("Registry of logged in user retrieved successfully"); + } + return registry; + + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } + } + } + + /** + * This method retrieves all meta information and registry resources required for an API to + * recreate + * + * @param apiID Identifier of the exporting API + * @param userName User name of the requester + * @return HttpResponse indicating whether resource retrieval got succeed or not + * @throws APIExportException If an error occurs while retrieving API related resources + */ + public static Response retrieveApiToExport(APIIdentifier apiID, String userName) throws APIExportException { + + API apiToReturn; + String archivePath = archiveBasePath.concat(File.separator + apiID.getApiName() + "-" + + apiID.getVersion()); + //initializing provider + APIProvider provider = getProvider(userName); + //registry for the current user + Registry registry = APIExportUtil.getRegistry(userName); + + int tenantId = APIUtil.getTenantId(userName); + + //directory creation + APIExportUtil.createDirectory(archivePath); + + try { + apiToReturn = provider.getAPI(apiID); + } catch (APIManagementException e) { + log.error("Unable to retrieve API", e); + return Response.status(Response.Status.NOT_FOUND).entity("Unable to retrieve API") + .type(MediaType.APPLICATION_JSON). + build(); + } + + //export thumbnail + exportAPIThumbnail(apiID, registry); + + //export documents + List docList; + try { + docList = provider.getAllDocumentation(apiID); + } catch (APIManagementException e) { + log.error("Unable to retrieve API Documentation", e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Internal Server Error") + .type(MediaType.APPLICATION_JSON).build(); + } + + if (!docList.isEmpty()) { + exportAPIDocumentation(docList, apiID, registry); + } + + //export wsdl + String wsdlUrl = apiToReturn.getWsdlUrl(); + if (wsdlUrl != null) { + exportWSDL(apiID, registry); + } + + //export sequences + exportSequences(apiToReturn, apiID, tenantId, registry); + + //set API status to created + apiToReturn.setStatus(APIStatus.CREATED); + + //export meta information + exportMetaInformation(apiToReturn, registry); + + return Response.ok().build(); + + } + + /** + * Retrieve thumbnail image for the exporting API and store it in the archive directory + * + * @param apiIdentifier ID of the requesting API + * @param registry Current tenant registry + * @throws APIExportException If an error occurs while retrieving image from the registry or + * storing in the archive directory + */ + private static void exportAPIThumbnail(APIIdentifier apiIdentifier, Registry registry) throws APIExportException { + String thumbnailUrl = APIConstants.API_IMAGE_LOCATION + RegistryConstants.PATH_SEPARATOR + + apiIdentifier.getProviderName() + RegistryConstants.PATH_SEPARATOR + + apiIdentifier.getApiName() + RegistryConstants.PATH_SEPARATOR + + apiIdentifier.getVersion() + RegistryConstants.PATH_SEPARATOR + + APIConstants.API_ICON_IMAGE; + + InputStream imageDataStream = null; + OutputStream outputStream = null; + String archivePath = archiveBasePath.concat(File.separator + apiIdentifier.getApiName() + + "-" + apiIdentifier.getVersion()); + try { + if (registry.resourceExists(thumbnailUrl)) { + Resource icon = registry.get(thumbnailUrl); + + imageDataStream = icon.getContentStream(); + + String mediaType = icon.getMediaType(); + String extension = getThumbnailFileType(mediaType); + + if (extension != null) { + createDirectory(archivePath + File.separator + "Image"); + + outputStream = new FileOutputStream(archivePath + File.separator + "Image" + File.separator + + "icon." + extension); + + IOUtils.copy(imageDataStream, outputStream); + + if (log.isDebugEnabled()) { + log.debug("Thumbnail image retrieved successfully"); + } + } + } + } catch (IOException e) { + //Exception is ignored by logging due to the reason that Thumbnail is not essential for + // an API to be recreated + log.error("I/O error while writing API Thumbnail to file" + e.getMessage()); + } catch (RegistryException e) { + log.error("Error while retrieving API Thumbnail " + e.getMessage()); + } finally { + IOUtils.closeQuietly(imageDataStream); + IOUtils.closeQuietly(outputStream); + } + } + + /** + * Retrieve content type of the thumbnail image for setting the exporting file extension + * + * @param mediaType Media type of the thumbnail registry resource + * @return File extension for the exporting image + */ + private static String getThumbnailFileType(String mediaType) { + if (("image/png").equals(mediaType)) { + return "png"; + } else if (("image/jpg").equals(mediaType)) { + return "jpg"; + } else if ("image/jpeg".equals(mediaType)) { + return "jpeg"; + } else if (("image/bmp").equals(mediaType)) { + return "bmp"; + } else if (("image/gif").equals(mediaType)) { + return "gif"; + } else { + //api gets imported without thumbnail + log.error("Unsupported media type for icon " + mediaType); + } + + return null; + } + + /** + * Retrieve documentation for the exporting API and store it in the archive directory + * FILE, INLINE and URL documentations are handled + * + * @param apiIdentifier ID of the requesting API + * @param registry Current tenant registry + * @param docList documentation list of the exporting API + * @throws APIExportException If an error occurs while retrieving documents from the + * registry or storing in the archive directory + */ + public static void exportAPIDocumentation(List docList, APIIdentifier apiIdentifier, + Registry registry) throws APIExportException { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String archivePath = archiveBasePath.concat(File.separator + apiIdentifier.getApiName() + "-" + + apiIdentifier.getVersion()); + createDirectory(archivePath + File.separator + "Docs"); + InputStream fileInputStream = null; + OutputStream outputStream = null; + try { + for (Documentation doc : docList) { + String sourceType = doc.getSourceType().name(); + if (Documentation.DocumentSourceType.FILE.toString().equalsIgnoreCase(sourceType)) { + String fileName = doc.getFilePath().substring(doc.getFilePath(). + lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1); + String filePath = APIUtil.getDocumentationFilePath(apiIdentifier, fileName); + + //check whether resource exists in the registry + Resource docFile = registry.get(filePath); + String localFilePath = File.separator + "Docs" + File.separator + fileName; + outputStream = new FileOutputStream(archivePath + localFilePath); + fileInputStream = docFile.getContentStream(); + + IOUtils.copy(fileInputStream, outputStream); + + doc.setFilePath(localFilePath); + + if (log.isDebugEnabled()) { + log.debug(fileName + " retrieved successfully"); + } + } + } + + String json = gson.toJson(docList); + writeFile(archivePath + File.separator + "Docs" + File.separator + "docs.json", json); + + if (log.isDebugEnabled()) { + log.debug("API Documentation retrieved successfully"); + } + + } catch (IOException e) { + log.error("I/O error while writing API documentation to file" + e.getMessage()); + throw new APIExportException("I/O error while writing API documentation to file", e); + } catch (RegistryException e) { + log.error("Error while retrieving documentation " + e.getMessage()); + throw new APIExportException("Error while retrieving documentation", e); + } finally { + IOUtils.closeQuietly(fileInputStream); + IOUtils.closeQuietly(outputStream); + } + } + + /** + * Retrieve WSDL for the exporting API and store it in the archive directory + * + * @param apiIdentifier ID of the requesting API + * @param registry Current tenant registry + * @throws APIExportException If an error occurs while retrieving WSDL from the registry or + * storing in the archive directory + */ + public static void exportWSDL(APIIdentifier apiIdentifier, Registry registry) throws APIExportException { + + InputStream wsdlStream = null; + OutputStream outputStream = null; + String archivePath = archiveBasePath.concat("/" + apiIdentifier.getApiName() + "-" + + apiIdentifier.getVersion()); + + try { + String wsdlPath = APIConstants.API_WSDL_RESOURCE_LOCATION + + apiIdentifier.getProviderName() + "--" + apiIdentifier.getApiName() + + apiIdentifier.getVersion() + ".wsdl"; + if (registry.resourceExists(wsdlPath)) { + createDirectory(archivePath + File.separator + "WSDL"); + + Resource wsdl = registry.get(wsdlPath); + + wsdlStream = wsdl.getContentStream(); + + outputStream = new FileOutputStream(archivePath + File.separator + "WSDL" + File.separator + + apiIdentifier.getApiName() + "-" + apiIdentifier.getVersion() + ".wsdl"); + + IOUtils.copy(wsdlStream, outputStream); + + if (log.isDebugEnabled()) { + log.debug("WSDL file retrieved successfully"); + } + } + } catch (IOException e) { + log.error("I/O error while writing WSDL to file" + e.getMessage()); + throw new APIExportException("I/O error while writing WSDL to file", e); + } catch (RegistryException e) { + log.error("Error while retrieving WSDL " + e.getMessage()); + throw new APIExportException("Error while retrieving WSDL", e); + } finally { + IOUtils.closeQuietly(wsdlStream); + IOUtils.closeQuietly(outputStream); + } + } + + /** + * Retrieve available custom sequences for the exporting API + * + * @param api exporting API + * @param apiIdentifier ID of the requesting API + * @param registry current tenant registry + * @throws APIExportException If an error occurs while exporting sequences + */ + public static void exportSequences(API api, APIIdentifier apiIdentifier, int tenantId, Registry registry) + throws APIExportException { + + Map sequences = new HashMap(); + + if (api.getInSequence() != null) { + sequences.put(APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN, api.getInSequence()); + } + + if (api.getOutSequence() != null) { + sequences.put(APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT, api.getOutSequence()); + } + + if (api.getOutSequence() != null) { + sequences.put(APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT, api.getFaultSequence()); + } + + if (!sequences.isEmpty()) { + String archivePath = archiveBasePath.concat(File.separator + apiIdentifier.getApiName() + "-" + + apiIdentifier.getVersion()); + createDirectory(archivePath + File.separator + "Sequences"); + + String sequenceName; + String direction; + for (Map.Entry sequence : sequences.entrySet()) { + sequenceName = sequence.getValue(); + direction = sequence.getKey(); + AbstractMap.SimpleEntry sequenceDetails; + if (sequenceName != null) { + if (APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN.equalsIgnoreCase(direction)) { + sequenceDetails = getCustomSequence(sequenceName, APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN, + registry); + writeSequenceToFile(sequenceDetails, APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN, + apiIdentifier); + } else if (APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT.equalsIgnoreCase(direction)) { + sequenceDetails = getCustomSequence(sequenceName, APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT, + registry); + writeSequenceToFile(sequenceDetails, APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT, + apiIdentifier); + } else { + sequenceDetails = getCustomSequence(sequenceName, + APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT, registry); + writeSequenceToFile(sequenceDetails, APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT, + apiIdentifier); + } + } + } + } + } + + /** + * Retrieve custom sequence details from the registry + * + * @param sequenceName Name of the sequence + * @param type Sequence type + * @param registry Current tenant registry + * @return Registry resource name of the sequence and its content + * @throws APIExportException If an error occurs while retrieving registry elements + */ + private static AbstractMap.SimpleEntry getCustomSequence(String sequenceName, + String type, Registry registry) throws APIExportException { + AbstractMap.SimpleEntry sequenceDetails; + + org.wso2.carbon.registry.api.Collection seqCollection = null; + + try { + if (APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN.equals(type)) { + seqCollection = + (org.wso2.carbon.registry.api.Collection) registry.get(APIConstants.API_CUSTOM_INSEQUENCE_LOCATION); + } + else if (APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT.equals(type)) { + seqCollection = + (org.wso2.carbon.registry.api.Collection) registry.get(APIConstants.API_CUSTOM_OUTSEQUENCE_LOCATION); + } + else if(APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT.equals(type)) { + seqCollection = + (org.wso2.carbon.registry.api.Collection) registry.get(APIConstants.API_CUSTOM_FAULTSEQUENCE_LOCATION); + } + + if (seqCollection != null) { + String[] childPaths = seqCollection.getChildren(); + + for (int i = 0; i < childPaths.length; i++) { + Resource sequence = registry.get(childPaths[i]); + OMElement seqElment = APIUtil.buildOMElement(sequence.getContentStream()); + if (sequenceName.equals(seqElment.getAttributeValue(new QName("name")))) { + String sequenceFileName = sequence.getPath().substring(sequence.getPath().lastIndexOf('/')); + sequenceDetails = new AbstractMap.SimpleEntry(sequenceFileName, seqElment); + return sequenceDetails; + } + } + } + + } catch (RegistryException e) { + log.error("Error while retrieving sequence from the registry " + e.getMessage()); + throw new APIExportException("Error while retrieving sequence from the registry", e); + } catch (Exception e ) { //APIUtil.buildOMElement() throws a generic exception + log.error("Error while reading sequence content " + e.getMessage()); + throw new APIExportException("Error while reading sequence content", e); + } + + return null; + + } + + /** + * Store custom sequences in the archive directory + * + * @param sequenceDetails Details of the sequence + * @param direction Direction of the sequence "in", "out" or "fault" + * @param apiIdentifier ID of the requesting API + * @throws APIExportException If an error occurs while serializing XML stream or storing in + * archive directory + */ + private static void writeSequenceToFile(AbstractMap.SimpleEntry sequenceDetails, String direction, + APIIdentifier apiIdentifier) throws APIExportException { + OutputStream outputStream = null; + String archivePath = archiveBasePath.concat(File.separator + apiIdentifier.getApiName() + "-" + + apiIdentifier.getVersion()) + File.separator + "Sequences" + File.separator; + + String pathToExportedSequence = archivePath + direction + "-sequence" + File.separator; + String sequenceFileName = sequenceDetails.getKey(); + OMElement sequenceConfig = sequenceDetails.getValue(); + String exportedSequenceFile = pathToExportedSequence + sequenceFileName; + try { + createDirectory(pathToExportedSequence); + outputStream = new FileOutputStream(exportedSequenceFile); + sequenceConfig.serialize(outputStream); + + if (log.isDebugEnabled()) { + log.debug("Sequence retrieved successfully"); + } + + } catch (FileNotFoundException e) { + log.error("Unable to find file" + e.getMessage()); + throw new APIExportException("Unable to find file: " + exportedSequenceFile, e); + } catch (XMLStreamException e) { + log.error("Error while processing XML stream" + e.getMessage()); + throw new APIExportException("Error while processing XML stream", e); + } finally { + IOUtils.closeQuietly(outputStream); + } + } + + /** + * Create directory at the given path + * + * @param path Path of the directory + * @throws APIExportException If directory creation failed + */ + public static void createDirectory(String path) throws APIExportException { + if (path != null) { + File file = new File(path); + if (!file.exists() && !file.mkdirs()) { + log.error("Error while creating directory : " + path); + throw new APIExportException("Directory creation failed " + path); + } + } + } + + /** + * Retrieve meta information of the API to export + * URL template information are stored in swagger.json definition while rest of the required + * data are in api.json + * + * @param apiToReturn API to be exported + * @param registry Current tenant registry + * @throws APIExportException If an error occurs while exporting meta information + */ + private static void exportMetaInformation(API apiToReturn, Registry registry) throws APIExportException { + APIDefinition definitionFromSwagger20 = new APIDefinitionFromSwagger20(); + String archivePath = archiveBasePath.concat(File.separator + apiToReturn.getId().getApiName() + "-" + + apiToReturn.getId().getVersion()); + + createDirectory(archivePath + File.separator + "Meta-information"); + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String apiInJson = gson.toJson(apiToReturn); + writeFile(archivePath + File.separator + "Meta-information" + File.separator + "api.json", apiInJson); + + try { + String swaggerDefinition = definitionFromSwagger20.getAPIDefinition(apiToReturn.getId(), registry); + JsonParser parser = new JsonParser(); + JsonObject json = parser.parse(swaggerDefinition).getAsJsonObject(); + String formattedSwaggerJson = gson.toJson(json); + writeFile(archivePath + File.separator + "Meta-information" + File.separator + "swagger.json", + formattedSwaggerJson); + + if (log.isDebugEnabled()) { + log.debug("Meta information retrieved successfully"); + } + + } catch (APIManagementException e) { + log.error("Error while retrieving Swagger definition" + e.getMessage()); + throw new APIExportException("Error while retrieving Swagger definition", e); + } + } + + /** + * Write content to file + * + * @param path Location of the file + * @param content Content to be written + * @throws APIExportException If an error occurs while writing to file + */ + private static void writeFile(String path, String content) throws APIExportException { + FileWriter writer = null; + + try { + writer = new FileWriter(path); + IOUtils.copy(new StringReader(content), writer); + } catch (IOException e) { + log.error("I/O error while writing to file" + e.getMessage()); + throw new APIExportException("I/O error while writing to file", e); + } finally { + IOUtils.closeQuietly(writer); + } + + } + +} diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/utils/APIImportUtil.java b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/APIImportUtil.java new file mode 100644 index 0000000000..d0850792b6 --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/APIImportUtil.java @@ -0,0 +1,562 @@ +/* + * + * 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 apim.restful.importexport.utils; + +import apim.restful.importexport.APIExportException; +import apim.restful.importexport.APIImportExportConstants; +import apim.restful.importexport.APIImportException; +import apim.restful.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.axiom.om.OMElement; +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.Icon; +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.RegistryConstants; +import org.wso2.carbon.registry.core.Resource; + +import javax.xml.namespace.QName; +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; + +/** + * 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) { + log.error("Error in transferring files.", e); + throw new APIImportException("Error in transferring archive files. " + e.getMessage()); + } 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) { + log.error("Failed to extract archive file ", e); + throw new APIImportException("Failed to extract archive file. " + e.getMessage()); + } 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) { + log.error("Error in locating api.json file. ", e); + throw new APIImportException("Error in locating api.json file. " + e.getMessage()); + } 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) { + log.error("Error in setting API provider to logged in user. ", e); + throw new APIImportException("Error in setting API provider to logged in user. " + e.getMessage()); + } + } + + Set allowedTiers; + Set unsupportedTiersList; + + try{ + allowedTiers = provider.getTiers(); + } catch (APIManagementException e) { + log.error("Error in retrieving tiers of the provider. ", e); + throw new APIImportException("Error in retrieving tiers of the provider. " + e.getMessage()); + } + + 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 + log.error("Error in adding API to the provider. ", e); + throw new APIImportException("Error in adding API to the provider. " + e.getMessage()); + } + + //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); + 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()); + Icon apiImage = new Icon(inputStream, mimeType); + String thumbPath = APIUtil.getIconPath(importedApi.getId()); + String thumbnailUrl = provider.addIcon(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()); + Icon apiDocument = new Icon(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.addIcon(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); + //Adding in-sequence, if any + String inSequenceName = importedApi.getInSequence(); + if (inSequenceName != null && !inSequenceName.isEmpty()) { + importAPISequence(inSequenceName, registry, APIConstants.API_CUSTOM_SEQUENCE_TYPE_IN,pathToArchive, + APIImportExportConstants.IN_SEQUENCE_LOCATION); + } + + //Adding out-sequence, if any + String outSequenceName = importedApi.getOutSequence(); + if (outSequenceName != null && !outSequenceName.isEmpty()) { + importAPISequence(outSequenceName, registry, APIConstants.API_CUSTOM_SEQUENCE_TYPE_OUT,pathToArchive, + APIImportExportConstants.OUT_SEQUENCE_LOCATION); + } + + //Adding fault-sequence, if any + String faultSequenceName = importedApi.getFaultSequence(); + if (faultSequenceName != null && !faultSequenceName.isEmpty()) { + importAPISequence(faultSequenceName, registry, APIConstants.API_CUSTOM_SEQUENCE_TYPE_FAULT, pathToArchive, + APIImportExportConstants.FAULT_SEQUENCE_LOCATION); + } + } + + /** + * Import custom sequences + * + * @param sequenceName Name of the sequence + * @param registry Tenant registry + * @param direction Direction of the sequence + * @param pathToArchive Location of the extracted folder of the imported APi archive + */ + private static void importAPISequence(String sequenceName, Registry registry, String direction, + String pathToArchive, String sequenceLocation) + { + String sequenceFileLocation = pathToArchive + sequenceLocation; + File sequenceFileFolder = new File(sequenceFileLocation); + File[] fileList = sequenceFileFolder.listFiles(); + String sequenceFileName; + InputStream fileInputStream = null; + for (final File fileEntry : fileList) { + if (fileEntry.isFile()) { + try { + fileInputStream = new FileInputStream(fileEntry); + OMElement seqElement = APIUtil.buildOMElement(fileInputStream); + if (sequenceName.equals(seqElement.getAttributeValue(new QName("name")))) { + sequenceFileName = FilenameUtils.getName(fileEntry.getName()); + addSequenceToRegistry(registry, direction, sequenceFileName, + sequenceFileLocation + sequenceFileName); + } + } catch (Exception e) { + //this error is logged and ignored because sequences are optional in an API + log.error("Failed to retrieve Sequence of imported API.", e); + } finally { + IOUtils.closeQuietly(fileInputStream); + } + } + } + } + + /** + * This method adds the sequence files to the registry. + * + * @param registry the registry instance + * @param customSequenceType type of the sequence + * @param sequenceFileName name of the sequence + * @param sequenceFileLocation location of the sequence file + */ + private static void addSequenceToRegistry(Registry registry, String customSequenceType, String sequenceFileName, + String sequenceFileLocation) { + + String regResourcePath = APIConstants.API_CUSTOM_SEQUENCE_LOCATION + RegistryConstants.PATH_SEPARATOR + + customSequenceType + RegistryConstants.PATH_SEPARATOR + sequenceFileName; + 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: " + customSequenceType, 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, Sequence type: " + customSequenceType, 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) { + log.error("Error in adding Swagger definition for the API. ", e); + throw new APIImportException("Error in adding Swagger definition for the API. " + e.getMessage()); + } catch (IOException e) { + log.error("Error in importing Swagger definition for the API. ", e); + throw new APIImportException("Error in importing Swagger definition for the API. " + e.getMessage()); + } + } + + /** + * 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(); + } +} + diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/utils/ArchiveGeneratorUtil.java b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/ArchiveGeneratorUtil.java new file mode 100644 index 0000000000..4ac18fdd57 --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/ArchiveGeneratorUtil.java @@ -0,0 +1,144 @@ +/* + * + * 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 apim.restful.importexport.utils; + +import apim.restful.importexport.APIExportException; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * This class is used to generate zipped archive files + */ +public class ArchiveGeneratorUtil { + private static final Log log = LogFactory.getLog(ArchiveGeneratorUtil.class); + + private ArchiveGeneratorUtil() { + } + + /** + * Archive a provided source directory to a zipped file + * + * @param sourceDirectory Source directory + * @throws APIExportException If an error occurs while generating archive + */ + public static void archiveDirectory(String sourceDirectory) throws APIExportException { + + File directoryToZip = new File(sourceDirectory); + + List fileList = new ArrayList(); + getAllFiles(directoryToZip, fileList); + writeArchiveFile(directoryToZip, fileList); + + if (log.isDebugEnabled()) { + log.debug("Archived API generated successfully"); + } + + } + + /** + * Retrieve all the files included in the source directory to be archived + * + * @param sourceDirectory Source directory + * @param fileList List of files + */ + private static void getAllFiles(File sourceDirectory, List fileList) { + File[] files = sourceDirectory.listFiles(); + if (files != null) { + for (File file : files) { + fileList.add(file); + if (file.isDirectory()) { + getAllFiles(file, fileList); + } + } + } + } + + /** + * Generate archive file + * + * @param directoryToZip Location of the archive + * @param fileList List of files to be included in the archive + * @throws APIExportException If an error occurs while adding files to the archive + */ + private static void writeArchiveFile(File directoryToZip, List fileList) throws APIExportException { + + FileOutputStream fileOutputStream = null; + ZipOutputStream zipOutputStream = null; + + try { + fileOutputStream = new FileOutputStream(directoryToZip.getPath() + ".zip"); + zipOutputStream = new ZipOutputStream(fileOutputStream); + for (File file : fileList) { + if (!file.isDirectory()) { + addToArchive(directoryToZip, file, zipOutputStream); + } + } + + } catch (IOException e) { + log.error("I/O error while adding files to archive" + e.getMessage()); + throw new APIExportException("I/O error while adding files to archive", e); + } finally { + IOUtils.closeQuietly(zipOutputStream); + IOUtils.closeQuietly(fileOutputStream); + } + } + + /** + * Add files of the directory to the archive + * + * @param directoryToZip Location of the archive + * @param file File to be included in the archive + * @param zipOutputStream Output stream + * @throws APIExportException If an error occurs while writing files to the archive + */ + private static void addToArchive(File directoryToZip, File file, ZipOutputStream zipOutputStream) + throws APIExportException { + + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + + // Get relative path from archive directory to the specific file + String zipFilePath = file.getCanonicalPath() + .substring(directoryToZip.getCanonicalPath().length() + 1, file.getCanonicalPath().length()); + ZipEntry zipEntry = new ZipEntry(zipFilePath); + zipOutputStream.putNextEntry(zipEntry); + + IOUtils.copy(fileInputStream, zipOutputStream); + + zipOutputStream.closeEntry(); + } catch (IOException e) { + log.error("I/O error while writing files to archive" + e.getMessage()); + throw new APIExportException("I/O error while writing files to archive", e); + } finally { + IOUtils.closeQuietly(fileInputStream); + } + } +} + diff --git a/modules/api-import-export/src/main/java/apim/restful/importexport/utils/AuthenticatorUtil.java b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/AuthenticatorUtil.java new file mode 100644 index 0000000000..dbde61b102 --- /dev/null +++ b/modules/api-import-export/src/main/java/apim/restful/importexport/utils/AuthenticatorUtil.java @@ -0,0 +1,170 @@ +/* + * + * 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 apim.restful.importexport.utils; + +import apim.restful.importexport.APIExportException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.api.UserStoreManager; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; + +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.Arrays; +import java.util.List; +import java.util.StringTokenizer; + +/** + * This class provides authentication facility for importing and exporting APIs + * Basic authentication is used for this purpose + * Users with admin roles are only eligible for accessing those JAX-RS services + */ +public class AuthenticatorUtil { + + private static final String AUTHORIZATION_PROPERTY = "Authorization"; + private static final String AUTHENTICATION_SCHEME = "Basic"; + private static final Log log = LogFactory.getLog(AuthenticatorUtil.class); + private static String username; + private static String password; + + private AuthenticatorUtil() { + } + + /** + * Checks whether received credentials for accessing API is authorized for exporting and + * importing APIs + * + * @param headers HTTP headers of the received request + * @return Response indicating whether authentication and authorization for accessing API got + * succeeded + * @throws APIExportException If an error occurs while authorizing current user + */ + + public static Response authorizeUser(HttpHeaders headers) throws APIExportException { + if (!isValidCredentials(headers)) { + log.error("No username and password is provided for authentication"); + return Response.status(Response.Status.UNAUTHORIZED) + .entity("No username and password is provided for authentication").type(MediaType.APPLICATION_JSON). + build(); + + } + + try { + String tenantDomain = MultitenantUtils.getTenantDomain(username); + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true); + + UserStoreManager userstoremanager = + CarbonContext.getThreadLocalCarbonContext().getUserRealm().getUserStoreManager(); + + String tenantAwareUsername = MultitenantUtils.getTenantAwareUsername(username); + + //authenticate user provided credentials + if (userstoremanager.authenticate(tenantAwareUsername, password)) { + log.info(username + " user authenticated successfully"); + //Get admin role name of the current domain + String adminRoleName = + CarbonContext.getCurrentContext().getUserRealm().getRealmConfiguration().getAdminRoleName(); + + String[] userRoles = userstoremanager.getRoleListOfUser(tenantAwareUsername); + + //user is only authorized for exporting and importing if he is an admin of his + // domain + if (Arrays.asList(userRoles).contains(adminRoleName)) { + log.info(username + " is authorized to import and export APIs"); + return Response.ok().build(); + } else { + return Response.status(Response.Status.FORBIDDEN).entity("User Authorization " + "Failed") + .type(MediaType.APPLICATION_JSON).build(); + } + + } else { + return Response.status(Response.Status.UNAUTHORIZED).entity("User Authentication " + "Failed") + .type(MediaType.APPLICATION_JSON).build(); + } + + } catch (UserStoreException e) { + log.error("Error while accessing user configuration" + e.getMessage()); + throw new APIExportException("Error while accessing user configuration", e); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + + } + + /** + * Checks whether user has provided non blank username and password for authentication + * + * @param headers Http Headers of the request + * @return boolean Whether a user name and password has been provided for authentication + * @throws APIExportException If an error occurs while extracting username and password from + * the header + */ + private static boolean isValidCredentials(HttpHeaders headers) throws APIExportException { + + //Fetch authorization header + final List authorization = headers.getRequestHeader(AUTHORIZATION_PROPERTY); + + //If no authorization information present; block access + if (authorization == null || authorization.isEmpty()) { + return false; + } + + //Get encoded username and password + final String encodedUserPassword = authorization.get(0).replaceFirst(AUTHENTICATION_SCHEME + " ", ""); + + //Decode username and password + String usernameAndPassword; + usernameAndPassword = StringUtils.newStringUtf8(Base64.decodeBase64(encodedUserPassword.getBytes())); + + if (usernameAndPassword != null) { + //Split username and password tokens + final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":"); + + if (tokenizer.hasMoreTokens()) { + username = tokenizer.nextToken(); + } + + if (tokenizer.hasMoreTokens()) { + password = tokenizer.nextToken(); + } + + if (username != null && password != null) { + return true; + } + } + + return false; + } + + /** + * Retrieve authenticated user name for the current session + * + * @return User name + */ + public static String getAuthenticatedUserName() { + return username; + } +} diff --git a/modules/api-import-export/src/main/webapp/META-INF/MANIFEST.MF b/modules/api-import-export/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..274e1a9e53 --- /dev/null +++ b/modules/api-import-export/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Class-Path: cxf-rt-frontend-jaxrs-2.6.1.jar cxf-api-2.6.1.jar woodstox + -core-asl-4.1.2.jar stax2-api-3.1.1.jar xmlschema-core-2.0.2.jar gero + nimo-javamail_1.4_spec-1.7.1.jar wsdl4j-1.6.2.jar cxf-rt-core-2.6.1.j + ar jaxb-impl-2.1.13.jar jsr311-api-1.1.1.jar cxf-rt-bindings-xml-2.6. + 1.jar cxf-rt-transports-http-2.6.1.jar jackson-core-asl-1.8.6.jar jac + kson-mapper-asl-1.8.6.jar jackson-jaxrs-1.8.6.jar spring-web-3.0.6.RE + LEASE.jar aopalliance-1.0.jar spring-beans-3.0.6.RELEASE.jar spring-c + ore-3.0.6.RELEASE.jar spring-asm-3.0.6.RELEASE.jar commons-logging-1. + 1.1.jar spring-context-3.0.6.RELEASE.jar spring-aop-3.0.6.RELEASE.jar + spring-expression-3.0.6.RELEASE.jar + diff --git a/modules/api-import-export/src/main/webapp/META-INF/webapp-classloading.xml b/modules/api-import-export/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 0000000000..f9f4993fc3 --- /dev/null +++ b/modules/api-import-export/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,33 @@ + + + + + + + + + false + + + CXF,Carbon + diff --git a/modules/api-import-export/src/main/webapp/WEB-INF/cxf-servlet.xml b/modules/api-import-export/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 0000000000..5dc831d4da --- /dev/null +++ b/modules/api-import-export/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + diff --git a/modules/api-import-export/src/main/webapp/WEB-INF/web.xml b/modules/api-import-export/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..d7bff92bf1 --- /dev/null +++ b/modules/api-import-export/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,75 @@ + + + + + + JAX-WS/JAX-RS Webapp + + + carbon.enable.saas + * + + + + + enable.saml2.sso + true + + + + JAXServlet + JAX-WS/JAX-RS Servlet + JAX-WS/JAX-RS Endpoint + + org.apache.cxf.transport.servlet.CXFServlet + + + service-list-stylesheet + servicelist.css + + 1 + + + + JAXServlet + /* + + + + 60 + + + + + Secured Resources + /* + GET + POST + PUT + DELETE + + + + CONFIDENTIAL + + + + + diff --git a/modules/api-import-export/src/main/webapp/servicelist.css b/modules/api-import-export/src/main/webapp/servicelist.css new file mode 100644 index 0000000000..bbc4987c0a --- /dev/null +++ b/modules/api-import-export/src/main/webapp/servicelist.css @@ -0,0 +1,117 @@ +@CHARSET "ISO-8859-1"; + +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +html { + background: #efefef; +} + +body { + line-height: 1; + width:960px; + margin:auto; + background:white; + padding:10px; + box-shadow:0px 0px 5px #CCC; + font-family:"Lucida Grande","Lucida Sans","Microsoft Sans Serif", "Lucida Sans Unicode","Verdana","Sans-serif","trebuchet ms" !important; + +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; + width:960px; + border:solid 1px #ccc; +} + +table a { + font-size:12px; + color:#1e90ff; + padding:7px; +float:left; +; +} + +.heading { + font-size: 18px; + margin-top: 20px; + float:left; + color:#0067B1; + margin-bottom:20px; + padding-top:20px; +} + +.field { + font-weight: normal; + width:120px; + font-size:12px; + float:left; + padding:7px; + clear:left; +} +.value { + font-weight: bold; + font-size:12px; + float:left; + padding:7px; + clear:right; +} +.porttypename { + font-weight: bold; + font-size:14px; +} +UL { + margin-top: 0; +} +LI { + font-weight: normal; + font-size:12px; + margin-top:10px; +} + +TD { + border:1px solid #ccc; + vertical-align: text-top; + padding: 5px; +} + + diff --git a/modules/distribution/product/src/main/assembly/bin.xml b/modules/distribution/product/src/main/assembly/bin.xml index 03ff046aa2..0736df433f 100644 --- a/modules/distribution/product/src/main/assembly/bin.xml +++ b/modules/distribution/product/src/main/assembly/bin.xml @@ -534,6 +534,13 @@ **/patch0011/*.* + + ../../p2-profile/product/target/WSO2-CARBON-PATCH-4.2.0-0012 + wso2am-${pom.version}/repository/components/patches/ + + **/patch0012/*.* + + @@ -602,6 +609,10 @@ ../../p2-profile/product/target/WSO2-CARBON-PATCH-4.2.0-0010/lib wso2am-${pom.version}/lib/ + + + ../../p2-profile/product/target/WSO2-CARBON-PATCH-4.2.0-0012/dbscripts + wso2am-${pom.version}/dbscripts diff --git a/modules/distribution/product/src/main/conf/axis2.xml b/modules/distribution/product/src/main/conf/axis2.xml index 23df14ed9b..5d26edeaa4 100644 --- a/modules/distribution/product/src/main/conf/axis2.xml +++ b/modules/distribution/product/src/main/conf/axis2.xml @@ -166,10 +166,10 @@ class="org.apache.axis2.format.PlainTextFormatter"/> - - + + - - + + - + diff --git a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_auth_failure_handler_.xml b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_auth_failure_handler_.xml index 5a5213d83c..a2348de693 100644 --- a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_auth_failure_handler_.xml +++ b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_auth_failure_handler_.xml @@ -1,4 +1,5 @@ + diff --git a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_cors_request_handler_.xml b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_cors_request_handler_.xml index 503bc372ba..2f4ceb0763 100644 --- a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_cors_request_handler_.xml +++ b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_cors_request_handler_.xml @@ -1,3 +1,20 @@ + diff --git a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_throttle_out_handler_.xml b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_throttle_out_handler_.xml index 40e8124047..9b86af8852 100644 --- a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_throttle_out_handler_.xml +++ b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/_throttle_out_handler_.xml @@ -1,5 +1,6 @@ + \ No newline at end of file diff --git a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/main.xml b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/main.xml index 9063e8adbe..3d485e2126 100644 --- a/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/main.xml +++ b/modules/distribution/product/src/main/conf/synapse-configs/default/sequences/main.xml @@ -86,6 +86,7 @@ + diff --git a/modules/distribution/product/src/main/statistics/API_Manager_Analytics/analytics/am_stats_analyzer b/modules/distribution/product/src/main/statistics/API_Manager_Analytics/analytics/am_stats_analyzer index 81b8054367..b1913d5a55 100644 --- a/modules/distribution/product/src/main/statistics/API_Manager_Analytics/analytics/am_stats_analyzer +++ b/modules/distribution/product/src/main/statistics/API_Manager_Analytics/analytics/am_stats_analyzer @@ -94,4 +94,35 @@ CREATE EXTERNAL TABLE IF NOT EXISTS APIDestinationDataSummaryData (api STRING, v insert overwrite table APIDestinationDataSummaryData select api,version,apiPublisher, context,destination, sum(request) as total_request_count,hostName, year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as year, month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as month,day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as day,concat(substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,16),':00') as time from APIDestinationData where context is not NULL group by api,version,apiPublisher,context,destination,hostName,year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )), month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),hour(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),minute(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,16); + + +CREATE EXTERNAL TABLE IF NOT EXISTS APIRequestDataMinimal (key STRING, + api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,requestTime BIGINT,request INT) STORED BY + 'org.apache.hadoop.hive.cassandra.CassandraStorageHandler' WITH SERDEPROPERTIES ('wso2.carbon.datasource.name'='WSO2BAM_CASSANDRA_DATASOURCE', + "cassandra.cf.name" = "org_wso2_apimgt_statistics_request", + "cassandra.columns.mapping" = ":key,payload_api,payload_api_version,payload_context,payload_apiPublisher,payload_applicationName,payload_tenantDomain,payload_requestTime,payload_request" ); + +CREATE EXTERNAL TABLE IF NOT EXISTS APIRequestSummaryDataMinimal (api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,year SMALLINT,month SMALLINT,day SMALLINT, week INT, time STRING,success_request_count INT) STORED BY + 'org.wso2.carbon.hadoop.hive.jdbc.storage.JDBCStorageHandler' TBLPROPERTIES ( 'wso2.carbon.datasource.name'='WSO2AM_STATS_DB', + 'hive.jdbc.update.on.duplicate' = 'true', + 'hive.jdbc.primary.key.fields'='api,api_version,context,apiPublisher,applicationName,tenantDomain,time', + 'hive.jdbc.table.create.query' = 'CREATE TABLE API_THROTTLED_OUT_SUMMARY ( api VARCHAR(100), api_version VARCHAR(100),context VARCHAR(100),apiPublisher VARCHAR(100), applicationName VARCHAR(100), tenantDomain VARCHAR(100), year SMALLINT, month SMALLINT, day SMALLINT, week INT, time VARCHAR(30), success_request_count INT , throttleout_count INT, PRIMARY KEY(api,api_version,context,apiPublisher,applicationName,tenantDomain,time))' ); +insert overwrite table APIRequestSummaryDataMinimal select api,api_version,context,apiPublisher,applicationName,tenantDomain, year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as year, month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as month,day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as day,cast(requestTime/(1000 * 60 * 60 *24 * 7) as INT) as week,concat(substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13),':00:00') as time,sum(request) as success_request_count from APIRequestDataMinimal where context is not NULL group by api,api_version,context,apiPublisher,applicationName,tenantDomain,year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )), month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),cast(requestTime/(1000 * 60 * 60 *24 * 7) as INT),substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13); + + + +CREATE EXTERNAL TABLE IF NOT EXISTS APIThrottleData (key STRING, + api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,throttledTime BIGINT) STORED BY + 'org.apache.hadoop.hive.cassandra.CassandraStorageHandler' WITH SERDEPROPERTIES ('wso2.carbon.datasource.name'='WSO2BAM_CASSANDRA_DATASOURCE', + "cassandra.cf.name" = "org_wso2_apimgt_statistics_throttle", + "cassandra.columns.mapping" = ":key,payload_api,payload_api_version,payload_context,payload_apiPublisher,payload_applicationName,payload_tenantDomain,payload_throttledTime" ); + + +CREATE EXTERNAL TABLE IF NOT EXISTS APIThrottleSummaryData (api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,year SMALLINT,month SMALLINT,day SMALLINT,week INT, time STRING,throttleout_count INT) STORED BY + 'org.wso2.carbon.hadoop.hive.jdbc.storage.JDBCStorageHandler' TBLPROPERTIES ( 'wso2.carbon.datasource.name'='WSO2AM_STATS_DB', + 'hive.jdbc.update.on.duplicate' = 'true', + 'hive.jdbc.primary.key.fields'='api,api_version,context,apiPublisher,applicationName,tenantDomain,time', + 'hive.jdbc.table.create.query' = 'CREATE TABLE API_THROTTLED_OUT_SUMMARY ( api VARCHAR(100), api_version VARCHAR(100),context VARCHAR(100),apiPublisher VARCHAR(100), applicationName VARCHAR(100), tenantDomain VARCHAR(100), year SMALLINT, month SMALLINT, day SMALLINT,week INT, time VARCHAR(30), success_request_count INT , throttleout_count INT, PRIMARY KEY(api,api_version,context,apiPublisher,applicationName,tenantDomain,time))' ); + +insert overwrite table APIThrottleSummaryData select api,api_version,context,apiPublisher,applicationName,tenantDomain, year(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as year, month(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as month,day(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as day, cast(throttledTime/(1000 * 60 * 60 *24 * 7) as INT) as week, concat(substring(from_unixtime(cast(throttledTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13),':00:00') as time,count(apiPublisher) as throttleout_count from APIThrottleData where context is not NULL group by api,api_version,context,apiPublisher,applicationName,tenantDomain,year(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )), month(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),day(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),cast(throttledTime/(1000 * 60 * 60 *24 * 7) as INT),substring(from_unixtime(cast(throttledTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13); diff --git a/modules/distribution/product/src/main/statistics/API_Manager_Analytics_Oracle/analytics/am_stats_analyzer b/modules/distribution/product/src/main/statistics/API_Manager_Analytics_Oracle/analytics/am_stats_analyzer index 9c176b27b6..5984108237 100644 --- a/modules/distribution/product/src/main/statistics/API_Manager_Analytics_Oracle/analytics/am_stats_analyzer +++ b/modules/distribution/product/src/main/statistics/API_Manager_Analytics_Oracle/analytics/am_stats_analyzer @@ -94,4 +94,34 @@ CREATE EXTERNAL TABLE IF NOT EXISTS APIDestinationDataSummaryData (api STRING, v insert overwrite table APIDestinationDataSummaryData select api,version,apiPublisher, context,destination, sum(request) as total_request_count,hostName, year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as year, month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as month,day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as day,concat(substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,16),':00') as time from APIDestinationData where context is not NULL group by api,version,apiPublisher,context,destination,hostName,year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )), month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),hour(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),minute(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,16); + + +CREATE EXTERNAL TABLE IF NOT EXISTS APIRequestDataMinimal (key STRING, + api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,requestTime BIGINT,request INT) STORED BY + 'org.apache.hadoop.hive.cassandra.CassandraStorageHandler' WITH SERDEPROPERTIES ('wso2.carbon.datasource.name'='WSO2BAM_CASSANDRA_DATASOURCE', + "cassandra.cf.name" = "org_wso2_apimgt_statistics_request", + "cassandra.columns.mapping" = ":key,payload_api,payload_api_version,payload_context,payload_apiPublisher,payload_applicationName,payload_tenantDomain,payload_requestTime,payload_request" ); + +CREATE EXTERNAL TABLE IF NOT EXISTS APIRequestSummaryDataMinimal (api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,year SMALLINT,month SMALLINT,day SMALLINT, week INT, time STRING,success_request_count INT) STORED BY + 'org.wso2.carbon.hadoop.hive.jdbc.storage.JDBCStorageHandler' TBLPROPERTIES ( 'wso2.carbon.datasource.name'='WSO2AM_STATS_DB', + 'hive.jdbc.update.on.duplicate' = 'true', + 'hive.jdbc.primary.key.fields'='api,api_version,context,apiPublisher,applicationName,tenantDomain,time', + 'hive.jdbc.table.create.query' = 'CREATE TABLE API_THROTTLED_OUT_SUMMARY ( api VARCHAR2(100), api_version VARCHAR2(100),context VARCHAR2(100),apiPublisher VARCHAR2(100), applicationName VARCHAR2(100), tenantDomain VARCHAR2(100), year SMALLINT, month SMALLINT, day SMALLINT, week INT, time VARCHAR2(30), success_request_count INT , throttleout_count INT, PRIMARY KEY(api,api_version,context,apiPublisher,applicationName,tenantDomain,time))' ); +insert overwrite table APIRequestSummaryDataMinimal select api,api_version,context,apiPublisher,applicationName,tenantDomain, year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as year, month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as month,day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as day,cast(requestTime/(1000 * 60 * 60 *24 * 7) as INT) as week,concat(substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13),':00:00') as time,sum(request) as success_request_count from APIRequestDataMinimal where context is not NULL group by api,api_version,context,apiPublisher,applicationName,tenantDomain,year(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )), month(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),day(from_unixtime(cast(requestTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),cast(requestTime/(1000 * 60 * 60 *24 * 7) as INT),substring(from_unixtime(cast(requestTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13); + + +CREATE EXTERNAL TABLE IF NOT EXISTS APIThrottleData (key STRING, + api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,throttledTime BIGINT) STORED BY + 'org.apache.hadoop.hive.cassandra.CassandraStorageHandler' WITH SERDEPROPERTIES ('wso2.carbon.datasource.name'='WSO2BAM_CASSANDRA_DATASOURCE', + "cassandra.cf.name" = "org_wso2_apimgt_statistics_throttle", + "cassandra.columns.mapping" = ":key,payload_api,payload_api_version,payload_context,payload_apiPublisher,payload_applicationName,payload_tenantDomain,payload_throttledTime" ); + + +CREATE EXTERNAL TABLE IF NOT EXISTS APIThrottleSummaryData (api STRING,api_version STRING, context STRING, apiPublisher STRING,applicationName STRING,tenantDomain STRING,year SMALLINT,month SMALLINT,day SMALLINT,week INT, time STRING,throttleout_count INT) STORED BY + 'org.wso2.carbon.hadoop.hive.jdbc.storage.JDBCStorageHandler' TBLPROPERTIES ( 'wso2.carbon.datasource.name'='WSO2AM_STATS_DB', + 'hive.jdbc.update.on.duplicate' = 'true', + 'hive.jdbc.primary.key.fields'='api,api_version,context,apiPublisher,applicationName,tenantDomain,time', + 'hive.jdbc.table.create.query' = 'CREATE TABLE API_THROTTLED_OUT_SUMMARY ( api VARCHAR2(100), api_version VARCHAR2(100),context VARCHAR2(100),apiPublisher VARCHAR2(100), applicationName VARCHAR2(100), tenantDomain VARCHAR2(100), year SMALLINT, month SMALLINT, day SMALLINT,week INT, time VARCHAR2(30), success_request_count INT , throttleout_count INT, PRIMARY KEY(api,api_version,context,apiPublisher,applicationName,tenantDomain,time))' ); + +insert overwrite table APIThrottleSummaryData select api,api_version,context,apiPublisher,applicationName,tenantDomain, year(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as year, month(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as month,day(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )) as day, cast(throttledTime/(1000 * 60 * 60 *24 * 7) as INT) as week, concat(substring(from_unixtime(cast(throttledTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13),':00:00') as time,count(apiPublisher) as throttleout_count from APIThrottleData where context is not NULL group by api,api_version,context,apiPublisher,applicationName,tenantDomain,year(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )), month(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),day(from_unixtime(cast(throttledTime/1000 as BIGINT),'yyyy-MM-dd HH:mm:ss.SSS' )),cast(throttledTime/(1000 * 60 * 60 *24 * 7) as INT),substring(from_unixtime(cast(throttledTime/1000 as BIGINT), 'yyyy-MM-dd HH:mm:ss'),0,13); diff --git a/modules/distribution/product/src/main/statistics/README.txt b/modules/distribution/product/src/main/statistics/README.txt index 0522418e86..61b74a6ab7 100644 --- a/modules/distribution/product/src/main/statistics/README.txt +++ b/modules/distribution/product/src/main/statistics/README.txt @@ -137,3 +137,7 @@ drop table APIRequestSummaryData; drop table APIVersionUsageSummaryData; drop table APIResponseData; drop table APIResponseSummaryData; +drop table APIRequestDataMinimal; +drop table APIRequestSummaryDataMinimal; +drop table APIThrottleData; +drop table APIThrottleSummaryData; diff --git a/modules/distribution/resources/api_templates/velocity_template.xml b/modules/distribution/resources/api_templates/velocity_template.xml index 13998d2297..4302e0730a 100644 --- a/modules/distribution/resources/api_templates/velocity_template.xml +++ b/modules/distribution/resources/api_templates/velocity_template.xml @@ -183,6 +183,14 @@ #end #end + +#macro ( handle_query_params $type $endpoint_config ) +#set($endpoints = $endpoint_config.get("${type}_endpoints")) +#if ( $endpoints.get("url").contains("?") ) + +#end +#end + ######################## End of Macros ###################################### @@ -245,8 +253,10 @@ #end #if(($environmentType == 'sandbox') || ($environmentType =='hybrid' && ! $endpoint_config.get("production_endpoints") )) + #handle_query_params( "sandbox" $endpoint_config ) #draw_endpoint( "sandbox" $endpoint_config ) #else + #handle_query_params( "production" $endpoint_config ) #draw_endpoint( "production" $endpoint_config ) #end #if($apiStatus != 'PROTOTYPED') @@ -272,6 +282,8 @@ #else #if($endpoint_config.get("production_endpoints") && $endpoint_config.get("sandbox_endpoints")) + + #handle_query_params( "sandbox" $endpoint_config ) #draw_endpoint( "sandbox" $endpoint_config ) #elseif($endpoint_config.get("production_endpoints")) diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/pom.xml b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/pom.xml new file mode 100644 index 0000000000..df261f8a32 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/pom.xml @@ -0,0 +1,160 @@ + + + 4.0.0 + + org.wso2.carbon + org.wso2.carbon.apimgt.migrate.client + 1.7.0 + bundle + + + + wso2-nexus + WSO2 internal Repository + http://maven.wso2.org/nexus/content/groups/wso2-public/ + + true + daily + ignore + + + + wso2.releases + WSO2 internal Repository + http://maven.wso2.org/nexus/content/repositories/releases/ + + true + daily + ignore + + + + wso2.snapshots + WSO2 Snapshot Repository + http://maven.wso2.org/nexus/content/repositories/snapshots/ + + true + daily + + + false + + + + + + + + org.apache.felix + maven-scr-plugin + ${org.apache.felix.src.plugin.version} + + + generate-scr-scrdescriptor + + scr + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + + + + org.apache.felix + maven-bundle-plugin + true + ${org.apache.felix.budnle.plugin.version} + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.carbon.apimgt.migration.client.internal + + + org.apache.commons.logging.*; version=${org.wso2.carbon.logging.import.version}, + org.wso2.carbon.registry.core.* version=${org.wso2.carbon.registry.core.import.version}, + org.wso2.carbon.apimgt.impl, + *;resolution:=optional + + * + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.5.3 + + + dist + package + + attached + + + false + src/assembly/dist.xml + wso2-api-migration-client-${project.version} + + + + + + + + + + org.wso2.carbon + org.wso2.carbon.core.services + ${org.wso2.carbon.core.services.version} + + + org.wso2.carbon + org.wso2.carbon.logging + ${org.wso2.carbon.logging.version} + + + org.wso2.carbon + org.wso2.carbon.registry.core + ${org.wso2.carbon.registry.core.version} + + + org.wso2.carbon + org.wso2.carbon.utils + ${org.wso2.carbon.utils.version} + + + org.wso2.carbon + org.wso2.carbon.apimgt.impl + 1.2.2 + + + org.wso2.carbon + org.wso2.carbon.apimgt.api + 1.2.2 + + + + + UTF-8 + 1.7.2 + 2.5.3 + 4.2.0 + 4.2.0 + 1.0.4 + 4.2.0 + 4.2.0 + 1.0.1 + + + \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/assembly/dist.xml b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/assembly/dist.xml new file mode 100644 index 0000000000..e6caed26d2 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/assembly/dist.xml @@ -0,0 +1,27 @@ + + dist + + zip + + false + + + ${project.basedir} + + + README* + + + + ${project.basedir}/src/main/resources + + + + ${project.build.directory} + + + *.jar + + + + \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/APIMigrationException.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/APIMigrationException.java new file mode 100644 index 0000000000..6250855b6e --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/APIMigrationException.java @@ -0,0 +1,35 @@ +/* +* 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.migration; + +/** + * A custom exception handler class to handle all the migration exceptions + */ +public class APIMigrationException extends Exception { + + public APIMigrationException(String msg) { + super(msg); + } + + public APIMigrationException(String msg, Throwable e) { + super(msg, e); + } + + public APIMigrationException(Throwable throwable) { + super(throwable); + } +} \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom16to17.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom16to17.java new file mode 100644 index 0000000000..9308b838c7 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom16to17.java @@ -0,0 +1,388 @@ +/* +* 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.migration.client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIMgtDBUtil; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.internal.ServiceHolder; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.apimgt.migration.util.ResourceUtil; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.governance.api.generic.GenericArtifactManager; +import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; +import org.wso2.carbon.governance.api.util.GovernanceUtils; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.core.Registry; +import org.wso2.carbon.registry.core.session.UserRegistry; +import org.wso2.carbon.user.api.Tenant; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.tenant.TenantManager; +import org.wso2.carbon.utils.CarbonUtils; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathExpressionException; +import java.io.*; +import java.sql.*; +import java.util.*; + + +/** + * This class contains all the methods which is used to migrate APIs from APIManager 1.6.0 to APIManager 1.7.0. + * The migration performs in database, registry and file system + */ + +@SuppressWarnings("unchecked") +public class MigrateFrom16to17 { + + private static final Log log = LogFactory.getLog(MigrateFrom16to17.class); + private List tenantsArray; + + public MigrateFrom16to17(String tenantArguments) throws UserStoreException { + TenantManager tenantManager = ServiceHolder.getRealmService().getTenantManager(); + + if (tenantArguments != null) { // Tenant arguments have been provided so need to load specific ones + tenantArguments = tenantArguments.replaceAll("\\s",""); // Remove spaces and tabs + + tenantsArray = new ArrayList(); + + if (tenantArguments.contains(",")) { // Multiple arguments specified + String[] parts = tenantArguments.split(","); + + for (int i = 0; i < parts.length; ++i) { + if (parts[i].length() > 0) { + populateTenants(tenantManager, tenantsArray, parts[i]); + } + } + } + else { // Only single argument provided + populateTenants(tenantManager, tenantsArray, tenantArguments); + } + } else { // Load all tenants + tenantsArray = new ArrayList(Arrays.asList(tenantManager.getAllTenants())); + Tenant superTenant = new Tenant(); + superTenant.setDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + superTenant.setId(MultitenantConstants.SUPER_TENANT_ID); + tenantsArray.add(superTenant); + } + } + + private void populateTenants(TenantManager tenantManager, List tenantList, String argument) throws UserStoreException { + log.debug("Argument provided : " + argument); + + if (argument.contains("@")) { // Username provided as argument + int tenantID = tenantManager.getTenantId(argument); + + if (tenantID != -1) { + tenantList.add(tenantManager.getTenant(tenantID)); + } + else { + log.error("Tenant does not exist for username " + argument); + } + } + else { // Domain name provided as argument + Tenant[] tenants = tenantManager.getAllTenantsForTenantDomainStr(argument); + + if (tenants.length > 0) { + tenantList.addAll(Arrays.asList(tenants)); + } + else { + log.error("Tenant does not exist for domain " + argument); + } + } + } + + + /** + * This method is used to migrate all registry resources + * This migrates swagger resources and rxts + * + * @throws APIMigrationException + */ + public void registryResourceMigration() throws APIMigrationException { + swaggerMigration(); + docResourceMigration(); + rxtMigration(); + } + + + /** + * This method is used to migrate rxt + * This adds three new attributes to the api rxt + * + * @throws APIMigrationException + */ + void rxtMigration() throws APIMigrationException { + log.info("Rxt migration for API Manager 1.9.0 started."); + boolean isTenantFlowStarted = false; + for (Tenant tenant : tenantsArray) { + log.debug("Start rxtMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + try { + PrivilegedCarbonContext.startTenantFlow(); + isTenantFlowStarted = true; + + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain(), true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId(), true); + + Registry registry = getRegistry(tenant); + if (registry != null) { + GenericArtifactManager artifactManager = APIUtil.getArtifactManager(registry, APIConstants.API_KEY); + GenericArtifact[] artifacts = getGenericArtifacts(registry, artifactManager); + + if (artifacts != null && artifactManager != null) { + for (GenericArtifact artifact : artifacts) { + RegistryMigration.rxtMigration(artifactManager, artifacts); + } + } + } + else { + log.debug("No api artifacts found in registry for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + } + + catch (APIManagementException e) { + ResourceUtil.handleException("Error occurred while reading API from the artifact ", e); + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } + } + log.debug("End rxtMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + log.info("Rxt resource migration done for all the tenants"); + } + + + /** + * Doc resource migration + * + * + */ + void docResourceMigration() { + log.info("Doc migration for API Manager 1.9.0 started."); + boolean isTenantFlowStarted = false; + + for (Tenant tenant : tenantsArray) { + if (log.isDebugEnabled()) { + log.debug("Start docResourceMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + try { + PrivilegedCarbonContext.startTenantFlow(); + isTenantFlowStarted = true; + + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId()); + + Registry registry = getRegistry(tenant); + + if (registry != null) { + GenericArtifactManager artifactManager = APIUtil.getArtifactManager(registry, APIConstants.API_KEY); + GenericArtifact[] artifacts = getGenericArtifacts(registry, artifactManager); + + if (artifacts != null) { + RegistryMigration.updateDocResourceAssociation(artifacts, registry, tenant); + } + } + } catch (APIManagementException e) { + log.error("Error when getting GenericArtifactManager for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } + } + + log.debug("End docResourceMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + log.info("Doc resource migration done for all the tenants."); + } + + + /** + * This method is used to migrate swagger v1.2 resources to swagger v2.0 resource + * This reads the swagger v1.2 doc from the registry and creates swagger v2.0 doc + * + * @throws APIMigrationException + */ + void swaggerMigration() { + log.info("Swagger migration for API Manager 1.9.0 started."); + boolean isTenantFlowStarted = false; + + for (Tenant tenant : tenantsArray) { + if (log.isDebugEnabled()) { + log.debug("Start swaggerMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + try { + PrivilegedCarbonContext.startTenantFlow(); + isTenantFlowStarted = true; + + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId()); + + Registry registry = getRegistry(tenant); + + if (registry != null) { + GenericArtifactManager artifactManager = APIUtil.getArtifactManager(registry, APIConstants.API_KEY); + GenericArtifact[] artifacts = getGenericArtifacts(registry, artifactManager); + + if (artifacts != null) { + RegistryMigration.swagger12Migration(artifacts, registry, tenant); + } + } + } catch (APIManagementException e) { + log.error("Error when getting GenericArtifactManager for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } + } + + log.debug("End swaggerMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + log.info("Swagger resource migration done for all the tenants."); + } + + private Registry getRegistry(Tenant tenant) { + log.debug("Calling getRegistry"); + Registry registry = null; + + try { + String adminName = ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getRealmConfiguration().getAdminUserName(); + log.debug("Tenant admin username : " + adminName); + registry = ServiceHolder.getRegistryService().getGovernanceUserRegistry(adminName, tenant.getId()); + ServiceHolder.getTenantRegLoader().loadTenantRegistry(tenant.getId()); + } catch (UserStoreException e) { + log.error("Error occurred while reading tenant information of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (RegistryException e) { + log.error("Error occurred while accessing the registry of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } + + return registry; + } + + + private GenericArtifact[] getGenericArtifacts(Registry registry, GenericArtifactManager manager) { + log.debug("Calling getGenericArtifacts"); + GenericArtifact[] artifacts = null; + + try { + if (GovernanceUtils.findGovernanceArtifactConfiguration(Constants.API, registry) != null) { + GovernanceUtils.loadGovernanceArtifacts((UserRegistry) registry); + artifacts = manager.getAllGenericArtifacts(); + + log.debug("Total number of api artifacts : " + artifacts.length); + } + else { + log.debug("API artifacts do not exist in registry"); + } + + } catch (RegistryException e) { + log.error("Error occurred when getting GenericArtifacts from registry", e); + } + + return artifacts; + } + + + /** + * This method is used to migrate all the file system components + * such as sequences and synapse files + * + * @throws APIMigrationException + */ + public void fileSystemMigration() throws APIMigrationException { + synapseAPIMigration(); + } + + + /** + * This method is used to migrate synapse files + * This changes the synapse api and add the new handlers + * + * @throws APIMigrationException + */ + + void synapseAPIMigration() { + String repository = CarbonUtils.getCarbonRepository(); + String tenantRepository = CarbonUtils.getCarbonTenantsDirPath(); + for (Tenant tenant : tenantsArray) { + log.debug("Start synapseAPIMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + String apiFilePath; + if (tenant.getId() != MultitenantConstants.SUPER_TENANT_ID) { + apiFilePath = tenantRepository + "/" + tenant.getId() + + "/synapse-configs/default/api"; + } else { + apiFilePath = repository + "synapse-configs/default/api"; + } + File APIFiles = new File(apiFilePath); + File[] synapseFiles = APIFiles.listFiles(); + + if (synapseFiles == null) { + log.debug("No api folder " + apiFilePath + " exists for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + continue; + } + + for (File synapseFile : synapseFiles) { + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docFactory.setNamespaceAware(true); + + try { + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(synapseFile); + + doc.getDocumentElement().normalize(); + + Element rootElement = doc.getDocumentElement(); + + if (Constants.SYNAPSE_API_ROOT_ELEMENT.equals(rootElement.getNodeName()) && + rootElement.hasAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VERSION)) { + SynapseMigration.modifyGoogleAnalyticsTrackingHandler(synapseFile, doc); + } + + + } catch (ParserConfigurationException e) { + log.error("Parsing exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (SAXException e) { + log.error("SAX exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (IOException e) { + log.error("IO exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (XPathExpressionException e) { + log.error("XPathExpression exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (TransformerException e) { + log.error("Transformer exception encountered for " + synapseFile.getAbsolutePath(), e); + } + } + + log.debug("End synapseAPIMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + } +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java new file mode 100644 index 0000000000..a8949f1140 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java @@ -0,0 +1,206 @@ +/* +* 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.migration.client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.apimgt.migration.util.ResourceUtil; +import org.wso2.carbon.utils.CarbonUtils; +import org.wso2.carbon.utils.dbcreator.DatabaseCreator; + +import javax.sql.DataSource; +import java.io.*; +import java.sql.*; +import java.util.StringTokenizer; + +public class MigrationDBCreator extends DatabaseCreator { + + private static final Log log = LogFactory.getLog(MigrationDBCreator.class); + private DataSource dataSource; + private String delimiter = ";"; + private Connection connection = null; + Statement statement; + + public MigrationDBCreator(DataSource dataSource) { + super(dataSource); + this.dataSource = dataSource; + } + + @Override + protected String getDbScriptLocation(String databaseType) { + String scriptName = databaseType + ".sql"; + String resourcePath = CarbonUtils.getCarbonHome() + "/dbscripts/migration-1.8.0_to_1.9.0/"; + if (log.isDebugEnabled()) { + log.debug("Loading database script :" + scriptName); + } + return resourcePath + scriptName; + } + + @Override + public void createRegistryDatabase() throws SQLException, APIMigrationException { + try { + connection = dataSource.getConnection(); + connection.setAutoCommit(false); + statement = connection.createStatement(); + executeSQLScript(); + connection.commit(); + if (log.isTraceEnabled()) { + log.trace("Registry tables are created successfully."); + } + } catch (SQLException e) { + ResourceUtil.handleException("Error occurred while migrating the database", e); + } catch (Exception e) { + /* executeSQLScript throws generic Exception because DatabaseCreator.getDatabaseType superclass throws */ + ResourceUtil.handleException("Error occurred while executing sql script", e); + } finally { + if (connection != null) { + connection.close(); + } + + } + } + + + //org.wso2.carbon.utils.dbcreator.DatabaseCreator.getDatabaseType throws generic Exception + private void executeSQLScript() throws Exception { + String databaseType = DatabaseCreator.getDatabaseType(this.connection); + boolean keepFormat = false; + if (Constants.DB_TYPE_ORACLE.equals(databaseType)) { + delimiter = "/"; + } else if (Constants.DB_TYPE_DB2.equals(databaseType)) { + delimiter = "/"; + } else if (Constants.DB_TYPE_OPENEDGE.equals(databaseType)) { + delimiter = "/"; + keepFormat = true; + } + + String dbscriptName = getDbScriptLocation(databaseType); + + StringBuffer sql = new StringBuffer(); + BufferedReader reader = null; + + try { + InputStream is = new FileInputStream(dbscriptName); + reader = new BufferedReader(new InputStreamReader(is, "UTF8")); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (!keepFormat) { + if (line.startsWith("//")) { + continue; + } + if (line.startsWith("--")) { + continue; + } + StringTokenizer st = new StringTokenizer(line); + if (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("REM".equalsIgnoreCase(token)) { + continue; + } + } + } + sql.append(keepFormat ? "\n" : " ").append(line); + + // SQL defines "--" as a comment to EOL + // and in Oracle it may contain a hint + // so we cannot just remove it, instead we must end it + if (!keepFormat && line.indexOf("--") >= 0) { + sql.append("\n"); + } + if ((checkStringBufferEndsWith(sql, delimiter))) { + executeSQL(sql.substring(0, sql.length() - delimiter.length())); + sql.replace(0, sql.length(), ""); + } + } + // Catch any statements not followed by ; + if (sql.length() > 0) { + executeSQL(sql.toString()); + } + } catch (IOException e) { + log.error("Error occurred while executing SQL script for creating registry database", e); + throw new APIMigrationException("Error occurred while executing SQL script for creating registry database", e); + + } finally { + if (reader != null) { + reader.close(); + } + } + } + + + private void executeSQL(String sql) throws APIMigrationException { + // Check and ignore empty statements + if ("".equals(sql.trim())) { + return; + } + + ResultSet resultSet = null; + try { + if (log.isDebugEnabled()) { + log.debug("SQL : " + sql); + } + + boolean returnedValue; + int updateCount; + int updateCountTotal = 0; + returnedValue = statement.execute(sql); + updateCount = statement.getUpdateCount(); + resultSet = statement.getResultSet(); + do { + if (!returnedValue && updateCount != -1) { + updateCountTotal += updateCount; + } + returnedValue = statement.getMoreResults(); + if (returnedValue) { + updateCount = statement.getUpdateCount(); + resultSet = statement.getResultSet(); + } + } while (returnedValue); + + if (log.isDebugEnabled()) { + log.debug(sql + " : " + updateCountTotal + " rows affected"); + } + SQLWarning warning = connection.getWarnings(); + while (warning != null) { + log.debug(warning + " sql warning"); + warning = warning.getNextWarning(); + } + connection.clearWarnings(); + } catch (SQLException e) { + if (e.getSQLState().equals("X0Y32") || e.getSQLState().equals("42710")) { + // eliminating the table already exception for the derby and DB2 database types + if (log.isDebugEnabled()) { + log.info("Table Already Exists. Hence, skipping table creation"); + } + } else { + throw new APIMigrationException("Error occurred while executing : " + sql, e); + } + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + log.error("Error occurred while closing result set.", e); + } + } + } + } + +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/RegistryMigration.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/RegistryMigration.java new file mode 100644 index 0000000000..ac787a46c3 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/RegistryMigration.java @@ -0,0 +1,554 @@ +/* +* 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.migration.client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +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.Documentation; +import org.wso2.carbon.apimgt.api.model.URITemplate; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.internal.ServiceHolder; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.apimgt.migration.util.ResourceUtil; +import org.wso2.carbon.governance.api.exception.GovernanceException; +import org.wso2.carbon.governance.api.generic.GenericArtifactManager; +import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.core.*; +import org.wso2.carbon.user.api.Tenant; +import org.wso2.carbon.user.api.UserStoreException; + +import java.io.UnsupportedEncodingException; +import java.util.*; + +/** + * Created by uvindra on 8/8/15. + */ +public class RegistryMigration { + private static final Log log = LogFactory.getLog(RegistryMigration.class); + + public static void updateDocResourceAssociation(GenericArtifact[] artifacts, Registry registry, Tenant tenant) { + log.debug("Calling updateDocResourceAssociation"); + for (GenericArtifact artifact : artifacts) { + API api = getAPI(artifact); + + if (api != null) { + APIIdentifier apiIdentifier = api.getId(); + String apiName = apiIdentifier.getApiName(); + String apiVersion = apiIdentifier.getVersion(); + String apiProviderName = apiIdentifier.getProviderName(); + APIIdentifier apiIdentfier = api.getId(); + + String apiResourcePath = APIUtil.getAPIPath(apiIdentfier); + try{ + Association[] docAssociations = registry.getAssociations(apiResourcePath, "document"); + for (Association association : docAssociations) { + String docPath = association.getDestinationPath(); + + Resource docResource = registry.get(docPath); + GenericArtifactManager docArtifactManager = new GenericArtifactManager(registry, + APIConstants.DOCUMENTATION_KEY); + GenericArtifact docArtifact = docArtifactManager.getGenericArtifact( + docResource.getUUID()); + String docFilePath = docArtifact.getAttribute(APIConstants.DOC_FILE_PATH); + Documentation doc = APIUtil.getDocumentation(docArtifact); + if (Documentation.DocumentSourceType.FILE.equals(doc.getSourceType())) { + if(docFilePath != null && !docFilePath.equals("")){ + //The docFilePatch comes as /t/tenanatdoman/registry/resource/_system/governance/apimgt/applicationdata.. + //We need to remove the /t/tenanatdoman/registry/resource/_system/governance section to set permissions. + int startIndex = docFilePath.indexOf("governance") + "governance".length(); + String filePath = docFilePath.substring(startIndex, docFilePath.length()); + if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".") == -1) { + Resource resource = registry.get(filePath); + resource.setMediaType("text/plain"); + registry.put(filePath, resource); + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".wsdl") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/api-wsdl"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".pdf") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/pdf"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".xl") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/vnd.ms-excel"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".ppt") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/vnd.ms-powerpoint"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".xml") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/xml"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".js") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/javascript"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".css") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("text/css"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".csv") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("text/csv"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".html") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("text/html"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".json") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/json"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".png") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("image/png"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".ttf") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/x-font-ttf"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".eot") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/vnd.ms-fontobject"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".woff") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/font-woff"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".otf") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/x-font-otf"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".zip") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/zip"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".xhtml") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("application/xhtml+xml"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".txt") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("text/plain"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".png") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("image/png"); + registry.put(filePath, resource); + } + } else if (filePath.split(RegistryConstants.PATH_SEPARATOR + "files" + RegistryConstants.PATH_SEPARATOR)[1].indexOf(".jpeg") > -1) { + String resourcePath = "_system" + RegistryConstants.PATH_SEPARATOR + "governance" + filePath; + if (registry.resourceExists(resourcePath)) { + Resource resource = registry.get(filePath); + resource.setMediaType("image/jpeg"); + registry.put(filePath, resource); + } + } + + registry.copy(filePath, filePath); + registry.addAssociation(docArtifact.getPath(), filePath, + APIConstants.DOCUMENTATION_FILE_ASSOCIATION); + } + } + } + } catch (RegistryException e) { + log.error("Registry error encountered for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (APIManagementException e) { + log.error("Error occurred while creating swagger v2.0 document for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } + } + } + } + + public static void rxtMigration(GenericArtifactManager manager, GenericArtifact[] artifacts) { + for (GenericArtifact artifact : artifacts) { + try { + artifact.setAttribute(APIConstants.PROTOTYPE_OVERVIEW_IMPLEMENTATION, APIConstants.IMPLEMENTATION_TYPE_ENDPOINT); + + manager.updateGenericArtifact(artifact); + + } catch (RegistryException e) { + log.error("Registry error encountered when updating rxt", e); + } + } + + } + + public static void swagger12Migration(GenericArtifact[] artifacts, Registry registry, Tenant tenant) { + for (GenericArtifact artifact : artifacts) { + API api = getAPI(artifact); + + if (api != null) { + APIIdentifier apiIdentifier = api.getId(); + try { + createSwagger12Resources(artifact, registry, api, tenant); + + updateSwagger12ResourcesUsingSwagger11Doc(apiIdentifier, registry); + } catch (UserStoreException e) { + log.error("UserStoreException thrown when migrating swagger for api "+ api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (ParseException e) { + log.error("ParseException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (APIManagementException e) { + log.error("APIManagementException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (RegistryException e) { + log.error("RegistryException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (UnsupportedEncodingException e) { + log.error("UnsupportedEncodingException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (APIMigrationException e) { + log.error("APIMigrationException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } + } + } + } + + /** + * create swagger 1.2 resources + * @param artifact + * @param registry + * @param api + * @throws APIManagementException + * @throws RegistryException + * @throws UserStoreException + */ + public static void createSwagger12Resources(GenericArtifact artifact, Registry registry, + API api, Tenant tenant) throws UserStoreException, APIManagementException, ParseException { + + JSONParser parser = new JSONParser(); + String pathJsonTemplate = "{\n \"path\": \"\",\n \"operations\": []\n}"; + String operationJsonTemplate = "{\n \"method\": \"\",\n \"parameters\": []\n}"; + + // for apidoc + String apiJsonTemplate = "{\n \"apiVersion\": \"\",\n \"swaggerVersion\": \"1.2\",\n \"apis\": [],\n \"info\": {\n \"title\": \"\",\n \"description\": \"\",\n \"termsOfServiceUrl\": \"\",\n \"contact\": \"\",\n \"license\": \"\",\n \"licenseUrl\": \"\"\n },\n \"authorizations\": {\n \"oauth2\": {\n \"type\": \"oauth2\",\n \"scopes\": []\n }\n }\n}"; + + // for each resource + // String apiResourceJsontemplate = + // "{\n \"apiVersion\": \"\",\n \"swaggerVersion\": \"1.2\",\n \"resourcePath\":\"\",\n \"apis\": [],\n \"info\": {\n \"title\": \"\",\n \"description\": \"\",\n \"termsOfServiceUrl\": \"\",\n \"contact\": \"\",\n \"license\": \"\",\n \"licenseUrl\": \"\"\n },\n \"authorizations\": {\n \"oauth2\": {\n \"type\": \"oauth2\",\n \"scopes\": []\n }\n }\n}"; + String apiResourceJsontemplate = "{\n \"apiVersion\": \"\",\n \"swaggerVersion\": \"1.2\",\n \"resourcePath\":\"\",\n \"apis\": [] \n}"; + + //Auth Types + HashMap auth_types = new HashMap(); + auth_types.put("None","None"); + auth_types.put("Application_User","Application User"); + auth_types.put("Application","Application"); + auth_types.put("Any","Application & Application User"); + + JSONObject mainAPIJson; + try { + String apiVersion = artifact + .getAttribute(APIConstants.API_OVERVIEW_VERSION); + + Set uriTemplates = api.getUriTemplates(); + Map> resourceNamepaths = new HashMap>(); + Map> resourcePathJSONs = new HashMap>(); + + for (URITemplate template : uriTemplates) { + + String path = template.getUriTemplate(); + + if (path == null) { + log.error("URI Template does not exist for api "+ api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + continue; + } + + if (path.equals("/")) { + path = "/*"; + } + List resourcePaths; + int resourceNameEndIndex = path.indexOf("/", 1); + String resourceName = "/default"; + if(resourceNameEndIndex != -1) { + resourceName = path.substring(1, resourceNameEndIndex); + } + + if(!resourceName.startsWith("/")) { + resourceName = "/" + resourceName; + } + + if(resourceNamepaths.get(resourceName) != null) { + resourcePaths = resourceNamepaths.get(resourceName); + if (!resourcePaths.contains(path)) { + resourcePaths.add(path); + } + //verbs comes as a [POST, GET] type of a string + String[] httpVerbs = template.getMethodsAsString().split(" "); + String[] authtypes = template.getAuthTypeAsString().split(" "); + String[] tries = template.getThrottlingTiersAsString().split(" "); + + for(int j = 0; j < httpVerbs.length ; j ++) { + final JSONObject operationJson = (JSONObject) parser.parse(operationJsonTemplate); + operationJson.put("method", httpVerbs[j]); + operationJson.put("auth_type", auth_types.get(authtypes[j])); + operationJson.put("throttling_tier", tries[j]); + + if(resourcePathJSONs.get(path) != null) { + resourcePathJSONs.get(path).add(operationJson); + + } else { + resourcePathJSONs.put(path, new ArrayList() {{ + add(operationJson); + }}); + } + } + resourceNamepaths.put(resourceName, resourcePaths); + } else { + resourcePaths = new ArrayList(); + resourcePaths.add(path); + + //verbs comes as a [POST, GET] type of a string + String[] httpVerbs = template.getMethodsAsString().split(" "); + String[] authtypes = template.getAuthTypeAsString().split(" "); + String[] tries = template.getThrottlingTiersAsString().split(" "); + + for(int j = 0; j < httpVerbs.length ; j ++) { + final JSONObject operationJson = (JSONObject) parser.parse(operationJsonTemplate); + operationJson.put("method", httpVerbs[j]); + operationJson.put("auth_type", auth_types.get(authtypes[j])); + operationJson.put("throttling_tier", tries[j]); + + if(resourcePathJSONs.get(path) != null) { + resourcePathJSONs.get(path).add(operationJson); + + } else { + resourcePathJSONs.put(path, new ArrayList() {{ + add(operationJson); + }}); + } + } + + resourceNamepaths.put(resourceName, resourcePaths); + } + } + + //list to store the api array objects + List apiArray = new ArrayList(); + + for (Map.Entry> entry : resourcePathJSONs + .entrySet()) { + String resourcePath = entry.getKey(); + JSONObject pathJson = (JSONObject) parser + .parse(pathJsonTemplate); + pathJson.put("path", resourcePath); + List methodJsons = entry.getValue(); + for (JSONObject methodJson : methodJsons) { + JSONArray operations = (JSONArray) pathJson + .get("operations"); + operations.add(methodJson); + } + + apiArray.add(pathJson); + } + + /** + * create only one resource doc for all the resources. name it as 'resources' + */ + // create resources in the registry + APIIdentifier apiIdentfier = api.getId(); + String apiDefinitionFilePath = APIUtil.getSwagger12DefinitionFilePath(apiIdentfier.getApiName(), + apiIdentfier.getVersion(),apiIdentfier.getProviderName()); + + String resourceName = Constants.API_DOC_12_ALL_RESOURCES_DOC; + JSONObject resourcesObj = (JSONObject) parser.parse(apiResourceJsontemplate); + resourcesObj.put("apiVersion", apiVersion); + resourcesObj.put("resourcePath", "/" + resourceName); + JSONArray apis = (JSONArray) resourcesObj.get("apis"); + //add all the apis to single one + for(JSONObject arraObj : apiArray){ + apis.add(arraObj); + } + String registryRes = apiDefinitionFilePath + + RegistryConstants.PATH_SEPARATOR + resourceName; + createResource(registry, resourcesObj.toJSONString(), registryRes, api,tenant); + + // create api-doc file in the 1.2 resource location + + mainAPIJson = (JSONObject) parser.parse(apiJsonTemplate); + mainAPIJson.put("apiVersion", apiVersion); + ((JSONObject)mainAPIJson.get("info")).put("description", "Available resources"); + ((JSONObject)mainAPIJson.get("info")).put("title", artifact.getAttribute(APIConstants.API_OVERVIEW_NAME)); + + JSONArray apis1 = (JSONArray) mainAPIJson.get("apis"); + JSONObject pathjob = new JSONObject(); + pathjob.put("path", "/" + resourceName); + pathjob.put("description", "All resources for the api"); + apis1.add(pathjob); + + + createResource(registry, mainAPIJson.toJSONString(), + apiDefinitionFilePath + + APIConstants.API_DOC_1_2_RESOURCE_NAME, api, tenant); + + } catch (GovernanceException e) { + String msg = "Failed to get API fro artifact "; + throw new APIManagementException(msg, e); + } catch (ParseException e) { + throw new APIManagementException( + "Error while generating swagger 1.2 resource for api ", e); + } + + } + + /** + * save create resource at the given location and set permission + * @param re + * @param content + * @param resourcePath + * @param api + * @throws UserStoreException + * @throws RegistryException + * @throws APIManagementException + */ + private static void createResource(Registry re, String content, String resourcePath, API api, Tenant tenant) throws UserStoreException{ + try { + Resource docContent = re.newResource(); + docContent.setContent(content); + docContent.setMediaType("text/plain"); + re.put(resourcePath, docContent); + + ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getAuthorizationManager().authorizeRole(APIConstants.ANONYMOUS_ROLE, + "_system/governance" + resourcePath, + ActionConstants.GET); + } catch (RegistryException e) { + String msg = "Failed to add the API Definition content of : " + + APIConstants.API_DEFINITION_DOC_NAME + " of API :" + api.getId().getApiName(); + log.error(msg); + } + } + + /** + * Update the swagger 1.2 resources using swagger 1.1 doc + * @param apiIdentfier + * @param registry + * @throws APIManagementException + * @throws RegistryException + */ + private static void updateSwagger12ResourcesUsingSwagger11Doc(APIIdentifier apiIdentfier, Registry registry) + throws APIManagementException, RegistryException, UnsupportedEncodingException, APIMigrationException { + + String apiDef11Path = + ResourceUtil.getSwagger11ResourceLocation(apiIdentfier.getApiName(), + apiIdentfier.getVersion()); + + if (!registry.resourceExists(apiDef11Path)) { + throw new APIMigrationException("Swagger 1.1 document at " + apiDef11Path + " does not exist"); + } + + Resource apiDef11 = registry.get(apiDef11Path); + + String apiDef11Json = new String((byte[]) apiDef11.getContent(), "UTF8"); + + String swagger12location = + ResourceUtil.getSwagger12ResourceLocation(apiIdentfier.getApiName(), + apiIdentfier.getVersion(), + apiIdentfier.getProviderName()); + + if (!registry.resourceExists(swagger12location)) { + throw new APIMigrationException("Swagger 1.2 document at " + swagger12location + " does not exist"); + } + + Resource swagger12Res = registry.get(swagger12location); + String[] resourcePaths = (String[]) swagger12Res.getContent(); + + try { + ResourceUtil.updateAPISwaggerDocs(apiDef11Json, resourcePaths, registry); + } catch (ParseException e) { + throw new APIManagementException("Unable to parse registry resource", e); + } + + } + + + private static API getAPI(GenericArtifact artifact) { + log.debug("Calling getAPI"); + API api = null; + + try { + api = APIUtil.getAPI(artifact); + } catch (APIManagementException e) { + log.error("Error when getting api artifact " + artifact.getId() + " from registry", e); + } + + return api; + } +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/SynapseMigration.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/SynapseMigration.java new file mode 100644 index 0000000000..eb19ec6368 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/SynapseMigration.java @@ -0,0 +1,87 @@ +package org.wso2.carbon.apimgt.migration.client; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import java.io.File; +import java.io.IOException; + +public class SynapseMigration { + private static final Log log = LogFactory.getLog(SynapseMigration.class); + + /** + * method to add property element to the existing google analytics tracking + * handler + * + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + * @throws XPathExpressionException + * @throws TransformerException + */ + public static void modifyGoogleAnalyticsTrackingHandler(File api, Document xmlDocument) + throws + TransformerException, XPathExpressionException { + // current handler element + String expression = "//handler[@class='org.wso2.carbon.apimgt.usage.publisher." + + "APIMgtGoogleAnalyticsTrackingHandler']"; + XPath xPath = XPathFactory.newInstance().newXPath(); + NodeList nodeList = (NodeList) xPath.compile(expression).evaluate( + xmlDocument, XPathConstants.NODESET); + Element oldHandlerElem = (Element) nodeList.item(0); + + /* + * Replace + * + * with + * + * + * + */ + + if (oldHandlerElem != null) { + // new handler to replace the old one + Element newHandlerElem = xmlDocument.createElement("handler"); + newHandlerElem.setAttribute("class", + "org.wso2.carbon.apimgt.usage.publisher." + + "APIMgtGoogleAnalyticsTrackingHandler"); + // child element for the handler + Element propertyElem = xmlDocument.createElement("property"); + propertyElem.setAttribute("name", "configKey"); + propertyElem.setAttribute("value", + "gov:/apimgt/statistics/ga-config.xml"); + + newHandlerElem.appendChild(propertyElem); + + Element root = xmlDocument.getDocumentElement(); + NodeList handlersNodelist = root.getElementsByTagName("handlers"); + Element handlers = (Element) handlersNodelist.item(0); + // replace old handler with the new one + handlers.replaceChild(newHandlerElem, oldHandlerElem); + + // write the content into xml file + TransformerFactory transformerFactory = TransformerFactory + .newInstance(); + Transformer transformer = transformerFactory.newTransformer(); + DOMSource source = new DOMSource(xmlDocument); + StreamResult result = new StreamResult(api); + transformer.transform(source, result); + log.debug("Updated api: " + api.getName()); + } + + } +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java new file mode 100644 index 0000000000..52d4e94e9c --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java @@ -0,0 +1,263 @@ +/* +* 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.migration.client.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; +import org.wso2.carbon.apimgt.impl.utils.APIMgtDBUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.MigrateFrom16to17; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.registry.core.service.RegistryService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.service.RealmService; +import org.wso2.carbon.utils.CarbonUtils; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; + + +/** + * @scr.component name="org.wso2.carbon.apimgt.migration.client" immediate="true" + * @scr.reference name="realm.service" + * interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1" + * policy="dynamic" bind="setRealmService" unbind="unsetRealmService" + * @scr.reference name="registry.service" + * interface="org.wso2.carbon.registry.core.service.RegistryService" cardinality="1..1" + * policy="dynamic" bind="setRegistryService" unbind="unsetRegistryService" + * @scr.reference name="registry.core.dscomponent" + * interface="org.wso2.carbon.registry.core.service.RegistryService" cardinality="1..1" + * policy="dynamic" bind="setRegistryService" unbind="unsetRegistryService" + * @scr.reference name="tenant.registryloader" interface="org.wso2.carbon.registry.core.service.TenantRegistryLoader" cardinality="1..1" + * policy="dynamic" bind="setTenantRegistryLoader" unbind="unsetTenantRegistryLoader" + * @scr.reference name="apim.configuration" interface="org.wso2.carbon.apimgt.impl.APIManagerConfigurationService" cardinality="1..1" + * policy="dynamic" bind="setApiManagerConfig" unbind="unsetApiManagerConfig" + */ + +@SuppressWarnings("unused") +public class APIMMigrationServiceComponent { + + private static final Log log = LogFactory.getLog(APIMMigrationServiceComponent.class); + + /** + * Method to activate bundle. + * + * @param context OSGi component context. + */ + protected void activate(ComponentContext context) { + boolean isCorrectProductVersion = false; + try { + APIMgtDBUtil.initialize(); + } catch (Exception e) { + //APIMgtDBUtil.initialize() throws generic exception + log.error("Error occurred while initializing DB Util ", e); + } + + // Product and version validation + File carbonXmlConfig = new File(CarbonUtils.getServerXml()); + + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + + try { + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(carbonXmlConfig); + + doc.getDocumentElement().normalize(); + + NodeList nameNodes = doc.getElementsByTagName("Name"); + + if (nameNodes.getLength() > 0) { + Element name = (Element) nameNodes.item(0); + if (Constants.APIM_PRODUCT_NAME.equals(name.getTextContent())) { + NodeList versionNodes = doc.getElementsByTagName("Version"); + + if (versionNodes.getLength() > 0) { + Element version = (Element) versionNodes.item(0); + if (Constants.VERSION_1_7.equals(version.getTextContent())) { + isCorrectProductVersion = true; + } + } + } + } + } catch (ParserConfigurationException e) { + log.error("ParserConfigurationException when processing carbon.xml", e); + } catch (SAXException e) { + log.error("SAXException when processing carbon.xml", e); + } catch (IOException e) { + log.error("IOException when processing carbon.xml", e); + } + + String tenants = System.getProperty(Constants.ARG_MIGRATE_TENANTS); + boolean migrateAll = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_ALL)); + boolean isRegistryMigration = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_REG)); + boolean isFileSystemMigration = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_FILE_SYSTEM)); + + try { + if (isCorrectProductVersion) { + log.info("Migrating WSO2 API Manager " + Constants.PREVIOUS_VERSION + " to WSO2 API Manager " + Constants.VERSION_1_7); + + // Create a thread and wait till the APIManager DBUtils is initialized + + MigrateFrom16to17 migrateFrom16to17 = new MigrateFrom16to17(tenants); + + boolean isArgumentValid = false; + + //Default operation will migrate all three types of resources + if (migrateAll) { + log.info("Migrating WSO2 API Manager " + Constants.PREVIOUS_VERSION + " resources to WSO2 API Manager " + Constants.VERSION_1_7); + migrateFrom16to17.registryResourceMigration(); + migrateFrom16to17.fileSystemMigration(); + isArgumentValid = true; + } else { + //Only performs registry migration + if (isRegistryMigration) { + log.info("Migrating WSO2 API Manager " + Constants.PREVIOUS_VERSION + " registry resources to WSO2 API Manager " + Constants.VERSION_1_7); + migrateFrom16to17.registryResourceMigration(); + isArgumentValid = true; + } + //Only performs file system migration + if (isFileSystemMigration) { + log.info("Migrating WSO2 API Manager " + Constants.PREVIOUS_VERSION + " file system resources to WSO2 API Manager " + Constants.VERSION_1_7); + migrateFrom16to17.fileSystemMigration(); + isArgumentValid = true; + } + } + + if (isArgumentValid) { + log.info("API Manager " + Constants.PREVIOUS_VERSION + " to " + Constants.VERSION_1_7 + " migration successfully completed"); + } + } else { + log.error("Migration client installed in incompatible product version. This migration client is only compatible with " + + Constants.APIM_PRODUCT_NAME + " " + Constants.VERSION_1_7 + ". Please verify the product/version in use."); + } + } catch (APIMigrationException e) { + log.error("API Management exception occurred while migrating", e); + } catch (UserStoreException e) { + log.error("User store exception occurred while migrating", e); + } catch (Exception e) { + log.error("Generic exception occurred while migrating", e); + } catch (Throwable t) { + log.error("Throwable error", t); + } + log.info("WSO2 API Manager migration component successfully activated."); + } + + /** + * Method to deactivate bundle. + * + * @param context OSGi component context. + */ + protected void deactivate(ComponentContext context) { + log.info("WSO2 API Manager migration bundle is deactivated"); + } + + /** + * Method to set registry service. + * + * @param registryService service to get tenant data. + */ + protected void setRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { + log.debug("Setting RegistryService for WSO2 API Manager migration"); + } + ServiceHolder.setRegistryService(registryService); + } + + /** + * Method to unset registry service. + * + * @param registryService service to get registry data. + */ + protected void unsetRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { + log.debug("Unset Registry service"); + } + ServiceHolder.setRegistryService(null); + } + + /** + * Method to set realm service. + * + * @param realmService service to get tenant data. + */ + protected void setRealmService(RealmService realmService) { + log.debug("Setting RealmService for WSO2 API Manager migration"); + ServiceHolder.setRealmService(realmService); + } + + /** + * Method to unset realm service. + * + * @param realmService service to get tenant data. + */ + protected void unsetRealmService(RealmService realmService) { + if (log.isDebugEnabled()) { + log.debug("Unset Realm service"); + } + ServiceHolder.setRealmService(null); + } + + /** + * Method to set tenant registry loader + * + * @param tenantRegLoader tenant registry loader + */ + protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegLoader) { + log.debug("Setting TenantRegistryLoader for WSO2 API Manager migration"); + ServiceHolder.setTenantRegLoader(tenantRegLoader); + } + + /** + * Method to unset tenant registry loader + * + * @param tenantRegLoader tenant registry loader + */ + protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegLoader) { + log.debug("Unset Tenant Registry Loader"); + ServiceHolder.setTenantRegLoader(null); + } + + /** + * Method to set API Manager configuration + * + * @param apiManagerConfig api manager configuration + */ + protected void setApiManagerConfig(APIManagerConfigurationService apiManagerConfig) { + log.info("Setting APIManager configuration"); + } + + /** + * Method to unset API manager configuration + * + * @param apiManagerConfig api manager configuration + */ + protected void unsetApiManagerConfig(APIManagerConfigurationService apiManagerConfig) { + log.info("Un-setting APIManager configuration"); + } + +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/ServiceHolder.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/ServiceHolder.java new file mode 100644 index 0000000000..b03635c444 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/ServiceHolder.java @@ -0,0 +1,86 @@ +/* +* 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.migration.client.internal; + +import org.wso2.carbon.registry.core.service.RegistryService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.user.core.service.RealmService; + +@SuppressWarnings("unused") +public class ServiceHolder { + //Registry Service which is used to get registry data. + private static RegistryService registryService; + + //Realm Service which is used to get tenant data. + private static RealmService realmService; + + //Tenant registry loader which is used to load tenant registry + private static TenantRegistryLoader tenantRegLoader; + + /** + * Method to get RegistryService. + * + * @return registryService. + */ + public static RegistryService getRegistryService() { + return registryService; + } + + /** + * Method to set registry RegistryService. + * + * @param service registryService. + */ + public static void setRegistryService(RegistryService service) { + registryService = service; + } + + /** + * This method used to get RealmService. + * + * @return RealmService. + */ + public static RealmService getRealmService() { + return realmService; + } + + /** + * Method to set registry RealmService. + * + * @param service RealmService. + */ + public static void setRealmService(RealmService service) { + realmService = service; + } + + /** + * This method used to get TenantRegistryLoader + * + * @return tenantRegLoader Tenant registry loader for load tenant registry + */ + public static TenantRegistryLoader getTenantRegLoader() { + return tenantRegLoader; + } + + /** + * This method used to set TenantRegistryLoader + * + * @param service Tenant registry loader for load tenant registry + */ + public static void setTenantRegLoader(TenantRegistryLoader service) { + tenantRegLoader = service; + } +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java new file mode 100644 index 0000000000..e8a95c495e --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java @@ -0,0 +1,103 @@ +/* +* 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.migration.util; + +public class Constants { + public static final String APIM_PRODUCT_NAME = "WSO2 API Manager"; + public static final String PREVIOUS_VERSION = "1.6.0"; + public static final String VERSION_1_7 = "1.7.0"; + public static final String LINE_BREAK = "\\n"; + public static final String CONSTRAINT = "constraint"; + public static final String API = "api"; + public static final String MIGRATION_SCRIPTS_FOLDER = "migration-scripts"; + + // Migration client argument property names + public static final String ARG_MIGRATE_TO_VERSION = "migrateToVersion"; + public static final String ARG_MIGRATE_TENANTS = "tenants"; + public static final String ARG_MIGRATE_ALL = "migrate"; + public static final String ARG_MIGRATE_REG = "migrateReg"; + public static final String ARG_MIGRATE_FILE_SYSTEM = "migrateFS"; + + // Synapse configuration related + public static final String SYNAPSE_API_ROOT_ELEMENT = "api"; + public static final String SYNAPSE_API_ATTRIBUTE_VERSION = "version"; + + /* + * Variables in api_doc.json version 1.1 + */ + + public static final String API_DOC_11_BASE_PATH = "basePath"; + public static final String API_DOC_11_RESOURCE_PATH = "resourcePath"; + public static final String API_DOC_11_API_VERSION = "apiVersion"; + public static final String API_DOC_11_APIS = "apis"; + public static final String API_DOC_11_PATH = "path"; + public static final String API_DOC_11_OPERATIONS = "operations"; + public static final String API_DOC_11_METHOD = "httpMethod"; + public static final String API_DOC_11_PARAMETERS = "parameters"; + + /* + * Variables in api_doc.json version 1.2 + */ + + public static final String API_DOC_12_BASE_PATH = "basePath"; + public static final String API_DOC_12_APIS = "apis"; + public static final String API_DOC_12_PATH = "path"; + public static final String API_DOC_12_OPERATIONS = "operations"; + public static final String API_DOC_12_METHOD = "method"; + public static final String API_DOC_12_PARAMETERS = "parameters"; + public static final String API_DOC_12_NICKNAME = "nickname"; + //this resource contains all the resources. This is introduced to swagger 1.2 location to hold + //all the resource during the migration of 1.6. AM 1.6 does not have resources seperated by name + //so all resources are in one doc + public static final String API_DOC_12_ALL_RESOURCES_DOC = "resources"; + + /** + * default parameter array + */ + public static final String DEFAULT_PARAM_ARRAY = "[ " + " { " + + " \"dataType\": \"String\", " + + " \"description\": \"Access Token\", " + + " \"name\": \"Authorization\", " + + " \"allowMultiple\": false, " + + " \"required\": true, " + + " \"paramType\": \"header\" " + " }, " + + " { " + + " \"description\": \"Request Body\", " + + " \"name\": \"body\", " + + " \"allowMultiple\": false, " + + " \"type\": \"string\", " + + " \"required\": true, " + + " \"paramType\": \"body\" " + " } " + + "]"; + + public static final String DEFAULT_PARAM_FOR_URL_TEMPLATE = " { " + + "\"name\": \"\", " + + "\"allowMultiple\": false, " + + "\"required\": true, " + + "\"type\": \"string\", " + + "\"paramType\": \"path\" " + + "}"; + + + //database types + public static final String DB_TYPE_ORACLE = "oracle"; + public static final String DB_TYPE_DB2 = "db2"; + public static final String DB_TYPE_MYSQL= "mysql"; + public static final String DB_TYPE_MSSQL = "mssql"; + public static final String DB_TYPE_POSTGRE = "postgre"; + public static final String DB_TYPE_OPENEDGE = "openedge"; +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java new file mode 100644 index 0000000000..8b6ced8fba --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java @@ -0,0 +1,617 @@ +/* +* 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.migration.util; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIMgtDBUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.MigrationDBCreator; +import org.wso2.carbon.registry.core.Registry; +import org.wso2.carbon.registry.core.RegistryConstants; +import org.wso2.carbon.registry.core.Resource; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.utils.CarbonUtils; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ResourceUtil { + + private static final Log log = LogFactory.getLog(ResourceUtil.class); + + /** + * location for the swagger 1.1 resources + * + * @param apiName api name + * @param apiVersion api version + * @return swagger v1.1 location + */ + public static String getSwagger11ResourceLocation(String apiName, String apiVersion) { + return APIConstants.API_DOC_LOCATION + RegistryConstants.PATH_SEPARATOR + + apiName +"-" + apiVersion + RegistryConstants.PATH_SEPARATOR + APIConstants.API_DOC_RESOURCE_NAME; + } + + + /** + * location for the swagger 1.2 resources + * + * @param apiName api name + * @param apiVersion api version + * @param apiProvider api provider + * @return swagger v1.2 location + */ + public static String getSwagger12ResourceLocation(String apiName, String apiVersion, String apiProvider) { + return APIConstants.API_DOC_LOCATION + RegistryConstants.PATH_SEPARATOR + apiName + "-" + apiVersion + "-" + + apiProvider + RegistryConstants.PATH_SEPARATOR + APIConstants.API_DOC_1_2_LOCATION; + } + + + /** + * This method picks the query according to the users database + * + * @return exact query to execute + * @throws SQLException + * @throws APIMigrationException + * @throws IOException + */ + public static String pickQueryFromResources(String queryType) throws SQLException, APIMigrationException, + IOException { + + String queryTobeExecuted; + try { + String databaseType = MigrationDBCreator.getDatabaseType(APIMgtDBUtil.getConnection()); + + //pick from 18to19Migration/sql-scripts + String resourcePath = CarbonUtils.getCarbonHome() + File.separator + Constants.MIGRATION_SCRIPTS_FOLDER + File.separator; + + if (Constants.CONSTRAINT.equals(queryType)) { + //queryTobeExecuted = resourcePath + "drop-fk.sql"; + queryTobeExecuted = IOUtils.toString(new FileInputStream(new File(resourcePath + "drop-fk.sql")), "UTF-8"); + } else { + queryTobeExecuted = resourcePath + databaseType + ".sql"; + //queryTobeExecuted = IOUtils.toString(new FileInputStream(new File(resourcePath + databaseType + ".sql")), "UTF-8"); + } + + } catch (IOException e) { + throw new APIMigrationException("Error occurred while accessing the sql from resources. " + e); + } catch (Exception e) { + //getDatabaseType inherited from DBCreator, which throws generic exception + throw new APIMigrationException("Error occurred while searching for database type " + e); + } + + return queryTobeExecuted; + } + + /** + * To handle exceptions + * + * @param msg error message + * @throws APIMigrationException + */ + public static void handleException(String msg, Throwable e) throws APIMigrationException { + log.error(msg, e); + throw new APIMigrationException(msg, e); + } + + + + + /** + * Get all the parameters related to each resource. The parameter array is + * an array which is part of the operations object inside each resource. + * + * @param resource + * api-doc which contains swagger 1.1 info + * @return map of parameter array related to all the http methods for each + * resource. the key for + * the map is resourcepath_httpmethod + */ + public static Map getAllParametersForResources(JSONObject resource) { + Map parameters = new HashMap(); + + String resourcePath = (String) resource.get(Constants.API_DOC_11_RESOURCE_PATH); + String apiVersion = (String) resource.get(Constants.API_DOC_11_API_VERSION); + String resourcePathPrefix = resourcePath + "/" + apiVersion; + + String key; + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS); + for (int i = 0; i < apis.size(); i++) { + + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_11_PATH); + JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_11_OPERATIONS); + + if (resourcePathPrefix.length() > path.length()) { + log.error("Cannot obtain key prefix because swagger resourcePathPrefix : " + resourcePathPrefix + " is incompatible with path : " + path); + continue; + } + + // get the key by removing the "apiVersion" and "resourcePath" + // from the "path" variable + // and concat the http method + String keyPrefix = path.substring(resourcePathPrefix.length()); + if (keyPrefix.isEmpty()) { + keyPrefix = "/*"; + } + + + for (int j = 0; j < operations.size(); j++) { + JSONObject operation = (JSONObject) operations.get(j); + String httpMethod = (String) operation.get(Constants.API_DOC_11_METHOD); + JSONArray parameterArray = (JSONArray) operation.get(Constants.API_DOC_11_PARAMETERS); + + key = keyPrefix + "_" + httpMethod.toLowerCase(); + + parameters.put(key, parameterArray); + } + } + + return parameters; + + } + + /** + * Get all the operation object related to each resource. Method is inside the operation object + * this object contains the nickname, description related to that resource method + * @param resource + * api-doc which contains swagger 1.1 info + * @return map of operations array related to all the http methods for each + * resource. the key for + * the map is resourcepath_httpmethod + */ + private static Map getAllOperationsForResources(JSONObject resource) { + Map parameters = new HashMap(); + + String resourcePath = (String) resource.get(Constants.API_DOC_11_RESOURCE_PATH); + String apiVersion = (String) resource.get(Constants.API_DOC_11_API_VERSION); + String resourcePathPrefix = resourcePath + "/" + apiVersion; + + String key; + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS); + for (int i = 0; i < apis.size(); i++) { + + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_11_PATH); + JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_11_OPERATIONS); + + if (resourcePathPrefix.length() > path.length()) { + log.error("Cannot obtain key prefix because swagger resourcePathPrefix : " + resourcePathPrefix + " is incompatible with path : " + path); + continue; + } + + // get the key by removing the "apiVersion" and "resourcePath" + // from the "path" variable + // and concat the http method + String keyPrefix = path.substring(resourcePathPrefix.length()); + if (keyPrefix.isEmpty()) { + keyPrefix = "/*"; + } + + for (int j = 0; j < operations.size(); j++) { + JSONObject operation = (JSONObject) operations.get(j); + String httpMethod = (String) operation.get(Constants.API_DOC_11_METHOD); + JSONArray parameterArray = (JSONArray) operation.get(Constants.API_DOC_11_PARAMETERS); + + key = keyPrefix + "_" + httpMethod.toLowerCase(); + + parameters.put(key, operation); + } + } + + return parameters; + } + /** + * Get all the apis as a map. key for map is the full resource path for that api. key is created + * using 'basepath + apis[i].path' values in the api-doc.json file (swagger 1.1 doc) + * + * @param resource + * api-doc which contains swagger 1.1 info + * @return map of apis in the swagger 1.1 doc. key is the full resource path for that resource + */ + public static Map getAllAPIsByResourcePath(JSONObject resource) { + Map parameters = new HashMap(); + + String basePath = (String) resource.get(Constants.API_DOC_11_BASE_PATH); + String key = null; + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS); + for (int i = 0; i < apis.size(); i++) { + + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_11_PATH); + key = basePath + path; + parameters.put(key, apiInfo); + } + + return parameters; + + } + + private static JSONArray getDefaultParameters() { + JSONParser parser = new JSONParser(); + JSONArray defaultParam = null; + try { + defaultParam = (JSONArray) parser.parse(Constants.DEFAULT_PARAM_ARRAY); + } catch (ParseException e) { + log.error("ParseException when getting swagger default Parameters", e); + } + return defaultParam; + + } + + /** + * Modify the resource in registry location '1.2' to be compatible with the + * AM 1.8. add the + * parameters to operations element, add 'nickname' variable and the + * 'basePath' variable + * + * @param resource + * resource inside the 1.2 location + * @param allParameters + * map containing all the parameters extracted from api-doc + * containing + * resources for swagger 1.1 + * @param allOperations + * @param basePath + * base path for the resource + * @return modified resource for the api + */ + public static String getUpdatedSwagger12Resource(JSONObject resource, + Map allParameters, + Map allOperations, String basePath) { + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_12_APIS); + for (int i = 0; i < apis.size(); i++) { + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_12_PATH); + JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_12_OPERATIONS); + + for (int j = 0; j < operations.size(); j++) { + JSONObject operation = (JSONObject) operations.get(j); + String method = (String) operation.get(Constants.API_DOC_12_METHOD); + + // nickname is method name + "_" + path without starting "/" + // symbol + String nickname = method.toLowerCase() + "_" + path.substring(1); + // add nickname variable + operation.put(Constants.API_DOC_12_NICKNAME, nickname); + String key = path + "_" + method.toLowerCase(); + + JSONArray parameters; + if (allParameters.containsKey(key)) { + parameters = allParameters.get(key); + + //setting the 'type' to 'string' if this variable is missing + for(int m = 0; m < parameters.size(); m++ ){ + JSONObject para = (JSONObject)parameters.get(m); + if(!para.containsKey("type")){ + para.put("type", "string"); + } + } + + } else { + parameters = getDefaultParameters(); + + } + //if there are parameters already in this + JSONArray existingParams = (JSONArray) operation.get(Constants.API_DOC_12_PARAMETERS); + if(existingParams.isEmpty()) { + JSONParser parser = new JSONParser(); + if(path.contains("{")) { + List urlParams = ResourceUtil.getURLTempateParams(path); + for(String p: urlParams){ + try { + JSONObject paramObj = (JSONObject) parser.parse(Constants.DEFAULT_PARAM_FOR_URL_TEMPLATE); + paramObj.put("name", p); + parameters.add(paramObj); + } catch (ParseException e) { + log.error("ParseException when getting swagger default Parameters from URI template", e); + } + } + } + // add parameters array + operation.put(Constants.API_DOC_12_PARAMETERS, parameters); + } else { + for(int k = 0; k < existingParams.size(); k ++ ) { + parameters.add(existingParams.get(k)); + } + operation.put(Constants.API_DOC_12_PARAMETERS, parameters); + } + + //updating the resource description and nickname using values in the swagger 1.1 doc + if(allOperations.containsKey(key)){ + + //update info related to object + JSONObject operationObj11 = allOperations.get(key); + //add summery + if(operationObj11.containsKey("summary")) { + operation.put("summary", (String) operationObj11.get("summery")); + } + + } + } + } + + // add basePath variable + resource.put(Constants.API_DOC_12_BASE_PATH, basePath); + + return resource.toJSONString(); + } + + + /** + * update all the the swagger document in the registry related to an api + * @param apiDocJson + * @param docResourcePaths + * @param registry + * @throws ParseException + * @throws RegistryException + */ + public static void updateAPISwaggerDocs(String apiDocJson, String[] docResourcePaths, + Registry registry) throws ParseException, RegistryException, UnsupportedEncodingException, APIMigrationException { + + JSONParser parser = new JSONParser(); + JSONObject apiDoc11 = (JSONObject) parser.parse(apiDocJson); + + Map allParameters = ResourceUtil.getAllParametersForResources(apiDoc11); + + Map allOperations = ResourceUtil.getAllOperationsForResources(apiDoc11); + + Map apisByPath = ResourceUtil.getAllAPIsByResourcePath(apiDoc11); + + //this collection holds description given for each resource against the resource name. + //descriptions added resources in an api in AM 1.7 are stored in api-doc 1.1. this desciption + //is showed in am 1.7 api console in the store applicatoin. AM 1.8 uses descriptions in + // api-doc in 1.2 resource folder. following map collects this value from api-doc 1.1 and + // store it to add to api-doc 1.2 + Map descriptionsForResource = new HashMap(); + + + + String basePath = (String) apiDoc11.get(Constants.API_DOC_11_BASE_PATH); + String resourcePath = (String) apiDoc11.get(Constants.API_DOC_11_RESOURCE_PATH); + String apiVersion = (String) apiDoc11.get(Constants.API_DOC_11_API_VERSION); + + if (basePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_BASE_PATH); + } + + if (resourcePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_RESOURCE_PATH); + } + + if (apiVersion == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_API_VERSION); + } + + resourcePath = resourcePath.endsWith("/") ? resourcePath : resourcePath + "/"; + String basePathForResource = basePath + resourcePath + apiVersion; + + String apidoc12path = ""; + + //update each resource in the 1.2 folder except the api-doc resource + for (String docResourcePath : docResourcePaths) { + String resourceName = docResourcePath.substring(docResourcePath.lastIndexOf("/")); + + if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) { + //store api-doc in 1.2 folder for future use + apidoc12path = docResourcePath; + continue; + } + + if (!registry.resourceExists(docResourcePath)) { + log.error("Doc resource path at : " + docResourcePath + " does not exist"); + continue; + } + + Resource resource = registry.get(docResourcePath); + JSONObject apiDoc = (JSONObject) parser.parse(new String((byte[]) resource.getContent(), "UTF8")); + + + String description = ""; + //generate the key to query the descriptionsForResource map + JSONArray apisInResource = (JSONArray) apiDoc.get(Constants.API_DOC_12_APIS); + + if (apisInResource == null) { + log.error("Could not find " + Constants.API_DOC_12_APIS + " in document resource path"); + continue; + } + + JSONObject apiTemp = (JSONObject) apisInResource.get(0); + String path = (String) apiTemp.get(Constants.API_DOC_12_PATH); + + if (path == null) { + log.error("Could not find " + Constants.API_DOC_12_PATH + " in document resource path"); + continue; + } + + String key = ""; + if (path.equals("/*")) { + key = basePathForResource; + } else { + key = basePathForResource + path; + } + + + //get the description for that resource. query the api list generated using api-doc 1.1 + if(apisByPath.containsKey(key)) { + JSONObject apiInfo = (JSONObject) apisByPath.get(key); + description = (String) apiInfo.get("description"); + descriptionsForResource.put(resourceName, description); + } + + String updatedJson = + ResourceUtil.getUpdatedSwagger12Resource(apiDoc, allParameters, allOperations, + basePathForResource); + log.info("\t update " + resourceName.substring(1)); + Resource res = registry.get(docResourcePath); + res.setContent(updatedJson); + //update the registry + registry.put(docResourcePath, res); + + } + + //update the api-doc. add the descriptions to each api resource + ResourceUtil.updateSwagger12APIdoc(apidoc12path, descriptionsForResource, registry, parser); + + } + + + + /** + * update the swagger 1.2 api-doc. This method updates the descriptions + * @param apidoc12path + * @param descriptionsForResource + * @param registry + * @param parser + * @throws RegistryException + * @throws ParseException + */ + private static void updateSwagger12APIdoc(String apidoc12path, + Map descriptionsForResource, + Registry registry, JSONParser parser) + throws RegistryException, + ParseException, UnsupportedEncodingException, APIMigrationException { + if (!registry.resourceExists(apidoc12path)) { + throw new APIMigrationException("Swagger 1.2 doc does not exist"); + } + Resource res = registry.get(apidoc12path); + JSONObject api12Doc = (JSONObject) parser.parse(new String((byte[]) res.getContent(), "UTF8")); + JSONArray apis = (JSONArray) api12Doc.get(Constants.API_DOC_12_APIS); + for (int j = 0; j < apis.size(); j++) { + JSONObject api = (JSONObject) apis.get(j); + + // get the resource name for each api in api-doc 1.2 + String resPathName = (String) api.get(Constants.API_DOC_12_PATH); + if (descriptionsForResource.containsKey(resPathName)) { + // if the descrption is available for that resource update it + api.put("description", descriptionsForResource.get(resPathName)); + } + } + log.info("\t update api-doc"); + res.setContent(api12Doc.toJSONString()); + // update the registry + registry.put(apidoc12path, res); + } + + /** + * remove header and body parameters + * @param docResourcePaths + * @param registry + * @throws RegistryException + * @throws ParseException + */ + public static void updateSwagger12ResourcesForAM18(String[] docResourcePaths, + Registry registry) throws RegistryException, ParseException, UnsupportedEncodingException { + JSONParser parser = new JSONParser(); + for (String docResourcePath : docResourcePaths) { + + String resourceName = docResourcePath.substring(docResourcePath.lastIndexOf("/")); + + //modify this if api-doc resource needed to be changed + if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) { + continue; + } + + Resource resource = registry.get(docResourcePath); + JSONObject resourceDoc = (JSONObject) parser.parse(new String((byte[]) resource.getContent(), "UTF8")); + JSONArray apis = (JSONArray) resourceDoc.get(Constants.API_DOC_12_APIS); + for (int j = 0; j < apis.size(); j++) { + JSONObject api = (JSONObject) apis.get(j); + JSONArray operations = (JSONArray) api.get("operations"); + + for (int k = 0; k < operations.size(); k++) { + JSONObject operation = (JSONObject) operations.get(k); + JSONArray parameters = (JSONArray) operation.get("parameters"); + String method = (String) operation.get("method"); + JSONArray parametersNew = new JSONArray(); + //remove header and body parameters + for (int l = 0; l < parameters.size(); l++) { + JSONObject parameter = (JSONObject) parameters.get(l); + + if(parameter.get("paramType").equals("header")){ + continue; + } + if(parameter.get("paramType").equals("body")) { + + //only remove body of a GET and DELETE + if("GET".equalsIgnoreCase(method) || + "DELETE".equalsIgnoreCase(method)) { + continue; + } + } + parametersNew.add(parameter); + } + operation.put("parameters", parametersNew); + } + + + } + + resource.setContent(resourceDoc.toJSONString()); + //update the registry + registry.put(docResourcePath, resource); + } + + } + + /** + * extract the parameters from the url tempate. + * @param url + * @return + */ + public static List getURLTempateParams(String url) { + boolean endVal = false; + + List params = new ArrayList(); + if(url.contains("{")){ + + int start = 0; + int end = 0; + for(int i = 0; i < url.length(); i++) { + if(url.charAt(i) == '{') + start = i; + else if(url.charAt(i) == '}') { + end = i; + endVal = true; + } + + if(endVal){ + params.add(url.substring(start + 1, end)); + endVal = false; + } + } + + } + return params; + } + +} diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/h2.sql b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/h2.sql new file mode 100644 index 0000000000..a1e634e99d --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/h2.sql @@ -0,0 +1,371 @@ +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP LOGIN_PAGE_URL; +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP ERROR_PAGE_URL; +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP CONSENT_PAGE_URL; + +ALTER TABLE IDN_OAUTH2_ACCESS_TOKEN ALTER TOKEN_SCOPE VARCHAR (2048); + +ALTER TABLE AM_API_URL_MAPPING ADD MEDIATION_SCRIPT BLOB DEFAULT NULL; + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE ( + SCOPE_ID INTEGER NOT NULL AUTO_INCREMENT, + SCOPE_KEY VARCHAR(100) NOT NULL, + NAME VARCHAR(255) NULL, + DESCRIPTION VARCHAR(512) NULL, + TENANT_ID INTEGER NOT NULL DEFAULT 0, + ROLES VARCHAR (500) NULL, + PRIMARY KEY (SCOPE_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_RESOURCE_SCOPE ( + RESOURCE_PATH VARCHAR(255) NOT NULL, + SCOPE_ID INTEGER (11) NOT NULL, + PRIMARY KEY (RESOURCE_PATH), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_SCIM_GROUP ( + ID INTEGER GENERATED ALWAYS AS IDENTITY, + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR(255) NOT NULL, + ATTR_NAME VARCHAR(1024) NOT NULL, + ATTR_VALUE VARCHAR(1024), + PRIMARY KEY (ID) +); + +CREATE TABLE IF NOT EXISTS IDN_SCIM_PROVIDER ( + CONSUMER_ID VARCHAR(255) NOT NULL, + PROVIDER_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + USER_PASSWORD VARCHAR(255) NOT NULL, + USER_URL VARCHAR(1024) NOT NULL, + GROUP_URL VARCHAR(1024), + BULK_URL VARCHAR(1024), + PRIMARY KEY (CONSUMER_ID,PROVIDER_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OPENID_REMEMBER_ME ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + COOKIE_VALUE VARCHAR(1024), + CREATED_TIME TIMESTAMP, + PRIMARY KEY (USER_NAME, TENANT_ID) +); + +CREATE TABLE IF NOT EXISTS IDN_OPENID_ASSOCIATIONS ( + HANDLE VARCHAR(255) NOT NULL, + ASSOC_TYPE VARCHAR(255) NOT NULL, + EXPIRE_IN TIMESTAMP NOT NULL, + MAC_KEY VARCHAR(255) NOT NULL, + ASSOC_STORE VARCHAR(128) DEFAULT 'SHARED', + PRIMARY KEY (HANDLE) +); + +CREATE TABLE IDN_STS_STORE ( + ID INTEGER AUTO_INCREMENT, + TOKEN_ID VARCHAR(255) NOT NULL, + TOKEN_CONTENT BLOB NOT NULL, + CREATE_DATE TIMESTAMP NOT NULL, + EXPIRE_DATE TIMESTAMP NOT NULL, + STATE INTEGER DEFAULT 0, + PRIMARY KEY (ID) +); + +CREATE TABLE IDN_IDENTITY_USER_DATA ( + TENANT_ID INTEGER DEFAULT -1234, + USER_NAME VARCHAR(255) NOT NULL, + DATA_KEY VARCHAR(255) NOT NULL, + DATA_VALUE VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, DATA_KEY) +); + +CREATE TABLE IDN_IDENTITY_META_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + METADATA_TYPE VARCHAR(255) NOT NULL, + METADATA VARCHAR(255) NOT NULL, + VALID VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, METADATA_TYPE,METADATA) +); + +CREATE TABLE IF NOT EXISTS IDN_THRIFT_SESSION ( + SESSION_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + CREATED_TIME VARCHAR(255) NOT NULL, + LAST_MODIFIED_TIME VARCHAR(255) NOT NULL, + PRIMARY KEY (SESSION_ID) +); + +-- End of IDN Tables -- + + +-- Start of IDN-APPLICATION-MGT Tables-- + +CREATE TABLE IF NOT EXISTS SP_APP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + APP_NAME VARCHAR (255) NOT NULL , + USER_STORE VARCHAR (255) NOT NULL, + USERNAME VARCHAR (255) NOT NULL , + DESCRIPTION VARCHAR (1024), + ROLE_CLAIM VARCHAR (512), + AUTH_TYPE VARCHAR (255) NOT NULL, + PROVISIONING_USERSTORE_DOMAIN VARCHAR (512), + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '1', + IS_SEND_LOCAL_SUBJECT_ID CHAR(1) DEFAULT '0', + IS_SEND_AUTH_LIST_OF_IDPS CHAR(1) DEFAULT '0', + SUBJECT_CLAIM_URI VARCHAR (512), + IS_SAAS_APP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID)); + +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_NAME_CONSTRAINT UNIQUE(APP_NAME, TENANT_ID); + +CREATE TABLE IF NOT EXISTS SP_INBOUND_AUTH ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + INBOUND_AUTH_KEY VARCHAR (255) NOT NULL, + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + PROP_NAME VARCHAR (255), + PROP_VALUE VARCHAR (1024) , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_INBOUND_AUTH ADD CONSTRAINT APPLICATION_ID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_AUTH_STEP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + STEP_ORDER INTEGER DEFAULT 1, + APP_ID INTEGER NOT NULL , + IS_SUBJECT_STEP CHAR(1) DEFAULT '0', + IS_ATTRIBUTE_STEP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID)); + +ALTER TABLE SP_AUTH_STEP ADD CONSTRAINT APPLICATION_ID_CONSTRAINT_STEP FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_FEDERATED_IDP ( + ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_ID INTEGER NOT NULL, + PRIMARY KEY (ID, AUTHENTICATOR_ID)); + +ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_CLAIM VARCHAR (512) NOT NULL , + SP_CLAIM VARCHAR (512) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_REQUESTED VARCHAR(128) DEFAULT '0', + DEFAULT_VALUE VARCHAR(255), + PRIMARY KEY (ID)); + +ALTER TABLE SP_CLAIM_MAPPING ADD CONSTRAINT CLAIMID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_ROLE_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_ROLE VARCHAR (255) NOT NULL , + SP_ROLE VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_ROLE_MAPPING ADD CONSTRAINT ROLEID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_REQ_PATH_AUTHENTICATOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)); + +ALTER TABLE SP_REQ_PATH_AUTHENTICATOR ADD CONSTRAINT REQ_AUTH_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_PROVISIONING_CONNECTOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_NAME VARCHAR (255) NOT NULL , + CONNECTOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_JIT_ENABLED CHAR(1) NOT NULL DEFAULT '0', + BLOCKING CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID)); + +ALTER TABLE SP_PROVISIONING_CONNECTOR ADD CONSTRAINT PRO_CONNECTOR_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS IDP ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + NAME VARCHAR(254) NOT NULL, + IS_ENABLED CHAR(1) NOT NULL DEFAULT '1', + IS_PRIMARY CHAR(1) NOT NULL DEFAULT '0', + HOME_REALM_ID VARCHAR(254), + IMAGE MEDIUMBLOB, + CERTIFICATE BLOB, + ALIAS VARCHAR(254), + INBOUND_PROV_ENABLED CHAR (1) NOT NULL DEFAULT '0', + INBOUND_PROV_USER_STORE_ID VARCHAR(254), + USER_CLAIM_URI VARCHAR(254), + ROLE_CLAIM_URI VARCHAR(254), + DESCRIPTION VARCHAR (1024), + DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), + DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), + PROVISIONING_ROLE VARCHAR(128), + IS_FEDERATION_HUB CHAR(1) NOT NULL DEFAULT '0', + IS_LOCAL_CLAIM_DIALECT CHAR(1) NOT NULL DEFAULT '0', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, NAME)); + +INSERT INTO IDP (TENANT_ID, NAME, HOME_REALM_ID) VALUES (-1234, 'LOCAL', 'localhost'); + +CREATE TABLE IF NOT EXISTS IDP_ROLE ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + ROLE VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, ROLE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_ROLE_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_ROLE_ID INTEGER, + TENANT_ID INTEGER, + USER_STORE_ID VARCHAR (253), + LOCAL_ROLE VARCHAR(253), + PRIMARY KEY (ID), + UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), + FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_CLAIM ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, CLAIM), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_CLAIM_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_CLAIM_ID INTEGER, + TENANT_ID INTEGER, + LOCAL_CLAIM VARCHAR(253), + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), + FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '1', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +INSERT INTO IDP_AUTHENTICATOR (TENANT_ID, IDP_ID, NAME) VALUES (-1234, 1, 'samlsso'); + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + AUTHENTICATOR_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), + FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_CONFIG ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '0', + IS_BLOCKING CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_PROV_CONFIG_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048), + PROPERTY_BLOB_VALUE BLOB, + PROPERTY_TYPE CHAR(32) NOT NULL, + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, PROVISIONING_CONFIG_ID, PROPERTY_KEY), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_ENTITY ( + ID INTEGER AUTO_INCREMENT, + PROVISIONING_CONFIG_ID INTEGER, + ENTITY_TYPE VARCHAR(255) NOT NULL, + ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, + ENTITY_NAME VARCHAR(255) NOT NULL, + ENTITY_VALUE VARCHAR(255), + TENANT_ID INTEGER, + PRIMARY KEY (ID), + UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME), + UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE); + +CREATE TABLE IF NOT EXISTS IDP_LOCAL_CLAIM ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + CLAIM_URI VARCHAR(255) NOT NULL, + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, CLAIM_URI), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE); + +-- End of IDN-APPLICATION-MGT Tables-- + + +ALTER TABLE AM_APPLICATION_KEY_MAPPING DROP PRIMARY KEY; +ALTER TABLE AM_APPLICATION_KEY_MAPPING ALTER CONSUMER_KEY SET NULL; +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD PRIMARY KEY(APPLICATION_ID,KEY_TYPE); +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD STATE VARCHAR(30) DEFAULT 'COMPLETED'; + +CREATE TABLE IF NOT EXISTS AM_APPLICATION_REGISTRATION ( + REG_ID INT AUTO_INCREMENT, + SUBSCRIBER_ID INT, + WF_REF VARCHAR(255) NOT NULL, + APP_ID INT, + TOKEN_TYPE VARCHAR(30), + ALLOWED_DOMAINS VARCHAR(256), + VALIDITY_PERIOD BIGINT, + UNIQUE (SUBSCRIBER_ID,APP_ID,TOKEN_TYPE), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, + FOREIGN KEY(APP_ID) REFERENCES AM_APPLICATION(APPLICATION_ID) ON UPDATE CASCADE ON DELETE RESTRICT, + PRIMARY KEY (REG_ID) +); + +CREATE TABLE IF NOT EXISTS AM_API_SCOPES ( + API_ID INTEGER NOT NULL, + SCOPE_ID INTEGER NOT NULL, + FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE TABLE IF NOT EXISTS AM_API_DEFAULT_VERSION ( + DEFAULT_VERSION_ID INT AUTO_INCREMENT, + API_NAME VARCHAR(256) NOT NULL , + API_PROVIDER VARCHAR(256) NOT NULL , + DEFAULT_API_VERSION VARCHAR(30) , + PUBLISHED_DEFAULT_API_VERSION VARCHAR(30) , + PRIMARY KEY (DEFAULT_VERSION_ID) +); + + diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/mssql.sql b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/mssql.sql new file mode 100644 index 0000000000..121860f8d8 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/mssql.sql @@ -0,0 +1,416 @@ +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP COLUMN LOGIN_PAGE_URL; +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP COLUMN ERROR_PAGE_URL; +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP COLUMN CONSENT_PAGE_URL; + +ALTER TABLE AM_API_URL_MAPPING ADD MEDIATION_SCRIPT VARBINARY(MAX) DEFAULT NULL; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_OAUTH2_SCOPE]') AND TYPE IN (N'U')) +CREATE TABLE IDN_OAUTH2_SCOPE ( + SCOPE_ID INTEGER IDENTITY(1,1), + SCOPE_KEY VARCHAR(100) NOT NULL, + NAME VARCHAR(255) NULL, + DESCRIPTION VARCHAR(512) NULL, + TENANT_ID INTEGER NOT NULL DEFAULT 0, + ROLES VARCHAR (500) NULL, + PRIMARY KEY (SCOPE_ID) +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_OAUTH2_RESOURCE_SCOPE]') AND TYPE IN (N'U')) +CREATE TABLE IDN_OAUTH2_RESOURCE_SCOPE ( + RESOURCE_PATH VARCHAR(255) NOT NULL, + SCOPE_ID INTEGER NOT NULL, + PRIMARY KEY (RESOURCE_PATH), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE ON UPDATE CASCADE +); + +CREATE TABLE IDN_SCIM_GROUP ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR(255) NOT NULL, + ATTR_NAME VARCHAR(1024) NOT NULL, + ATTR_VALUE VARCHAR(1024), + PRIMARY KEY (ID) +); + +CREATE TABLE IDN_SCIM_PROVIDER ( + CONSUMER_ID VARCHAR(255) NOT NULL, + PROVIDER_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + USER_PASSWORD VARCHAR(255) NOT NULL, + USER_URL VARCHAR(1024) NOT NULL, + GROUP_URL VARCHAR(1024), + BULK_URL VARCHAR(1024), + PRIMARY KEY (CONSUMER_ID,PROVIDER_ID) +); + +CREATE TABLE IDN_OPENID_REMEMBER_ME ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + COOKIE_VALUE VARCHAR(1024), + CREATED_TIME DATETIME, + PRIMARY KEY (USER_NAME, TENANT_ID) +); + +CREATE TABLE IDN_OPENID_ASSOCIATIONS ( + HANDLE VARCHAR(255) NOT NULL, + ASSOC_TYPE VARCHAR(255) NOT NULL, + EXPIRE_IN DATETIME NOT NULL, + MAC_KEY VARCHAR(255) NOT NULL, + ASSOC_STORE VARCHAR(128) DEFAULT 'SHARED', + PRIMARY KEY (HANDLE) +); + +CREATE TABLE IDN_STS_STORE ( + ID INTEGER IDENTITY(1,1), + TOKEN_ID VARCHAR(255) NOT NULL, + TOKEN_CONTENT VARBINARY(MAX) NOT NULL, + CREATE_DATE DATETIME NOT NULL, + EXPIRE_DATE DATETIME NOT NULL, + STATE INTEGER DEFAULT 0, + PRIMARY KEY (ID) +); + +CREATE TABLE IDN_IDENTITY_USER_DATA ( + TENANT_ID INTEGER DEFAULT -1234, + USER_NAME VARCHAR(255) NOT NULL, + DATA_KEY VARCHAR(255) NOT NULL, + DATA_VALUE VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, DATA_KEY) +); + +CREATE TABLE IDN_IDENTITY_META_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + METADATA_TYPE VARCHAR(255) NOT NULL, + METADATA VARCHAR(255) NOT NULL, + VALID VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, METADATA_TYPE,METADATA) +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_THRIFT_SESSION]') AND TYPE IN (N'U')) +CREATE TABLE IDN_THRIFT_SESSION ( + SESSION_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + CREATED_TIME VARCHAR(255) NOT NULL, + LAST_MODIFIED_TIME VARCHAR(255) NOT NULL, + PRIMARY KEY (SESSION_ID) +); + +-- End of IDN Tables -- + + +-- Start of IDN-APPLICATION-MGT Tables-- + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_APP]') AND TYPE IN (N'U')) +CREATE TABLE SP_APP ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + APP_NAME VARCHAR (255) NOT NULL , + USER_STORE VARCHAR (255) NOT NULL, + USERNAME VARCHAR (255) NOT NULL , + DESCRIPTION VARCHAR (1024), + ROLE_CLAIM VARCHAR (512), + AUTH_TYPE VARCHAR (255) NOT NULL, + PROVISIONING_USERSTORE_DOMAIN VARCHAR (512), + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '1', + IS_SEND_LOCAL_SUBJECT_ID CHAR(1) DEFAULT '0', + IS_SEND_AUTH_LIST_OF_IDPS CHAR(1) DEFAULT '0', + SUBJECT_CLAIM_URI VARCHAR (512), + IS_SAAS_APP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID) +); + +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_NAME_CONSTRAINT UNIQUE(APP_NAME, TENANT_ID); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_INBOUND_AUTH]') AND TYPE IN (N'U')) +CREATE TABLE SP_INBOUND_AUTH ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + INBOUND_AUTH_KEY VARCHAR (255) NOT NULL, + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + PROP_NAME VARCHAR (255), + PROP_VALUE VARCHAR (1024) , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +); + +ALTER TABLE SP_INBOUND_AUTH ADD CONSTRAINT APPLICATION_ID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_AUTH_STEP]') AND TYPE IN (N'U')) +CREATE TABLE SP_AUTH_STEP ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + STEP_ORDER INTEGER DEFAULT 1, + APP_ID INTEGER NOT NULL , + IS_SUBJECT_STEP CHAR(1) DEFAULT '0', + IS_ATTRIBUTE_STEP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID) +); + +ALTER TABLE SP_AUTH_STEP ADD CONSTRAINT APPLICATION_ID_CONSTRAINT_STEP FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_FEDERATED_IDP]') AND TYPE IN (N'U')) +CREATE TABLE SP_FEDERATED_IDP ( + ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_ID INTEGER NOT NULL, + PRIMARY KEY (ID, AUTHENTICATOR_ID) +); + +ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_CLAIM_MAPPING]') AND TYPE IN (N'U')) +CREATE TABLE SP_CLAIM_MAPPING ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + IDP_CLAIM VARCHAR (512) NOT NULL , + SP_CLAIM VARCHAR (512) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_REQUESTED VARCHAR(128) DEFAULT '0', + DEFAULT_VALUE VARCHAR(255), + PRIMARY KEY (ID) +); + +ALTER TABLE SP_CLAIM_MAPPING ADD CONSTRAINT CLAIMID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_ROLE_MAPPING]') AND TYPE IN (N'U')) +CREATE TABLE SP_ROLE_MAPPING ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + IDP_ROLE VARCHAR (255) NOT NULL , + SP_ROLE VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +); + +ALTER TABLE SP_ROLE_MAPPING ADD CONSTRAINT ROLEID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_REQ_PATH_AUTHENTICATOR]') AND TYPE IN (N'U')) +CREATE TABLE SP_REQ_PATH_AUTHENTICATOR ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +); + +ALTER TABLE SP_REQ_PATH_AUTHENTICATOR ADD CONSTRAINT REQ_AUTH_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[SP_PROVISIONING_CONNECTOR]') AND TYPE IN (N'U')) +CREATE TABLE SP_PROVISIONING_CONNECTOR ( + ID INTEGER NOT NULL IDENTITY(1,1), + TENANT_ID INTEGER NOT NULL, + IDP_NAME VARCHAR (255) NOT NULL , + CONNECTOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_JIT_ENABLED CHAR(1) NOT NULL DEFAULT '0', + BLOCKING CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID) +); + +ALTER TABLE SP_PROVISIONING_CONNECTOR ADD CONSTRAINT PRO_CONNECTOR_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP]') AND TYPE IN (N'U')) +CREATE TABLE IDP ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER, + NAME VARCHAR(254) NOT NULL, + IS_ENABLED CHAR(1) NOT NULL DEFAULT '1', + IS_PRIMARY CHAR(1) NOT NULL DEFAULT '0', + HOME_REALM_ID VARCHAR(254), + IMAGE VARBINARY(MAX), + CERTIFICATE VARBINARY(MAX), + ALIAS VARCHAR(254), + INBOUND_PROV_ENABLED CHAR (1) NOT NULL DEFAULT '0', + INBOUND_PROV_USER_STORE_ID VARCHAR(254), + USER_CLAIM_URI VARCHAR(254), + ROLE_CLAIM_URI VARCHAR(254), + DESCRIPTION VARCHAR (1024), + DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), + DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), + PROVISIONING_ROLE VARCHAR(128), + IS_FEDERATION_HUB CHAR(1) NOT NULL DEFAULT '0', + IS_LOCAL_CLAIM_DIALECT CHAR(1) NOT NULL DEFAULT '0', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, NAME) +); + +INSERT INTO IDP (TENANT_ID, NAME, HOME_REALM_ID) VALUES (-1234, 'LOCAL', 'localhost'); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_ROLE]') AND TYPE IN (N'U')) +CREATE TABLE IDP_ROLE ( + ID INTEGER IDENTITY(1,1), + IDP_ID INTEGER, + TENANT_ID INTEGER, + ROLE VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, ROLE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_ROLE_MAPPING]') AND TYPE IN (N'U')) +CREATE TABLE IDP_ROLE_MAPPING ( + ID INTEGER IDENTITY(1,1), + IDP_ROLE_ID INTEGER, + TENANT_ID INTEGER, + USER_STORE_ID VARCHAR (253), + LOCAL_ROLE VARCHAR(253), + PRIMARY KEY (ID), + UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), + FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_CLAIM]') AND TYPE IN (N'U')) +CREATE TABLE IDP_CLAIM ( + ID INTEGER IDENTITY(1,1), + IDP_ID INTEGER, + TENANT_ID INTEGER, + CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, CLAIM), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_CLAIM_MAPPING]') AND TYPE IN (N'U')) +CREATE TABLE IDP_CLAIM_MAPPING ( + ID INTEGER IDENTITY(1,1), + IDP_CLAIM_ID INTEGER, + TENANT_ID INTEGER, + LOCAL_CLAIM VARCHAR(253), + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), + FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_AUTHENTICATOR]') AND TYPE IN (N'U')) +CREATE TABLE IDP_AUTHENTICATOR ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '1', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +); + +INSERT INTO IDP_AUTHENTICATOR (TENANT_ID, IDP_ID, NAME) VALUES (-1234, 1, 'samlsso'); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_AUTHENTICATOR_PROPERTY]') AND TYPE IN (N'U')) +CREATE TABLE IDP_AUTHENTICATOR_PROPERTY ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER, + AUTHENTICATOR_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), + FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_PROVISIONING_CONFIG]') AND TYPE IN (N'U')) +CREATE TABLE IDP_PROVISIONING_CONFIG ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER, + IDP_ID INTEGER, + PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '0', + IS_BLOCKING CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_PROV_CONFIG_PROPERTY]') AND TYPE IN (N'U')) +CREATE TABLE IDP_PROV_CONFIG_PROPERTY ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048), + PROPERTY_BLOB_VALUE VARBINARY(MAX), + PROPERTY_TYPE CHAR(32) NOT NULL, + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, PROVISIONING_CONFIG_ID, PROPERTY_KEY), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_PROVISIONING_ENTITY]') AND TYPE IN (N'U')) +CREATE TABLE IDP_PROVISIONING_ENTITY ( + ID INTEGER IDENTITY(1,1), + PROVISIONING_CONFIG_ID INTEGER, + ENTITY_TYPE VARCHAR(255) NOT NULL, + ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, + ENTITY_NAME VARCHAR(255) NOT NULL, + ENTITY_VALUE VARCHAR(255), + TENANT_ID INTEGER, + PRIMARY KEY (ID), + UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME), + UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDP_LOCAL_CLAIM]') AND TYPE IN (N'U')) +CREATE TABLE IDP_LOCAL_CLAIM ( + ID INTEGER IDENTITY(1,1), + TENANT_ID INTEGER, + IDP_ID INTEGER, + CLAIM_URI VARCHAR(255) NOT NULL, + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, CLAIM_URI), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +); +-- End of IDN-APPLICATION-MGT Tables-- + +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD STATE VARCHAR(30) DEFAULT 'COMPLETED'; + +DECLARE @SQL VARCHAR(4000); +SET @SQL = 'ALTER TABLE |TABLE_NAME| DROP CONSTRAINT |CONSTRAINT_NAME|'; + +SET @SQL = REPLACE(@SQL, '|CONSTRAINT_NAME|',( SELECT name FROM sysobjects WHERE xtype = 'PK' AND parent_obj = OBJECT_ID('AM_APPLICATION_KEY_MAPPING'))); +SET @SQL = REPLACE(@SQL,'|TABLE_NAME|','AM_APPLICATION_KEY_MAPPING'); +EXEC (@SQL); + +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD PRIMARY KEY(APPLICATION_ID,KEY_TYPE); +ALTER TABLE AM_APPLICATION_KEY_MAPPING ALTER COLUMN CONSUMER_KEY VARCHAR(512) NULL; + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_APPLICATION_REGISTRATION]') AND TYPE IN (N'U')) +CREATE TABLE AM_APPLICATION_REGISTRATION ( + REG_ID INTEGER IDENTITY(1,1), + SUBSCRIBER_ID INTEGER, + WF_REF VARCHAR(255) NOT NULL, + APP_ID INTEGER, + TOKEN_TYPE VARCHAR(30), + ALLOWED_DOMAINS VARCHAR(256), + VALIDITY_PERIOD BIGINT, + UNIQUE (SUBSCRIBER_ID,APP_ID,TOKEN_TYPE), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE NO ACTION, + FOREIGN KEY(APP_ID) REFERENCES AM_APPLICATION(APPLICATION_ID) ON UPDATE CASCADE ON DELETE NO ACTION, + PRIMARY KEY (REG_ID) +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_API_SCOPES]') AND TYPE IN (N'U')) +CREATE TABLE AM_API_SCOPES ( + API_ID INTEGER NOT NULL, + SCOPE_ID INTEGER NOT NULL, + FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE ON UPDATE CASCADE +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[AM_API_DEFAULT_VERSION]') AND TYPE IN (N'U')) +CREATE TABLE AM_API_DEFAULT_VERSION ( + DEFAULT_VERSION_ID INT IDENTITY(1,1), + API_NAME VARCHAR(256) NOT NULL , + API_PROVIDER VARCHAR(256) NOT NULL , + DEFAULT_API_VERSION VARCHAR(30) , + PUBLISHED_DEFAULT_API_VERSION VARCHAR(30) , + PRIMARY KEY (DEFAULT_VERSION_ID) +); diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/mysql.sql b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/mysql.sql new file mode 100644 index 0000000000..2766074ba7 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/mysql.sql @@ -0,0 +1,383 @@ +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP LOGIN_PAGE_URL; +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP ERROR_PAGE_URL; +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP CONSENT_PAGE_URL; + +ALTER TABLE AM_API_URL_MAPPING ADD MEDIATION_SCRIPT BLOB DEFAULT NULL; + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE ( + SCOPE_ID INT(11) NOT NULL AUTO_INCREMENT, + SCOPE_KEY VARCHAR(100) NOT NULL, + NAME VARCHAR(255) NULL, + DESCRIPTION VARCHAR(512) NULL, + TENANT_ID INT(11) NOT NULL DEFAULT 0, + ROLES VARCHAR (500) NULL, + PRIMARY KEY (SCOPE_ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_RESOURCE_SCOPE ( + RESOURCE_PATH VARCHAR(255) NOT NULL, + SCOPE_ID INTEGER (11) NOT NULL, + PRIMARY KEY (RESOURCE_PATH), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_SCIM_GROUP ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR(255) NOT NULL, + ATTR_NAME VARCHAR(1024) NOT NULL, + ATTR_VALUE VARCHAR(1024), + PRIMARY KEY (ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_SCIM_PROVIDER ( + CONSUMER_ID VARCHAR(255) NOT NULL, + PROVIDER_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + USER_PASSWORD VARCHAR(255) NOT NULL, + USER_URL VARCHAR(1024) NOT NULL, + GROUP_URL VARCHAR(1024), + BULK_URL VARCHAR(1024), + PRIMARY KEY (CONSUMER_ID,PROVIDER_ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_OPENID_REMEMBER_ME ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + COOKIE_VALUE VARCHAR(1024), + CREATED_TIME TIMESTAMP, + PRIMARY KEY (USER_NAME, TENANT_ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_OPENID_ASSOCIATIONS ( + HANDLE VARCHAR(255) NOT NULL, + ASSOC_TYPE VARCHAR(255) NOT NULL, + EXPIRE_IN TIMESTAMP NOT NULL, + MAC_KEY VARCHAR(255) NOT NULL, + ASSOC_STORE VARCHAR(128) DEFAULT 'SHARED', + PRIMARY KEY (HANDLE) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_STS_STORE ( + ID INTEGER AUTO_INCREMENT, + TOKEN_ID VARCHAR(255) NOT NULL, + TOKEN_CONTENT BLOB(1024) NOT NULL, + CREATE_DATE TIMESTAMP NOT NULL, + EXPIRE_DATE TIMESTAMP NOT NULL, + STATE INTEGER DEFAULT 0, + PRIMARY KEY (ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_IDENTITY_USER_DATA ( + TENANT_ID INTEGER DEFAULT -1234, + USER_NAME VARCHAR(255) NOT NULL, + DATA_KEY VARCHAR(255) NOT NULL, + DATA_VALUE VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, DATA_KEY) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_IDENTITY_META_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + METADATA_TYPE VARCHAR(255) NOT NULL, + METADATA VARCHAR(255) NOT NULL, + VALID VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, METADATA_TYPE,METADATA) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_THRIFT_SESSION ( + SESSION_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + CREATED_TIME VARCHAR(255) NOT NULL, + LAST_MODIFIED_TIME VARCHAR(255) NOT NULL, + PRIMARY KEY (SESSION_ID) +)ENGINE INNODB; + +-- End of IDN Tables -- + + +-- Start of IDN-APPLICATION-MGT Tables-- + +CREATE TABLE IF NOT EXISTS SP_APP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + APP_NAME VARCHAR (255) NOT NULL , + USER_STORE VARCHAR (255) NOT NULL, + USERNAME VARCHAR (255) NOT NULL , + DESCRIPTION VARCHAR (1024), + ROLE_CLAIM VARCHAR (512), + AUTH_TYPE VARCHAR (255) NOT NULL, + PROVISIONING_USERSTORE_DOMAIN VARCHAR (512), + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '1', + IS_SEND_LOCAL_SUBJECT_ID CHAR(1) DEFAULT '0', + IS_SEND_AUTH_LIST_OF_IDPS CHAR(1) DEFAULT '0', + SUBJECT_CLAIM_URI VARCHAR (512), + IS_SAAS_APP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_NAME_CONSTRAINT UNIQUE(APP_NAME, TENANT_ID); + +CREATE TABLE IF NOT EXISTS SP_INBOUND_AUTH ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + INBOUND_AUTH_KEY VARCHAR (255) NOT NULL, + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + PROP_NAME VARCHAR (255), + PROP_VALUE VARCHAR (1024) , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_INBOUND_AUTH ADD CONSTRAINT APPLICATION_ID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_AUTH_STEP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + STEP_ORDER INTEGER DEFAULT 1, + APP_ID INTEGER NOT NULL , + IS_SUBJECT_STEP CHAR(1) DEFAULT '0', + IS_ATTRIBUTE_STEP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_AUTH_STEP ADD CONSTRAINT APPLICATION_ID_CONSTRAINT_STEP FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_FEDERATED_IDP ( + ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_ID INTEGER NOT NULL, + PRIMARY KEY (ID, AUTHENTICATOR_ID) +)ENGINE INNODB; + +ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_CLAIM VARCHAR (512) NOT NULL , + SP_CLAIM VARCHAR (512) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_REQUESTED VARCHAR(128) DEFAULT '0', + DEFAULT_VALUE VARCHAR(255), + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_CLAIM_MAPPING ADD CONSTRAINT CLAIMID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_ROLE_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_ROLE VARCHAR (255) NOT NULL , + SP_ROLE VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_ROLE_MAPPING ADD CONSTRAINT ROLEID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_REQ_PATH_AUTHENTICATOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_REQ_PATH_AUTHENTICATOR ADD CONSTRAINT REQ_AUTH_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_PROVISIONING_CONNECTOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_NAME VARCHAR (255) NOT NULL , + CONNECTOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_JIT_ENABLED CHAR(1) NOT NULL DEFAULT '0', + BLOCKING CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID) +)ENGINE INNODB; + +ALTER TABLE SP_PROVISIONING_CONNECTOR ADD CONSTRAINT PRO_CONNECTOR_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS IDP ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + NAME VARCHAR(254) NOT NULL, + IS_ENABLED CHAR(1) NOT NULL DEFAULT '1', + IS_PRIMARY CHAR(1) NOT NULL DEFAULT '0', + HOME_REALM_ID VARCHAR(254), + IMAGE MEDIUMBLOB, + CERTIFICATE BLOB, + ALIAS VARCHAR(254), + INBOUND_PROV_ENABLED CHAR (1) NOT NULL DEFAULT '0', + INBOUND_PROV_USER_STORE_ID VARCHAR(254), + USER_CLAIM_URI VARCHAR(254), + ROLE_CLAIM_URI VARCHAR(254), + DESCRIPTION VARCHAR (1024), + DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), + DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), + PROVISIONING_ROLE VARCHAR(128), + IS_FEDERATION_HUB CHAR(1) NOT NULL DEFAULT '0', + IS_LOCAL_CLAIM_DIALECT CHAR(1) NOT NULL DEFAULT '0', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, NAME) +)ENGINE INNODB; + +INSERT INTO IDP (TENANT_ID, NAME, HOME_REALM_ID) VALUES (-1234, 'LOCAL', 'localhost'); + +CREATE TABLE IF NOT EXISTS IDP_ROLE ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + ROLE VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, ROLE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_ROLE_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_ROLE_ID INTEGER, + TENANT_ID INTEGER, + USER_STORE_ID VARCHAR (253), + LOCAL_ROLE VARCHAR(253), + PRIMARY KEY (ID), + UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), + FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_CLAIM ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, CLAIM), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_CLAIM_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_CLAIM_ID INTEGER, + TENANT_ID INTEGER, + LOCAL_CLAIM VARCHAR(253), + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), + FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '1', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE INNODB; + +INSERT INTO IDP_AUTHENTICATOR (TENANT_ID, IDP_ID, NAME) VALUES (-1234, 1, 'samlsso'); + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + AUTHENTICATOR_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), + FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_CONFIG ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '0', + IS_BLOCKING CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_PROV_CONFIG_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048), + PROPERTY_BLOB_VALUE BLOB, + PROPERTY_TYPE CHAR(32) NOT NULL, + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, PROVISIONING_CONFIG_ID, PROPERTY_KEY), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_ENTITY ( + ID INTEGER AUTO_INCREMENT, + PROVISIONING_CONFIG_ID INTEGER, + ENTITY_TYPE VARCHAR(255) NOT NULL, + ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, + ENTITY_NAME VARCHAR(255) NOT NULL, + ENTITY_VALUE VARCHAR(255), + TENANT_ID INTEGER, + PRIMARY KEY (ID), + UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME), + UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDP_LOCAL_CLAIM ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + CLAIM_URI VARCHAR(255) NOT NULL, + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, CLAIM_URI), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE INNODB; +-- End of IDN-APPLICATION-MGT Tables-- + +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD STATE VARCHAR(30) DEFAULT 'COMPLETED'; + +ALTER TABLE AM_APPLICATION_KEY_MAPPING DROP PRIMARY KEY, ADD PRIMARY KEY(APPLICATION_ID,KEY_TYPE); + +CREATE TABLE IF NOT EXISTS AM_APPLICATION_REGISTRATION ( + REG_ID INT AUTO_INCREMENT, + SUBSCRIBER_ID INT, + WF_REF VARCHAR(255) NOT NULL, + APP_ID INT, + TOKEN_TYPE VARCHAR(30), + ALLOWED_DOMAINS VARCHAR(256), + VALIDITY_PERIOD BIGINT, + UNIQUE (SUBSCRIBER_ID,APP_ID,TOKEN_TYPE), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON UPDATE CASCADE ON DELETE RESTRICT, + FOREIGN KEY(APP_ID) REFERENCES AM_APPLICATION(APPLICATION_ID) ON UPDATE CASCADE ON DELETE RESTRICT, + PRIMARY KEY (REG_ID) +)ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS AM_API_SCOPES ( + API_ID INTEGER NOT NULL, + SCOPE_ID INTEGER NOT NULL, + FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE ON UPDATE CASCADE +)ENGINE = INNODB; + +CREATE TABLE IF NOT EXISTS AM_API_DEFAULT_VERSION ( + DEFAULT_VERSION_ID INT AUTO_INCREMENT, + API_NAME VARCHAR(256) NOT NULL , + API_PROVIDER VARCHAR(256) NOT NULL , + DEFAULT_API_VERSION VARCHAR(30) , + PUBLISHED_DEFAULT_API_VERSION VARCHAR(30) , + PRIMARY KEY (DEFAULT_VERSION_ID) +); diff --git a/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/oracle.sql b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/oracle.sql new file mode 100644 index 0000000000..0809fe4bc2 --- /dev/null +++ b/modules/distribution/resources/migration-1.6.0_to_1.7.0/wso2-api-migration-client/src/main/resources/migration-scripts/oracle.sql @@ -0,0 +1,697 @@ +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP COLUMN LOGIN_PAGE_URL +/ +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP COLUMN ERROR_PAGE_URL +/ +ALTER TABLE IDN_OAUTH_CONSUMER_APPS DROP COLUMN CONSENT_PAGE_URL +/ +/* +DROP INDEX IDX_AT_CK_AU +/ +DROP SEQUENCE IDP_SEQUENCE +/ +DROP SEQUENCE IDP_ROLE_MAPPINGS_SEQUENCE +/ +DROP SEQUENCE IDP_ROLES_SEQUENCE +/ +ALTER TABLE UM_TENANT_IDP_ROLE_MAPPINGS DROP PRIMARY KEY CASCADE +/ +ALTER TABLE UM_TENANT_IDP_ROLES DROP PRIMARY KEY CASCADE +/ +ALTER TABLE IDP_BASE_TABLE DROP PRIMARY KEY CASCADE +/ +ALTER TABLE UM_TENANT_IDP DROP PRIMARY KEY CASCADE +/ +DROP TABLE UM_TENANT_IDP_ROLE_MAPPINGS CASCADE CONSTRAINTS +/ +DROP TABLE UM_TENANT_IDP_ROLES CASCADE CONSTRAINTS +/ +DROP TABLE UM_TENANT_IDP CASCADE CONSTRAINTS +/ +DROP TABLE IDP_BASE_TABLE CASCADE CONSTRAINTS +/ +*/ +ALTER TABLE AM_API_URL_MAPPING ADD (MEDIATION_SCRIPT BLOB DEFAULT NULL) +/ +CREATE TABLE IDN_OAUTH2_SCOPE ( + SCOPE_ID INTEGER, + SCOPE_KEY VARCHAR2 (100) NOT NULL, + NAME VARCHAR2 (255) NULL, + DESCRIPTION VARCHAR2 (512) NULL, + TENANT_ID INTEGER DEFAULT 0 NOT NULL, + ROLES VARCHAR2 (500) NULL, + PRIMARY KEY (SCOPE_ID)) +/ +CREATE SEQUENCE IDN_OAUTH2_SCOPE_SEQUENCE START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_OAUTH2_SCOPE_TRIGGER + BEFORE INSERT + ON IDN_OAUTH2_SCOPE + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_OAUTH2_SCOPE_SEQUENCE.nextval INTO :NEW.SCOPE_ID FROM dual; + END; +/ +CREATE TABLE IDN_OAUTH2_RESOURCE_SCOPE ( + RESOURCE_PATH VARCHAR2 (255) NOT NULL, + SCOPE_ID INTEGER NOT NULL, + PRIMARY KEY (RESOURCE_PATH), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE +) +/ +CREATE TABLE IDN_SCIM_GROUP ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR2(255) NOT NULL, + ATTR_NAME VARCHAR2(1024) NOT NULL, + ATTR_VALUE VARCHAR2(1024), + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE IDN_SCIM_GROUP_SEQUENCE START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_SCIM_GROUP_TRIGGER + BEFORE INSERT + ON IDN_SCIM_GROUP + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_SCIM_GROUP_SEQUENCE.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDN_SCIM_PROVIDER ( + CONSUMER_ID VARCHAR(255) NOT NULL, + PROVIDER_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + USER_PASSWORD VARCHAR(255) NOT NULL, + USER_URL VARCHAR(1024) NOT NULL, + GROUP_URL VARCHAR(1024), + BULK_URL VARCHAR(1024), + PRIMARY KEY (CONSUMER_ID,PROVIDER_ID)) +/ +CREATE TABLE IDN_OPENID_REMEMBER_ME ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + COOKIE_VALUE VARCHAR(1024), + CREATED_TIME TIMESTAMP, + PRIMARY KEY (USER_NAME, TENANT_ID)) +/ +CREATE TABLE IDN_OPENID_ASSOCIATIONS ( + HANDLE VARCHAR(255) NOT NULL, + ASSOC_TYPE VARCHAR(255) NOT NULL, + EXPIRE_IN TIMESTAMP NOT NULL, + MAC_KEY VARCHAR(255) NOT NULL, + ASSOC_STORE VARCHAR(128) DEFAULT 'SHARED', + PRIMARY KEY (HANDLE)) +/ +CREATE TABLE IDN_STS_STORE ( + ID INTEGER, + TOKEN_ID VARCHAR(255) NOT NULL, + TOKEN_CONTENT BLOB NOT NULL, + CREATE_DATE TIMESTAMP NOT NULL, + EXPIRE_DATE TIMESTAMP NOT NULL, + STATE INTEGER DEFAULT 0, + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE IDN_STS_STORE_SEQUENCE START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_STS_STORE_TRIGGER + BEFORE INSERT + ON IDN_STS_STORE + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_STS_STORE_SEQUENCE.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDN_IDENTITY_USER_DATA ( + TENANT_ID INTEGER DEFAULT -1234, + USER_NAME VARCHAR(255) NOT NULL, + DATA_KEY VARCHAR(255) NOT NULL, + DATA_VALUE VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, DATA_KEY)) +/ +CREATE TABLE IDN_IDENTITY_META_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + METADATA_TYPE VARCHAR(255) NOT NULL, + METADATA VARCHAR(255) NOT NULL, + VALID VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, METADATA_TYPE,METADATA)) +/ +-- End of IDN Tables -- + + +-- Start of IDN-APPLICATION-MGT Tables-- + +CREATE TABLE SP_APP ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + APP_NAME VARCHAR (255) NOT NULL , + USER_STORE VARCHAR (255) NOT NULL, + USERNAME VARCHAR (255) NOT NULL , + DESCRIPTION VARCHAR (1024), + ROLE_CLAIM VARCHAR (512), + AUTH_TYPE VARCHAR (255) NOT NULL, + PROVISIONING_USERSTORE_DOMAIN VARCHAR (512), + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '1', + IS_SEND_LOCAL_SUBJECT_ID CHAR(1) DEFAULT '0', + IS_SEND_AUTH_LIST_OF_IDPS CHAR(1) DEFAULT '0', + SUBJECT_CLAIM_URI VARCHAR (512), + IS_SAAS_APP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_APP_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_APP_TRIG + BEFORE INSERT + ON SP_APP + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_APP_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE UNIQUE INDEX APPLICATION_NAME_CONSTRAINT ON SP_APP(APP_NAME, TENANT_ID) +/ +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_NAME_CONSTRAINT UNIQUE (APP_NAME, TENANT_ID) USING INDEX APPLICATION_NAME_CONSTRAINT +/ +CREATE TABLE SP_INBOUND_AUTH ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + INBOUND_AUTH_KEY VARCHAR (255) NOT NULL, + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + PROP_NAME VARCHAR (255), + PROP_VALUE VARCHAR (1024) , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_INBOUND_AUTH_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_INBOUND_AUTH_TRIG + BEFORE INSERT + ON SP_INBOUND_AUTH + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_INBOUND_AUTH_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +ALTER TABLE SP_INBOUND_AUTH ADD CONSTRAINT APPLICATION_ID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +/ +CREATE TABLE SP_AUTH_STEP ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + STEP_ORDER INTEGER DEFAULT 1, + APP_ID INTEGER NOT NULL , + IS_SUBJECT_STEP CHAR(1) DEFAULT '0', + IS_ATTRIBUTE_STEP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_AUTH_STEP_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_AUTH_STEP_TRIG + BEFORE INSERT + ON SP_AUTH_STEP + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_AUTH_STEP_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +ALTER TABLE SP_AUTH_STEP ADD CONSTRAINT APPLICATION_ID_CONSTRAINT_STEP FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +/ +CREATE TABLE SP_FEDERATED_IDP ( + ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_ID INTEGER NOT NULL, + PRIMARY KEY (ID, AUTHENTICATOR_ID)) +/ +ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE +/ +CREATE TABLE SP_CLAIM_MAPPING ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + IDP_CLAIM VARCHAR (512) NOT NULL , + SP_CLAIM VARCHAR (512) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_REQUESTED VARCHAR(128) DEFAULT '0', + DEFAULT_VALUE VARCHAR(255), + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_CLAIM_MAPPING_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_CLAIM_MAPPING_TRIG + BEFORE INSERT + ON SP_CLAIM_MAPPING + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_CLAIM_MAPPING_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +ALTER TABLE SP_CLAIM_MAPPING ADD CONSTRAINT CLAIMID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +/ +CREATE TABLE SP_ROLE_MAPPING ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + IDP_ROLE VARCHAR (255) NOT NULL , + SP_ROLE VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_ROLE_MAPPING_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_ROLE_MAPPING_TRIG + BEFORE INSERT + ON SP_ROLE_MAPPING + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_ROLE_MAPPING_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +ALTER TABLE SP_ROLE_MAPPING ADD CONSTRAINT ROLEID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +/ +CREATE TABLE SP_REQ_PATH_AUTHENTICATOR ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_REQ_PATH_AUTH_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_REQ_PATH_AUTH_TRIG + BEFORE INSERT + ON SP_REQ_PATH_AUTHENTICATOR + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_REQ_PATH_AUTH_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +ALTER TABLE SP_REQ_PATH_AUTHENTICATOR ADD CONSTRAINT REQ_AUTH_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +/ +CREATE TABLE SP_PROVISIONING_CONNECTOR ( + ID INTEGER, + TENANT_ID INTEGER NOT NULL, + IDP_NAME VARCHAR (255) NOT NULL , + CONNECTOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_JIT_ENABLED CHAR(1) DEFAULT '0', + BLOCKING CHAR(1) DEFAULT '0', + PRIMARY KEY (ID)) +/ +CREATE SEQUENCE SP_PROV_CONNECTOR_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER SP_PROV_CONNECTOR_TRIG + BEFORE INSERT + ON SP_PROVISIONING_CONNECTOR + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT SP_PROV_CONNECTOR_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +ALTER TABLE SP_PROVISIONING_CONNECTOR ADD CONSTRAINT PRO_CONNECTOR_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE +/ +CREATE TABLE IDP ( + ID INTEGER, + TENANT_ID INTEGER, + NAME VARCHAR(254) NOT NULL, + IS_ENABLED CHAR(1) DEFAULT '1', + IS_PRIMARY CHAR(1) DEFAULT '0', + HOME_REALM_ID VARCHAR(254), + IMAGE BLOB, + CERTIFICATE BLOB, + ALIAS VARCHAR(254), + INBOUND_PROV_ENABLED CHAR (1) DEFAULT '0', + INBOUND_PROV_USER_STORE_ID VARCHAR(254), + USER_CLAIM_URI VARCHAR(254), + ROLE_CLAIM_URI VARCHAR(254), + DESCRIPTION VARCHAR (1024), + DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), + DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), + PROVISIONING_ROLE VARCHAR(128), + IS_FEDERATION_HUB CHAR(1) DEFAULT '0', + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '0', + PRIMARY KEY (ID), + DISPLAY_NAME VARCHAR(254), + UNIQUE (TENANT_ID, NAME)) +/ +CREATE SEQUENCE IDP_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_TRIG + BEFORE INSERT + ON IDP + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +INSERT INTO IDP (TENANT_ID, NAME, HOME_REALM_ID) VALUES (-1234, 'LOCAL', 'localhost') +/ +CREATE TABLE IDP_ROLE ( + ID INTEGER, + IDP_ID INTEGER, + TENANT_ID INTEGER, + ROLE VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, ROLE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_ROLE_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_ROLE_TRIG + BEFORE INSERT + ON IDP_ROLE + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_ROLE_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_ROLE_MAPPING ( + ID INTEGER, + IDP_ROLE_ID INTEGER, + TENANT_ID INTEGER, + USER_STORE_ID VARCHAR (253), + LOCAL_ROLE VARCHAR(253), + PRIMARY KEY (ID), + UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), + FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_ROLE_MAPPING_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_ROLE_MAPPING_TRIG + BEFORE INSERT + ON IDP_ROLE_MAPPING + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_ROLE_MAPPING_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_CLAIM ( + ID INTEGER, + IDP_ID INTEGER, + TENANT_ID INTEGER, + CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, CLAIM), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE) +/ +CREATE TABLE IDP_CLAIM_MAPPING ( + ID INTEGER, + IDP_CLAIM_ID INTEGER, + TENANT_ID INTEGER, + LOCAL_CLAIM VARCHAR(253), + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), + FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_CLAIM_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_CLAIM_TRIG + BEFORE INSERT + ON IDP_CLAIM + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_CLAIM_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE SEQUENCE IDP_CLAIM_MAPPING_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_CLAIM_MAPPING_TRIG + BEFORE INSERT + ON IDP_CLAIM_MAPPING + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_CLAIM_MAPPING_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_AUTHENTICATOR ( + ID INTEGER, + TENANT_ID INTEGER, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '1', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_AUTHENTICATOR_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_AUTHENTICATOR_TRIG + BEFORE INSERT + ON IDP_AUTHENTICATOR + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_AUTHENTICATOR_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +INSERT INTO IDP_AUTHENTICATOR (TENANT_ID, IDP_ID, NAME) VALUES (-1234, 1, 'saml2sso') +/ +CREATE TABLE IDP_AUTHENTICATOR_PROPERTY ( + ID INTEGER, + TENANT_ID INTEGER, + AUTHENTICATOR_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), + FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_AUTHENTICATOR_PROP_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_AUTHENTICATOR_PROP_TRIG + BEFORE INSERT + ON IDP_AUTHENTICATOR_PROPERTY + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_AUTHENTICATOR_PROP_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_PROVISIONING_CONFIG ( + ID INTEGER, + TENANT_ID INTEGER, + IDP_ID INTEGER, + PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '0', + IS_BLOCKING CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_PROVISIONING_CONFIG_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_PROVISIONING_CONFIG_TRIG + BEFORE INSERT + ON IDP_PROVISIONING_CONFIG + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_PROVISIONING_CONFIG_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_PROV_CONFIG_PROPERTY ( + ID INTEGER, + TENANT_ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048), + PROPERTY_BLOB_VALUE BLOB, + PROPERTY_TYPE CHAR(32) NOT NULL, + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, PROVISIONING_CONFIG_ID, PROPERTY_KEY), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_PROV_CONFIG_PROP_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_PROV_CONFIG_PROP_TRIG + BEFORE INSERT + ON IDP_PROV_CONFIG_PROPERTY + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_PROV_CONFIG_PROP_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_PROVISIONING_ENTITY ( + ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + ENTITY_TYPE VARCHAR(255) NOT NULL, + ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, + ENTITY_NAME VARCHAR(255) NOT NULL, + ENTITY_VALUE VARCHAR(255), + TENANT_ID INTEGER, + PRIMARY KEY (ID), + UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME), + UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_PROV_ENTITY_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_PROV_ENTITY_TRIG + BEFORE INSERT + ON IDP_PROVISIONING_ENTITY + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_PROV_ENTITY_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDP_LOCAL_CLAIM ( + ID INTEGER, + TENANT_ID INTEGER, + IDP_ID INTEGER, + CLAIM_URI VARCHAR(255) NOT NULL, + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, CLAIM_URI), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE) +/ +CREATE SEQUENCE IDP_LOCAL_CLAIM_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDP_LOCAL_CLAIM_TRIG + BEFORE INSERT + ON IDP_LOCAL_CLAIM + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDP_LOCAL_CLAIM_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ + +-- End of IDN-APPLICATION-MGT Tables-- + +ALTER TABLE AM_APPLICATION_KEY_MAPPING DROP PRIMARY KEY CASCADE +/ +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD (STATE VARCHAR2(30 BYTE) DEFAULT 'COMPLETED' NOT NULL) +/ +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD PRIMARY KEY (APPLICATION_ID, KEY_TYPE) +/ +CREATE TABLE AM_APPLICATION_REGISTRATION ( + REG_ID INTEGER , + SUBSCRIBER_ID INTEGER, + WF_REF VARCHAR2(255) NOT NULL, + APP_ID INTEGER, + TOKEN_TYPE VARCHAR2(30), + ALLOWED_DOMAINS VARCHAR2(256), + VALIDITY_PERIOD NUMBER(19), + UNIQUE (SUBSCRIBER_ID,APP_ID,TOKEN_TYPE), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID), + FOREIGN KEY(APP_ID) REFERENCES AM_APPLICATION(APPLICATION_ID), + PRIMARY KEY (REG_ID) +) +/ +CREATE SEQUENCE AM_APP_REGISTRATION_SEQUENCE START WITH 1 INCREMENT BY 1 +/ +CREATE OR REPLACE TRIGGER AM_APP_REGISTRATION_TRIGGER + BEFORE INSERT + ON AM_APPLICATION_REGISTRATION + REFERENCING NEW AS NEW + FOR EACH ROW +BEGIN + SELECT AM_APP_REGISTRATION_SEQUENCE.nextval INTO :NEW.REG_ID FROM dual; + END; +/ +CREATE TABLE AM_API_SCOPES ( + API_ID INTEGER NOT NULL, + SCOPE_ID INTEGER NOT NULL, + FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE, + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE +) +/ +CREATE TABLE AM_API_DEFAULT_VERSION ( + DEFAULT_VERSION_ID NUMBER, + API_NAME VARCHAR(256) NOT NULL , + API_PROVIDER VARCHAR(256) NOT NULL , + DEFAULT_API_VERSION VARCHAR(30) , + PUBLISHED_DEFAULT_API_VERSION VARCHAR(30) , + PRIMARY KEY (DEFAULT_VERSION_ID) +) +/ +CREATE SEQUENCE AM_API_DEFAULT_VERSION_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER AM_API_DEFAULT_VERSION_TRG + BEFORE INSERT + ON AM_API_DEFAULT_VERSION + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT AM_API_DEFAULT_VERSION_SEQ.nextval INTO :NEW.DEFAULT_VERSION_ID FROM dual; + END; +/ +CREATE OR REPLACE FUNCTION DROP_ALL_SCHEMA_OBJECTS RETURN NUMBER AS +PRAGMA AUTONOMOUS_TRANSACTION; +cursor c_get_objects is + select object_type,'"'||object_name||'"'||decode(object_type,'TABLE' ,' cascade constraints',null) obj_name + from user_objects + where object_type in ('TABLE','VIEW','PACKAGE','SEQUENCE','SYNONYM', 'MATERIALIZED VIEW') + order by object_type; +cursor c_get_objects_type is + select object_type, '"'||object_name||'"' obj_name + from user_objects + where object_type in ('TYPE'); +BEGIN + begin + for object_rec in c_get_objects loop + execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name); + end loop; + for object_rec in c_get_objects_type loop + begin + execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name); + end; + end loop; + end; + RETURN 0; +END DROP_ALL_SCHEMA_OBJECTS; +/ +ALTER TABLE IDN_OAUTH2_ACCESS_TOKEN MODIFY(TOKEN_SCOPE VARCHAR2(2048 BYTE)) +/ +DECLARE +statement VARCHAR2(2000); +constr_name VARCHAR2(30); +BEGIN + SELECT CONSTRAINT_NAME INTO constr_name FROM USER_CONS_COLUMNS WHERE table_name = 'IDN_OAUTH1A_ACCESS_TOKEN' AND column_name = 'CONSUMER_KEY'; + statement := 'ALTER TABLE IDN_OAUTH1A_ACCESS_TOKEN DROP CONSTRAINT '|| constr_name; + EXECUTE IMMEDIATE(statement); +END; +/ +ALTER TABLE IDN_OAUTH1A_ACCESS_TOKEN ADD FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS (CONSUMER_KEY) ON DELETE CASCADE +/ +DECLARE +statement VARCHAR2(2000); +constr_name VARCHAR2(30); +BEGIN + SELECT CONSTRAINT_NAME INTO constr_name FROM USER_CONS_COLUMNS WHERE table_name = 'IDN_OAUTH1A_REQUEST_TOKEN' AND column_name = 'CONSUMER_KEY'; + statement := 'ALTER TABLE IDN_OAUTH1A_REQUEST_TOKEN DROP CONSTRAINT '|| constr_name; + EXECUTE IMMEDIATE(statement); +END; +/ +ALTER TABLE IDN_OAUTH1A_REQUEST_TOKEN ADD FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS (CONSUMER_KEY) ON DELETE CASCADE +/ +DECLARE +statement VARCHAR2(2000); +constr_name VARCHAR2(30); +BEGIN + SELECT CONSTRAINT_NAME INTO constr_name FROM USER_CONS_COLUMNS WHERE table_name = 'IDN_OAUTH2_AUTHORIZATION_CODE' AND column_name = 'CONSUMER_KEY'; + statement := 'ALTER TABLE IDN_OAUTH2_AUTHORIZATION_CODE DROP CONSTRAINT '|| constr_name; + EXECUTE IMMEDIATE(statement); +END; +/ +ALTER TABLE IDN_OAUTH2_AUTHORIZATION_CODE ADD FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS (CONSUMER_KEY) ON DELETE CASCADE +/ + diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/pom.xml b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/pom.xml new file mode 100644 index 0000000000..dd9c729238 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/pom.xml @@ -0,0 +1,164 @@ + + + 4.0.0 + + org.wso2.carbon + org.wso2.carbon.apimgt.migrate.client + 1.8.0 + bundle + + + + wso2-nexus + WSO2 internal Repository + http://maven.wso2.org/nexus/content/groups/wso2-public/ + + true + daily + ignore + + + + wso2.releases + WSO2 internal Repository + http://maven.wso2.org/nexus/content/repositories/releases/ + + true + daily + ignore + + + + wso2.snapshots + WSO2 Snapshot Repository + http://maven.wso2.org/nexus/content/repositories/snapshots/ + + true + daily + + + false + + + + + + + + org.apache.felix + maven-scr-plugin + ${org.apache.felix.src.plugin.version} + + + generate-scr-scrdescriptor + + scr + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + + + + org.apache.felix + maven-bundle-plugin + true + ${org.apache.felix.budnle.plugin.version} + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.carbon.apimgt.migration.client.internal + + + org.apache.commons.logging.*; version=${org.wso2.carbon.logging.import.version}, + org.wso2.carbon.registry.core.* version=${org.wso2.carbon.registry.core.import.version}, + org.wso2.carbon.apimgt.impl, + *;resolution:=optional + + * + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.5.3 + + + dist + package + + attached + + + false + src/assembly/dist.xml + wso2-api-migration-client-${project.version} + + + + + + + + + + + + + org.wso2.carbon + org.wso2.carbon.core.services + ${org.wso2.carbon.core.services.version} + + + org.wso2.carbon + org.wso2.carbon.logging + ${org.wso2.carbon.logging.version} + + + org.wso2.carbon + org.wso2.carbon.registry.core + ${org.wso2.carbon.registry.core.version} + + + org.wso2.carbon + org.wso2.carbon.utils + ${org.wso2.carbon.utils.version} + + + org.wso2.carbon + org.wso2.carbon.apimgt.impl + 1.2.3 + + + org.wso2.carbon + org.wso2.carbon.apimgt.api + 1.2.3 + + + + + UTF-8 + 1.7.2 + 2.5.3 + 4.2.0 + 4.2.0 + 1.0.4 + 4.2.0 + 4.2.0 + 1.0.1 + + + + \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/assembly/dist.xml b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/assembly/dist.xml new file mode 100644 index 0000000000..e6caed26d2 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/assembly/dist.xml @@ -0,0 +1,27 @@ + + dist + + zip + + false + + + ${project.basedir} + + + README* + + + + ${project.basedir}/src/main/resources + + + + ${project.build.directory} + + + *.jar + + + + \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/APIMigrationException.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/APIMigrationException.java new file mode 100644 index 0000000000..6250855b6e --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/APIMigrationException.java @@ -0,0 +1,35 @@ +/* +* 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.migration; + +/** + * A custom exception handler class to handle all the migration exceptions + */ +public class APIMigrationException extends Exception { + + public APIMigrationException(String msg) { + super(msg); + } + + public APIMigrationException(String msg, Throwable e) { + super(msg, e); + } + + public APIMigrationException(Throwable throwable) { + super(throwable); + } +} \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom17to18.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom17to18.java new file mode 100644 index 0000000000..bcbf424df8 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom17to18.java @@ -0,0 +1,202 @@ +/* +* 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.migration.client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.api.APIManagementException; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.internal.ServiceHolder; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.base.MultitenantConstants; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.governance.api.generic.GenericArtifactManager; +import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; +import org.wso2.carbon.governance.api.util.GovernanceUtils; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.core.Registry; +import org.wso2.carbon.registry.core.session.UserRegistry; +import org.wso2.carbon.user.api.Tenant; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.tenant.TenantManager; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + + +/** + * This class contains all the methods which is used to migrate APIs from APIManager 1.8.0 to APIManager 1.9.0. + * The migration performs in database, registry and file system + */ + +@SuppressWarnings("unchecked") +public class MigrateFrom17to18 { + + private static final Log log = LogFactory.getLog(MigrateFrom17to18.class); + private List tenantsArray; + + public MigrateFrom17to18(String tenantArguments) throws UserStoreException { + TenantManager tenantManager = ServiceHolder.getRealmService().getTenantManager(); + + if (tenantArguments != null) { // Tenant arguments have been provided so need to load specific ones + tenantArguments = tenantArguments.replaceAll("\\s", ""); // Remove spaces and tabs + + tenantsArray = new ArrayList(); + + if (tenantArguments.contains(",")) { // Multiple arguments specified + String[] parts = tenantArguments.split(","); + + for (int i = 0; i < parts.length; ++i) { + if (parts[i].length() > 0) { + populateTenants(tenantManager, tenantsArray, parts[i]); + } + } + } else { // Only single argument provided + populateTenants(tenantManager, tenantsArray, tenantArguments); + } + } else { // Load all tenants + tenantsArray = new ArrayList(Arrays.asList(tenantManager.getAllTenants())); + Tenant superTenant = new Tenant(); + superTenant.setDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + superTenant.setId(MultitenantConstants.SUPER_TENANT_ID); + tenantsArray.add(superTenant); + } + } + + private void populateTenants(TenantManager tenantManager, List tenantList, String argument) throws UserStoreException { + log.debug("Argument provided : " + argument); + + if (argument.contains("@")) { // Username provided as argument + int tenantID = tenantManager.getTenantId(argument); + + if (tenantID != -1) { + tenantList.add(tenantManager.getTenant(tenantID)); + } else { + log.error("Tenant does not exist for username " + argument); + } + } else { // Domain name provided as argument + Tenant[] tenants = tenantManager.getAllTenantsForTenantDomainStr(argument); + + if (tenants.length > 0) { + tenantList.addAll(Arrays.asList(tenants)); + } else { + log.error("Tenant does not exist for domain " + argument); + } + } + } + + + /** + * This method is used to migrate all registry resources + * This migrates swagger resources and rxts + * + * @throws APIMigrationException + */ + public void registryResourceMigration() throws APIMigrationException { + swaggerMigration(); + } + + + /** + * This method is used to migrate swagger v1.2 resources to swagger v2.0 resource + * This reads the swagger v1.2 doc from the registry and creates swagger v2.0 doc + * + * @throws APIMigrationException + */ + void swaggerMigration() { + log.info("Swagger migration for API Manager 1.9.0 started."); + boolean isTenantFlowStarted = false; + + for (Tenant tenant : tenantsArray) { + if (log.isDebugEnabled()) { + log.debug("Start swaggerMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + try { + PrivilegedCarbonContext.startTenantFlow(); + isTenantFlowStarted = true; + + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId()); + + Registry registry = getRegistry(tenant); + + if (registry != null) { + GenericArtifactManager artifactManager = APIUtil.getArtifactManager(registry, APIConstants.API_KEY); + GenericArtifact[] artifacts = getGenericArtifacts(registry, artifactManager); + + if (artifacts != null) { + RegistryMigration.swagger12Migration(artifacts, registry, tenant); + } + } + } catch (APIManagementException e) { + log.error("Error when getting GenericArtifactManager for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } + } + + log.debug("End swaggerMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + log.info("Swagger resource migration done for all the tenants."); + } + + private Registry getRegistry(Tenant tenant) { + log.debug("Calling getRegistry"); + Registry registry = null; + + try { + String adminName = ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getRealmConfiguration().getAdminUserName(); + log.debug("Tenant admin username : " + adminName); + registry = ServiceHolder.getRegistryService().getGovernanceUserRegistry(adminName, tenant.getId()); + ServiceHolder.getTenantRegLoader().loadTenantRegistry(tenant.getId()); + } catch (UserStoreException e) { + log.error("Error occurred while reading tenant information of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (RegistryException e) { + log.error("Error occurred while accessing the registry of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } + + return registry; + } + + + private GenericArtifact[] getGenericArtifacts(Registry registry, GenericArtifactManager manager) { + log.debug("Calling getGenericArtifacts"); + GenericArtifact[] artifacts = null; + + try { + if (GovernanceUtils.findGovernanceArtifactConfiguration(Constants.API, registry) != null) { + GovernanceUtils.loadGovernanceArtifacts((UserRegistry) registry); + artifacts = manager.getAllGenericArtifacts(); + + log.debug("Total number of api artifacts : " + artifacts.length); + } else { + log.debug("API artifacts do not exist in registry"); + } + + } catch (RegistryException e) { + log.error("Error occurred when getting GenericArtifacts from registry", e); + } + + return artifacts; + } + +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java new file mode 100644 index 0000000000..a8949f1140 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java @@ -0,0 +1,206 @@ +/* +* 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.migration.client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.apimgt.migration.util.ResourceUtil; +import org.wso2.carbon.utils.CarbonUtils; +import org.wso2.carbon.utils.dbcreator.DatabaseCreator; + +import javax.sql.DataSource; +import java.io.*; +import java.sql.*; +import java.util.StringTokenizer; + +public class MigrationDBCreator extends DatabaseCreator { + + private static final Log log = LogFactory.getLog(MigrationDBCreator.class); + private DataSource dataSource; + private String delimiter = ";"; + private Connection connection = null; + Statement statement; + + public MigrationDBCreator(DataSource dataSource) { + super(dataSource); + this.dataSource = dataSource; + } + + @Override + protected String getDbScriptLocation(String databaseType) { + String scriptName = databaseType + ".sql"; + String resourcePath = CarbonUtils.getCarbonHome() + "/dbscripts/migration-1.8.0_to_1.9.0/"; + if (log.isDebugEnabled()) { + log.debug("Loading database script :" + scriptName); + } + return resourcePath + scriptName; + } + + @Override + public void createRegistryDatabase() throws SQLException, APIMigrationException { + try { + connection = dataSource.getConnection(); + connection.setAutoCommit(false); + statement = connection.createStatement(); + executeSQLScript(); + connection.commit(); + if (log.isTraceEnabled()) { + log.trace("Registry tables are created successfully."); + } + } catch (SQLException e) { + ResourceUtil.handleException("Error occurred while migrating the database", e); + } catch (Exception e) { + /* executeSQLScript throws generic Exception because DatabaseCreator.getDatabaseType superclass throws */ + ResourceUtil.handleException("Error occurred while executing sql script", e); + } finally { + if (connection != null) { + connection.close(); + } + + } + } + + + //org.wso2.carbon.utils.dbcreator.DatabaseCreator.getDatabaseType throws generic Exception + private void executeSQLScript() throws Exception { + String databaseType = DatabaseCreator.getDatabaseType(this.connection); + boolean keepFormat = false; + if (Constants.DB_TYPE_ORACLE.equals(databaseType)) { + delimiter = "/"; + } else if (Constants.DB_TYPE_DB2.equals(databaseType)) { + delimiter = "/"; + } else if (Constants.DB_TYPE_OPENEDGE.equals(databaseType)) { + delimiter = "/"; + keepFormat = true; + } + + String dbscriptName = getDbScriptLocation(databaseType); + + StringBuffer sql = new StringBuffer(); + BufferedReader reader = null; + + try { + InputStream is = new FileInputStream(dbscriptName); + reader = new BufferedReader(new InputStreamReader(is, "UTF8")); + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (!keepFormat) { + if (line.startsWith("//")) { + continue; + } + if (line.startsWith("--")) { + continue; + } + StringTokenizer st = new StringTokenizer(line); + if (st.hasMoreTokens()) { + String token = st.nextToken(); + if ("REM".equalsIgnoreCase(token)) { + continue; + } + } + } + sql.append(keepFormat ? "\n" : " ").append(line); + + // SQL defines "--" as a comment to EOL + // and in Oracle it may contain a hint + // so we cannot just remove it, instead we must end it + if (!keepFormat && line.indexOf("--") >= 0) { + sql.append("\n"); + } + if ((checkStringBufferEndsWith(sql, delimiter))) { + executeSQL(sql.substring(0, sql.length() - delimiter.length())); + sql.replace(0, sql.length(), ""); + } + } + // Catch any statements not followed by ; + if (sql.length() > 0) { + executeSQL(sql.toString()); + } + } catch (IOException e) { + log.error("Error occurred while executing SQL script for creating registry database", e); + throw new APIMigrationException("Error occurred while executing SQL script for creating registry database", e); + + } finally { + if (reader != null) { + reader.close(); + } + } + } + + + private void executeSQL(String sql) throws APIMigrationException { + // Check and ignore empty statements + if ("".equals(sql.trim())) { + return; + } + + ResultSet resultSet = null; + try { + if (log.isDebugEnabled()) { + log.debug("SQL : " + sql); + } + + boolean returnedValue; + int updateCount; + int updateCountTotal = 0; + returnedValue = statement.execute(sql); + updateCount = statement.getUpdateCount(); + resultSet = statement.getResultSet(); + do { + if (!returnedValue && updateCount != -1) { + updateCountTotal += updateCount; + } + returnedValue = statement.getMoreResults(); + if (returnedValue) { + updateCount = statement.getUpdateCount(); + resultSet = statement.getResultSet(); + } + } while (returnedValue); + + if (log.isDebugEnabled()) { + log.debug(sql + " : " + updateCountTotal + " rows affected"); + } + SQLWarning warning = connection.getWarnings(); + while (warning != null) { + log.debug(warning + " sql warning"); + warning = warning.getNextWarning(); + } + connection.clearWarnings(); + } catch (SQLException e) { + if (e.getSQLState().equals("X0Y32") || e.getSQLState().equals("42710")) { + // eliminating the table already exception for the derby and DB2 database types + if (log.isDebugEnabled()) { + log.info("Table Already Exists. Hence, skipping table creation"); + } + } else { + throw new APIMigrationException("Error occurred while executing : " + sql, e); + } + } finally { + if (resultSet != null) { + try { + resultSet.close(); + } catch (SQLException e) { + log.error("Error occurred while closing result set.", e); + } + } + } + } + +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/RegistryMigration.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/RegistryMigration.java new file mode 100644 index 0000000000..cb07af233b --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/RegistryMigration.java @@ -0,0 +1,129 @@ +/* +* 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.migration.client; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +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.Documentation; +import org.wso2.carbon.apimgt.api.model.URITemplate; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.internal.ServiceHolder; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.apimgt.migration.util.ResourceUtil; +import org.wso2.carbon.governance.api.exception.GovernanceException; +import org.wso2.carbon.governance.api.generic.GenericArtifactManager; +import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.core.*; +import org.wso2.carbon.user.api.Tenant; +import org.wso2.carbon.user.api.UserStoreException; + +import java.io.UnsupportedEncodingException; +import java.util.*; + +public class RegistryMigration { + private static final Log log = LogFactory.getLog(RegistryMigration.class); + + + public static void swagger12Migration(GenericArtifact[] artifacts, Registry registry, Tenant tenant) { + for (GenericArtifact artifact : artifacts) { + API api = getAPI(artifact); + + if (api != null) { + APIIdentifier apiIdentifier = api.getId(); + try { + String apiDef11Path = APIUtil.getAPIDefinitionFilePath(apiIdentifier.getApiName(), + apiIdentifier.getVersion(), + apiIdentifier.getProviderName()); + + if (!registry.resourceExists(apiDef11Path)) { + log.error("Swagger 1.1 document does not exist for api " + + apiIdentifier.getApiName() + "-" + apiIdentifier.getVersion() + "-" + apiIdentifier.getProviderName() + + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + continue; + } + + Resource apiDef11 = registry.get(apiDef11Path); + + String apiDef11Json = new String((byte[]) apiDef11.getContent(), "UTF8"); + + String swagger12location = ResourceUtil.getSwagger12ResourceLocation(apiIdentifier.getApiName(), + apiIdentifier.getVersion(), + apiIdentifier.getProviderName()); + + if(!registry.resourceExists(swagger12location)) { + log.error("Swagger 1.2 document does not exist for api " + + apiIdentifier.getApiName() + "-" + apiIdentifier.getVersion() + "-" + apiIdentifier.getProviderName() + + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } else { + String allResourceFile = swagger12location + RegistryConstants.PATH_SEPARATOR + + Constants.API_DOC_12_ALL_RESOURCES_DOC; + if(registry.resourceExists(allResourceFile)) { + //no need to update the swagger doc 1.2 with 1.1 doc because it has already happened + //remove parameters to suit AM 1.8 + log.debug("Remove unwanted parameters from swagger 1.2 doc for api : " + apiIdentifier.getApiName() + "-" + apiIdentifier.getVersion() + "-" + apiIdentifier.getProviderName() + + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + ResourceUtil.updateSwagger12ResourcesForAM18(new String[]{allResourceFile}, registry); + } else { + Resource swagger12Res = registry.get(swagger12location); + String[] resourcePaths = (String[]) swagger12Res.getContent(); + + log.debug("Updating swagger 1.2 resource using 1.1 for api : " + apiIdentifier.getApiName() + "-" + apiIdentifier.getVersion() + "-" + apiIdentifier.getProviderName() + + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + ResourceUtil.updateAPISwaggerDocs(apiDef11Json, resourcePaths, registry); + //remove paramaters to suit AM 1.8 + ResourceUtil.updateSwagger12ResourcesForAM18(resourcePaths, registry); + log.debug("Remove unwanted parameters from swagger 1.2 doc for api : " + apiIdentifier.getApiName() + "-" + apiIdentifier.getVersion() + "-" + apiIdentifier.getProviderName() + + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + } + } catch (ParseException e) { + log.error("ParseException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (RegistryException e) { + log.error("RegistryException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (UnsupportedEncodingException e) { + log.error("UnsupportedEncodingException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (APIMigrationException e) { + log.error("APIMigrationException thrown when migrating swagger for api " + api.getId().getApiName() + "-" + api.getId().getVersion() + "-" + api.getId().getProviderName() + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } + } + } + } + + + private static API getAPI(GenericArtifact artifact) { + log.debug("Calling getAPI"); + API api = null; + + try { + api = APIUtil.getAPI(artifact); + } catch (APIManagementException e) { + log.error("Error when getting api artifact " + artifact.getId() + " from registry", e); + } + + return api; + } +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java new file mode 100644 index 0000000000..9dbca05f61 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java @@ -0,0 +1,247 @@ +/* +* 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.migration.client.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.wso2.carbon.apimgt.impl.APIManagerConfigurationService; +import org.wso2.carbon.apimgt.impl.utils.APIMgtDBUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.MigrateFrom17to18; +import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.registry.core.service.RegistryService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.service.RealmService; +import org.wso2.carbon.utils.CarbonUtils; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; + + +/** + * @scr.component name="org.wso2.carbon.apimgt.migration.client" immediate="true" + * @scr.reference name="realm.service" + * interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1" + * policy="dynamic" bind="setRealmService" unbind="unsetRealmService" + * @scr.reference name="registry.service" + * interface="org.wso2.carbon.registry.core.service.RegistryService" cardinality="1..1" + * policy="dynamic" bind="setRegistryService" unbind="unsetRegistryService" + * @scr.reference name="registry.core.dscomponent" + * interface="org.wso2.carbon.registry.core.service.RegistryService" cardinality="1..1" + * policy="dynamic" bind="setRegistryService" unbind="unsetRegistryService" + * @scr.reference name="tenant.registryloader" interface="org.wso2.carbon.registry.core.service.TenantRegistryLoader" cardinality="1..1" + * policy="dynamic" bind="setTenantRegistryLoader" unbind="unsetTenantRegistryLoader" + * @scr.reference name="apim.configuration" interface="org.wso2.carbon.apimgt.impl.APIManagerConfigurationService" cardinality="1..1" + * policy="dynamic" bind="setApiManagerConfig" unbind="unsetApiManagerConfig" + */ + +@SuppressWarnings("unused") +public class APIMMigrationServiceComponent { + + private static final Log log = LogFactory.getLog(APIMMigrationServiceComponent.class); + + /** + * Method to activate bundle. + * + * @param context OSGi component context. + */ + protected void activate(ComponentContext context) { + boolean isCorrectProductVersion = false; + try { + APIMgtDBUtil.initialize(); + } catch (Exception e) { + //APIMgtDBUtil.initialize() throws generic exception + log.error("Error occurred while initializing DB Util ", e); + } + + // Product and version validation + File carbonXmlConfig = new File(CarbonUtils.getServerXml()); + + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + + try { + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(carbonXmlConfig); + + doc.getDocumentElement().normalize(); + + NodeList nameNodes = doc.getElementsByTagName("Name"); + + if (nameNodes.getLength() > 0) { + Element name = (Element) nameNodes.item(0); + if (Constants.APIM_PRODUCT_NAME.equals(name.getTextContent())) { + NodeList versionNodes = doc.getElementsByTagName("Version"); + + if (versionNodes.getLength() > 0) { + Element version = (Element) versionNodes.item(0); + if (Constants.VERSION_1_8.equals(version.getTextContent())) { + isCorrectProductVersion = true; + } + } + } + } + } catch (ParserConfigurationException e) { + log.error("ParserConfigurationException when processing carbon.xml", e); + } catch (SAXException e) { + log.error("SAXException when processing carbon.xml", e); + } catch (IOException e) { + log.error("IOException when processing carbon.xml", e); + } + + String tenants = System.getProperty(Constants.ARG_MIGRATE_TENANTS); + boolean migrateAll = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_ALL)); + + try { + if (isCorrectProductVersion) { + log.info("Migrating WSO2 API Manager " + Constants.PREVIOUS_VERSION + " to WSO2 API Manager " + Constants.VERSION_1_8); + + // Create a thread and wait till the APIManager DBUtils is initialized + + MigrateFrom17to18 migrateFrom17to18 = new MigrateFrom17to18(tenants); + + boolean isArgumentValid = false; + + //Default operation will migrate all three types of resources + if (migrateAll) { + log.info("Migrating WSO2 API Manager " + Constants.PREVIOUS_VERSION + " resources to WSO2 API Manager " + Constants.VERSION_1_8); + migrateFrom17to18.registryResourceMigration(); + isArgumentValid = true; + } + + if (isArgumentValid) { + log.info("API Manager " + Constants.PREVIOUS_VERSION + " to " + Constants.VERSION_1_8 + " migration successfully completed"); + } + } else { + log.error("Migration client installed in incompatible product version. This migration client is only compatible with " + + Constants.APIM_PRODUCT_NAME + " " + Constants.VERSION_1_8 + ". Please verify the product/version in use."); + } + } catch (APIMigrationException e) { + log.error("API Management exception occurred while migrating", e); + } catch (UserStoreException e) { + log.error("User store exception occurred while migrating", e); + } catch (Exception e) { + log.error("Generic exception occurred while migrating", e); + } catch (Throwable t) { + log.error("Throwable error", t); + } + log.info("WSO2 API Manager migration component successfully activated."); + } + + /** + * Method to deactivate bundle. + * + * @param context OSGi component context. + */ + protected void deactivate(ComponentContext context) { + log.info("WSO2 API Manager migration bundle is deactivated"); + } + + /** + * Method to set registry service. + * + * @param registryService service to get tenant data. + */ + protected void setRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { + log.debug("Setting RegistryService for WSO2 API Manager migration"); + } + ServiceHolder.setRegistryService(registryService); + } + + /** + * Method to unset registry service. + * + * @param registryService service to get registry data. + */ + protected void unsetRegistryService(RegistryService registryService) { + if (log.isDebugEnabled()) { + log.debug("Unset Registry service"); + } + ServiceHolder.setRegistryService(null); + } + + /** + * Method to set realm service. + * + * @param realmService service to get tenant data. + */ + protected void setRealmService(RealmService realmService) { + log.debug("Setting RealmService for WSO2 API Manager migration"); + ServiceHolder.setRealmService(realmService); + } + + /** + * Method to unset realm service. + * + * @param realmService service to get tenant data. + */ + protected void unsetRealmService(RealmService realmService) { + if (log.isDebugEnabled()) { + log.debug("Unset Realm service"); + } + ServiceHolder.setRealmService(null); + } + + /** + * Method to set tenant registry loader + * + * @param tenantRegLoader tenant registry loader + */ + protected void setTenantRegistryLoader(TenantRegistryLoader tenantRegLoader) { + log.debug("Setting TenantRegistryLoader for WSO2 API Manager migration"); + ServiceHolder.setTenantRegLoader(tenantRegLoader); + } + + /** + * Method to unset tenant registry loader + * + * @param tenantRegLoader tenant registry loader + */ + protected void unsetTenantRegistryLoader(TenantRegistryLoader tenantRegLoader) { + log.debug("Unset Tenant Registry Loader"); + ServiceHolder.setTenantRegLoader(null); + } + + /** + * Method to set API Manager configuration + * + * @param apiManagerConfig api manager configuration + */ + protected void setApiManagerConfig(APIManagerConfigurationService apiManagerConfig) { + log.info("Setting APIManager configuration"); + } + + /** + * Method to unset API manager configuration + * + * @param apiManagerConfig api manager configuration + */ + protected void unsetApiManagerConfig(APIManagerConfigurationService apiManagerConfig) { + log.info("Un-setting APIManager configuration"); + } + +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/ServiceHolder.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/ServiceHolder.java new file mode 100644 index 0000000000..b03635c444 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/ServiceHolder.java @@ -0,0 +1,86 @@ +/* +* 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.migration.client.internal; + +import org.wso2.carbon.registry.core.service.RegistryService; +import org.wso2.carbon.registry.core.service.TenantRegistryLoader; +import org.wso2.carbon.user.core.service.RealmService; + +@SuppressWarnings("unused") +public class ServiceHolder { + //Registry Service which is used to get registry data. + private static RegistryService registryService; + + //Realm Service which is used to get tenant data. + private static RealmService realmService; + + //Tenant registry loader which is used to load tenant registry + private static TenantRegistryLoader tenantRegLoader; + + /** + * Method to get RegistryService. + * + * @return registryService. + */ + public static RegistryService getRegistryService() { + return registryService; + } + + /** + * Method to set registry RegistryService. + * + * @param service registryService. + */ + public static void setRegistryService(RegistryService service) { + registryService = service; + } + + /** + * This method used to get RealmService. + * + * @return RealmService. + */ + public static RealmService getRealmService() { + return realmService; + } + + /** + * Method to set registry RealmService. + * + * @param service RealmService. + */ + public static void setRealmService(RealmService service) { + realmService = service; + } + + /** + * This method used to get TenantRegistryLoader + * + * @return tenantRegLoader Tenant registry loader for load tenant registry + */ + public static TenantRegistryLoader getTenantRegLoader() { + return tenantRegLoader; + } + + /** + * This method used to set TenantRegistryLoader + * + * @param service Tenant registry loader for load tenant registry + */ + public static void setTenantRegLoader(TenantRegistryLoader service) { + tenantRegLoader = service; + } +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java new file mode 100644 index 0000000000..3b37ba6dab --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java @@ -0,0 +1,101 @@ +/* +* 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.migration.util; + +public class Constants { + public static final String APIM_PRODUCT_NAME = "WSO2 API Manager"; + public static final String PREVIOUS_VERSION = "1.7.0"; + public static final String VERSION_1_8 = "1.8.0"; + public static final String LINE_BREAK = "\\n"; + public static final String CONSTRAINT = "constraint"; + public static final String API = "api"; + public static final String MIGRATION_SCRIPTS_FOLDER = "migration-scripts"; + + // Migration client argument property names + public static final String ARG_MIGRATE_TO_VERSION = "migrateToVersion"; + public static final String ARG_MIGRATE_TENANTS = "tenants"; + public static final String ARG_MIGRATE_ALL = "migrate"; + + // Synapse configuration related + public static final String SYNAPSE_API_ROOT_ELEMENT = "api"; + public static final String SYNAPSE_API_ATTRIBUTE_VERSION = "version"; + + /* + * Variables in api_doc.json version 1.1 + */ + + public static final String API_DOC_11_BASE_PATH = "basePath"; + public static final String API_DOC_11_RESOURCE_PATH = "resourcePath"; + public static final String API_DOC_11_API_VERSION = "apiVersion"; + public static final String API_DOC_11_APIS = "apis"; + public static final String API_DOC_11_PATH = "path"; + public static final String API_DOC_11_OPERATIONS = "operations"; + public static final String API_DOC_11_METHOD = "httpMethod"; + public static final String API_DOC_11_PARAMETERS = "parameters"; + + /* + * Variables in api_doc.json version 1.2 + */ + + public static final String API_DOC_12_BASE_PATH = "basePath"; + public static final String API_DOC_12_APIS = "apis"; + public static final String API_DOC_12_PATH = "path"; + public static final String API_DOC_12_OPERATIONS = "operations"; + public static final String API_DOC_12_METHOD = "method"; + public static final String API_DOC_12_PARAMETERS = "parameters"; + public static final String API_DOC_12_NICKNAME = "nickname"; + //this resource contains all the resources. This is introduced to swagger 1.2 location to hold + //all the resource during the migration of 1.6. AM 1.6 does not have resources seperated by name + //so all resources are in one doc + public static final String API_DOC_12_ALL_RESOURCES_DOC = "resources"; + + /** + * default parameter array + */ + public static final String DEFAULT_PARAM_ARRAY = "[ " + " { " + + " \"dataType\": \"String\", " + + " \"description\": \"Access Token\", " + + " \"name\": \"Authorization\", " + + " \"allowMultiple\": false, " + + " \"required\": true, " + + " \"paramType\": \"header\" " + " }, " + + " { " + + " \"description\": \"Request Body\", " + + " \"name\": \"body\", " + + " \"allowMultiple\": false, " + + " \"type\": \"string\", " + + " \"required\": true, " + + " \"paramType\": \"body\" " + " } " + + "]"; + + public static final String DEFAULT_PARAM_FOR_URL_TEMPLATE = " { " + + "\"name\": \"\", " + + "\"allowMultiple\": false, " + + "\"required\": true, " + + "\"type\": \"string\", " + + "\"paramType\": \"path\" " + + "}"; + + + //database types + public static final String DB_TYPE_ORACLE = "oracle"; + public static final String DB_TYPE_DB2 = "db2"; + public static final String DB_TYPE_MYSQL= "mysql"; + public static final String DB_TYPE_MSSQL = "mssql"; + public static final String DB_TYPE_POSTGRE = "postgre"; + public static final String DB_TYPE_OPENEDGE = "openedge"; +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java new file mode 100644 index 0000000000..d2fbee5974 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java @@ -0,0 +1,696 @@ +/* +* 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.migration.util; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.wso2.carbon.apimgt.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.utils.APIMgtDBUtil; +import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.client.MigrationDBCreator; +import org.wso2.carbon.registry.core.Registry; +import org.wso2.carbon.registry.core.RegistryConstants; +import org.wso2.carbon.registry.core.Resource; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.utils.CarbonUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ResourceUtil { + + private static final Log log = LogFactory.getLog(ResourceUtil.class); + + /** + * location for the swagger 1.2 resources + * + * @param apiName api name + * @param apiVersion api version + * @param apiProvider api provider + * @return swagger v1.2 location + */ + public static String getSwagger12ResourceLocation(String apiName, String apiVersion, String apiProvider) { + return APIConstants.API_DOC_LOCATION + RegistryConstants.PATH_SEPARATOR + apiName + "-" + apiVersion + "-" + + apiProvider + RegistryConstants.PATH_SEPARATOR + APIConstants.API_DOC_1_2_LOCATION; + } + + + /** + * This method picks the query according to the users database + * + * @return exact query to execute + * @throws SQLException + * @throws APIMigrationException + * @throws IOException + */ + public static String pickQueryFromResources(String queryType) throws SQLException, APIMigrationException, + IOException { + + String queryTobeExecuted; + try { + String databaseType = MigrationDBCreator.getDatabaseType(APIMgtDBUtil.getConnection()); + + //pick from 18to19Migration/sql-scripts + String resourcePath = CarbonUtils.getCarbonHome() + File.separator + Constants.MIGRATION_SCRIPTS_FOLDER + File.separator; + + if (Constants.CONSTRAINT.equals(queryType)) { + //queryTobeExecuted = resourcePath + "drop-fk.sql"; + queryTobeExecuted = IOUtils.toString(new FileInputStream(new File(resourcePath + "drop-fk.sql")), "UTF-8"); + } else { + queryTobeExecuted = resourcePath + databaseType + ".sql"; + //queryTobeExecuted = IOUtils.toString(new FileInputStream(new File(resourcePath + databaseType + ".sql")), "UTF-8"); + } + + } catch (IOException e) { + throw new APIMigrationException("Error occurred while accessing the sql from resources. " + e); + } catch (Exception e) { + //getDatabaseType inherited from DBCreator, which throws generic exception + throw new APIMigrationException("Error occurred while searching for database type " + e); + } + + return queryTobeExecuted; + } + + /** + * To handle exceptions + * + * @param msg error message + * @throws APIMigrationException + */ + public static void handleException(String msg, Throwable e) throws APIMigrationException { + log.error(msg, e); + throw new APIMigrationException(msg, e); + } + + + + + /** + * Get all the parameters related to each resource. The parameter array is + * an array which is part of the operations object inside each resource. + * + * @param resource + * api-doc which contains swagger 1.1 info + * @return map of parameter array related to all the http methods for each + * resource. the key for + * the map is resourcepath_httpmethod + */ + public static Map getAllParametersForResources(JSONObject resource) throws APIMigrationException { + Map parameters = new HashMap(); + + String resourcePath = (String) resource.get(Constants.API_DOC_11_RESOURCE_PATH); + String apiVersion = (String) resource.get(Constants.API_DOC_11_API_VERSION); + + if (resourcePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_RESOURCE_PATH); + } + + if (apiVersion == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_API_VERSION); + } + + String resourcePathPrefix = resourcePath + "/" + apiVersion; + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS); + + if (apis == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_APIS); + } + + for (int i = 0; i < apis.size(); i++) { + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_11_PATH); + JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_11_OPERATIONS); + + if (path == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_PATH); + } + + if (operations == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_OPERATIONS); + } + + if (resourcePathPrefix.length() > path.length()) { + throw new APIMigrationException("Cannot obtain key prefix from swagger 1.1 document because resourcePathPrefix : " + + resourcePathPrefix + " is incompatible with path : " + path); + } + + // get the key by removing the "apiVersion" and "resourcePath" + // from the "path" variable + // and concat the http method + String keyPrefix = path.substring(resourcePathPrefix.length()); + if (keyPrefix.isEmpty()) { + keyPrefix = "/*"; + } + + for (int j = 0; j < operations.size(); j++) { + JSONObject operation = (JSONObject) operations.get(j); + String httpMethod = (String) operation.get(Constants.API_DOC_11_METHOD); + JSONArray parameterArray = (JSONArray) operation.get(Constants.API_DOC_11_PARAMETERS); + + if (httpMethod == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_METHOD); + } + + if (parameterArray == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_PARAMETERS); + } + + + String key = keyPrefix + "_" + httpMethod.toLowerCase(); + + parameters.put(key, parameterArray); + } + } + + return parameters; + } + + /** + * Get all the operation object related to each resource. Method is inside the operation object + * this object contains the nickname, description related to that resource method + * @param resource + * api-doc which contains swagger 1.1 info + * @return map of operations array related to all the http methods for each + * resource. the key for + * the map is resourcepath_httpmethod + */ + private static Map getAllOperationsForResources(JSONObject resource) throws APIMigrationException { + Map parameters = new HashMap(); + + String resourcePath = (String) resource.get(Constants.API_DOC_11_RESOURCE_PATH); + String apiVersion = (String) resource.get(Constants.API_DOC_11_API_VERSION); + + if (resourcePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_RESOURCE_PATH); + } + + if (apiVersion == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_API_VERSION); + } + + String resourcePathPrefix = resourcePath + "/" + apiVersion; + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS); + + if (apis == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_APIS); + } + + for (int i = 0; i < apis.size(); i++) { + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_11_PATH); + JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_11_OPERATIONS); + + if (path == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_PATH); + } + + if (operations == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_OPERATIONS); + } + + if (resourcePathPrefix.length() > path.length()) { + throw new APIMigrationException("Cannot obtain key prefix from swagger 1.1 document because resourcePathPrefix : " + + resourcePathPrefix + " is incompatible with path : " + path); + } + + // get the key by removing the "apiVersion" and "resourcePath" + // from the "path" variable + // and concat the http method + String keyPrefix = path.substring(resourcePathPrefix.length()); + if (keyPrefix.isEmpty()) { + keyPrefix = "/*"; + } + + for (int j = 0; j < operations.size(); j++) { + JSONObject operation = (JSONObject) operations.get(j); + String httpMethod = (String) operation.get(Constants.API_DOC_11_METHOD); + + if (httpMethod == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_METHOD); + } + + String key = keyPrefix + "_" + httpMethod.toLowerCase(); + + parameters.put(key, operation); + } + } + + return parameters; + } + /** + * Get all the apis as a map. key for map is the full resource path for that api. key is created + * using 'basepath + apis[i].path' values in the api-doc.json file (swagger 1.1 doc) + * + * @param resource + * api-doc which contains swagger 1.1 info + * @return map of apis in the swagger 1.1 doc. key is the full resource path for that resource + */ + public static Map getAllAPIsByResourcePath(JSONObject resource) throws APIMigrationException { + Map parameters = new HashMap(); + + String basePath = (String) resource.get(Constants.API_DOC_11_BASE_PATH); + + if (basePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_BASE_PATH); + } + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_11_APIS); + + if (apis == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_APIS); + } + + for (int i = 0; i < apis.size(); i++) { + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_11_PATH); + + if (path == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_PATH); + } + + String key = basePath + path; + parameters.put(key, apiInfo); + } + + return parameters; + + } + + private static JSONArray getDefaultParameters() { + JSONParser parser = new JSONParser(); + JSONArray defaultParam = null; + try { + defaultParam = (JSONArray) parser.parse(Constants.DEFAULT_PARAM_ARRAY); + } catch (ParseException e) { + log.error("ParseException when getting swagger default Parameters", e); + } + return defaultParam; + + } + + /** + * Modify the resource in registry location '1.2' to be compatible with the + * AM 1.8. add the + * parameters to operations element, add 'nickname' variable and the + * 'basePath' variable + * + * @param resource + * resource inside the 1.2 location + * @param allParameters + * map containing all the parameters extracted from api-doc + * containing + * resources for swagger 1.1 + * @param allOperations + * @param basePath + * base path for the resource + * @return modified resource for the api + */ + public static String getUpdatedSwagger12Resource(JSONObject resource, + Map allParameters, + Map allOperations, String basePath) throws APIMigrationException { + + JSONArray apis = (JSONArray) resource.get(Constants.API_DOC_12_APIS); + + if (apis == null) { + throw new APIMigrationException("Swagger 1.2 document does not contain required field: " + Constants.API_DOC_12_APIS); + } + + for (int i = 0; i < apis.size(); i++) { + JSONObject apiInfo = (JSONObject) apis.get(i); + String path = (String) apiInfo.get(Constants.API_DOC_12_PATH); + JSONArray operations = (JSONArray) apiInfo.get(Constants.API_DOC_12_OPERATIONS); + + if (path == null) { + log.error("Swagger 1.2 document does not contain required field: " + Constants.API_DOC_12_PATH); + continue; + } + + if (operations == null) { + log.error("Swagger 1.2 document does not contain required field: " + Constants.API_DOC_12_OPERATIONS); + continue; + } + + for (int j = 0; j < operations.size(); j++) { + JSONObject operation = (JSONObject) operations.get(j); + String method = (String) operation.get(Constants.API_DOC_12_METHOD); + + if (method == null) { + log.error("Swagger 1.2 document does not contain required field: " + Constants.API_DOC_12_METHOD); + continue; + } + + // nickname is method name + "_" + path without starting "/" + // symbol + String nickname = method.toLowerCase() + "_" + path.substring(1); + // add nickname variable + operation.put(Constants.API_DOC_12_NICKNAME, nickname); + String key = path + "_" + method.toLowerCase(); + + JSONArray parameters; + if (allParameters.containsKey(key)) { + parameters = allParameters.get(key); + + //setting the 'type' to 'string' if this variable is missing + for(int m = 0; m < parameters.size(); m++ ){ + JSONObject para = (JSONObject)parameters.get(m); + if(!para.containsKey("type")){ + para.put("type", "string"); + } + } + + } else { + parameters = getDefaultParameters(); + + } + //if there are parameters already in this + JSONArray existingParams = (JSONArray) operation.get(Constants.API_DOC_12_PARAMETERS); + + if (existingParams != null) { + if (existingParams.isEmpty()) { + JSONParser parser = new JSONParser(); + if (path.contains("{")) { + List urlParams = ResourceUtil.getURLTempateParams(path); + for (String p : urlParams) { + try { + JSONObject paramObj = (JSONObject) parser.parse(Constants.DEFAULT_PARAM_FOR_URL_TEMPLATE); + paramObj.put("name", p); + parameters.add(paramObj); + } catch (ParseException e) { + log.error("ParseException when getting swagger default Parameters from URI template", e); + } + } + } + // add parameters array + operation.put(Constants.API_DOC_12_PARAMETERS, parameters); + } else { + for (int k = 0; k < existingParams.size(); k++) { + parameters.add(existingParams.get(k)); + } + operation.put(Constants.API_DOC_12_PARAMETERS, parameters); + } + } + + //updating the resource description and nickname using values in the swagger 1.1 doc + if(allOperations.containsKey(key)){ + + //update info related to object + JSONObject operationObj11 = allOperations.get(key); + //add summery + if(operationObj11.containsKey("summary")) { + operation.put("summary", (String) operationObj11.get("summery")); + } + + } + } + } + + // add basePath variable + resource.put(Constants.API_DOC_12_BASE_PATH, basePath); + + return resource.toJSONString(); + } + + + /** + * update all the the swagger document in the registry related to an api + * @param apiDocJson + * @param docResourcePaths + * @param registry + * @throws ParseException + * @throws RegistryException + */ + public static void updateAPISwaggerDocs(String apiDocJson, String[] docResourcePaths, + Registry registry) throws ParseException, RegistryException, UnsupportedEncodingException, APIMigrationException { + + JSONParser parser = new JSONParser(); + JSONObject apiDoc11 = (JSONObject) parser.parse(apiDocJson); + + Map allParameters = ResourceUtil.getAllParametersForResources(apiDoc11); + + Map allOperations = ResourceUtil.getAllOperationsForResources(apiDoc11); + + Map apisByPath = ResourceUtil.getAllAPIsByResourcePath(apiDoc11); + + //this collection holds description given for each resource against the resource name. + //descriptions added resources in an api in AM 1.7 are stored in api-doc 1.1. this desciption + //is showed in am 1.7 api console in the store applicatoin. AM 1.8 uses descriptions in + // api-doc in 1.2 resource folder. following map collects this value from api-doc 1.1 and + // store it to add to api-doc 1.2 + Map descriptionsForResource = new HashMap(); + + String basePath = (String) apiDoc11.get(Constants.API_DOC_11_BASE_PATH); + String resourcePath = (String) apiDoc11.get(Constants.API_DOC_11_RESOURCE_PATH); + String apiVersion = (String) apiDoc11.get(Constants.API_DOC_11_API_VERSION); + + if (basePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_BASE_PATH); + } + + if (resourcePath == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_RESOURCE_PATH); + } + + if (apiVersion == null) { + throw new APIMigrationException("Swagger 1.1 document does not contain required field: " + Constants.API_DOC_11_API_VERSION); + } + + resourcePath = resourcePath.endsWith("/") ? resourcePath : resourcePath + "/"; + String basePathForResource = basePath + resourcePath + apiVersion; + + String apidoc12path = ""; + + //update each resource in the 1.2 folder except the api-doc resource + for (String docResourcePath : docResourcePaths) { + String resourceName = docResourcePath.substring(docResourcePath.lastIndexOf("/")); + + if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) { + //store api-doc in 1.2 folder for future use + apidoc12path = docResourcePath; + continue; + } + + if (!registry.resourceExists(docResourcePath)) { + log.error("Doc resource path at : " + docResourcePath + " does not exist"); + continue; + } + + Resource resource = registry.get(docResourcePath); + JSONObject apiDoc = (JSONObject) parser.parse(new String((byte[]) resource.getContent(), "UTF8")); + + + String description = ""; + //generate the key to query the descriptionsForResource map + JSONArray apisInResource = (JSONArray) apiDoc.get(Constants.API_DOC_12_APIS); + + if (apisInResource == null) { + log.error("Could not find " + Constants.API_DOC_12_APIS + " in document resource path"); + continue; + } + + JSONObject apiTemp = (JSONObject) apisInResource.get(0); + String path = (String) apiTemp.get(Constants.API_DOC_12_PATH); + + if (path == null) { + log.error("Could not find " + Constants.API_DOC_12_PATH + " in document resource path"); + continue; + } + + String key = ""; + if (path.equals("/*")) { + key = basePathForResource; + } else { + key = basePathForResource + path; + } + + + //get the description for that resource. query the api list generated using api-doc 1.1 + if(apisByPath.containsKey(key)) { + JSONObject apiInfo = (JSONObject) apisByPath.get(key); + description = (String) apiInfo.get("description"); + descriptionsForResource.put(resourceName, description); + } + + String updatedJson = + ResourceUtil.getUpdatedSwagger12Resource(apiDoc, allParameters, allOperations, + basePathForResource); + log.info("\t update " + resourceName.substring(1)); + Resource res = registry.get(docResourcePath); + res.setContent(updatedJson); + //update the registry + registry.put(docResourcePath, res); + + } + + //update the api-doc. add the descriptions to each api resource + ResourceUtil.updateSwagger12APIdoc(apidoc12path, descriptionsForResource, registry, parser); + + } + + + + /** + * update the swagger 1.2 api-doc. This method updates the descriptions + * @param apidoc12path + * @param descriptionsForResource + * @param registry + * @param parser + * @throws RegistryException + * @throws ParseException + */ + private static void updateSwagger12APIdoc(String apidoc12path, + Map descriptionsForResource, + Registry registry, JSONParser parser) + throws RegistryException, + ParseException, UnsupportedEncodingException, APIMigrationException { + if (!registry.resourceExists(apidoc12path)) { + throw new APIMigrationException("Swagger 1.2 doc does not exist"); + } + + Resource res = registry.get(apidoc12path); + JSONObject api12Doc = (JSONObject) parser.parse(new String((byte[]) res.getContent(), "UTF8")); + JSONArray apis = (JSONArray) api12Doc.get(Constants.API_DOC_12_APIS); + for (int j = 0; j < apis.size(); j++) { + JSONObject api = (JSONObject) apis.get(j); + + // get the resource name for each api in api-doc 1.2 + String resPathName = (String) api.get(Constants.API_DOC_12_PATH); + if (descriptionsForResource.containsKey(resPathName)) { + // if the descrption is available for that resource update it + api.put("description", descriptionsForResource.get(resPathName)); + } + } + log.info("\t update api-doc"); + res.setContent(api12Doc.toJSONString()); + // update the registry + registry.put(apidoc12path, res); + } + + /** + * remove header and body parameters + * @param docResourcePaths + * @param registry + * @throws RegistryException + * @throws ParseException + */ + public static void updateSwagger12ResourcesForAM18(String[] docResourcePaths, + Registry registry) throws RegistryException, ParseException, UnsupportedEncodingException, APIMigrationException { + JSONParser parser = new JSONParser(); + for (String docResourcePath : docResourcePaths) { + + String resourceName = docResourcePath.substring(docResourcePath.lastIndexOf("/")); + + //modify this if api-doc resource needed to be changed + if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) { + continue; + } + + if (!registry.resourceExists(docResourcePath)) { + throw new APIMigrationException("Doc resource does not exist in swagger 1.2"); + } + + Resource resource = registry.get(docResourcePath); + JSONObject resourceDoc = (JSONObject) parser.parse(new String((byte[]) resource.getContent(), "UTF8")); + JSONArray apis = (JSONArray) resourceDoc.get(Constants.API_DOC_12_APIS); + + if (apis == null) { + throw new APIMigrationException("Swagger 1.2 doc does not contain required field : " + Constants.API_DOC_12_APIS); + } + + for (int j = 0; j < apis.size(); j++) { + JSONObject api = (JSONObject) apis.get(j); + JSONArray operations = (JSONArray) api.get("operations"); + + for (int k = 0; k < operations.size(); k++) { + JSONObject operation = (JSONObject) operations.get(k); + JSONArray parameters = (JSONArray) operation.get("parameters"); + String method = (String) operation.get("method"); + JSONArray parametersNew = new JSONArray(); + //remove header and body parameters + for (int l = 0; l < parameters.size(); l++) { + JSONObject parameter = (JSONObject) parameters.get(l); + + if(parameter.get("paramType").equals("header")){ + continue; + } + if(parameter.get("paramType").equals("body")) { + + //only remove body of a GET and DELETE + if("GET".equalsIgnoreCase(method) || + "DELETE".equalsIgnoreCase(method)) { + continue; + } + } + parametersNew.add(parameter); + } + operation.put("parameters", parametersNew); + } + + + } + + resource.setContent(resourceDoc.toJSONString()); + //update the registry + registry.put(docResourcePath, resource); + } + + } + + /** + * extract the parameters from the url tempate. + * @param url + * @return + */ + public static List getURLTempateParams(String url) { + boolean endVal = false; + + List params = new ArrayList(); + if(url.contains("{")){ + + int start = 0; + int end = 0; + for(int i = 0; i < url.length(); i++) { + if(url.charAt(i) == '{') + start = i; + else if(url.charAt(i) == '}') { + end = i; + endVal = true; + } + + if(endVal){ + params.add(url.substring(start + 1, end)); + endVal = false; + } + } + + } + return params; + } + +} diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/h2.sql b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/h2.sql new file mode 100644 index 0000000000..5b59b9119c --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/h2.sql @@ -0,0 +1 @@ +ALTER TABLE AM_SUBSCRIPTION ADD SUBS_CREATE_STATE VARCHAR(50) DEFAULT 'SUBSCRIBE'; \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/mssql.sql b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/mssql.sql new file mode 100644 index 0000000000..5b59b9119c --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/mssql.sql @@ -0,0 +1 @@ +ALTER TABLE AM_SUBSCRIPTION ADD SUBS_CREATE_STATE VARCHAR(50) DEFAULT 'SUBSCRIBE'; \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/mysql.sql b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/mysql.sql new file mode 100644 index 0000000000..45e75b01b0 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/mysql.sql @@ -0,0 +1 @@ +ALTER TABLE AM_SUBSCRIPTION ADD COLUMN SUBS_CREATE_STATE VARCHAR(50) DEFAULT 'SUBSCRIBE'; \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/oracle.sql b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/oracle.sql new file mode 100644 index 0000000000..5b59b9119c --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/oracle.sql @@ -0,0 +1 @@ +ALTER TABLE AM_SUBSCRIPTION ADD SUBS_CREATE_STATE VARCHAR(50) DEFAULT 'SUBSCRIBE'; \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/postgresql.sql b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/postgresql.sql new file mode 100644 index 0000000000..45e75b01b0 --- /dev/null +++ b/modules/distribution/resources/migration-1.7.0_to_1.8.0/wso2-api-migration-client/src/main/resources/migration-scripts/postgresql.sql @@ -0,0 +1 @@ +ALTER TABLE AM_SUBSCRIPTION ADD COLUMN SUBS_CREATE_STATE VARCHAR(50) DEFAULT 'SUBSCRIBE'; \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/pom.xml b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/pom.xml index 0cd0a6ae27..52b0add516 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/pom.xml +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/pom.xml @@ -6,7 +6,7 @@ org.wso2.carbon org.wso2.carbon.apimgt.migrate.client - 1.9.1-SNAPSHOT + 1.9.X bundle @@ -59,6 +59,15 @@ + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + + org.apache.felix maven-bundle-plugin @@ -81,30 +90,29 @@ + + org.apache.maven.plugins + maven-assembly-plugin + 2.5.3 + + + dist + package + + attached + + + false + src/assembly/dist.xml + wso2-api-migration-client + + + + - - org.apache.ws.commons.axiom - axiom-api - ${org.apache.ws.commons.axiom.version} - - - org.apache.ws.commons.axiom - axiom-impl - ${org.apache.ws.commons.axiom.version} - - - org.apache.ws.commons.axiom.wso2 - axiom - ${org.apache.ws.commons.axiom.wso2.version} - - - org.bouncycastle.wso2 - bcprov-jdk15on - ${org.bouncycastle.wso2.version} - org.wso2.carbon org.wso2.carbon.core.services @@ -120,41 +128,20 @@ org.wso2.carbon.registry.core ${org.wso2.carbon.registry.core.version} - - org.wso2.carbon - org.wso2.carbon.registry.api - ${org.wso2.carbon.registry.api.version} - provided - org.wso2.carbon org.wso2.carbon.utils ${org.wso2.carbon.utils.version} - commons-scxml.wso2 - commons-scxml - ${commons-scxml.wso2.version} - - - commons-codec - commons-codec - ${commons-codec.version} - - - commons-logging - commons-logging - ${commons-logging.version} - - - org.wso2.carbon + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.impl - [1.2.1,1.2.4] + [1.2.0,1.3.0) - org.wso2.carbon + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.api - [1.2.1,1.2.4] + [1.2.0,1.3.0) @@ -162,23 +149,12 @@ UTF-8 1.7.2 2.5.3 - 1.2.14 - 1.2.11.wso2v5 - 1.49.0.wso2v2 4.2.0 4.2.0 1.0.4 4.2.0 - 4.2.0 4.2.0 1.0.1 - 1.8 - 1.10 - 1.1.3 - 0.9.0.wso2v1 - 0.0.0 - 2.4.0 - 2.4.0 diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/assembly/dist.xml b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/assembly/dist.xml new file mode 100644 index 0000000000..88ddad5f7e --- /dev/null +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/assembly/dist.xml @@ -0,0 +1,29 @@ + + dist + + zip + + false + + + ${project.basedir}/src/main/resources/18to19Migration/sql-scripts/constraint/drop-fk.sql + migration-scripts/18-19-migration + + + + + ${project.basedir}/src/main/resources/18to19Migration/sql-scripts + migration-scripts/18-19-migration + + *.sql + + + + ${project.build.directory} + + + *.jar + + + + \ No newline at end of file diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom18to19.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom18to19.java index 49bdfb6d2c..0641315d4f 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom18to19.java +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrateFrom18to19.java @@ -23,21 +23,27 @@ import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; 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.impl.APIConstants; +import org.wso2.carbon.apimgt.impl.definitions.APIDefinitionFromSwagger20; import org.wso2.carbon.apimgt.impl.utils.APIMgtDBUtil; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.apimgt.migration.APIMigrationException; import org.wso2.carbon.apimgt.migration.client.internal.ServiceHolder; import org.wso2.carbon.apimgt.migration.util.Constants; import org.wso2.carbon.apimgt.migration.util.ResourceUtil; +import org.wso2.carbon.apimgt.migration.util.StatDBUtil; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.governance.api.generic.GenericArtifactManager; import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact; import org.wso2.carbon.governance.api.util.GovernanceUtils; +import org.wso2.carbon.registry.api.RegistryException; +import org.wso2.carbon.registry.api.Resource; import org.wso2.carbon.registry.core.ActionConstants; import org.wso2.carbon.registry.core.Registry; import org.wso2.carbon.registry.core.RegistryConstants; @@ -46,29 +52,15 @@ import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.tenant.TenantManager; import org.wso2.carbon.utils.CarbonUtils; -import org.wso2.carbon.registry.api.RegistryException; -import org.wso2.carbon.registry.api.Resource; +import org.xml.sax.SAXException; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; import java.net.MalformedURLException; -import java.net.URL; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; +import java.sql.*; +import java.util.*; /** @@ -82,13 +74,88 @@ public class MigrateFrom18to19 implements MigrationClient { private static final Log log = LogFactory.getLog(MigrateFrom18to19.class); private List tenantsArray; - public MigrateFrom18to19() throws UserStoreException { + public MigrateFrom18to19(String tenantArguments, String blackListTenantArguments) throws UserStoreException { TenantManager tenantManager = ServiceHolder.getRealmService().getTenantManager(); - tenantsArray = new ArrayList(Arrays.asList(tenantManager.getAllTenants())); - Tenant superTenant = new Tenant(); - superTenant.setDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); - superTenant.setId(MultitenantConstants.SUPER_TENANT_ID); - tenantsArray.add(superTenant); + + if (tenantArguments != null) { // Tenant arguments have been provided so need to load specific ones + tenantArguments = tenantArguments.replaceAll("\\s", ""); // Remove spaces and tabs + + tenantsArray = new ArrayList(); + + buildTenantList(tenantManager, tenantsArray, tenantArguments); + } else if (blackListTenantArguments != null) { + blackListTenantArguments = blackListTenantArguments.replaceAll("\\s", ""); // Remove spaces and tabs + + List blackListTenants = new ArrayList(); + buildTenantList(tenantManager, blackListTenants, blackListTenantArguments); + + List allTenants = new ArrayList(Arrays.asList(tenantManager.getAllTenants())); + Tenant superTenant = new Tenant(); + superTenant.setDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + superTenant.setId(MultitenantConstants.SUPER_TENANT_ID); + allTenants.add(superTenant); + + tenantsArray = new ArrayList(); + + for (Tenant tenant : allTenants) { + boolean isBlackListed = false; + for (Tenant blackListTenant : blackListTenants) { + if (blackListTenant.getId() == tenant.getId()) { + isBlackListed = true; + break; + } + } + + if (!isBlackListed) { + tenantsArray.add(tenant); + } + } + + } else { // Load all tenants + tenantsArray = new ArrayList(Arrays.asList(tenantManager.getAllTenants())); + Tenant superTenant = new Tenant(); + superTenant.setDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + superTenant.setId(MultitenantConstants.SUPER_TENANT_ID); + tenantsArray.add(superTenant); + } + } + + + private void buildTenantList(TenantManager tenantManager, List tenantList, String tenantArguments) throws UserStoreException { + if (tenantArguments.contains(",")) { // Multiple arguments specified + String[] parts = tenantArguments.split(","); + + for (int i = 0; i < parts.length; ++i) { + if (parts[i].length() > 0) { + populateTenants(tenantManager, tenantList, parts[i]); + } + } + } else { // Only single argument provided + populateTenants(tenantManager, tenantList, tenantArguments); + } + } + + + private void populateTenants(TenantManager tenantManager, List tenantList, String argument) throws UserStoreException { + log.debug("Argument provided : " + argument); + + if (argument.contains("@")) { // Username provided as argument + int tenantID = tenantManager.getTenantId(argument); + + if (tenantID != -1) { + tenantList.add(tenantManager.getTenant(tenantID)); + } else { + log.error("Tenant does not exist for username " + argument); + } + } else { // Domain name provided as argument + Tenant[] tenants = tenantManager.getAllTenantsForTenantDomainStr(argument); + + if (tenants.length > 0) { + tenantList.addAll(Arrays.asList(tenants)); + } else { + log.error("Tenant does not exist for domain " + argument); + } + } } /** @@ -100,21 +167,21 @@ public MigrateFrom18to19() throws UserStoreException { * @throws SQLException */ @Override - public void databaseMigration(String migrateVersion) throws APIMigrationException, SQLException { - log.info("Database migration for API Manager 1.8.0 started"); + public void databaseMigration(String migrateVersion) throws SQLException { + log.info("Database migration for API Manager " + Constants.VERSION_1_9 + " started"); Connection connection = null; PreparedStatement preparedStatement = null; + BufferedReader bufferedReader = null; try { connection = APIMgtDBUtil.getConnection(); String dbType = MigrationDBCreator.getDatabaseType(connection); String dbScript = ResourceUtil.pickQueryFromResources(migrateVersion, dbType); - BufferedReader bufferedReader; InputStream is = new FileInputStream(dbScript); - bufferedReader = new BufferedReader(new InputStreamReader(is)); + bufferedReader = new BufferedReader(new InputStreamReader(is, "UTF8")); String sqlQuery; while ((sqlQuery = bufferedReader.readLine()) != null) { - if ("oracle".equals(dbType)) { + if (Constants.DB_TYPE_ORACLE.equals(dbType)) { sqlQuery = sqlQuery.replace(";", ""); } sqlQuery = sqlQuery.trim(); @@ -137,20 +204,25 @@ public void databaseMigration(String migrateVersion) throws APIMigrationExceptio preparedStatement = connection.prepareStatement(sqlQuery.trim()); preparedStatement.execute(); connection.commit(); - preparedStatement.close(); } } //To drop the foreign key dropFKConstraint(migrateVersion, dbType); + bufferedReader.close(); + } catch (IOException e) { - //ResourceUtil.handleException("Error occurred while finding the query. Please check the file path.", e); + //Errors logged to let user know the state of the db migration and continue other resource migrations log.error("Error occurred while migrating databases", e); } catch (Exception e) { - //ResourceUtil.handleException("Error occurred while finding the query. Please check the file path.", e); + /* MigrationDBCreator extends from org.wso2.carbon.utils.dbcreator.DatabaseCreator and in the super class + method getDatabaseType throws generic Exception */ log.error("Error occurred while migrating databases", e); } finally { + if (preparedStatement != null) { + preparedStatement.close(); + } if (connection != null) { connection.close(); } @@ -160,46 +232,63 @@ public void databaseMigration(String migrateVersion) throws APIMigrationExceptio /** * This method is used to remove the FK constraint which is unnamed - * This finds the name of the constraint and build the query to delete the constaint and execute it + * This finds the name of the constraint and build the query to delete the constraint and execute it * * @param migrateVersion version to be migrated * @param dbType database type of the user * @throws SQLException * @throws IOException - * @throws APIMigrationException */ - public void dropFKConstraint(String migrateVersion, String dbType) throws SQLException, IOException, APIMigrationException { - String constraintName = null; - Connection connection; - String queryToExecute = ResourceUtil.pickQueryFromResources(migrateVersion, Constants.CONSTRAINT).trim(); - String queryArray[] = queryToExecute.split(Constants.LINE_BREAK); - - connection = APIMgtDBUtil.getConnection(); - connection.setAutoCommit(false); - Statement statement = connection.createStatement(); - if ("oracle".equals(dbType)) { - queryArray[0] = queryArray[0].replace(Constants.DELIMITER, ""); - } - ResultSet resultSet = statement.executeQuery(queryArray[0]); - while (resultSet.next()) { - constraintName = resultSet.getString("constraint_name"); - } + public void dropFKConstraint(String migrateVersion, String dbType) throws SQLException { + Connection connection = null; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + Statement statement = null; + try { + String queryToExecute = ResourceUtil.pickQueryFromResources(migrateVersion, Constants.CONSTRAINT).trim(); + String queryArray[] = queryToExecute.split(Constants.LINE_BREAK); - if (constraintName != null) { - queryToExecute = queryArray[1].replace("", constraintName); - if ("oracle".equals(dbType)) { - queryToExecute = queryToExecute.replace(Constants.DELIMITER, ""); + connection = APIMgtDBUtil.getConnection(); + connection.setAutoCommit(false); + statement = connection.createStatement(); + if (Constants.DB_TYPE_ORACLE.equals(dbType)) { + queryArray[0] = queryArray[0].replace(Constants.DELIMITER, ""); } + resultSet = statement.executeQuery(queryArray[0]); + String constraintName = null; - if (queryToExecute.contains("\\n")) { - queryToExecute = queryToExecute.replace("\\n", ""); + while (resultSet.next()) { + constraintName = resultSet.getString("constraint_name"); } - PreparedStatement preparedStatement = connection.prepareStatement(queryToExecute); - preparedStatement.execute(); - connection.commit(); - preparedStatement.close(); + + if (constraintName != null) { + queryToExecute = queryArray[1].replace("", constraintName); + if (Constants.DB_TYPE_ORACLE.equals(dbType)) { + queryToExecute = queryToExecute.replace(Constants.DELIMITER, ""); + } + + if (queryToExecute.contains("\\n")) { + queryToExecute = queryToExecute.replace("\\n", ""); + } + preparedStatement = connection.prepareStatement(queryToExecute); + preparedStatement.execute(); + connection.commit(); + } + } catch (APIMigrationException e) { + //Foreign key might be already deleted, log the error and let it continue + log.error("Error occurred while deleting foreign key", e); + } catch (IOException e) { + //If user does not add the file migration will continue and migrate the db without deleting + // the foreign key reference + log.error("Error occurred while finding the foreign key deletion query for execution", e); + } finally { + if (statement != null) { + statement.close(); + } + + APIMgtDBUtil.closeAllConnections(preparedStatement, connection, resultSet); } - connection.close(); + } /** @@ -223,69 +312,71 @@ public void registryResourceMigration() throws APIMigrationException { * @throws APIMigrationException */ void rxtMigration() throws APIMigrationException { - log.info("Rxt migration for API Manager 1.9.0 started."); + log.info("Rxt migration for API Manager " + Constants.VERSION_1_9 + " started."); boolean isTenantFlowStarted = false; - try { - for (Tenant tenant : tenantsArray) { + for (Tenant tenant : tenantsArray) { + log.debug("Start rxtMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + try { PrivilegedCarbonContext.startTenantFlow(); isTenantFlowStarted = true; - /*Use the super tenant instead of tenant because tenants do not have access to master-datasources.xml - If you use tenant details instead of super tenant, you will get javax.naming.NameNotFoundException: - Name [jdbc/AM_API] is not bound in this Context. Unable to find [jdbc]*/ - - PrivilegedCarbonContext.getThreadLocalCarbonContext(). - setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain(), true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId(), true); String adminName = ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()) .getRealmConfiguration().getAdminUserName(); + + log.debug("Tenant admin username : " + adminName); ServiceHolder.getTenantRegLoader().loadTenantRegistry(tenant.getId()); Registry registry = ServiceHolder.getRegistryService().getGovernanceUserRegistry(adminName, tenant .getId()); GenericArtifactManager artifactManager = APIUtil.getArtifactManager(registry, APIConstants.API_KEY); - //GenericArtifactManager manager = new GenericArtifactManager(registry, "api"); - GovernanceUtils.loadGovernanceArtifacts((UserRegistry) registry); - GenericArtifact[] artifacts = artifactManager.getAllGenericArtifacts(); - for (GenericArtifact artifact : artifacts) { - API api = APIUtil.getAPI(artifact, registry); - APIIdentifier apiIdentifier = api.getId(); - String apiVersion = apiIdentifier.getVersion(); + if (artifactManager != null) { + GovernanceUtils.loadGovernanceArtifacts((UserRegistry) registry); + GenericArtifact[] artifacts = artifactManager.getAllGenericArtifacts(); + for (GenericArtifact artifact : artifacts) { + API api = APIUtil.getAPI(artifact, registry); - if(!(api.getContext().endsWith(RegistryConstants.PATH_SEPARATOR + apiVersion))) { - artifact.setAttribute("overview_context", api.getContext() + - RegistryConstants.PATH_SEPARATOR + apiVersion); - } + if (api == null) { + log.error("Cannot find corresponding api for registry artifact " + artifact.getAttribute("overview_name") + "-" + artifact.getAttribute("overview_version") + "-" + artifact.getAttribute("overview_provider") + + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ") in AM_DB"); + continue; + } - artifact.addAttribute("overview_contextTemplate", api.getContext() + - RegistryConstants.PATH_SEPARATOR + "{version}"); - artifact.addAttribute("overview_environments", ""); - artifact.addAttribute("overview_versionType", ""); + APIIdentifier apiIdentifier = api.getId(); + String apiVersion = apiIdentifier.getVersion(); - artifactManager.updateGenericArtifact(artifact); - } + if (!(api.getContext().endsWith(RegistryConstants.PATH_SEPARATOR + apiVersion))) { + artifact.setAttribute("overview_context", api.getContext() + + RegistryConstants.PATH_SEPARATOR + apiVersion); + } - } - if(isTenantFlowStarted){ - PrivilegedCarbonContext.endTenantFlow(); - } + artifact.addAttribute("overview_contextTemplate", api.getContext() + + RegistryConstants.PATH_SEPARATOR + "{version}"); + artifact.addAttribute("overview_environments", ""); + artifact.addAttribute("overview_versionType", ""); - } catch (APIManagementException e) { - ResourceUtil.handleException("Error occurred while reading API from the artifact ", e); - } catch (RegistryException e) { - ResourceUtil.handleException("Error occurred while accessing the registry", e); - } catch (UserStoreException e) { - ResourceUtil.handleException("Error occurred while reading tenant information", e); - } - finally { - if(isTenantFlowStarted){ - PrivilegedCarbonContext.endTenantFlow(); + artifactManager.updateGenericArtifact(artifact); + } + } else { + log.debug("No api artifacts found in registry for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + } catch (APIManagementException e) { + ResourceUtil.handleException("Error occurred while reading API from the artifact ", e); + } catch (RegistryException e) { + ResourceUtil.handleException("Error occurred while accessing the registry", e); + } catch (UserStoreException e) { + ResourceUtil.handleException("Error occurred while reading tenant information", e); + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } } + log.debug("End rxtMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); } - if (log.isDebugEnabled()) { - log.debug("Rxt resource migration done for all the tenants"); - } + + log.info("Rxt resource migration done for all the tenants"); } @@ -306,10 +397,8 @@ void copyNewRxtFileToRegistry() throws APIMigrationException { int tenantId = tenant.getId(); isTenantFlowStarted = true; PrivilegedCarbonContext.startTenantFlow(); - PrivilegedCarbonContext.getThreadLocalCarbonContext() - .setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true); - PrivilegedCarbonContext.getThreadLocalCarbonContext() - .setTenantId(MultitenantConstants.SUPER_TENANT_ID); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain(), true); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId(), true); String adminName = ServiceHolder.getRealmService().getTenantUserRealm(tenantId) .getRealmConfiguration().getAdminUserName(); @@ -357,93 +446,156 @@ void copyNewRxtFileToRegistry() throws APIMigrationException { * @throws APIMigrationException */ void swaggerResourceMigration() throws APIMigrationException { - log.info("Swagger migration for API Manager 1.9.0 started."); + log.info("Swagger migration for API Manager " + Constants.VERSION_1_9 + " started."); boolean isTenantFlowStarted = false; - try { - for (Tenant tenant : tenantsArray) { - if (log.isDebugEnabled()) { - log.debug("Swagger migration for tenant " + tenant.getDomain() + "[" + tenant.getId() + "]" + " "); - } + for (Tenant tenant : tenantsArray) { + if (log.isDebugEnabled()) { + log.debug("Start swaggerResourceMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + try { PrivilegedCarbonContext.startTenantFlow(); isTenantFlowStarted = true; - //Use the super tenant instead of tenant because tenants do not have access to master-datasources.xml - PrivilegedCarbonContext.getThreadLocalCarbonContext(). - setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); - PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID); - - String adminName = ServiceHolder.getRealmService().getTenantUserRealm( - tenant.getId()).getRealmConfiguration().getAdminUserName(); - ServiceHolder.getTenantRegLoader().loadTenantRegistry(tenant.getId()); - Registry registry = ServiceHolder.getRegistryService(). - getGovernanceUserRegistry(adminName, tenant.getId()); - GenericArtifactManager manager = new GenericArtifactManager(registry, "api"); - GovernanceUtils.loadGovernanceArtifacts((UserRegistry) registry); - GenericArtifact[] artifacts = manager.getAllGenericArtifacts(); - - for (GenericArtifact artifact : artifacts) { - API api = APIUtil.getAPI(artifact, registry); - APIIdentifier apiIdentifier = api.getId(); - String apiName = apiIdentifier.getApiName(); - String apiVersion = apiIdentifier.getVersion(); - String apiProviderName = apiIdentifier.getProviderName(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenant.getDomain()); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenant.getId()); - String swagger12location = ResourceUtil.getSwagger12ResourceLocation(apiName, - apiVersion, apiProviderName); + Registry registry = getRegistry(tenant); - if (!registry.resourceExists(swagger12location)) { - log.error("Swagger Resource migration has not happen yet for " + - apiName + "-" + apiVersion + "-" - + apiProviderName); + if (registry != null) { + GenericArtifact[] artifacts = getGenericArtifacts(registry); - } else { - if (log.isDebugEnabled()) { - log.debug("Creating swagger v2.0 resource for : " + apiName + "-" + apiVersion + "-" - + apiProviderName); - } - //get swagger v2 doc - String swagger2doc = getSwagger2docUsingSwagger12RegistryResources(registry, swagger12location); - - //create location in registry and add this - String swagger2location = ResourceUtil.getSwagger2ResourceLocation(apiName, apiVersion, - apiProviderName); - - Resource docContent = registry.newResource(); - docContent.setContent(swagger2doc); - docContent.setMediaType("application/json"); - registry.put(swagger2location, docContent); - - //Currently set to ANONYMOUS_ROLE, need to set to visible roles - ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getAuthorizationManager() - .authorizeRole(APIConstants.ANONYMOUS_ROLE, - "_system/governance" + swagger2location, ActionConstants.GET); + if (artifacts != null) { + updateSwaggerResources(artifacts, registry, tenant); } } - - PrivilegedCarbonContext.endTenantFlow(); + } finally { + if (isTenantFlowStarted) { + PrivilegedCarbonContext.endTenantFlow(); + } } - } catch (MalformedURLException e) { - ResourceUtil.handleException("Error occurred while creating swagger v2.0 document ", e); - } catch (APIManagementException e) { - ResourceUtil.handleException("Error occurred while reading API from the artifact ", e); - } catch (RegistryException e) { - ResourceUtil.handleException("Error occurred while accessing the registry", e); - } catch (ParseException e) { - ResourceUtil.handleException("Error occurred while getting swagger v2.0 document", e); + + log.debug("End swaggerResourceMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + } + + log.info("Swagger resource migration done for all the tenants."); + } + + private Registry getRegistry(Tenant tenant) { + log.debug("Calling getRegistry"); + Registry registry = null; + + try { + String adminName = ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getRealmConfiguration().getAdminUserName(); + log.debug("Tenant admin username : " + adminName); + registry = ServiceHolder.getRegistryService().getGovernanceUserRegistry(adminName, tenant.getId()); + ServiceHolder.getTenantRegLoader().loadTenantRegistry(tenant.getId()); } catch (UserStoreException e) { - ResourceUtil.handleException("Error occurred while reading tenant information", e); + log.error("Error occurred while reading tenant information of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (RegistryException e) { + log.error("Error occurred while accessing the registry of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); } - if(isTenantFlowStarted){ - PrivilegedCarbonContext.endTenantFlow(); + + return registry; + } + + + private GenericArtifact[] getGenericArtifacts(Registry registry) { + log.debug("Calling getGenericArtifacts"); + GenericArtifact[] artifacts = null; + + try { + if (GovernanceUtils.findGovernanceArtifactConfiguration(Constants.API, registry) != null) { + GenericArtifactManager manager = new GenericArtifactManager(registry, Constants.API); + GovernanceUtils.loadGovernanceArtifacts((UserRegistry) registry); + artifacts = manager.getAllGenericArtifacts(); + + log.debug("Total number of api artifacts : " + artifacts.length); + } else { + log.debug("API artifacts do not exist in registry"); + } + + } catch (RegistryException e) { + log.error("Error occurred when getting GenericArtifacts from registry", e); } - if (log.isDebugEnabled()) { - log.debug("Swagger resource migration done for all the tenants"); + return artifacts; + } + + private API getAPI(GenericArtifact artifact) { + log.debug("Calling getAPI"); + API api = null; + + try { + api = APIUtil.getAPI(artifact); + } catch (APIManagementException e) { + log.error("Error when getting api artifact " + artifact.getId() + " from registry", e); } + return api; + } + + private void updateSwaggerResources(GenericArtifact[] artifacts, Registry registry, Tenant tenant) throws APIMigrationException { + log.debug("Calling updateSwaggerResources"); + for (GenericArtifact artifact : artifacts) { + API api = getAPI(artifact); + + if (api != null) { + APIIdentifier apiIdentifier = api.getId(); + String apiName = apiIdentifier.getApiName(); + String apiVersion = apiIdentifier.getVersion(); + String apiProviderName = apiIdentifier.getProviderName(); + try { + String swagger2location = ResourceUtil.getSwagger2ResourceLocation(apiName, apiVersion, apiProviderName); + + // Create swagger 2.0 doc only if it does not exist + /*if (registry.resourceExists(swagger2location)) { + continue; + }*/ + + String swagger12location = ResourceUtil.getSwagger12ResourceLocation(apiName, apiVersion, apiProviderName); + + String swagger2Document; + + if (!registry.resourceExists(swagger12location)) { + log.debug("Creating swagger v2.0 resource from scratch for : " + apiName + "-" + apiVersion + "-" + apiProviderName); + + APIDefinitionFromSwagger20 definitionFromSwagger20 = new APIDefinitionFromSwagger20(); + + swagger2Document = definitionFromSwagger20.generateAPIDefinition(api); + } else { + log.debug("Creating swagger v2.0 resource using v1.2 for : " + apiName + "-" + apiVersion + "-" + apiProviderName); + swagger2Document = getSwagger2docUsingSwagger12RegistryResources(registry, swagger12location, api); + } + + Resource docContent = registry.newResource(); + docContent.setContent(swagger2Document); + docContent.setMediaType("application/json"); + registry.put(swagger2location, docContent); + + ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getAuthorizationManager() + .authorizeRole(APIConstants.ANONYMOUS_ROLE, + "_system/governance" + swagger2location, ActionConstants.GET); + ServiceHolder.getRealmService().getTenantUserRealm(tenant.getId()).getAuthorizationManager() + .authorizeRole(APIConstants.EVERYONE_ROLE, + "_system/governance" + swagger2location, ActionConstants.GET); + } catch (RegistryException e) { + log.error("Registry error encountered for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (ParseException e) { + log.error("Error occurred while parsing swagger v1.2 document for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (UserStoreException e) { + log.error("Error occurred while setting permissions of swagger v2.0 document for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (MalformedURLException e) { + log.error("Error occurred while creating swagger v2.0 document for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } catch (APIManagementException e) { + log.error("Error occurred while creating swagger v2.0 document for api " + apiName + "-" + apiVersion + "-" + apiProviderName + " of tenant " + tenant.getId() + "(" + tenant.getDomain() + ")", e); + } + } + } } + /** * This method generates swagger v2 doc using swagger 1.2 doc * @@ -455,46 +607,67 @@ void swaggerResourceMigration() throws APIMigrationException { * @throws org.wso2.carbon.registry.core.exceptions.RegistryException */ - private String getSwagger2docUsingSwagger12RegistryResources(Registry registry, String swagger12location) + private String getSwagger2docUsingSwagger12RegistryResources(Registry registry, String swagger12location, API api) throws MalformedURLException, ParseException, RegistryException { - + log.debug("Calling getSwagger2docUsingSwagger12RegistryResources"); JSONParser parser = new JSONParser(); String swagger12BasePath = null; Resource swaggerRes = registry.get(swagger12location + APIConstants.API_DOC_1_2_RESOURCE_NAME); - JSONObject swagger12doc = (JSONObject) parser.parse(new String((byte[]) swaggerRes.getContent())); - Map apiDefPaths = new HashMap(); - Resource swagger12Res = registry.get(swagger12location); + try { + JSONObject swagger12doc = (JSONObject) parser.parse(new String((byte[]) swaggerRes.getContent(), "UTF8")); - //get all the resources inside the 1.2 resource location - String[] apiDefinitions = (String[]) swagger12Res.getContent(); + Map apiDefPaths = new HashMap(); + Resource swagger12Res = registry.get(swagger12location); - //get each resource in the 1.2 folder except the api-doc resource - for (String apiDefinition : apiDefinitions) { + //get all the resources inside the 1.2 resource location + String[] apiDefinitions = (String[]) swagger12Res.getContent(); - String resourceName = apiDefinition.substring(apiDefinition.lastIndexOf("/")); - //skip if api-doc file - if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) { - continue; - } + //get each resource in the 1.2 folder except the api-doc resource + for (String apiDefinition : apiDefinitions) { + + String resourceName = apiDefinition.substring(apiDefinition.lastIndexOf("/")); + //skip if api-doc file + if (resourceName.equals(APIConstants.API_DOC_1_2_RESOURCE_NAME)) { + continue; + } + + Resource resource = registry.get(apiDefinition); + + String swaggerDocContent; - Resource resource = registry.get(apiDefinition); - JSONObject apiDef = - (JSONObject) parser.parse(new String((byte[]) resource.getContent())); - //get the base path. this is same for all api definitions. - swagger12BasePath = (String) apiDef.get("basePath"); - JSONArray apiArray = (JSONArray) apiDef.get("apis"); - for (Object anApiArray : apiArray) { - JSONObject api = (JSONObject) anApiArray; - String path = (String) api.get("path"); - JSONArray operations = (JSONArray) api.get("operations"); - //set the operations object inside each api definition and set it in a map against its resource path - apiDefPaths.put(path, operations); + if (resource.getContent() instanceof String[]) { + swaggerDocContent = Arrays.toString((String[]) resource.getContent()); + } else { + swaggerDocContent = new String((byte[]) resource.getContent(), "UTF8"); + } + + log.debug("swaggerDocContent : " + swaggerDocContent); + + JSONObject apiDef = (JSONObject) parser.parse(swaggerDocContent); + //get the base path. this is same for all api definitions. + swagger12BasePath = (String) apiDef.get("basePath"); + if (apiDef.containsKey("apis")) { + JSONArray apiArray = (JSONArray) apiDef.get("apis"); + for (Object anApiArray : apiArray) { + JSONObject apiObject = (JSONObject) anApiArray; + String path = (String) apiObject.get("path"); + JSONArray operations = (JSONArray) apiObject.get("operations"); + //set the operations object inside each api definition and set it in a map against its resource path + apiDefPaths.put(path, operations); + } + } else { + log.error("Cannot find resources in swagger v1.2 document"); + } } + JSONObject swagger2Doc = generateSwagger2Document(swagger12doc, apiDefPaths, swagger12BasePath, api); + return swagger2Doc.toJSONString(); + } catch (UnsupportedEncodingException e) { + log.error("Error while reading swagger resource", e); } - JSONObject swagger2Doc = generateSwagger2Document(swagger12doc, apiDefPaths, swagger12BasePath); - return swagger2Doc.toJSONString(); + + return null; } @@ -510,37 +683,52 @@ private String getSwagger2docUsingSwagger12RegistryResources(Registry registry, */ private static JSONObject generateSwagger2Document(JSONObject swagger12doc, - Map apiDefPaths, String swagger12BasePath) + Map apiDefPaths, String swagger12BasePath, API api) throws ParseException, MalformedURLException { + log.debug("Calling generateSwagger2Document"); + //create swagger 2.0 doc JSONObject swagger20doc = new JSONObject(); //set swagger version - swagger20doc.put("swagger", "2.0"); + swagger20doc.put(Constants.SWAGGER, Constants.SWAGGER_V2); //set the info object - JSONObject info = generateInfoObject(swagger12doc); + JSONObject info = generateInfoObject(swagger12doc, api); //update info object - swagger20doc.put("info", info); + swagger20doc.put(Constants.SWAGGER_INFO, info); //set the paths object JSONObject pathObj = generatePathsObj(apiDefPaths); - swagger20doc.put("paths", pathObj); - - URL url = new URL(swagger12BasePath); - swagger20doc.put("host", url.getHost()); - swagger20doc.put("basePath", url.getPath()); - - JSONArray schemes = new JSONArray(); - schemes.add(url.getProtocol()); - swagger20doc.put("schemes", schemes); + //JSONObject pathObj = generatePathsObj(api); + swagger20doc.put(Constants.SWAGGER_PATHS, pathObj); + + //Base path and host is not needed for swagger v2.0 + /*if (swagger12BasePath != null) { + URL url = new URL(swagger12BasePath); + swagger20doc.put(Constants.SWAGGER_HOST, url.getHost()); + swagger20doc.put(Constants.SWAGGER_BASE_PATH, url.getPath()); + + JSONArray schemes = new JSONArray(); + schemes.add(url.getProtocol()); + swagger20doc.put(Constants.SWAGGER_SCHEMES, schemes); + } + else { + log.debug("swagger12BasePath is null"); + }*/ //securityDefinitions - if (swagger12doc.containsKey("authorizations")) { + if (swagger12doc.containsKey(Constants.SWAGGER_AUTHORIZATIONS)) { JSONObject securityDefinitions = generateSecurityDefinitionsObject(swagger12doc); - swagger20doc.put("securityDefinitions", securityDefinitions); + swagger20doc.put(Constants.SWAGGER_X_WSO2_SECURITY, securityDefinitions); } + //Add a sample definition + JSONObject sampleDefinitionObject = new JSONObject(); + JSONObject sampleItemObject = new JSONObject(); + sampleDefinitionObject.put(Constants.SWAGGER_SAMPLE_DEFINITION, sampleItemObject); + swagger20doc.put(Constants.SWAGGER_DEFINITIONS, sampleDefinitionObject); + return swagger20doc; } @@ -554,20 +742,23 @@ private static JSONObject generateSwagger2Document(JSONObject swagger12doc, * @throws ParseException */ private static JSONObject generateSecurityDefinitionsObject(JSONObject swagger12doc) throws ParseException { + log.debug("Calling generateSecurityDefinitionsObject"); JSONParser parser = new JSONParser(); JSONObject securityDefinitionObject = new JSONObject(); JSONObject securitySchemeObject = (JSONObject) parser.parse(Constants.DEFAULT_SECURITY_SCHEME); - - JSONObject authorizations = (JSONObject) swagger12doc.get("authorizations"); - Set authTypes = authorizations.keySet(); - - for (Object obj : authTypes) { - JSONObject authObj = (JSONObject) authorizations.get(obj.toString()); - if (authObj.containsKey("scopes")) { - //Put it to custom WSO2 scopes - securitySchemeObject.put("x-wso2-scopes", authObj.get("scopes")); + if(swagger12doc.containsKey(Constants.SWAGGER_AUTHORIZATIONS)) { + JSONObject authorizations = (JSONObject) swagger12doc.get(Constants.SWAGGER_AUTHORIZATIONS); + Set authTypes = authorizations.keySet(); + for (Object obj : authTypes) { + JSONObject authObj = (JSONObject) authorizations.get(obj.toString()); + if (authObj.containsKey(Constants.SWAGGER_SCOPES)) { + //Put it to custom WSO2 scopes + if(authObj.containsKey(Constants.SWAGGER_SCOPES)) { + securitySchemeObject.put(Constants.SWAGGER_X_WSO2_SCOPES, authObj.get(Constants.SWAGGER_SCOPES)); + } + } + securityDefinitionObject.put(Constants.SWAGGER_OBJECT_NAME_APIM, securitySchemeObject); } - securityDefinitionObject.put(obj.toString(), securitySchemeObject); } return securityDefinitionObject; } @@ -581,51 +772,60 @@ private static JSONObject generateSecurityDefinitionsObject(JSONObject swagger12 * @return swagger v2 infoObject * @throws ParseException */ - private static JSONObject generateInfoObject(JSONObject swagger12doc) throws ParseException { + private static JSONObject generateInfoObject(JSONObject swagger12doc, API api) throws ParseException { - JSONObject infoObj = (JSONObject) swagger12doc.get("info"); + JSONObject infoObj; JSONParser parser = new JSONParser(); JSONObject swagger2InfoObj = (JSONObject) parser.parse(Constants.DEFAULT_INFO); + String title = api.getId().getApiName(); + String version = api.getId().getVersion(); - //set the required parameters first - String title = (String) infoObj.get("title"); - String version = (String) swagger12doc.get("apiVersion"); - - swagger2InfoObj.put("title", title); - swagger2InfoObj.put("version", version); - if (infoObj.containsKey("description")) { - swagger2InfoObj.put("description", infoObj.get("description")); - } - if (infoObj.containsKey("termsOfServiceUrl")) { - swagger2InfoObj.put("termsOfService", infoObj.get("termsOfServiceUrl")); - } + /*Check whether info object is available in swagger 1.2 or not, if not skip reading it and get title and version + from API object */ + if (swagger12doc.containsKey("info")) { + infoObj = (JSONObject) swagger12doc.get("info"); + if (infoObj.containsKey("title")) { + title = (String) infoObj.get("title"); + } + if (infoObj.containsKey("apiVersion")) { + version = (String) swagger12doc.get("apiVersion"); + } + if (infoObj.containsKey(Constants.SWAGGER_DESCRIPTION)) { + swagger2InfoObj.put(Constants.SWAGGER_DESCRIPTION, infoObj.get("description")); + } + if (infoObj.containsKey(Constants.SWAGGER_TERMS_OF_SERVICE_URL)) { + swagger2InfoObj.put(Constants.SWAGGER_TERMS_OF_SERVICE, infoObj.get(Constants.SWAGGER_TERMS_OF_SERVICE_URL)); + } - //contact object - if (infoObj.containsKey("contact")) { - JSONObject contactsObj = new JSONObject(); - String contact = (String) infoObj.get("contact"); - if (contact.contains("http")) { - contactsObj.put("url", contact); - } else if (contact.contains("@")) { - contactsObj.put("email", contact); - } else { - contactsObj.put("name", contact); + //contact object + if (infoObj.containsKey(Constants.SWAGGER_CONTACT)) { + JSONObject contactsObj = new JSONObject(); + String contact = (String) infoObj.get(Constants.SWAGGER_CONTACT); + if (contact.contains("http")) { + contactsObj.put(Constants.SWAGGER_URL, contact); + } else if (contact.contains("@")) { + contactsObj.put(Constants.SWAGGER_EMAIL, contact); + } else { + contactsObj.put(Constants.SWAGGER_NAME, contact); + } + swagger2InfoObj.put(Constants.SWAGGER_CONTACT, contactsObj); } - swagger2InfoObj.put("contact", contactsObj); - } - //licence object - JSONObject licenseObj = new JSONObject(); - if (infoObj.containsKey("license")) { - licenseObj.put("name", infoObj.get("license")); - } - if (infoObj.containsKey("licenseUrl")) { - licenseObj.put("url", infoObj.get("licenseUrl")); - } - if (!licenseObj.isEmpty()) { - swagger2InfoObj.put("license", licenseObj); + //licence object + JSONObject licenseObj = new JSONObject(); + if (infoObj.containsKey(Constants.SWAGGER_LICENCE)) { + licenseObj.put(Constants.SWAGGER_NAME, infoObj.get(Constants.SWAGGER_LICENCE)); + } + if (infoObj.containsKey(Constants.SWAGGER_LICENCE_URL)) { + licenseObj.put(Constants.SWAGGER_URL, infoObj.get(Constants.SWAGGER_LICENCE_URL)); + } + if (!licenseObj.isEmpty()) { + swagger2InfoObj.put(Constants.SWAGGER_LICENCE, licenseObj); + } } + swagger2InfoObj.put(Constants.SWAGGER_TITLE, title); + swagger2InfoObj.put(Constants.SWAGGER_VER, version); return swagger2InfoObj; } @@ -640,7 +840,13 @@ private static JSONObject generateInfoObject(JSONObject swagger12doc) throws Par */ private static JSONObject generatePathsObj(Map apiDefinitionPaths) throws ParseException { JSONObject pathsObj = new JSONObject(); - JSONParser jsonParser = new JSONParser(); + + String defaultType = "string"; + //add default response + JSONObject responseObject = new JSONObject(); + JSONObject status200 = new JSONObject(); + status200.put(Constants.SWAGGER_DESCRIPTION, "OK"); + responseObject.put(Constants.SWAGGER_RESPONSE_200, status200); for (Map.Entry entry : apiDefinitionPaths.entrySet()) { String key = entry.getKey(); @@ -648,64 +854,81 @@ private static JSONObject generatePathsObj(Map apiDefinitionP JSONObject pathItemObj = new JSONObject(); for (Object operation : operations) { JSONObject operationObject = (JSONObject) operation; - String method = (String) operationObject.get("method"); - JSONArray swagger2ParamObjects = (JSONArray) operationObject.get("parameters"); - JSONObject swagger2OperationsObj = new JSONObject(); - JSONArray newParameters = new JSONArray(); - for (Object swagger2ParamObj : swagger2ParamObjects) { - JSONObject oldParam = (JSONObject) swagger2ParamObj; - JSONObject paramObj = new JSONObject(); - paramObj.put("name", oldParam.get("name")); - paramObj.put("in", oldParam.get("paramType")); - paramObj.put("required", oldParam.get("required")); - if (paramObj.containsKey("description")) { - paramObj.put("description", oldParam.get("description")); - } else { - paramObj.put("description", ""); - } - //Skip body parameter of GET and DELETE methods - /*if (!("GET".equals(method)) && !("DELETE".equals(method))) { - newParameters.add(paramObj); - } else { - if (!("body".equals(oldParam.get("paramType")))) { + if (operationObject.containsKey("method")) { + String method = (String) operationObject.get("method"); + if (operationObject.containsKey("parameters")) { + JSONArray swagger2ParamObjects = (JSONArray) operationObject.get("parameters"); + JSONObject swagger2OperationsObj = new JSONObject(); + JSONArray newParameters = new JSONArray(); + for (Object swagger2ParamObj : swagger2ParamObjects) { + JSONObject oldParam = (JSONObject) swagger2ParamObj; + JSONObject paramObj = new JSONObject(); + paramObj.put(Constants.SWAGGER_NAME, oldParam.get(Constants.SWAGGER_NAME)); + + paramObj.put(Constants.SWAGGER_PARAM_TYPE_IN, oldParam.get("paramType")); + if (Constants.SWAGGER_PARAM_TYPE_BODY.equals(oldParam.get("paramType"))) { + JSONObject refObject = new JSONObject(); + refObject.put(Constants.SWAGGER_REF, "#/definitions/sampleItem"); + paramObj.put(Constants.SWAGGER_BODY_SCHEMA, refObject); + } else { + if (paramObj.containsKey(Constants.SWAGGER_REQUIRED_PARAM)) { + paramObj.put(Constants.SWAGGER_PARAM_TYPE, oldParam.get("type")); + } else { + paramObj.put(Constants.SWAGGER_PARAM_TYPE, defaultType); + } + } + + if (paramObj.containsKey(Constants.SWAGGER_REQUIRED_PARAM)) { + paramObj.put(Constants.SWAGGER_REQUIRED_PARAM, oldParam.get(Constants.SWAGGER_REQUIRED_PARAM)); + } else { + paramObj.put(Constants.SWAGGER_REQUIRED_PARAM, false); + } + if (paramObj.containsKey(Constants.SWAGGER_DESCRIPTION)) { + paramObj.put(Constants.SWAGGER_DESCRIPTION, oldParam.get(Constants.SWAGGER_DESCRIPTION)); + } else { + paramObj.put(Constants.SWAGGER_DESCRIPTION, ""); + } newParameters.add(paramObj); } - }*/ - } - - //generate the Operation object - // (https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operationObject) - swagger2OperationsObj.put("operationId", operationObject.get("nickname")); - //setting operation level params - swagger2OperationsObj.put("parameters", newParameters); - if (operationObject.containsKey("notes")) { - swagger2OperationsObj.put("description", operationObject.get("notes")); - } - if (operationObject.containsKey("summary")) { - swagger2OperationsObj.put("summary", operationObject.get("summary")); - } + //generate the Operation object + // (https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operationObject) + swagger2OperationsObj.put(Constants.SWAGGER_OPERATION_ID, operationObject.get("nickname")); + //setting operation level params + swagger2OperationsObj.put(Constants.SWAGGER_PARAMETERS, newParameters); - //set pathItem object for the resource - //(https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#pathItemObject) - pathItemObj.put(method.toLowerCase(), swagger2OperationsObj); + //Add auth_type and throttling_tier + if (operationObject.containsKey(Constants.SWAGGER_AUTH_TYPE)) { + swagger2OperationsObj.put(Constants.SWAGGER_X_AUTH_TYPE, operationObject.get(Constants.SWAGGER_AUTH_TYPE)); + } + if (operationObject.containsKey(Constants.SWAGGER_THROTTLING_TIER)) { + swagger2OperationsObj.put(Constants.SWAGGER_X_THROTTLING_TIER, operationObject.get(Constants.SWAGGER_THROTTLING_TIER)); + } - //set the responseObject - //(https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#responsesObject) - JSONObject responseObject = null; - if (operationObject.containsKey("responseMessages")) { - responseObject = new JSONObject(); - JSONArray responseMessages = (JSONArray) operationObject.get("responseMessages"); - for (Object responseMessage : responseMessages) { - JSONObject errorObj = (JSONObject) responseMessage; - responseObject.put(errorObj.get("code"), errorObj.get("message")); + if (operationObject.containsKey("notes")) { + swagger2OperationsObj.put(Constants.SWAGGER_DESCRIPTION, operationObject.get("notes")); + } + if (operationObject.containsKey(Constants.SWAGGER_SUMMARY)) { + swagger2OperationsObj.put(Constants.SWAGGER_SUMMARY, operationObject.get(Constants.SWAGGER_SUMMARY)); + } + //set pathItem object for the resource + //(https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#pathItemObject) + pathItemObj.put(method.toLowerCase(), swagger2OperationsObj); + //set the responseObject + //(https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#responsesObject) + if (operationObject.containsKey("responseMessages")) { + responseObject = new JSONObject(); + JSONArray responseMessages = (JSONArray) operationObject.get("responseMessages"); + for (Object responseMessage : responseMessages) { + JSONObject errorObj = (JSONObject) responseMessage; + responseObject.put(errorObj.get("code"), errorObj.get("message")); + } + } + swagger2OperationsObj.put(Constants.SWAGGER_RESPONSES, responseObject); } + } else { + log.error("Needed parameter method does not exists in swagger v1.2 doc"); } - if (responseObject == null) { - //set a default response message since this is required field - responseObject = (JSONObject) jsonParser.parse(Constants.DEFAULT_RESPONSE); - } - swagger2OperationsObj.put("responses", responseObject); } pathsObj.put(key, pathItemObj); } @@ -721,7 +944,7 @@ private static JSONObject generatePathsObj(Map apiDefinitionP */ @Override public void cleanOldResources() throws APIMigrationException { - log.info("Resource cleanup started for API Manager 1.9.0"); + log.info("Resource cleanup started for API Manager " + Constants.VERSION_1_9); try { for (Tenant tenant : tenantsArray) { PrivilegedCarbonContext.startTenantFlow(); @@ -770,6 +993,17 @@ public void cleanOldResources() throws APIMigrationException { } } + /** + * This method is used to migrate API stats database. + * Database schema changes and data modifications as required will be carried out. + * + * @throws APIMigrationException + */ + @Override + public void statsMigration() throws APIMigrationException { + StatDBUtil.updateContext(); + } + /** * This method is used to migrate all the file system components * such as sequences and synapse files @@ -788,10 +1022,11 @@ public void fileSystemMigration() throws APIMigrationException { * * @throws APIMigrationException */ - void sequenceMigration() throws APIMigrationException { + void sequenceMigration() { String repository = CarbonUtils.getCarbonRepository(); String TenantRepo = CarbonUtils.getCarbonTenantsDirPath(); for (Tenant tenant : tenantsArray) { + log.debug("Start sequenceMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); String SequenceFilePath; if (tenant.getId() != MultitenantConstants.SUPER_TENANT_ID) { SequenceFilePath = TenantRepo + "/" + tenant.getId() + @@ -799,6 +1034,13 @@ void sequenceMigration() throws APIMigrationException { } else { SequenceFilePath = repository + "synapse-configs/default/sequences/"; } + + File sequenceFolder = new File(SequenceFilePath); + if (!sequenceFolder.exists()) { + log.debug("No sequence folder exists for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + continue; + } + try { FileUtils.copyInputStreamToFile(MigrateFrom18to19.class.getResourceAsStream( "/18to19Migration/sequence-scripts/_cors_request_handler_.xml"), @@ -808,8 +1050,12 @@ void sequenceMigration() throws APIMigrationException { ResourceUtil.copyNewSequenceToExistingSequences(SequenceFilePath, "_token_fault_"); ResourceUtil.copyNewSequenceToExistingSequences(SequenceFilePath, "fault"); } catch (IOException e) { - ResourceUtil.handleException("Error occurred while reading file to copy.", e); + log.error("Error occurred while reading file to copy.", e); + } catch (APIMigrationException e) { + log.error("Copying sequences failed", e); } + + log.debug("End sequenceMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); } } @@ -821,32 +1067,56 @@ void sequenceMigration() throws APIMigrationException { * @throws APIMigrationException */ - void synapseAPIMigration() throws APIMigrationException { + void synapseAPIMigration() { String repository = CarbonUtils.getCarbonRepository(); String tenantRepository = CarbonUtils.getCarbonTenantsDirPath(); for (Tenant tenant : tenantsArray) { - - String SequenceFilePath; + log.debug("Start synapseAPIMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + String apiFilePath; if (tenant.getId() != MultitenantConstants.SUPER_TENANT_ID) { - SequenceFilePath = tenantRepository + "/" + tenant.getId() + + apiFilePath = tenantRepository + "/" + tenant.getId() + "/synapse-configs/default/api"; } else { - SequenceFilePath = repository + "synapse-configs/default/api"; + apiFilePath = repository + "synapse-configs/default/api"; } - File APIFiles = new File(SequenceFilePath); + File APIFiles = new File(apiFilePath); File[] synapseFiles = APIFiles.listFiles(); + + if (synapseFiles == null) { + log.debug("No api folder " + apiFilePath + " exists for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); + continue; + } + for (File synapseFile : synapseFiles) { - if (tenant.getId() == MultitenantConstants.SUPER_TENANT_ID) { - if (synapseFile.getName().matches("[\\w+][--][\\w+][__v]")) { - ResourceUtil.updateSynapseAPI(synapseFile, "ENDPOINT"); - } - } else { - if (synapseFile.getName().matches("[\\w+][-AT-]" + tenant.getDomain() + "[--][\\w+][--v]]")) { - ResourceUtil.updateSynapseAPI(synapseFile, "ENDPOINT"); + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docFactory.setNamespaceAware(true); + + try { + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(synapseFile); + + doc.getDocumentElement().normalize(); + + Element rootElement = doc.getDocumentElement(); + + if (Constants.SYNAPSE_API_ROOT_ELEMENT.equals(rootElement.getNodeName()) && + rootElement.hasAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VERSION)) { + ResourceUtil.updateSynapseAPI(doc, synapseFile); } - } + + } catch (ParserConfigurationException e) { + log.error("Parsing exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (SAXException e) { + log.error("SAX exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (IOException e) { + log.error("IO exception encountered for " + synapseFile.getAbsolutePath(), e); + } catch (APIMigrationException e) { + log.error("Updating synapse file failed for " + synapseFile.getAbsolutePath(), e); + } } + + log.debug("End synapseAPIMigration for tenant " + tenant.getId() + "(" + tenant.getDomain() + ")"); } } } diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationClient.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationClient.java index 07d2ba13dc..868b36cde4 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationClient.java +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationClient.java @@ -65,4 +65,12 @@ public interface MigrationClient { */ public void cleanOldResources() throws APIMigrationException; + /** + * This method is used to migrate API stats database. + * Database schema changes and data modifications as required will be carried out. + * + * @throws APIMigrationException + */ + public void statsMigration() throws APIMigrationException; + } diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java index 0ef7593adf..af67c52770 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/MigrationDBCreator.java @@ -19,13 +19,22 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.apimgt.migration.APIMigrationException; +import org.wso2.carbon.apimgt.migration.util.Constants; import org.wso2.carbon.apimgt.migration.util.ResourceUtil; import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.dbcreator.DatabaseCreator; import javax.sql.DataSource; -import java.io.*; -import java.sql.*; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.Statement; import java.util.StringTokenizer; public class MigrationDBCreator extends DatabaseCreator { @@ -53,22 +62,6 @@ protected String getDbScriptLocation(String databaseType) { @Override public void createRegistryDatabase() throws SQLException, APIMigrationException { - /*String databaseType; - try { - databaseType = DatabaseCreator.getDatabaseType(this.dataSource.getConnection()); - - String scriptPath = getDbScriptLocation(databaseType); - File scriptFile = new File(scriptPath); - if (scriptFile.exists()) { - super.createRegistryDatabase(); - } else { - log.error("API Migration client cannot find the database script."); - } - } catch (Exception e) { - ResourceUtil.handleException("Error occurred while accessing the database connection", e); - }*/ - - try { connection = dataSource.getConnection(); connection.setAutoCommit(false); @@ -81,6 +74,7 @@ public void createRegistryDatabase() throws SQLException, APIMigrationException } catch (SQLException e) { ResourceUtil.handleException("Error occurred while migrating the database", e); } catch (Exception e) { + /* executeSQLScript throws generic Exception because DatabaseCreator.getDatabaseType superclass throws */ ResourceUtil.handleException("Error occurred while executing sql script", e); } finally { if (connection != null) { @@ -91,14 +85,15 @@ public void createRegistryDatabase() throws SQLException, APIMigrationException } + //org.wso2.carbon.utils.dbcreator.DatabaseCreator.getDatabaseType throws generic Exception private void executeSQLScript() throws Exception { String databaseType = DatabaseCreator.getDatabaseType(this.connection); boolean keepFormat = false; - if ("oracle".equals(databaseType)) { + if (Constants.DB_TYPE_ORACLE.equals(databaseType)) { delimiter = "/"; - } else if ("db2".equals(databaseType)) { + } else if (Constants.DB_TYPE_DB2.equals(databaseType)) { delimiter = "/"; - } else if ("openedge".equals(databaseType)) { + } else if (Constants.DB_TYPE_OPENEDGE.equals(databaseType)) { delimiter = "/"; keepFormat = true; } @@ -110,7 +105,7 @@ private void executeSQLScript() throws Exception { try { InputStream is = new FileInputStream(dbscriptName); - reader = new BufferedReader(new InputStreamReader(is)); + reader = new BufferedReader(new InputStreamReader(is, "UTF8")); String line; while ((line = reader.readLine()) != null) { line = line.trim(); @@ -148,17 +143,17 @@ private void executeSQLScript() throws Exception { } } catch (IOException e) { log.error("Error occurred while executing SQL script for creating registry database", e); - throw new Exception("Error occurred while executing SQL script for creating registry database", e); + throw new APIMigrationException("Error occurred while executing SQL script for creating registry database", e); } finally { - if(reader != null){ + if (reader != null) { reader.close(); } } } - private void executeSQL(String sql) throws Exception { + private void executeSQL(String sql) throws APIMigrationException { // Check and ignore empty statements if ("".equals(sql.trim())) { return; @@ -203,7 +198,7 @@ private void executeSQL(String sql) throws Exception { log.info("Table Already Exists. Hence, skipping table creation"); } } else { - throw new Exception("Error occurred while executing : " + sql, e); + throw new APIMigrationException("Error occurred while executing : " + sql, e); } } finally { if (resultSet != null) { diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java index fedf9f7c32..2b4a6a43c7 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/client/internal/APIMMigrationServiceComponent.java @@ -25,14 +25,13 @@ import org.wso2.carbon.apimgt.migration.client.MigrateFrom18to19; import org.wso2.carbon.apimgt.migration.client.MigrationClient; import org.wso2.carbon.apimgt.migration.util.Constants; +import org.wso2.carbon.apimgt.migration.util.StatDBUtil; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.registry.core.service.TenantRegistryLoader; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.service.RealmService; import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; /** @@ -63,70 +62,51 @@ public class APIMMigrationServiceComponent { * @param context OSGi component context. */ protected void activate(ComponentContext context) { - String migrateVersion = null; - boolean cleanupNeeded = false; - boolean isDBMigrationNeeded = false; - boolean isRegistryMigrationNeeded = false; - boolean isFileSystemMigrationNeeded = false; - try { APIMgtDBUtil.initialize(); } catch (Exception e) { - log.error("Error occurred while initializing DB Util " + e.getMessage()); + //APIMgtDBUtil.initialize() throws generic exception + log.error("Error occurred while initializing DB Util ", e); } - Map argsMap = new HashMap(); - argsMap.put("migrateVersion", System.getProperty("migrate")); - argsMap.put("isCleanUpNeeded", System.getProperty("cleanup")); - argsMap.put("isDBMigrationNeeded", System.getProperty("migrateDB")); - argsMap.put("isRegMigrationNeeded", System.getProperty("migrateReg")); - argsMap.put("isFileSysMigrationNeeded", System.getProperty("migrateFS")); - - - if (!argsMap.isEmpty()) { - migrateVersion = argsMap.get("migrateVersion"); - if (argsMap.get("isCleanUpNeeded") != null) { - cleanupNeeded = Boolean.parseBoolean(argsMap.get("isCleanUpNeeded")); - } - if (argsMap.get("isDBMigrationNeeded") != null) { - isDBMigrationNeeded = Boolean.parseBoolean(argsMap.get("isDBMigrationNeeded")); - } - if (argsMap.get("isRegMigrationNeeded") != null) { - isRegistryMigrationNeeded = Boolean.parseBoolean(argsMap.get("isRegMigrationNeeded")); - } - if (argsMap.get("isFileSysMigrationNeeded") != null) { - isFileSystemMigrationNeeded = Boolean.parseBoolean(argsMap.get("isFileSysMigrationNeeded")); - } - } + String migrateToVersion = System.getProperty(Constants.ARG_MIGRATE_TO_VERSION); + String tenants = System.getProperty(Constants.ARG_MIGRATE_TENANTS); + String blackListTenants = System.getProperty(Constants.ARG_MIGRATE_BLACKLIST_TENANTS); + boolean migrateAll = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_ALL)); + boolean cleanupNeeded = Boolean.parseBoolean(System.getProperty(Constants.ARG_CLEANUP)); + boolean isDBMigration = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_DB)); + boolean isRegistryMigration = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_REG)); + boolean isFileSystemMigration = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_FILE_SYSTEM)); + boolean isStatMigration = Boolean.parseBoolean(System.getProperty(Constants.ARG_MIGRATE_STATS)); try { - if (migrateVersion != null) { - if (Constants.VERSION_1_9.equalsIgnoreCase(migrateVersion)) { - log.info("Migrating WSO2 API Manager 1.8.0 resources to WSO2 API Manager 1.9.0"); + if (migrateToVersion != null) { + if (Constants.VERSION_1_9.equalsIgnoreCase(migrateToVersion)) { + log.info("Migrating WSO2 API Manager 1.8.0 to WSO2 API Manager 1.9.0"); // Create a thread and wait till the APIManager DBUtils is initialized - MigrationClient migrateFrom18to19 = new MigrateFrom18to19(); + MigrationClient migrateFrom18to19 = new MigrateFrom18to19(tenants, blackListTenants); //Default operation will migrate all three types of resources - if (argsMap.get("isDBMigrationNeeded") == null && argsMap.get("isRegMigrationNeeded") == null && argsMap.get("isFileSysMigrationNeeded") == null) { + if (migrateAll) { log.info("Migrating WSO2 API Manager 1.8.0 resources to WSO2 API Manager 1.9.0"); - migrateFrom18to19.databaseMigration(migrateVersion); + migrateFrom18to19.databaseMigration(migrateToVersion); migrateFrom18to19.registryResourceMigration(); migrateFrom18to19.fileSystemMigration(); } else { //Only performs database migration - if (isDBMigrationNeeded) { + if (isDBMigration) { log.info("Migrating WSO2 API Manager 1.8.0 databases to WSO2 API Manager 1.9.0"); - migrateFrom18to19.databaseMigration(migrateVersion); + migrateFrom18to19.databaseMigration(migrateToVersion); } //Only performs registry migration - if (isRegistryMigrationNeeded) { + if (isRegistryMigration) { log.info("Migrating WSO2 API Manager 1.8.0 registry resources to WSO2 API Manager 1.9.0"); migrateFrom18to19.registryResourceMigration(); } //Only performs file system migration - if (isFileSystemMigrationNeeded) { + if (isFileSystemMigration) { log.info("Migrating WSO2 API Manager 1.8.0 file system resources to WSO2 API Manager 1.9.0"); migrateFrom18to19.fileSystemMigration(); } @@ -137,21 +117,35 @@ protected void activate(ComponentContext context) { log.info("Old resources cleaned up."); } + if (isStatMigration) { + StatDBUtil.initialize(); + migrateFrom18to19.statsMigration(); + log.info("Stat migration completed"); + } + if (log.isDebugEnabled()) { log.debug("API Manager 1.8.0 to 1.9.0 migration successfully completed"); } } else { - log.error("The given migrate version " + migrateVersion + " is not supported. Please check the version and try again."); + log.error("The given migrate version " + migrateToVersion + " is not supported. Please check the version and try again."); + + } + } + else { // Migration version not specified + if (migrateAll || cleanupNeeded || isDBMigration || isRegistryMigration || isFileSystemMigration) { + log.error("The property " + Constants.ARG_MIGRATE_TO_VERSION + " has not been specified . Please specify the property and try again."); } } } catch (APIMigrationException e) { - log.error("API Management exception occurred while migrating " + e.getMessage()); + log.error("API Management exception occurred while migrating", e); } catch (UserStoreException e) { - log.error("User store exception occurred while migrating " + e.getMessage()); + log.error("User store exception occurred while migrating", e); } catch (SQLException e) { - log.error("SQL exception occurred while migrating " + e.getMessage()); + log.error("SQL exception occurred while migrating", e); } catch (Exception e) { - log.error("Error occurred while initializing data source. " + e.getMessage()); + log.error("Generic exception occurred while migrating", e); + } catch (Throwable t) { + log.error("Throwable error", t); } log.info("WSO2 API Manager migration component successfully activated."); } diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java index a26023a8b5..6416abd0ff 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/Constants.java @@ -18,20 +18,121 @@ public class Constants { - public static final String VERSION_1_7 = "1.7"; - public static final String VERSION_1_8 = "1.8"; public static final String VERSION_1_9 = "1.9"; public static final String LINE_BREAK = "\\n"; public static final String CONSTRAINT = "constraint"; public static final String ALTER = "alter"; public static final String DELIMITER = ";"; + public static final String API = "api"; public static final String GOVERNANCE_COMPONENT_REGISTRY_LOCATION = "/repository/components/org.wso2.carbon" + ".governance"; public static final String RXT_PATH = "/repository/resources/rxts/api.rxt"; public static final String DATA_SOURCE_NAME = "DataSourceName"; - //constants for swagger v2 + // Migration client argument property names + public static final String ARG_MIGRATE_TO_VERSION = "migrateToVersion"; + public static final String ARG_MIGRATE_TENANTS = "tenants"; + public static final String ARG_MIGRATE_BLACKLIST_TENANTS = "blackListed"; + public static final String ARG_MIGRATE_ALL = "migrate"; + public static final String ARG_CLEANUP = "cleanup"; + public static final String ARG_MIGRATE_DB = "migrateDB"; + public static final String ARG_MIGRATE_REG = "migrateReg"; + public static final String ARG_MIGRATE_FILE_SYSTEM = "migrateFS"; + public static final String ARG_MIGRATE_STATS = "migrateStats"; + + // Synapse configuration related + public static final String SYNAPSE_API_ROOT_ELEMENT = "api"; + public static final String SYNAPSE_API_ATTRIBUTE_CONTEXT = "context"; + public static final String SYNAPSE_API_ATTRIBUTE_VERSION = "version"; + public static final String SYNAPSE_API_ATTRIBUTE_VERSION_TYPE = "version-type"; + public static final String SYNAPSE_API_ATTRIBUTE_SOURCE = "source"; + public static final String SYNAPSE_API_ATTRIBUTE_NAME = "name"; + public static final String SYNAPSE_API_ATTRIBUTE_EXPRESSION = "expression"; + public static final String SYNAPSE_API_ATTRIBUTE_CLASS = "class"; + public static final String SYNAPSE_API_ATTRIBUTE_VALUE = "value"; + public static final String SYNAPSE_API_ATTRIBUTE_XMLNS = "xmlns"; + public static final String SYNAPSE_API_ELEMENT_PROPERTY = "property"; + public static final String SYNAPSE_API_ELEMENT_FILTER = "filter"; + public static final String SYNAPSE_API_ELEMENT_CLASS = "class"; + public static final String SYNAPSE_API_ELEMENT_INSEQUENCE = "inSequence"; + public static final String SYNAPSE_API_ELEMENT_OUTSEQUENCE = "outSequence"; + public static final String SYNAPSE_API_ELEMENT_HANDLERS = "handlers"; + public static final String SYNAPSE_API_ELEMENT_HANDLER = "handler"; + public static final String SYNAPSE_API_ELEMENT_THEN = "then"; + public static final String SYNAPSE_API_ELEMENT_SEND = "send"; + public static final String SYNAPSE_API_VALUE_BACKEND_REQUEST_TIME = "api.ut.backendRequestTime"; + public static final String SYNAPSE_API_VALUE_AM_KEY_TYPE = "$ctx:AM_KEY_TYPE"; + public static final String SYNAPSE_API_VALUE_EXPRESSION = "get-property('SYSTEM_TIME')"; + public static final String SYNAPSE_API_VALUE_RESPONSE_HANDLER = "org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"; + public static final String SYNAPSE_API_VALUE_CORS_HANDLER = "org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler"; + public static final String SYNAPSE_API_VALUE_INLINE = "inline"; + public static final String SYNAPSE_API_VALUE_INLINE_UPPERCASE = "INLINE"; + public static final String SYNAPSE_API_VALUE_ENPOINT = "ENDPOINT"; + public static final String SYNAPSE_API_VALUE_VERSION_TYPE_URL = "url"; + public static final String SYNAPSE_API_VALUE_VERSION_TYPE_CONTEXT = "context"; + public static final String SYNAPSE_API_XMLNS = "http://ws.apache.org/ns/synapse"; + + + //Swagger v2.0 constants + public static final String SWAGGER_X_SCOPE = "x-scope"; + public static final String SWAGGER_X_AUTH_TYPE = "x-auth-type"; + public static final String SWAGGER_X_THROTTLING_TIER = "x-throttling-tier"; + public static final String SWAGGER_AUTH_TYPE = "auth_type"; + public static final String SWAGGER_THROTTLING_TIER = "throttling_tier"; + public static final String SWAGGER_X_MEDIATION_SCRIPT = "x-mediation-script"; + public static final String SWAGGER_X_WSO2_SECURITY = "x-wso2-security"; + public static final String SWAGGER_X_WSO2_SCOPES = "x-wso2-scopes"; + public static final String SWAGGER_SCOPE_KEY = "key"; + public static final String SWAGGER_NAME = "name"; + public static final String SWAGGER_DESCRIPTION = "description"; + public static final String SWAGGER_ROLES = "roles"; + public static final String SWAGGER_TITLE = "title"; + public static final String SWAGGER_EMAIL = "email"; + public static final String SWAGGER_URL = "url"; + public static final String SWAGGER_CONTACT = "contact"; + public static final String SWAGGER_LICENCE = "license"; + public static final String SWAGGER_LICENCE_URL = "licenseUrl"; + public static final String SWAGGER_VER = "version"; + public static final String SWAGGER_OBJECT_NAME_APIM = "apim"; + public static final String SWAGGER_PATHS = "paths"; + public static final String SWAGGER_RESPONSES = "responses"; + public static final String SWAGGER = "swagger"; + public static final String SWAGGER_V2 = "2.0"; + public static final String SWAGGER_INFO = "info"; + public static final String SWAGGER_REQUIRED_PARAM = "required"; + public static final String SWAGGER_HOST = "host"; + public static final String SWAGGER_BASE_PATH = "basePath"; + public static final String SWAGGER_SCHEMES = "schemes"; + public static final String SWAGGER_AUTHORIZATIONS = "authorizations"; + public static final String SWAGGER_SECURITY_DEFINITIONS = "securityDefinitions"; + public static final String SWAGGER_SCOPES = "scopes"; + public static final String SWAGGER_TERMS_OF_SERVICE = "termsOfService"; + public static final String SWAGGER_TERMS_OF_SERVICE_URL = "termsOfServiceUrl"; + public static final String SWAGGER_PARAM_TYPE_IN = "in"; + public static final String SWAGGER_OPERATION_ID = "operationId"; + public static final String SWAGGER_PARAMETERS = "parameters"; + public static final String SWAGGER_SUMMARY = "summary"; + public static final String SWAGGER_RESPONSE_200 = "200"; + public static final String SWAGGER_PARAM_TYPE = "type"; + public static final String SWAGGER_PARAM_TYPE_BODY = "body"; + public static final String SWAGGER_BODY_SCHEMA = "schema"; + public static final String SWAGGER_DEFINITIONS = "definitions"; + public static final String SWAGGER_REF = "$ref"; + public static final String SWAGGER_SAMPLE_DEFINITION = "sampleItem"; + + + + + + //database types + public static final String DB_TYPE_ORACLE = "oracle"; + public static final String DB_TYPE_DB2 = "db2"; + public static final String DB_TYPE_MYSQL = "mysql"; + public static final String DB_TYPE_MSSQL = "mssql"; + public static final String DB_TYPE_POSTGRE = "postgre"; + public static final String DB_TYPE_OPENEDGE = "openedge"; + //default Swagger v2 response parameter public static final String DEFAULT_RESPONSE = "{ " + diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java index 37772b56d7..12843caa10 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/ResourceUtil.java @@ -33,14 +33,12 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.sql.Connection; import java.sql.SQLException; public class ResourceUtil { @@ -91,31 +89,6 @@ public static String getRxtResourceLocation(String apiName, String apiVersion, S - /** - * This method is used to get the database driver name - * - * @return user database type as a string - * @throws SQLException - */ - private static String getDatabaseDriverName() throws SQLException { - Connection connection = APIMgtDBUtil.getConnection(); - String databaseType; - - if (connection.getMetaData().getDriverName().contains("MySQL")) { - databaseType = "MYSQL"; - } else if (connection.getMetaData().getDriverName().contains("MS SQL") || - connection.getMetaData().getDriverName().contains("Microsoft")) { - databaseType = "MSSQL"; - } else if (connection.getMetaData().getDriverName().contains("H2")) { - databaseType = "H2"; - } else if (connection.getMetaData().getDriverName().contains("PostgreSQL")) { - databaseType = "POSTGRESQL"; - } else { - databaseType = "ORACLE"; - } - return databaseType; - } - /** * This method picks the query according to the users database * @@ -134,32 +107,27 @@ public static String pickQueryFromResources(String migrateVersion, String queryT String resourcePath; - if (migrateVersion.equalsIgnoreCase(Constants.VERSION_1_9)) { + if (Constants.VERSION_1_9.equalsIgnoreCase(migrateVersion)) { //pick from 18to19Migration/sql-scripts - resourcePath = CarbonUtils.getCarbonHome() + "/dbscripts/migration-1.8.0_to_1.9.0/"; - } else if (migrateVersion.equalsIgnoreCase(Constants.VERSION_1_8)) { - //pick from 17to18Migration/sql-scripts - resourcePath = CarbonUtils.getCarbonHome() + "/dbscripts/migration-1.7.0_to_1.8.0/"; - } else if (migrateVersion.equalsIgnoreCase(Constants.VERSION_1_7)) { - //pick from 16to17Migration/sql-scripts - resourcePath = CarbonUtils.getCarbonHome() + "/dbscripts/migration-1.6.0_to_1.7.0/"; + resourcePath = CarbonUtils.getCarbonHome() + File.separator + "migration-scripts" + File.separator + "18-19-migration" + File.separator; } else { throw new APIMigrationException("No query picked up for the given migrate version. Please check the migrate version."); } if (Constants.CONSTRAINT.equals(queryType)) { - resourcePath = CarbonUtils.getCarbonHome() + "/dbscripts/migration-1.8.0_to_1.9.0/"; + resourcePath = CarbonUtils.getCarbonHome() + File.separator + "migration-scripts" + File.separator + "18-19-migration" + File.separator; //queryTobeExecuted = resourcePath + "drop-fk.sql"; queryTobeExecuted = IOUtils.toString(new FileInputStream(new File(resourcePath + "drop-fk.sql")), "UTF-8"); } else { - queryTobeExecuted = resourcePath + databaseType + ".sql"; + queryTobeExecuted = resourcePath + databaseType + ".sql"; //queryTobeExecuted = IOUtils.toString(new FileInputStream(new File(resourcePath + databaseType + ".sql")), "UTF-8"); } } catch (IOException e) { throw new APIMigrationException("Error occurred while accessing the sql from resources. " + e); } catch (Exception e) { - throw new APIMigrationException("Error occurred while accessing the sql from resources. " + e); + //getDatabaseType inherited from DBCreator, which throws generic exception + throw new APIMigrationException("Error occurred while searching for database type " + e); } return queryTobeExecuted; @@ -188,18 +156,26 @@ public static void copyNewSequenceToExistingSequences(String sequenceDirectoryFi try { String namespace = "http://ws.apache.org/ns/synapse"; String filePath = sequenceDirectoryFilePath + sequenceName + ".xml"; + + File sequenceFile = new File(filePath); + + if (!sequenceFile.exists()) { + log.debug("Sequence file " + sequenceName + ".xml does not exist"); + return; + } + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document doc = docBuilder.parse(filePath); Node sequence = doc.getElementsByTagName("sequence").item(0); Element corsSequence = doc.createElementNS(namespace, "sequence"); - corsSequence.setAttribute("key", "_cors_request_handler"); + corsSequence.setAttribute("key", "_cors_request_handler_"); boolean available = false; for (int i = 0; i < sequence.getChildNodes().getLength(); i++) { Node tempNode = sequence.getChildNodes().item(i); if (tempNode.getNodeType() == Node.ELEMENT_NODE &&"sequence".equals(tempNode.getLocalName()) && - "_cors_request_handler".equals(tempNode.getAttributes().getNamedItem("key").getTextContent())) { + "_cors_request_handler_".equals(tempNode.getAttributes().getNamedItem("key").getTextContent())) { available = true; break; } @@ -235,48 +211,164 @@ public static void copyNewSequenceToExistingSequences(String sequenceDirectoryFi /** * To update synapse API * - * @param filePath file path - * @param implementation new impl + * @param document XML document object + * @param file synapse file * @throws APIMigrationException */ - public static void updateSynapseAPI(File filePath, String implementation) throws APIMigrationException { + public static void updateSynapseAPI(Document document, File file) throws APIMigrationException { try { - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - docFactory.setNamespaceAware(true); - DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); - Document doc = null; - doc = docBuilder.parse(filePath.getAbsolutePath()); - Node handlers = doc.getElementsByTagName("handlers").item(0); - Element corsHandler = doc.createElement("handler"); - corsHandler.setAttribute("class", "org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler"); - Element property = doc.createElement("property"); - property.setAttribute("name", "inline"); - property.setAttribute("value", implementation); - corsHandler.appendChild(property); - NodeList handlerNodes = doc.getElementsByTagName("handler"); - for (int i = 0; i < handlerNodes.getLength(); i++) { - Node tempNode = handlerNodes.item(i); - if ("org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler" - .equals(tempNode.getAttributes().getNamedItem("class").getTextContent())) { - handlers.removeChild(tempNode); - } - handlers.insertBefore(corsHandler, handlerNodes.item(0)); - } + updateAPIAttributes(document, file); + updateHandlers(document, file); + updateResources(document, file); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(filePath); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + DOMSource source = new DOMSource(document); + StreamResult result = new StreamResult(file); transformer.transform(source, result); - } catch (ParserConfigurationException e) { - handleException("Could not initiate Document Builder.", e); } catch (TransformerConfigurationException e) { handleException("Could not initiate TransformerFactory Builder.", e); } catch (TransformerException e) { handleException("Could not transform the source.", e); - } catch (SAXException e) { - handleException("SAX exception occurred while parsing the file.", e); - } catch (IOException e) { - handleException("IO Exception occurred. Please check the file.", e); + } + } + + private static void updateAPIAttributes(Document document, File file) { + Element apiElement = document.getDocumentElement(); + + String versionType = apiElement.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VERSION_TYPE); + + if (versionType.equals(Constants.SYNAPSE_API_VALUE_VERSION_TYPE_URL)) { + String context = apiElement.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_CONTEXT); + String version = apiElement.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VERSION); + + context = context + "/" + version; + apiElement.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_CONTEXT, context); + apiElement.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VERSION_TYPE, Constants.SYNAPSE_API_VALUE_VERSION_TYPE_CONTEXT); + } + } + + + private static void updateHandlers(Document document, File file) { + Element handlersElement = (Element) document.getElementsByTagNameNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_HANDLERS).item(0); + + NodeList handlerNodes = handlersElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_HANDLER); + + for (int i = 0; i < handlerNodes.getLength(); ++i) { + Element handler = (Element) handlerNodes.item(i); + + String className = handler.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_CLASS); + + if (className.equals(Constants.SYNAPSE_API_VALUE_CORS_HANDLER)) { + handlersElement.removeChild(handler); + break; + } + } + + // Find the inSequence + Element inSequenceElement = (Element) document.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_INSEQUENCE).item(0); + + NodeList sendElements = inSequenceElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_SEND); + + Element corsHandler = document.createElementNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_HANDLER); + corsHandler.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_CLASS, Constants.SYNAPSE_API_VALUE_CORS_HANDLER); + Element property = document.createElementNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_PROPERTY); + property.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_NAME, Constants.SYNAPSE_API_VALUE_INLINE); + + if (0 < sendElements.getLength()) { + property.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VALUE, Constants.SYNAPSE_API_VALUE_ENPOINT); + } + else { + property.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_VALUE, Constants.SYNAPSE_API_VALUE_INLINE_UPPERCASE); + } + + corsHandler.appendChild(property); + + handlersElement.insertBefore(corsHandler, handlersElement.getFirstChild()); + + } + + private static void updateResources(Document document, File file) throws APIMigrationException { + NodeList resourceNodes = document.getElementsByTagName("resource"); + for (int i = 0; i < resourceNodes.getLength(); i++) { + Element resourceElement = (Element) resourceNodes.item(i); + + updateInSequence(resourceElement, document); + + updateOutSequence(resourceElement, document); + } + } + + private static void updateInSequence(Element resourceElement, Document doc) { + // Find the inSequence + Element inSequenceElement = (Element) resourceElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_INSEQUENCE).item(0); + + // Find the property element in the inSequence + NodeList properties = inSequenceElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_PROPERTY); + + boolean isBackEndRequestTimeSet = false; + + for (int i = 0; i < properties.getLength(); ++i) { + Element propertyElement = (Element) properties.item(i); + + if (propertyElement.hasAttribute(Constants.SYNAPSE_API_ATTRIBUTE_NAME)) { + if (Constants.SYNAPSE_API_VALUE_BACKEND_REQUEST_TIME.equals(propertyElement.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_NAME))) { + isBackEndRequestTimeSet = true; + break; + } + } + } + + if (!isBackEndRequestTimeSet) { + NodeList filters = inSequenceElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_FILTER); + + for (int j = 0; j < filters.getLength(); ++j) { + Element filterElement = (Element) filters.item(j); + + if (Constants.SYNAPSE_API_VALUE_AM_KEY_TYPE.equals(filterElement.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_SOURCE))) { + // Only one element can exist in filter mediator + Element thenElement = (Element) filterElement.getElementsByTagNameNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_THEN).item(0); + + // At least one element must exist as a child of element + Element sendElement = (Element) thenElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_SEND).item(0); + + Element propertyElement = doc.createElementNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_PROPERTY); + propertyElement.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_NAME, Constants.SYNAPSE_API_VALUE_BACKEND_REQUEST_TIME); + propertyElement.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_EXPRESSION, Constants.SYNAPSE_API_VALUE_EXPRESSION); + + thenElement.insertBefore(propertyElement, sendElement); + } + } + } + } + + + private static void updateOutSequence(Element resourceElement, Document doc) { + // Find the outSequence + Element outSequenceElement = (Element) resourceElement.getElementsByTagNameNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_OUTSEQUENCE).item(0); + + NodeList classNodes = outSequenceElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_CLASS); + + boolean isResponseHandlerSet = false; + + for (int i = 0; i < classNodes.getLength(); ++i) { + Element classElement = (Element) classNodes.item(i); + + if (Constants.SYNAPSE_API_VALUE_RESPONSE_HANDLER.equals(classElement.getAttribute(Constants.SYNAPSE_API_ATTRIBUTE_NAME))) { + isResponseHandlerSet = true; + break; + } + } + + if (!isResponseHandlerSet) { + // There must be at least one element for an outSequence + Element sendElement = (Element) outSequenceElement.getElementsByTagName(Constants.SYNAPSE_API_ELEMENT_SEND).item(0); + + Element classElement = doc.createElementNS(Constants.SYNAPSE_API_XMLNS, Constants.SYNAPSE_API_ELEMENT_CLASS); + classElement.setAttribute(Constants.SYNAPSE_API_ATTRIBUTE_NAME, Constants.SYNAPSE_API_VALUE_RESPONSE_HANDLER); + classElement.removeAttribute(Constants.SYNAPSE_API_ATTRIBUTE_XMLNS); + + outSequenceElement.insertBefore(classElement, sendElement); } } } diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/StatDBUtil.java b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/StatDBUtil.java new file mode 100644 index 0000000000..558d79dc67 --- /dev/null +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/java/org/wso2/carbon/apimgt/migration/util/StatDBUtil.java @@ -0,0 +1,102 @@ +/* +* 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.migration.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.apimgt.migration.APIMigrationException; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class StatDBUtil { + private static volatile DataSource dataSource = null; + private static final String DATA_SOURCE_NAME = "jdbc/WSO2AM_STATS_DB"; + + private static final String TABLE_API_DESTINATION_SUMMARY = "API_DESTINATION_SUMMARY"; + private static final String TABLE_API_FAULT_SUMMARY = "API_FAULT_SUMMARY"; + private static final String TABLE_API_REQUEST_SUMMARY = "API_REQUEST_SUMMARY"; + private static final String TABLE_API_RESOURCE_USAGE_SUMMARY = "API_Resource_USAGE_SUMMARY"; + private static final String TABLE_API_VERSION_USAGE_SUMMARY = "API_VERSION_USAGE_SUMMARY"; + + private static final Log log = LogFactory.getLog(StatDBUtil.class); + + public static void initialize() throws APIMigrationException { + try { + Context ctx = new InitialContext(); + dataSource = (DataSource) ctx.lookup(DATA_SOURCE_NAME); + } catch (NamingException e) { + throw new APIMigrationException("Error while looking up the data " + + "source: " + DATA_SOURCE_NAME); + } + } + + + public static void updateContext() throws APIMigrationException { + if (dataSource == null) { + throw new APIMigrationException("Stats Data source is not configured properly."); + } + + String responseSummarySQL = "UPDATE API_RESPONSE_SUMMARY " + + "SET CONTEXT = concat(API_RESPONSE_SUMMARY.CONTEXT,'/'," + + "(SELECT DISTINCT(VERSION) FROM WSO2AM_STATS_DB.API_REQUEST_SUMMARY WHERE CONTEXT NOT LIKE concat('%', VERSION))) " + + "WHERE API_VERSION = (SELECT DISTINCT(API_VERSION) FROM WSO2AM_STATS_DB.API_REQUEST_SUMMARY WHERE CONTEXT NOT LIKE concat('%', VERSION))"; + + executeSQL(responseSummarySQL); + + executeSQL(getCommonUpdateSQL(TABLE_API_DESTINATION_SUMMARY)); + executeSQL(getCommonUpdateSQL(TABLE_API_FAULT_SUMMARY)); + executeSQL(getCommonUpdateSQL(TABLE_API_REQUEST_SUMMARY)); + executeSQL(getCommonUpdateSQL(TABLE_API_RESOURCE_USAGE_SUMMARY)); + executeSQL(getCommonUpdateSQL(TABLE_API_VERSION_USAGE_SUMMARY)); + } + + private static String getCommonUpdateSQL(String table) { + return "UPDATE " + table + " SET CONTEXT = concat(CONTEXT,'/',VERSION) " + + "WHERE CONTEXT NOT LIKE concat('%', VERSION)"; + } + + + private static void executeSQL(String sql) { + Connection connection = null; + Statement statement = null; + try { + connection = dataSource.getConnection(); + statement = connection.createStatement(); + connection.setAutoCommit(false); + statement.execute(sql); + connection.commit(); + + } catch (SQLException e) { + log.error("SQLException when executing: " + sql, e); + } + finally { + try { + if (statement != null) { statement.close(); } + if (connection != null) { connection.close(); } + } catch (SQLException e) { + log.error("SQLException when closing resource", e); + } + + } + } +} diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/constraint/query.sql b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/constraint/drop-fk.sql similarity index 100% rename from modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/constraint/query.sql rename to modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/constraint/drop-fk.sql diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/h2.sql b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/h2.sql index ae07a78757..715dc21948 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/h2.sql +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/h2.sql @@ -5,3 +5,28 @@ ALTER TABLE IDN_OAUTH1A_ACCESS_TOKEN ALTER COLUMN SCOPE VARCHAR(767); ALTER TABLE IDN_OAUTH2_AUTHORIZATION_CODE ALTER COLUMN SCOPE VARCHAR(767); ALTER TABLE IDN_OAUTH2_ACCESS_TOKEN ALTER COLUMN TOKEN_SCOPE VARCHAR(767); ALTER TABLE AM_SUBSCRIBER ALTER COLUMN USER_ID VARCHAR(255); +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD CREATE_MODE VARCHAR(30) DEFAULT 'CREATED'; +ALTER TABLE AM_APPLICATION_REGISTRATION ADD TOKEN_SCOPE VARCHAR(256) DEFAULT 'default'; +ALTER TABLE AM_APPLICATION_REGISTRATION ADD INPUTS VARCHAR(256); +ALTER TABLE AM_APPLICATION ADD GROUP_ID VARCHAR(100); +ALTER TABLE AM_API ADD CONTEXT_TEMPLATE VARCHAR(256); +UPDATE AM_API SET CONTEXT_TEMPLATE = CONTEXT WHERE CONTEXT_TEMPLATE IS NULL; +UPDATE AM_API SET CONTEXT = concat(CONTEXT,concat('/',API_VERSION)) WHERE CONTEXT NOT LIKE concat('%', API_VERSION); +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET TOKEN_SCOPE = concat(TOKEN_SCOPE, concat(' ', 'am_application_scope')) WHERE USER_TYPE = 'APPLICATION' AND TOKEN_SCOPE NOT LIKE '%am_application_scope%'; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET VALIDITY_PERIOD = -2000 WHERE VALIDITY_PERIOD = 9223372036854775807; +ALTER TABLE AM_API ADD CREATED_BY VARCHAR(100); +ALTER TABLE AM_API ADD CREATED_TIME TIMESTAMP; +ALTER TABLE AM_API ADD UPDATED_BY VARCHAR(100); +ALTER TABLE AM_API ADD UPDATED_TIME TIMESTAMP; +ALTER TABLE AM_SUBSCRIBER ADD CREATED_BY VARCHAR(100); +ALTER TABLE AM_SUBSCRIBER ADD CREATED_TIME TIMESTAMP; +ALTER TABLE AM_SUBSCRIBER ADD UPDATED_BY VARCHAR(100); +ALTER TABLE AM_SUBSCRIBER ADD UPDATED_TIME TIMESTAMP; +ALTER TABLE AM_SUBSCRIPTION ADD CREATED_BY VARCHAR(100); +ALTER TABLE AM_SUBSCRIPTION ADD CREATED_TIME TIMESTAMP; +ALTER TABLE AM_SUBSCRIPTION ADD UPDATED_BY VARCHAR(100); +ALTER TABLE AM_SUBSCRIPTION ADD UPDATED_TIME TIMESTAMP; +ALTER TABLE AM_APPLICATION ADD CREATED_BY VARCHAR(100); +ALTER TABLE AM_APPLICATION ADD CREATED_TIME TIMESTAMP; +ALTER TABLE AM_APPLICATION ADD UPDATED_BY VARCHAR(100); +ALTER TABLE AM_APPLICATION ADD UPDATED_TIME TIMESTAMP; diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mssql.sql b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mssql.sql index bfbeb01f83..ff4a631f0f 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mssql.sql +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mssql.sql @@ -1,11 +1,15 @@ +ALTER TABLE AM_SUBSCRIBER ALTER COLUMN USER_ID VARCHAR(255); +ALTER TABLE AM_APPLICATION ADD GROUP_ID VARCHAR(100); +ALTER TABLE AM_API ADD CONTEXT_TEMPLATE VARCHAR(256); ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD CREATE_MODE VARCHAR(30) DEFAULT 'CREATED'; -ALTER TABLE AM_API_LC_EVENT ALTER COLUMN USER_ID VARCHAR(255) NOT NULL; ALTER TABLE AM_APPLICATION_REGISTRATION ADD TOKEN_SCOPE VARCHAR(256) DEFAULT 'default'; ALTER TABLE AM_APPLICATION_REGISTRATION ADD INPUTS VARCHAR(256); -ALTER TABLE AM_APPLICATION ADD GROUP_ID VARCHAR(100); -ALTER TABLE AM_APPLICATION ALTER COLUMN NAME VARCHAR(100); -ALTER TABLE IDN_OAUTH1A_REQUEST_TOKEN ALTER COLUMN SCOPE VARCHAR(767); -ALTER TABLE IDN_OAUTH1A_ACCESS_TOKEN ALTER COLUMN SCOPE VARCHAR(767); -ALTER TABLE IDN_OAUTH2_AUTHORIZATION_CODE ALTER COLUMN SCOPE VARCHAR(767); -ALTER TABLE IDN_OAUTH2_ACCESS_TOKEN ALTER COLUMN TOKEN_SCOPE VARCHAR(767); -ALTER TABLE AM_SUBSCRIBER ALTER COLUMN USER_ID VARCHAR(255); +ALTER TABLE AM_API_LC_EVENT ALTER COLUMN USER_ID VARCHAR(255) NOT NULL; +UPDATE AM_API SET CONTEXT_TEMPLATE = CONTEXT WHERE CONTEXT_TEMPLATE IS NULL; +UPDATE AM_API SET CONTEXT = CONTEXT + '/' + API_VERSION WHERE CONTEXT NOT LIKE '%' + API_VERSION; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET TOKEN_SCOPE = TOKEN_SCOPE + ' ' + 'am_application_scope' WHERE USER_TYPE = 'APPLICATION' AND TOKEN_SCOPE NOT LIKE '%am_application_scope%'; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET VALIDITY_PERIOD = -2000 WHERE VALIDITY_PERIOD = 9223372036854775807; +ALTER TABLE AM_API ADD CREATED_BY VARCHAR(100), CREATED_TIME DATETIME, UPDATED_BY VARCHAR(100), UPDATED_TIME DATETIME; +ALTER TABLE AM_SUBSCRIBER ADD CREATED_BY VARCHAR(100), CREATED_TIME DATETIME, UPDATED_BY VARCHAR(100), UPDATED_TIME DATETIME; +ALTER TABLE AM_SUBSCRIPTION ADD CREATED_BY VARCHAR(100), CREATED_TIME DATETIME, UPDATED_BY VARCHAR(100), UPDATED_TIME DATETIME; +ALTER TABLE AM_APPLICATION ADD CREATED_BY VARCHAR(100), CREATED_TIME DATETIME, UPDATED_BY VARCHAR(100), UPDATED_TIME DATETIME; diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mysql.sql b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mysql.sql index 1289cfdbd3..c40ed2fc35 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mysql.sql +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/mysql.sql @@ -9,3 +9,12 @@ ALTER TABLE IDN_OAUTH1A_ACCESS_TOKEN MODIFY COLUMN SCOPE VARCHAR(767); ALTER TABLE IDN_OAUTH2_AUTHORIZATION_CODE MODIFY COLUMN SCOPE VARCHAR(767); ALTER TABLE IDN_OAUTH2_ACCESS_TOKEN MODIFY COLUMN TOKEN_SCOPE VARCHAR(767); ALTER TABLE AM_SUBSCRIBER MODIFY COLUMN USER_ID VARCHAR(255); +ALTER TABLE AM_API ADD CONTEXT_TEMPLATE VARCHAR(256); +UPDATE AM_API SET CONTEXT_TEMPLATE = CONTEXT WHERE CONTEXT_TEMPLATE IS NULL; +UPDATE AM_API SET CONTEXT = concat(CONTEXT,concat('/',API_VERSION)) WHERE CONTEXT NOT LIKE concat('%', API_VERSION); +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET TOKEN_SCOPE = concat(TOKEN_SCOPE, concat(' ', 'am_application_scope')) WHERE USER_TYPE = 'APPLICATION' AND TOKEN_SCOPE NOT LIKE '%am_application_scope%'; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET VALIDITY_PERIOD = -2000 WHERE VALIDITY_PERIOD = 9223372036854775807; +ALTER TABLE AM_API ADD (CREATED_BY VARCHAR(100), CREATED_TIME TIMESTAMP, UPDATED_BY VARCHAR(100), UPDATED_TIME TIMESTAMP); +ALTER TABLE AM_SUBSCRIBER ADD (CREATED_BY VARCHAR(100), CREATED_TIME TIMESTAMP, UPDATED_BY VARCHAR(100), UPDATED_TIME TIMESTAMP); +ALTER TABLE AM_SUBSCRIPTION ADD (CREATED_BY VARCHAR(100), CREATED_TIME TIMESTAMP, UPDATED_BY VARCHAR(100), UPDATED_TIME TIMESTAMP); +ALTER TABLE AM_APPLICATION ADD (CREATED_BY VARCHAR(100), CREATED_TIME TIMESTAMP, UPDATED_BY VARCHAR(100), UPDATED_TIME TIMESTAMP); diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/oracle.sql b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/oracle.sql index e16ad449ae..a02d48f1a4 100644 --- a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/oracle.sql +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/oracle.sql @@ -1,11 +1,16 @@ -ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD CREATE_MODE VARCHAR(30) DEFAULT 'CREATED'; -ALTER TABLE AM_API_LC_EVENT MODIFY COLUMN USER_ID VARCHAR(255) NOT NULL; -ALTER TABLE AM_APPLICATION_REGISTRATION ADD TOKEN_SCOPE VARCHAR(256) DEFAULT 'default'; -ALTER TABLE AM_APPLICATION_REGISTRATION ADD INPUTS VARCHAR(256); -ALTER TABLE AM_APPLICATION ADD COLUMN GROUP_ID VARCHAR(100); -ALTER TABLE AM_APPLICATION MODIFY COLUMN NAME VARCHAR(100); -ALTER TABLE IDN_OAUTH1A_REQUEST_TOKEN MODIFY COLUMN SCOPE VARCHAR(767); -ALTER TABLE IDN_OAUTH1A_ACCESS_TOKEN MODIFY COLUMN SCOPE VARCHAR(767); -ALTER TABLE IDN_OAUTH2_AUTHORIZATION_CODE MODIFY COLUMN SCOPE VARCHAR(767); -ALTER TABLE IDN_OAUTH2_ACCESS_TOKEN MODIFY COLUMN TOKEN_SCOPE VARCHAR(767); -ALTER TABLE AM_SUBSCRIBER MODIFY COLUMN USER_ID VARCHAR(255); +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD CREATE_MODE VARCHAR2(30) DEFAULT 'CREATED'; +ALTER TABLE AM_API_LC_EVENT MODIFY USER_ID VARCHAR2(255); +ALTER TABLE AM_APPLICATION_REGISTRATION ADD TOKEN_SCOPE VARCHAR2(256) DEFAULT 'default'; +ALTER TABLE AM_APPLICATION_REGISTRATION ADD INPUTS VARCHAR2(256); +ALTER TABLE AM_APPLICATION ADD GROUP_ID VARCHAR2(100); +ALTER TABLE AM_APPLICATION MODIFY NAME VARCHAR2(100); +ALTER TABLE AM_SUBSCRIBER MODIFY USER_ID VARCHAR2(255); +ALTER TABLE AM_API ADD CONTEXT_TEMPLATE VARCHAR2(256); +UPDATE AM_API SET CONTEXT_TEMPLATE = CONTEXT WHERE CONTEXT_TEMPLATE IS NULL; +UPDATE AM_API SET CONTEXT = concat(CONTEXT,concat('/',API_VERSION)) WHERE CONTEXT NOT LIKE concat('%', API_VERSION); +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET TOKEN_SCOPE = concat(TOKEN_SCOPE, concat(' ', 'am_application_scope')) WHERE USER_TYPE = 'APPLICATION' AND TOKEN_SCOPE NOT LIKE '%am_application_scope%'; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET VALIDITY_PERIOD = -2000 WHERE VALIDITY_PERIOD = 9223372036854775807; +ALTER TABLE AM_API ADD (CREATED_BY VARCHAR2(100), CREATED_TIME DATE, UPDATED_BY VARCHAR2(100), UPDATED_TIME DATE); +ALTER TABLE AM_SUBSCRIBER ADD (CREATED_BY VARCHAR2(100), CREATED_TIME DATE, UPDATED_BY VARCHAR2(100), UPDATED_TIME DATE); +ALTER TABLE AM_SUBSCRIPTION ADD (CREATED_BY VARCHAR2(100), CREATED_TIME DATE, UPDATED_BY VARCHAR2(100), UPDATED_TIME DATE); +ALTER TABLE AM_APPLICATION ADD (CREATED_BY VARCHAR2(100), CREATED_TIME DATE, UPDATED_BY VARCHAR2(100), UPDATED_TIME DATE); diff --git a/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/postgresql.sql b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/postgresql.sql new file mode 100644 index 0000000000..e1456b5613 --- /dev/null +++ b/modules/distribution/resources/migration-1.8.0_to_1.9.0/wso2-api-migration-client/src/main/resources/18to19Migration/sql-scripts/postgresql.sql @@ -0,0 +1,16 @@ +ALTER TABLE AM_SUBSCRIBER ALTER COLUMN USER_ID TYPE VARCHAR(255); +ALTER TABLE AM_APPLICATION ADD COLUMN GROUP_ID VARCHAR(100); +ALTER TABLE AM_API ADD COLUMN CONTEXT_TEMPLATE VARCHAR(256); +ALTER TABLE AM_APPLICATION_KEY_MAPPING ADD COLUMN CREATE_MODE VARCHAR(30) DEFAULT 'CREATED'; +ALTER TABLE AM_APPLICATION_REGISTRATION ADD COLUMN TOKEN_SCOPE VARCHAR(256) DEFAULT 'default'; +ALTER TABLE AM_APPLICATION_REGISTRATION ADD COLUMN INPUTS VARCHAR(256); +ALTER TABLE AM_API_LC_EVENT ALTER COLUMN USER_ID TYPE VARCHAR(255); +ALTER TABLE AM_API_LC_EVENT ALTER COLUMN USER_ID SET NOT NULL; +UPDATE AM_API SET CONTEXT_TEMPLATE = CONTEXT WHERE CONTEXT_TEMPLATE IS NULL; +UPDATE AM_API SET CONTEXT = CONTEXT || '/' || API_VERSION WHERE CONTEXT NOT LIKE '%' || API_VERSION; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET TOKEN_SCOPE = TOKEN_SCOPE || ' ' || 'am_application_scope' WHERE USER_TYPE = 'APPLICATION' AND TOKEN_SCOPE NOT LIKE '%am_application_scope%'; +UPDATE IDN_OAUTH2_ACCESS_TOKEN SET VALIDITY_PERIOD = -2000 WHERE VALIDITY_PERIOD = 9223372036854775807; +ALTER TABLE AM_API ADD CREATED_BY VARCHAR(100), ADD CREATED_TIME DATE, ADD UPDATED_BY VARCHAR(100), ADD UPDATED_TIME DATE; +ALTER TABLE AM_SUBSCRIBER ADD CREATED_BY VARCHAR(100), ADD CREATED_TIME DATE, ADD UPDATED_BY VARCHAR(100), ADD UPDATED_TIME DATE; +ALTER TABLE AM_SUBSCRIPTION ADD CREATED_BY VARCHAR(100), ADD CREATED_TIME DATE, ADD UPDATED_BY VARCHAR(100), ADD UPDATED_TIME DATE; +ALTER TABLE AM_APPLICATION ADD CREATED_BY VARCHAR(100), ADD CREATED_TIME DATE, ADD UPDATED_BY VARCHAR(100), ADD UPDATED_TIME DATE; \ No newline at end of file diff --git a/modules/distribution/resources/sql/mysql_cluster.sql b/modules/distribution/resources/sql/mysql_cluster.sql new file mode 100644 index 0000000000..89376537c3 --- /dev/null +++ b/modules/distribution/resources/sql/mysql_cluster.sql @@ -0,0 +1,637 @@ +-- Start of IDN Tables -- +CREATE TABLE IDN_BASE_TABLE ( + PRODUCT_NAME VARCHAR(20), + PRIMARY KEY (PRODUCT_NAME) +)ENGINE NDB; + +INSERT INTO IDN_BASE_TABLE values ('WSO2 Identity Server'); + +CREATE TABLE IF NOT EXISTS IDN_OAUTH_CONSUMER_APPS ( + CONSUMER_KEY VARCHAR(255), + CONSUMER_SECRET VARCHAR(512), + USERNAME VARCHAR(255), + TENANT_ID INTEGER DEFAULT 0, + APP_NAME VARCHAR(255), + OAUTH_VERSION VARCHAR(128), + CALLBACK_URL VARCHAR(1024), + GRANT_TYPES VARCHAR (1024), + PRIMARY KEY (CONSUMER_KEY) +)ENGINE NDB; + +CREATE TABLE IDN_OAUTH1A_REQUEST_TOKEN ( + REQUEST_TOKEN VARCHAR(255), + REQUEST_TOKEN_SECRET VARCHAR(512), + CONSUMER_KEY VARCHAR(255), + CALLBACK_URL VARCHAR(1024), + SCOPE VARCHAR(767), + AUTHORIZED VARCHAR(128), + OAUTH_VERIFIER VARCHAR(512), + AUTHZ_USER VARCHAR(512), + PRIMARY KEY (REQUEST_TOKEN), + FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(CONSUMER_KEY) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IDN_OAUTH1A_ACCESS_TOKEN ( + ACCESS_TOKEN VARCHAR(255), + ACCESS_TOKEN_SECRET VARCHAR(512), + CONSUMER_KEY VARCHAR(255), + SCOPE VARCHAR(767), + AUTHZ_USER VARCHAR(512), + PRIMARY KEY (ACCESS_TOKEN), + FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(CONSUMER_KEY) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IDN_OAUTH2_AUTHORIZATION_CODE ( + AUTHORIZATION_CODE VARCHAR(255), + CONSUMER_KEY VARCHAR(255), + CALLBACK_URL VARCHAR(1024), + SCOPE VARCHAR(767), + AUTHZ_USER VARCHAR(512), + TIME_CREATED TIMESTAMP, + VALIDITY_PERIOD BIGINT, + PRIMARY KEY (AUTHORIZATION_CODE), + FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(CONSUMER_KEY) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IDN_OAUTH2_ACCESS_TOKEN ( + ACCESS_TOKEN VARCHAR(255), + REFRESH_TOKEN VARCHAR(255), + CONSUMER_KEY VARCHAR(255), + AUTHZ_USER VARCHAR(100), + USER_TYPE VARCHAR (25), + TIME_CREATED TIMESTAMP DEFAULT 0, + VALIDITY_PERIOD BIGINT, + TOKEN_SCOPE VARCHAR(767), + TOKEN_STATE VARCHAR(25) DEFAULT 'ACTIVE', + TOKEN_STATE_ID VARCHAR (255) DEFAULT 'NONE', + PRIMARY KEY (ACCESS_TOKEN), + FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(CONSUMER_KEY) ON DELETE CASCADE, + CONSTRAINT CON_APP_KEY UNIQUE (CONSUMER_KEY, AUTHZ_USER,USER_TYPE,TOKEN_STATE,TOKEN_STATE_ID,TOKEN_SCOPE) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_SCOPE ( + SCOPE_ID INT(11) NOT NULL AUTO_INCREMENT, + SCOPE_KEY VARCHAR(100) NOT NULL, + NAME VARCHAR(255) NULL, + DESCRIPTION VARCHAR(512) NULL, + TENANT_ID INT(11) NOT NULL DEFAULT 0, + ROLES VARCHAR (500) NULL, + PRIMARY KEY (SCOPE_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDN_OAUTH2_RESOURCE_SCOPE ( + RESOURCE_PATH VARCHAR(255) NOT NULL, + SCOPE_ID INTEGER (11) NOT NULL, + PRIMARY KEY (RESOURCE_PATH), + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IDN_SCIM_GROUP ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + ROLE_NAME VARCHAR(255) NOT NULL, + ATTR_NAME VARCHAR(1024) NOT NULL, + ATTR_VALUE VARCHAR(1024), + PRIMARY KEY (ID) +)ENGINE NDB; + +CREATE TABLE IDN_SCIM_PROVIDER ( + CONSUMER_ID VARCHAR(255) NOT NULL, + PROVIDER_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + USER_PASSWORD VARCHAR(255) NOT NULL, + USER_URL VARCHAR(1024) NOT NULL, + GROUP_URL VARCHAR(1024), + BULK_URL VARCHAR(1024), + PRIMARY KEY (CONSUMER_ID,PROVIDER_ID) +)ENGINE NDB; + +CREATE TABLE IDN_OPENID_REMEMBER_ME ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + COOKIE_VALUE VARCHAR(1024), + CREATED_TIME TIMESTAMP, + PRIMARY KEY (USER_NAME, TENANT_ID) +)ENGINE NDB; + +CREATE TABLE IDN_OPENID_USER_RPS ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + RP_URL VARCHAR(255) NOT NULL, + TRUSTED_ALWAYS VARCHAR(128) DEFAULT 'FALSE', + LAST_VISIT DATE NOT NULL, + VISIT_COUNT INTEGER DEFAULT 0, + DEFAULT_PROFILE_NAME VARCHAR(255) DEFAULT 'DEFAULT', + PRIMARY KEY (USER_NAME, TENANT_ID, RP_URL) +)ENGINE NDB; + +CREATE TABLE IDN_OPENID_ASSOCIATIONS ( + HANDLE VARCHAR(255) NOT NULL, + ASSOC_TYPE VARCHAR(255) NOT NULL, + EXPIRE_IN TIMESTAMP NOT NULL, + MAC_KEY VARCHAR(255) NOT NULL, + ASSOC_STORE VARCHAR(128) DEFAULT 'SHARED', + PRIMARY KEY (HANDLE) +)ENGINE NDB; + +CREATE TABLE IDN_STS_STORE ( + ID INTEGER AUTO_INCREMENT, + TOKEN_ID VARCHAR(255) NOT NULL, + TOKEN_CONTENT BLOB(1024) NOT NULL, + CREATE_DATE TIMESTAMP NOT NULL, + EXPIRE_DATE TIMESTAMP NOT NULL, + STATE INTEGER DEFAULT 0, + PRIMARY KEY (ID) +)ENGINE NDB; + +CREATE TABLE IDN_IDENTITY_USER_DATA ( + TENANT_ID INTEGER DEFAULT -1234, + USER_NAME VARCHAR(255) NOT NULL, + DATA_KEY VARCHAR(255) NOT NULL, + DATA_VALUE VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, DATA_KEY) +)ENGINE NDB; + +CREATE TABLE IDN_IDENTITY_META_DATA ( + USER_NAME VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + METADATA_TYPE VARCHAR(255) NOT NULL, + METADATA VARCHAR(255) NOT NULL, + VALID VARCHAR(255) NOT NULL, + PRIMARY KEY (TENANT_ID, USER_NAME, METADATA_TYPE,METADATA) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDN_THRIFT_SESSION ( + SESSION_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + CREATED_TIME VARCHAR(255) NOT NULL, + LAST_MODIFIED_TIME VARCHAR(255) NOT NULL, + PRIMARY KEY (SESSION_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDN_ASSOCIATED_ID ( + ID INTEGER AUTO_INCREMENT, + IDP_USER_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER DEFAULT -1234, + IDP_ID VARCHAR(255) NOT NULL, + USER_NAME VARCHAR(255) NOT NULL, + PRIMARY KEY (ID), + UNIQUE(IDP_USER_ID, TENANT_ID, IDP_ID) +)ENGINE NDB; + +-- End of IDN Tables -- + + +-- Start of IDN-APPLICATION-MGT Tables-- + +CREATE TABLE IF NOT EXISTS SP_APP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + APP_NAME VARCHAR (255) NOT NULL , + USER_STORE VARCHAR (255) NOT NULL, + USERNAME VARCHAR (255) NOT NULL , + DESCRIPTION VARCHAR (1024), + ROLE_CLAIM VARCHAR (512), + AUTH_TYPE VARCHAR (255) NOT NULL, + PROVISIONING_USERSTORE_DOMAIN VARCHAR (512), + IS_LOCAL_CLAIM_DIALECT CHAR(1) DEFAULT '1', + IS_SEND_LOCAL_SUBJECT_ID CHAR(1) DEFAULT '0', + IS_SEND_AUTH_LIST_OF_IDPS CHAR(1) DEFAULT '0', + SUBJECT_CLAIM_URI VARCHAR (512), + IS_SAAS_APP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_APP ADD CONSTRAINT APPLICATION_NAME_CONSTRAINT UNIQUE(APP_NAME, TENANT_ID); + +CREATE TABLE IF NOT EXISTS SP_INBOUND_AUTH ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + INBOUND_AUTH_KEY VARCHAR (255) NOT NULL, + INBOUND_AUTH_TYPE VARCHAR (255) NOT NULL, + PROP_NAME VARCHAR (255), + PROP_VALUE VARCHAR (1024) , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_INBOUND_AUTH ADD CONSTRAINT APPLICATION_ID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_AUTH_STEP ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + STEP_ORDER INTEGER DEFAULT 1, + APP_ID INTEGER NOT NULL , + IS_SUBJECT_STEP CHAR(1) DEFAULT '0', + IS_ATTRIBUTE_STEP CHAR(1) DEFAULT '0', + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_AUTH_STEP ADD CONSTRAINT APPLICATION_ID_CONSTRAINT_STEP FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_FEDERATED_IDP ( + ID INTEGER NOT NULL, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_ID INTEGER NOT NULL, + PRIMARY KEY (ID, AUTHENTICATOR_ID) +)ENGINE NDB; + +ALTER TABLE SP_FEDERATED_IDP ADD CONSTRAINT STEP_ID_CONSTRAINT FOREIGN KEY (ID) REFERENCES SP_AUTH_STEP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_CLAIM_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_CLAIM VARCHAR (512) NOT NULL , + SP_CLAIM VARCHAR (512) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_REQUESTED VARCHAR(128) DEFAULT '0', + DEFAULT_VALUE VARCHAR(255), + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_CLAIM_MAPPING ADD CONSTRAINT CLAIMID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_ROLE_MAPPING ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_ROLE VARCHAR (255) NOT NULL , + SP_ROLE VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_ROLE_MAPPING ADD CONSTRAINT ROLEID_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_REQ_PATH_AUTHENTICATOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + AUTHENTICATOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_REQ_PATH_AUTHENTICATOR ADD CONSTRAINT REQ_AUTH_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS SP_PROVISIONING_CONNECTOR ( + ID INTEGER NOT NULL AUTO_INCREMENT, + TENANT_ID INTEGER NOT NULL, + IDP_NAME VARCHAR (255) NOT NULL , + CONNECTOR_NAME VARCHAR (255) NOT NULL , + APP_ID INTEGER NOT NULL, + IS_JIT_ENABLED CHAR(1) NOT NULL DEFAULT '0', + BLOCKING CHAR(1) NOT NULL DEFAULT '0', + PRIMARY KEY (ID) +)ENGINE NDB; + +ALTER TABLE SP_PROVISIONING_CONNECTOR ADD CONSTRAINT PRO_CONNECTOR_APPID_CONSTRAINT FOREIGN KEY (APP_ID) REFERENCES SP_APP (ID) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS IDP ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + NAME VARCHAR(254) NOT NULL, + IS_ENABLED CHAR(1) NOT NULL DEFAULT '1', + IS_PRIMARY CHAR(1) NOT NULL DEFAULT '0', + HOME_REALM_ID VARCHAR(254), + IMAGE MEDIUMBLOB, + CERTIFICATE BLOB, + ALIAS VARCHAR(254), + INBOUND_PROV_ENABLED CHAR (1) NOT NULL DEFAULT '0', + INBOUND_PROV_USER_STORE_ID VARCHAR(254), + USER_CLAIM_URI VARCHAR(254), + ROLE_CLAIM_URI VARCHAR(254), + DESCRIPTION VARCHAR (1024), + DEFAULT_AUTHENTICATOR_NAME VARCHAR(254), + DEFAULT_PRO_CONNECTOR_NAME VARCHAR(254), + PROVISIONING_ROLE VARCHAR(128), + IS_FEDERATION_HUB CHAR(1) NOT NULL DEFAULT '0', + IS_LOCAL_CLAIM_DIALECT CHAR(1) NOT NULL DEFAULT '0', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, NAME) +)ENGINE NDB; + +INSERT INTO IDP (TENANT_ID, NAME, HOME_REALM_ID) VALUES (-1234, 'LOCAL', 'localhost'); + +CREATE TABLE IF NOT EXISTS IDP_ROLE ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + ROLE VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, ROLE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_ROLE_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_ROLE_ID INTEGER, + TENANT_ID INTEGER, + USER_STORE_ID VARCHAR (253), + LOCAL_ROLE VARCHAR(253), + PRIMARY KEY (ID), + UNIQUE (IDP_ROLE_ID, TENANT_ID, USER_STORE_ID, LOCAL_ROLE), + FOREIGN KEY (IDP_ROLE_ID) REFERENCES IDP_ROLE(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_CLAIM ( + ID INTEGER AUTO_INCREMENT, + IDP_ID INTEGER, + TENANT_ID INTEGER, + CLAIM VARCHAR(254), + PRIMARY KEY (ID), + UNIQUE (IDP_ID, CLAIM), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_CLAIM_MAPPING ( + ID INTEGER AUTO_INCREMENT, + IDP_CLAIM_ID INTEGER, + TENANT_ID INTEGER, + LOCAL_CLAIM VARCHAR(253), + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (IDP_CLAIM_ID, TENANT_ID, LOCAL_CLAIM), + FOREIGN KEY (IDP_CLAIM_ID) REFERENCES IDP_CLAIM(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + NAME VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '1', + DISPLAY_NAME VARCHAR(255), + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, NAME), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE NDB; + +INSERT INTO IDP_AUTHENTICATOR (TENANT_ID, IDP_ID, NAME) VALUES (-1234, 1, 'samlsso'); + +CREATE TABLE IF NOT EXISTS IDP_AUTHENTICATOR_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + AUTHENTICATOR_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2047), + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, AUTHENTICATOR_ID, PROPERTY_KEY), + FOREIGN KEY (AUTHENTICATOR_ID) REFERENCES IDP_AUTHENTICATOR(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_CONFIG ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + PROVISIONING_CONNECTOR_TYPE VARCHAR(255) NOT NULL, + IS_ENABLED CHAR (1) DEFAULT '0', + IS_BLOCKING CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, PROVISIONING_CONNECTOR_TYPE), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_PROV_CONFIG_PROPERTY ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + PROVISIONING_CONFIG_ID INTEGER, + PROPERTY_KEY VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048), + PROPERTY_BLOB_VALUE BLOB, + PROPERTY_TYPE CHAR(32) NOT NULL, + IS_SECRET CHAR (1) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, PROVISIONING_CONFIG_ID, PROPERTY_KEY), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_PROVISIONING_ENTITY ( + ID INTEGER AUTO_INCREMENT, + PROVISIONING_CONFIG_ID INTEGER, + ENTITY_TYPE VARCHAR(255) NOT NULL, + ENTITY_LOCAL_USERSTORE VARCHAR(255) NOT NULL, + ENTITY_NAME VARCHAR(255) NOT NULL, + ENTITY_VALUE VARCHAR(255), + TENANT_ID INTEGER, + PRIMARY KEY (ID), + UNIQUE (ENTITY_TYPE, TENANT_ID, ENTITY_LOCAL_USERSTORE, ENTITY_NAME), + UNIQUE (PROVISIONING_CONFIG_ID, ENTITY_TYPE, ENTITY_VALUE), + FOREIGN KEY (PROVISIONING_CONFIG_ID) REFERENCES IDP_PROVISIONING_CONFIG(ID) ON DELETE CASCADE +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDP_LOCAL_CLAIM ( + ID INTEGER AUTO_INCREMENT, + TENANT_ID INTEGER, + IDP_ID INTEGER, + CLAIM_URI VARCHAR(255) NOT NULL, + DEFAULT_VALUE VARCHAR(255), + IS_REQUESTED VARCHAR(128) DEFAULT '0', + PRIMARY KEY (ID), + UNIQUE (TENANT_ID, IDP_ID, CLAIM_URI), + FOREIGN KEY (IDP_ID) REFERENCES IDP(ID) ON DELETE CASCADE +)ENGINE NDB; +-- End of IDN-APPLICATION-MGT Tables-- + + +-- Start of API-MGT Tables -- +CREATE TABLE IF NOT EXISTS AM_SUBSCRIBER ( + SUBSCRIBER_ID INTEGER AUTO_INCREMENT, + USER_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + EMAIL_ADDRESS VARCHAR(256) NULL, + DATE_SUBSCRIBED TIMESTAMP NOT NULL, + PRIMARY KEY (SUBSCRIBER_ID), + CREATED_BY VARCHAR(100), + CREATED_TIME TIMESTAMP, + UPDATED_BY VARCHAR(100), + UPDATED_TIME TIMESTAMP, + UNIQUE (TENANT_ID,USER_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_APPLICATION ( + APPLICATION_ID INTEGER AUTO_INCREMENT, + NAME VARCHAR(100), + SUBSCRIBER_ID INTEGER, + APPLICATION_TIER VARCHAR(50) DEFAULT 'Unlimited', + CALLBACK_URL VARCHAR(512), + DESCRIPTION VARCHAR(512), + APPLICATION_STATUS VARCHAR(50) DEFAULT 'APPROVED', + GROUP_ID VARCHAR(100), + CREATED_BY VARCHAR(100), + CREATED_TIME TIMESTAMP, + UPDATED_BY VARCHAR(100), + UPDATED_TIME TIMESTAMP, + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE RESTRICT, + PRIMARY KEY(APPLICATION_ID), + UNIQUE (NAME,SUBSCRIBER_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_API ( + API_ID INTEGER AUTO_INCREMENT, + API_PROVIDER VARCHAR(200), + API_NAME VARCHAR(200), + API_VERSION VARCHAR(30), + CONTEXT VARCHAR(256), + CONTEXT_TEMPLATE VARCHAR(256), + CREATED_BY VARCHAR(100), + CREATED_TIME TIMESTAMP, + UPDATED_BY VARCHAR(100), + UPDATED_TIME TIMESTAMP, + PRIMARY KEY(API_ID), + UNIQUE (API_PROVIDER,API_NAME,API_VERSION) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_API_URL_MAPPING ( + URL_MAPPING_ID INTEGER AUTO_INCREMENT, + API_ID INTEGER NOT NULL, + HTTP_METHOD VARCHAR(20) NULL, + AUTH_SCHEME VARCHAR(50) NULL, + URL_PATTERN VARCHAR(512) NULL, + THROTTLING_TIER varchar(512) DEFAULT NULL, + MEDIATION_SCRIPT BLOB, + PRIMARY KEY (URL_MAPPING_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_SUBSCRIPTION ( + SUBSCRIPTION_ID INTEGER AUTO_INCREMENT, + TIER_ID VARCHAR(50), + API_ID INTEGER, + LAST_ACCESSED TIMESTAMP NULL, + APPLICATION_ID INTEGER, + SUB_STATUS VARCHAR(50), + SUBS_CREATE_STATE VARCHAR(50) DEFAULT 'SUBSCRIBE', + CREATED_BY VARCHAR(100), + CREATED_TIME TIMESTAMP, + UPDATED_BY VARCHAR(100), + UPDATED_TIME TIMESTAMP, + FOREIGN KEY(APPLICATION_ID) REFERENCES AM_APPLICATION(APPLICATION_ID) ON DELETE RESTRICT, + FOREIGN KEY(API_ID) REFERENCES AM_API(API_ID) ON DELETE RESTRICT, + PRIMARY KEY (SUBSCRIPTION_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_SUBSCRIPTION_KEY_MAPPING ( + SUBSCRIPTION_ID INTEGER, + ACCESS_TOKEN VARCHAR(255), + KEY_TYPE VARCHAR(512) NOT NULL, + FOREIGN KEY(SUBSCRIPTION_ID) REFERENCES AM_SUBSCRIPTION(SUBSCRIPTION_ID) ON DELETE RESTRICT, + PRIMARY KEY(SUBSCRIPTION_ID,ACCESS_TOKEN) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_APPLICATION_KEY_MAPPING ( + APPLICATION_ID INTEGER, + CONSUMER_KEY VARCHAR(255), + KEY_TYPE VARCHAR(512) NOT NULL, + STATE VARCHAR(30) NOT NULL, + CREATE_MODE VARCHAR(30) DEFAULT 'CREATED', + FOREIGN KEY(APPLICATION_ID) REFERENCES AM_APPLICATION(APPLICATION_ID) ON DELETE RESTRICT, + PRIMARY KEY(APPLICATION_ID,KEY_TYPE) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_API_LC_EVENT ( + EVENT_ID INTEGER AUTO_INCREMENT, + API_ID INTEGER NOT NULL, + PREVIOUS_STATE VARCHAR(50), + NEW_STATE VARCHAR(50) NOT NULL, + USER_ID VARCHAR(255) NOT NULL, + TENANT_ID INTEGER NOT NULL, + EVENT_DATE TIMESTAMP NOT NULL, + FOREIGN KEY(API_ID) REFERENCES AM_API(API_ID) ON DELETE RESTRICT, + PRIMARY KEY (EVENT_ID) +)ENGINE NDB; + +CREATE TABLE AM_APP_KEY_DOMAIN_MAPPING ( + CONSUMER_KEY VARCHAR(255), + AUTHZ_DOMAIN VARCHAR(255) DEFAULT 'ALL', + PRIMARY KEY (CONSUMER_KEY,AUTHZ_DOMAIN), + FOREIGN KEY (CONSUMER_KEY) REFERENCES IDN_OAUTH_CONSUMER_APPS(CONSUMER_KEY) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_API_COMMENTS ( + COMMENT_ID INTEGER AUTO_INCREMENT, + COMMENT_TEXT VARCHAR(512), + COMMENTED_USER VARCHAR(255), + DATE_COMMENTED TIMESTAMP NOT NULL, + API_ID INTEGER NOT NULL, + PRIMARY KEY (COMMENT_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_API_RATINGS ( + RATING_ID INTEGER AUTO_INCREMENT, + API_ID INTEGER, + RATING INTEGER, + SUBSCRIBER_ID INTEGER, + FOREIGN KEY(API_ID) REFERENCES AM_API(API_ID) ON DELETE RESTRICT, + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE RESTRICT, +PRIMARY KEY (RATING_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_TIER_PERMISSIONS ( + TIER_PERMISSIONS_ID INTEGER AUTO_INCREMENT, + TIER VARCHAR(50) NOT NULL, + PERMISSIONS_TYPE VARCHAR(50) NOT NULL, + ROLES VARCHAR(512) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY(TIER_PERMISSIONS_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_EXTERNAL_STORES ( + APISTORE_ID INTEGER AUTO_INCREMENT, + API_ID INTEGER, + STORE_ID VARCHAR(255) NOT NULL, + STORE_DISPLAY_NAME VARCHAR(255) NOT NULL, + STORE_ENDPOINT VARCHAR(255) NOT NULL, + STORE_TYPE VARCHAR(255) NOT NULL, +FOREIGN KEY(API_ID) REFERENCES AM_API(API_ID) ON DELETE RESTRICT, +PRIMARY KEY (APISTORE_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_WORKFLOWS( + WF_ID INTEGER AUTO_INCREMENT, + WF_REFERENCE VARCHAR(255) NOT NULL, + WF_TYPE VARCHAR(255) NOT NULL, + WF_STATUS VARCHAR(255) NOT NULL, + WF_CREATED_TIME TIMESTAMP DEFAULT 0, + WF_UPDATED_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , + WF_STATUS_DESC VARCHAR(1000), + TENANT_ID INTEGER, + TENANT_DOMAIN VARCHAR(255), + WF_EXTERNAL_REFERENCE VARCHAR(255) NOT NULL, + PRIMARY KEY (WF_ID), + UNIQUE (WF_EXTERNAL_REFERENCE) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_APPLICATION_REGISTRATION ( + REG_ID INT AUTO_INCREMENT, + SUBSCRIBER_ID INT, + WF_REF VARCHAR(255) NOT NULL, + APP_ID INT, + TOKEN_TYPE VARCHAR(30), + TOKEN_SCOPE VARCHAR(256) DEFAULT 'default', + INPUTS VARCHAR(1000), + ALLOWED_DOMAINS VARCHAR(256), + VALIDITY_PERIOD BIGINT, + UNIQUE (SUBSCRIBER_ID,APP_ID,TOKEN_TYPE), + FOREIGN KEY(SUBSCRIBER_ID) REFERENCES AM_SUBSCRIBER(SUBSCRIBER_ID) ON DELETE RESTRICT, + FOREIGN KEY(APP_ID) REFERENCES AM_APPLICATION(APPLICATION_ID) ON DELETE RESTRICT, + PRIMARY KEY (REG_ID) +)ENGINE NDB; + +CREATE TABLE IF NOT EXISTS AM_API_SCOPES ( + API_ID INTEGER NOT NULL, + SCOPE_ID INTEGER NOT NULL, + FOREIGN KEY (API_ID) REFERENCES AM_API (API_ID) ON DELETE CASCADE, + FOREIGN KEY (SCOPE_ID) REFERENCES IDN_OAUTH2_SCOPE (SCOPE_ID) ON DELETE CASCADE +)ENGINE = NDB; + +CREATE TABLE IF NOT EXISTS AM_API_DEFAULT_VERSION ( + DEFAULT_VERSION_ID INT AUTO_INCREMENT, + API_NAME VARCHAR(256) NOT NULL , + API_PROVIDER VARCHAR(256) NOT NULL , + DEFAULT_API_VERSION VARCHAR(30) , + PUBLISHED_DEFAULT_API_VERSION VARCHAR(30) , + PRIMARY KEY (DEFAULT_VERSION_ID) +); + +CREATE INDEX IDX_SUB_APP_ID ON AM_SUBSCRIPTION (APPLICATION_ID, SUBSCRIPTION_ID); diff --git a/modules/features/service/org.wso2.stratos.apimgt.dashboard.ui.feature/pom.xml b/modules/features/service/org.wso2.stratos.apimgt.dashboard.ui.feature/pom.xml index 339ec907aa..fa72dcb2f0 100644 --- a/modules/features/service/org.wso2.stratos.apimgt.dashboard.ui.feature/pom.xml +++ b/modules/features/service/org.wso2.stratos.apimgt.dashboard.ui.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.am wso2stratos-am-features - 2.2.0 + 2.2.1-SNAPSHOT ../pom.xml @@ -36,12 +36,12 @@ org.wso2.am org.wso2.stratos.apimgt.dashboard.ui - 2.2.0 + ${apimgt.stratos.version} org.wso2.carbon org.wso2.carbon.ui.menu.stratos - ${stratos.version} + 2.2.0 diff --git a/modules/features/service/org.wso2.stratos.apimgt.login.ui.feature/pom.xml b/modules/features/service/org.wso2.stratos.apimgt.login.ui.feature/pom.xml index 4c18f9f019..5d0afa6584 100644 --- a/modules/features/service/org.wso2.stratos.apimgt.login.ui.feature/pom.xml +++ b/modules/features/service/org.wso2.stratos.apimgt.login.ui.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.am wso2stratos-am-features - 2.2.0 + 2.2.1-SNAPSHOT ../pom.xml @@ -36,7 +36,7 @@ org.wso2.am org.wso2.stratos.apimgt.login.ui - 2.2.0 + 2.2.1-SNAPSHOT diff --git a/modules/features/service/org.wso2.stratos.apimgt.styles.feature/pom.xml b/modules/features/service/org.wso2.stratos.apimgt.styles.feature/pom.xml index 573420e8a9..2791a07a5f 100644 --- a/modules/features/service/org.wso2.stratos.apimgt.styles.feature/pom.xml +++ b/modules/features/service/org.wso2.stratos.apimgt.styles.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.am wso2stratos-am-features - 2.2.0 + 2.2.1-SNAPSHOT ../pom.xml diff --git a/modules/features/service/org.wso2.stratos.apimgt.utils.feature/pom.xml b/modules/features/service/org.wso2.stratos.apimgt.utils.feature/pom.xml index 27eca2ea40..7560055140 100644 --- a/modules/features/service/org.wso2.stratos.apimgt.utils.feature/pom.xml +++ b/modules/features/service/org.wso2.stratos.apimgt.utils.feature/pom.xml @@ -22,7 +22,7 @@ org.wso2.am wso2stratos-am-features - 2.2.0 + 2.2.1-SNAPSHOT ../pom.xml diff --git a/modules/features/service/pom.xml b/modules/features/service/pom.xml index be2c972604..f322d4a0a8 100644 --- a/modules/features/service/pom.xml +++ b/modules/features/service/pom.xml @@ -28,7 +28,7 @@ 4.0.0 wso2stratos-am-features - 2.2.0 + 2.2.1-SNAPSHOT pom WSO2 Stratos API Manager - Features Aggregator Module http://wso2.org diff --git a/modules/integration/tests-common/integration-test-utils/pom.xml b/modules/integration/tests-common/integration-test-utils/pom.xml index d8c1b0088b..b62269cad2 100644 --- a/modules/integration/tests-common/integration-test-utils/pom.xml +++ b/modules/integration/tests-common/integration-test-utils/pom.xml @@ -33,7 +33,7 @@ under the License. - org.wso2.carbon + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.api diff --git a/modules/integration/tests-integration/tests-backend/pom.xml b/modules/integration/tests-integration/tests-backend/pom.xml index 25d8783873..3eae07721e 100644 --- a/modules/integration/tests-integration/tests-backend/pom.xml +++ b/modules/integration/tests-integration/tests-backend/pom.xml @@ -271,7 +271,7 @@ under the License. org.wso2.carbon.integration.common.utils - org.wso2.carbon + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.api @@ -288,5 +288,11 @@ under the License. + + com.github.dblock.waffle.wso2 + waffle-jna + 1.6.wso2v2 + test + diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/ChangeEndPointSecurityOfAPITestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/ChangeEndPointSecurityOfAPITestCase.java index ae0a0a5aab..a7e4024ea2 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/ChangeEndPointSecurityOfAPITestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/ChangeEndPointSecurityOfAPITestCase.java @@ -107,6 +107,7 @@ public void testInvokeGETResourceWithSecuredEndPointPasswordOnlyNumbersAndLetter apiCreationRequestBean.setTier(TIER_UNLIMITED); apiCreationRequestBean.setTiersCollection(TIER_UNLIMITED); APIIdentifier apiIdentifier = new APIIdentifier(providerName, API_NAME, API_VERSION_1_0_0); + apiIdentifier.setTier(TIER_UNLIMITED); createPublishAndSubscribeToAPI( apiIdentifier, apiCreationRequestBean, apiPublisherClientUser1, apiStoreClientUser1, APPLICATION_NAME); String accessToken = generateApplicationKeys(apiStoreClientUser1, APPLICATION_NAME).getAccessToken(); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/PluggableVersioningStrategyTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/PluggableVersioningStrategyTestCase.java new file mode 100644 index 0000000000..9a311961e6 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/api/lifecycle/PluggableVersioningStrategyTestCase.java @@ -0,0 +1,131 @@ +/* +* 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.am.integration.tests.api.lifecycle; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; +import org.wso2.am.integration.test.utils.bean.APICreationRequestBean; +import org.wso2.am.integration.test.utils.clients.APIPublisherRestClient; +import org.wso2.am.integration.test.utils.clients.APIStoreRestClient; +import org.wso2.carbon.apimgt.api.model.APIIdentifier; +import org.wso2.carbon.automation.test.utils.http.client.HttpRequestUtil; +import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; +import org.wso2.carbon.logging.view.stub.LogViewerLogViewerException; + +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class PluggableVersioningStrategyTestCase extends APIManagerLifecycleBaseTest { + + private static final Log log = LogFactory.getLog(PluggableVersioningStrategyTestCase.class); + + private static final String API_NAME = "PluggableVersionTestAPI"; + private static final String API_CONTEXT = "{version}/PluggableVersionTestAPI"; + private static final String API_VERSION_1_0_0 = "1.0.0"; + private static final String INVOKABLE_API_CONTEXT = API_VERSION_1_0_0 + "/PluggableVersionTestAPI"; + private static final String API_TAGS = "Pluggable, Version, testTag3"; + private static final String API_DESCRIPTION = "This is test API to test pluggable version strategy"; + private static final String API_END_POINT_POSTFIX_URL = "jaxrs_basic/services/customers/customerservice/"; + private static final String APPLICATION_NAME = "PluggableVersionTestApp"; + private String providerName; + private APIIdentifier apiIdentifier; + private APIPublisherRestClient apiPublisherClientUser; + private APIStoreRestClient apiStoreClientUser; + private APICreationRequestBean apiCreationRequestBean; + private final static String API_GET_ENDPOINT_METHOD = "/customers/123"; + private final static String RESPONSE_GET = "123John"; + + + @BeforeClass(alwaysRun = true) + public void initialize() throws Exception { + super.init(); + String apiEndPointUrl = gatewayUrls.getWebAppURLHttp() + API_END_POINT_POSTFIX_URL; + providerName = publisherContext.getContextTenant().getContextUser().getUserName(); + String publisherURLHttp = publisherUrls.getWebAppURLHttp(); + String storeURLHttp = storeUrls.getWebAppURLHttp(); + apiPublisherClientUser = new APIPublisherRestClient(publisherURLHttp); + apiStoreClientUser = new APIStoreRestClient(storeURLHttp); + //Login to API Publisher with admin + apiPublisherClientUser.login(publisherContext.getContextTenant().getContextUser().getUserName(), + publisherContext.getContextTenant().getContextUser().getPassword()); + //Login to API Store with admin + apiStoreClientUser.login(storeContext.getContextTenant().getContextUser().getUserName(), + storeContext.getContextTenant().getContextUser().getPassword()); + apiIdentifier = new APIIdentifier(providerName, API_NAME, API_VERSION_1_0_0); + + apiCreationRequestBean = new APICreationRequestBean(API_NAME, API_CONTEXT, API_VERSION_1_0_0, providerName, + new URL(apiEndPointUrl)); + apiCreationRequestBean.setTags(API_TAGS); + apiCreationRequestBean.setDescription(API_DESCRIPTION); + apiCreationRequestBean.setTier(TIER_GOLD); + apiCreationRequestBean.setTiersCollection(TIER_GOLD); + } + + @Test(groups = {"wso2.am"}, description = "This test method tests the pluggable versioning stratergy") + public void testPluggableVersioningStratergy() throws APIManagerIntegrationTestException, + IOException, LogViewerLogViewerException { + + //Create an application with gold tier + apiStoreClientUser.addApplication(APPLICATION_NAME, TIER_GOLD, "", ""); + + //Create publish and subscribe an API + APIIdentifier apiIdentifier = new APIIdentifier(providerName, API_NAME, API_VERSION_1_0_0); + apiIdentifier.setTier(TIER_GOLD); + createPublishAndSubscribeToAPI( + apiIdentifier, apiCreationRequestBean, apiPublisherClientUser, apiStoreClientUser, APPLICATION_NAME); + + //Add request headers + HashMap requestHeadersGet = new HashMap(); + requestHeadersGet.put("accept", "text/xml"); + + //Get the access token + String accessToken = generateApplicationKeys(apiStoreClientUser, APPLICATION_NAME).getAccessToken(); + requestHeadersGet.put("Authorization", "Bearer " + accessToken); + + //Send GET Request + HttpResponse httpResponse = + HttpRequestUtil.doGet(gatewayWebAppUrl + INVOKABLE_API_CONTEXT + API_GET_ENDPOINT_METHOD, + requestHeadersGet); + assertEquals(httpResponse.getResponseCode(), HTTP_RESPONSE_CODE_OK, "Invocation fails for GET request"); + assertTrue(httpResponse.getData().contains(RESPONSE_GET), "Response Data not match for GET request." + + " Expected value : " + RESPONSE_GET + " not contains in response data " + httpResponse.getData()); + } + + + @AfterClass(alwaysRun = true) + public void destroy() throws Exception { + + //Remove application and the subscription + if (apiStoreClientUser != null) { + apiStoreClientUser.removeApplication(APPLICATION_NAME); + } + + //delete the API + if (apiPublisherClientUser != null) { + apiPublisherClientUser.deleteAPI(API_NAME, API_VERSION_1_0_0, providerName); + } + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/hostobject/HostObjectTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/hostobject/HostObjectTestCase.java index 59b16dfc16..1a102b8f1e 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/hostobject/HostObjectTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/hostobject/HostObjectTestCase.java @@ -45,6 +45,7 @@ import org.wso2.carbon.utils.FileManipulator; import org.wso2.carbon.utils.ServerConstants; +import javax.xml.xpath.XPathExpressionException; import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -62,6 +63,8 @@ public class HostObjectTestCase extends APIMIntegrationBaseTest { private Log log = LogFactory.getLog(getClass()); private APIPublisherRestClient apiPublisher; private APIStoreRestClient apiStore; + private static boolean isConfigApplied = false; + private static ServerConfigurationManager serverConfigurationManager; @Factory(dataProvider = "userModeDataProvider") public HostObjectTestCase(TestUserMode userMode) { @@ -71,6 +74,8 @@ public HostObjectTestCase(TestUserMode userMode) { @BeforeClass(alwaysRun = true) public void setEnvironment() throws Exception { super.init(userMode); + serverConfigurationManager = + new ServerConfigurationManager(new AutomationContext("APIM", "gateway",TestUserMode.SUPER_TENANT_ADMIN)); /* If test run in external distributed deployment you need to copy following resources accordingly. @@ -81,19 +86,19 @@ public void setEnvironment() throws Exception { */ String publisherURLHttp = publisherUrls.getWebAppURLHttp(); String storeURLHttp = storeUrls.getWebAppURLHttp(); - ServerConfigurationManager serverConfigurationManager = - new ServerConfigurationManager(new AutomationContext("APIM", "gateway", - TestUserMode.SUPER_TENANT_ADMIN)); - - serverConfigurationManager.applyConfiguration(new File(getAMResourceLocation() - + File.separator + - "configFiles/hostobjecttest/" + - "api-manager.xml")); - serverConfigurationManager.applyConfiguration(new File(getAMResourceLocation() - + File.separator + - "configFiles/tokenTest/" + - "log4j.properties")); - super.init(userMode); + + if (!isConfigApplied) { + serverConfigurationManager.applyConfigurationWithoutRestart(new File(getAMResourceLocation() + + File.separator + + "configFiles/hostobjecttest/" + + "api-manager.xml")); + serverConfigurationManager.applyConfiguration(new File(getAMResourceLocation() + + File.separator + + "configFiles/tokenTest/" + + "log4j.properties")); + super.init(userMode); + isConfigApplied = true; + } apiPublisher = new APIPublisherRestClient(publisherURLHttp); apiStore = new APIStoreRestClient(storeURLHttp); } @@ -228,10 +233,9 @@ public void testHostObjectTestCase() throws Exception { responseArrayFromPublisher = finalOutputPublisher.split("=="); isPublisherResponse = responseArrayFromPublisher[30].contains("HostObjectTestAPI"); } - log.info(finalOutputPublisher); in.close(); - } + log.info(finalOutputPublisher); validatePublisherResponseArray(responseArrayFromPublisher); } catch (IOException e) { @@ -260,11 +264,9 @@ public void testHostObjectTestCase() throws Exception { isStoreResponse = responseArrayFromStore[9].contains("HostObjectTestAPI"); } in.close(); - log.info(finalOutputStore); } + log.info(finalOutputStore); validateStoreResponseArray(responseArrayFromStore); - - } catch (IOException e) { log.error("Error while invoking test application to test publisher host object"); } finally { @@ -287,10 +289,11 @@ public void testAPIProvider() { @AfterClass(alwaysRun = true) public void destroy() throws Exception { apiStore.removeApplication("HostObjectTestAPI-Application"); + serverConfigurationManager.restoreToLastConfiguration(); super.cleanup(); } - public static boolean validateStoreResponseArray(String[] array) { + public boolean validateStoreResponseArray(String[] array) throws XPathExpressionException { assertTrue(array[1].contains("true"), "Error while getting status of billing system from API store host object (isBillingEnabled)"); assertTrue(array[2].contains("https"), @@ -348,7 +351,7 @@ public static boolean validateStoreResponseArray(String[] array) { return true; } - public static boolean validatePublisherResponseArray(String[] array) { + public boolean validatePublisherResponseArray(String[] array) { assertTrue(array[1].contains("true"), "Error while validating roles from API store host object (validateRoles)"); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/jwt/JWTTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/jwt/JWTTestCase.java index ca472c7b75..34b6ce471c 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/jwt/JWTTestCase.java +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/jwt/JWTTestCase.java @@ -27,18 +27,27 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.wso2.am.admin.clients.user.RemoteUserStoreManagerServiceClient; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; import org.wso2.am.integration.test.utils.base.APIMIntegrationBaseTest; import org.wso2.am.integration.test.utils.bean.*; import org.wso2.am.integration.test.utils.clients.APIPublisherRestClient; import org.wso2.am.integration.test.utils.clients.APIStoreRestClient; import org.wso2.am.integration.test.utils.generic.APIMTestCaseUtils; import org.wso2.am.integration.test.utils.monitor.utils.WireMonitorServer; +import org.wso2.carbon.automation.test.utils.http.client.HttpRequestUtil; +import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; import org.wso2.carbon.integration.common.admin.client.UserManagementClient; import org.wso2.carbon.integration.common.utils.mgt.ServerConfigurationManager; +import javax.xml.xpath.XPathExpressionException; import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; @@ -53,15 +62,15 @@ public class JWTTestCase extends APIMIntegrationBaseTest { private WireMonitorServer server; int hostPort = 9988; - private String APIName = "JWTTokenTestAPI"; - private String APIContext = "tokenTest"; + private String apiName = "JWTTokenTestAPI"; + private String apiContext = "tokenTest"; private String tags = "token, jwt"; private String wireMonitorURL = ""; private String description = "This is test API create by API manager integration test"; private String providerName = "admin"; - private String APIVersion = "1.0.0"; - private String ApplicationName = "APILifeCycleTestAPI-application"; - private String APITier = "Gold"; + private String apiVersion = "1.0.0"; + private String applicationName = "APILifeCycleTestAPI-application"; + private String apiTier = "Gold"; @BeforeClass(alwaysRun = true) public void setEnvironment() throws Exception { @@ -90,6 +99,12 @@ public void setEnvironment() throws Exception { server = new WireMonitorServer(hostPort); server.setReadTimeOut(300); server.start(); + + String gatewaySessionCookie = createSession(gatewayContext); + //Load the back-end dummy API + loadSynapseConfigurationFromClasspath( + "artifacts" + File.separator + "AM" + File.separator + "synapseconfigs" + File.separator + "rest" + + File.separator + "dummy_api.xml", gatewayContext, gatewaySessionCookie); } @AfterClass(alwaysRun = true) @@ -100,22 +115,24 @@ public void destroy() throws Exception { serverConfigurationManager.restoreToLastConfiguration(); } - private void addAPI() throws Exception { + private void addAPI(String apiName, String apiVersion, String apiContext, String description, String endpointURL, + String tags, String providerName) + throws APIManagerIntegrationTestException, MalformedURLException, XPathExpressionException { APIPublisherRestClient apiPublisher = new APIPublisherRestClient(publisherURLHttp); apiPublisher.login(publisherContext.getContextTenant().getContextUser().getUserName(), publisherContext.getContextTenant().getContextUser().getPassword()); - APIRequest apiRequest = new APIRequest(APIName, APIContext, new URL(wireMonitorURL)); + APIRequest apiRequest = new APIRequest(apiName, apiContext, new URL(endpointURL)); apiRequest.setTags(tags); apiRequest.setDescription(description); - apiRequest.setVersion(APIVersion); + apiRequest.setVersion(apiVersion); apiRequest.setVisibility("public"); apiRequest.setProvider(providerName); apiPublisher.addAPI(apiRequest); - APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(APIName, providerName, + APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(apiName, providerName, APILifeCycleState.PUBLISHED); apiPublisher.changeAPILifeCycleStatus(updateRequest); @@ -144,19 +161,19 @@ public void testEnableJWTAndClaims() throws Exception { // restart the server since updated claims not picked unless cache expired serverConfigurationManager.restartGracefully(); - addAPI(); + addAPI(apiName, apiVersion, apiContext,description,wireMonitorURL,tags,providerName); APIStoreRestClient apiStoreRestClient = new APIStoreRestClient(storeURLHttp); apiStoreRestClient.login(storeContext.getContextTenant().getContextUser().getUserName(), storeContext.getContextTenant().getContextUser().getPassword()); - apiStoreRestClient.addApplication(ApplicationName, APITier, "", "this-is-test"); - SubscriptionRequest subscriptionRequest = new SubscriptionRequest(APIName, + apiStoreRestClient.addApplication(applicationName, apiTier, "", "this-is-test"); + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(apiName, storeContext.getContextTenant().getContextUser().getUserName()); - subscriptionRequest.setApplicationName(ApplicationName); + subscriptionRequest.setApplicationName(applicationName); apiStoreRestClient.subscribe(subscriptionRequest); - APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(ApplicationName); + APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(applicationName); String responseString = apiStoreRestClient.generateApplicationKey(generateAppKeyRequest).getData(); JSONObject response = new JSONObject(responseString); String accessToken = response.getJSONObject("data").getJSONObject("key").get("accessToken").toString(); @@ -202,6 +219,64 @@ public void testEnableJWTAndClaims() throws Exception { assertTrue("JWT claim invalid claim received", bExceptionOccured); } + /** + * This test case is a test for the fix fix for APIMANAGER-3912, where jwt claims are attempted to retrieve from + * an invalidated cache and hence failed. In carbon 4.2 products cache invalidation timeout is not configurable + * and is hardcoded to 15 mins. So the test case will take approximately 15mins to complete and it will delay the + * product build unnecessarily, hence the test case is disabled. + * + */ + @Test(groups = { "wso2.am" }, description = "JWT Token generation when JWT caching is enabled", enabled = false) + public void testAPIAccessWhenJWTCachingEnabledTestCase() + throws APIManagerIntegrationTestException, XPathExpressionException, IOException, JSONException, + InterruptedException { + + String applicationName = "JWTTokenCacheTestApp"; + String apiName = "JWTTokenCacheTestAPI"; + String apiContext = "JWTTokenCacheTestAPI"; + String apiVersion = "1.0.0"; + String description = "JWTTokenCacheTestAPI description"; + String endpointURL = gatewayUrls.getWebAppURLNhttp() + "response"; + String apiTier = "Gold"; + String tags = "token,jwt,cache"; + int waitingSecs = 900; + + addAPI(apiName, apiVersion, apiContext, description, endpointURL, tags, providerName); + + APIStoreRestClient apiStoreRestClient = new APIStoreRestClient(storeURLHttp); + apiStoreRestClient.login(storeContext.getContextTenant().getContextUser().getUserName(), + storeContext.getContextTenant().getContextUser().getPassword()); + + apiStoreRestClient.addApplication(applicationName, apiTier, "", "this-is-test"); + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(apiName, + storeContext.getContextTenant().getContextUser().getUserName()); + subscriptionRequest.setApplicationName(applicationName); + apiStoreRestClient.subscribe(subscriptionRequest); + + APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(applicationName); + String responseString = apiStoreRestClient.generateApplicationKey(generateAppKeyRequest).getData(); + JSONObject response = new JSONObject(responseString); + String accessToken = response.getJSONObject("data").getJSONObject("key").get("accessToken").toString(); + + String url = gatewayUrls.getWebAppURLNhttp() + apiContext + "/" + apiVersion; + + Map headers = new HashMap(); + headers.put("Authorization", "Bearer " + accessToken); + //Invoke the API + HttpResponse httpResponse = HttpRequestUtil.doGet(url, headers); + assertEquals("GET request failed for " + url, 200, httpResponse.getResponseCode()); + + //Wait till cache is invalidated + log.info("Waiting " + waitingSecs + " sec(s) till claims local cache is invalidated"); + Thread.sleep(waitingSecs * 1000); + + //Second attempt to invoke the API. + httpResponse = HttpRequestUtil.doGet(url, headers); + assertEquals("GET request failed for " + url + + ". Most probably due to a failed invalidated cache access to retrieve JWT claims.", 200, + httpResponse.getResponseCode()); + } + private void checkDefaultUserClaims(JSONObject jsonObject) throws JSONException { String claim = jsonObject.getString("iss"); assertTrue("JWT assertion is invalid", claim.contains("wso2.org/products/am")); @@ -279,13 +354,13 @@ public void testSpecificUserJWTClaims() throws Exception { APIStoreRestClient apiStoreRestClient = new APIStoreRestClient(storeURLHttp); apiStoreRestClient.login(subscriberUser, password); - apiStoreRestClient.addApplication(ApplicationName, APITier, "", "this-is-test"); - SubscriptionRequest subscriptionRequest = new SubscriptionRequest(APIName, + apiStoreRestClient.addApplication(applicationName, apiTier, "", "this-is-test"); + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(apiName, providerName); - subscriptionRequest.setApplicationName(ApplicationName); + subscriptionRequest.setApplicationName(applicationName); apiStoreRestClient.subscribe(subscriptionRequest); - APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(ApplicationName); + APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(applicationName); String responseString = apiStoreRestClient.generateApplicationKey(generateAppKeyRequest).getData(); JSONObject response = new JSONObject(responseString); accessToken = response.getJSONObject("data").getJSONObject("key").get("accessToken").toString(); @@ -335,10 +410,10 @@ public void testTenantUserJWTClaims() throws Exception { apiPublisherRestClient.login(tenantUser, password); - APIRequest apiRequest = new APIRequest(APIName, APIContext, new URL(wireMonitorURL)); + APIRequest apiRequest = new APIRequest(apiName, apiContext, new URL(wireMonitorURL)); apiRequest.setTags(tags); apiRequest.setDescription(description); - apiRequest.setVersion(APIVersion); + apiRequest.setVersion(apiVersion); apiRequest.setWsdl("https://svn.wso2.org/repos/wso2/carbon/platform/trunk/products" + "/bps/modules/samples/product/src/main/resources/bpel/2.0/MyRoleMexTestProcess/echo.wsdl"); apiRequest.setVisibility("public"); @@ -346,20 +421,20 @@ public void testTenantUserJWTClaims() throws Exception { apiRequest.setProvider(provider); apiPublisherRestClient.addAPI(apiRequest); - APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(APIName, provider, + APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(apiName, provider, APILifeCycleState.PUBLISHED); apiPublisherRestClient.changeAPILifeCycleStatus(updateRequest); APIStoreRestClient apiStoreRestClient = new APIStoreRestClient(storeURLHttp); apiStoreRestClient.login(tenantUser, password); - apiStoreRestClient.addApplication(ApplicationName, APITier, "", "this-is-test"); - SubscriptionRequest subscriptionRequest = new SubscriptionRequest(APIName, + apiStoreRestClient.addApplication(applicationName, apiTier, "", "this-is-test"); + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(apiName, provider); - subscriptionRequest.setApplicationName(ApplicationName); + subscriptionRequest.setApplicationName(applicationName); apiStoreRestClient.subscribe(subscriptionRequest); - APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(ApplicationName); + APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator(applicationName); String responseString = apiStoreRestClient.generateApplicationKey(generateAppKeyRequest).getData(); JSONObject response = new JSONObject(responseString); accessToken = response.getJSONObject("data").getJSONObject("key").get("accessToken").toString(); diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/APIMANAGER4033CheckAuthTypeTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/APIMANAGER4033CheckAuthTypeTestCase.java new file mode 100644 index 0000000000..7ae2597f35 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/APIMANAGER4033CheckAuthTypeTestCase.java @@ -0,0 +1,116 @@ +/* +* 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.am.integration.tests.other; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; +import org.wso2.am.integration.test.utils.bean.APILifeCycleState; +import org.wso2.am.integration.test.utils.bean.APILifeCycleStateRequest; +import org.wso2.am.integration.test.utils.bean.APIRequest; +import org.wso2.am.integration.test.utils.clients.APIPublisherRestClient; +import org.wso2.am.integration.tests.api.lifecycle.APIManagerLifecycleBaseTest; +import org.wso2.carbon.apimgt.api.model.APIIdentifier; +import org.wso2.carbon.authenticator.stub.LoginAuthenticationExceptionException; +import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; +import org.xml.sax.SAXException; + +import javax.xml.stream.XMLStreamException; +import javax.xml.xpath.XPathExpressionException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + + +public class APIMANAGER4033CheckAuthTypeTestCase extends APIManagerLifecycleBaseTest { + private APIPublisherRestClient apiPublisher; + private String apiEndPointUrl; + APIIdentifier apiIdentifier; + + private static final String TEST_DATA_APINAME = "APIMANAGER4033"; + private static final String TEST_DATA_APICONTEXT = "apimanager4033"; + private static final String TEST_DATA_TAGS = "4033, auth_type"; + private static final String TEST_DATA_API_DESCRIPTION = "This is test API created to test Auth Type"; + private static final String TEST_DATA_API_PROVIDER_NAME = "admin"; + private static final String TEST_DATA_API_VERSION = "1.0.0"; + private static final String API_END_POINT_POSTFIX_URL = "jaxrs_basic/services/customers/customerservice/"; + private static final String TEST_DATA_ENDPOINT_TYPE = "nonsecured"; + private static final String TEST_DATA_RESOURCE_METHOD = "GET"; + private static final String TEST_DATA_RESOURCE_METHOD_ENDPOINT_TYPE = "Any"; + private static final String TEST_DATA_EXPECTED_ENDPOINT_TYPE = "Application & Application User"; + private static final String TEST_DATA_RESOURCE_METHOD_ENDPOINT_THROTTLING = "Unlimited"; + private static final String TEST_DATA_API_VISIBILITY = "public"; + private static final String TEST_DATA_URI_TEMPLATE = "*"; + + + @BeforeClass(alwaysRun = true) + public void setEnvironment() throws APIManagerIntegrationTestException, IOException, + XPathExpressionException, URISyntaxException, SAXException, XMLStreamException, + LoginAuthenticationExceptionException { + super.init(); + apiEndPointUrl = gatewayUrls.getWebAppURLHttp() + API_END_POINT_POSTFIX_URL; + String publisherURLHttp = publisherUrls.getWebAppURLHttp(); + apiPublisher = new APIPublisherRestClient(publisherURLHttp); + } + + @Test(groups = {"wso2.am"}, description = "API Auth type test case") + public void testAuthTypeOfCreatedAPI() throws Exception { + + apiIdentifier = new APIIdentifier(TEST_DATA_API_PROVIDER_NAME, TEST_DATA_APINAME, TEST_DATA_API_VERSION); + //login to the publisher + apiPublisher.login(publisherContext.getContextTenant().getContextUser().getUserName(), + publisherContext.getContextTenant().getContextUser().getPassword()); + + //set api details to the API being published + APIRequest apiRequest = new APIRequest(TEST_DATA_APINAME, TEST_DATA_APICONTEXT, new URL(apiEndPointUrl)); + apiRequest.setTags(TEST_DATA_TAGS); + apiRequest.setDescription(TEST_DATA_API_DESCRIPTION); + apiRequest.setVersion(TEST_DATA_API_VERSION); + apiRequest.setEndpointType(TEST_DATA_ENDPOINT_TYPE); + + apiRequest.setResourceCount("0"); + apiRequest.setResourceMethod(TEST_DATA_RESOURCE_METHOD); + apiRequest.setUriTemplate(TEST_DATA_URI_TEMPLATE); + apiRequest.setResourceMethodAuthType(TEST_DATA_RESOURCE_METHOD_ENDPOINT_TYPE); + apiRequest.setResourceMethodThrottlingTier(TEST_DATA_RESOURCE_METHOD_ENDPOINT_THROTTLING); + apiRequest.setVisibility(TEST_DATA_API_VISIBILITY); + apiRequest.setRoles(TEST_DATA_API_PROVIDER_NAME); + + //Add API + apiPublisher.addAPI(apiRequest); + + //Update API + APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(TEST_DATA_APINAME, + TEST_DATA_API_PROVIDER_NAME, APILifeCycleState.PUBLISHED); + apiPublisher.changeAPILifeCycleStatus(updateRequest); + + //getAPIManagePage + HttpResponse managePage = apiPublisher.getAPIManagePage(TEST_DATA_APINAME, TEST_DATA_API_PROVIDER_NAME, + TEST_DATA_API_VERSION); + Assert.assertTrue(managePage.getData().contains(TEST_DATA_EXPECTED_ENDPOINT_TYPE), + "Resource method endpoint type not set properly."); + + } + + + @AfterClass(alwaysRun = true) + public void cleanUpArtifacts() throws APIManagerIntegrationTestException { + deleteAPI(apiIdentifier, apiPublisher); + } +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NTLMTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NTLMTestCase.java new file mode 100644 index 0000000000..53829e1697 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/NTLMTestCase.java @@ -0,0 +1,122 @@ +/* +* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +* WSO2 Inc. 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.am.integration.tests.other; + +import org.apache.axiom.util.base64.Base64Utils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.json.JSONObject; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.test.utils.base.APIMIntegrationBaseTest; +import org.wso2.am.integration.test.utils.bean.APPKeyRequestGenerator; +import org.wso2.am.integration.test.utils.clients.APIStoreRestClient; +import waffle.apache.NegotiateAuthenticator; +import waffle.util.Base64; +import waffle.windows.auth.IWindowsCredentialsHandle; +import waffle.windows.auth.impl.WindowsAccountImpl; +import waffle.windows.auth.impl.WindowsCredentialsHandleImpl; +import waffle.windows.auth.impl.WindowsSecurityContextImpl; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import static org.testng.Assert.assertNotNull; + +public class NTLMTestCase extends APIMIntegrationBaseTest { + private APIStoreRestClient apiStore; + static NegotiateAuthenticator _authenticator = null; + + @BeforeClass(alwaysRun = true) + public void setEnvironment() throws Exception { + super.init(); + String storeURLHttp = storeUrls.getWebAppURLHttp(); + apiStore = new APIStoreRestClient(storeURLHttp); + } + + @Test(groups = {"wso2.am"}, description = "This test method only runs on windows environment.We exchange NTLM " + + "token for access_token") + public void testGenerateNTLMTokensTestCase() throws Exception { + + String securityPackage = "Negotiate"; + _authenticator = new NegotiateAuthenticator(); + String clientToken; + IWindowsCredentialsHandle clientCredentials; + WindowsSecurityContextImpl clientContext; + // client credentials handle + clientCredentials = WindowsCredentialsHandleImpl.getCurrent(securityPackage); + clientCredentials.initialize(); + // initial client security context + clientContext = new WindowsSecurityContextImpl(); + clientContext.setPrincipalName(WindowsAccountImpl.getCurrentUsername()); + + clientContext.setCredentialsHandle(clientCredentials.getHandle()); + clientContext.setSecurityPackage(securityPackage); + clientContext.initialize(null, null, WindowsAccountImpl.getCurrentUsername()); + //NTLM token. + clientToken = Base64.encode(clientContext.getToken()); + apiStore.login(storeContext.getContextTenant().getContextUser().getUserName(), + storeContext.getContextTenant().getContextUser().getPassword()); + apiStore.addApplication("NTLM", "Unlimited", "some_url", "NewApp"); + + //Generate production token and invoke with that + APPKeyRequestGenerator generateAppKeyRequest = new APPKeyRequestGenerator("NTLM"); + String responseString = apiStore.generateApplicationKey(generateAppKeyRequest).getData(); + JSONObject jsonResponse = new JSONObject(responseString); + + // get Consumer Key and Consumer Secret + String consumerKey = jsonResponse.getJSONObject("data").getJSONObject("key").getString("consumerKey"); + String consumerSecret = jsonResponse.getJSONObject("data").getJSONObject("key").getString("consumerSecret"); + + Thread.sleep(4000); + HttpClient httpclient = new DefaultHttpClient(); + byte[] userKey = (consumerKey + ":" + consumerSecret).getBytes(); + String encoding = Base64Utils.encode(userKey); + URL tokenEndpointURL = new URL(gatewayUrls.getWebAppURLNhttp() + "token"); + HttpPost httppost = new HttpPost(String.valueOf(tokenEndpointURL)); + httppost.setHeader("Authorization", "Basic " + encoding); + List paramVals = new ArrayList(); + paramVals.add(new BasicNameValuePair("grant_type", "iwa:ntlm")); + paramVals.add(new BasicNameValuePair("windows_token", clientToken)); + HttpResponse response; + httppost.setEntity(new UrlEncodedFormEntity(paramVals, "UTF-8")); + response = httpclient.execute(httppost); + HttpEntity entity = response.getEntity(); + responseString = EntityUtils.toString(entity, "UTF-8"); + JSONObject accessTokenGenerationResponse = new JSONObject(responseString); + String accessToken = accessTokenGenerationResponse.getString("access_token"); + assertNotNull(accessToken, "Error while getting access token.. access token is empty"); + } + + @AfterClass(alwaysRun = true) + public void destroy() throws Exception { + super.cleanUp(gatewayContext.getContextTenant().getTenantAdmin().getUserName(), + gatewayContext.getContextTenant().getContextUser().getPassword(), + storeUrls.getWebAppURLHttp(), publisherUrls.getWebAppURLHttp()); + } +} \ No newline at end of file diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/ReadOnlySecondaryUserStoreAPITokenGenerationTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/ReadOnlySecondaryUserStoreAPITokenGenerationTestCase.java new file mode 100644 index 0000000000..ed46edc8c7 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/ReadOnlySecondaryUserStoreAPITokenGenerationTestCase.java @@ -0,0 +1,213 @@ +/* +*Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +* +*WSO2 Inc. 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.am.integration.tests.other; + +import org.apache.axis2.AxisFault; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONObject; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.test.utils.base.APIMIntegrationBaseTest; +import org.wso2.am.integration.test.utils.bean.APILifeCycleState; +import org.wso2.am.integration.test.utils.bean.APILifeCycleStateRequest; +import org.wso2.am.integration.test.utils.bean.APIRequest; +import org.wso2.am.integration.test.utils.bean.SubscriptionRequest; +import org.wso2.am.integration.test.utils.bean.APPKeyRequestGenerator; +import org.wso2.am.integration.test.utils.clients.APIPublisherRestClient; +import org.wso2.am.integration.test.utils.clients.APIStoreRestClient; +import org.wso2.carbon.integration.common.admin.client.AuthenticatorClient; +import org.wso2.carbon.integration.common.admin.client.UserManagementClient; +import org.wso2.carbon.integration.common.utils.mgt.ServerConfigurationManager; + +import java.io.File; +import java.net.URL; + +/* +* This class test the token generation for the APIs subscribed from an ReadOnly External Store +* */ +public class ReadOnlySecondaryUserStoreAPITokenGenerationTestCase extends APIMIntegrationBaseTest { + + private static final Log log = LogFactory.getLog(ReadOnlySecondaryUserStoreAPITokenGenerationTestCase.class); + + private APIPublisherRestClient apiPublisher; + private APIStoreRestClient apiStore; + private static String apiProvider; + private String gatewaySessionCookie; + + private ServerConfigurationManager serverConfigurationManager; + private UserManagementClient userMgtClient; + private UserManagementClient testUserMgtClient; + private AuthenticatorClient authenticatorClient; + private String newUserName = "CAT.COM/chamalee"; + private String newUserRole = "CAT.COM/userStoreSubscriber"; + + private String newUserPassword = "password"; + private String backendURL; + + private static final String API_NAME = "JDBCSecStoreTestAPI"; + private static final String API_VERSION = "1.0.0"; + private static final String APP_NAME = "chamsApp"; + + @BeforeClass(alwaysRun = true) + public void setEnvironment() throws Exception { + + super.init(); + //change the user-mgt.xml configuration + String userMgtXml = getAMResourceLocation() + File.separator + "configFiles/externalstore/user-mgt.xml"; + serverConfigurationManager = new ServerConfigurationManager(gatewayContext); + serverConfigurationManager.applyConfiguration(new File(userMgtXml)); + } + + @Test(groups = "wso2.am", description = "Read only External Store Token Generation") + public void addUserIntoJDBCUserStore() throws Exception { + + gatewaySessionCookie = createSession(gatewayContext); + backendURL = gatewayContext.getContextUrls().getBackEndUrl(); + + userMgtClient = new UserManagementClient(backendURL, gatewaySessionCookie); + authenticatorClient = new AuthenticatorClient(gatewayContext.getContextUrls().getBackEndUrl()); + + //add Role + userMgtClient.addRole(newUserRole, null, new String[]{"/permission/admin/login" + , "/permission/admin/manage/api/subscribe"}); + Assert.assertTrue(userMgtClient.roleNameExists(newUserRole), "Role name doesn't exists"); + + //add User + userMgtClient.addUser(newUserName, newUserPassword, new String[]{newUserRole}, null); + Assert.assertTrue(userMgtClient.userNameExists(newUserRole, newUserName), "User name doesn't exists"); + + String sessionCookie = authenticatorClient.login(newUserName, newUserPassword, "localhost"); + Assert.assertTrue(sessionCookie.contains("JSESSIONID"), "Session Cookie not found. Login failed"); + + + //change the user-mgt.xml file with read only property + String userMgtReadOnlyXml = getAMResourceLocation() + File.separator + + "configFiles/externalstore/user-mgt-readonly.xml"; + String targetReadOnlyXML = serverConfigurationManager.getCarbonHome() + "/repository/conf/user-mgt.xml"; + + serverConfigurationManager = new ServerConfigurationManager(gatewayContext); + serverConfigurationManager.applyConfiguration(new File(userMgtReadOnlyXml), new File(targetReadOnlyXML)); + + //create a new gateway session cookie since server is restarted + String newGatewaySessionCookie = createSession(gatewayContext); + + //check for AxisFault when adding roles to the read only user store + testUserMgtClient = new UserManagementClient(backendURL, newGatewaySessionCookie); + AuthenticatorClient testAuthenticatorClient = new AuthenticatorClient(gatewayContext.getContextUrls().getBackEndUrl()); + + try{ + testUserMgtClient.addRole("CAT.COM/testRole", null, new String[]{"/permission/admin/login" + , "/permission/admin/manage/api/subscribe"}); + + }catch (AxisFault axisFault) { + log.info("The Exception is expected since adding roles is disabled when user store is readonly."); + } + Assert.assertEquals(testUserMgtClient.roleNameExists("CAT.COM/testRole"), false, + "User Store is still not readonly"); + + //Load the back-end dummy API + loadSynapseConfigurationFromClasspath("artifacts" + File.separator + "AM" + + File.separator + "synapseconfigs" + File.separator + "rest" + + File.separator + "dummy_api.xml", gatewayContext, newGatewaySessionCookie); + + //add an API + String apiContext = "test"; + String tags = "testing"; + String url = gatewayUrls.getWebAppURLNhttp() + "response"; + String description = "This is a test API created by API manager integration test"; + + apiPublisher = new APIPublisherRestClient(publisherUrls.getWebAppURLHttp()); + apiStore = new APIStoreRestClient(storeUrls.getWebAppURLHttp()); + apiProvider = publisherContext.getSuperTenant().getContextUser().getUserName(); + + apiPublisher.login("admin", "admin"); + + APIRequest apiRequest = new APIRequest(API_NAME, apiContext, new URL(url)); + apiRequest.setTags(tags); + apiRequest.setDescription(description); + apiRequest.setVersion(API_VERSION); + apiRequest.setProvider(apiProvider); + apiRequest.setSandbox(url); + + apiPublisher.addAPI(apiRequest); + + //publish the API + APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(API_NAME, apiProvider, + APILifeCycleState.PUBLISHED); + apiPublisher.changeAPILifeCycleStatus(updateRequest); + + authenticatorClient.logOut(); + + //go to store with external store user credentials + apiStore.login(newUserName, newUserPassword); + + //create application + apiStore.addApplication(APP_NAME, "Unlimited", "some_url", "NewApp"); + + //subscribed the API + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(API_NAME, apiProvider); + subscriptionRequest.setApplicationName(APP_NAME); + + apiStore.subscribe(subscriptionRequest); + + //Generate sandbox Token + APPKeyRequestGenerator generateAppKeyRequestSandBox = new APPKeyRequestGenerator(APP_NAME); + generateAppKeyRequestSandBox.setKeyType("SANDBOX"); + String responseStringSandBox = + apiStore.generateApplicationKey(generateAppKeyRequestSandBox).getData(); + JSONObject responseSandBox = new JSONObject(responseStringSandBox); + Assert.assertEquals(responseSandBox.getJSONObject("data").equals(null), false, "Generating SANDBOX key failed"); + + String sandBoxAccessToken = + responseSandBox.getJSONObject("data").getJSONObject("key").get("accessToken") + .toString(); + Assert.assertEquals(sandBoxAccessToken.isEmpty(), false, "SANDBOX access token is Empty"); + + + APPKeyRequestGenerator generateAppKeyRequestProduction = new APPKeyRequestGenerator(APP_NAME); + generateAppKeyRequestProduction.setKeyType("PRODUCTION"); + + String responseStringProduction = + apiStore.generateApplicationKey(generateAppKeyRequestProduction).getData(); + JSONObject responseProduction = new JSONObject(responseStringProduction); + Assert.assertEquals(responseProduction.getJSONObject("data").equals(null), false, + "Generating production key failed"); + + String productionAccessToken = + responseProduction.getJSONObject("data").getJSONObject("key").get("accessToken") + .toString(); + Assert.assertEquals(productionAccessToken.isEmpty(), false, "Production access token is Empty"); + } + + @AfterClass(alwaysRun = true) + public void destroy() throws Exception { + + //removing APIs and Applications + super.cleanUp(gatewayContext.getContextTenant().getTenantAdmin().getUserName(), + gatewayContext.getContextTenant().getContextUser().getPassword(), + storeUrls.getWebAppURLHttp(), publisherUrls.getWebAppURLHttp()); + + //restore configuration + serverConfigurationManager.restoreToLastConfiguration(); + log.info("Restored configuration"); + } +} + diff --git a/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/RelativeUrlLocationHeaderTestCase.java b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/RelativeUrlLocationHeaderTestCase.java new file mode 100644 index 0000000000..826c15fcdb --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/java/org/wso2/am/integration/tests/other/RelativeUrlLocationHeaderTestCase.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.am.integration.tests.other; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; +import org.wso2.am.integration.test.utils.APIManagerIntegrationTestException; +import org.wso2.am.integration.test.utils.base.APIMIntegrationBaseTest; + +import org.wso2.am.integration.test.utils.bean.APILifeCycleState; +import org.wso2.am.integration.test.utils.bean.APILifeCycleStateRequest; +import org.wso2.am.integration.test.utils.bean.APIRequest; +import org.wso2.am.integration.test.utils.bean.APPKeyRequestGenerator; +import org.wso2.am.integration.test.utils.bean.SubscriptionRequest; +import org.wso2.am.integration.test.utils.clients.APIPublisherRestClient; +import org.wso2.am.integration.test.utils.clients.APIStoreRestClient; + +import org.json.JSONObject; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.carbon.automation.test.utils.http.client.HttpRequestUtil; +import org.wso2.carbon.automation.test.utils.http.client.HttpResponse; +import javax.xml.xpath.XPathExpressionException; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +/** + * Test to check the Http 201 response when location header is a relative URL + */ +public class RelativeUrlLocationHeaderTestCase extends APIMIntegrationBaseTest { + + private static final Log log = LogFactory.getLog(RelativeUrlLocationHeaderTestCase.class); + + private APIPublisherRestClient apiPublisher; + private APIStoreRestClient apiStore; + + @BeforeClass(alwaysRun = true) + public void setEnvironment() throws Exception { + super.init(); + String gatewaySessionCookie = createSession(gatewayContext); + //Initialize publisher and store. + apiPublisher = new APIPublisherRestClient(publisherUrls.getWebAppURLHttp()); + apiStore = new APIStoreRestClient(storeUrls.getWebAppURLHttp()); + + //Load the back-end dummy API + loadSynapseConfigurationFromClasspath("artifacts" + File.separator + "AM" + + File.separator + "synapseconfigs" + File.separator + "rest" + + File.separator + "dummy_api_relative_url_loc_header.xml", gatewayContext, gatewaySessionCookie); + } + + @Test(groups = "wso2.am", description = "Check functionality of the API for relative URL location header") + public void testAPIWithRelativeUrlLocationHeader() throws Exception { + + try { + apiPublisher.login(publisherContext.getContextTenant().getContextUser().getUserName(), + publisherContext.getContextTenant().getContextUser().getPassword()); + } catch (APIManagerIntegrationTestException e) { + log.error("APIManagerIntegrationTestException " + e.getMessage()); + Assert.assertTrue(false); + } catch (XPathExpressionException e) { + log.error("XPathExpressionException " + e.getMessage()); + Assert.assertTrue(false); + } + + String apiName = "RelativeUrlLocationHeaderAPI"; + String apiVersion = "1.0.0"; + String apiContext = "/relative"; + String endpointUrl = gatewayUrls.getWebAppURLNhttp() + "response/1.0.0"; + + String appName = "RelativeLocHeaderAPP"; + + //Create the api creation request object + APIRequest apiRequest = null; + try { + apiRequest = new APIRequest(apiName, apiContext, new URL(endpointUrl)); + } catch (APIManagerIntegrationTestException e) { + log.error("Error creating APIRequest " + e.getMessage()); + Assert.assertTrue(false); + } catch (MalformedURLException e) { + log.error("Invalid URL " + gatewayUrls.getWebAppURLNhttp() + "response", e); + Assert.assertTrue(false); + } + + apiRequest.setVersion(apiVersion); + apiRequest.setTiersCollection("Unlimited"); + apiRequest.setTier("Unlimited"); + + //Add the API using the API publisher. + try { + apiPublisher.addAPI(apiRequest); + + APILifeCycleStateRequest updateRequest = new APILifeCycleStateRequest(apiName, + publisherContext.getContextTenant().getContextUser().getUserName(), + APILifeCycleState.PUBLISHED); + //Publish the API + apiPublisher.changeAPILifeCycleStatus(updateRequest); + + //Login to the API Store + apiStore.login(storeContext.getContextTenant().getContextUser().getUserName(), + storeContext.getContextTenant().getContextUser().getPassword()); + + //Add an Application in the Store. + apiStore.addApplication(appName, "Unlimited", "", ""); + + //Subscribe the API to the application + SubscriptionRequest subscriptionRequest = new SubscriptionRequest(apiName, apiVersion, + storeContext.getContextTenant().getContextUser().getUserName(), + appName, "Unlimited"); + apiStore.subscribe(subscriptionRequest); + + APPKeyRequestGenerator generateAppKeyRequestProduction = new APPKeyRequestGenerator(appName); + generateAppKeyRequestProduction.setKeyType("PRODUCTION"); + + String responseString = + apiStore.generateApplicationKey(generateAppKeyRequestProduction).getData(); + JSONObject responseProduction = new JSONObject(responseString); + Assert.assertEquals(responseProduction.getJSONObject("data").equals(null), false, + "Generating production key failed"); + + String accessToken = + responseProduction.getJSONObject("data").getJSONObject("key").get("accessToken") + .toString(); + Assert.assertEquals(accessToken.isEmpty(), false, "Production access token is Empty"); + + //Send GET Request + + Map requestHeadersGet = new HashMap(); + requestHeadersGet.put("accept", "text/xml"); + + requestHeadersGet.put("Authorization", "Bearer " + accessToken); + + HttpResponse httpResponse = HttpRequestUtil.doGet(endpointUrl + "/" + apiVersion, requestHeadersGet); + + Assert.assertEquals(httpResponse.getResponseCode(), 201, "Response Code Mismatched"); + + } catch (APIManagerIntegrationTestException e) { + log.error("APIManagerIntegrationTestException " + e.getMessage(), e); + Assert.assertTrue(false); + } catch (JSONException e) { + log.error("Error parsing JSON to get access token " + e.getMessage(), e); + Assert.assertTrue(false); + } catch (XPathExpressionException e) { + log.error("XPathExpressionException " + e.getMessage(), e); + Assert.assertTrue(false); + } catch (IOException e) { + log.error("IOException " + e.getMessage(), e); + Assert.assertTrue(false); + } + } + + @AfterClass(alwaysRun = true) + public void destroy() throws Exception { + + //removing APIs and Applications + super.cleanUp(gatewayContext.getContextTenant().getTenantAdmin().getUserName(), + gatewayContext.getContextTenant().getContextUser().getPassword(), + storeUrls.getWebAppURLHttp(), publisherUrls.getWebAppURLHttp()); + + log.info("Cleaned up API Manager"); + } + +} diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/externalstore/user-mgt-readonly.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/externalstore/user-mgt-readonly.xml new file mode 100644 index 0000000000..4837a0eb5e --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/externalstore/user-mgt-readonly.xml @@ -0,0 +1,372 @@ + + + + + + true + admin + + admin + admin + + everyone + jdbc/WSO2CarbonDB + + + + + + + org.wso2.carbon.user.core.tenant.JDBCTenantManager + false + 100 + false + default + SHA-256 + true + true + true + false + ^[\S]{5,30}$ + ^[\S]{5,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + true + 100 + 100 + false + false + + + + + + org.wso2.carbon.user.core.tenant.JDBCTenantManager + 100 + false + default + SHA-256 + true + true + true + true + false + ^[\S]{5,30}$ + ^[\S]{5,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + true + 100 + 100 + false + false + cat.com + + + + + + + + + + + + + + + + + + + + + /permission + true + + + + + diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/externalstore/user-mgt.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/externalstore/user-mgt.xml new file mode 100644 index 0000000000..418b17abb6 --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/externalstore/user-mgt.xml @@ -0,0 +1,372 @@ + + + + + + true + admin + + admin + admin + + everyone + jdbc/WSO2CarbonDB + + + + + + + org.wso2.carbon.user.core.tenant.JDBCTenantManager + false + 100 + false + default + SHA-256 + true + true + true + false + ^[\S]{5,30}$ + ^[\S]{5,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + true + 100 + 100 + false + false + + + + + + org.wso2.carbon.user.core.tenant.JDBCTenantManager + false + 100 + false + default + SHA-256 + true + true + true + false + ^[\S]{5,30}$ + ^[\S]{5,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + ^[^~!#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$ + ^[\S]{3,30}$ + true + 100 + 100 + false + false + cat.com + + + + + + + + + + + + + + + + + + + + + /permission + true + + + + + diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/hostobjecttest/api-manager.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/hostobjecttest/api-manager.xml index 8ac0b3dc50..b5cbb4e0d2 100755 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/hostobjecttest/api-manager.xml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/configFiles/hostobjecttest/api-manager.xml @@ -468,8 +468,8 @@ Store1 http://localhost:9763/store - admin@wso2.com - admin + user1@tenantdomain1.com + test123 diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testPublisherTenant.jag b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testPublisherTenant.jag index 36b5ab32b8..f861d1bf9a 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testPublisherTenant.jag +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testPublisherTenant.jag @@ -111,7 +111,7 @@ print("=="); var tierData = {}; tierData["tierName"] = "Gold"; tierData["permissiontype"] = "Deny"; -tierData["roles"] = "admin@wso2.com"; +tierData["roles"] = "admin"; //26 print(publisherHostObj.updateTierPermissions(tierData)); print("=="); diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStore.jag b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStore.jag index a183dd5973..bad2c6a76f 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStore.jag +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStore.jag @@ -98,7 +98,7 @@ print("==");
 print(storeHostObj.updateApplicationTier("DefaultApplication","gold","admin")); 
print("==");
 //24 -print(storeHostObj.updateApplication("DefaultApplicationTest","DefaultApplication","admin","gold","test-url","updated-application"));
 +print(storeHostObj.updateApplication("DefaultApplication","DefaultApplication","admin","gold","test-url","updated-application"));
 print("==");
 //25 print(storeHostObj.validateWFPermission("Basic YWRtaW46YWRtaW4=")); diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStoreTenant.jag b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStoreTenant.jag index 70abf19384..5789257154 100644 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStoreTenant.jag +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/jaggery/testStoreTenant.jag @@ -98,7 +98,7 @@ print("==");
 print(storeHostObj.updateApplicationTier("DefaultApplication","gold","admin@wso2.com")); 
print("==");
 //24 -print(storeHostObj.updateApplication("DefaultApplicationTest","DefaultApplication","admin@wso2.com","gold","test-url","updated-application"));
 +print(storeHostObj.updateApplication("DefaultApplication","DefaultApplication","admin@wso2.com","gold","test-url","updated-application"));
 print("==");
 //25 print(storeHostObj.validateWFPermission("Basic YWRtaW46YWRtaW4=")); diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/synapseconfigs/rest/dummy_api_relative_url_loc_header.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/synapseconfigs/rest/dummy_api_relative_url_loc_header.xml new file mode 100644 index 0000000000..e66585d8ce --- /dev/null +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/artifacts/AM/synapseconfigs/rest/dummy_api_relative_url_loc_header.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + $1 + Status report + Runtime Error + $2 + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + The default main sequence for API manager - Returns 404 Not Found + + + + + + + + + + 403 + Status report + Forbidden + Unsupported Transport [ $2 ]. The requested resource (/$1) is not + available. + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + 404 + Status report + Not Found + The requested resource (/$1) is not available. + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + Received Request + + + + + + +
+ + + + + + diff --git a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml index 72a10254a5..ebbb789281 100755 --- a/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml +++ b/modules/integration/tests-integration/tests-backend/src/test/resources/testng.xml @@ -47,6 +47,7 @@ + @@ -83,15 +84,20 @@ - - + + + + + diff --git a/modules/integration/tests-ui-integration/pom.xml b/modules/integration/tests-ui-integration/pom.xml index e4d89d84d8..a5e36ae1fc 100644 --- a/modules/integration/tests-ui-integration/pom.xml +++ b/modules/integration/tests-ui-integration/pom.xml @@ -74,6 +74,12 @@ under the License. usedefaultlisteners false + + download.location + + ${basedir}/target + + ${basedir}/target/security-verifier/ ${basedir}/target/emma ${basedir}/src/test/resources/instrumentation.txt diff --git a/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER3366MultipleGatewayPublishTestCase.java b/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER3366MultipleGatewayPublishTestCase.java index b2edef06bf..cc4b473a76 100644 --- a/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER3366MultipleGatewayPublishTestCase.java +++ b/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER3366MultipleGatewayPublishTestCase.java @@ -1,5 +1,3 @@ - - /* * * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. @@ -21,6 +19,8 @@ */ package org.wso2.am.integration.ui.tests; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; @@ -35,6 +35,7 @@ import org.wso2.carbon.utils.CarbonUtils; import java.io.BufferedReader; +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; @@ -44,7 +45,8 @@ public class APIMANAGER3366MultipleGatewayPublishTestCase extends APIMIntegratio private static final String API_URL = "http://gdata.youtube.com/feeds/api/standardfeeds"; private static final String API_METHOD = "/most_popular"; private String accessHTTPURL; - WebDriverWait wait; + private static final Log log = LogFactory.getLog(APIMANAGER3366MultipleGatewayPublishTestCase.class); + WebDriverWait wait; String carbonLogFilePath = CarbonUtils.getCarbonLogsPath() + "/wso2carbon.log"; @BeforeClass(alwaysRun = true) @@ -224,18 +226,36 @@ public void tearDown() throws Exception { driver.quit(); } - private boolean isAPIPublished(String apiName, String version) throws IOException { - BufferedReader input = new BufferedReader(new FileReader(carbonLogFilePath)); - String lastLine = null, line; + private boolean isAPIPublished(String apiName, String version) { + BufferedReader input = null; + boolean status = false; + try { + input = new BufferedReader(new FileReader(carbonLogFilePath)); + String lastLine = null, line; - while ((line = input.readLine()) != null) { - lastLine = line; - } - input.close(); - if (lastLine != null && (lastLine.contains("INFO {org.apache.synapse.rest.API}"))) { - return true; - } else { - return false; - } - } + while ((line = input.readLine()) != null) { + lastLine = line; + } + if (lastLine != null && (lastLine.contains("INFO {org.apache.synapse.rest.API}"))) { + status = true; + } else { + status = false; + } + } catch (FileNotFoundException e) { + String msg = "Couldn't find the " + carbonLogFilePath; + log.error(msg, e); + } catch (IOException e) { + String msg = "Couldn't Read the " + carbonLogFilePath; + log.error(msg, e); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + //Ignore + } + } + } + return status; + } } diff --git a/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER4006SampleApiDeploymentTestCase.java b/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER4006SampleApiDeploymentTestCase.java new file mode 100644 index 0000000000..f1883d75d0 --- /dev/null +++ b/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIMANAGER4006SampleApiDeploymentTestCase.java @@ -0,0 +1,159 @@ +/* + * + * 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.am.integration.ui.tests; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxProfile; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; +import org.wso2.am.integration.ui.tests.util.APIMTestConstants; +import org.wso2.carbon.automation.engine.context.AutomationContext; +import org.wso2.carbon.automation.test.utils.common.TestConfigurationProvider; +import org.wso2.carbon.integration.common.utils.mgt.ServerConfigurationManager; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; + +import java.io.File; + +/** + * This test case evaluates whether the WSDL file of provided SOAP endpoint + * can be downloaded from both API publisher and store in super tenant and tenant modes. + */ +public class APIMANAGER4006SampleApiDeploymentTestCase extends APIMIntegrationUiTestBase { + protected AutomationContext gatewayContext; + private ServerConfigurationManager configManagerApiManager; + private WebDriver driver; + private WebDriverWait wait; + private final String SUPER_TENANT_USERNAME = "admin"; + private final String SUPER_TENANT_PASSWORD = "admin"; + private final String TENANT_DOMAIN_NAME = "wso2.com"; + private final String TENANT_USERNAME = "testuser11"; + private final String TENANT_PASSWORD = "testuser11"; + + private static final Log log = LogFactory.getLog(APIMANAGER4006SampleApiDeploymentTestCase.class); + + @BeforeClass(alwaysRun = true) + public void initialize() throws Exception { + init(); + + //create gateway server instance based on configuration given at automation.xml + gatewayContext = + new AutomationContext(APIMIntegrationConstants.AM_PRODUCT_GROUP_NAME, + APIMIntegrationConstants.AM_GATEWAY_INSTANCE, userMode); + configManagerApiManager = new ServerConfigurationManager(gatewayContext); + configManagerApiManager.applyConfiguration( + new File(TestConfigurationProvider.getResourceLocation() + File.separator + "artifacts" + File.separator + + "AM" + File.separator + "configFiles" + File.separator + "apim4006test" + File.separator + + "api-manager.xml")); + } + + @BeforeClass(alwaysRun = true) + public void setUp() throws Exception { + FirefoxProfile firefoxProfile = new FirefoxProfile(); + firefoxProfile.setPreference("browser.download.folderList", 2); + firefoxProfile.setPreference("browser.download.manager.showWhenStarting", false); + firefoxProfile.setPreference("browser.download.dir", System.getProperty("download.location")); + firefoxProfile.setPreference("browser.helperApps.alwaysAsk.force", false); + //Set browser settings to automatically download wsdl files + firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/force-download"); + driver = new FirefoxDriver(firefoxProfile); + wait = new WebDriverWait(driver, 60); + } + + @Test(groups = "wso2.am", priority = 1, description = "Deploy sample API when unlimited tier unavailable" + + " in super tenant mode") + public void testDeploySampleAPISuperTenantUser() { + deploySampleAPI(SUPER_TENANT_USERNAME, SUPER_TENANT_PASSWORD, MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + } + + @Test(groups = "wso2.am", priority = 2, description = "Deploy sample API when unlimited tier unavailable" + + " in tenant mode") + public void testDeploySampleAPITenantUser() { + deploySampleAPI(TENANT_USERNAME, TENANT_PASSWORD, TENANT_DOMAIN_NAME); + } + + @AfterClass(alwaysRun = true) + public void tearDown() throws Exception { + driver.quit(); + //remove added APIs from all tenants + super.cleanUp(SUPER_TENANT_USERNAME, SUPER_TENANT_PASSWORD, storeUrls.getWebAppURLHttp(), + publisherUrls.getWebAppURLHttp()); + super.cleanUp(TENANT_USERNAME + APIMTestConstants.EMAIL_DOMAIN_SEPARATOR + TENANT_DOMAIN_NAME, TENANT_PASSWORD, + storeUrls.getWebAppURLHttp(), publisherUrls.getWebAppURLHttp()); + //restore modified configurations to previous status + configManagerApiManager.restoreToLastConfiguration(); + } + + /** + * Deploy sample API when Unlimited tier is not available + * + * @param username Username to log into publisher + * @param password Password of the user + * @param domain tenant domain of the user + */ + private void deploySampleAPI(String username, String password, String domain) { + try { + driver.get(getPublisherURL()); + } catch (Exception e) { //This exception doesn't need to be thrown since the test case gets failed + // if an exception occurs. + log.error("couldn't retrieve publisher url", e); + } + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("loginButton"))); + if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(domain)) { + driver.findElement(By.id("username")). + sendKeys(username + APIMTestConstants.EMAIL_DOMAIN_SEPARATOR + domain); + } else { + driver.findElement(By.id("username")).sendKeys(username); + } + driver.findElement(By.id("pass")).sendKeys(password); + driver.findElement(By.id("loginButton")).click(); + log.info("After publisher login"); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("Add"))); + driver.findElement(By.id("deploy_sample1")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("WeatherAPI"))); + driver.findElement(By.linkText("WeatherAPI")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("viewLink"))); + driver.findElement(By.id("viewLink")).click(); + String assignedTier = driver.findElement(By.id("tierAvb")).getText(); + + publisherLogout(); + + Assert.assertEquals(assignedTier, "Gold", "Sample API deployment failed"); + } + + /** + * Logout from the publisher + */ + private void publisherLogout() { + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("userMenu"))); + driver.findElement(By.id("userMenu")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("button.btn.btn-danger"))); + driver.findElement(By.cssSelector("button.btn.btn-danger")).click(); + log.info("After publisher logout"); + } + +} diff --git a/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIWsdlDownloadTestCase.java b/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIWsdlDownloadTestCase.java new file mode 100644 index 0000000000..297b07202d --- /dev/null +++ b/modules/integration/tests-ui-integration/src/test/java/org/wso2/am/integration/ui/tests/APIWsdlDownloadTestCase.java @@ -0,0 +1,351 @@ +/* + * + * 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.am.integration.ui.tests; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxProfile; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.openqa.selenium.support.ui.Select; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.wso2.am.integration.test.utils.base.APIMIntegrationConstants; +import org.wso2.am.integration.ui.tests.util.APIMTestConstants; +import org.wso2.carbon.automation.engine.context.AutomationContext; +import org.wso2.carbon.automation.test.utils.common.FileManager; +import org.wso2.carbon.automation.test.utils.common.TestConfigurationProvider; +import org.wso2.carbon.integration.common.utils.mgt.ServerConfigurationManager; +import org.wso2.carbon.tenant.mgt.stub.TenantMgtAdminServiceExceptionException; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; + +import javax.xml.xpath.XPathExpressionException; +import java.io.File; +import java.io.IOException; + +/** + * This test case evaluates whether the WSDL file of provided SOAP endpoint + * can be downloaded from both API publisher and store in super tenant and tenant modes. + */ +public class APIWsdlDownloadTestCase extends APIMIntegrationUiTestBase { + protected AutomationContext gatewayContext; + private ServerConfigurationManager configManagerDB, configManagerMasterDatasource, configManagerReg; + private WebDriver driver; + private WebDriverWait wait; + private final String SUPER_TENANT_DOMAIN_NAME = "carbon.super"; + private final String SUPER_TENANT_USERNAME = "admin"; + private final String SUPER_TENANT_PASSWORD = "admin"; + private final String TENANT_DOMAIN_NAME = "wso2.com"; + private final String TENANT_USERNAME = "testuser11"; + private final String TENANT_PASSWORD = "testuser11"; + private final String TEST_API_NAME = "AZ176"; + + private static final Log log = LogFactory.getLog(APIWsdlDownloadTestCase.class); + + @BeforeClass(alwaysRun = true) + public void initialize() throws Exception { + init(); + + //create gateway server instance based on configuration given at automation.xml + gatewayContext = + new AutomationContext(APIMIntegrationConstants.AM_PRODUCT_GROUP_NAME, + APIMIntegrationConstants.AM_GATEWAY_INSTANCE, userMode); + configManagerDB = new ServerConfigurationManager(gatewayContext); + configManagerDB.applyConfigurationWithoutRestart( + new File(TestConfigurationProvider.getResourceLocation() + File.separator + "artifacts" + File.separator + + "AM" + File.separator + "configFiles" + File.separator + "wsdldownloadtest" + File.separator + + "WSO2REG_DB.h2.db"), + new File(System.getProperty("carbon.home") + File.separator + "repository" + File.separator + + "database" + File.separator + "WSO2REG_DB.h2.db"), false); + configManagerMasterDatasource = new ServerConfigurationManager(gatewayContext); + configManagerMasterDatasource.applyConfigurationWithoutRestart( + new File(TestConfigurationProvider.getResourceLocation() + File.separator + "artifacts" + File.separator + + "AM" + File.separator + "configFiles" + File.separator + "wsdldownloadtest" + File.separator + + "master-datasources.xml"), + new File(System.getProperty("carbon.home") + File.separator + "repository" + File.separator + + "conf" + File.separator + "datasources" + File.separator + "master-datasources.xml"), true); + configManagerReg = new ServerConfigurationManager(gatewayContext); + configManagerReg.applyConfigurationWithoutRestart( + new File(TestConfigurationProvider.getResourceLocation() + File.separator + "artifacts" + File.separator + + "AM" + File.separator + "configFiles" + File.separator + "wsdldownloadtest" + File.separator + + "registry.xml"), + new File(System.getProperty("carbon.home") + File.separator + "repository" + File.separator + + "conf" + File.separator + "registry.xml"), true); + //init is required to apply to modified configurations to the server + init(); + } + + @BeforeClass(alwaysRun = true) + public void setUp() throws Exception { + FirefoxProfile firefoxProfile = new FirefoxProfile(); + firefoxProfile.setPreference("browser.download.folderList", 2); + firefoxProfile.setPreference("browser.download.manager.showWhenStarting", false); + firefoxProfile.setPreference("browser.download.dir", System.getProperty("download.location")); + firefoxProfile.setPreference("browser.helperApps.alwaysAsk.force", false); + //Set browser settings to automatically download wsdl files + firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk", "application/force-download"); + driver = new FirefoxDriver(firefoxProfile); + wait = new WebDriverWait(driver, 60); + } + + @Test(groups = "wso2.am", priority = 1, description = "Download WSDL from publisher in super tenant mode") + public void testDownloadWSDLFromPublisherSuperTenantUser() + throws InterruptedException, IOException { + createAPIWithWSDLEndpoint(TEST_API_NAME, SUPER_TENANT_USERNAME, SUPER_TENANT_PASSWORD, + MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); + downloadWSDLFromPublisher(SUPER_TENANT_USERNAME, SUPER_TENANT_DOMAIN_NAME, TEST_API_NAME); + } + + @Test(groups = "wso2.am", priority = 2, description = "Download WSDL from store in super tenant mode", + dependsOnMethods = { "testDownloadWSDLFromPublisherSuperTenantUser" }) + public void testDownloadWSDLFromStoreSuperTenantUser() throws IOException, InterruptedException { + downloadWSDLFromStore(SUPER_TENANT_USERNAME, SUPER_TENANT_PASSWORD, SUPER_TENANT_DOMAIN_NAME, TEST_API_NAME); + } + + @Test(groups = "wso2.am", priority = 3, description = "Download WSDL from publisher in tenant mode", + dependsOnMethods = { "testDownloadWSDLFromStoreSuperTenantUser" }) + public void testDownloadFromPublisherTenantUser() + throws TenantMgtAdminServiceExceptionException, InterruptedException, IOException, + XPathExpressionException { + createAPIWithWSDLEndpoint(TEST_API_NAME, TENANT_USERNAME, TENANT_PASSWORD, TENANT_DOMAIN_NAME); + downloadWSDLFromPublisher(TENANT_USERNAME, TENANT_DOMAIN_NAME, TEST_API_NAME); + } + + @Test(groups = "wso2.am", priority = 4, description = "Download WSDL from store in tenant mode", + dependsOnMethods = { "testDownloadFromPublisherTenantUser" }) + public void testDownloadFromStoreTenantUser() throws IOException, InterruptedException { + downloadWSDLFromStore(TENANT_USERNAME, TENANT_PASSWORD, TENANT_DOMAIN_NAME, TEST_API_NAME); + } + + @AfterClass(alwaysRun = true) + public void tearDown() throws Exception { + driver.quit(); + //remove added APIs from all tenants + super.cleanUp(SUPER_TENANT_USERNAME, SUPER_TENANT_PASSWORD, storeUrls.getWebAppURLHttp(), + publisherUrls.getWebAppURLHttp()); + super.cleanUp(TENANT_USERNAME + APIMTestConstants.EMAIL_DOMAIN_SEPARATOR + TENANT_DOMAIN_NAME, TENANT_PASSWORD, + storeUrls.getWebAppURLHttp(), publisherUrls.getWebAppURLHttp()); + //restore modified configurations to previous status + configManagerReg.restoreToLastConfiguration(); + configManagerMasterDatasource.restoreToLastConfiguration(); + FileManager.deleteFile(System.getProperty("carbon.home") + File.separator + "repository" + File.separator + + "database" + File.separator + "WSO2REG_DB.h2.db"); + } + + /** + * Create api with a WSDL endpoint + * + * @param apiName api name + * @param username username to login to publisher + * @param password password of the user + * @param domain domain of the user + */ + private void createAPIWithWSDLEndpoint(String apiName, String username, String password, String domain) + throws InterruptedException { + try { + driver.get(getPublisherURL()); + } catch (Exception e) { + log.error("couldn't retrieve publisher url", e); + } + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("loginButton"))); + if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(domain)) { + driver.findElement(By.id("username")). + sendKeys(username + APIMTestConstants.EMAIL_DOMAIN_SEPARATOR + domain); + } else { + driver.findElement(By.id("username")).sendKeys(username); + } + driver.findElement(By.id("pass")).sendKeys(password); + driver.findElement(By.id("loginButton")).click(); + log.info("After publisher login"); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("Add"))); + driver.findElement(By.linkText("Add")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("create-new-api"))); + driver.findElement(By.xpath("(//input[@name='create-api'])[2]")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("startFromExistingSOAPEndpoint"))); + driver.findElement(By.id("wsdl-url")).clear(); + driver.findElement(By.id("wsdl-url")).sendKeys("http://www.webservicex.com/globalweather.asmx?WSDL"); + driver.findElement(By.id("startFromExistingSOAPEndpoint")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("go_to_implement"))); + driver.findElement(By.id("name")).clear(); + driver.findElement(By.id("name")).sendKeys(apiName); + driver.findElement(By.id("context")).clear(); + driver.findElement(By.id("context")).sendKeys(apiName); + driver.findElement(By.id("version")).clear(); + driver.findElement(By.id("version")).sendKeys("1.0.0"); + driver.findElement(By.id("go_to_implement")).click(); + log.info("After API design"); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@value='#managed-api']"))); + driver.findElement(By.xpath("//div[@value='#managed-api']")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("go_to_manage"))); + driver.findElement(By.id("jsonform-0-elt-production_endpoints")).clear(); + driver.findElement(By.id("jsonform-0-elt-production_endpoints")).sendKeys(storeUrls.getWebAppURLHttp()); + driver.findElement(By.id("jsonform-0-elt-sandbox_endpoints")).clear(); + driver.findElement(By.id("jsonform-0-elt-sandbox_endpoints")).sendKeys(storeUrls.getWebAppURLHttp()); + driver.findElement(By.id("go_to_manage")).click(); + log.info("After API manage"); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("publish_api"))); + driver.findElement(By.xpath("//button[@type='button']")).click(); + driver.findElement(By.xpath("//input[@value='Gold']")).click(); + driver.findElement(By.id("publish_api")).click(); + log.info("After API publish"); + } + + /** + * Logout from the publisher + */ + private void publisherLogout() { + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("userMenu"))); + driver.findElement(By.id("userMenu")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("button.btn.btn-danger"))); + driver.findElement(By.cssSelector("button.btn.btn-danger")).click(); + log.info("After publisher logout"); + } + + /** + * Download WSDL file from the publisher + * + * @param username username to login to store + * @param tenant domain of the login user + * @param apiName api name of the published api + * @throws java.io.IOException if downloaded file couldn't found + * @throws InterruptedException If an interruption occurs in the threads + */ + private void downloadWSDLFromPublisher(String username, String tenant, String apiName) + throws IOException, InterruptedException { + + String tenantUnawareUsername; + //Set the domain name for non super tenant users + if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenant)) { + tenantUnawareUsername = username.concat("-AT-" + tenant); + } else { + tenantUnawareUsername = username; + } + + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("Go to Overview"))); + driver.findElement(By.linkText("Go to Overview")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("lifecyclesLink"))); + driver.findElement(By.id("lifecyclesLink")).click(); + + //Change api status to published if it is not already set + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("editStatus"))); + Select status = new Select(driver.findElement(By.id("editStatus"))); + if (!"PUBLISHED".equals(status.getFirstSelectedOption().getText())) { + status.selectByVisibleText("PUBLISHED"); + } + + driver.findElement(By.id("updateStateButton")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("viewLink"))); + driver.findElement(By.id("viewLink")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("/" + tenantUnawareUsername + "--" + + apiName + "1.0.0.wsdl"))); + //Download wsdl by clicking its link + driver.findElement(By.linkText("/" + tenantUnawareUsername + "--" + apiName + "1.0.0.wsdl")).click(); + File file = new File( + System.getProperty("download.location") + File.separator + tenantUnawareUsername + "--" + apiName + + "1.0.0.wsdl"); + while (!file.exists()) { + Thread.sleep(1000); + } + //check whether downloaded file is readable + boolean isReadableFile = file.canRead(); + file.delete(); + //Logout from publisher once the test is completed + publisherLogout(); + Assert.assertEquals(isReadableFile, true, "Download WSDL from publisher failed"); + } + + /** + * Download WSDL file from API Store + * + * @param username username to login to store + * @param password password of the user + * @param tenant domain of the login user + * @param apiName api name of the published api + * @throws java.io.IOException if downloaded file couldn't found + * @throws InterruptedException If an interruption occurs in the threads + */ + private void downloadWSDLFromStore(String username, String password, String tenant, String apiName) + throws IOException, InterruptedException { + try { + driver.get(getStoreURL() + "?tenant=" + tenant); + } catch (Exception e) { + log.error("Couldn't retrieve store url of api manager"); + } + + Thread.sleep(2000); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("login-link"))); + WebElement login = driver.findElement(By.id("login-link")); + String tenantUnawareUsername = null; + if (login != null) { + login.click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("loginBtn"))); + if (!MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenant)) { + driver.findElement(By.id("username")).sendKeys(username + "@" + tenant); + tenantUnawareUsername = username.concat("-AT-" + tenant); + } else { + driver.findElement(By.id("username")).sendKeys(username); + tenantUnawareUsername = username; + } + driver.findElement(By.id("password")).clear(); + driver.findElement(By.id("password")).sendKeys(password); + driver.findElement(By.id("loginBtn")).click(); + log.info("After store login"); + } + + long waitTime = 30000; // Wait only for 30s until the + long targetWaitTime = System.currentTimeMillis() + waitTime; + + while ((!driver.getPageSource().contains(apiName + "-1.0.0")) && System.currentTimeMillis() < targetWaitTime) { + Thread.sleep(500); // Waiting 0.5 second to check API is visible on UI + driver.navigate().refresh(); + } + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText(apiName + "-1.0.0"))); + driver.findElement(By.linkText(apiName + "-1.0.0")).click(); + driver.findElement(By.linkText("Overview")).click(); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("Download WSDL"))); + driver.findElement(By.linkText("Download WSDL")).click(); + File file = new File( + System.getProperty("download.location") + File.separator + tenantUnawareUsername + "--" + apiName + + "1.0.0.wsdl"); + while (!file.exists()) { + Thread.sleep(1000); + } + boolean isReadableFile = file.canRead(); + file.delete(); + //Logout from store once the test is completed + storeLogout(username); + Assert.assertEquals(isReadableFile, true, "Download WSDL from store failed"); + } + + /** + * Logout from the store + */ + private void storeLogout(String username) throws InterruptedException { + wait.until(ExpectedConditions.visibilityOfElementLocated(By.partialLinkText(username))); + driver.findElement(By.partialLinkText(username)).click(); + driver.findElement(By.id("logout-link")).click(); + log.info("After store logout"); + } +} diff --git a/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/apim4006test/api-manager.xml b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/apim4006test/api-manager.xml new file mode 100755 index 0000000000..004950cd4b --- /dev/null +++ b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/apim4006test/api-manager.xml @@ -0,0 +1,512 @@ + + + jdbc/WSO2AM_DB + + + Synapse + + + false + + + + + + + + + + + + + + + + https://${carbon.local.ip}:${mgt.transport.https.port}${carbon.context}/services/ + + ${admin.username} + + ${admin.password} + + + + + + X-JWT-Assertion + + + + + + + + + + + + + + + org.wso2.carbon.apimgt.impl.token.JWTGenerator + + + + + + + + + + + + + + + Production and Sandbox + Description of environment + + https://${carbon.local.ip}:${mgt.transport.https.port}${carbon.context}/services/ + + ${admin.username} + + ${admin.password} + + http://${carbon.local.ip}:${http.nio.port},https://${carbon.local.ip}:${https.nio.port} + + + + + true + + + true + + + referer + + + + + false + + + + + + false + + + org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageDataBridgeDataPublisher + + + false + + + + org.wso2.apimgt.statistics.request + 1.0.0 + + + org.wso2.apimgt.statistics.response + 1.0.0 + + + org.wso2.apimgt.statistics.fault + 1.0.0 + + + org_wso2_apimgt_statistics_destination + 1.0.0 + bam-profile + + + org.wso2.apimgt.statistics.throttle + 1.0.0 + + + org.wso2.apimgt.statistics.workflow + 1.0.0 + + + + + + + + + https://${carbon.local.ip}:${mgt.transport.https.port}${carbon.context}/services/ + + + ${admin.username} + + + ${admin.password} + + false + + + + false + + + + ThriftClient + 10397 + 10000 + 10397 + + true + + + am_application_scope + + + org.wso2.carbon.apimgt.keymgt.handlers.DefaultKeyValidationHandler + + + + + + + + + /oauth2/token + + + https://${carbon.local.ip}:${https.nio.port}/revoke + + + false + + + + + + + + + + + false + + + + + + + + + true + false + https://${carbon.local.ip}:${mgt.transport.https.port}/store + + false + + false + + + + + true + + + true + + + + + + false + + + + + false + https://${carbon.local.ip}:${mgt.transport.https.port}/publisher + + + + + + + + + + + + + false + + + + + /resource + admin + 1.0.0 + none + none + Any + + + + + + + + + + + + + + + + + + true + + + * + + + GET,PUT,POST,DELETE,OPTIONS + + + authorization,Access-Control-Allow-Origin,Content-Type + + + + + diff --git a/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/WSO2REG_DB.h2.db b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/WSO2REG_DB.h2.db new file mode 100644 index 0000000000..638e244237 Binary files /dev/null and b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/WSO2REG_DB.h2.db differ diff --git a/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/master-datasources.xml b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/master-datasources.xml new file mode 100644 index 0000000000..a39a3aaa8e --- /dev/null +++ b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/master-datasources.xml @@ -0,0 +1,97 @@ + + + + org.wso2.carbon.ndatasource.rdbms.RDBMSDataSourceReader + + + + + + WSO2_CARBON_DB + The datasource used for registry and user manager + + jdbc/WSO2CarbonDB + + + + jdbc:h2:repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE + wso2carbon + wso2carbon + org.h2.Driver + 50 + 60000 + true + SELECT 1 + 30000 + + + + + + WSO2_REG_DB + The datasource used for registry and user manager + + jdbc/WSO2RegDB + + + + jdbc:h2:repository/database/WSO2REG_DB;DB_CLOSE_ON_EXIT=FALSE + wso2carbon + wso2carbon + org.h2.Driver + 50 + 60000 + true + SELECT 1 + 30000 + + + + + + WSO2AM_DB + The datasource used for API Manager database + + jdbc/WSO2AM_DB + + + + jdbc:h2:repository/database/WSO2AM_DB;DB_CLOSE_ON_EXIT=FALSE + wso2carbon + wso2carbon + false + org.h2.Driver + 50 + 60000 + true + SELECT 1 + 30000 + + + + + + WSO2AM_STATS_DB + The datasource used for getting statistics to API Manager + + jdbc/WSO2AM_STATS_DB + + + + jdbc:h2:;AUTO_SERVER=TRUE + wso2carbon + wso2carbon + false + org.h2.Driver + 50 + 60000 + true + SELECT 1 + 30000 + + + + + + + \ No newline at end of file diff --git a/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/registry.xml b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/registry.xml new file mode 100644 index 0000000000..4d3a82308b --- /dev/null +++ b/modules/integration/tests-ui-integration/src/test/resources/artifacts/AM/configFiles/wsdldownloadtest/registry.xml @@ -0,0 +1,346 @@ + + + + + + wso2registry + false + true + / + + + + + jdbc/WSO2CarbonDB + + + + jdbc/WSO2RegDB + + + + + + + wso2reg + wso2reg + false + true + / + + + + + + wso2reg + /_system/config/integrate + + + + wso2reg + /_system/governance/integrate + + + + + + + .* + + + + + + + + .* + + + + + + + + true + + /trunk/schemas/ + + + /trunk/wsdls/ + + + /trunk/policies/ + + + + application/wsdl+xml + + + + + + + application/wsdl+xml + application/xsd+xml + 50 + true + + 3 + + /trunk/schemas/ + + + /trunk/wsdls/ + + + application/vnd.wso2.governance-archive + + + + + + + + 1.0.0-SNAPSHOT + true + + dev + qa + live + + + application/vnd.wso2-service+xml + + + + + + + + application/vnd.wso2-service+xml + + + + + + + + + /_system/governance/event/topics/registry/notifications/.* + + + + + + + + + Created + Tested + Deployed + + + application/vnd.wso2-smart-link + + + + + + + + /trunk/policies/ + + + application/policy+xml + + + + + + + + true + + /trunk/schemas/ + + + application/x-xsd+xml + + + + + + + + application/vnd.wso2-hyperlink + + + + + + + application/vnd.wso2.endpoint + + /trunk/endpoints/ + + + + + + + + application/vnd.wso2-uri+xml + + + + + + + + .* + + + + + + + .* + + + + + + + workflow-config + + + + + + + + + + + + 60 + 2 + + 50 + + 10 + + /_system/local/repository/components/org.wso2.carbon.registry/indexing/lastaccesstime + + + + + + + + + + + + + + + + + + + + + + + + + true + true + true + true + + /trunk/services/ + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/org.wso2.stratos.apimgt.dashboard.ui/pom.xml b/modules/org.wso2.stratos.apimgt.dashboard.ui/pom.xml index c9094dbeec..c5cf6c9770 100644 --- a/modules/org.wso2.stratos.apimgt.dashboard.ui/pom.xml +++ b/modules/org.wso2.stratos.apimgt.dashboard.ui/pom.xml @@ -25,7 +25,7 @@ 4.0.0 org.wso2.stratos.apimgt.dashboard.ui - 2.2.0 + 2.2.1-SNAPSHOT bundle WSO2 Stratos API Manager - Dashboard UI diff --git a/modules/org.wso2.stratos.apimgt.login.ui/pom.xml b/modules/org.wso2.stratos.apimgt.login.ui/pom.xml index ce1860b8ae..d72ea71a2f 100644 --- a/modules/org.wso2.stratos.apimgt.login.ui/pom.xml +++ b/modules/org.wso2.stratos.apimgt.login.ui/pom.xml @@ -26,7 +26,7 @@ 4.0.0 org.wso2.stratos.apimgt.login.ui - 2.2.0 + 2.2.1-SNAPSHOT bundle WSO2 AM - Login User Interface diff --git a/modules/p2-profile/product/pom.xml b/modules/p2-profile/product/pom.xml index 5161ac13b9..27f0458e85 100644 --- a/modules/p2-profile/product/pom.xml +++ b/modules/p2-profile/product/pom.xml @@ -268,6 +268,25 @@ + + 13-unpack-kernel-patch + test + + unpack + + + + + org.wso2.carbon + WSO2-CARBON-PATCH-4.2.0 + 0012 + zip + true + target + + + + @@ -393,7 +412,7 @@ org.jaggeryjs.modules:ws.feature:1.1.0 org.wso2.carbon.apimgt:org.wso2.carbon.apimgt.feature:${apimgt.feature.version} - org.wso2.am:org.wso2.stratos.apimgt.dashboard.ui.feature:${stratos.version} + org.wso2.am:org.wso2.stratos.apimgt.dashboard.ui.feature:${apimgt.stratos.version} org.wso2.carbon:org.wso2.carbon.registry.extensions.feature:4.2.1 @@ -765,7 +784,7 @@ org.wso2.stratos.apimgt.dashboard.ui.feature.group - ${stratos.version} + ${apimgt.stratos.version} org.wso2.carbon.event.server.feature.group @@ -1190,7 +1209,7 @@ org.wso2.stratos.apimgt.dashboard.ui.feature.group - ${stratos.version} + ${apimgt.stratos.version} org.wso2.carbon.event.server.feature.group @@ -1544,7 +1563,7 @@ org.wso2.stratos.apimgt.dashboard.ui.feature.group - ${stratos.version} + ${apimgt.stratos.version} org.wso2.carbon.event.server.feature.group @@ -1935,7 +1954,7 @@ org.wso2.stratos.apimgt.dashboard.ui.feature.group - ${stratos.version} + ${apimgt.stratos.version} org.wso2.carbon.event.server.feature.group @@ -2365,7 +2384,7 @@ org.wso2.stratos.apimgt.dashboard.ui.feature.group - ${stratos.version} + ${apimgt.stratos.version} org.wso2.carbon.event.server.feature.group @@ -2787,7 +2806,7 @@ org.wso2.stratos.apimgt.dashboard.ui.feature.group - ${stratos.version} + ${apimgt.stratos.version} org.wso2.carbon.event.server.feature.group diff --git a/nested-categories/gateway-manager/pom.xml b/nested-categories/gateway-manager/pom.xml index 60e92046f0..fca2b0648e 100644 --- a/nested-categories/gateway-manager/pom.xml +++ b/nested-categories/gateway-manager/pom.xml @@ -124,7 +124,7 @@ org.wso2.carbon.um.ws.service.server:4.2.2 org.wso2.carbon.user.mgt:4.2.3 org.wso2.carbon.xfer:${carbon.platform.version} - org.wso2.stratos.apimgt.dashboard.ui:${stratos.version} + org.wso2.stratos.apimgt.dashboard.ui:${apimgt.stratos.version} org.wso2.carbon.bam.message.tracer.handler:4.2.3 diff --git a/nested-categories/publisher/pom.xml b/nested-categories/publisher/pom.xml index 1938e27d9e..70a64b8819 100644 --- a/nested-categories/publisher/pom.xml +++ b/nested-categories/publisher/pom.xml @@ -107,7 +107,7 @@ org.wso2.carbon.user.mgt:4.2.3 org.wso2.carbon.webapp.mgt:4.2.2 org.wso2.carbon.xfer:${carbon.platform.version} - org.wso2.stratos.apimgt.dashboard.ui:${stratos.version} + org.wso2.stratos.apimgt.dashboard.ui:${apimgt.stratos.version} org.wso2.carbon.registry.contentsearch:4.2.2 org.apache.synapse.wso2:2.1.2-wso2v6 org.apache.synapse.transport.nhttp:2.1.2-wso2v6 diff --git a/nested-categories/store/pom.xml b/nested-categories/store/pom.xml index d2d2d563ab..36236ef29a 100644 --- a/nested-categories/store/pom.xml +++ b/nested-categories/store/pom.xml @@ -107,7 +107,7 @@ org.wso2.carbon.user.mgt:4.2.3 org.wso2.carbon.webapp.mgt:4.2.2 org.wso2.carbon.xfer:${carbon.platform.version} - org.wso2.stratos.apimgt.dashboard.ui:${stratos.version} + org.wso2.stratos.apimgt.dashboard.ui:${apimgt.stratos.version} org.wso2.carbon.registry.contentsearch:4.2.2 org.wso2.carbon.identity.oauth.common:4.2.3 org.apache.synapse.wso2:2.1.2-wso2v6 diff --git a/pom.xml b/pom.xml index 9814ac682e..9199d64b67 100644 --- a/pom.xml +++ b/pom.xml @@ -425,9 +425,9 @@ ${apimserver.version} - org.wso2.carbon + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.api - 1.2.3 + ${apimgt.api.version} org.codehaus.jettison.wso2 @@ -446,9 +446,9 @@ ${carbon.platform.version} - org.wso2.carbon + org.wso2.carbon.apimgt org.wso2.carbon.apimgt.hostobjects - 1.2.2 + ${apimgt.api.version} commons-digester @@ -775,7 +775,7 @@ 1.9.1-SNAPSHOT 1.2.5-SNAPSHOT 1.2.5-SNAPSHOT - 4.2.6 + 4.2.7-SNAPSHOT UTF-8 1.2.13 1.1.1 @@ -804,7 +804,7 @@ 1.2.1.wso2v1 1.6.1.wso2v10 2.2.5.wso2v1 - 2.2.0 + 2.2.1-SNAPSHOT 140 132 2.2.0.v201112011158