Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 253584 - Systematically detect the Connection Profile Provider ID for a JDBC connection profile
Summary: Systematically detect the Connection Profile Provider ID for a JDBC connectio...
Status: RESOLVED FIXED
Alias: None
Product: Data Tools
Classification: Tools
Component: JDBC Conn Profile (show other bugs)
Version: Ganymede   Edit
Hardware: PC Windows 2000
: P3 enhancement (vote)
Target Milestone: 1.7RC1   Edit
Assignee: Brian Fitzpatrick CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 253630
  Show dependency tree
 
Reported: 2008-11-03 19:42 EST by Linda Chan CLA
Modified: 2009-05-18 12:15 EDT (History)
2 users (show)

See Also:


Attachments
First Cut at Patch (32.27 KB, patch)
2009-04-28 21:19 EDT, Brian Fitzpatrick CLA
no flags Details | Diff
Add this to the first cut patch (7.14 KB, patch)
2009-05-11 18:06 EDT, Brian Fitzpatrick CLA
no flags Details | Diff
Updated patch (complete) (29.35 KB, patch)
2009-05-12 18:16 EDT, Brian Fitzpatrick CLA
no flags Details | Diff
Updated patch (with Linda's last round of comments) (27.81 KB, patch)
2009-05-13 17:06 EDT, Brian Fitzpatrick CLA
no flags Details | Diff
Mapping extensions for Generic JDBC and Apache Derby (1.94 KB, patch)
2009-05-13 18:30 EDT, Linda Chan CLA
no flags Details | Diff
Mapping extensions batch 1 (5.27 KB, patch)
2009-05-14 00:55 EDT, Linda Chan CLA
no flags Details | Diff
Patch for all enablement projects (14.15 KB, patch)
2009-05-14 20:15 EDT, Brian Fitzpatrick CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Linda Chan CLA 2008-11-03 19:42:19 EST
To create a JDBC connection profile instance using the Connectivity Profile Management API, a connection profile provider id is needed.

Given a database vendor and version, the framework will need to navigate and find the best supporting connection profile provider id.
A database vendor and version are defined in a driver template.  A driver template may be associated with zero or more types of profile providers.  However, such direct association is not explicitly defined in DTP.
They are only loosely coupled through a driver category in the UI page implementation of a profile provider.  Specifically, a profile provider specific UI page is associated with a driver category, which is then used to filter the list of supported driver templates and definitions.
  
The proposal is to extract such association from the UI implementation to a new element in the connection profile extension point.  That is, add a new element to define the "driverCategory" supported by a JDBC connection profile provider id.  A JDBC profile provider is expected to support one-and-only-one driver category.  And technically, multiple profile providers may support the same driver category.
Related profile UI page implementation can gradually migrate and replace its hard-coded driverCategory with the attribute value specified in the extension element.

New utiltiy API will be needed to support navigating from a driver template's category to 0..n profile providers.  The generic JDBC profile provider will be applied if none is found.  If more than one are found to be associated with a driver template's category, it will be up to a client to determine which connection profile provider to use.
Comment 1 Linda Chan CLA 2008-11-03 19:44:22 EST
I will start on this with a proposal of the related extension point schema definition.
Comment 2 Brian Fitzpatrick CLA 2009-04-02 10:25:37 EDT
I've been doing some thinking about this. Basically we're looking at a mapping between the driverCategory and a provider ID? And it would be a one to many relationship (if any exist), as a given connection profile type may support many different driver categories. 

And then we need a map to get from the driver template ID (up from there via the template category) to get back to the provider ID?

Since this will be fairly experimental for Galileo, can we simply create a new extension point that does this binding from provider ID to template category and then roll it back into the connection profile extension if we need to in a future release?
Comment 3 Linda Chan CLA 2009-04-02 15:53:12 EDT
(In reply to comment #2)

From what I understand, the current relationships are:
* 1 profile provider is expected to support one-and-only-one db driver category
* 1 db driver template's category may be supported by 0..n profile providers

Using a new extension point to specify such mapping should be fine.
An utility API method would then use this to look up to the connection profile provider id(s) based on a specified driver template ID (via the template category).

Wonder if there may be any issue with ensuring consistency with the mapping implemented in a profile provider specific UI page?  Larry, comments?
Comment 4 Larry Dunnell CLA 2009-04-09 14:15:02 EDT
Yes,  I think if an extension point is simply added then it is possible that the UI page could specify one category and the extension point could specify another.
Comment 5 Brian Fitzpatrick CLA 2009-04-10 11:19:13 EDT
Ok I get it. Right now the category ID is specified in the constructor for the UI page (wizard page or property page). The only problem with that is that it's in the UI plug-ins, not the core plug-ins, for the enablement projects. So if we're doing this all API under the covers, there's a chance it won't jive. 

So what happens if we provide this new extension point with a utility class that we can turn around and use to provide that category ID in the constructor from the new extension point? If there's no extension point defined, we can pass in a default. This should make it a fairly simple search/replace through the enablement projects for the property pages and wizard pages to adjust the constructor.

The new extension point would map the provider ID to a category ID. The utility class could then process the driver template registry to find a suitable category for a vendor/version (by surfing for entries that support the vendor/version and back-tracing to the category).

Am I oversimplifying this?
Comment 6 Brian Fitzpatrick CLA 2009-04-22 12:33:25 EDT
Larry, could really use your input on this so we might add it as an "experimental" item for Galileo.
Comment 7 Brian Fitzpatrick CLA 2009-04-27 19:06:18 EDT
So after discussing this with Larry & Linda at the Connectivity Team Meeting, we're going to do this...

1) Create an extension point that allows mapping of Connection Profile provider ID to Driver category ID as well as from Vendor and Version to Driver category ID. Ideally this should be done in the non-ui plug-in's plugin.xml so it's available for API use and UI use.

2) Create a utility class that provides a number of methods for retrieving the category ID from the provider ID and also from vendor and version.

