/*
* 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.designer.teiidimporter.ui.panels;
import java.lang.reflect.InvocationTargetException;
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.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.runtime.spi.ITeiidDataSource;
import org.teiid.designer.runtime.spi.TeiidPropertyDefinition;
import org.teiid.designer.teiidimporter.ui.Messages;
import org.teiid.designer.teiidimporter.ui.UiConstants;
import org.teiid.designer.teiidimporter.ui.wizard.ITeiidImportServer;
/**
* DataSourceManager - handles DataSource operations with the supplied TeiidServer
*/
public class DataSourceManager implements UiConstants {
private static final String DRIVER_KEY = "driver-name"; //$NON-NLS-1$
private static final String CLASSNAME_KEY = "class-name"; //$NON-NLS-1$
private static final String CONN_FACTORY_CLASS_KEY = "managedconnectionfactory-class"; //$NON-NLS-1$
private static final String DOT_RAR = ".rar"; //$NON-NLS-1$
private ITeiidImportServer teiidImportServer;
/**
* DataSourceManager constructor
* @param teiidImportServer the TeiidServer
*/
public DataSourceManager(ITeiidImportServer teiidImportServer) {
this.teiidImportServer = teiidImportServer;
}
/**
* Create a DataSource
* @param dataSourceName the name of the DataSource
* @param driverName the name of the Driver
* @param properties the dataSource properties
* @return the result status of the operation
*/
public IStatus createDataSource(final String dataSourceName, final String driverName, final Properties properties) {
IStatus resultStatus = new Status(IStatus.OK, PLUGIN_ID, Messages.dataSourceManager_createOk);
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run( IProgressMonitor monitor ) throws InvocationTargetException {
try {
teiidImportServer.getOrCreateDataSource(dataSourceName, dataSourceName, driverName, properties);
} catch (Throwable e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
try {
new ProgressMonitorDialog(Display.getCurrent().getActiveShell()).run(true, true, op);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
resultStatus = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID, 0, cause.getLocalizedMessage(), cause);
UTIL.log(resultStatus);
} catch (InterruptedException e) {
resultStatus = new Status(IStatus.ERROR,UiConstants.PLUGIN_ID, Messages.dataSourceManager_createInterruptedMsg);
UTIL.log(resultStatus);
}
// Give a 1 sec pause for the file to deploy
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return resultStatus;
}
/**
* Delete a DataSource
* @param dataSourceName the name of the DataSource
* @return the result status of the operation
*/
public IStatus deleteDataSource(final String dataSourceName) {
IStatus resultStatus = new Status(IStatus.OK, PLUGIN_ID, Messages.dataSourceManager_deleteOk);
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run( IProgressMonitor monitor ) throws InvocationTargetException {
try {
teiidImportServer.deleteDataSource(dataSourceName);
} catch (Throwable e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
try {
new ProgressMonitorDialog(Display.getCurrent().getActiveShell()).run(true, true, op);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
resultStatus = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID, 0, cause.getLocalizedMessage(), cause);
UTIL.log(resultStatus);
} catch (InterruptedException e) {
resultStatus = new Status(IStatus.ERROR,UiConstants.PLUGIN_ID, Messages.dataSourceManager_deleteInterruptedMsg);
UTIL.log(resultStatus);
}
// Give a 1 sec pause for the file to deploy
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return resultStatus;
}
/**
* Delete a DataSource, then Create a new DataSource with specified properties
* @param deleteSourceName the name of the DataSource to delete
* @param createSourceName the name of the DataSource to create
* @param driverName the name of the Driver
* @param properties the dataSource properties
* @return the result status of the operation
*/
public IStatus deleteAndCreateDataSource(final String deleteSourceName,
final String createSourceName, final String driverName, final Properties properties) {
IStatus resultStatus = new Status(IStatus.OK, PLUGIN_ID, Messages.dataSourceManager_deleteCreateOk);
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run( IProgressMonitor monitor ) throws InvocationTargetException {
try {
teiidImportServer.deleteDataSource(deleteSourceName);
teiidImportServer.getOrCreateDataSource(createSourceName, createSourceName, driverName, properties);
} catch (Throwable e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
try {
new ProgressMonitorDialog(Display.getCurrent().getActiveShell()).run(true, true, op);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
resultStatus = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID, 0, cause.getLocalizedMessage(), cause);
UTIL.log(resultStatus);
} catch (InterruptedException e) {
resultStatus = new Status(IStatus.ERROR,UiConstants.PLUGIN_ID, Messages.dataSourceManager_deleteCreateInterruptedMsg);
UTIL.log(resultStatus);
}
// Give a 1 sec pause for the file to deploy
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return resultStatus;
}
/**
* Copy a DataSource
* @param dataSourceToCopyName the name of the DataSource to copy
* @param dataSourceToCopyDriver the driver name for the DataSource being copied
* @param newDataSourceName the name of the new dataSource
* @return the result status of the operation
*/
public IStatus copyDataSource(final String dataSourceToCopyName, final String dataSourceToCopyDriver, final String newDataSourceName) {
IStatus resultStatus = new Status(IStatus.OK, PLUGIN_ID, Messages.dataSourceManager_copyOk);
IRunnableWithProgress op = new IRunnableWithProgress() {
@Override
public void run( IProgressMonitor monitor ) throws InvocationTargetException {
try {
// Get properties for the source to copy
Properties dsProps = teiidImportServer.getDataSourceProperties(dataSourceToCopyName);
dsProps.remove("jndi-name"); //$NON-NLS-1$
// Create source with the new name
teiidImportServer.getOrCreateDataSource(newDataSourceName, newDataSourceName, dataSourceToCopyDriver, dsProps);
} catch (Throwable e) {
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
};
try {
new ProgressMonitorDialog(Display.getCurrent().getActiveShell()).run(true, true, op);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
resultStatus = new Status(IStatus.ERROR, UiConstants.PLUGIN_ID, 0, cause.getLocalizedMessage(), cause);
UTIL.log(resultStatus);
} catch (InterruptedException e) {
resultStatus = new Status(IStatus.ERROR,UiConstants.PLUGIN_ID, Messages.dataSourceManager_copyInterruptedMsg);
UTIL.log(resultStatus);
}
// Give a 1 sec pause for the file to deploy
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return resultStatus;
}
/**
* Get the list of PropertyItems for the supplied DataSource name - from the TeiidServer
* @param dsName the data source name
* @return the list of PropertyItem
*/
public List<PropertyItem> getDataSourcePropertyItems(String dsName) {
// Get the driver template properties
String driverName = getDataSourceDriver(dsName, null);
List<PropertyItem> propertyItems = getDriverPropertyItems(driverName);
if(!propertyItems.isEmpty()) {
// Get the data source specific properties
Properties props = null;
try {
// Get the specific property values for this data source
props = teiidImportServer.getDataSourceProperties(dsName);
} catch (Exception ex) {
props = new Properties();
UTIL.log(ex);
}
// Set the template property values to data source specific value
for(PropertyItem propItem: propertyItems) {
String propName = propItem.getName();
String propValue = props.getProperty(propName);
if(props.containsKey(propName)) {
propValue = props.getProperty(propName);
if(propValue!=null) {
propItem.setValue(propValue);
propItem.setOriginalValue(propValue);
}
}
}
}
return propertyItems;
}
/**
* Get the list of PropertyItems for the supplied driver name - from the TeiidServer
* @param driverName the driver name
* @return the list of PropertyItem
*/
public List<PropertyItem> getDriverPropertyItems(String driverName) {
List<PropertyItem> propertyItemList = new ArrayList<PropertyItem>();
if( driverName == null ) return propertyItemList;
Collection<TeiidPropertyDefinition> propDefns;
try {
// Get the driver template properties
propDefns = teiidImportServer.getTemplatePropertyDefns(driverName);
} catch (Exception ex) {
propDefns = new ArrayList<TeiidPropertyDefinition>();
UTIL.log(ex);
}
// Get the Managed connection factory class for rars
String rarConnFactoryValue = getManagedConnectionFactoryClassDefault(propDefns);
// Create the PropertyItems, setting the template values for this source
for(TeiidPropertyDefinition propDefn: propDefns) {
PropertyItem propItem = new PropertyItem();
// ------------------------
// Set PropertyItem fields
// ------------------------
// Name
String name = propDefn.getName();
propItem.setName(name);
// DisplayName
String displayName = propDefn.getDisplayName();
propItem.setDisplayName(displayName);
propItem.setDescription(propDefn.getDescription());
// isModifiable
// TODO: remove this workaround (due to erroneous .rar values)
boolean isModifiable = isModifiable(driverName,propDefn);
propItem.setModifiable(isModifiable);
// isRequired
boolean isRequired = propDefn.isRequired();
propItem.setRequired(isRequired);
// isMasked
boolean isMasked = propDefn.isMasked();
propItem.setMasked(isMasked);
// defaultValue
Object defaultValue = propDefn.getDefaultValue();
if(defaultValue!=null) {
propItem.setDefaultValue(defaultValue.toString());
}
// Set the value and original Value
if(defaultValue!=null) {
propItem.setValue(defaultValue.toString());
propItem.setOriginalValue(defaultValue.toString());
// Set Connection URL to template if available and value was null
} else if(displayName.equalsIgnoreCase(PropertyItem.CONNECTION_URL_DISPLAYNAME)) {
String urlTemplate = TranslatorHelper.getUrlTemplate(driverName);
if(!CoreStringUtil.isEmpty(urlTemplate)) {
propItem.setValue(urlTemplate);
propItem.setOriginalValue(urlTemplate);
}
}
// Copy the 'managedconnectionfactory-class' default value into the 'class-name' default value
if(name.equals(CLASSNAME_KEY)) {
propItem.setDefaultValue(rarConnFactoryValue);
propItem.setValue(rarConnFactoryValue);
propItem.setOriginalValue(rarConnFactoryValue);
propItem.setRequired(true);
}
// ------------------------
// Add PropertyItem to List
// ------------------------
propertyItemList.add(propItem);
}
return propertyItemList;
}
/**
* Create a map of class-name to the associated DataSource template name. This
* matches the className of the datasource to the 'managedconnectionfactory-class' name from the template.
* @param teiidDataSources the collection of Teiid DataSources
* @return Map of RA class-name to DS template name
*/
public Map<String,String> getClassNameDriverNameMap(Collection<ITeiidDataSource> teiidDataSources) {
Map<String,String> raClassToDriverNameMap = new HashMap<String,String>();
// Get all distinct class-names from dataSources
Set<String> dsClassNames = new HashSet<String>();
for(ITeiidDataSource ds : teiidDataSources) {
String dsClass = ds.getPropertyValue("class-name"); //$NON-NLS-1$
if(!CoreStringUtil.isEmpty(dsClass)) {
dsClassNames.add(dsClass);
}
}
// Get all available templates from the server
Set<String> availableTemplateNames;
try {
availableTemplateNames = teiidImportServer.getDataSourceTemplateNames();
} catch (Exception ex) {
availableTemplateNames = Collections.EMPTY_SET;
UTIL.log(ex);
}
for(String className : dsClassNames) {
// Loop through all available templates. break if matching template is found
for(String templateName : availableTemplateNames) {
Collection<TeiidPropertyDefinition> propDefns;
try {
// Get the driver template properties
propDefns = teiidImportServer.getTemplatePropertyDefns(templateName);
// Get default value for managedconnectionfactory-class
String mcfDefault = getManagedConnectionFactoryClassDefault(propDefns);
if(className.equals(mcfDefault)) {
raClassToDriverNameMap.put(className, templateName);
break;
}
} catch (Exception ex) {
UTIL.log(ex);
}
}
}
return raClassToDriverNameMap;
}
/**
* Get the Driver name for the supplied DataSource name - from the TeiidServer
* @param dsName the data source name
* @param raClassNameDriverNameMap optionally supplied mapping of className to TemplateName
* @return the dataSource driver name
*/
public String getDataSourceDriver(String dsName, Map<String,String> raClassNameDriverNameMap) {
String driverName = null;
Properties props = new Properties();
try {
props = teiidImportServer.getDataSourceProperties(dsName);
} catch (Exception ex) {
UTIL.log(ex);
return null;
}
driverName = props.getProperty(DRIVER_KEY);
// If driver-name not found - 1) use map (if supplied) to get the driverName or 2) attempt to match server template
if(CoreStringUtil.isEmpty(driverName)) {
String className = props.getProperty(CLASSNAME_KEY);
if(raClassNameDriverNameMap!=null) {
driverName = raClassNameDriverNameMap.get(className);
} else {
String dsTemplateName = findDSTemplateWithMatchingClass(className);
if(!CoreStringUtil.isEmpty(dsTemplateName)) {
driverName = dsTemplateName;
}
}
}
return driverName;
}
/**
* Iterates through all of the available dataSource templates to find template with 'managedconnectionfactory-class' that
* matches the supplied className. If no match is found, null is returned.
* @param className the dataSource class name
* @return the templateName with 'managedconnectionfactory-class' that matches className, null if not found.
*/
private String findDSTemplateWithMatchingClass(String className) {
if(CoreStringUtil.isEmpty(className)) return null;
String dsTemplateName = null;
// Get all available templates from the server
Set<String> availableTemplateNames;
try {
availableTemplateNames = teiidImportServer.getDataSourceTemplateNames();
} catch (Exception ex) {
availableTemplateNames = Collections.EMPTY_SET;
UTIL.log(ex);
}
// Loop through all available templates. break if matching template is found
for(String templateName : availableTemplateNames) {
Collection<TeiidPropertyDefinition> propDefns;
try {
// Get the driver template properties
propDefns = teiidImportServer.getTemplatePropertyDefns(templateName);
// Get default value for managedconnectionfactory-class
String mcfDefault = getManagedConnectionFactoryClassDefault(propDefns);
if(className.equals(mcfDefault)) {
dsTemplateName = templateName;
break;
}
} catch (Exception ex) {
UTIL.log(ex);
}
}
return dsTemplateName;
}
/*
* Return the isModifiable property value. Need this currently because Teiid isModifiable values
* are inverted for all .rar sources
* @param driverName the driver name
* @param propDefn the property definition
* @return 'true' if modifiable, 'false' if not
*/
private boolean isModifiable(String driverName, TeiidPropertyDefinition propDefn) {
boolean isModifiable = propDefn.isModifiable();
if(driverName!=null && driverName.endsWith(DOT_RAR)) {
isModifiable = !isModifiable;
}
return isModifiable;
}
/*
* Get the default value for the Managed ConnectionFactory class
* @param propDefns the collection of property definitions
* @return default value of the ManagedConnectionFactory, null if not found.
*/
private String getManagedConnectionFactoryClassDefault (Collection<TeiidPropertyDefinition> propDefns) {
String resultValue = null;
for(TeiidPropertyDefinition pDefn : propDefns) {
if(pDefn.getName().equalsIgnoreCase(CONN_FACTORY_CLASS_KEY)) {
resultValue=(String)pDefn.getDefaultValue();
break;
}
}
return resultValue;
}
}