|
|
|
| Resource type | Description | Metric URI |
|---|---|---|
| Databases | Generated for users who create a new database or connect an existing database. | http://www.gria.org/sla/metric/activity/ogsadai/db |
| Database roles | Generated for each database role that is created. | http://www.gria.org/sla/metric/activity/ogsadai/role |
| Database subscriptions | Generated for the user who subscribes to a database role. | http://www.gria.org/sla/metric/activity/ogsadai/subscription |
| Database subscribers | Generated for the owner of a database role when somebody subscribes to it. | http://www.gria.org/sla/metric/resource/ogsadai/subscriber |
User A has been given permission by the service provider to create databases. He wants to create a new database, create some tables in that database, and then give User B read/write access to those tables.
User A calls createDatabase.
User A calls subscribe on his administrative role so he can create a table.
User A calls perform on his subscription, creating a table.
User A gives User B permission to subscribe to his Read/Write role.
User B calls subscribe on the Read/Write role.
User B executes some queries on his Read/Write subscription.
At the end of this example, the usage for the two users is as follows:
In some situations the service provider may wish to charge or constrain differently for different databases or database roles. For example, he may want to make read-only access to a database free while charging for read/write access.
This can be implemented through the use of custom metric URIs. There are two places where a custom URI can be entered:
When a user subscribes to a database role that uses custom metric URIs he generates one usage report for the standard subscription metric (http://www.gria.org/sla/metric/activity/ogsadai/subscription) and one for the custom metric. This is different from subscribing to a role without a custom metric URI, where the user would only generate a usage report for the standard subscription metric.
Providing a custom metric URI when creating a new database will assign similar metric URIs to the three automatically generated database roles. These URIs are generated using the same rules as username generation - the three postfixes are appended onto the end of the metric URI for each of the three roles.
For example, supposing you keep the default values for the username postfixes (eg, ".a" for the administrative role and ".r" for the read-only role), and specify a metric URI http://www.test.com/metric/test_database, the following metric URIs would be generated for the three roles:
SLA templates can be created to constrain on any of the above metrics. Several example sections of SLA templates are given below. See the GRIA user documentation for information on constructing full SLA template XML documents.
When inserted into the <constraints> section of an SLA template, this capacity constaint will limit the user to creating only one database. The user may still subscribe to other databases, and other users may subscribe to his database.
<constraint type='INSTANTANEOUS'>
<metric type='ACTIVITY'>
<uri>http://www.gria.org/sla/metric/activity/ogsadai/db</uri> <description> <description>database</description> </description> <units type='DECIMAL'> <instantaneous>database</instantaneous> </units> </metric> <bound>LE</bound> <private>false</private> <limit>1.0</limit> <contention>1.0</contention> <repeating>false</repeating> </constraint>
When inserted into the <constraints> section of an SLA template, these capacity constraints will allow the user to subscribe to three database roles, and have one person subscribe to any roles he creates. The user can create an unlimited number of databases.
<constraint type='INSTANTANEOUS'>
<metric type='ACTIVITY'>
<uri>http://www.gria.org/sla/metric/activity/ogsadai/subscription</uri> <description> <description>subscription</description> </description> <units type='DECIMAL'> <instantaneous>subscription</instantaneous> </units> </metric> <bound>LE</bound> <private>false</private> <limit>3.0</limit> <contention>1.0</contention> <repeating>false</repeating> </constraint> <constraint type='INSTANTANEOUS'> <metric type='RESOURCE'> <uri>http://www.gria.org/sla/metric/resource/ogsadai/subscriber</uri> <description> <description>subscriber</description> </description> <units type='DECIMAL'> <instantaneous>subscriber</instantaneous> </units> </metric> <bound>LE</bound> <private>false</private> <limit>1.0</limit> <contention>1.0</contention> <repeating>false</repeating> </constraint>
The GRIA client package can be downloaded from www.gria.org.
Installation instructions are available in the GRIA user guide.
Note: the gria ogsa-dai-client-5.2 plugin is only compatible with the 5.1 GRIA Client and later.
Visit the URL of the GRIA OGSA-DAI Service you wish to access and drag the wsdl link from the webpage in to the service view of the client.
Connecting to an OGSA-DAI Service from Client
If you are running the GRIA OGSA-DAI 1.0 client drag the OGSA-DAI Service legacy link, otherwise use the OGSA-DAI Service link. It is most likely that you are using a 5.2 client.
This feature allows you to expose existing databases containing existing data to users of the GRIA OGSA-DAI service. To use this feature you need to have been given access to the connect-database PBAC role on the OGSA-DAI service. See the Access Control section for more information.
Before starting you should ensure that the OGSA-DAI service is listed in your client. If it does not exist you can add it by either left clicking on the "Services" menu item and selecting "Add a service", or dragging the service's WSDL link onto the "Services" entry.
Right click on the OGSA-DAI service and select "Connect existing resource".
This will open a dialog box where you can enter the details of the database you wish to connect. You are able to enter the JDBC URL of any type of database here, and also a short description of the database. No checks as to the validity of the JDBC URL are made.
Once you have connected you data resource you are able to add roles. Right click on the connected data resource and select "Connect role".
Enter a description plus the username and password of the role on your database.
After clicking "OK", the role you have created is added to the list.
See the Access Control section to learn how you can control which users have permission to subscribe to your new data resource role.
This feature allows you to create new data resources which you can either subscribe to and use yourself, or give permission for others to use. To create new data resource you need to have been given access to the create-dataresource PBAC role on the OGSA-DAI service. See the Access Control section for more information.
Before starting you should ensure that the OGSA-DAI service is listed in your client. If it does not exist you can add it by either left clicking on the "Services" entry and selecting "Add a service", or dragging the service's WSDL link into the client.
Right click on the OGSA-DAI service and select "Create new dataresource".
Enter a description and press ok.
The database and its three roles have now been created.
See the Access Control section to learn how you can control which users have permission to subscribe to your new data resources.
Getting a subscription to a database role allows you to execute queries (perform documents) on it. By default you are allowed to subscribe to roles created by yourself. To be able to subscribe to roles created by other people, they need to have given you the client PBAC role on their resource. See the Access Control section for more information.
If you have been given access to a role and it does not appear in your client, try right clicking on the OGSA-DAI service and selecting "Discover existing resources".
Before starting you should ensure that the OGSA-DAI service is listed in your client. If it does not exist you can add it by either left clicking on the "Services" menu item and selecting "Add a service", or dragging the service's WSDL link into the client.
Right click on the role you wish to subscribe to and select "Subscribe". You will be asked to enter a short description for the subscription.
The subscription is now listed in your client. You can execute SQL queries on it directly from the client by right clicking on it and selecting one of "Execute query" or "Execute update" entries. Note this only works on SQL Database types of data resources.
This feature allows you to permit another user to execute database queries using your subscription. Note that the delegate only gets access to a subset of methods on your subscription:
| Action | Owner | Delegate |
|---|---|---|
| Executing perform documents | Permitted | Permitted |
| Running SELECT queries | Permitted | Permitted |
| Running UPDATE queries | Permitted | Permitted |
| Viewing and editing access control lists | Permitted | Denied |
| Destroying the resource | Permitted | Denied |
| Renaming the resource | Permitted | Denied |
Left click on the database subscription that you wish to delegate access to, and select "Access control list".

Now add a new access control rule for the "delegate" role. In the screenshot below we are adding a rule such that everyone is considered a delegate to this subscription, and will be able to run perform documents on it.

The GRIA client allows you to destroy any of the resources for which you have the owner PBAC role. To do this simply right click on the resource and select "Destroy".
When destroying a data resource that was created by the OGSA-DAI service (ie. by using the create new data resource feature), all tables and data in that database will be removed from the RDBMS.
Destroying a data resource that already existed (and was configured using the connect existing database feature) will only remove the link between the OGSA-DAI service and the back-end, and will leave the data intact.
Destroying a database will cause all roles and subscriptions on the database to be destroyed in addition to the database resource itself.
Destroying a role resource will also destroy any subscriptions that use that role.
Note you cannot destroy roles that were automatically created by the OGSA-DAI service. These roles exist until the database that they belong to is destroyed.
Removing a subscription resource will prevent any further queries from being run using that subscription.
The GRIA OGSA-DAI service makes use of functions written in the plpgsql language. Before using the GRIA OGSA-DAI service, you need to enable this language in the template database.
Due to a limitation of PostgreSQL, it is not possible to automatically set the correct permissions on new tables on databases created by the OGSA-DAI service. After executing a CREATE TABLE command, you are required to execute the following function:
SELECT grant_access_to_table(table_name);
For example, to create a table named testtable, you should perform the following SQL queries:
CREATE TABLE testtable (testcolumn TEXT);
SELECT grant_access_to_table('testtable');
Note that this is only necessary on databases created by users of the OGSA-DAI service. It is not needed for existing databases that have been connected to the service.
Please see the JavaDoc for a detailed descrition of the API.
The GRIA API is used to create and manage the GRIA resources representing databases, roles and subscriptions. See the AXIS plugin for OGSA-DAI clients document for instructions for using the OGSA-DAI API for OGSA-DAI operations (e.g. "perform").
To use the GRIA OGSA-DAI libraries from your own application, ensure that all of the following are in your application's classpath:
The WSDD file causes messages to be signed correctly and contains type mappings telling Axis how to serialise various types.
The crypto.properties file from the client's conf directory, which gives details of the keystore to use.
A StateRepository stores resources (accounts, SLAs, databases, roles and subscriptions) and services. There are two implementations provided with the GRIA library:
To create a new memory repository:
StateRepository repository = new MemoryStateRepository();
To create a new repository that stores its state in a file called client.state (this is what the standard client uses):
StateRepository repository = new FileStateRepository("client.state");
It is probably easiest to use FileStateRepository as you can create objects using the standard client and then use them from your own program.
Just as when using the graphical client interface, services must be added to the repository before they can be used. All the details about an object in a StateRepository are represented as a WS-Addressing EndpointReference. For example, to add a RemoteOgsaDaiService proxy to an OGSA-DAI service:
EndpointReference serviceEPR = new EndpointReference("https://.../services/DataService");
RemoteOgsaDaiService ogsaDaiService = repository.getOrCreateObject(RemoteOgsaDaiService.class, serviceEPR);
The getOrCreateObject method takes an EPR for the object you want, and a Java interface for the resulting object. If the object is already in the respository then it returns it, otherwise it creates a new one, adds it to the repository, and returns that.
For methods which create new resources, the client software will automatically add a SOAP header containing the billing information (i.e. the ID of the SLA managing the resource).
The following methods will be the most useful when using the OGSA-DAI service. For a full list of classes and methods see the Javadoc.
Methods on RemoteOgsaDaiService (the service) Methods on RemoteOgsaDaiServiceHelpers (the client's service helper class)Many classes have the following common methods:
The SOAP messages that are generated by the OGSA-DAI client-side library require slight modifications to become compatible with the GRIA OGSA-DAI client. These modifications include:
These modifications are performed by an AXIS message handler chain - a collection of Java classes that can change the SOAP message at various stages during its processing. More information about message handlers is available in the Axis documentation.
In order to use the GRIA OGSA-DAI service in an existing OGSA-DAI client application, you must bundle the following additional JAR files with your application:
From the GRIA client distribution:
From the GRIA OGSA-DAI Client distribution:
GRIA uses an ImplementationFactory class to locate implementations for a given interface. You should add the following line to an implementationfactory.properties in your classpath:
uk.ac.soton.itinnovation.grid.utils.Transport = uk.ac.soton.ecs.iam.grid.comms.client.AxisTransport
The message handlers need to use a certificate to sign all outgoing SOAP messages. Information about which certificate to use is held in a crypto.properties file loaded from the classpath. Your application should prompt the user for a keystore and generate this file automatically.
A sample crypto.properties file is shown below:
org.apache.ws.security.crypto.merlin.file=/home/bob/my-keystore.ks
org.apache.ws.security.crypto.merlin.keystore.password=password
org.apache.ws.security.crypto.merlin.keystore.alias=Bob
org.apache.ws.security.crypto.merlin.alias.password=password
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=JKS
The GRIA Client generates a crypto.properties file the first time it is run, saving it in the conf directory relative to the gridcli executable. If you have used the GRIA Client before you can use this file to test your OGSA-DAI application.
Note that your application will need to tell Java to use your keystore before making any calls to OGSA-DAI. This can be done by using the OgsaDaiSSLHelper class once on application startup:
OgsaDaiSSLHelper.setupKeystore();
Axis loads a client-config.wsdd file from the classpath to retrieve information about the message handler chains you wish to use in your application.
A suitable client-config.wsdd file is shown below. If you already have such a file in your application you will need to adapt it to include the sections shown in this example.
<?xml version='1.0'?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:grid-acct="http://www.it-innovation.soton.ac.uk/uk/ac/soton/itinnovation/grid/service/types"
xmlns:grid="http://www.it-innovation.soton.ac.uk/2004/grid"
xmlns:service-types="http://www.it-innovation.soton.ac.uk/uk/ac/soton/itinnovation/grid/service/types"
xmlns:grid-types="http://www.it-innovation.soton.ac.uk/uk/ac/soton/itinnovation/grid/types"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<parameter name="attachment_encapsulation_format" value="axis.attachment.style.dime"/>
<parameter name="disablePrettyXML" value="true"/>
<parameter name="enableNamespacePrefixOptimization" value="false" />
<parameter name="enableSignatureConfirmation" value="false"/> <!-- Needed for .NET compat -->
<requestFlow>
<handler type="java:uk.ac.soton.itinnovation.grid.client.ogsadai.OgsaDaiRequestHandler" />
<handler type="java:uk.ac.soton.itinnovation.grid.utils.wss4j.handler.WSOutboundHandler" >
<handler type="java:uk.ac.soton.itinnovation.grid.client.ogsadai.OgsaDaiSAMLHandler" >
<parameter name="action" value="Timestamp Signature"/>
<parameter name="signaturePropFile" value="crypto.properties" />
<parameter name="signatureKeyIdentifier" value="DirectReference" />
<parameter name="signatureParts" value="{}{http://schemas.xmlsoap.org/soap/envelope/}Body;{}{http://it-innovation.soton.ac.uk/2005/grid}ConversationID;{}{http://it-innovation.soton.ac.uk/2005/grid}BillingInformation;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{}{http://it-innovation.soton.ac.uk/2005/grid}OwnerRule"/>
<parameter name="passwordCallbackClass"
value="uk.ac.soton.itinnovation.grid.utils.PWCallback"/>
</handler>
</requestFlow>
<responseFlow>
<handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
<parameter name="action" value="Signature"/>
<parameter name="signaturePropFile" value="crypto.properties" />
</handler>
</responseFlow>
</globalConfiguration>
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<typeMapping qname="grid-types:X509Certificate"
languageSpecificType="java:java.security.cert.X509Certificate"
serializer="uk.ac.soton.itinnovation.grid.types.CertificateSerializerFactory"
deserializer="uk.ac.soton.itinnovation.grid.types.CertificateDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="wsa:EndpointReferenceType"
languageSpecificType="java:org.apache.axis.message.addressing.EndpointReferenceType"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="wsa:ReferenceParametersType"
languageSpecificType="java:org.apache.axis.message.addressing.ReferenceParametersType"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="xsd:anyURI"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
languageSpecificType="java:java.net.URL"
serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:SLATemplate"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.SLATemplate"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:SLAProposal"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.SLAProposal"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:Constraint"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.Constraint"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:Bound"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.Bound"
serializer="org.apache.axis.encoding.ser.EnumSerializerFactory"
deserializer="org.apache.axis.encoding.ser.EnumDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:TimePeriod"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.TimePeriod"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:PermittedService"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.PermittedService"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:Metric"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.Metric"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:PricingTerm"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.PricingTerm"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="grid-acct:StatementEvent"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.StatementEvent"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="grid-acct:AccountStatement"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.AccountStatement"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="grid-types:SubjectDescription"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.types.SubjectDescription"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="grid:IDType"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.types.IDType"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="grid-acct:account-statementType"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.AccountStatement"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="grid-types:MatchRule"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.types.MatchRule"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:UsageReport"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.UsageReport"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<typeMapping qname="service-types:Metric"
languageSpecificType="java:uk.ac.soton.itinnovation.grid.service.types.Metric"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle=""/>
<!-- This prevents "Could not convert org.apache.axis.types.URI" errors when sending EndpointReferenceTypes as arguments -->
<typeMapping qname="wsa:AttributedURI"
languageSpecificType="java:org.apache.axis.message.addressing.AttributedURI"
serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
encodingStyle=""/>
<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender"/>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
</deployment>
If access to a data resource subscription is controlled by a membership group (i.e. a SAML token is required to use it) then the token must be included in the OGSA-DAI API calls made to the service. This is done through one of the Axis handlers. The token is retrieved from the same default membership group as used in the normal GRIA client and the configuration is stored in the client.state file.
Run the GRIA Client as normal, drag the wsdl link from your membership service in to the client. Right click on the group you want to make your default and select "Set as default group"
Client selecting default membership group
Copy the client.state file from the gria client in to the classpath of your application.
It is recommended that you backup the client.state file in your copy of the GRIA Client prior to this process and remove this client.state file from the GRIA client's classpath. This will make a fresh client.state file when you do the above process.
Full documentation for creating an OGSA-DAI client is available in the OGSA-DAI documentation. This page aims to provide a simple example to get started with the OGSA-DAI client library.
Before trying this example remember to follow the instructions on Setting up Message Handlers.
import java.sql.ResultSet; import uk.ac.soton.itinnovation.grid.client.ogsadai.OgsaDaiSSLHelper; import uk.org.ogsadai.client.toolkit.GenericServiceFetcher; import uk.org.ogsadai.client.toolkit.ResourceID; import uk.org.ogsadai.client.toolkit.Response; import uk.org.ogsadai.client.toolkit.activity.ActivityRequest; import uk.org.ogsadai.client.toolkit.activity.sql.SQLQuery; import uk.org.ogsadai.client.toolkit.activity.sql.WebRowSet; import uk.org.ogsadai.client.toolkit.properties.DAIVersion; import uk.org.ogsadai.client.toolkit.service.DataService; public class Test { public static void main(String[] args) { try { // Loads the keystore specified in the crypto.properties file // This only needs to be done once on application startup. OgsaDaiSSLHelper.setupKeystore(); // This is the URL of the GRIA OGSA-DAI service String handle = "https://www.changeme.com:8443/gria-ogsadai-service/services/OgsaDaiServiceI2"; DataService service = GenericServiceFetcher.getInstance().getDataService(handle, null); // Fetch the OGSA-DAI version DAIVersion version = service.getVersion(); System.out.println("Version: " + version.getMajorVersion() + "." + version.getMinorVersion()); // Get a list of data resources we can access // This will return our database subscriptions // (those for which we have the "owner" or "client" role) ResourceID[] resources = service.getResourceIDs(); for (int i=0; i<resources.length; i++) { System.out.println(resources[i].getName()); } if (resources.length < 1) return; // In this example we shall perform a query on the first subscription that is returned service.setResourceID(resources[0]); // Create a query to list the tables in the database SQLQuery query = new SQLQuery("show tables"); WebRowSet rowset = new WebRowSet(query.getOutput()); ActivityRequest request = new ActivityRequest(); request.add(query); request.add(rowset); // Perform the request Response response = service.perform(request); // Get and display the results ResultSet result = rowset.getResultSet(); while (result.next()) { String tableName = result.getString(1); System.out.println(tableName); } } catch (Throwable e) { e.printStackTrace(); } } }
The service comes complete with interfaces to MySQL and PostgreSQL. There are minor differences between the required interface for one JDBC database and another. To integrate the GRIA OGSA-DAI service with a different JDBC database, follow the method below.
In order to add a completely different data resource to the service, implementations for several interfaces must be written. The implementations are loaded through the ImplementationFactory and the implementing classes must be defined in the implementationfactory.properties file.
The GRIA OGSA-DAI service makes the distinction between connecting and creating data resources and data resource roles (e.g. databases and database users). The term "connecting" means configuring the service to make use of pre-existing data resources or users. The term "creating" refers to the service instructing the back-end system to create new data resources or users. A new implementation may want to just provide the facility to connect to existing data resources.
The abstract class OgsaDaiDataResourceManager is the OGSA-DAI service's implementation of the DataResourceManager interface. It contains convenience functions useful for handling OGSA-DAI configuration files. It must be extended by a class specific to the back-end system. The only class that extends it so far is the RDBMSDataResourceManager.
One of the functions of the DataResourceManager is to connect an existing data resource. In order to do this, a new OGSA-DAI instance must be created and deployed. The RDBMSDataResourceManager creates the configuration files of the new OGSA-DAI instance by using template files contained within WEB-INF/etc/skeletons in the GRIA OGSA-DAI webapp. The templates are transformed into complete configuration files and written into the defined configuration directory of the GRIA OGSA-DAI service.
Two of the methods of DataResourceManager are createDataResource and connectDataResource
This is used by both the web interface and SOAP clients to provide presentation information about the OgsaDaiDataResourceManager subclass that is being used. The only class that implements it so far is RDBMSPresentation, which through the implementation of the DataResourceManager (see above) also saves the configuration data entered in the web interface. When extending OgsaDaiDataResourceManager another implementation for this class must also be written.
The OGSA-DAI RoleMapper provides the OGSA-DAI SQL activities with credentials for data resources they need to access. The interface defined by OGSA-DAI takes a string defining the credentials and a string defining the database to be used and returns an OGSA-DAI Role object containing whatever is required to log in to the database.
For the GRIA OGSA-DAI service RDBMSSubscriptionRoleMapper has been written. It takes a DataResourceSubscription ID for the credentials and a DataResource ID for the database specifier. As the DataResourceSubscription is already in the context of a user on a database, it just uses the DataResourceSubscription to retrieve the username and password from the parent DataResourceRole object and returns them in the OGSA-DAI DatabaseRole object (a standard implementation of Role).
It is suggested that custom OGSA-DAI activities also use the RoleMapper system for obtaining login credentials. If the database login only requires a username and password then the existing implementation (RDBMSSubscriptionRoleMapper) will be sufficient, otherwise another implementation for this class and for the OGSA-DAI Role class must also be written.
A whitelist of permitted OGSA-DAI activities is specified in the activityConfig.xml file in OGSA-DAI's configuration directory. This file is generated by RDBMSDataResourceManager from a template (WEB-INF/etc/skeletons/activityConfigRelational.xml in the webapp). In order to support new types of activity, a replacement for RDBMSDataResourceManager would have to be created to generate these different configuration files (see above). This new implementation would also need to interface differently with whatever back-end it used (RDBMS has a BackendHelper to do this). It would likely still be able to use OgsaDaiInstance (a protected field inherited from OgsaDaiDataResourceManager) to deploy and undeploy data resources on OGSA-DAI.
The GRIA OGSA-DAI service client plug-in provides maangement abilities for OGSA-DAI resources. For subscription resources it also has menu options for executing SQL select and update statements. These methods are provided just for convenience and it is not expected that anyone would use them for serious work. It would be possible to write an alternative client plug-in that provided similar convenience methods for whatever operations were useful for the alternative back-end.
In some cases, an Activity executed by the OGSA-DAI service may require the identity details (X.509 distinguished name, additional tokens, etc) of the client that invoked the service. These details are available from the user's SubjectDescription object. This is stored in a HashMap keyed off the unique name of each activity.
The following is an example of using the current users SubjectDescription to make a call on another GRIA OGSA-DAI Service. The example is of the processBlock method in an OGSA-DAI activity implementation.
public void processBlock() { StateRepository repos = new MemoryStateRepository(); EndpointReferenceType epr = ConversationID.getEPR("https://bodegas.it-innovation.soton.ac.uk:8443/gria-ogsadai-service/services/OgsaDaiSubscription#ff808181-14fede48-0114-fef342c9-0006"); OgsaDaiSubscriptionConversation convo = repos.getOrCreateObject(OgsaDaiSubscriptionConversation.class, epr); try { //getName() returns a unique string for each activity instance. //The SubjectDescription of the user that made the perform call that initiated the activity //Is stored in the OgsaDaiServiceImpl.activityClientMap SubjectDescription client = OgsaDaiServiceImpl.activityClientMap.get(getName()); convo.checkPolicyRule(client,"perform"); } catch (RemoteException e) { setError(e); } }
One specific example where the client's credentials are required is when the OGSA-DAI service is acting on behalf of many clients, for instance if the OGSA-DAI service is installed as an intermediary between the client and the final GRIA OGSA-DAI service. This situation is represented in a simplified form in the following figure.
A GRIA OGSA-DAI service acting as an intermediary
In the figure, Client A sends a request to Service B (step 1). Service B executes an OGSA-DAI activity that requires access to Service C (for instance, Service B may be in place to rewrite the query in a different query language). For Service B to access Service C (step 3) it must be authorised in the usual way on Service C, but it is a security loop-hole if step 3 is carried out with no further access control checks. In step 2, Service B checks that Client A is permitted to access Service C and only if Client A can access Service C will Service B access Service C on Client A's behalf.
There is no context displayed in the figure, instead the context of each call is listed below:
For this scenario to operate, Client A will have to authorise Service B to use Client A's data resource subscription at Service C (e.g. as a "delegate").
With these steps in place Client A can only access data at Service C that Client A is permitted to see. If step 2 is not used then a different client ("Client Z") who was authorised on Service B but not Service C, could find out the endpoint reference of Client A's subscription at Service C and perform the same query on Service B as above. Service B would then blindly perform a query on Service C and return the results to Client Z, exposing the data.