Starting with the 1.0 series, the Ganymede server gains the ability to import and export data using XML. Like HTML, XML is a plain text data format with structural tagging. Unlike HTML, which has a predefined set of tags that represent the structuring and rendering facilities of modern web browsers, XML has no pre-defined document tags. Instead, XML allows applications to define their own sets of tags for use according to the XML syntactical rules. Ganymede uses XML to structure its data structures in a way that is accessible to other software and even readable by humans. Before we get into discussing the custom tags used by Ganymede, it is worth setting forth a number of facts about XML in general that software needs to know about in order to properly communicate with Ganymede via XML.
A Brief Introduction to XML |
Facts about XML:
Tags are case-sensitive. <tag>, <Tag> and <TAG> are all separate tags, and will not be treated as equivalent by an XML parser.
All tags must come in pairs. HTML browsers can tolerate tags that stand alone, like <br> and <p>, but XML is more strict, and all elements must have an open tag (<element>) and a close tag (</element>).
The structure of XML files must be strictly tree-like. That is, XML structural elements can contain other XML structural elements, but one XML structural element may not be partially contained by another.
In other words,
<element1>
<element2>
</element1>
</element2>
is an invalid XML sequence, as the element2 and element1 structural elements are intermingled.
In contrast,
<element1>
<element2></element2>
</element1>
is perfectly valid, because the entirety of element2 is contained within element1.
In cases like the above, where the element2 element's open and close tag are immediately adjacent, XML supports a special syntax for an Empty Element, that is, an element which does not contain any thing between the open tag and close tag. The same legal XML structure shown above could be written as:
<element1>
<element2/>
</element1>
where the trailing slash in the element2 element indicates that there will be no matching close tag to come along. At any other time an element open tag (<element>) is seen, a compliant XML parser will expect and demand to see the matching close tag (</element>) for that element before it sees the close tag for any elements higher up in the document structure.
In XML, all XML documents contain a single element (the Document Element, in XML lingo) which contains in turn any other elements and character data. The start tag for the document element will generally be the first thing in an XML file's content proper, and the matching close tag for the document element will be the last thing in the XML file. For this reason, the following XML fragment could not be an entire XML file:
<element1>
<element2/>
</element1>
<element3>
<element4>
<element5/>
</element4>
</element3>
Because element1 does not contain elements 3, 4, and 5.
In XML, all attribute data must be quoted, as in
<object label="labeldata">
The following is illegal:
<object label=labeldata>
All possible characters are legal within the double quotes surrounding an attribute's value except the '&' character and the double quotation mark itself. If you need to include a double quotation mark in an attribute's data field, you have to use "
For example, if you wanted the string 'He said "hi" & I waved back.' in an XML tag attribute, you would have to do it this way:
<sentence text="He said "hi" & I waved back."/>
Newlines and other whitespace are explicitly acceptable within the quoted value of an attribute.
Likewise, if you want to include the '<', '>', or '&' characters anywhere in the body of an XML document, for anything other than tag or special character definitions, you need to use '<', '>', and '&' instead, just as with HTML.
XML files use Unicode, with the UTF-8 encoding, typically. American 7-bit ASCII is a proper subset of Unicode and require no special handling in UTF-8 encoding. International characters may be used in XML files, but you must do so in a manner compliant with UTF-8. Ganymede will always emit XML files using the standard UNIX end-of-line character, but as with any XML parser, Ganymede can also handle DOS/Windows style line termination when reading XML files.
There are limitations on what characters you can use for tag and attribute names. The rules on this are somewhat complex, but for the purpose of XML use with Ganymede at present, only the following characters will ever be used:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_
Eventually, Ganymede may be elaborated so that it knows all of the rules for XML character limitations in the full Unicode character range, but for now, only the above characters will ever appear or be used in XML tag and attribute names for use with Ganymede.
Unlike in HTML, the XML standard does not specify that whitespace can be ignored or contracted. For Ganymede's purposes, however, whitespace between tags is generally ignored, and newlines and indentation are nice for human readability but not necessary for Ganymede's input parsing. More on this as we discuss what Ganymede does with XML, below.
That's about all you should need to know about XML, at least as far as we'll need to talk about in discussing Ganymede. If you want to read about things like external reference entities, Document Type Definitions/DTD's, or the precise Backus-Naur style specification for what characters are allowed to go where when, you can probably find your way to the original XML standards documents over at www.XML.com.
On Ganymede and XML |
Ganymede exports and imports object and schema data using a simple XML format, in which the schema definition section and the object data sections comprise two separate elements. The basic structure of an XML file for Ganymede looks like this:
<ganymede major="1" minor="0" persona="supergash" password="testpass">
<ganyschema>
-- Optional Ganymede Schema Definition Section Here --
</ganyschema>
<ganydata>
-- Optional Ganymede Object Data Section Here --
</ganydata>
</ganymede>
The ganymede element is the XML file's Document Element, and has two mandatory attributes, major and minor, which specify the major and minor version numbers of the Ganymede XML file format the file adheres to, and two optional attributes, persona and password, which may be used to specify the username and password for the xmlclient to use in attempting to log into the server to apply the changes in the file.
The ganyschema element contains the schema definition for the Ganymede database. This section contains definitions of the types of objects that the Ganymede server knows about, including the fields defined for those objects and the constraints and relationships among those fields and objects. The field definitions in the Ganymede schema definition section control what fields may legally appear in the object data section of a Ganymede XML file, and what kind of data those fields are allowed to contain.
The optional ganydata element contains actual data records from the Ganymede database. The ganydata element contains a number of object elements, each of which contain the data for a single object in the Ganymede database.
Each of these two sections are optional, but an XML file without one of these two sections is pointless, as far as Ganymede is concerned. The sections below discuss these two components of a Ganymede XML file in detail.
Ganymede Schema Definition in XML |
The <ganyschema> element defines the structure of the Ganymede database, what types of objects are defined, what fields they have, what kind of data those fields can contained, and what everything is called.
The <ganyschema> element is optional. If you
run 'xmlclient -dumpschema' or 'xmlclient -dump', you will get
an XML file that includes the <ganyschema> element.
If you run xmlclient on an XML file that includes a <ganyschema>
element, xmlclient will attempt to edit the server's schema to
bring it into alignment with that described in the <ganyschema>
element.
The <ganyschema> element contains two other elements, <namespaces> and <object_type_definitions>.
<ganyschema>
<namespaces>
-- Optional Namespace Definitions --
</namespaces>
<object_type_definitions>
-- Object And Field Definitions --
</object_type_definitions>
</ganyschema>
<namespaces> |
The <namespaces> element contains definition elements for all unique namespace structures in the server. A namespace is essentially a unique value index that the server uses to assure that, across all fields in the database connected to the namespace, no value is repeated. Namespaces are used to keep user, group, and system names unique, among other things.
Here is an example <namespaces> element that would be contained at the start of a <ganyschema> element:
<namespaces>
<namespace name="username"/>
<namespace name="groupname"/>
<namespace name="IPspace"/>
<namespace name="UserCategory" case-sensitive="true"/>
<namespace name="systemtype" case-sensitive="true"/>
</namespaces>
In this example, the username, groupname, and IPspace namespaces consider two strings to be equivalent for namespace conflict considerations even if two instances of the string have different capitalization. The UserCategory and systemtype name spaces will not consider two strings to be in conflict if they have different capitalizations.
Namespaces are only significant when they are attached to fields in the <object_type_definitions> section, as we will see shortly.
<object_type_definitions> |
In the Ganymede server, all data stored is stored in the form of fields, which are aggregated in objects. Each object stored in the Ganymede server is of a certain type, such as a user, group, system, network, or whatever else has been defined in the server's schema. The objects, in turn, may be grouped into categories. Categories are a way of grouping similar kinds of objects together so that they may be viewed or ignored in the client's tree view.
The <object_type_definitions> element under the <ganyschema> element contains the actual schema definition information in terms of categories, objects, and fields. The corresponding elements for these are the <category>, <objectdef>, and <fielddef> elements.
Here is an example:
<object_type_definitions>
<category name="Categories">
<category name="Admin-Level Objects">
<category name="Events">
<objectdef name="System_Events" id="4">
<classdef name="arlut.csd.ganymede.eventCustom"/>
<label fieldid="100"/>
<fielddef name="Event_Token" id="100">
<comment>Single-word token for this event class</comment>
<typedef type="string">
<maxlength val="32"/>
<badchars val=" |"/>
<namespace val="eventtoken"/>
</typedef>
</fielddef>
<fielddef name="Event_Mail" id="103">
<comment>If true, events of this type should be mailed</comment>
<typedef type="boolean"/>
</fielddef>
<fielddef name="Mail_List" id="107">
<typedef type="string">
<vector/>
</typedef>
</fielddef>
</objectdef>
</category>
</category>
</category>
</object_type_definitions>
This example is of a small portion of a Ganymede server's schema definition. This fragment shows an object type called 'System Events' which has three fields defined; a scalar string field called 'Event Token' which is connected to the 'eventtoken' namespace, a boolean checkbox field caleld 'Event Mail', and a vector string field called 'Mail List'.
The 'System Events' object is contained within an 'Events' category, which is contained in turn within a 'Admin-Level Objects' category. The 'Categories' category is itself simply a container for the other categories.. it is the category root node. All <object_type_definitions> elements in Ganymede XML schema definition sections should contain a top-level 'Categories' category, even if you don't want any categorical organization of object types in the client. Note that all <category> elements that are opened are properly closed before the close of the <object_type_definitions> element.
<objectdef> |
The objectdef element is used to define object types in the Ganymede server. Each object type has a name and a numeric id, which are defined in an open objectdef tag via the 'name' and 'id' attributes. Both of these values must be unique within the <ganyschema> section. The value of the 'id' attribute must be an integer number, and the value of the 'name' attribute must be a string which contains only the letters a-z, in upper or lower case, numbers, a period, a dash, or a space.
Example:
<objectdef name="User" id="3">
Within the objectdef element, there are a couple of optional elements that define optional characteristics of the object, followed by a series of fielddef elements.
The optional elements are the <classdef>, <embedded> and <label> elements.
The classdef element, if present, specifies the fully qualified class name of a Java class to be loaded by the server to manage server operations on objects of this type. The classdef element has a name attribute whose value is the name of the Java class to be used. See the DBEditObject subclassing guide for details on the use of custom classes in the Ganymede server. The classdef element must be empty. That is, it must not contain any other elements.
Example:
<classdef name="arlut.csd.ganymede.custom.userCustom"/>
or (equivalently)
<classdef name="arlut.csd.ganymede.custom.userCustom"></classdef>
The optional embedded element, if present, indicates that the object is not a top-level object which will be shown in the client's object tree and which will have its ownership and permissions tracked independently, but rather is an embedded object which will be encapsulated in another object of a defined type. The embedded element must be empty and it takes no attributes.
Example:
<embedded/>
The optional label element has a fieldid attribute which gives the numeric field id of the field within the object which is to serve as the label field. Objects do not need to have designated label fields, but if they do, they can have only one, and it must refer to a String, IP, Numeric, or Floating Point field defined within the <objectdef> element. Password, Permission Matrix, Object Reference, and Boolean fields may not be specified as label fields. The label element must be empty.
Example:
<label fieldid="100"/>
Once the optional elements are out of the way, we get down to the meat of an object definition element.. the fields. The objectdef element will typically contain a series of fielddef elements, one for each field defined in this object type. These fielddef elements are listed in the order they should appear in the client. The first fielddef element in an objectdef element will appear at the top of the object editing window in the Ganymede client, with subsequent fielddef's in order below the first.
<fielddef> |
The <fielddef> element is a complex one, with many possible component elements. There are currently 9 different kinds of fields supported by the Ganymede server, and each of these field types have different options available. The open tag for the fielddef element itself is fairly simple, however. It has just two attributes, both mandatory. These are the same as the ones used in the objectdef tag.. name and id. The contents of the name attribute is limited in precisely the same manner as the name attribute of the objectdef tag's name attribute. It must contain only letters in the standard ASCII set, a-z, the numbers 0-9, a period or dash, and an underscore in place of a space. The id attribute must be an integer number less than 32768.
Example of the fielddef element's open tag:
<fielddef name="Username" id="100">
The fielddef element can contain a couple of optional elements, comment, and invisible.
The comment element is a text containing element. All text between the opening <comment> tag and the closing </comment> tags is treated as a comment to attach to the field. The Ganymede GUI client will show this text as a pop-up tooltip if the user lets the mouse linger on the GUI component. Aside from some text, however, the comment element should not contain any subelements.
The invisible element is an optional empty element, signifying that the field defined by the containing fielddef element should not be visible in the Ganymede client. This is used to establish invisible scratch fields used by custom code associated with the containing objectdef element for various purposes. This is a rather unusual element to define in a fielddef element, and will only be present in special cases.
Here's a (contrived) example of these two optional elements in use.
<fielddef name="Hidden_Field" id="302">
<comment>This is a hidden field to be used for namespace manipulations.</comment>
<invisible/>
</fielddef>
Okay, with the two optional elements out of the way, it's time for the meat of the fielddef element, the typedef element. The typedef element specifies what kind of data field the containing fielddef field definition element defines, and has a single attribute, type. The type attribute can have any of the values listed in the following table:
| Type | Explanation | Vector Allowed? |
|---|---|---|
| string | Unicode String | YES |
| ip | I.P. Address, IPv4 or IPv6 | YES |
| invid | Object Reference | YES |
| boolean | Boolean | NO |
| date | Date/Timestamp | NO |
| numeric | Integer Number Field | NO |
| float | Double precision float | NO |
| password | Password Field | NO |
| permmatrix | Ganymede Permissions Matrix | NO |
For example:
<typedef type="string">
After the typedef element open tag, there can be a variety of elements, depending on the element's type.
First off, the string, ip, and invid field types can be vector fields, in which a single data field can contain more than one value. In that case, the typedef element will contain a vector element.
The vector element is an empty element with a single attribute, maxSize, which has a numeric value specifying the maximum number of values that can be held in this field at a time. For example,
<typedef type="string">
<vector maxSize="100"/>
</typedef>
would describe a vector string field that could contain up to 100 strings in the field. Vector fields in Ganymede can not hold more than 32767 elements, so if no maxSize attribute is defined, an implicit value of 32767 is still in effect.
After the optional vector element (for the string, ip, and invid types only), there are a number of optional field constraint elements which differ by type. These are summarized in the table below. The trickiest options conceptually are those associated with the invid field type. I need to link this material to a general discussion of invid fields.
| field type | element name | element details | example |
|---|---|---|---|
| string | |||
| minlength | The minlegth element is an empty element with a single attribute, val, which contains a numeric value specifying a mandatory minimum number of characters present in this string field. |
<minlength val="2"/> | |
| maxlength |
The maxlength element is an empty element with a single attribute, val, which contains a numeric value specifying the maximum number of characters allowed in this string field. The Ganymede server supports string values of up to 32767 characters in length, and this limit is present implicitly if the maxlength element is not present in a string field definition. |
<maxlength val="8"/> | |
| okchars | The okchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters allowed in this string field. If this optional element is defined in a string typedef element, no characters will be allowed in any field of this type unless that character is present in the val value. |
<okchars val="0123456789-"/> | |
| badchars | The badchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters not allowed in this string field. If this optional element is defined in a string typedef element, a character will not be allowed in any field of this type if that character is present in the val value. |
<badchars val=":"/> | |
| regexp |
The regexp element is an optional empty element with a pair of attributes, one mandatory and one optional. The mandatory attribute is val, which contains a string value which defines a Perl-style regular expression. The optional attribute is desc, which if present will be used as a textual description of the meaning of the regexp. The desc attribute will be provided to the user in an error dialog if they enter a string in the client which does not match the regexp. If no desc attribute is present, the user will be shown the regexp itself in the error message. regexp is an optional element in the string typedef element. If a regexp element is present, all strings entered into fields of this type will be checked against the regexp. The regexp check is made in addition to any okchars and badchars constraints that are defined in the same typedef. |
<regexp val="^[a-z]+[a-z|\d]*$" desc="Usernames may contain letters and numbers, but must begin with a letter."/> | |
| multiline | The multiline element is an empty element with no attributes. This element signifies that this field should be presented in the Ganymede client as a multiline string area rather than a single line text field. |
<multiline/> | |
| namespace | The namespace element is an empty element with a single attribute, val, which contains a string naming a namespace defined in the namespaces element contained in the top-level ganyschema element. If this optional element is defined in a string typedef element, all fields associated with the specified namespace will be constrained to contain unique values across the specified namespace. |
<namespace val="username"/> | |
| ip | |||
| namespace | The namespace element is an empty element with a single attribute, val, which contains a string naming a namespace defined in the namespaces element contained in the top-level ganyschema element. If this optional element is defined in an ip typedef element, all fields associated with the specified namespace will be constrained to contain unique values across the specified namespace. |
<namespace val="IPSpace"/> | |
| invid | |||
| targetobject |
The targetobject element is an empty element with a pair of attributes, name and id, which constrains the type of object this object reference field may point to in the server. The name attribute contains a string which has the encoded (underscores for spaces) name of the object type to point to, while the id attribute contains the integer numberic id of the object type pointed to. Both may be specified, in which case the Ganymede server will verify that both the id number and the object name are consistent, or either one alone may be used. If this invid field is intended to be able to point to any kind of object, this is specified by using the name attribute alone, with a value of "*any*". In this case, no id attribute should be specified. |
<targetobject name="User" id="3"/> | |
| targetfield |
The targetfield element is an optional empty element that specifies the field that this invid field is to be linked with. If a targetfield is specified, the Ganymede server will maintain a symmetric link between this invid field and the target field in objects linked to this field. The target field may be identified using either a name or an id attribute. The name attribute contains a string which has the encoded (underscores for spaces) name of the field to point to, while the id attribute contains the integer numberic id of the field pointed to. Both may be specified, in which case the Ganymede server will verify that both the id number and the field name are consistent, or either one alone may be used. |
<targetfield name="Username" id="103"/> | |
| embedded |
The embedded element is an optional empty element that specifies that this invid field is to be used as an edit-in-place field. That is, that objects linked by this field will be handled as if it is contained within the object which holds this field. |
<embedded/> | |
| boolean | |||
| labeled | The labeled element is an optional empty element with a pair of attributes, true and false. If this element is present, the client will present this boolean field as a pair of radio buttons rather than a single check-box. This can be useful when you've got a pair of choices that don't fit naturally into a yes/no dichotomy. In general, support for this option has not really been tested, and may not work well. |
<labeled true="Normal User" false="Custom Account"/> | |
| numeric | |||
| namespace | The namespace element is an optional, empty element with a single attribute, val, which contains a string naming a namespace defined in the namespaces element contained in the top-level ganyschema element. If this optional element is defined in a numeric typedef element, all fields associated with the specified namespace will be constrained to contain unique values across the specified namespace. |
<namespace val="uid"/> | |
| password | |||
| minlength | The minlegth element is an empty element with a single attribute, val, which contains a numeric value specifying a mandatory minimum number of characters present in this password field. |
<minlength val="2"/> | |
| maxlength |
The maxlength element is an empty element with a single attribute, val, which contains a numeric value specifying the maximum number of characters allowed in this password field. The Ganymede server supports string values of up to 32767 characters in length, and this limit is present implicitly if the maxlength element is not present in a password field definition. The crypt encryption hash method supported by Ganymede only considers the first 8 characters of the password in generating the authentication hash, so setting a maxlength larger than 8 characters will not guarantee that Ganymede will require the full password length for login authentication if the crypt method is used. |
<maxlength val="8"/> | |
| okchars | The okchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters allowed in this password field. If this optional element is defined in a password typedef element, no characters will be allowed in any field of this type unless that character is present in the val value. |
<okchars val="0123456789-"/> | |
| badchars | The badchars element is an empty element with a single attribute, val, which contains a string value enumerating the characters not allowed in this password field. If this optional element is defined in a password typedef element, a character will not be allowed in any field of this type if that character is present in the val value. |
<badchars val=":"/> | |
| crypted |
The crypted element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in UNIX crypt() format. |
<crypted/> | |
| md5crypted |
The md5crypted element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in FreeBSD-style md5crypt() format. |
<md5crypted/> | |
| winHashed |
The winHashed element is an optional, empty element. If this element is present, the Ganymede server will store the contents of this password in the two Windows NT compatible hash formats used in the Samba encrypted password file. |
<winHashed/> | |
| plaintext |
The plaintext element is an optional, empty element. If this element is present, the Ganymede server will store the plaintext of passwords stored in this field to disk. Normally, if the Ganymede server has either crypted, md5crypted, or winHashed set, the server will never dump the plaintext of passwords in this field to disk, as it is capable of authenticating logins against any of the supported hash formats. If the plaintext element is present, the password will be preserved in plaintext form in the ganymede.db file, regardless of whether or not the password is also handled via one of the encryption hashes. |
<plaintext/> |
Schema Example Fragment |
The following is a transcript of the User object definition from the GASHARL schema kit in use at ARL. Notable features of this fragment include the Groups invid field which is bidirectionally linked with the Users field in the Groups object type, and the edit-in-place Directory Volume field which contains embedded Embedded Automounter Map Entry objects.
Note also the newline in the middle of the Groups field comment, which is actually preserved faithfully in the Ganymede database.
<objectdef name="User" id="3">
<classdef name="arlut.csd.ganymede.custom.userCustom"/>
<label fieldid="100"/>
<fielddef name="Username" id="100">
<comment>User name for an individual privileged to log into Ganymede and/or the network</comment>
<typedef type="string">
<maxlength val="8"/>
<badchars val=" :"/>
<namespace val="username"/>
<regexp val="^[a-z]+[a-z|\d]*$" desc="User names may consist of letters and numbers, but must begin with a letter"/>
</typedef>
</fielddef>
<fielddef name="UID" id="256">
<typedef type="numeric">
<namespace val="uid"/>
</typedef>
</fielddef>
<fielddef name="Password" id="101">
<comment>Password for an individual privileged to log into Ganymede and/or the network</comment>
<typedef type="password">
<minlength val="3"/>
<maxlength val="32"/>
<crypted/>
<plaintext/>
</typedef>
</fielddef>
<fielddef name="Account_Category" id="273">
<typedef type="invid">
<targetobject name="User_Category"/>
</typedef>
</fielddef>
<fielddef name="Full_Name" id="257">
<typedef type="string">
<maxlength val="64"/>
<badchars val=":,"/>
</typedef>
</fielddef>
<fielddef name="Social_Security" id="274">
<typedef type="string">
<okchars val="0123456789-"/>
</typedef>
</fielddef>
<fielddef name="Division" id="258">
<typedef type="string">
<maxlength val="32"/>
<badchars val=":,"/>
</typedef>
</fielddef>
<fielddef name="Room" id="259">
<typedef type="string">
<maxlength val="32"/>
<badchars val=": ,"/>
</typedef>
</fielddef>
<fielddef name="Office_Phone" id="260">
<typedef type="string">
<maxlength val="16"/>
<badchars val=":"/>
</typedef>
</fielddef>
<fielddef name="Home_Phone" id="261">
<typedef type="string">
<maxlength val="16"/>
<badchars val=":, "/>
</typedef>
</fielddef>
<fielddef name="Groups" id="264">
<comment>List of non-primary groups the user is a member of.
Limited to 16 for NFS.</comment>
<typedef type="invid">
<vector maxSize="16"/>
<targetobject name="Group"/>
<targetfield name="Users"/>
</typedef>
</fielddef>
<fielddef name="Home_Group" id="265">
<typedef type="invid">
<targetobject name="Group"/>
<targetfield name="Home_Users"/>
</typedef>
</fielddef>
<fielddef name="Login_Shell" id="263">
<typedef type="string">
<maxlength val="128"/>
<badchars val=" :"/>
</typedef>
</fielddef>
<fielddef name="Home_Directory" id="262">
<comment>UNIX default directory, normally assigned by Ganymede</comment>
<typedef type="string">
<maxlength val="128"/>
<badchars val=" :"/>
</typedef>
</fielddef>
<fielddef name="Admin_Personae" id="102">
<comment>A list of admin personae this user can assume</comment>
<typedef type="invid">
<vector/>
<targetobject name="Admin_Persona"/>
<targetfield name="User"/>
</typedef>
</fielddef>
<fielddef name="Netgroups" id="266">
<typedef type="invid">
<vector/>
<targetobject name="User_Netgroup"/>
<targetfield name="Users"/>
</typedef>
</fielddef>
<fielddef name="Directory_Volume" id="271">
<typedef type="invid">
<vector/>
<targetobject name="Embedded_Automounter_Map_Entry"/>
<targetfield name="Containing_Object"/>
<embedded/>
</typedef>
</fielddef>
<fielddef name="Email_Aliases" id="267">
<typedef type="string">
<vector/>
<maxlength val="32"/>
<badchars val="@"/>
<namespace val="username"/>
</typedef>
</fielddef>
<fielddef name="Signature_Alias" id="268">
<typedef type="string">
<maxlength val="32"/>
<badchars val="@"/>
</typedef>
</fielddef>
<fielddef name="Email_target" id="269">
<typedef type="string">
<vector/>
<badchars val=":"/>
</typedef>
</fielddef>
</objectdef>
Ganymede Object Data Import/Export Definition in XML |
While the Ganymede server is capable of expressing its schema definition information in the <ganyschema> section of its XML file, this aspect of Ganymede's XML support is bound to be much less used than the data dumping and loading support. This section discusses the <ganydata> element that may be present in the Ganymede XML file format.
| <ganydata> | |
| The <ganydata> element is a container for object data to be updated on the server. When exported, the <ganydata> element contains a complete dump of the server's data state. When imported, the <ganydata> element contains a collection of <object> elements which specify objects to be created, edited, inactivated, or deleted. [Example] , [Top] | |
| Parent(s) | Children |
| NONE | <object> |
| Attributes | |
|
|
The <ganydata> element contains a series of <object> elements, each one corresponding to an object in the Ganymede database. The <object> element itself may contain one element for each field in the object. The open tag for the object element as exported contains possibly four attributes, those being type (required), id, num, and action.
| <object> | |
| The <object> element contains data for a single object. When exported, the <object> element contains a complete dump of the object's state, minus the historical fields (last modification data, etc.).When imported, the <object> element contains a collection of field elements whose contents are to be transmitted to the server to update the object identified by the <object>'s attributes. [Example] , [Top] | |
| Parent(s) | Children |
| <ganydata> | Various field elements, each with a unique tag name based on the name of the corresponding server field |
| Attributes | |
|
|
Aside from the special case of object inactivation or deletion, all <object> elements in a <ganydata> section will contain a set of elements that correspond to fields in the object to be created or edited on the server. The elements for these fields have no fixed tag name. Instead, each field element will start with an open tag that is named according to the name of the field, with spaces transformed into underscores.
For instance, a record to change the values of the "Room", "Groups", "Home Group" and "Email Aliases" fields in a pre-existing object on the server would be represented in the XML file as:
<object type="User" id="broccol" action="edit">
<Room>S321</Room>
<Groups>
<invid type="Group" id="omssys"/>
<invid type="Group" id="omsnet"/>
</Groups>
<Home_Group><invid type="Group" id="omssys"/></Home_Group>
<Email_Aliases>
<string val="abbey"/>
<string val="jonabbey"/>
</Email_Aliases>
</object>
An <object> element contains nothing but such field elements, all of which lack any sort of attributes. The field elements themselves, however, will contain a variety of kinds of elements, depending on the field type. In the above example, the "Room" field is a scalar String field, the "Groups" field is a vector Invid/object reference field, the "Home Group" field is a scalar Invid/object reference field, and the "Email Aliases" field is a vector String field.
In the above example, the Groups and Email_Aliases vector field elements both contain a couple of items. These items will be added to those fields if they are not already present, but the xmlclient will not remove any other items which may already be in those fields.
If you want to assure that after xmlclient finishes its work that there will only be a given list of items in a vector field, you need to do this:
<object type="User" id="broccol" action="edit">
<Room>S321</Room>
<Groups>
<set>
<invid type="Group" id="omssys"/>
<invid type="Group" id="omsnet"/>
</set>
</Groups>
</object>
In this example, the <set> container element will force the xmlclient to set the Groups field to contain only the two items listed, adding or removing items as necessary.
You can also manually add or remove individual items:
<object type="User" id="broccol" action="edit">
<Room>S321</Room>
<Groups>
<add>
<invid type="Group" id="omsovr"/>
</add>
<delete>
<invid type="Group" id="omsnet"/>
</delete>
</Groups>
</object>
This will cause the omsovr group to be added and the omsnet group to be removed. You can have as many <add> and <delete> containers as you want within a vector field, but <add> and <delete> are not compatible with <set>. If you use <set>, you may not use <add> or <delete> as well.
If you don't specify <add>, <delete>, or <set>, the xmlclient will treat the items as belonging to an <add> container. For this reason, the following is not allowed:
<object type="User" id="broccol" action="edit">
<Room>S321</Room>
<Groups>
<invid type="Group" id="omsovr"/>
<set>
<invid type="Group" id="omssys"/>
<invid type="Group" id="omsnet"/>
</set>
</Groups>
</object>
because the omsovr element is considered to be in an <add>, which may not co-exist with a <set> in a single field element.
There are presently nine different types of data fields supported by the Ganymede server, and each of these types has its own rules as to what kinds of elements are allowed within the field element and how they may be structured. For the most part, these rules are very similar for all field types, with just the value carrying element type differing. The following table shows the data carrying element types that correspond to the nine field types.
| <string> | |
| The <string> element contains data for Ganymede string fields, but is mandatory only for vector string fields. The <string> element is not necessary for scalar string fields, which support simply placing the content to be placed in the string field directly between the field element's open and close tags. If the <string> element is used for string field content, it must be empty. [Example] , [Top] | |
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <string val="broccol"/> | |
| <boolean> | |
|
The <boolean> element is an optional data element for Ganymede boolean fields. Since Ganymede boolean fields are always scalar, you can simply place true, t, false or f (of whatever capitalization) between the field's start and end tags. If you do use the older <boolean> element as a data container, the <boolean> element must be empty. [Example] , [Top] |
|
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <boolean val="true"/> | |
| <int> | |
|
The <int> element is an optional data element for Ganymede numeric fields. Since Ganymede numeric fields are always scalar, you can simply place a 32 bit signed integer value between the containing field's start and end tags. If you do use the older <int> element as a data container, the <int> element must be empty. [Example] , [Top] |
|
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <int val="12042"/> | |
| <float> | |
| The <float> element contains a 64 bit floating point value, corresponding to the IEEE 754-1985 specification, for use with Ganymede float fields. As float fields are scalar in Ganymede, only one <float> element at a time may be contained in a float field element. The <float> element must be empty. [Example] , [Top] | |
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <float val="3.141596254"/> | |
| <ip> | |
| The <ip> element contains an IPv4 or IPv6 address. IP fields may be scalar or vector in Ganymede. The <ip> element must be empty. [Example] , [Top] | |
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <ip val="127.0.0.1"/> | |
| <date> | |
| The <date> element contains a Java date value, which is effectively a 64 bit time stamp with millisecond resolution centered at Midnight, January 1, 1970, UTC. As date fields are scalar in Ganymede, only one <date> element at a time may be contained in a field element. The <date> element must be empty. [Example] , [Top] | |
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <date val="Wed 28 Jun 2000 13:13:02" timecode="962215982000"/> | |
| <password> | |
| The <password> element contains a Java password value. As password fields are scalar in Ganymede, only one <password> element at a time may be contained in a field element. The <password> element must be empty. The <password> element must contain exactly one of three optional attributes, plaintext, crypt, or md5crypt, which are explained below. [Example] , [Top] | |
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <password crypt="nxGots4NO.BJY"/> | |
| <invid> | |
| The <invid> element contains a Ganymede object reference value, which is used to identify an object pointer in an invid field on the Ganymede server. The <invid> element must be empty. [Example] , [Top] | |
| Parent(s) | Children |
| <object> | NONE |
| Attributes | |
|
|
| Example | |
| <invid type="User" id="broccol"/> | |
Example |
For example, a user object from the GASH schema kit might be represented in an XML file in the following fashion:
<object type="User" id="broccol">
<Username>broccol</Username>
<UID>12003</UID>
<Password><password crypt="j8hgwcyw232Jo"/></Password>
<Account_Category><invid type="User_Category" id="normal"/></Account_Category>
<Full_Name>Jonathan Abbey</Full_Name>
<Social_Security>574743325</Social_Security>
<Division>CSD</Division>
<Room>S321</Room>
<Office_Phone>3199</Office_Phone>
<Home_Phone>335-7681</Home_Phone>
<Groups>
<invid type="Group" id="omsprl"/>
<invid type="Group" id="omsovr"/>
<invid type="Group" id="omssys"/>
<invid type="Group" id="genweb"/>
<invid type="Group" id="gendof"/>
<invid type="Group" id="omsnet"/>
<invid type="Group" id="ganycvs"/>
<invid type="Group" id="omjrst"/>
</Groups>
<Home_Group><invid type="Group" id="omssys"/></Home_Group>
<Login_Shell>/bin/tcsh</Login_Shell>
<Home_Directory>/home/broccol</Home_Directory>
<Admin_Personae>
<invid type="Admin_Persona" id="broccol:GASH Admin"/>
<invid type="Admin_Persona" id="broccol:supergash"/>
</Admin_Personae>
<Netgroups>
<invid type="User_Netgroup" id="omg-u"/>
<invid type="User_Netgroup" id="omguse-u"/>
<invid type="User_Netgroup" id="supad1-u"/>
</Netgroups>
<Directory_Volume>
<object type="Embedded_Automounter_Map_Entry" id="103" num="103">
<Automounter_Map><invid type="Automounter_Map" id="2"/></Automounter_Map>
<NFS_Volume><invid type="NFS_Volume" id="23"/></NFS_Volume>
</object>
</Directory_Volume>
<Email_Aliases>
<string val="jonabbey"/>
<string val="abbey"/>
<string val="rust-admin"/>
</Email_Aliases>
<Signature_Alias>jonabbey</Signature_Alias>
<Email_target>
<string val="broccol@arlut.utexas.edu"/>
<string val="broccol@csdsun7.arlut.utexas.edu"/>
</Email_target>
<Owner_list>
<invid type="Owner_Group" id="OMG"/>
</Owner_list>
</object>