3) Update the ExtensibleProfileDetailsPropertyPage and ExtensibleProfileDetailsWizardPage to use the utility class from #2 to map from the connection profile provider ID instead of hard-coding a category ID. If no mapping can be found via the utility class, default to the category ID specified if it is available.

4) Implement the extension point from #1 in all of the available enablement projects. 
Comment 8 Brian Fitzpatrick CLA 2009-04-27 19:09:11 EDT
So to clarify just a bit so I don't forget... the ultimate goal is to go from the vendor/version to the provider ID by way of the intermediary category ID. I think the proposed API and extension points will handle this case.
Comment 9 Brian Fitzpatrick CLA 2009-04-28 21:19:07 EDT
Created attachment 133671 [details]
First Cut at Patch

Hey guys... This patch provides three things:

1) The extension points and a registry class to get the info out that you want
2) Updated extensibility wizard and property pages that grab the info from the registry if it's there
3) An updated plugin.xml that registers the correct bits for Derby

Let me know what you think. It's not well documented yet, but it's pretty easy to use. 

--Fitz
Comment 10 Brian Fitzpatrick CLA 2009-04-30 15:47:28 EDT
Bumping this to RC1 so we have some time to review/change it if need be.
Comment 11 Larry Dunnell CLA 2009-05-01 14:19:13 EDT
Looks good.  Just as we discussed.
Comment 12 Brian Fitzpatrick CLA 2009-05-01 17:30:19 EDT
Linda, any thoughts?
Comment 13 Linda Chan CLA 2009-05-08 00:42:38 EDT
The part of extension point that maps between the driverCategoryId and providerId looks fine to me.

For the direct mapping of vendor+version to a driverCategory, I was walking thru the existing extension points, and notice that such mapping seem to already exist indirectly in the driverExtension extension point.
The driverTemplate element in driverExtension specifies the vendor and version properties, and its associated parentCategory.

Is it feasible to get the mapping from vendor+version to driverCategory thru the driverExtension's driverTemplate element?  If so, it would avoid inconsistent definition across different extension points.

