/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.runtime.client.admin;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.wst.server.core.IServer;
import org.jboss.dmr.ModelNode;
import org.jboss.ide.eclipse.as.core.server.v7.management.AS7ManagementDetails;
import org.jboss.ide.eclipse.as.management.core.IAS7ManagementDetails;
import org.jboss.ide.eclipse.as.management.core.JBoss7ManagerUtil;
import org.jboss.ide.eclipse.as.management.core.ModelDescriptionConstants;
import org.teiid.adminapi.Admin;
import org.teiid.adminapi.PropertyDefinition;
import org.teiid.adminapi.Translator;
import org.teiid.adminapi.VDB;
import org.teiid.core.util.ArgCheck;
import org.teiid.designer.annotation.AnnotationUtils;
import org.teiid.designer.annotation.Removed;
import org.teiid.designer.runtime.spi.EventManager;
import org.teiid.designer.runtime.spi.ExecutionConfigurationEvent;
import org.teiid.designer.runtime.spi.IExecutionAdmin;
import org.teiid.designer.runtime.spi.ITeiidConnectionInfo;
import org.teiid.designer.runtime.spi.ITeiidDataSource;
import org.teiid.designer.runtime.spi.ITeiidJdbcInfo;
import org.teiid.designer.runtime.spi.ITeiidServer;
import org.teiid.designer.runtime.spi.ITeiidTranslator;
import org.teiid.designer.runtime.spi.ITeiidTranslator.TranslatorPropertyType;
import org.teiid.designer.runtime.spi.ITeiidVdb;
import org.teiid.designer.runtime.spi.TeiidExecutionException;
import org.teiid.designer.runtime.spi.TeiidPropertyDefinition;
import org.teiid.designer.runtime.version.spi.ITeiidServerVersion;
import org.teiid.designer.runtime.version.spi.TeiidServerVersion.Version;
import org.teiid.jdbc.TeiidDriver;
import org.teiid.runtime.client.Messages;
import org.teiid.runtime.client.TeiidRuntimePlugin;
/**
*
*
* @since 8.0
*/
public class ExecutionAdmin implements IExecutionAdmin {
private static String PLUGIN_ID = "org.teiid.runtime.client"; //$NON-NLS-1$
private static String DYNAMIC_VDB_SUFFIX = "-vdb.xml"; //$NON-NLS-1$
private static int VDB_LOADING_TIMEOUT_SEC = 300;
private final Admin admin;
protected Map<String, ITeiidTranslator> translatorByNameMap;
protected Collection<String> dataSourceNames;
protected Map<String, ITeiidDataSource> dataSourceByNameMap;
protected Set<String> dataSourceTypeNames;
private final EventManager eventManager;
private final ITeiidServer teiidServer;
private final AdminSpec adminSpec;
private Map<String, ITeiidVdb> teiidVdbs;
private final ModelConnectionMatcher connectionMatcher;
private boolean loaded = false;
private boolean refreshing = false;
/**
* Constructor used for testing purposes only.
*
* @param admin the associated Teiid Admin API (never <code>null</code>)
* @param teiidServer the server this admin belongs to (never <code>null</code>)
* @throws Exception if there is a problem connecting the server
*/
ExecutionAdmin(Admin admin, ITeiidServer teiidServer) throws Exception {
ArgCheck.isNotNull(admin, "admin"); //$NON-NLS-1$
ArgCheck.isNotNull(teiidServer, "server"); //$NON-NLS-1$
this.admin = admin;
this.teiidServer = teiidServer;
this.adminSpec = AdminSpec.getInstance(teiidServer.getServerVersion());
this.eventManager = teiidServer.getEventManager();
this.connectionMatcher = new ModelConnectionMatcher();
init();
}
/**
* Default Constructor
*
* @param teiidServer the server this admin belongs to (never <code>null</code>)
*
* @throws Exception if there is a problem connecting the server
*/
public ExecutionAdmin(ITeiidServer teiidServer) throws Exception {
ArgCheck.isNotNull(teiidServer, "server"); //$NON-NLS-1$
this.adminSpec = AdminSpec.getInstance(teiidServer.getServerVersion());
this.admin = adminSpec.createAdmin(teiidServer);
ArgCheck.isNotNull(admin, "admin"); //$NON-NLS-1$
this.teiidServer = teiidServer;
this.eventManager = teiidServer.getEventManager();
this.connectionMatcher = new ModelConnectionMatcher();
init();
}
private boolean isLessThanTeiidEight() {
ITeiidServerVersion minVersion = teiidServer.getServerVersion().getMinimumVersion();
return minVersion.isLessThan(Version.TEIID_8_0);
}
private boolean isLessThanTeiidEightSeven() {
ITeiidServerVersion minVersion = teiidServer.getServerVersion().getMinimumVersion();
return minVersion.isLessThan(Version.TEIID_8_7);
}
@Override
public boolean dataSourceExists( String name ) {
// Check if exists, return false
if (this.dataSourceNames.contains(name)) {
return true;
}
return false;
}
@Override
public void deleteDataSource( String dsName ) throws Exception {
// Check if exists, return false
if (this.dataSourceNames.contains(dsName)) {
this.admin.deleteDataSource(dsName);
ITeiidDataSource tds = this.dataSourceByNameMap.get(dsName);
refreshDataSources();
if (tds != null) {
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createRemoveDataSourceEvent(tds));
}
}
}
@Override
public void deployVdb( IFile vdbFile ) throws Exception {
deployVdb(vdbFile, "1");
}
@Override
public void deployVdb( IFile vdbFile, String version) throws Exception {
ArgCheck.isNotNull(vdbFile, "vdbFile"); //$NON-NLS-1$
String vdbDeploymentName = vdbFile.getFullPath().lastSegment();
String vdbName = vdbFile.getFullPath().removeFileExtension().lastSegment();
// For Teiid Version less than 8.7, do explicit undeploy (TEIID-2873)
if(isLessThanTeiidEightSeven()) {
undeployVdb(vdbName);
}
String vdbVersion = "1";
if( version != null) {
vdbVersion = version;
}
doDeployVdb(vdbDeploymentName, getVdbName(vdbName), vdbVersion, vdbFile.getContents());
}
@Override
public void deployDynamicVdb( String deploymentName, InputStream inStream ) throws Exception {
ArgCheck.isNotNull(deploymentName, "deploymentName"); //$NON-NLS-1$
ArgCheck.isNotNull(inStream, "inStream"); //$NON-NLS-1$
// Check dynamic VDB deployment name
if(!deploymentName.endsWith(DYNAMIC_VDB_SUFFIX)) {
throw new Exception(Messages.getString(Messages.ExecutionAdmin.dynamicVdbInvalidName, deploymentName));
}
// Get VDB name
String vdbName = deploymentName.substring(0, deploymentName.indexOf(DYNAMIC_VDB_SUFFIX));
// For Teiid Version less than 8.7, do explicit undeploy (TEIID-2873)
if(isLessThanTeiidEightSeven()) {
undeployDynamicVdb(vdbName);
}
// Deploy the VDB
// TODO: Dont assume vdbVersion
doDeployVdb(deploymentName,vdbName,"1",inStream);
}
private void doDeployVdb(String deploymentName, String vdbName, String vdbVersion, InputStream inStream) throws Exception {
adminSpec.deploy(admin, deploymentName, inStream);
// Give a 0.5 sec pause for the VDB to finish loading metadata.
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
// Refresh VDBs list
refreshVDBs();
// TODO should get version from vdbFile
VDB vdb = admin.getVDB(vdbName, vdbVersion);
// If the VDB is still loading, refresh again and potentially start refresh job
if(vdb.getStatus().equals(adminSpec.getLoadingVDBStatus()) && vdb.getValidityErrors().isEmpty()) {
// Give a 0.5 sec pause for the VDB to finish loading metadata.
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
// Refresh again to update vdb states
refreshVDBs();
vdb = admin.getVDB(vdbName, vdbVersion);
// Determine if still loading, if so start refresh job. User will get dialog that the
// vdb is still loading - and try again in a few seconds
if(vdb.getStatus().equals(adminSpec.getLoadingVDBStatus()) && vdb.getValidityErrors().isEmpty()) {
final Job refreshVDBsJob = new RefreshVDBsJob(vdbName);
refreshVDBsJob.schedule();
}
}
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createDeployVDBEvent(vdb.getName()));
}
private String getVdbName(String originalVdbName) throws Exception {
String vdbName = originalVdbName;
int firstIndex = vdbName.indexOf('.');
int lastIndex = vdbName.lastIndexOf('.');
if (firstIndex != -1) {
if (firstIndex != lastIndex) {
throw new Exception(Messages.getString(Messages.ExecutionAdmin.invalidVdbName, originalVdbName));
}
vdbName = vdbName.substring(0, firstIndex);
}
return vdbName;
}
@Override
public String getSchema(String vdbName, String vdbVersion, String modelName) throws Exception {
return admin.getSchema(vdbName, vdbVersion, modelName, null, null);
}
@Override
public void disconnect() {
//
this.admin.close();
this.translatorByNameMap = new HashMap<String, ITeiidTranslator>();
this.dataSourceNames = new ArrayList<String>();
this.dataSourceByNameMap = new HashMap<String, ITeiidDataSource>();
this.dataSourceTypeNames = new HashSet<String>();
this.teiidVdbs = new HashMap<String, ITeiidVdb>();
}
@Override
public ITeiidDataSource getDataSource(String name) {
return this.dataSourceByNameMap.get(name);
}
@Override
public Collection<ITeiidDataSource> getDataSources() {
return this.dataSourceByNameMap.values();
}
@Override
public Set<String> getDataSourceTypeNames() {
return this.dataSourceTypeNames;
}
/**
* @return the event manager (never <code>null</code>)
*/
public EventManager getEventManager() {
return this.eventManager;
}
@Override
public ITeiidDataSource getOrCreateDataSource( String displayName,
String dsName,
String typeName,
Properties properties ) throws Exception {
ArgCheck.isNotEmpty(displayName, "displayName"); //$NON-NLS-1$
ArgCheck.isNotEmpty(dsName, "dsName"); //$NON-NLS-1$
ArgCheck.isNotEmpty(typeName, "typeName"); //$NON-NLS-1$
ArgCheck.isNotEmpty(properties, "properties"); //$NON-NLS-1$
// Check if exists, return false
if (dataSourceExists(dsName)) {
ITeiidDataSource tds = this.dataSourceByNameMap.get(dsName);
if (tds != null) {
return tds;
}
}
// For JDBC types, find the matching installed driver. This is done currently by matching
// the profile driver classname to the installed driver classname
String connProfileDriverClass = properties.getProperty("driver-class"); //$NON-NLS-1$
if("connector-jdbc".equals(typeName)) { //$NON-NLS-1$
// List of driver jars on the connection profile
String jarList = properties.getProperty("jarList"); //$NON-NLS-1$
// Get first driver name with the driver class that matches the connection profile
String dsNameMatch = getDSMatchForDriverClass(connProfileDriverClass);
// If a matching datasource was found, set typename
if(dsNameMatch!=null) {
typeName=dsNameMatch;
// No matching datasource, attempt to deploy the driver if jarList is populated.
} else if(jarList!=null && jarList.trim().length()>0) {
// Try to deploy the jars
deployJars(this.admin,jarList);
refresh();
// Retry the name match after deployment.
dsNameMatch = getDSMatchForDriverClass(connProfileDriverClass);
if(dsNameMatch!=null) {
typeName=dsNameMatch;
}
}
}
// Verify the "typeName" exists.
if (!this.dataSourceTypeNames.contains(typeName)) {
if("connector-jdbc".equals(typeName)) { //$NON-NLS-1$
throw new TeiidExecutionException(
ITeiidDataSource.ERROR_CODES.JDBC_DRIVER_SOURCE_NOT_FOUND,
Messages.getString(Messages.ExecutionAdmin.jdbcSourceForClassNameNotFound, connProfileDriverClass, getServer()));
} else {
throw new TeiidExecutionException(
ITeiidDataSource.ERROR_CODES.DATA_SOURCE_TYPE_DOES_NOT_EXIST_ON_SERVER,
Messages.getString(Messages.ExecutionAdmin.dataSourceTypeDoesNotExist, typeName, getServer()));
}
}
this.admin.createDataSource(dsName, typeName, properties);
// call admin.refresh() to clear cached resource info
this.admin.refresh();
refreshDataSources();
// Check that local name list contains new dsName
ITeiidDataSource tds = this.dataSourceByNameMap.get(dsName);
if( tds != null ) {
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createAddDataSourceEvent(tds));
return tds;
}
// We shouldn't get here if data source was created
throw new TeiidExecutionException(
ITeiidDataSource.ERROR_CODES.DATA_SOURCE_COULD_NOT_BE_CREATED,
Messages.getString(Messages.ExecutionAdmin.errorCreatingDataSource, dsName, typeName));
}
/**
* Look for an installed driver that has the driverClass which matches the supplied driverClass name.
*
* @param requestDriverClass the driver class to match
* @return the name of the matching driver, null if not found
*/
private String getDSMatchForDriverClass(String requestDriverClass) throws Exception {
if (requestDriverClass == null)
return null;
if (!getServer().isParentConnected())
return null;
ModelNode request = new ModelNode();
request.get(ModelDescriptionConstants.OP).set("installed-drivers-list"); //$NON-NLS-1$
ModelNode address = new ModelNode();
address.add(ModelDescriptionConstants.SUBSYSTEM, "datasources"); //$NON-NLS-1$
request.get(ModelDescriptionConstants.OP_ADDR).set(address);
try {
String requestString = request.toJSONString(true);
IServer parentServer = getServer().getParent();
//
// Add the timeout to a properties map
//
int timeout = teiidServer.getParentRequestTimeout();
Map<String, Object> props = new HashMap<String, Object>();
props.put(IAS7ManagementDetails.PROPERTY_TIMEOUT, timeout);
AS7ManagementDetails as7ManagementDetails = new AS7ManagementDetails(parentServer, props);
String resultString = JBoss7ManagerUtil.getService(parentServer).execute(as7ManagementDetails, requestString);
ModelNode operationResult = ModelNode.fromJSONString(resultString);
List<ModelNode> driverList = operationResult.asList();
for (ModelNode driver : driverList) {
String driverClassName = driver.get("driver-class-name").asString(); //$NON-NLS-1$
String driverName = driver.get("driver-name").asString(); //$NON-NLS-1$
if (requestDriverClass.equalsIgnoreCase(driverClassName)) return driverName;
}
} catch (Exception ex) {
// Failed to get mapping
TeiidRuntimePlugin.logError(getClass().getSimpleName(), ex, Messages.getString(Messages.ExecutionAdmin.failedToGetDriverMappings, requestDriverClass));
}
return null;
}
/*
* Deploy all jars in the supplied jarList
* @param admin the Admin instance
* @param jarList the colon-separated list of jar path locations
*/
private void deployJars(Admin admin, String jarList) {
// Path Entries are separated by the file system path separator (WINDOWS = ';', LINUX = ':')
String splitter = "[" + File.pathSeparatorChar + "]"; //$NON-NLS-1$ //$NON-NLS-2$
String[] jarPathStrs = jarList.split(splitter);
// Attempt to deploy each jar
for(String jarPathStr: jarPathStrs) {
File theFile = new File(jarPathStr);
if(theFile.exists()) {
if(theFile.canRead()) {
String fileName = theFile.getName();
InputStream iStream = null;
try {
iStream = new FileInputStream(theFile);
} catch (FileNotFoundException ex) {
TeiidRuntimePlugin.logError(getClass().getSimpleName(), ex, Messages.getString(Messages.ExecutionAdmin.jarDeploymentJarNotFound, theFile.getPath()));
continue;
}
try {
adminSpec.deploy(admin, fileName, iStream);
// call admin.refresh() to clear cached resource info
this.admin.refresh();
} catch (Exception ex) {
// Jar deployment failed
TeiidRuntimePlugin.logError(getClass().getSimpleName(), ex, Messages.getString(Messages.ExecutionAdmin.jarDeploymentFailed, theFile.getPath()));
}
if( iStream != null ) {
try {
iStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} else {
// Could not read the file
TeiidRuntimePlugin.logError(getClass().getSimpleName(), Messages.getString(Messages.ExecutionAdmin.jarDeploymentJarNotReadable, theFile.getPath()));
}
} else {
// The file was not found
TeiidRuntimePlugin.logError(getClass().getSimpleName(), Messages.getString(Messages.ExecutionAdmin.jarDeploymentJarNotFound, theFile.getPath()));
}
}
}
@Override
public void deployDriver(File jarOrRarFile) throws Exception {
if(jarOrRarFile.exists()) {
if(jarOrRarFile.canRead()) {
String fileName = jarOrRarFile.getName();
InputStream iStream = null;
try {
iStream = new FileInputStream(jarOrRarFile);
} catch (FileNotFoundException ex) {
TeiidRuntimePlugin.logError(getClass().getSimpleName(), ex, Messages.getString(Messages.ExecutionAdmin.jarDeploymentJarNotFound, jarOrRarFile.getPath()));
throw ex;
}
try {
adminSpec.deploy(admin, fileName, iStream);
// call admin.refresh() to clear cached resource info
this.admin.refresh();
refreshDataSourceTypes();
} catch (Exception ex) {
// Jar deployment failed
TeiidRuntimePlugin.logError(getClass().getSimpleName(), ex, Messages.getString(Messages.ExecutionAdmin.jarDeploymentFailed, jarOrRarFile.getPath()));
throw ex;
} finally {
if( iStream != null ) {
iStream.close();
}
}
} else {
// Could not read the file
TeiidRuntimePlugin.logError(getClass().getSimpleName(), Messages.getString(Messages.ExecutionAdmin.jarDeploymentJarNotReadable, jarOrRarFile.getPath()));
}
} else {
// The file was not found
TeiidRuntimePlugin.logError(getClass().getSimpleName(), Messages.getString(Messages.ExecutionAdmin.jarDeploymentJarNotFound, jarOrRarFile.getPath()));
}
}
/**
* @return the server who owns this admin object (never <code>null</code>)
*/
public ITeiidServer getServer() {
return this.teiidServer;
}
@Override
public ITeiidTranslator getTranslator( String name ) {
ArgCheck.isNotEmpty(name, "name"); //$NON-NLS-1$
return this.translatorByNameMap.get(name);
}
@Override
public Collection<ITeiidTranslator> getTranslators() {
return Collections.unmodifiableCollection(translatorByNameMap.values());
}
@Override
public Set<String> getDataSourceTemplateNames() throws Exception {
return this.dataSourceTypeNames;
}
@SuppressWarnings("unchecked")
@Override
public Collection<TeiidPropertyDefinition> getTemplatePropertyDefns(String templateName) throws Exception {
Collection<? extends PropertyDefinition> propDefs = this.admin.getTemplatePropertyDefinitions(templateName);
Collection<TeiidPropertyDefinition> teiidPropDefns = new ArrayList<TeiidPropertyDefinition>();
for (PropertyDefinition propDefn : propDefs) {
TeiidPropertyDefinition teiidPropertyDefn = new TeiidPropertyDefinition();
teiidPropertyDefn.setName(propDefn.getName());
teiidPropertyDefn.setDisplayName(propDefn.getDisplayName());
teiidPropertyDefn.setDescription(propDefn.getDescription());
teiidPropertyDefn.setPropertyTypeClassName(propDefn.getPropertyTypeClassName());
teiidPropertyDefn.setDefaultValue(propDefn.getDefaultValue());
teiidPropertyDefn.setAllowedValues(propDefn.getAllowedValues());
teiidPropertyDefn.setModifiable(propDefn.isModifiable());
teiidPropertyDefn.setConstrainedToAllowedValues(propDefn.isConstrainedToAllowedValues());
teiidPropertyDefn.setAdvanced(propDefn.isAdvanced());
teiidPropertyDefn.setRequired(propDefn.isRequired());
teiidPropertyDefn.setMasked(propDefn.isMasked());
teiidPropDefns.add(teiidPropertyDefn);
}
return teiidPropDefns;
}
/*
* (non-Javadoc)
* @see org.teiid.designer.runtime.spi.IExecutionAdmin#getDataSourceProperties(java.lang.String)
*/
@Override
public Properties getDataSourceProperties(String name) throws Exception {
if (isLessThanTeiidEight()) {
// Teiid 7.7.x does not support
return null;
}
return getDataSource(name).getProperties();
}
@Override
public ITeiidVdb getVdb( String name ) {
ArgCheck.isNotEmpty(name, "name"); //$NON-NLS-1$
return teiidVdbs.get(name);
}
@Override
public boolean hasVdb(String name) throws Exception {
return getVdb(name) != null;
}
@Override
public boolean isVdbActive(String vdbName) throws Exception {
if (! hasVdb(vdbName))
return false;
return getVdb(vdbName).isActive();
}
@Override
public boolean isVdbLoading(String vdbName) throws Exception {
if (! hasVdb(vdbName))
return false;
return getVdb(vdbName).isLoading();
}
@Override
public boolean isRefreshing() throws Exception {
return this.refreshing;
}
@Override
public boolean hasVdbFailed(String vdbName) throws Exception {
if (! hasVdb(vdbName))
return false;
return getVdb(vdbName).hasFailed();
}
@Override
public boolean wasVdbRemoved(String vdbName) throws Exception {
if (! hasVdb(vdbName))
return false;
return getVdb(vdbName).wasRemoved();
}
@Override
public List<String> retrieveVdbValidityErrors(String vdbName) throws Exception {
if (! hasVdb(vdbName))
return Collections.emptyList();
return getVdb(vdbName).getValidityErrors();
}
@Override
public Collection<ITeiidVdb> getVdbs() {
return Collections.unmodifiableCollection(teiidVdbs.values());
}
private void init() throws Exception {
this.translatorByNameMap = new HashMap<String, ITeiidTranslator>();
this.dataSourceNames = new ArrayList<String>();
this.dataSourceByNameMap = new HashMap<String, ITeiidDataSource>();
this.dataSourceTypeNames = new HashSet<String>();
refreshVDBs();
}
private void internalSetPropertyValue( ITeiidTranslator translator,
String propName,
String value,
TranslatorPropertyType type,
boolean notify ) throws Exception {
if (translator.isValidPropertyValue(propName, value, type) == null) {
String oldValue = translator.getPropertyValue(propName, type);
// don't set if value has not changed
if (oldValue == null) {
if (value == null) return;
} else if (oldValue.equals(value)) return;
if (notify) {
// TODO: Will we ever update Translator properties in TEIID Server?
// this.eventManager.notifyListeners(ExecutionConfigurationEvent.createUpdateConnectorEvent(translator));
}
} else {
throw new Exception(Messages.getString(Messages.ExecutionAdmin.invalidPropertyValue, value, propName));
}
}
/**
* @throws Exception if refreshing admin connection fails
*/
@Override
public void connect() throws Exception {
if (!this.loaded) {
refresh();
this.loaded = true;
}
}
/**
* Refreshes the cached lists and maps of current Teiid objects
* @throws Exception if refreshing admin connection fails
*/
public void refresh() throws Exception {
refreshing = true;
// Clears any cached data source or translator info prior to reloading
this.admin.refresh();
// populate data source type names
Exception resultException = null;
try {
try {
refreshDataSourceTypes();
} catch (Exception ex) {
resultException = ex;
}
try {
refreshDataSources();
} catch (Exception ex) {
resultException = ex;
}
// populate translator map
try {
refreshTranslators();
} catch (Exception ex) {
resultException = ex;
}
// populate VDBs and source bindings
try {
refreshVDBs();
} catch (Exception ex) {
resultException = ex;
}
} finally {
// Wrapped in try-catch so that any exception will still set refreshLoaded = true;
refreshing = false;
}
if(resultException!=null) throw resultException;
// notify listeners
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createServerRefreshEvent(this.teiidServer));
}
protected void refreshDataSources() throws Exception {
this.dataSourceByNameMap.clear();
this.dataSourceNames = new ArrayList<String>(this.admin.getDataSourceNames());
Collection<ITeiidDataSource> tdsList = connectionMatcher.findTeiidDataSources(this.dataSourceNames);
for (ITeiidDataSource ds : tdsList) {
if (!isLessThanTeiidEight()) {
/* Not done in Teiid 7.7 */
// Get Properties for the source
Properties dsProps = this.admin.getDataSource(ds.getName());
// Transfer properties to the ITeiidDataSource
ds.getProperties().clear();
ds.getProperties().putAll(dsProps);
}
// put ds into map
this.dataSourceByNameMap.put(ds.getName(), ds);
}
}
/**
* Refreshes the local collection of Translators on the referenced Teiid server.
*
* @param translators
* @throws Exception
*/
protected void refreshTranslators() throws Exception {
Collection<? extends Translator> translators = this.admin.getTranslators();
for (Translator translator : translators ) {
if (translator.getName() != null) {
TeiidTranslator teiidTranslator = null;
if( teiidServer.getServerVersion().isLessThan(Version.TEIID_8_6)) {
Collection<? extends PropertyDefinition> propDefs = this.admin.getTemplatePropertyDefinitions(translator.getName());
teiidTranslator = new TeiidTranslator(translator, propDefs, teiidServer);
this.translatorByNameMap.put(translator.getName(), teiidTranslator);
} else if( teiidServer.getServerVersion().isLessThan(Version.TEIID_8_7)) {
@SuppressWarnings("deprecation")
Collection<? extends PropertyDefinition> propDefs = this.admin.getTranslatorPropertyDefinitions(translator.getName());
teiidTranslator = new TeiidTranslator(translator, propDefs, teiidServer);
this.translatorByNameMap.put(translator.getName(), teiidTranslator);
} else { // TEIID SERVER VERSION 8.7 AND HIGHER
Collection<? extends PropertyDefinition> propDefs =
this.admin.getTranslatorPropertyDefinitions(translator.getName(), Admin.TranlatorPropertyType.OVERRIDE);
Collection<? extends PropertyDefinition> importPropDefs =
this.admin.getTranslatorPropertyDefinitions(translator.getName(), Admin.TranlatorPropertyType.IMPORT);
Collection<? extends PropertyDefinition> extPropDefs =
this.admin.getTranslatorPropertyDefinitions(translator.getName(), Admin.TranlatorPropertyType.EXTENSION_METADATA);
teiidTranslator = new TeiidTranslator(translator, propDefs, importPropDefs, extPropDefs, teiidServer);
this.translatorByNameMap.put(translator.getName(), teiidTranslator);
}
}
}
}
protected void refreshVDBs() throws Exception {
Collection<? extends VDB> vdbs = Collections.unmodifiableCollection(this.admin.getVDBs());
teiidVdbs = new HashMap<String, ITeiidVdb>();
for (VDB vdb : vdbs) {
teiidVdbs.put(vdb.getName(), new TeiidVdb(vdb, teiidServer));
}
}
protected void refreshDataSourceTypes() throws Exception {
// populate data source type names set
this.dataSourceTypeNames = new HashSet<String>(this.admin.getDataSourceTemplateNames());
}
/**
* @param translator the translator whose properties are being changed (never <code>null</code>)
* @param changedProperties a collection of properties that have changed (never <code>null</code> or empty)
* @param type the translator property type
* @throws Exception if there is a problem changing the properties
* @since 7.0
*/
public void setProperties( ITeiidTranslator translator,
Properties changedProperties,
TranslatorPropertyType type) throws Exception {
ArgCheck.isNotNull(translator, "translator"); //$NON-NLS-1$
ArgCheck.isNotNull(changedProperties, "changedProperties"); //$NON-NLS-1$
ArgCheck.isNotEmpty(changedProperties.entrySet(), "changedProperties"); //$NON-NLS-1$
if (changedProperties.size() == 1) {
String name = changedProperties.stringPropertyNames().iterator().next();
setPropertyValue(translator, name, changedProperties.getProperty(name), type);
} else {
for (String name : changedProperties.stringPropertyNames()) {
internalSetPropertyValue(translator, name, changedProperties.getProperty(name), type, false);
}
// this.eventManager.notifyListeners(ExecutionConfigurationEvent.createUpdateConnectorEvent(translator));
}
}
/**
* @param translator the translator whose property is being changed (never <code>null</code>)
* @param propName the name of the property being changed (never <code>null</code> or empty)
* @param value the new value
* @param type the translator property type
* @throws Exception if there is a problem setting the property
* @since 7.0
*/
public void setPropertyValue( ITeiidTranslator translator,
String propName,
String value,
TranslatorPropertyType type) throws Exception {
ArgCheck.isNotNull(translator, "translator"); //$NON-NLS-1$
ArgCheck.isNotEmpty(propName, "propName"); //$NON-NLS-1$
ArgCheck.isNotEmpty(value, "value"); //$NON-NLS-1$
internalSetPropertyValue(translator, propName, value, type, true);
}
@Override
public void undeployVdb( String vdbName) throws Exception {
ITeiidVdb vdb = getVdb(vdbName);
if(vdb!=null) {
String deploymentName = vdb.getPropertyValue("deployment-name"); //$NON-NLS-1$
if( deploymentName != null ) {
adminSpec.undeploy(admin, deploymentName, vdb.getVersion());
} else {
throw new Exception(Messages.getString(Messages.ExecutionAdmin.cannotUndeployVdbNoDeploymentName, vdbName));
}
}
vdb = getVdb(vdbName);
refreshVDBs();
if (vdb != null) {
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createUnDeployVDBEvent(vdb.getName()));
}
}
@Override
public void undeployDynamicVdb( String vdbName) throws Exception {
ITeiidVdb vdb = getVdb(vdbName);
if(vdb!=null) {
adminSpec.undeploy(admin, appendDynamicVdbSuffix(vdbName), vdb.getVersion());
}
vdb = getVdb(vdbName);
refreshVDBs();
if (vdb == null) {
} else {
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createUnDeployVDBEvent(vdb.getName()));
}
}
/**
*
* @param vdbName the vdb name
* @param vdbVersion the vdb version
* @throws Exception if undeploying vdb fails
*/
public void undeployVdb( String vdbName, String vdbVersion ) throws Exception {
adminSpec.undeploy(admin, appendVdbExtension(vdbName), vdbVersion);
ITeiidVdb vdb = getVdb(vdbName);
refreshVDBs();
if (vdb == null) {
} else {
this.eventManager.notifyListeners(ExecutionConfigurationEvent.createUnDeployVDBEvent(vdb.getName()));
}
}
/**
* Append the vdb file extension to the vdb name
* if not already appended.
*
* @param vdbName
* @return
*/
private String appendVdbExtension(String vdbName) {
if (vdbName.endsWith(ITeiidVdb.VDB_EXTENSION))
return vdbName;
return vdbName + ITeiidVdb.VDB_DOT_EXTENSION;
}
/**
* Append the suffix for dynamic VDB to the vdb name if not already appended.
*
* @param vdbName
* @return
*/
private String appendDynamicVdbSuffix(String vdbName) {
if (vdbName.endsWith(ITeiidVdb.DYNAMIC_VDB_SUFFIX))
return vdbName;
return vdbName + ITeiidVdb.DYNAMIC_VDB_SUFFIX;
}
@Override
public IStatus ping(PingType pingType) {
String msg = Messages.getString(Messages.ExecutionAdmin.cannotConnectToServer, teiidServer.getTeiidAdminInfo().getUsername());
try {
if (this.admin == null)
throw new Exception(msg);
switch(pingType) {
case JDBC:
return pingJdbc();
case ADMIN:
default:
return pingAdmin();
}
}
catch (Exception ex) {
return new Status(IStatus.ERROR, PLUGIN_ID, msg, ex);
}
}
private IStatus pingAdmin() throws Exception {
admin.getSessions();
return Status.OK_STATUS;
}
private IStatus pingJdbc() {
String host = teiidServer.getHost();
ITeiidJdbcInfo teiidJdbcInfo = teiidServer.getTeiidJdbcInfo();
String protocol = ITeiidConnectionInfo.MM;
if (teiidJdbcInfo.isSecure())
protocol = ITeiidConnectionInfo.MMS;
Connection teiidJdbcConnection = null;
String url = "jdbc:teiid:ping@" + protocol + host + ':' + teiidJdbcInfo.getPort(); //$NON-NLS-1$
try {
adminSpec.deploy(admin, PING_VDB, new ByteArrayInputStream(adminSpec.getTestVDB().getBytes()));
try{
String urlAndCredentials = url + ";"; //$NON-NLS-1$
TeiidDriver teiidDriver = TeiidDriver.getInstance();
teiidDriver.setTeiidVersion(teiidServer.getServerVersion());
Properties props = new Properties();
props.put("user", teiidJdbcInfo.getUsername());
props.put("password", teiidJdbcInfo.getPassword());
teiidJdbcConnection = teiidDriver.connect(urlAndCredentials, props);
//pass
} catch(SQLException ex){
String msg = Messages.getString(Messages.ExecutionAdmin.serverDeployUndeployProblemPingingTeiidJdbc, url);
return new Status(IStatus.ERROR, PLUGIN_ID, msg, ex);
} finally {
adminSpec.undeploy(admin, PING_VDB, "1");
if( teiidJdbcConnection != null ) {
teiidJdbcConnection.close();
}
}
} catch (Exception ex) {
String msg = Messages.getString(Messages.ExecutionAdmin.serverDeployUndeployProblemPingingTeiidJdbc, url);
return new Status(IStatus.ERROR, PLUGIN_ID, msg, ex);
}
return Status.OK_STATUS;
}
@Override
public String getAdminDriverPath() {
return Admin.class.getProtectionDomain().getCodeSource().getLocation().getFile();
}
@Override
public Driver getTeiidDriver(String driverClass) throws Exception {
Class<?> klazz = getClass().getClassLoader().loadClass(driverClass);
Object driver = klazz.newInstance();
if (driver instanceof Driver)
return (Driver) driver;
throw new Exception(Messages.getString(Messages.ExecutionAdmin.cannotLoadDriverClass, driverClass));
}
@Override
@Deprecated
@Removed(Version.TEIID_8_0)
public void mergeVdbs( String sourceVdbName, int sourceVdbVersion,
String targetVdbName, int targetVdbVersion ) throws Exception {
if (!AnnotationUtils.isApplicable(getClass().getMethod("mergeVdbs", String.class, int.class, String.class, int.class), getServer().getServerVersion())) //$NON-NLS-1$
throw new UnsupportedOperationException(Messages.getString(Messages.ExecutionAdmin.mergeVdbUnsupported));
admin.mergeVDBs(sourceVdbName, sourceVdbVersion, targetVdbName, targetVdbVersion);
}
/**
* Executes VDB refresh when a VDB is loading - as a background job.
*/
class RefreshVDBsJob extends Job {
String vdbName;
/**
* RefreshVDBsJob constructor
* @param vdbName the name of the VDB to monitor
*/
public RefreshVDBsJob(String vdbName ) {
super("VDB Refresh"); //$NON-NLS-1$
this.vdbName = vdbName;
setSystem(false);
setUser(true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run( IProgressMonitor monitor ) {
monitor.beginTask("VDB Refresh", //$NON-NLS-1$
IProgressMonitor.UNKNOWN);
try {
waitForVDBLoad(this.vdbName);
} catch (Exception ex) {
}
monitor.done();
return Status.OK_STATUS;
}
/*
* Wait for the VDB to finish loading. Will check status every 5 secs and return when the VDB is loaded.
* If not loaded within 30sec, it will timeout
* @param vdbName the name of the VDB
*/
private void waitForVDBLoad(String vdbName) throws Exception {
long waitUntil = System.currentTimeMillis() + VDB_LOADING_TIMEOUT_SEC*1000;
boolean first = true;
do {
// Pauses 5 sec
if (!first) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
break;
}
} else {
first = false;
}
// Refreshes from adminApi
refreshVDBs();
// Get the VDB
ITeiidVdb vdb = getVdb(vdbName);
// Stop waiting if any conditions have been met
if(vdb!=null) {
boolean hasValidityErrors = !vdb.getValidityErrors().isEmpty();
if( !vdb.hasModels() || vdb.hasFailed() || !vdb.isLoading()
|| vdb.isActive() || vdb.wasRemoved() || hasValidityErrors ) {
return;
}
} else {
return;
}
} while (System.currentTimeMillis() < waitUntil);
refreshVDBs();
return;
}
}
}