package org.teiid.designer.datatools.connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.datatools.connectivity.IConnectionProfile;
import org.eclipse.datatools.connectivity.internal.ConnectionProfile;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.core.workspace.ResourceAnnotationHelper;
import org.teiid.designer.datatools.DatatoolsPlugin;
import org.teiid.designer.datatools.profiles.jbossds.IJBossDsProfileConstants;
import org.teiid.designer.datatools.profiles.ws.IWSProfileConstants;
import org.teiid.designer.type.IDataTypeManagerService.DataSourceTypes;
/**
* @since 8.0
*/
public class ConnectionInfoHelper implements IConnectionInfoHelper, ITranslatorOverridesProvider {
private ResourceAnnotationHelper resourceAnnotationHelper;
private ConnectionProfileFactory connectionProfileFactory;
public ConnectionInfoHelper() {
super();
}
public ConnectionInfoHelper( ResourceAnnotationHelper resourceAnnotationHelper,
ConnectionProfileFactory connectionProfileFactory ) {
super();
CoreArgCheck.isNotNull(resourceAnnotationHelper, "resourceAnnotationHelper"); //$NON-NLS-1$
CoreArgCheck.isNotNull(connectionProfileFactory, "connectionProfileFactory"); //$NON-NLS-1$
this.resourceAnnotationHelper = resourceAnnotationHelper;
this.connectionProfileFactory = connectionProfileFactory;
}
protected ResourceAnnotationHelper getHelper() {
if (resourceAnnotationHelper == null) {
resourceAnnotationHelper = new ResourceAnnotationHelper();
}
return resourceAnnotationHelper;
}
/**
* Provides means to find a connection profile for a supplied <code>ModelResource</code>
*
* @param modelResource
* @return
*/
@Override
public IConnectionProfile getConnectionProfile( ModelResource modelResource ) {
CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$
Properties connectionProps = null;
Properties profileProps = null;
try {
profileProps = getHelper().getProperties(modelResource, CONNECTION_PROFILE_NAMESPACE);
connectionProps = getHelper().getProperties(modelResource, CONNECTION_NAMESPACE);
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
if (connectionProps == null || connectionProps.isEmpty() || profileProps == null || profileProps.isEmpty()) {
return null;
}
// Now we need to
// cache non-base-property values
String name = profileProps.getProperty(CONNECTION_PROFILE_NAMESPACE + PROFILE_NAME_KEY);
String desc = profileProps.getProperty(CONNECTION_PROFILE_NAMESPACE + PROFILE_DESCRIPTION_KEY);
String id = profileProps.getProperty(CONNECTION_PROFILE_NAMESPACE + PROFILE_PROVIDER_ID_KEY);
// Reconstruct the set of base-properties for the ConnectionProfile
// Need to swap out the property keys
Properties baseProps = new Properties();
Set<Object> keys = connectionProps.keySet();
for (Object nextKey : keys) {
baseProps.put(removeNamespace((String)nextKey), connectionProps.getProperty((String)nextKey));
}
return createConnectionProfile(name, desc, id, baseProps);
}
/**
* Helper method to create an instance of a <code>ConnectionProfileFactory</code>.
*
* @param name the name of the connection profile
* @param description the description
* @param id the provider ID
* @param props the base properties
* @return the connection profile
*/
@Override
public ConnectionProfile createConnectionProfile( String name,
String description,
String id,
Properties props ) {
if (this.connectionProfileFactory == null) {
this.connectionProfileFactory = new ConnectionProfileFactory();
}
return this.connectionProfileFactory.createConnectionProfile(name, description, id, props);
}
protected String removeNamespace( String str ) {
int semiColonIndex = str.indexOf(':') + 1;
if (semiColonIndex > 0) {
return str.substring(semiColonIndex, str.length());
}
return str;
}
protected Properties removeNamespaces( Properties props ) {
Properties result = new Properties();
Set<Object> keys = props.keySet();
for (Object nextKey : keys) {
result.put(removeNamespace((String)nextKey), props.getProperty((String)nextKey));
}
return result;
}
/**
* Verifies if a <code>ModelResource</code> contains a model that contains connection information
*
* @param modelResource the <code>ModelResource</code>
* @return true if model resource contains connection info. false if not.
*/
@Override
public boolean hasConnectionInfo( ModelResource modelResource ) {
CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$
Properties props = null;
try {
props = getHelper().getProperties(modelResource, CONNECTION_NAMESPACE);
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
if (props == null || props.isEmpty()) {
return false;
}
return true;
}
/**
* Get the JBossDs JNDI property from the provided <code>ModelResource</code>
* @param modelResource the <code>ModelResource</code>
* @return the JBossDs JNDI property. If not found, returns null
*/
@Override
public String getJndiProperty( ModelResource modelResource ) {
CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$
Properties props = null;
try {
props = getHelper().getProperties(modelResource, CONNECTION_NAMESPACE);
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
if (props != null && !props.isEmpty()) {
return props.getProperty(CONNECTION_NAMESPACE+IJBossDsProfileConstants.JNDI_PROP_ID);
}
return null;
}
/**
* Returns the collective properties of a <code>ConnectionProfile</code> to include name, description and provider id in
* addition to it's base properties. These properties are also prefixed with a custom namespace for storage in a model
* resource "annotation"
*
* @param connectionProfile the connection profile
* @return the name-spaced properties for the connection profile
*/
@Override
public Properties getProperties( IConnectionProfile connectionProfile ) {
CoreArgCheck.isNotNull(connectionProfile, "connectionProfile"); //$NON-NLS-1$
if (this.connectionProfileFactory == null) {
this.connectionProfileFactory = new ConnectionProfileFactory();
}
return this.connectionProfileFactory.getNamespacedProperties(connectionProfile);
}
@Override
public Properties getCommonProfileProperties( IConnectionProfile profile ) {
Properties commonProps = new Properties();
commonProps.put(IConnectionInfoHelper.CONNECTION_PROFILE_NAMESPACE + IConnectionInfoHelper.PROFILE_NAME_KEY,
profile.getName());
commonProps.put(IConnectionInfoHelper.CONNECTION_PROFILE_NAMESPACE + IConnectionInfoHelper.PROFILE_DESCRIPTION_KEY,
profile.getDescription());
commonProps.put(IConnectionInfoHelper.CONNECTION_PROFILE_NAMESPACE + IConnectionInfoHelper.PROFILE_PROVIDER_ID_KEY,
profile.getProviderId());
commonProps.put(IConnectionInfoHelper.CONNECTION_PROFILE_NAMESPACE + IConnectionInfoHelper.PROFILE_ID_KEY,
profile.getInstanceID());
commonProps.put(IConnectionInfoHelper.CONNECTION_PROFILE_NAMESPACE + IConnectionInfoHelper.CATEGORY_ID_KEY,
profile.getCategory().getId());
return commonProps;
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.datatools.connection.IConnectionInfoHelper#getConnectionProperties(org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public Properties getConnectionProperties( ModelResource modelResource ) throws ModelWorkspaceException {
return removeNamespaces(getHelper().getProperties(modelResource, CONNECTION_NAMESPACE));
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.datatools.connection.IConnectionInfoHelper#getConnectionProperties(org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public Properties getProfileProperties( ModelResource modelResource ) throws ModelWorkspaceException {
return removeNamespaces(getHelper().getProperties(modelResource, CONNECTION_PROFILE_NAMESPACE));
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.datatools.connection.IConnectionInfoHelper#getTranslatorProperties(org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public Properties getTranslatorProperties( ModelResource modelResource ) {
CoreArgCheck.isNotNull(modelResource);
Properties props = null;
try {
props = removeNamespaces(getHelper().getProperties(modelResource, TRANSLATOR_NAMESPACE));
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
return props;
}
@Override
public String getTranslatorName( ModelResource modelResource ) {
if( modelResource == null ) {
return CoreStringUtil.Constants.EMPTY_STRING;
}
Properties props = null;
try {
props = getHelper().getProperties(modelResource, TRANSLATOR_NAMESPACE);
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
return props.getProperty(TRANSLATOR_NAMESPACE + TRANSLATOR_NAME_KEY, CoreStringUtil.Constants.EMPTY_STRING);
}
public void setTranslatorName( ModelResource modelResource, String translatorName ) {
CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$
CoreArgCheck.isNotEmpty(translatorName, "translatorName"); //$NON-NLS-1$
try {
getHelper().setProperty(modelResource, TRANSLATOR_NAMESPACE + TRANSLATOR_NAME_KEY, translatorName);
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
}
public void setJNDIName( ModelResource modelResource, String jndiName ) {
CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$
try {
getHelper().setProperty(modelResource, CONNECTION_NAMESPACE + IJBossDsProfileConstants.JNDI_PROP_ID, jndiName);
} catch (Exception e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e,
DatatoolsPlugin.Util.getString("errorFindingConnectionProfilePropertiesForModelResource", //$NON-NLS-1$
modelResource.getItemName()));
}
}
/**
* @param model the model whose JNDI data source name is being requested
* @param uuid the workspace UUID
* @return the JNDI name (never <code>null</code>)
*/
public String generateUniqueConnectionJndiName( IFile model,
String uuid ) {
return generateUniqueConnectionJndiName(model.getFullPath().removeFileExtension().lastSegment(),
model.getFullPath(),
ModelerCore.workspaceUuid().toString());
}
/**
* Creates a unique JNDI name for a source model based on a <code>ModelResource</code>
*
* @param modelResource
* @return the JNDI name
*/
@Override
public String generateUniqueConnectionJndiName( ModelResource modelResource,
String uuid ) {
CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$
CoreArgCheck.isNotEmpty(uuid, "uuid"); //$NON-NLS-1$
return generateUniqueConnectionJndiName(modelResource.getItemName(),
modelResource.getPath(),
ModelerCore.workspaceUuid().toString());
}
/**
* Creates a unique JNDI name for a source model based on a name and path in the workspace
*
* @param name
* @param path
* @return
*/
@Override
public String generateUniqueConnectionJndiName( String name,
IPath path,
String uuid ) {
CoreArgCheck.isNotEmpty(name, "name"); //$NON-NLS-1$
CoreArgCheck.isNotNull(path, "path"); //$NON-NLS-1$
CoreArgCheck.isNotEmpty(uuid, "uuid"); //$NON-NLS-1$
final StringBuilder builder = new StringBuilder(uuid + '_');
for (final String segment : path.removeLastSegments(1).segments())
builder.append(segment).append('_');
return builder.append(name).toString();
}
public String findTranslatorName( ModelResource modelResource ) {
String translator = getTranslatorName(modelResource);
for (String translatorName : DataSourceConnectionConstants.Translators.JDBC_TRANSLATORS) {
if (translator.toUpperCase().contains(translatorName.toUpperCase())) {
return translatorName;
}
}
return null;
}
/**
* Given a set of properties, find a suitable translator name.
*
* @param matchableStrings
* @param translators
* @return
*/
public String findTranslatorName( Properties properties ) {
Collection<String> matchableStrings = new ArrayList<String>();
matchableStrings.add(properties.getProperty(IConnectionInfoHelper.TRANSLATOR_NAME_KEY));
for (String translatorName : DataSourceConnectionConstants.Translators.ALL_TRANSLATORS) {
for (String keyword : matchableStrings) {
if (keyword.toUpperCase().contains(translatorName.toUpperCase())) {
return translatorName;
}
}
}
return null;
}
/**
* Given a set of matchable strings and a set of data source type strings, find a suitable match. If a match isn't found, then
* <unknown> string is returned.
*
* @param matchableStrings
* @param dataSourceTypeNames
* @return
*/
@Override
public String findMatchingDataSourceTypeName( Collection<String> matchableStrings,
Set<String> dataSourceTypeNames ) {
for (String dsTypeName : dataSourceTypeNames) {
for (String keyword : matchableStrings) {
if (keyword.toUpperCase().contains(dsTypeName.toUpperCase())) {
return dsTypeName;
}
}
}
return DataSourceConnectionConstants.Translators.UNKNOWN;
}
@Override
public String findMatchingDataSourceTypeName( ModelResource modelResource ) throws ModelWorkspaceException {
ResourceAnnotationHelper helper = new ResourceAnnotationHelper();
Properties properties = helper.getProperties(modelResource, IConnectionInfoHelper.TRANSLATOR_NAMESPACE);
return findMatchingDataSourceTypeName(properties);
}
@Override
public String findMatchingDataSourceTypeName( Properties properties ) {
for (String translatorName : DataSourceConnectionConstants.Translators.ALL_TRANSLATORS) {
String translator = properties.getProperty(IConnectionInfoHelper.TRANSLATOR_NAME_KEY);
if (translator.toUpperCase().contains(translatorName.toUpperCase())) {
return translator;
}
}
return ModelerCore.getTeiidDataTypeManagerService().getDataSourceType(DataSourceTypes.UNKNOWN);
}
/**
* Utility method to clear all connection info properties from a source model
* ConnectionInfoHelper.errorFindingTranslatorOverrideProperties
* @param modelResource
* @throws ModelWorkspaceException
*/
public void clearConnectionInfo(ModelResource modelResource) throws ModelWorkspaceException {
// Remove old connection properties
getHelper().removeProperties(modelResource, CONNECTION_PROFILE_NAMESPACE);
getHelper().removeProperties(modelResource, CONNECTION_NAMESPACE);
getHelper().removeProperties(modelResource, TRANSLATOR_NAMESPACE);
}
/**
* Utility method for reading the 'endpoint' property from a set of connection profile properties.
* Tries the 'endpoint' property key and then tries the legacy 'wsdlURI' property which was used
* in the wsdl importer during the 7.7.1 release
*
* @param properties
* @return 'endpoint' property value
*/
public static String readEndPointProperty(Properties properties) {
String endPointPropId = properties.getProperty(IWSProfileConstants.END_POINT_URI_PROP_ID);
if (endPointPropId == null) {
// Check for the incorrect version that was getting used by the WSDL importer in 7.7.1
endPointPropId = properties.getProperty(IWSProfileConstants.WSDL_URI_PROP_ID);
}
return endPointPropId;
}
@Override
public Properties getTranslatorOverrideProperties( ModelResource modelResource){
Properties props = new Properties();
try {
Properties rawProps = getHelper().getProperties(modelResource, TRANSLATOR_NAMESPACE);
// Strip namespace
for( Object key : rawProps.keySet()) {
String value = (String)rawProps.get(key);
int loc = ((String)key).indexOf(':') +1;
String propID = ((String)key).substring(loc);
props.put(propID, value);
}
} catch (ModelWorkspaceException e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e, DatatoolsPlugin.Util.getString("ConnectionInfoHelper.errorFindingTranslatorOverrideProperties", modelResource.getItemName()));
}
return props;
}
@Override
public void replaceTranlatorOverrideProperties(ModelResource modelResource, Properties properties) {
if( properties.isEmpty() ) {
return;
}
clearTranslatorOverrideProperties(modelResource);
Properties finalProps = new Properties();
for( Object key : properties.keySet()) {
String value = (String)properties.get(key);
finalProps.put(TRANSLATOR_NAMESPACE + key, value);
}
try {
// Add new connection properties
getHelper().setProperties(modelResource, finalProps);
} catch (ModelWorkspaceException e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e, DatatoolsPlugin.Util.getString("ConnectionInfoHelper.errorReplacingTranslatorOverrideProperties", modelResource.getItemName()));
}
}
@Override
public void clearTranslatorOverrideProperties(ModelResource modelResource) {
String translatorName = getTranslatorName(modelResource);
try {
getHelper().removeProperties(modelResource, TRANSLATOR_NAMESPACE);
Properties props = new Properties();
props.put(TRANSLATOR_NAMESPACE + TRANSLATOR_NAME_KEY, translatorName);
// Add new connection properties
getHelper().setProperties(modelResource, props);
} catch (ModelWorkspaceException e) {
DatatoolsPlugin.Util.log(IStatus.ERROR,
e, DatatoolsPlugin.Util.getString("ConnectionInfoHelper.errorClearingTranslatorOverrideProperties", modelResource.getItemName()));
}
}
}