The same vendor+version may be supported by multiple driverTemplates (defined in a driverExtension), which each can specify a different parentCategory.  
So technically, the registry method #getCategoryIdForVendorVersion could end up finding multiple categories that match the specified vendor+version.  So the method should perhaps return a collection of driver category ids?

The caller can then pick the appropriate driver category id that it wants, and call the mapping registry to get the corresponding providerId.
The driverCategory could be a hierarchy. And it could be the parent category of a specified category id that has a mapping to a provider id.
Perhaps the registry method #getProviderIDforDriverCategoryID 
can traverse up the driverCategory hierarchy, to find its first corresponding profileProviderId (defined in the new extension point)?


Comment 14 Brian Fitzpatrick CLA 2009-05-08 08:57:25 EDT
Very interesting observation. I'll have to look at it today and get back to you.

Right now without surfing through all the available driver template extensions there's no index that would make this easy. But it would make sense to reuse what's already there in the driver extension.

We're pushing this really close to the edge of RC1 though...
Comment 15 Brian Fitzpatrick CLA 2009-05-11 18:06:47 EDT
Created attachment 135230 [details]
Add this to the first cut patch

Hey guys...

Ok, so I went back and revamped the ProviderIDMappingRegistry to use the driver template instead of the vendor/version to category ID extension point I created before. 

The upshot is that I default to the parent category of the parent category of the driver template wherever possible. The reasoning behind this is typically you have a version-specific category (you have the org.eclipse.datatools.connectivity.db.derby.10_2.driverCategory for derby, but we're not interested in that category, we're more interested in the org.eclipse.datatools.connectivity.db.derby.driverCategory category, which is the child of the main Database category). 

The only place where this appears to be a problem is for the generic JDBC driver template, which is a direct child beneath the Database category. 

Anyway... Long story short, I think this works. I haven't removed the extra extension point yet, but wanted someone to take a look at this to see what they think.

Linda? Larry?

Thanks in advance.
--Fitz
Comment 16 Linda Chan CLA 2009-05-11 21:05:43 EDT
Brian,

The method that returns a providerId for vendor+version does work fine when a category has up to one level of db-specific parent.  Thanks!
BTW, the method name #getCategoryIDforVendorVersion can use a rename, since it now returns a "providerId".

In case there are third-party driver categories that have more than 1 level of parent category before it reaches the DATABASE_CATEGORY_ID, it would be nice if the implementation can keep iterate up the parent category hierarchy till it gets to the DATABASE_CATEGORY_ID, and include each of the intermediate parent category ids in the sVendorVersionToCategoryIDMap.

Somewhat separately,
will the public method #getProviderIDforDriverCategoryID implementation be updated as well to handle mapping of a category hierarchy?
For example, a mapping extension may specify the provider id for the top-level db-specific category only.  
The #getProviderIDforDriverCategoryID method argument may be its child category id, which ideally should return the providerId inherited from its parent category's mapping.  Otherwise, one would have to create separate mapping extensions for each of the child category ids.

Another separate minor thing, we currently have sqm.core.SQMServices as the main entry point to get various registry services.  Should it be consistent and provide a new getter method in SQMServices to get the ProviderIDMappingRegistry singleton instance?
E.g.
  public static ProviderIDMappingRegistry getProviderIDMappingRegistry()
Comment 17 Brian Fitzpatrick CLA 2009-05-12 17:11:34 EDT
1) Well... in the case of multiple nested categories, sometimes you don't want the top one. Sometimes you want one beneath that. 

Take for example Sybase driver templates...

Databases
	Sybase
		ASA
			9.x
			10.x
		ASE
			15.x
		
If we climb all the way up to the one below the Databases node, you end up with Sybase, which isn't really what you want. So I'm not sure about that. Yes, this is because we used a slightly different hierarchy for our driver template categories for the Sybase plug-ins, but we shouldn't force changes unless they're really needed.

2) Are you asking to change getProviderIDforDriverCategoryID to be aware of child category IDs?

