Access Keys:
Skip to content (Access Key - 0)

GME


GME 1.4 Developers Guide


caGrid 1.4 Documentation    |  GME 1.4 Documentation  |  GME 1.4 Developers Guide ]


GME Overview


The Global Model Exchange (GME) Grid Service is a simple, stateless service, created with Introduce, which acts as an authoritative XML Schema registry for the grid. It's primary function is to ensure global referential integrity of all the XML Schemas used on the grid, and provide operations for their registration and discovery. It provides utility APIs for uploading from and downloading to a local file system, graphical interfaces, and integration into as a data type discovery mechanism.

Service Operations Overview


The GME, as an XML Schema registry, supports basic publish, update, delete, and retrieve operations. XML Schemas (represented using XMLSchema) are uniquely identified by GME using their target namespaces (represented using XMLSchemaNamespace).

The publishXMLSchemas operation is used for all publish and update operations (Note: update is not yet supported in the current version of the GME but will use this operation when it is). It is used to store new XML Schemas in the GME, and the schemas that are published are required to be fully defined (i.e., all imported schemas must be valid and present), using the combination of XML Schemas supplied and those already published. For example, if one uploads XML Schema "A" that imports XML Schema "B," the "B" XML Schema must already be published or be contained in the array of the XMLSchema being published. For more information on the processing behavior of the publish operation, see the GME Design Guide.

Once an XML Schema is published, the GME provides various operations for viewing information about the schema, including its dependencies (getImportedXMLSchemaNamespaces) and the schemas that depend upon it (getImportingXMLSchemaNamespaces). It can then be downloaded via the getXMLSchema operation, which only retrieves that particular schema, or the getXMLSchemaAndDependencies operation, which returns an XMLSchemaBundle containing that schema and every schema required to fully resolve its dependencies (this could be a complex graph of schemas).

The client API provides some convenience methods in the org.cagrid.gme.client.GlobalModelExchangeClient class. A method named cacheSchemas internally calls the getXMLSchemaAndDependencies operation, and writes all of the retrieved schemas to the file system, handling any potential naming conflicts. A method named validateXML validates an XML document in String using the namespace of the document's root element to retrieve the schema from GME. A similar method named validateXMLFile validates an XML document in a file.

The GME allows one to retrieve the list of targetNamespaces of all of its published XML Schemas via the getXMLSchemaNamespaces operation. Finally, it allows a collection of XML Schemas to be deleted via the deleteXMLSchemas operation. Similar to the publishXMLSchemas operation, this takes an array of XML Schemas (actually just their targetNamespace) so that a schema and all of the schemas that depend upon it can be deleted at the same time. This is because attempting to delete a schema which has other schemas depending upon it will generate an error. For more information on the processing behavior of the delete operation, see the GME Design Guide.

GME Class Model


All operations of the GME work with the Class Model shown below, which is a representational model for describing XML Schemas and their dependencies.

The primary means by which an XML Schema is identified by external entities is its targetNamespace (see the XML Schema Specification). This is a URI, and is represented as such in the GME model when used as an attribute within a class (such as in the XMLSchema class), but is represented using the XMLSchemaNamespace when used by itself (such as when it is the input or output of an operation).

XML Schemas can be comprised of multiple actual "documents." As such, the GME model represents XML Schemas using the XMLSchema class, which consists of one or more XMLSchemaDocuments. An XMLSchema has a targetNamespace a "root" document (XMLSchemaDocument), and zero or more additional documents (XMLSchemaDocuments). Each XMLSchemaDocument has a unique (within an XMLSchema) identifier, represented by the systemID attribute (see the XML Specification), and the actual text of the document, represented by the schemaText attribute.

The XMLSchema, XMLSchemaDocument, and XMLSchemaNamespace are the only Classes the GME client uses to describe XML Schemas to the GME service. The GME service uses two additional Classes, XMLSchemaBundle and XMLSchemaImportInformation to describe, to the client, additional details about how XML Schemas relate to each other. The XMLSchemaImportInformation Class is used to describe the set of XML Schemas (identified via a set of XMLSchemaNamespace representing their targetNamespaces) imported by a given XML Schema (identified via its targetNamespace). The XMLSchemaBundle class conceptually represents a graph of XML Schemas. It is a complex data structure which contains a set of XMLSchema and a set of XMLSchemaImportInformation and utility methods to interrogate those sets, such as getImportedSchemasForTargetNamespace{*}.

The GME is able to provide a class model with complex data structures (such as using Java5 typed collections) and utility operations as it leverages Castor for serialization and deserialization into custom, hand-written Java Beans.

Migrating from the Deprecated GME


