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())); } } }