3) That's fine. I can add a reference from SQMServices.
Comment 18 Linda Chan CLA 2009-05-12 18:08:30 EDT
1) If I understand the implementation correctly, the sVendorVersionToCategoryIDMap is mainly used as an interim collection to figure out sVendorVersionToProviderIDMap?
For the Sybase case, including vendor+version -> "Sybase" category id in sVendorVersionToCategoryIDMap would not affect the sVendorVersionToProviderIDMap, since the "Sybase" category will not find a corresponding providerId in a Mapping extension. 
But for other cases where the top-level and/or intermediate category does have a mapped providerId in a Mapping extension, its vendor+version mapping to the providerId will then get correctly included in the providerId map.

2) >> Are you asking to change getProviderIDforDriverCategoryID to be aware of child category IDs?

Yes in the public method, which would be separate from the private access to the Mapping extension entries.  This would be more friendly and not require a providerId Mapping extension for each level of nested categories.
Comment 19 Brian Fitzpatrick CLA 2009-05-12 18:11:44 EDT
For 1) - ASA and ASE have different provider IDs. That's what I'm trying to say. So if we go this route and we try to bind the high-level category (the Sybase category, not Sybase ASA) to a provider ID, you end up binding to the wrong thing and will end up broken.

For 2) - Cool, I'm working on it
Comment 20 Brian Fitzpatrick CLA 2009-05-12 18:16:42 EDT
Created attachment 135469 [details]
Updated patch (complete)

This updated patch cleans up the unnecessary extension point now and does pretty much everything I think what you've asked except for processing up to the Database category for the reasons I've explained in an earlier comment.
Comment 21 Linda Chan CLA 2009-05-12 18:46:01 EDT
>> For 1) - ASA and ASE have different provider IDs

That's what I thought too. 
So for the Sybase nested categories, it will only have the following Mapping extensions:
A) ASA category <-> ASA provider id
B) ASE category <-> ASE provider id

When it walks up to the top level, and add each nested category to sVendorVersionToCategoryIDMap,
it will have the following entries:
1) ASA+9.x -> ASA category
2) ASA+9.x -> Sybase category
3) ASA+10.x -> ASA category
4) ASA+10.x -> Sybase category
5) ASE_15.x -> ASE category
6) ASE_15.x -> Sybase category

Then when it iterates thru each categoryId key in sVendorVersionToCategoryIDMap,
to find corresponding mapped providerId, the Sybase category will not find a mapping providerId:

1) ASA+9.x -> ASA category -> ASA provider id
2) ASA+9.x -> Sybase category -> null
3) ASA+10.x -> ASA category -> ASA provider id
4) ASA+10.x -> Sybase category -> null
5) ASE_15.x -> ASE category-> ASE provider id
6) ASE_15.x -> Sybase category -> null

So isn't it that only those category ids with mapping providerId will get
added to sVendorVersionToProviderIDMap:
1) ASA+9.x -> ASA provider id
3) ASA+10.x -> ASA provider id
5) ASE_15.x -> ASE provider id
Comment 22 Linda Chan CLA 2009-05-12 20:19:04 EDT
My last comment was based on the previous implementation in #loadMaps, in which it looks up the sCategoryIDtoProviderIDMap only when it iterates thru each categoryId in sVendorVersionToCategoryIDMap to populate sVendorVersionToProviderIDMap.

Now that patch 135469 has #loadMaps using the reworked #getProviderIDforDriverCategoryID, this actually would take care of the multiple nested category issue #1 as well, if #loadMaps simply uses the driverTemplate's categoryId to put in sVendorVersionToCategoryIDMap (i.e. no need to even use its immediate parent categoryId).  E.g. 

if (vendor != null && vendor.trim().length() > 0 &&
    version != null && version.trim().length() > 0) {
	String encoded = encodeVendorVersion(vendor, version);
	String categoryID = templates[i].getParentCategory();
        if (categoryID != null) {
            sVendorVersionToCategoryIDMap.put(
                            encoded, 
                            categoryID);
         }
}