Previous versions of caGrid included a conceptually similar but functionally different GME. There is no API-level equivalency between these projects, as the current GME is a ground up redesign aimed at addressing the limitations of the previous GME. For example, the current GME models XML Schemas as being comprised of one or more XML Schema Documents. This allows it to support such features as xsd:include and xsd:redefine. Additionally, the current GME allows multiple schemas to be published at the same time, whereas the previous implementation only allowed a single document to be published at a time. This prevented XML Schemas with cyclic imports (i.e., A imports B imports A) from being published as their dependencies could never be resolved; the new GME supports processing such schemas.

In using the new GME, the basic workflow of the API is similar to the previous API. However, the current client API, now being a standard Introduce-created service, follows the expected usage, whereas the previous API required using a specialized Mobius API to leverage the grid service; this is no longer necessary.

Using the GME User Interface


The GME provides graphical user interface components via integration with the Introduce service development environment; even if you aren't planning to develop services, you may use this capability. The integration takes two forms: 1) a general ability to view, download, and upload XML Schemas, described in the GME Browsing and Upload section and 2) an ability to add XML Schemas from a GME to an Introduce service, described in the GME Schema Discovery section.

The GME with which Introduce will communicate is configured via the GME Service URL value in the Global Extension Properties in the Introduce Preferences. Generally this value is automatically set when you configure caGrid to use a particular grid.

GME Browsing and Upload


To use the GME's ability to upload, view, or download schemas, you must first launch Introduce, by typing 'ant introduce' from the caGrid directory, as described in the Introduce documentation. Once Introduce has launched, click the Browse Data Types button on the top toolbar and click the Global Model Exchange tab on the Browse Data Types window that opens up (shown below).

This window initially shows the "Browse" tab and contains a drop-down menu labeled "Target Namespace", which is populated with all of the targetNamespaces of the XML Schemas which have been published to the GME. Selecting a particular namespace will display the text of the root document of the XML Schema with the corresponding targetNamespace, in the text area labeled "Schema Root Document Text." You can also download the schema and all of its dependencies to a directory on your local file system by selecting its namespace and pressing the "Download Schemas and Dependencies..." button. This will prompt you for a directory, and will then write all of the files to the selected directory. This uses the API described in the Retrieving an XML Schema Bundle example.

Upon switching to the "Upload" tab, a user interface for publishing schemas to the GME is shown. The top window of the panel shows any errors which currently exist in the submission package (Note: it initially displays an error indicating no schemas have been selected to be published).

The Add Schemas... button can be used to launch a file browser to locate schemas from the local file system which should be published. This can be used repeatedly to locate all schemas that should be uploaded as a group. In the even that a scheme must be removed because it contains an error or was accidentally added, select it and press the Remove Selected Schema button (NOTE: this removes it from the schema submission package, not the server). For each schema added to the submission package, it will be shown in the "XML Schemas" panel, as represented by its targetNamespace. Upon selecting one of these namespaces, the "Documents Comprising Selected Schema" panel will be populated with the actual XML Schema Documents needed to comprise this schema. For most cases, this will just be the single schema file which was selected, but for schemas that make use of xsd:redefine or xsd:include, multiple documents may be shown (NOTE: to add schemas which make use of xsd:include or xsd:redefine, select the "root" schema and the other documents will automatically be added). Selecting a document from this list will display its textual content in the "Schema Preview" panel. The screen shot below illustrates the interface when a single XML Schema that consists of two actual documents is to be published. Once all desired XML Schemas have been added to the interface and there are no errors shown in the top panel, click the Publish Schemas button. If this completes without error, a success dialog will display, and the schemas should be able to be found using the "Browse" tab of the same window after pressing the Refresh button.

GME Schema Discovery

When doing service development with Introduce, a key aspect is to be able to discover and add data types (in the form of XML Schemas) for use in the service's operations. To facilitate the use of the GME for this purpose, a GME data type discovery extension (see the Introduce design guide) is provided. Shown below, this component embeds itself into the "Import Data Types" panel of the "Types" tab. Its use is fairly straightforward, as a drop-down menu of the currently published XML Schemas represented by their targetNamespacess is shown, and when the Add button is pressed, the selected schema and all of its dependencies are downloaded and added to the service. For example, in the screen-shot below, when the "gme://a" schema was added, the "gme://b" schema was also added because "gme://a" imports it. Accordingly, so was "gme://c" because "gme://b" imports it, as shown in the "Imported Data Types" window on the left of the screen shot.

Security Considerations


Because the GME is typically deployed as a secure service (though currently it is not strictly required by the GME), one must synchronize with a trust fabric as described in the GTS Developer's Guide in order to use its client API. Failure to do so may yield exceptions similar to the stack trace shown below. Be sure to pay particular attention to the "Caused by: Unknown CA" message.

AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode:
 faultString: org.globus.common.ChainedIOException: Authentication failed [Caused by: Failure unspecified at GSS-API level [Caused by: Unknown CA]]
 faultActor:
 faultNode:
 faultDetail:
	{http://xml.apache.org/axis/}stackTrace:Authentication failed. Caused by Failure unspecified at GSS-API level. Caused by COM.claymoresystems.ptls.SSLThrewAlertException: Unknown CA
	at COM.claymoresystems.ptls.SSLConn.alert(SSLConn.java:235)
	at COM.claymoresystems.ptls.SSLHandshake.recvCertificate(SSLHandshake.java:304)
	at COM.claymoresystems.ptls.SSLHandshakeClient.processTokens(SSLHandshakeClient.java:128)
	at COM.claymoresystems.ptls.SSLHandshake.processHandshake(SSLHandshake.java:135)
	at org.globus.gsi.gssapi.GlobusGSSContextImpl.initSecContext(GlobusGSSContextImpl.java:483)
	at org.globus.gsi.gssapi.net.GssSocket.authenticateClient(GssSocket.java:102)
	at org.globus.gsi.gssapi.net.GssSocket.startHandshake(GssSocket.java:140)
	at org.globus.gsi.gssapi.net.GssSocket.getOutputStream(GssSocket.java:161)
	at org.apache.axis.transport.http.HTTPSender.writeToSocket(HTTPSender.java:433)
	at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:135)
	at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
	at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
	at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
	at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
	at org.apache.axis.client.Call.invokeEngine(Call.java:2727)
	at org.apache.axis.client.Call.invoke(Call.java:2710)
	at org.apache.axis.client.Call.invoke(Call.java:2386)
	at org.apache.axis.client.Call.invoke(Call.java:2309)
	at org.apache.axis.client.Call.invoke(Call.java:1766)
	at org.cagrid.gme.stubs.bindings.GlobalModelExchangePortTypeSOAPBindingStub.getServiceSecurityMetadata(GlobalModelExchangePortTypeSOAPBindingStub.java:1520)
	at org.cagrid.gme.client.GlobalModelExchangeClient.getServiceSecurityMetadata(GlobalModelExchangeClient.java:87)
	at gov.nih.nci.cagrid.introduce.security.client.ServiceSecurityClient.configureStubSecurity(ServiceSecurityClient.java:210)
	at org.cagrid.gme.client.GlobalModelExchangeClient.getXMLSchemaNamespaces(GlobalModelExchangeClient.java:122)
	at DevelopersGuideExamples.main(DevelopersGuideExamples.java:16)

	{http://xml.apache.org/axis/}hostname:meadowgrain.local

org.globus.common.ChainedIOException: Authentication failed [Caused by: Failure unspecified at GSS-API level [Caused by: Unknown CA]]
	at org.apache.axis.AxisFault.makeFault(AxisFault.java:101)
	at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:144)
	at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
	at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
	at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
	at org.apache.axis.client.AxisClient.invoke(AxisClient.java:165)
	at org.apache.axis.client.Call.invokeEngine(Call.java:2727)
	at org.apache.axis.client.Call.invoke(Call.java:2710)
	at org.apache.axis.client.Call.invoke(Call.java:2386)
	at org.apache.axis.client.Call.invoke(Call.java:2309)
	at org.apache.axis.client.Call.invoke(Call.java:1766)
	at org.cagrid.gme.stubs.bindings.GlobalModelExchangePortTypeSOAPBindingStub.getServiceSecurityMetadata(GlobalModelExchangePortTypeSOAPBindingStub.java:1520)
	at org.cagrid.gme.client.GlobalModelExchangeClient.getServiceSecurityMetadata(GlobalModelExchangeClient.java:87)
	at gov.nih.nci.cagrid.introduce.security.client.ServiceSecurityClient.configureStubSecurity(ServiceSecurityClient.java:210)
	at org.cagrid.gme.client.GlobalModelExchangeClient.getXMLSchemaNamespaces(GlobalModelExchangeClient.java:122)
	at DevelopersGuideExamples.main(DevelopersGuideExamples.java:16)
Caused by: org.globus.common.ChainedIOException: Authentication failed [Caused by: Failure unspecified at GSS-API level [Caused by: Unknown CA]]
	at org.globus.gsi.gssapi.net.GssSocket.startHandshake(GssSocket.java:145)
	at org.globus.gsi.gssapi.net.GssSocket.getOutputStream(GssSocket.java:161)
	at org.apache.axis.transport.http.HTTPSender.writeToSocket(HTTPSender.java:433)
	at org.apache.axis.transport.http.HTTPSender.invoke(HTTPSender.java:135)
	... 14 more

Code Examples


Be sure to note the information in the Security Considerations section before running these examples. These examples make use of the caGrid Training Grid.

Further examples of use of the GME API can be found in the globalModelExchange-ui project, which contains the source code for the user interface components described above in the user interface section.

