Using Jakarta Slide Dec 5, 2004 == Configuration files == * slide.properties in class path. * Domain.xml : default is the file in current directory. can be specified in slide.properties file == Services / Stores == Slide can store the data it manages in a broad array of repositories. Each repository is accessed through a module called a Service or a Store. Each of these services have widely different dependencies, and can need a lot of extra setup steps. It is expected that services will be developed by Slide adopters to address their specific content management needs. For example, one company would want to access its website and NFS file server through Slide, so a NFS Service will be needed, along with a HTTP service. The scope of the Slide project is not to integrate every existing repository in the universe (although there will be out-of-the-box support for the most widely used ones), but to enable users to easily write services which would enable access to them. Default services included with Slide are: * File system (default store) * JDBC == The Domain configuration file == Sample configuration file : [http://jakarta.apache.org/slide/samples/Domain.sample Click Here] Slide needs a configuration file to initialize the Domain. This configuration file defines the namespaces which are part of this domain, the services associated with them, and the namespaces data configuration. This file uses the XML language for its syntax. A domain is an aggregation of one or more namespaces. If we use the UNIX filesystem analogy, a domain represents the root ("/") anchor where filesystems (in this case, namespaces) are mounted. The domain controls access to its registered namespaces and performs initialization and connection management on behalf of the namespaces. When Slide is first initialized, the Domain configuration is loaded. Once again, if you are familiar with UNIX, the domain configuration file is the equivalent of the fstab file. The path to the domain configuration file is given through the org.apache.slide.domain property in your slide.properties file (which must be located somewhere in your CLASSPATH). The domain configuration is written by an administrator and tells how to initialize each Namespace. The namespace initialization includes information like: * The low-level services the namespace uses (structure store, content store ...). * The namespace base topology, which includes the location of the base actions and paths in the namespace. == Jakarta Slide core API == === Architecture === The Slide architecture is a matrix of modules, ranging from high-level to low-level services, clearly separating functionality around different aspects (content, structure, security, locking and versioning). Content in Slide is organized in Namespaces, which contain a hierarchical tree of information (analogous to directories and files in a filesystem). Multiple namespaces are aggregated in a Domain. The default implementation of a Slide domain is as a static entity, so only one domain can exist per JVM. The high-level interfaces (Helpers) are meant to provide a simple, standardized way of manipulating a namespace from a client application. Underneath these interfaces lie pluggable, low-level services (Stores), which take care of actual storing the information. /image/ Overview of the Slide architecture == Stores == Stores are low level services that handle the actual storage of content and related data. Stores are totally pluggable, enabling the use of the most appropriate storage method for the type of data to store. Two different kinds of services exist: * The Descriptors stores, which are responsible for storing structure, locks, metadata, etc. * The Content stores, which is only responsible for storing the actual content. This distinction has been made because it's easy to see that while some repositories are very efficient at managing and indexing small amounts of data (relational databases are a good example of this), others are best for storing big chunks of data (for example filesystems). Within Slide, every object can possibly have a different kind of backing low-level service. For example, some objects might be stored in a remote LDAP directory, while others could be stored in an local SQL database. Thus, the content of a namespace can be distributed across several different descriptors and content stores. It is up to the administrator to choose how objects will be stored using the Slide configuration file, which maps low-level services to individual nodes in the namespace. Services are attributed to nodes in the namespace. This mapping is automatically inherited by sub-nodes. Here is an example of how one namespace might be mapped into different low-level services: /image/ Namespace mapped to multiple stores It is obvious that decent transaction capabilities are required in each individual store as well as across all the stores. Slide provides it's own transaction manager based on the Java Transaction API (JTA) to comply with this requirement. Operations that include multiple objects and span various stores can be grouped in transactions and rolled back if one of the operations fails. /image/ Transactions in Slide == Helpers == Slide also provides a higher level abstraction of the content management system through a set of Java classes, called helpers. These encompass all the functionality a client application will need, clearly separated by aspect. These high-level services allow an application to access content in a uniform fashion, no matter where it might be located, or how it is physically stored. Tight dependencies exist between the high-level services because of the need to enforce security, locking and other constraints throughout the client API. The following helpers are provided: * Structure Provides access to the hierarchical namespace tree. See the org.apache.slide.structure package for more details... * Content Manages object content, versioning and meta-data. See the org.apache.slide.content package for more details... * Security Manages access control to objects in a namespace. See the org.apache.slide.security package for more details... * Lock Provides locking functionality. See the org.apache.slide.lock package for more details... * Macro Provides object management functions that deal with operations which span multiple helpers (like for example deleting, copying and moving objects). See the org.apache.slide.macro package for more details... Instances of these helpers for a specific namespace can be obtained through the NamespaceAccessToken that you receive when accessing the namespace. === Content Interface === |Method | Summary | | void create(SlideToken token, java.lang.String strUri, boolean isVersioned) | Create new revision descriptors. Set the isVersioned as true to manage the resource in versioned way.| void create(SlideToken token, java.lang.String strUri, NodeRevisionDescriptor revisionDescriptor, NodeRevisionContent revisionContent) Create new revision in main branch. void create(SlideToken token, java.lang.String strUri, java.lang.String branch, NodeRevisionDescriptor newRevisionDescriptor, NodeRevisionContent revisionContent) Create new revision based on a previous revision. NodeRevisionNumber fork(SlideToken token, java.lang.String strUri, java.lang.String branchName, NodeRevisionDescriptor basedOnRevisionDescriptor) Create a branch based on specified revision. NodeRevisionNumber fork(SlideToken token, java.lang.String strUri, java.lang.String branchName, NodeRevisionNumber basedOnRevisionNumber) Create a branch based on specified revision. void merge(SlideToken token, java.lang.String strUri, NodeRevisionDescriptor mainBranch, NodeRevisionDescriptor branch, NodeRevisionDescriptor newRevisionDescriptor, NodeRevisionContent revisionContent) Merge specified branches into a single branch. void merge(SlideToken token, java.lang.String strUri, java.lang.String mainBranch, java.lang.String branch, NodeRevisionDescriptor newRevisionDescriptor, NodeRevisionContent revisionContent) Merge specified branches into a single branch. void remove(SlideToken token, NodeRevisionDescriptors revisionDescriptors) Remove all revisions at this Uri. void remove(SlideToken token, java.lang.String strUri, NodeRevisionDescriptor revisionDescriptor) Remove specified revision. void remove(SlideToken token, java.lang.String strUri, NodeRevisionNumber revisionNumber) Remove specified revision. NodeRevisionDescriptor retrieve(SlideToken token, NodeRevisionDescriptors revisionDescriptors) Retrieve revision descriptor from the latest revision in the main branch. NodeRevisionContent retrieve(SlideToken token, NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor) Retrieve revision content. NodeRevisionDescriptor retrieve(SlideToken token, NodeRevisionDescriptors revisionDescriptors, NodeRevisionNumber revisionNumber) Retrieve revision descriptor. NodeRevisionDescriptor retrieve(SlideToken token, NodeRevisionDescriptors revisionDescriptors, java.lang.String branch) Retrieve revision descriptor from the latest revision of a branch. NodeRevisionDescriptors retrieve(SlideToken token, java.lang.String strUri) Retrieve revision descriptors. NodeRevisionContent retrieve(SlideToken token, java.lang.String strUri, NodeRevisionDescriptor revisionDescriptor) Retrieve revision content. void store(SlideToken token, java.lang.String strUri, NodeRevisionDescriptor revisionDescriptor, NodeRevisionContent revisionContent) Update contents of an existing revision. Structure Interface Structure helper. Provides methods to manage and navigate the hierarchy of nodes in a namespace. Method Summary void addBinding(SlideToken token, ObjectNode collectionNode, java.lang.String segment, ObjectNode sourceNode) Modifies the collection identified by collectionNode, by adding a new binding from the specified segment to the resource identified by sourceNode. void create(SlideToken token, ObjectNode object, java.lang.String strUri) Creates a new node in the namespace. void createLink(SlideToken token, LinkNode link, java.lang.String linkUri, ObjectNode linkedObject) Creates a link to another node in the namespace. java.lang.String generateUniqueUri(SlideToken token, java.lang.String parentUri) Generates an URI that is guranteed to be unqiue globally. java.util.Enumeration getChildren(SlideToken token, ObjectNode object) Returns the children of a node. ObjectNode getParent(SlideToken token, ObjectNode object) Returns the parent of a node. java.util.List getParents(SlideToken token, ObjectNode object, boolean pathOnly, boolean storeOnly, boolean includeSelf) Return all parents of this object node. void remove(SlideToken token, ObjectNode object) Removes a node from the namespace. void removeBinding(SlideToken token, ObjectNode collectionNode, java.lang.String segment) Modifies the collection identified by collectionNode, by removing the binding for the specified segment. ObjectNode retrieve(SlideToken token, java.lang.String strUri) Retrieves a node by URI, following any links. ObjectNode retrieve(SlideToken token, java.lang.String strUri, boolean translateLastUriElement) Retrieves a node by URI. void store(SlideToken token, ObjectNode object) Stores/updates an object. NodeRevisionDescriptors class Method Summary (package private) void addSuccessor(NodeRevisionNumber number, NodeRevisionNumber successor) Add relation. NodeRevisionDescriptors cloneObject() Clone. java.util.Enumeration enumerateBranchNames() Enumerate all branch names. java.util.Enumeration enumerateRevisionNumbers() Enumerate all revision numbers in all branches. boolean equals(java.lang.Object obj) Equals. NodeRevisionNumber getInitialRevision() Get initial revision. NodeRevisionNumber getLatestRevision() Get latest revision from main branch. NodeRevisionNumber getLatestRevision(java.lang.String branchName) Get latest revision from a branch. java.lang.String getOriginalUri() OriginalUri accessor. java.util.Enumeration getSuccessors(NodeRevisionNumber number) Get relations. java.lang.String getUri() Uri accessor. boolean hasRevisions() Has revision ? boolean isAncestorDescendant(NodeRevisionNumber ancNrn, NodeRevisionNumber descNrn) Return true, if ancNrn and descNrn are in an ancestor-descendant relationship in this history. boolean isRedirected() Returns true, if and only if uri != originalUri boolean isVersioned() Use versioning accessor. (package private) void removeSuccessor(NodeRevisionNumber number, NodeRevisionNumber successor) Remove relation. (package private) void setLatestRevision(NodeRevisionNumber number) Latest revision mutator. (package private) void setLatestRevision(java.lang.String branch, NodeRevisionNumber number) Latest revision mutator. (package private) void setOriginalUri(java.lang.String originalUri) OriginalUri mutator. (package private) void setSuccessors(NodeRevisionNumber number, NodeRevisionNumber successor) Add relation. (package private) void setSuccessors(NodeRevisionNumber number, java.util.Vector successors) Add relation. void setUri(java.lang.String uri) Uri mutator. (package private) void setVersioned(boolean useVersioning) Use versioning mutator. void validate(java.lang.String expectedUri) Validate. NodeRevisionDescriptor class Method Summary void addLabel(java.lang.String label) Add new label. NodeRevisionDescriptor cloneObject() Clone. java.util.Enumeration enumerateLabels() Enumerate labels. java.util.Enumeration enumerateProperties() Properties values enumerator. java.util.Enumeration enumeratePropertiesName() Properties names enumerator. java.util.Enumeration enumerateRemovedProperties() java.util.Enumeration enumerateUpdatedProperties() boolean equals(java.lang.Object obj) Equals. boolean exists(java.lang.String name) Tests if a property has been set. boolean exists(java.lang.String name, java.lang.String namespace) Tests if a property has been set. java.lang.String getBranchName() Branch name accessor. java.lang.String getContentLanguage() Content language accessor. long getContentLength() Content length accessor. java.lang.String getContentType() Get the MIME content type of the data (if any). java.lang.String getCreationDate() Creation date accessor. java.util.Date getCreationDateAsDate() Creation date accessor. java.lang.String getCreationUser() Get the creation user java.lang.String getETag() Get the ETAG property (if any). java.lang.String getLastModified() Last modification date accessor. java.util.Date getLastModifiedAsDate() Creation date accessor. java.lang.String getModificationDate() Modification date accessor. java.lang.String getModificationUser() Get the mofications user java.lang.String getName() Name accessor. java.lang.String getNamespacedPropertyName(java.lang.String namespace, java.lang.String propertyName) Calculate the property name concatenated with the namespace, if available java.lang.String getOwner() Get the owner property (if any). (package private) java.util.Hashtable getProperties() Properties accessor. java.util.Enumeration getPropertiesNames() Deprecated. Replaced by enumeratePropertiesName java.util.Enumeration getPropertiesValues() Deprecated. Replaced by enumerate properties NodeProperty getProperty(java.lang.String name) Property accessor. NodeProperty getProperty(java.lang.String name, java.lang.String namespace) Property accessor. java.lang.String getResourceType() Get the ResourceType property (if any). NodeRevisionNumber getRevisionNumber() Revision number accessor. java.lang.String getSource() Get the source property (if any). boolean propertyValueContains(java.lang.String name, java.lang.String substr) Checks whether the value of the given property contains the specified substring. boolean propertyValueContains(java.lang.String name, java.lang.String namespace, java.lang.String substr) Checks whether the value of the given property contains the specified substring. void removeLabel(java.lang.String label) Remove a label. void removeLabels() Remove all labels. void removeProperty(NodeProperty property) Remove a property. void removeProperty(java.lang.String property) Remove a property. void removeProperty(java.lang.String property, java.lang.String nameSpace) Remove a property. void resetRemovedProperties() void resetUpdatedProperties() (package private) void setBranchName(java.lang.String branchName) Branch name mutator. void setContentLanguage(java.lang.String contentLanguage) Content language mutator. void setContentLength(long contentLength) Creation length mutator. void setContentLength(java.lang.String contentLength) Creation length mutator. void setContentType(java.lang.String contentType) Content type mutator. void setCreationDate(java.util.Date creationDate) Creation date mutator. void setCreationDate(java.lang.String creationDate) Creation date mutator. void setCreationUser(java.lang.String creationUser) Creation user mutator. (package private) void setDefaultProperties(java.util.Enumeration defaultProperties) Set default properties. void setETag(java.lang.String eTag) Set ETAG property. void setLastModified(java.util.Date lastModified) Last modified mutator. void setLastModified(java.lang.String lastModified) Last modified mutator. void setModificationDate(java.util.Date modificationDate) Modification date mutator. void setModificationDate(java.lang.String modificationDate) Modification date mutator. void setModificationUser(java.lang.String modificationUser) Modification user mutator. void setName(java.lang.String name) Name mutator. void setOwner(java.lang.String owner) Set owner property. void setOwner(java.lang.String owner, java.lang.String userpath) Set owner property. (package private) void setProperties(java.util.Hashtable properties) Properties mutator. void setProperty(NodeProperty property) Property mutatory. void setProperty(java.lang.String name, java.lang.Object value) Property mutator. void setProperty(java.lang.String name, java.lang.String namespace, java.lang.Object value) Property mutator. void setResourceType(java.lang.String resourceType) Set ResourceType property. (package private) void setRevisionNumber(NodeRevisionNumber number) Revision number mutator. void setSource(java.lang.String source) Set source property. void validate() Validate. NodeRevisionNumber class Method Summary (package private) NodeRevisionNumber cloneObject() Clone. boolean equals(java.lang.Object obj) Equals. int getMajor() Get the first number in the revision number. int getMinor() Get the second number in the revision number. int getNbDigits() Return number of digits if the revision number. int getNumber(int pos) Get a number by specifying its order. int hashCode() HashCode. java.lang.String toString() Get a String representation of the revision number. void validate() Validate. Definition Node 1. Domain.xml Definition Node From my understanding, the definition section sets where all the data concerning different parts of Slide will be stored. In the example all sub-stores (lock, content, etc...) are stored using "org.apache.slide.store.txfile.[WWW]TxXMLFileDescriptorsStore", which essentially stores data in an XML formatted file. 120 store/metadata work/metadata true 120 store/sequence store/content work/content true 120 To setup Slide with multiple Store Definitions see MultiStoreConfig 1.1. General Store Information Stores are low level services that handle the actual storage of content and related data. Stores are totally pluggable, enabling the use of the most appropriate storage method for the type of data to store. Two different kinds of services exist: * The Descriptors stores, which are responsible for storing structure, locks, metadata, etc. * The Content stores, which is only responsible for storing the actual content. This distinction has been made because it's easy to see that while some repositories are very efficient at managing and indexing small amounts of data (relational databases are a good example of this), others are best for storing big chunks of data (for example filesystems). Within Slide, every object can possibly have a different kind of backing low-level service. For example, some objects might be stored in a remote LDAP directory, while others could be stored in an local SQL database. Thus, the content of a namespace can be distributed across several different descriptors and content stores. It is up to the administrator to choose how objects will be stored using the Slide configuration file, which maps low-level services to individual nodes in the namespace. Services are attributed to nodes in the namespace. This mapping is automatically inherited by sub-nodes. Here is an example of how one namespace might be mapped into different low-level services: 1.2. Parameters 1.2.1. Cache Parameters cluster Caching mode should be set to "cluster" when you want every change in the file system to be immediately displayed in Slide. Other options for this parameter are not yet known - if you know it please add / elaborate here For more information see CacheConfiguration. 1.2.2. Locking 120 This determines how many seconds pass before your Slide session times out? 1.2.3. Rootpath store/metadata 1.2.4. Cache Timeout For Slide 2.2 and above you can add this parameter for more caching with a timeout (100 sec in this case) 100 full 1.3. Scope "You need to add the scope to have the store (tx) visible." "So far, you can choose to configure the tags either directly underneath each store, or put all the tags at the bottom of configuring all your stores at this time. Soon there will be a standard and expectation, but for now lasse faire." Basically this determines how you access your Slide applicatio. In the above example accessing the Slide application would be: http://localhost:8080/tx 1.4. General Store Definition Information (Low Level Services) This describes low-level services configuration for the store. (For some reason, it was decided that these low level services also be called "stores" - this makes it a bit confusing.) "classname" specifies the class that implements the sub-store in question. This hints at developers being able to create their own custom store, which is was Slide was designed for from the beginning. For more information see the CreateNewSlideStore entry. The following are sub-store class implementions that are built into Slide - TxFileContentStore [WWW]TxXMLFileDescriptorsStore [WWW]JDBCStore FileSequenceStore From my understanding (please correct me if I'm wrong), you have the following choices in regard to low level services related to stores. 1. Define the low level service by associating it with the appropriate concrete class 1. Define a low level service that can be referenced by other low level services as seen in nodestore store/metadata work/metadata true 120 "The reference means that for the security store the same object is used as is, is configured at the node store." To get a better understanding compare the default nodestore definition (above) and the nodestore definition using JDBC. The default nodestore stores all of its data in XML format text files while the nodestore below stores the data in predefined tables. 1.4.1. callback-store Parameter org.apache.slide.store.simple.WebdavFileStore 1.4.2. rootpath Parameter This is where all the resources in the "files, content, etc..." collection go to c:/tmp 1.5. Content Store Low Level Service store/content work/content true 120 1.6. Node Store Low Level Service 1.6.1. Default File Based Node Store Low Level Service Using the default node store, will have the namespace's data be stored in XML formatted text files. store/metadata work/metadata true 120 1.6.2. JDBC Node Store Low Level Service Of course, for ease of maintenance most people will probably want to use a database to store most of the data related to a Slide namespace. In the example below, most sub-stores (except content) are using the JDBC configured nodestore. Note If you want to try a JDBC nodestore you also have to create all the necessary tables and views that Slide expects. You can use the scripts (configured for most major database servers) found in jakarta-slide-2.1-tomcat-5.0.28/webapps/slide/db-schema/ (for 2.1). org.apache.slide.store.impl.rdbms.PostgresRDBMSAdapter org.postgresql.Driver jdbc:postgresql://19.26.54.86:5432/db_name test 12345 true 10 SERIALIZABLE false org.postgresql.Driver Put the name of the jdbc driver you want to use here. jdbc:postgresql://19.26.54.86:5432/db_name The database url varies by database and jdbc driver. Consult the accompanying jdbc documentation. test 12345 A username / password combination that can access the database. true 10 This enables DBCPPooling and specifies the number of connections it can have. false I believe if you set this true, Slide will compress (using zip) incomming data and uncompress outbound data. This is quite useful. 1.7. Sequence Store 1.8. Security Store 1.9. Lock Store J2EEStore In order to use the J2EE stores, the Domain.xml file needs to contain the following configuration for the store: jdbc/mtx org.apache.slide.store.impl.rdbms.MySqlRDBMSAdapter false where the adapter determines which database adapter you want to use. In this case you configured the MySQL adapter. Most adapters have a parameter to decide whether the content shall be compressed (zipped) before storing to the database. This might be fast in some enviroments. This option is switched off here. You have to create the tables of the database schema manually. Schemata are available in src/conf/schema if you have the source distribution or in slide/db-schema if you have the Tomcat bundled or binary distribution. If your store is not configured using a datasource looked up using JNDI you will have to provide more information to Slide like this for example: org.apache.slide.store.impl.rdbms.MySqlRDBMSAdapter com.mysql.jdbc.Driver jdbc:mysql://localhost/Slide root true 10 SERIALIZABLE false You can see you will have to configure you driver, the connection url and the user for the database. You can optionally configure if connection pooling using DBCP is enabled or not and if enabled how many connections shall be pooled. If you want you can also choose the isolation level of your database. SERIALIZABLE is a safe choice, but - depending on you database - at least READ COMMITTED is recommended. Locks Needed 1. Table of accesses per method * All write and read requests have a read access from the accessed uri to the root uri * All write and read requests have a read access to the users and roles folder * Even a pure read access might create a new user in the users folder if user auto creation is set * All writing requests have an additional write access to the history folder if auto versioning is turned on Method Read Write Implemented COPY source uri recursive target uri recursive YES DELETE target uri recursive target uri recursive YES GET like head - YES HEAD uri - YES MKCOL like put like put without calls to history folder YES MOVE source and target uri recursive source and target uri recursive YES OPTIONS like head - YES POST like head - YES PROPPATCH uri uri and history sub folder YES PUT uri and history folder uri and direct parent, history and sub folder when resource is put under version control, subfolder when already under version control YES VERSION uri and history folder uri and history and sub folder YES REPORT uri und history folder - YES CHECKIN like checkout like checkout YES CHECKOUT uri und history folder uri and history sub folder YES UNCHECKOUT like checkout like checkout YES SEARCH global - YES PROPFIND source uri and descendants if depth > 0 - YES LOCK like head uri YES UNLOCK like head uri YES ACL uri uri and history sub folder YES SUBSCRIBE - - n/a UNSUBSCRIBE - - n/a POLL - - n/a NOTIFY - - n/a MKWORKSPACE ? ? tentative as global write lock UPDATE ? ? tentative as global write lock LABEL ? ? tentative as global write lock BIND ? ? tentative as global write lock UNBIND ? ? tentative as global write lock REBIND ? ? tentative as global write lock