/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * 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.kie.workbench.common.screens.datasource.management.backend.core.wildfly; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.inject.Named; import javax.naming.InitialContext; import org.kie.workbench.common.screens.datasource.management.backend.core.DataSource; import org.kie.workbench.common.screens.datasource.management.backend.core.DataSourceProvider; import org.kie.workbench.common.screens.datasource.management.backend.integration.wildfly.WildflyDataSourceDef; import org.kie.workbench.common.screens.datasource.management.backend.integration.wildfly.WildflyDataSourceManagementClient; import org.kie.workbench.common.screens.datasource.management.model.DataSourceDef; import org.kie.workbench.common.screens.datasource.management.model.DataSourceDeploymentInfo; import org.kie.workbench.common.screens.datasource.management.model.DataSourceStatus; import org.kie.workbench.common.screens.datasource.management.model.DriverDeploymentInfo; import org.kie.workbench.common.screens.datasource.management.util.UUIDGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Wildly based implementation of a DataSourceProvider. */ @ApplicationScoped @Named(value = "WildflyDataSourceProvider") public class WildflyDataSourceProvider implements DataSourceProvider { private static final Logger logger = LoggerFactory.getLogger(WildflyDataSourceProvider.class); private WildflyDriverProvider driverProvider; private WildflyDataSourceManagementClient dataSourceMgmtClient = new WildflyDataSourceManagementClient(); private Map< String, WildlfyDataSource > managedDataSources = new HashMap<>(); private Map< String, WildlfyDataSource > unManagedDataSources = new HashMap<>(); public WildflyDataSourceProvider() { } @Inject public WildflyDataSourceProvider(WildflyDriverProvider driverProvider) { this.driverProvider = driverProvider; } /** * Gets the list of data source definitions for the currently defined data sources in the Wildfly server. * @return list with the definitions for the defined data sources. * @throws Exception exceptions may be thrown if e.g. communication with the Wildfly server fails, etc. */ @Override public List< DataSourceDef > getDeployments() throws Exception { List< WildflyDataSourceDef > dataSources; List< DataSourceDef > dataSourceDefs = new ArrayList<>(); DataSourceDef dataSourceDef; String dataSourceUuid; String driverUuid; dataSources = dataSourceMgmtClient.getDataSources(); for (WildflyDataSourceDef internalDef : dataSources) { dataSourceDef = new DataSourceDef(); try { dataSourceUuid = DeploymentIdGenerator.extractUuid(internalDef.getName()); } catch (Exception e) { dataSourceUuid = internalDef.getName(); } try { driverUuid = DeploymentIdGenerator.extractUuid(internalDef.getDriverName()); } catch (Exception e) { driverUuid = internalDef.getDriverName(); } dataSourceDef.setUuid(dataSourceUuid); dataSourceDef.setName(internalDef.getName()); dataSourceDef.setConnectionURL(internalDef.getConnectionURL()); dataSourceDef.setDriverUuid(driverUuid); dataSourceDef.setUser(internalDef.getUser()); dataSourceDef.setPassword(internalDef.getPassword()); dataSourceDefs.add(dataSourceDef); } return dataSourceDefs; } @Override public DataSourceDeploymentInfo deploy(DataSourceDef dataSourceDef) throws Exception { //This random identifiers calculation should be removed when WF supports deletion //of data sources without letting them published on server until next restart. String random = "_" + generateRandomUUID(); String deploymentId = DeploymentIdGenerator.generateDeploymentId(dataSourceDef) + random; String kieJndi = JndiNameGenerator.generateJNDIName(dataSourceDef); String deploymentJndi = kieJndi + random; DataSourceDeploymentInfo deploymentInfo = deploy(dataSourceDef, deploymentJndi, deploymentId); javax.sql.DataSource dataSource = (javax.sql.DataSource) jndiLookupDataSource(deploymentJndi); WildlfyDataSource wfDataSource = new WildlfyDataSource(dataSource, deploymentJndi); managedDataSources.put(deploymentId, wfDataSource); return deploymentInfo; } /** * protected for helping tests programming. */ protected String generateRandomUUID() { return UUIDGenerator.generateUUID(); } /** * Creates a data source in the Wildfly server. * @param dataSourceDef Data source definition to be created. * @param jndi jndi name to be use the Wildly server to bound the data source in the jndi context. * @return returns the deployment information for the created data source. * @throws Exception exceptions may be thrown if the data source couldn't be created. */ private DataSourceDeploymentInfo deploy(final DataSourceDef dataSourceDef, final String jndi, String deploymentId) throws Exception { DriverDeploymentInfo driverDeploymentInfo = driverProvider.getDeploymentInfo(dataSourceDef.getDriverUuid()); if (driverDeploymentInfo == null) { throw new Exception("Required driver: " + dataSourceDef.getDriverUuid() + " is not deployed."); } WildflyDataSourceDef wfDataSourceDef = buildWFDataSource(deploymentId, jndi, dataSourceDef, driverDeploymentInfo.getDriverDeploymentId()); dataSourceMgmtClient.createDataSource(wfDataSourceDef); return new DataSourceDeploymentInfo(deploymentId, true, dataSourceDef.getUuid(), jndi, false); } public DataSourceDeploymentInfo resync(DataSourceDef dataSourceDef, DataSourceDeploymentInfo deploymentInfo) throws Exception { javax.sql.DataSource dataSource = (javax.sql.DataSource) jndiLookupDataSource(deploymentInfo.getJndi()); WildlfyDataSource wfDataSource = new WildlfyDataSource(dataSource, deploymentInfo.getJndi()); managedDataSources.put(deploymentInfo.getDeploymentId(), wfDataSource); return deploymentInfo; } @Override public void undeploy(final DataSourceDeploymentInfo deploymentInfo) throws Exception { DataSourceDeploymentInfo currentDeploymentInfo = getDeploymentInfo(deploymentInfo.getUuid()); if (currentDeploymentInfo == null) { throw new Exception("DataSource: " + deploymentInfo.getUuid() + " is not deployed"); } dataSourceMgmtClient.deleteDataSource(currentDeploymentInfo.getDeploymentId()); managedDataSources.remove(currentDeploymentInfo.getDeploymentId()); } /** * Gets the deployment information about a data source definition. * @param uuid the data source definition identifier. * @return the deployment information for the data source definition of null if no data source has been created * with the given uuid. * @throws Exception exceptions may be thrown if e.g. communication with the Wildfly server fails, etc. */ public DataSourceDeploymentInfo getDeploymentInfo(final String uuid) throws Exception { for (DataSourceDeploymentInfo deploymentInfo : getDeploymentsInfo()) { if (uuid.equals(deploymentInfo.getUuid())) { return deploymentInfo; } } return null; } /** * Gets the deployment information for all the data sources currently defined on the Wildfly server. * @return a list with the deployment information for all the data sources. * @throws Exception exceptions may be thrown if e.g. communication with the Wildfly server fails, etc. */ public List< DataSourceDeploymentInfo > getDeploymentsInfo() throws Exception { List< WildflyDataSourceDef > dataSources = dataSourceMgmtClient.getDataSources(); List< DataSourceDeploymentInfo > result = new ArrayList<>(); DataSourceDeploymentInfo deploymentInfo; String uuid; WildlfyDataSource managedDataSource; boolean managed; String jndi; for (WildflyDataSourceDef internalDef : dataSources) { try { uuid = DeploymentIdGenerator.extractUuid(internalDef.getName()); } catch (Exception e) { uuid = internalDef.getName(); } managedDataSource = managedDataSources.get(internalDef.getName()); if (managedDataSource != null) { managed = true; jndi = managedDataSource.getExternalJndi(); } else { managed = false; jndi = internalDef.getJndi(); } deploymentInfo = new DataSourceDeploymentInfo(internalDef.getName(), managed, uuid, jndi, wasReferenced(internalDef.getName())); result.add(deploymentInfo); } return result; } @Override public DataSource lookupDataSource(DataSourceDeploymentInfo deploymentInfo) throws Exception { WildlfyDataSource dataSource = managedDataSources.get(deploymentInfo.getDeploymentId()); if (dataSource == null) { dataSource = unManagedDataSources.get(deploymentInfo.getDeploymentId()); } if (dataSource == null) { DataSourceDeploymentInfo refreshedDeploymentInfo = getDeploymentInfo(deploymentInfo.getUuid()); if (refreshedDeploymentInfo != null && refreshedDeploymentInfo.getJndi() != null) { javax.sql.DataSource sqlDataSource = (javax.sql.DataSource) jndiLookupDataSource(refreshedDeploymentInfo.getJndi()); if (sqlDataSource != null) { dataSource = new WildlfyDataSource(sqlDataSource, refreshedDeploymentInfo.getJndi()); unManagedDataSources.put(deploymentInfo.getDeploymentId(), dataSource); return dataSource; } } } if (dataSource != null) { if (dataSource.isNew()) { //first access to the data source dataSource.setStatus(DataSourceStatus.REFERENCED); } return dataSource; } else { throw new Exception("Data source for: " + deploymentInfo + " is not deployed in current system."); } } @Override public void loadConfig(Properties properties) { dataSourceMgmtClient.loadConfig(properties); driverProvider.loadConfig(properties); } @Override public void hasStarted() throws Exception { dataSourceMgmtClient.testConnection(); dataSourceMgmtClient.getDataSources(); } /** * protected for helping tests programming. */ protected Object jndiLookupDataSource(String jndi) { try { InitialContext context = new InitialContext(); return context.lookup(jndi); } catch (Exception e) { logger.warn("JNDI lookup failed for name: {}", jndi); return null; } } private WildflyDataSourceDef buildWFDataSource(String deploymentId, String jndi, DataSourceDef dataSourceDef, String driverDeploymentId) { WildflyDataSourceDef wfDataSourceDef = new WildflyDataSourceDef(); wfDataSourceDef.setName(deploymentId); wfDataSourceDef.setDriverName(driverDeploymentId); wfDataSourceDef.setJndi(jndi); wfDataSourceDef.setConnectionURL(dataSourceDef.getConnectionURL()); wfDataSourceDef.setUser(dataSourceDef.getUser()); wfDataSourceDef.setPassword(dataSourceDef.getPassword()); wfDataSourceDef.setUseJTA(true); return wfDataSourceDef; } private boolean wasReferenced(String deploymentId) { WildlfyDataSource dataSource = managedDataSources.get(deploymentId); if (dataSource == null) { dataSource = unManagedDataSources.get(deploymentId); } if (dataSource != null) { return dataSource.isReferenced(); } return false; } public void setDataSourceMgmtClient(WildflyDataSourceManagementClient dataSourceMgmtClient) { this.dataSourceMgmtClient = dataSourceMgmtClient; } }