Prerequisites

To get started developing against the GME APIs, the project will require the Java libraries found in the GME project's ext/dependencies/jars directory and those in its build/lib directory.

Developers using Ivy to integrate with the caGrid build artifacts may use the following line in their dependencies:

<dependency rev="1.3" org="caGrid" name="globalModelExchange" conf="client"/>

Listing the Published XML Schemas

The code shown below prints the list of the targetNamespaces of the published XML Schemas.

import java.rmi.RemoteException;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
import org.cagrid.gme.domain.XMLSchemaNamespace;


public class DevelopersGuideExamples {

    public static void main(String[] args) {

        try {
            GlobalModelExchangeClient gme = new GlobalModelExchangeClient(
                "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange");

            XMLSchemaNamespace[] namespaces = gme.getXMLSchemaNamespaces();
            if (namespaces != null && namespaces.length > 0) {
                System.out.println("The GME has published XML Schemas with the following namespaces:");
                for (XMLSchemaNamespace ns : namespaces) {
                    System.out.println("\t"+ns);
                }
            } else {
                System.out.println("The GME has no published schemas.");
            }

        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        }

    }
}

Retrieving an XML Schema

The code example below shows how to acquire the text of a given schema, as identified by its targetNamespace. Note the NoSuchNamespaceExistsFault addition to the catch block, which will be raised by the GME if the requested XML Schema has not been published.

import java.net.URISyntaxException;
import java.rmi.RemoteException;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
import org.cagrid.gme.domain.XMLSchema;
import org.cagrid.gme.domain.XMLSchemaDocument;
import org.cagrid.gme.domain.XMLSchemaNamespace;
import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault;


public class DevelopersGuideExamples {

    public static void main(String[] args) {

        try {
            GlobalModelExchangeClient gme = new GlobalModelExchangeClient(
                "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange");

            XMLSchemaNamespace schemaTargetNamespace = new XMLSchemaNamespace(
                "gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata");
            XMLSchema schema = gme.getXMLSchema(schemaTargetNamespace);
            XMLSchemaDocument rootDocument = schema.getRootDocument();
            System.out.println("The XML Schema with targetNamespace " + schema.getTargetNamespace()
                + " has the following text:\n" + rootDocument.getSchemaText());

        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (URISyntaxException e) {
            // TODO handle the case where the schemaTargetNamespace is
            // constructed with an invalid URI
            e.printStackTrace();
        } catch (NoSuchNamespaceExistsFault e) {
            // TODO handle the case where the schema requested is not actually
            // published
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        }

    }
}


Running this code should yield the output shown below:

The XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata has the following text:
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:cagrid="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
    xmlns:serv="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
    xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
    elementFormDefault="qualified">

    <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
        schemaLocation="common/common.xsd" />
    <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
        schemaLocation="service/servicemodel.xsd" />

    <xs:element name="ServiceMetadata" type="cagrid:ServiceMetadata" />
    <xs:complexType name="ServiceMetadata">
        <xs:sequence>
            <xs:element name="serviceDescription">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="serv:Service" minOccurs="0" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="hostingResearchCenter">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="com:ResearchCenter" minOccurs="0" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Retrieving an XML Schema Bundle

If you inspect the example above, and the output it produces, you'll notice we only retrieved the actual text of the specific schema we requested and that schema contains xsd:imports of two other schemas not retrieved from the GME. This example extends the previous example by requesting the GME to return all such imported schemas, as well as any they may import and so on, such that we have all such referenced schemas.

import java.net.URISyntaxException;
import java.rmi.RemoteException;
import java.util.Set;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
import org.cagrid.gme.domain.XMLSchemaBundle;
import org.cagrid.gme.domain.XMLSchemaNamespace;
import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault;


public class DevelopersGuideExamples {