Then when #loadMaps later calls #getProviderIDforDriverCategoryID to populate sVendorVersionToProviderIDMap, it takes care of walking up the category hierarchy (including multiple-level cases) and would correctly applies the first mapping providerId for the vendor+version.

--------

Separately, to ensure thread-safe usage, how about add synchronized to #getInstance, e.g.

	public static ProviderIDMappingRegistry getInstance() {
		if (sRegistry == null) {
		    synchronized( ProviderIDMappingRegistry.class ) {
		        if (sRegistry == null)
		            sRegistry = new ProviderIDMappingRegistry();
		    }
		}
		return sRegistry;
	}
Comment 23 Brian Fitzpatrick CLA 2009-05-13 10:54:43 EDT
Good points on both items. I'll see about updating the patch this morning.
Comment 24 Brian Fitzpatrick CLA 2009-05-13 17:06:11 EDT
Created attachment 135694 [details]
Updated patch (with Linda's last round of comments)

Here's the updated patch with Linda's latest round of suggestions.

Once this is in we can update each enablement plug-in to provide the provider ID to category ID mapping and we should be good to go. That's a minor tweak.
Comment 25 Linda Chan CLA 2009-05-13 18:29:44 EDT
The latest patch 135694 looks good.  Thanks!

I can help add the mapping extensions for some of the db-specific components.
Should the extension be in the *.dbdefinition plugin, or the runtime plugin?  Attached are the ones for the generic JDBC and Apache ones in their dbdefinition plugin.
Comment 26 Linda Chan CLA 2009-05-13 18:30:50 EDT
Created attachment 135711 [details]
Mapping extensions for Generic JDBC and Apache Derby
Comment 27 Brian Fitzpatrick CLA 2009-05-13 19:52:22 EDT
That would be great if you can help out. I'd put them in the runtime plug-ins along with the driver definitions, since they kind of go together.

And I'll go ahead and label these more explicitly as experimental.

In the exsd documentation description and in the related
public API Javadoc comments:

* <p>
* <strong>EXPERIMENTAL</strong>. This class or interface has been added
as
* part of a work in progress. There is no guarantee that this API will
* work or that it will remain the same. Please do not use this API
without
* consulting with the DTP Connectivity team.
* </p>
Comment 28 Linda Chan CLA 2009-05-14 00:55:28 EDT
Created attachment 135728 [details]
Mapping extensions batch 1

Mapping extensions for 
* Generic JDBC 
* Apache Derby
* DB2 LUW
* Informix
* SQL Server
* Oracle
Comment 29 Brian Fitzpatrick CLA 2009-05-14 18:55:20 EDT
Delivered framework changes to o.e.d.connectivity.sqm.core and o.e.d.connectivity.ui as tag v200905150650
Comment 30 Brian Fitzpatrick CLA 2009-05-14 20:15:38 EDT
Created attachment 135885 [details]
Patch for all enablement projects

This patch hits 'em all. I'll deliver now...
Comment 31 Brian Fitzpatrick CLA 2009-05-14 20:26:38 EDT
I'm guessing these tweaks won't make it into today's build, but may make it into the first RC2 build?

Linda, can you verify as many of these as you want (you've already obviously done a few) when we get a build?

Updated the following with tag v200905150820

o.e.d.c.apache.derby
o.e.d.c.db.generic
o.e.d.e.hsqldb
o.e.d.e.ibm.db2.iseries
o.e.d.e.ibm.db2.luw
o.e.d.e.ibm.db2.zseries
o.e.d.e.ibm.informix
o.e.d.e.ingres
o.e.d.e.msft.sqlserver
o.e.d.e.mysql
o.e.d.e.oracle
o.e.d.e.postgresql
o.e.d.e.sap.maxdb
o.e.d.e.sqlite
o.e.d.e.sybase.asa.ui (should really be in o.e.d.e.sybase.asa, but it's arranged differently for some reason)
o.e.d.e.sybase.ase.ui (same as asa)

Comment 32 Brian Fitzpatrick CLA 2009-05-18 12:15:41 EDT
Marking as fixed.