    public static void main(String[] args) {

        try {
            GlobalModelExchangeClient gme = new GlobalModelExchangeClient(
                "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange");

            XMLSchemaNamespace schemaTargetNamespace = new XMLSchemaNamespace(
                "gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata");

            XMLSchemaBundle schemaBundle = gme.getXMLSchemaAndDependencies(schemaTargetNamespace);
            Set<XMLSchemaNamespace> schemaTargetNamespaces = schemaBundle.getXMLSchemaTargetNamespaces();
            System.out.println("Fully retrieving the XML Schema with targetNamespace " + schemaTargetNamespace
                + " requires the following XML Schemas:");

            System.out.println("==================================================");
            for (XMLSchemaNamespace ns : schemaTargetNamespaces) {
                System.out.println("--------------------------------------------------");
                System.out.println("\t" + ns);
                System.out.println("--------------------------------------------------");
                // extract the schema from the bundle, and print its root
                // document's text
                System.out.println(schemaBundle.getXMLSchemaForTargetNamespace(ns).getRootDocument().getSchemaText());

            }

        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (URISyntaxException e) {
            // TODO handle the case where the schemaTargetNamespace is
            // constructed with an invalid URI
            e.printStackTrace();
        } catch (NoSuchNamespaceExistsFault e) {
            // TODO handle the case where the schema requested is not actually
            // published
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        }
    }
}


Running the example above should yield output similar to the following:

Fully retrieving the XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata requires the following XML Schemas:
==================================================
--------------------------------------------------
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service
--------------------------------------------------
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:serv="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service" xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" elementFormDefault="qualified">
	<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" schemaLocation="../common/common.xsd"/>
	<xs:element name="Service" type="serv:Service"/>
	<xs:complexType name="Service">
		<xs:annotation>
			<xs:documentation>A service is a "conceptual" definition of a collection of functional contexts.
This has no physical manifestation in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element name="pointOfContactCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="com:PointOfContact" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="serviceContextCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="serv:ServiceContext" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element ref="serv:CaDSRRegistration" minOccurs="0"/>
			<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="name" use="required" type="xs:string"/>
		<xs:attribute name="version" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="Operation" type="serv:Operation"/>
	<xs:complexType name="Operation">
		<xs:annotation>
			<xs:documentation>This represents a method/operation/function in a service context.  Its input parameters are described by its InputParameter associations,  its output by its Output association, and any errors it produces by its Fault associations.

This is manifested as an operation of a service in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element name="inputParameterCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="serv:InputParameter" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element ref="serv:Output" minOccurs="0"/>
			<xs:element name="faultCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="serv:Fault" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="name" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="Output" type="serv:Output"/>
	<xs:complexType name="Output">
		<xs:annotation>
			<xs:documentation>Represents the result/output of an operation.  Its non-existence represents the operation produces no result.

This is manifested as the value of an operation response in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element ref="com:UMLClass" minOccurs="0"/>
		</xs:sequence>
		<xs:attribute name="dimensionality" use="required" type="xs:int">
			<xs:annotation>
				<xs:documentation>Only valid if isArray is true; indicates number of dimensions in the array</xs:documentation>
			</xs:annotation>
		</xs:attribute>
		<xs:attribute name="isArray" use="required" type="xs:boolean"/>
		<xs:attribute name="qName" use="required" type="xs:QName"/>
	</xs:complexType>
	<xs:element name="InputParameter" type="serv:InputParameter"/>
	<xs:complexType name="InputParameter">
		<xs:annotation>
			<xs:documentation>Represents an input parameter to an operation.

This is manifested as a parameter of a service request in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element ref="com:UMLClass" minOccurs="0"/>
		</xs:sequence>
		<xs:attribute name="dimensionality" use="required" type="xs:int">
			<xs:annotation>
				<xs:documentation>Only valid if isArray is true; represents the dimensionality of the array</xs:documentation>
			</xs:annotation>
		</xs:attribute>
		<xs:attribute name="index" use="required" type="xs:int">
			<xs:annotation>
				<xs:documentation>This is the 0-based index of the parameter in the operation's signature</xs:documentation>
			</xs:annotation>
		</xs:attribute>
		<xs:attribute name="isArray" use="required" type="xs:boolean"/>
		<xs:attribute name="isRequired" use="required" type="xs:boolean">
			<xs:annotation>
				<xs:documentation>Whether the given parameter is allowed to be null or not</xs:documentation>
			</xs:annotation>
		</xs:attribute>
		<xs:attribute name="name" use="required" type="xs:string"/>
		<xs:attribute name="qName" use="required" type="xs:QName"/>
	</xs:complexType>
	<xs:element name="Fault" type="serv:Fault"/>
	<xs:complexType name="Fault">
		<xs:annotation>
			<xs:documentation>This represents an error that could occur during the execution of the operation.

This is manifested as an operation fault in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence/>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="name" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="ServiceContext" type="serv:ServiceContext"/>
	<xs:complexType name="ServiceContext">
		<xs:annotation>
			<xs:documentation>This is a functional collection of operations that work over a common collection of stateful resources.
A service without stateful resources would have a single context.

This is manifested as an actual service in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element name="operationCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="serv:Operation" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="contextPropertyCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="serv:ContextProperty" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
		</xs:sequence>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="name" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="ContextProperty" type="serv:ContextProperty"/>
	<xs:complexType name="ContextProperty">
		<xs:annotation>
			<xs:documentation>This represents an exposed property of a service context's state.

This is manifested as a resource property in the grid.</xs:documentation>
		</xs:annotation>
		<xs:sequence/>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="name" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="CaDSRRegistration" type="serv:CaDSRRegistration"/>
	<xs:complexType name="CaDSRRegistration">
		<xs:sequence/>
		<xs:attribute name="registrationStatus" use="required" type="xs:string"/>
		<xs:attribute name="workflowStatus" use="required" type="xs:string"/>
	</xs:complexType>
</xs:schema>
--------------------------------------------------
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata
--------------------------------------------------
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:cagrid="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata"
    xmlns:serv="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
    xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
    elementFormDefault="qualified">

    <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
        schemaLocation="common/common.xsd" />
    <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
        schemaLocation="service/servicemodel.xsd" />

    <xs:element name="ServiceMetadata" type="cagrid:ServiceMetadata" />
    <xs:complexType name="ServiceMetadata">
        <xs:sequence>
            <xs:element name="serviceDescription">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="serv:Service" minOccurs="0" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="hostingResearchCenter">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element ref="com:ResearchCenter" minOccurs="0" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
--------------------------------------------------
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common
--------------------------------------------------
<?xml version="1.0"?>
<xs:schema targetNamespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:com="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common" elementFormDefault="qualified">
	<xs:element name="Enumeration" type="com:Enumeration"/>
	<xs:complexType name="Enumeration">
		<xs:sequence>
			<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="permissibleValue" use="required" type="xs:string"/>
		<xs:attribute name="valueMeaning" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="ValueDomain" type="com:ValueDomain"/>
	<xs:complexType name="ValueDomain">
		<xs:sequence>
			<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element name="enumerationCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="com:Enumeration" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
		</xs:sequence>
		<xs:attribute name="longName" use="required" type="xs:string"/>
		<xs:attribute name="unitOfMeasure" use="optional" type="xs:string"/>
	</xs:complexType>
	<xs:element name="SemanticMetadata" type="com:SemanticMetadata"/>
	<xs:complexType name="SemanticMetadata">
		<xs:sequence/>
		<xs:attribute name="conceptCode" use="required" type="xs:string"/>
		<xs:attribute name="conceptDefinition" use="required" type="xs:string"/>
		<xs:attribute name="conceptName" use="required" type="xs:string"/>
		<xs:attribute name="order" use="optional" type="xs:int"/>
		<xs:attribute name="orderLevel" use="optional" type="xs:int"/>
	</xs:complexType>
	<xs:element name="PointOfContact" type="com:PointOfContact"/>
	<xs:complexType name="PointOfContact">
		<xs:annotation>
			<xs:documentation>For the static model, instances of these should be the POCs associated with the design and implementation of the service itself (not deployments of it, e.g. not system support staff)

The "role" attribute should probably be an enumeration of known types</xs:documentation>
		</xs:annotation>
		<xs:sequence/>
		<xs:attribute name="affiliation" use="required" type="xs:string"/>
		<xs:attribute name="email" use="required" type="xs:string"/>
		<xs:attribute name="firstName" use="required" type="xs:string"/>
		<xs:attribute name="lastName" use="required" type="xs:string"/>
		<xs:attribute name="phoneNumber" use="optional" type="xs:string"/>
		<xs:attribute name="role" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="UMLClass" type="com:UMLClass"/>
	<xs:complexType name="UMLClass">
		<xs:annotation>
			<xs:documentation>caDSR-related

Represents the UML Class of the given input or output.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element name="umlAttributeCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="com:UMLAttribute" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
		</xs:sequence>
		<xs:attribute name="className" use="required" type="xs:string"/>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="id" use="required" type="xs:string">
			<xs:annotation>
				<xs:documentation>This is used soley for the purposes of referencing this class in associations.  It does not represent any caDSR identifier.</xs:documentation>
			</xs:annotation>
		</xs:attribute>
		<xs:attribute name="packageName" use="required" type="xs:string"/>
		<xs:attribute name="projectName" use="required" type="xs:string"/>
		<xs:attribute name="projectVersion" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="UMLAttribute" type="com:UMLAttribute"/>
	<xs:complexType name="UMLAttribute">
		<xs:annotation>
			<xs:documentation>caDSR-related

Represents a UML attribute of the parent UML Class.  Indication of isRequired=false means the operation will function without the existence of this attribute.</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element ref="com:SemanticMetadata" minOccurs="0" maxOccurs="unbounded"/>
			<xs:element ref="com:ValueDomain" minOccurs="0"/>
		</xs:sequence>
		<xs:attribute name="dataTypeName" use="required" type="xs:string"/>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="name" use="required" type="xs:string"/>
		<xs:attribute name="publicID" use="required" type="xs:long"/>
		<xs:attribute name="version" use="required" type="xs:float"/>
	</xs:complexType>
	<xs:element name="ResearchCenter" type="com:ResearchCenter"/>
	<xs:complexType name="ResearchCenter">
		<xs:sequence>
			<xs:element ref="com:Address" minOccurs="0"/>
			<xs:element ref="com:ResearchCenterDescription" minOccurs="0"/>
			<xs:element name="pointOfContactCollection">
				<xs:complexType>
					<xs:sequence>
						<xs:element ref="com:PointOfContact" minOccurs="0" maxOccurs="unbounded"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
		</xs:sequence>
		<xs:attribute name="displayName" use="required" type="xs:string"/>
		<xs:attribute name="shortName" use="required" type="xs:string"/>
	</xs:complexType>
	<xs:element name="Address" type="com:Address"/>
	<xs:complexType name="Address">
		<xs:sequence/>
		<xs:attribute name="country" use="required" type="xs:string"/>
		<xs:attribute name="locality" use="optional" type="xs:string"/>
		<xs:attribute name="postalCode" use="optional" type="xs:string"/>
		<xs:attribute name="stateProvince" use="optional" type="xs:string"/>
		<xs:attribute name="street1" use="required" type="xs:string"/>
		<xs:attribute name="street2" use="optional" type="xs:string"/>
	</xs:complexType>
	<xs:element name="ResearchCenterDescription" type="com:ResearchCenterDescription"/>
	<xs:complexType name="ResearchCenterDescription">
		<xs:sequence/>
		<xs:attribute name="description" use="required" type="xs:string"/>
		<xs:attribute name="homepageURL" use="required" type="xs:string"/>
		<xs:attribute name="imageURL" use="optional" type="xs:string"/>
		<xs:attribute name="rssNewsURL" use="optional" type="xs:string"/>
	</xs:complexType>
</xs:schema>

Downloading an XML Schema and its Dependencies

Extending upon the example above, we can use the cacheSchemas operation to get the XMLSchemaBundle and write it to the local filesystem. We can then walk the metadata returned from this operation to see where the files were written.

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.rmi.RemoteException;
import java.util.Map;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
import org.cagrid.gme.domain.XMLSchemaNamespace;
import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault;


public class DevelopersGuideExamples {

    public static void main(String[] args) {

        try {
            GlobalModelExchangeClient gme = new GlobalModelExchangeClient(
                "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange");

            XMLSchemaNamespace schemaTargetNamespace = new XMLSchemaNamespace(
                "gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata");

            File directory = new File(".", "gme_schemas");
            Map<XMLSchemaNamespace, File> cachedSchemas = gme.cacheSchemas(schemaTargetNamespace, directory);
            System.out.println("Downloaded the XML Schema with targetNamespace " + schemaTargetNamespace
                + ", and its dependencies, to the local file system directory:" + directory);

            System.out.println("The schemas were written to the following files:");
            for (XMLSchemaNamespace ns : cachedSchemas.keySet()) {
                File f = cachedSchemas.get(ns);
                System.out.println("\t"+ns+" => "+f);
            }

        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (URISyntaxException e) {
            // TODO handle the case where the schemaTargetNamespace is
            // constructed with an invalid URI
            e.printStackTrace();
        } catch (NoSuchNamespaceExistsFault e) {
            // TODO handle the case where the schema requested is not actually
            // published
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        } catch (IOException e) {
            // TODO handle issues creating directories/files for caching the
            // schemas
            e.printStackTrace();
        }

    }
}


Running this code should yield output similar to the below:

Downloaded the XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata, and its dependencies, to the local file system directory:./gme_schemas
The schemas were written to the following files:
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common => ./gme_schemas/common.xsd
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata => ./gme_schemas/caGridMetadata.xsd
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service => ./gme_schemas/servicemodel.xsd


If the example code is ran again, the results change to something like this:

Downloaded the XML Schema with targetNamespace gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata, and its dependencies, to the local file system directory:./gme_schemas
The schemas were written to the following files:
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common => ./gme_schemas/0_common.xsd
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata => ./gme_schemas/0_caGridMetadata.xsd
	gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service => ./gme_schemas/0_servicemodel.xsd


This is because the operation tries to honor the original names of the XML Schemas, as defined by their systemIDs at publish time, but it takes care to not overwrite existing files and thus comes up with unique names for them.

You will also notice if you open a file, that the xsd:import tags have been appropriately modified to point to their local locations. For example, in the example above the root document had imports like below (as they were published):

    <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
        schemaLocation="common/common.xsd" />
    <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
        schemaLocation="service/servicemodel.xsd" />


Whereas, the schemas retrieved in this example have the following imports, which point to the locally written files:

<xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.common"
    schemaLocation="0_common.xsd" />
  <xs:import namespace="gme://caGrid.caBIG/1.0/gov.nih.nci.cagrid.metadata.service"
    schemaLocation="0_servicemodel.xsd" />

Publishing an XML Schema

This example shows how to use the XSDUtil utility class to help construct an XML Schema from the file system and publish it the GME. This example should be run from the GME_HOME directory because it references a test schema from the project.

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.rmi.RemoteException;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
import org.cagrid.gme.common.XSDUtil;
import org.cagrid.gme.domain.XMLSchema;
import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault;


public class DevelopersGuideExamples {

    public static void main(String[] args) {

        try {
            GlobalModelExchangeClient gme = new GlobalModelExchangeClient(
                "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange");

            // the targetNamespace of the schema we are publishing
            URI schemaToPublishTargetNamespace = new URI("gme://f");
            // the file containing the schema's text
            File schemaToPublishRootDocument = new File("test/resources/schema/simple/F.xsd");
            // Use the XSDUtil to help build the XMLSchema
            XMLSchema schemaToPublish = XSDUtil.createSchema(schemaToPublishTargetNamespace,
                schemaToPublishRootDocument);

            // build an array of all the schemas to publish
            XMLSchema[] schemasToPublish = new XMLSchema[1];
            schemasToPublish[0] = schemaToPublish;
            gme.publishXMLSchemas(schemasToPublish);

        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (URISyntaxException e) {
            // TODO handle the case where the schemaTargetNamespace is
            // constructed with an invalid URI
            e.printStackTrace();
        } catch (NoSuchNamespaceExistsFault e) {
            // TODO handle the case where the schema requested is not actually
            // published
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        } catch (IOException e) {
            // TODO handle issues reading directories/files passed to XSDUtil
            e.printStackTrace();
        }

    }
}

Client-Side Validation of XML Documents

This example validates an XML document in a file using an XML schema from GME. The validation is done by calling the GlobalModelExchangeClient class's validateXMLFile method. It expects the root element of the XML document to specify an xmlns that it will use to identify the schema for retrieval from GME.

The GlobalModelExchangeClient class has a similar method named validateXML that is passed as a string that contains the actual XML document for validation.

import gov.nih.nci.cagrid.common.SchemaValidationException;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.rmi.RemoteException;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;


public class GMEListingExample {
    static final String GME_URL = "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange";

    public static void main(String[] args) {
        File xmlFile = new File("resources", "gme_example.xml");
        GlobalModelExchangeClient gme;
        try {
            gme = new GlobalModelExchangeClient(GME_URL);
        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        }
        try {
            gme.validateXMLFile(xmlFile);
            System.out.println(xmlFile.getCanonicalPath() + " is valid");
        } catch (IOException e) {
            // TODO Handle problems reading the file.
            e.printStackTrace();
            return;
        } catch (URISyntaxException e) {
            // TODO Handle XML namespace not being a valid URI.
            e.printStackTrace();
            return;
        } catch (SchemaValidationException e) {
            // TODO Handle invalid XML document.
            e.printStackTrace();
        }
   }
}

Deleting an XML Schema

This example will delete the schema that was published in the preceding example. An XML Schema cannot be deleted if there are any remaining references to it. Accordingly, in order to delete a referenced schema, the referencing schemas must also be deleted by passing all their targetNamespaces in the array. Also, schema deletion is irreversible so it should not be used unless strictly necessary.

import java.net.URISyntaxException;
import java.rmi.RemoteException;

import org.apache.axis.types.URI.MalformedURIException;
import org.cagrid.gme.client.GlobalModelExchangeClient;
import org.cagrid.gme.domain.XMLSchemaNamespace;
import org.cagrid.gme.stubs.types.NoSuchNamespaceExistsFault;


public class DevelopersGuideExamples {

    public static void main(String[] args) {

        try {
            GlobalModelExchangeClient gme = new GlobalModelExchangeClient(
                "https://globalmodelexchange.training.cagrid.org:8443/wsrf/services/cagrid/GlobalModelExchange");

            // the targetNamespace of the schema we are deleting
            XMLSchemaNamespace schemaToDeleteTargetNamespace = new XMLSchemaNamespace("gme://f");

            XMLSchemaNamespace[] targetNamespacesToDelete = new XMLSchemaNamespace[1];
            targetNamespacesToDelete[0] = schemaToDeleteTargetNamespace;

            gme.deleteXMLSchemas(targetNamespacesToDelete);

        } catch (MalformedURIException e) {
            // TODO handle the case where the client is constructed with an
            // invalid URL
            e.printStackTrace();
            return;
        } catch (URISyntaxException e) {
            // TODO handle the case where the schemaTargetNamespace is
            // constructed with an invalid URI
            e.printStackTrace();
        } catch (NoSuchNamespaceExistsFault e) {
            // TODO handle the case where the schema requested is not actually
            // published
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO handle general errors, such as connection refused
            e.printStackTrace();
            return;
        }

    }
}
Last edited by
Clayton Clark (1014 days ago) , ...
Adaptavist Theme Builder Powered by Atlassian Confluence