<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ ModeShape (http://www.modeshape.org)
  ~
  ~ See the COPYRIGHT.txt file distributed with this work for information
  ~ regarding copyright ownership.  Some portions may be licensed
  ~ to Red Hat, Inc. under one or more contributor license agreements.
  ~ See the AUTHORS.txt file in the distribution for a full listing of 
  ~ individual contributors.
  ~
  ~ ModeShape is free software. Unless otherwise indicated, all code in ModeShape
  ~ is licensed to you under the terms of the GNU Lesser General Public License as
  ~ published by the Free Software Foundation; either version 2.1 of
  ~ the License, or (at your option) any later version.
  ~
  ~ ModeShape is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  ~ for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public License
  ~ along with this distribution; if not, write to:
  ~ Free Software Foundation, Inc.
  ~ 51 Franklin Street, Fifth Floor
  ~ Boston, MA  02110-1301  USA
  -->
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"	[
<!ENTITY % CustomDTD SYSTEM "../../custom.dtd">
%CustomDTD;
]>
<chapter id="jcr">
  <title>Using the JCR API with ModeShape</title>
  <para>
  	The
    <ulink url="&JSR283;">Content Repository for Java Technology API 2.0</ulink>
    provides a standard Java API for working with content repositories. Abbreviated "JCR", this API was developed as part of the
		Java Community Process under <ulink url="&JSR170;">JSR-170</ulink> (JCR 1.0) and has been revised and improved as JCR 2.0 under <ulink url="&JSR283;">JSR-283</ulink>.
		Some of the improvements make it possible for your application to be written entirely against the JCR 2.0 API.
  </para>
	<note>
		<para>
			In the interests of brevity, this chapter does not attempt to reproduce the JSR-283 specification nor provide
		  an exhaustive definition of ModeShape JCR capabilities.  Rather, this chapter will describe any deviations from the
		  specification as well as any ModeShape-specific public APIs and configuration. So, for a detailed explanation
		  of the JCR API and its many interfaces and methods, see the <ulink url="&JSR283;">JSR-283</ulink> specification.
		</para>
	</note>
	<para>
		Using ModeShape within your application is actually quite straightforward, and with JCR 2.0 it is possible for your
		application to do everything using only the JCR 2.0 API. Your application will first obtain a <code>javax.jcr.Repository</code> instance,
		and will use that object to create sessions through which your application will read, modify, search,
		or monitor content in the repository.
    JCR sessions are designed to be lightweight, so it is perfectly fine 
		(and actually recommended) for your application to create many short-lived sessions while generally avoiding
		longer-lived sessions. In fact, <code>javax.jcr.Session</code> objects are not required to be thread-safe
		(and are not in ModeShape), so your application should avoid using a single Session instance in multiple threads.
	</para>
	<sect1 id="whats_new_in_jcr2">
		<title>What's new in JCR 2.0?</title>
		<para>
			Before we get started talking about how to use ModeShape via the standard JCR 2.0 API, it's worth spending a little time talking
			about the changes in JCR 2.0 compared with JCR 1.0.
		</para>
		<para>
	    Although an application written against the JCR 1.0 API will for the most part work very well against a JCR 2.0 repository, there are
	    a few improvements to the JCR 2.0 API that your application will likely want to leverage.
		</para>
		<para>
			Let's look at some of the more important changes in the JCR 2.0 API. However, this is certainly not definitive nor a complete
			comparison, so please consult the <ulink url="&JSR283;">JSR-283</ulink> specification.
		</para>
		<sect2 id="jcr2_establishing_connections">
			<title>Connecting</title>
			<para>
				JCR 1.0 did not specify a way for client applications to obtain the &Repository; instance, though the JCR 1.0 specification did
				state this is typically done through JNDI. Consequently, JCR clients either used the JNDI approach or were required to use
				implementation-specific code. Often, client applications abstracted this process to minimize their reliance upon implementation-specific
				interfaces.
			</para>
			<para>
				While the JNDI approach still works, JCR 2.0 introduces a new mechanism that makes it possible to find a &Repository; instance 
				using only the JCR API. Details	of this are covered more in <link linkend="obtainining_jcr_repository">later</link>, but suffice 
				to say that ModeShape does support this new &RepositoryFactory; approach. 
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> If your application used an implementation-specific approach to obtaining
				a &Repository; instance, you might consider changing it to use the 
				<link linkend="obtainining_jcr_repository">new &RepositoryFactory; mechanism</link>.
			</para>
		</sect2>
		<sect2 id="jcr2_identifiers">
			<title>Identifiers</title>
			<para>
				JCR 1.0 used the notion of UUIDs on referenceable nodes - in other words those nodes with the "mix:referenceable" mixin.
				However, there were several disadvantages to this design.  First, non-referenceable nodes had no such identifier in the JCR API,
				leading to difficulties in easily identifying nodes using an immutable and invariant identifier (unlike the path, which can change
				at any time) and requiring a fair amount of code to check whether a node is referenceable before its UUID could safely be obtained. 
				Second and perhaps more importantly, only valid UUIDs could be used to identify nodes. This can cause difficulty
				when JCR is used as an API to another system that does not use UUIDs.
			</para>
			<para>
				JCR 2.0 introduces the notion of an identifier on all nodes, and the format of this identifier is designed to be opaque to the
				client applications. This dramatically reduces the code to access a node's identifier down to a simple method call. And it
				makes it possible for an implementation to use any identifiers format. This is good for ModeShape federation, as connectors
				no longer need to force UUIDs for all nodes.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> The <code>Node.getUUID()</code> method is now deprecated, and instead 
				your code should call <code>Node.getIdentifier()</code>, which works on any node. However, be aware that the resulting identifier 
				is no longer required to be a valid UUID.  ModeShape does support these methods and behavior.
			</para>
		</sect2>
		<sect2 id="jcr2_binary_values">
			<title>Binary Values</title>
			<para>
				JCR 1.0 has always supported storing binary values in properties, but clients could do little more than just stream the bytes
				for each value.  JCR 2.0 introduces a &Binary; interface that defines a way to get the size of the binary value, an InputStream
				to the value, a method for random access to the value's bytes, and a way to dispose of the binary value when completed
				(allowing the implementation to better clean up memory and other resources).
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> The way your existing JCR application accesses and sets binary values
				will still work, but the methods are now deprecated.  Therefore, you will very likely want to change to use the new &Binary; interface. 
				For example, code that previously accessed the input stream directly from the &Property;:
			</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[Property property = ...
InputStream stream = property.getInputStream();
try {
   // Read stream
} finally {
   stream.close();
}
]]></programlisting>
  		<para>
	      can be minimally changed to first get the &Binary; value and then get the stream from this Binary value:
			</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[Property property = ...
InputStream stream = property.getBinary().getInputStream();
try {
   // Read stream
} finally {
   stream.close();
}
]]></programlisting>
  		<para>
	      This second example is not using any deprecated methods, but does not actually dispose of the &Binary; object. This actually
	      works just fine in ModeShape, as closing the InputStream will automatically dispose of the &Binary; object.
	    </para>
	    <para>
	      You may also consider whether your application may benefit from the new <code>Binary.getSize()</code> or <code>Binary.read(byte[],long)</code> methods.
			</para>
		</sect2>
		<sect2 id="jcr2_node_type_management">
			<title>Node Type Management</title>
			<para>
				In JCR 1.0, client applications could discover node types, property definitions, and child node definitions, but the API did not
				provide a way for client applications to modify or create new node types. This has been rectified in the JCR 2.0 API, and is
				these methods are now supported by ModeShape.
			</para>
			<para>
				Additionally, the JCR 2.0 specification formalized the <emphasis>Compact Node Definition</emphasis> grammar, and made a few minor
				improvements to the CND formats used in some JCR 1.0 implementations. Earlier ModeShape releases supported the older CND format,
				and ModeShape &versionNumber; now supports the grammar as defined in the specification.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Your application can now define its node types using the standard
				CND format and/or using the new programmatic mechanism. If you already used the older CND format, be aware of the few new
				options available when defining property definitions (e.g., searchable, queryable, etc.). Note that node type discovery is
				largely unchanged.
			</para>
	    <note>
		    <para>
					Remember to specify the <link linkend="system_workspace_configuration">system workspace name</link> for your repositories
					if dynamically adding or modifying node types. Otherwise, ModeShape will not persist your node type changes.
				</para>
		  </note>
		</sect2>
		<sect2 id="jcr2_query_feature">
			<title>Queries</title>
			<para>
				JCR 1.0 made it possible for applications to query the repository using XPath and JCR-SQL query languages. JCR 2.0 maintains
				the (mostly) similar Java interfaces for executing queries, but it deprecates the XPath and JCR-SQL query languages
				and introduces a new declarative language called "JCR-SQL2" that is a very good improvement over JCR-SQL. JCR 2.0 also
				introduces a new query object model (called "JCR-QOM") for defining queries using a programmatic API.
			</para>
			<para>
				ModeShape supports all of these languages (<link linkend="jcr-xpath-query-language">XPath</link>, 
				<link linkend="jcr-sql-query-language">JCR-SQL</link>, <link linkend="jcr-sql2-query-language">JCR-SQL2</link>, 
				<link linkend="jcr-qom-query-language">JCR-QOM</link>), and also supports a 
				<link linkend="fulltext-search-query-language">full-text query language</link>
				that is defined by the full-text search expression in the JCR-SQL2 language. Additionally, ModeShape extends most of these
				languages to support richer and more capable queries.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Your application can continue to use XPath and JCR-SQL queries.
				However, your application may benefit from switching from JCR-SQL to JCR-SQL2 and its greater capabilities and expressive
				power. Leverage some of the ModeShape extensions to make your JCR-SQL2 queries even more powerful.
			</para>
		</sect2>
		<sect2 id="jcr2_workspace_management">
			<title>Workspace Management</title>
			<para>
				Applications could not use the JCR 1.0 API to create or destroy workspaces, meaning such operations could only be done through
				a non-standard and implementation-specific API. The JCR 2.0 API now standardizes these operations, and although not all
				implementations are required to support them, ModeShape does support these (though not all connectors do support them).
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Your application can now create and remove workspaces using the standard JCR 2.0 API.
			</para>
		</sect2>
		<sect2 id="jcr2_observation">
			<title>Observation</title>
			<para>
				Applications could use the JCR 1.0 API to be notified of changes to the content, using the optional observation feature.
				However, the JCR 1.0 API required multiple events to be created when a subtree was moved or deleted.
				This requirement has been relaxed in JCR 2.0 and ModeShape now fully supports the optional observation feature.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Your application can now use specification-compliant JCR 2.0 observation with ModeShape.
			</para>
		</sect2>
		<sect2 id="jcr2_locking">
			<title>Locking</title>
			<para>
				JCR 1.0 API had the notion of locking nodes, useful in situations that required synchronization around reading and modifying
				content. This optional API is simple and clean, and worked quite well. The JCR 2.0 API preserved all of the JCR 1.0 locking semantics,
				but added a few (optional) methods. ModeShape implements this optional locking feature.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> If your application is already using the JCR 1.0 locking feature,
				be aware that many of the locking-related methods on &Node; were deprecated in JCR 2.0 and moved to the new &LockManager; interface.
				However, locking semantics remain unchanged.
			</para>
	    <note>
		    <para>
					Remember to specify the <link linkend="system_workspace_configuration">system workspace name</link> for your repositories
					if clustering or if the lock information is to be persisted beyond the lifetime of the ModeShape engine.
				</para>
		  </note>
		</sect2>
		<sect2 id="jcr2_versioning">
			<title>Versioning</title>
			<para>
				Versioning of nodes was defined as an optional feature of the JCR 1.0 API. The JCR 2.0 API expanded upon locking by defining
				a simple versioning model, introducing the &VersionManager; interface, and making some semantic changes as well. For example, 
				restoring a version that contained a versioned child in its subgraph no longer automatically restores the versioned child.
				This behavior was ambiguous in the JCR 1.0 specification, and ModeShape 1.x performed the restore operation recursively down the graph.
				The JCR 2.0 specification more clearly requires a non-recursive restore. Therefore, ModeShape &versionNumber; now supports
				the "full versioning" model.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> If your application is already using JCR 1.0 versioning feature,
				be aware that many of the version-related methods on &Node; were deprecated in JCR 2.0 and moved to the new &VersionManager; interface.
				Also, any reliance upon ModeShape's recursive restore operation must be changed, per the JCR 2.0 specification.
			</para>
	    <note>
		    <para>
					Remember to specify the <link linkend="system_workspace_configuration">system workspace name</link> for your repositories
					if using versioning. Otherwise, ModeShape will not persist your versioning information.
				</para>
		  </note>
		</sect2>
		<sect2 id="jcr2_importing_and_exporting">
			<title>Importing and Exporting</title>
			<para>
				Importing and exporting content is largely unchanged in JCR 2.0, with the exception of specific requirements on handling
				node identifiers.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Exporting from a JCR 1.0 or 2.0 repository and importing into a JCR 2.0 repository
				should work as before. ModeShape does support importing and exporting.
			</para>
		</sect2>
		<sect2 id="jcr2_shareable_nodes">
			<title>Shareable Nodes</title>
			<para>
				JCR 2.0 introduced the notion of <emphasis>shareable nodes</emphasis>, which allows a node that exists under one parent to be shared
				under multiple other nodes. These are similar to symbolic links in a *nix file system. For more details about how to create and use
				shareable nodes, please see the <ulink url="&JSR283;">JCR 2.0 specification</ulink>.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Your application can now use specification-compliant JCR 2.0 shareable nodes with ModeShape.
			</para>
		</sect2>
		<sect2 id="jcr2_orderable_child_nodes">
			<title>Orderable Child Nodes</title>
			<para>
				Orderable child nodes was an optional feature in JCR 1.0, and has been carried over to JCR 2.0 unchanged. Node ordering has been supported
				by ModeShape since the initial release.
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> No changes are required if your application relies upon node ordering.
			</para>
		</sect2>
		<sect2 id="jcr2_paths">
			<title>Paths</title>
			<para>
				As defined in JCR 1.0, paths only consisted of segments with node names. JCR 2.0 adds a new form of path called "identifier paths" that
				are of the form <code>'[' </code><emphasis>identifier</emphasis><code> ']'</code>, where <emphasis>identifier</emphasis> is an opaque
				identifier. (Note that the JCR 2.0 specification might appear to allow identifier segments and name segments to be used together, but
				Section 3.4.1.1 requires that an identifier segment must be the first and only segment in a path.)
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Any application written to JCR 1.0 paths will likely work as expected (this is
				certainly true when using ModeShape repositories). However, with JCR 2.0 it is now possible for your application to start making us
				of identifier paths. For example, PATH properties can now store identifier paths, and it is possible to resolve an identifier path
				to the actual node. And while the specification does not preclude an implementation returning an identifier path as the node's
				absolute path, ModeShape never does this and will always return the name-oriented path.
			</para>
		</sect2>
		<sect2 id="jcr2_getting_items">
			<title>getItem(String)</title>
			<para>
				The JCR 1.0 specification was slightly ambiguous in defining how the <code>getItem(String)</code> method behaved if the relative path
				could resolve to a node or a property.  ModeShape always implemented this by first attempting to resolve to a node, and only if no
				such node could be found would it attempt to resolve to a property. The JCR 2.0 specification now explicitly specifies this behavior
				(see Section 3.4.2.2).
			</para>
			<para>
				<emphasis>How this affects your application:</emphasis> Your application will need to change if it uses <code>getItem(String)</code> and 
				expects relative paths to be resolved against properties before nodes, as this is clearly different from the JCR 2.0 specified behavior.
				Otherwise, your application needs no changes with respect to <code>getItem(String)</code>.
			</para>
		</sect2>
  </sect1>
	<sect1 id="obtainining_jcr_repository">
		<title>Obtaining a JCR Repository</title>
		<para>
			Before your application can use a JCR repository, it has to find it. As mentioned <link linkend="jcr2_establishing_connections">above</link>,
			the JCR 2.0 API defines a new &RepositoryFactory; interface that can be used with the 
			<ulink url="&Java;java/util/ServiceLoader.html">Java Standard Edition Service Loader mechanism</ulink>
			to obtain a &Repository; instance, all using the JCR API alone:
		</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[
Map<String,String> parameters = ...
Repository repository = null;
for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
    repository = factory.getRepository(parameters);
    if (repository != null) break;
}]]></programlisting>
		<para>
			This code looks for all &RepositoryFactory; implementations on the classpath (assuming those implementations properly defined the service provider
			within their JARs), and will ask each to create a repository given the supplied parameters. Thus, the parameters
			are specific to the implementation you want to use.
	  </para>
		<note>
			<para>
				With JCR 1.0, applications could only find a &Repository; instance using implementation-specific code.
				This new JCR 2.0 approach is a bit more complicated, but should work with most JCR 2.0 implementations
				and does not require using any implementation classes. And your application can even load the parameters
				from a configuration resource, meaning nothing in your application depends on a particular JCR implementation.
			</para>
		</note>
	  <para>
			ModeShape uses a single property named "<code>org.modeshape.jcr.URL</code>"
			with a value that is a URL that either resolves to a ModeShape configuration file.
			Pointing directly to a configuration file often works well in stand-alone applications or where the configuration
			is managed in a central system. JNDI works great for applications deployed to server platforms (e.g., an application
			server or servlet container) where multiple applications might want to use the same JCR repository (or same 
			ModeShape engine). We'll see in the <link linkend="jcr_engine">next section</link> 
			how to configure ModeShape's &JcrEngine; explicitly and register it in JNDI.
		</para>
		<para>
			So, here's the ServiceLoader example again, but with ModeShape-specific parameters:
		</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[
String configUrl = ... ; // URL that points to your configuration file
Map<String,String> parameters = Collections.singletonMap("org.modeshape.jcr.URL", configUrl);

Repository repository = null;
for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
    repository = factory.getRepository(parameters);
    if (repository != null) break;
}]]></programlisting>
		<para>
			Once you've gotten hold of a &Repository; instance, you can use it to create &Session;s, using code similar to:
    </para>			
    <programlisting language="JAVA" role="JAVA"><![CDATA[
Credentials credentials = ...; // JCR credentials
String workspaceName = ...;  // Name of repository workspace
Session session = repository.login(credentials,workspaceName);
]]></programlisting>
    <para>
	    We'll talk about the various ways of creating sessions in a <link linkend="">later chapter</link>.
	    First, let's look at the various kinds of URLs that you can use.
		</para>
		<sect2>
			<title>Configuration File URLs</title>
			<para>
				The value of <code>configUrl</code> in the code snippets can be any URL that is resolvable on your
				system.  For example:
		  </para>
	    <programlisting><![CDATA[ file://path/to/configFile.xml?repositoryName=MyRepository ]]></programlisting>
	    <para>
				In this example, the configuration file that specifies the repository setup will be loaded from the file path <code>relativePathToConfigFile</code> and 
				the repository named <code>yourRepositoryName</code> will be returned.  If ModeShape cannot find a file at the given path,
				it will try to load a configuration file as a resource through the classloader.
			</para>
		  <para>
			  You might have noticed that this URL contains a query parameter (the "<code>?repositoryName=MyRepository</code>" part).
			  ModeShape strips all query parameters when attempting to resolve <code>file:</code> URLs to the underlying file.
			</para>
			<para>
				Here's another example of a file URL that uses an absolute path to the file:
			</para>
	    <programlisting><![CDATA[ file://path/to/configFile.xml?repositoryName=MyRepository ]]></programlisting>
	    <para>
				Note the addition of the three forward slashes after the protocol portion of the URL (i.e., <code>file:</code>). These indicate the
				path is absolute.
		  </para>
	    <para>
				Other URLs are possible, too. Here is a URL that points to a configuration file stored in a web-enabled service,
				such as a web server, WebDAV file share, or version control system: 
		  </para>
	    <programlisting><![CDATA[ http://www.example.com/path/to/configFile.xml?repositoryName=MyRepository ]]></programlisting>
			<para>
				Unlike with "<code>file:</code>" URLs, ModeShape does not strip the URL's query parameters when resolving to the
				configuration file, since most web servers ignore any query parameters not needed. This allows you to include 
				additional query parameters in the URL if they're needed to retrieve the file from the server.
			</para>
			<para>
				If your platform supports URLs with the "<code>classpath:</code>" scheme, you can point to a resource file on the
				classpath:
			</para>
	    <programlisting><![CDATA[ classpath:path/to/configFile.xml?repositoryName=MyRepository ]]></programlisting>
	    <para>
				Not all environments have such support, however. Many application servers, including 
			  <ulink url="http://jboss.org/jbossas">JBoss AS</ulink> and <ulink url="http://www.jboss.com/products/platforms/application/">EAP</ulink>,
				do include support by default. However, the Java Standard Edition (SE) does not come with a "<code>classpath:</code>" URL handler,
				though it is <ulink url="http://stackoverflow.com/questions/861500/url-to-load-resources-from-the-classpath-in-java">easy to add</ulink>.
		  </para>
			<para>
				ModeShape does the same thing with all of these URLs: it looks to see whether it already has started a &JcrEngine; with a configuration file
				at the given URL. If so, it uses the value of the "<code>repositoryName</code>" query parameter and passes it to the
			  <code>getRepository(String)</code> method. The result of this method call will be a &Repository; object that is then returned from
			  the factory.
			</para>
			<para>
				However, if the RepositoryFactory has not yet seen this URL, it will download the configuration file at the URL, load it
				using a new &JcrConfiguration; object, and start a new &JcrEngine; instance.  It then uses the "<code>repositoryName</code>"
				query parameter to obtain the &Repository; as mentioned above.
			</para>
		</sect2>
		<sect2>
			<title>Using JNDI URLs</title>
			<para>
				The previous section showed how to use a URL to a configuration file to start a new ModeShape instance. However, 
				ModeShape can be deployed and managed as a <link linkend="modeshape_in_web_applications">central, shared service</link>
				in a variety of environments, including <ulink url="http://jboss.org/jbossas">JBoss AS</ulink> and 
				<ulink url="http://www.jboss.com/products/platforms/application/">EAP</ulink>.
				Since a single ModeShape instance can manage multiple repositories, using a single shared instance will have a smaller
				footprint than multiple ModeShape instances each running a single repository. Plus, the central ModeShape instance
				can be configured, monitored, administered, and managed without requiring each application to perform these functions.
			</para>
			<para>
				The easiest and most common way for applications to find and reuse this central, shared ModeShape service is to
				use JNDI. ModeShape's &RepositoryFactory; implementation accepts "<code>jndi:</code>" URLs instead of the file-based
				URL described in the previous chapter. The format of these JNDI URLs is:
			</para>
			<programlisting><![CDATA[ jndi:name/in/jndi?repositoryName=MyRepository ]]></programlisting>
		  <para>
			  The RepositoryFactory will look for a ModeShape engine registered in JNDI at "<code>name/in/jndi</code>", and
			  will ask that engine for the &Repository; instance with the name "<code>MyRepository</code>". Note that
			  when a JNDI URL is used, RepositoryFactory is will never create its own ModeShape engine instance: if none
			  can be found in JNDI, the RepositoryFactory will simply return null.
			</para>
			<para>
				Sometimes a JNDI implementation will require creating a new &InitialContext; instance with a hashtable of environment parameters.
				If this is the case for your environment, simply include those extra parameters in the Map passed into the 
				<code>getRepository(Map)</code> method. ModeShape will forward these extra parameters into the 
				&InitialContext; constructor it uses look up the JNDI reference.
			</para>
		</sect2>
		<sect2>
			<title>Cleaning Up after JcrRepositoryFactory</title>
			<para>
				If your application uses &RepositoryFactory; with a ModeShape URL pointing to a configuration file,
				the &RepositoryFactory; creates an embedded ModeShape engine (or several, if multiple configuration files are used)
				that maintains a serious of connections, thread pools, and other resources. In these cases, your application should shutdown ModeShape
				so that it can properly release all accumulated resources.
			</para>
			<para>
				The <ulink url="&JSR283;">JSR-283</ulink> specification does not specify a standard way to shutdown engines or repositories 
				created as a side effect of &RepositoryFactory;, so ModeShape has an extension to the <ulink url="&JSR283;">JSR-283</ulink> API 
				that provides this capability.
			</para>
			<para>
	      When you obtain your Repository instance using the ServiceLoader mechanism described earlier, keep a reference to the
				&RepositoryFactory; that returns a non-null &Repository;:
			</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[Map<String,String> parameters = ...
Repository repository = null;
RepositoryFactory factory = null;
for (RepositoryFactory aFactory : ServiceLoader.load(RepositoryFactory.class)) {
    repository = aFactory.getRepository(parameters);
    if (repository != null) {
        factory = aFactory;
        break;
    }
}]]></programlisting>
      <para>
	      Save this reference where your application's shutdown code can access it, then when your application is terminating,
				check the type of the factory, cast to the ModeShape extension, and call the "<code>shutdown()</code>" method:
      </para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[if ( factory instanceof org.modeshape.jcr.api.RepositoryFactory ) {
    ((org.modeshape.jcr.api.RepositoryFactory)factory).shutdown();
}]]></programlisting>
      <para>
				This call to <code>shutdown(...)</code> instructs each of the &JcrEngine; instances created by the factory
				to shutdown gracefully and return immediately (without waiting for any of them to complete the shutdown process).
				If you'd rather block while the engines perform their shutdown, simply supply a timeout:
      </para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[if ( factory instanceof org.modeshape.jcr.api.RepositoryFactory ) {
    ((org.modeshape.jcr.api.RepositoryFactory)factory).shutdown(30,TimeUnit.SECONDS);
}]]></programlisting>
			<para>
				This call will wait up to 30 seconds for each &JcrEngine; to shut down.
			</para>
		</sect2>
	</sect1>
	<sect1 id="jcr_engine">
		<title>ModeShape's JcrEngine</title>
		<para>
			Although the preferred mechanism to obtain a &Repository; object is through the &RepositoryFactory; interface
			<link linkend="obtainining_jcr_repository">described above</link>, there are times when an application wants
			or needs to have more control over an actual ModeShape engine, which encapsulates everything necessary
			to run one or more JCR repositories and managing the underlying repository sources, the pools of connections to the sources, the sequencers,
			the MIME type detector(s), and the &Repository; implementations.
		</para>
		<note>
			<para>
				If your application uses the &RepositoryFactory;, then you can proceed to the <link linkend="jcr-sessions">next section</link>.
			</para>
		</note>
		<para>
			The first step to programmatically instantiating a ModeShape &JcrEngine; is to define a configuration file as described
			in the <link linkend="jcr_configuration">previous chapter</link>. Then, load that configuration file and check
			for problems:
		</para>
   	<programlisting language="JAVA" role="JAVA"><![CDATA[JcrConfiguration config = new JcrConfiguration();
configuration.loadFrom(file);
if ( !configuration.getProblems().isEmpty() ) {
    for ( Problem problem : configuration.getProblems() ) {
        // Report these problems!
    }
}]]></programlisting>
		<para>
			where the <code>file</code> parameter can actually be a &File; instance, a &URL; to the file, an &InputStream; 
			containing the contents of the file, or a &String; containing the path to the configuration file.
		</para>
		<note>
			<para>The <code>loadFrom(...)</code> method can be called any number of times, but each time it is called it completely wipes
			  out any current notion of the configuration and replaces it with the configuration found in the file.
			</para>
		</note>
		<para>
			There is an optional second parameter that defines the &Path; within the configuration file identifying the parent node of the various
			configuration nodes.  If not specified, it assumes "/".  This makes it possible for the configuration content to be
			located at a different location in the hierarchical structure.  (This is not often required, but it is very useful
			if you ModeShape configuration file is embedded within another XML file.)
		</para>
		<note>
			<para>
				If your application is coding against the ModeShape classes, you may also consider 
				<link linkend="programmatic_configuration">programmatically creating the configuration</link>. 
				This is useful when you cannot predefine a configuration, but instead have to build one based upon
				some parameters known only at runtime. Of course, you can always create the configuration programmatically,
				write that configuration out to a file, and then load the configuration using the standard &RepositoryFactory;
				mechanism.
			</para>
		</note>
		<para>
			Once you have a valid &JcrConfiguration; instance with no errors, you can build and start the &JcrEngine;:
		</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[
JcrConfiguration config = ...
JcrEngine engine = config.build();
engine.start();
 ]]></programlisting>
		<para>
			Obtaining a JCR &Repository; instance is a matter of simply asking the engine for it by the name defined in the configuration:
		</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[
javax.jcr.Repository repository = engine.getRepository("Name of repository");
 ]]></programlisting>
		<para>
			At this point, your application can proceed by working with the JCR API.
		</para>
		<para>
			And, once you're finished with the &JcrEngine;, you should shut it down:
		</para>
    <programlisting language="JAVA" role="JAVA"><![CDATA[
engine.shutdown();
engine.awaitTermination(3,TimeUnit.SECONDS);	// optional
 ]]></programlisting>
		<para>
			When the <code>shutdown()</code> method is called, the &Repository; instances managed by the engine are marked as being shut down,
			and they will not be able to create new &Session;s.  However, any existing &Session;s or ongoing operations (e.g., event notifications)
			present at the time of the <code>shutdown()</code> call will be allowed to finish.  
			In essence, <code>shutdown()</code> is a <emphasis>graceful</emphasis> request, and since it may take some time to complete,
			you can wait until the shutdown has completed by simply calling <code>awaitTermination(...)</code> as shown above.
			This method will block until the engine has indeed shutdown or until the supplied time duration has passed (whichever comes first).
			And, yes, you can call the <code>awaitTermination(...)</code> method repeatedly if needed.
		</para>
	</sect1>
  <sect1 id="jcr-sessions">
    <title>Creating JCR Sessions</title>
		<para>
			Once you have obtained a reference to the JCR &Repository;, you can create a JCR session using one of its
			<code>login(...)</code> methods.  The <ulink url="&JSR283;">JSR-283</ulink> specification provides four login methods, but the
			behavior of these methods depends on the kind of authentication system your application is using.
		</para>
	  <sect2 id="jcr-sessions-jaas">
	    <title>Using JAAS</title>
			<para>
				The <code>login()</code> method allows the implementation to choose its own security context to create a session in the default workspace
			  for the repository.  The ModeShape JCR implementation uses the security context from the current JAAS &AccessControlContext;.  This implies
			  that this method will throw a &LoginException; if it is not executed as a &PrivilegedAction; (AND the 
			  <code>JcrRepository.Options.ANONYMOUS_USER_ROLES</code> option does not allow access;
			  <link linkend="jcr-guest-access">see below</link> for an example of how to configure guest user access).  
			  Here is one example of how this might work:
		  </para>
    <programlisting>
Subject subject = ...;
&Session; session = Subject.doAsPrivileged(subject, 
    new PrivilegedExceptionAction&lt;&Session;&gt;() {
        public Session run() throws Exception {
            return repository.login();
        }
    }, AccessController.getContext());
</programlisting>	
   <para>
		Another variant of this is to use the AccessControlContext directly, which then operates against the current Subject:
	 </para>
    <programlisting>
&Session; session = AccessController.doPrivileged( 
    new PrivilegedExceptionAction&lt;&Session;&gt;() {
        public Session run() throws Exception {
            return repository.login();
        }
    });
</programlisting>	
	<para>
		Either of these approaches will yield a session with the same user name and roles as <code>subject</code>.  The <code>login(String workspaceName)</code>
		method is comparable and allows the workspace to be specified by name:
	</para>
    <programlisting>
Subject subject = ...;
final &String; workspaceName = ...;
&Session; session = (&Session;) Subject.doAsPrivileged(subject, 
    new PrivilegedExceptionAction&lt;&Session;&gt;() {
        public Session run() throws Exception {
            return repository.login(workspaceName);
        }
    }, AccessController.getContext());
</programlisting>	
		<para>The JCR API also allows supplying a JCR &Credentials; object directly as part of the login process, although ModeShape imposes
		some requirements on what types of &Credentials; may be supplied.  The simplest way is to provide a JCR &SimpleCredentials; object.
		These credentials will be validated against the JAAS realm named "modeshape-jcr", unless another realm name is provided as an option 
		during the JCR repository configuration.  For example:
		</para>
	    <programlisting>
&String; userName = ...;
char[] password = ...;
&Session; session = repository.login(new &SimpleCredentials;(userName, password));
</programlisting>	
    <para>
		Similarly, the <code>login(Credentials credentials, String workspaceName)</code> method enables passing the credentials and a workspace name:
  	</para>
	    <programlisting>
&String; userName = ...;
char[] password = ...;
&String; workspaceName = ...;
&Credentials; credentials = new &SimpleCredentials;(userName, password);
&Session; session = repository.login(credentials, workspaceName);
</programlisting>	
  <para>
		If you'd want to use a different JAAS realm that what ModeShape is configured to use, you can use a &JaasCredentials; instance
		to pass the actual JAAS &LoginContext; that should be used for authentication and authorization:
  </para>
	    <programlisting>
&LoginContext; loginContext = ...;
&Credentials; credentials = new &JaasCredentials;(loginContext);
&String; workspaceName = ...;
&Session; session = repository.login(credentials,workspaceName);
</programlisting>
		  <para>
				Note that even in this case, ModeShape will still use the same <link linkend="modeshape_jcr_security">roles</link> for authorization.
		  </para>
	  </sect2>
		<sect2 id="jcr-sessions-servlet">
  		<title>Using HTTP Servlet security</title>
			<para>
		Servlet-based applications can make use of the servlet's existing authentication mechanism from &HttpServletRequest;.  Please note that 
		the example below assumes that the servlet has a security constraint that prevents unauthenticated access.
	    <programlisting>
&HttpServletRequest; request = ...;
&Session; session = repository.login(new &ServletCredentials;(request));
</programlisting>
    The &ServletCredentials; is just a JCR &Credentials; implementation that is used by ModeShape's &ServletProvider; to delegate the
    authorization requests to &HttpServletRequest;'s "hasRole" method. The &ServletCredentials; class is in the small "modeshape-jcr-api" module,
    so feel free to use this class in your servlet-based applications.
		</para>
	</sect2>
		<sect2 id="jcr-guest-access">
  		<title>Guest (Anonymous) User Access</title>
			<para>
		By default, ModeShape allows guest users full administrative access.  This is done to make it easier to get started with ModeShape.  Of course,
		this is clearly not an appropriate security model for a production system.  
		</para>
		<para>
		To modify the roles granted to guest users, change
		the <code>JcrRepository.Options.ANONYMOUS_USER_ROLES</code> option for your repository to have a different value, like &quot;&quot; (to disable
		guest access entirely) or &quot;readonly&quot; (to give guests read-only access to all repositories).  The value of this option can
		be any pattern that matches those described in the <link linkend="role-formats">table below</link>.  
		</para>
		<note>
			<para>
				The Using ModeShape chapter of the Getting Started Guide provides examples of modifying this option through programmatic configuration or
				in an XML configuration file.
			</para>
		</note>
		<para>
			Once ModeShape is configured properly, getting anonymous JCR sessions requires no authentication. The easiest way to do this is to
			use the JCR API methods that do not have &Credentials; parameters. For example, this gets an anonymous session to the default workspace:
<programlisting>
&Session; session = repository.login();
</programlisting>
		<para>
			while the following gets an anonymous session to the workspace with the supplied name:
		</para>
<programlisting>
&String; workspaceName = ...;
&Session; session = repository.login(workspaceName);
</programlisting>
			Per the JCR API, these are equivalent to passing a null &Credentials; reference to "login" methods, so you can choose that approach as well.
			ModeShape provides the &AnonymousCredentials; implementation that can be used if your application expects a to use non-null Credentials object:
		</para>
<programlisting>
&Session; session = repository.login(new &AnonymousCredentials;());
</programlisting>
		<para>
			or
		</para>
<programlisting>
&String; workspaceName = ...;
&Session; session = repository.login(new &AnonymousCredentials;(),workspaceName);
</programlisting>
		<para>
			If you supply any other &Credentials; implementation to the "login" methods, ModeShape will not treat it as an anonymous login and
			<emphasis>will authenticate</emphasis> using JAAS or, if the credentials is a &SecurityContextCredentials; instance, its &SecurityContext; instance.
			In other words, there's no way to turn off authentication, but you can use anonymous sessions.
		</para>
	</sect2>
		<sect2 id="jcr-sessions-custom">
  		<title>Using Custom Security</title>
			<para>
		Not all applications can or want to use JAAS for their authentication system, so ModeShape provides a way to integrate your own custom
		security provider. Most of the steps are outlined in the <link linkend="jcr-custom-auth-providers">previous chapter</link>,
		but when logging in your application needs to use a compatible &Credentials; implementation, similar to the examples shown above.
	</para>
	</sect2>
	</sect1>
	<sect1 id="jcr-spec-support">
		<title>JCR Specification Support</title>
		<para>
		We believe that ModeShape JCR implementation is JCR-compliant, but we are awaiting final certification of compliance.
		Additionally, the JCR 
		specification allows some latitude to implementors for some implementation details.  The sections below
		clarify ModeShape's current and planned behavior.  <emphasis>As always, please consult the 
		<ulink url="&Roadmap;">current list of known issues and bugs</ulink>.</emphasis>
		</para> 
		<sect2>
			<title>Required features</title>
			<para>
				ModeShape &versionNumber; implements all of the JCR 2.0 required features:
		    <itemizedlist>
		      <listitem><para>repository acquisition</para></listitem>
		      <listitem><para>authentication</para></listitem>
		      <listitem><para>reading/navigating</para></listitem>
		      <listitem><para>query</para></listitem>
		      <listitem><para>export</para></listitem>
		      <listitem><para>node type discovery</para></listitem>
		      <listitem><para>permissions and capability checking</para></listitem>
		    </itemizedlist>
	    </para>
	    <para>
		    ModeShape supports several query languages, including the <link linkend="jcr-sql2-query-language">JCR-SQL2</link> and 
		    <link linkend="jcr-qom-query-language">JCR-QOM</link> query languages defined in <ulink url="&JSR283;">JSR-283</ulink>, 
		    and the <link linkend="jcr-xpath-query-language">XPath</link> and <link linkend="jcr-sql-query-language">JCR-SQL</link> 
		    languages defined in <ulink url="&JSR170;">JSR-170</ulink> but deprecated in <ulink url="&JSR283;">JSR-283</ulink>.
		    ModeShape also supports a <link linkend="jcr-fulltext-search-query-language">fulltext search</link> language that
		    is defined by the <link linkend="jcr-sql2-full-text-search-constraints">full-text search expression grammar</link>
				used in the second parameter of the <code>CONTAINS(...)</code> function of the 
				<link linkend="jcr-sql2-query-language">JCR-SQL2</link> language.
				We just pulled it out and made it available as a first-class query language.
		  </para>
	  </sect2>
		<sect2>
			<title>Optional features</title>
			<para>
				ModeShape &versionNumber; implements most of the JCR 2.0 optional features:
		    <itemizedlist>
		      <listitem><para>writing</para></listitem>
		      <listitem><para>import</para></listitem>
		      <listitem><para>observation</para></listitem>
		      <listitem><para>workspace management</para></listitem>
		      <listitem><para>versioning</para></listitem>
		      <listitem><para>locking</para></listitem>
		      <listitem><para>node type management</para></listitem>
		      <listitem><para>same-name siblings</para></listitem>
		      <listitem><para>orderable child nodes</para></listitem>
		      <listitem><para>shareable nodes</para></listitem>
		    </itemizedlist>
		    The remaining optional features (access control management, lifecycle management, 
				retention and hold, and transactions) may be introduced in future versions.
	    </para>
	  </sect2>
		<sect2>
			<title>TCK Compatibility features</title>
			<para>
			  The ModeShape project has not yet been certified to be fully-compliant with the JCR 2.0 specification, but does plan
			  on attaining this certification in the very near future.
			</para>
			<para>
				However, the ModeShape project also runs the JCR TCK unit tests from the reference implementation every night.  These tests 
				technically do not represent the official TCK, but are used within the TCK. Most of these unit tests are run in the <code>modeshape-jcr</code>
				module against the <link linkend="in-memory-connector">in-memory repository</link> to ensure our JCR implementation behaves
				correctly, and the same tests are run in the <code>modeshape-integration-tests</code> module against a variety of connectors
				to ensure they're implemented correctly. The <code>modeshape-jcr-tck</code> module runs <emphasis>all</emphasis> of these
				TCK unit tests, and currently there are only a handful of failures due to known issues (see the
				<link linkend="jcr-spec-support">JCR specification support</link> section for details).
			</para>
			<para>
			  ModeShape &versionNumber; currently passes 1372 of the 1391 JCR TCK tests, where 17 of these 19 failures appear
			  to be bugs in the TCK tests (see 
			  <ulink url="https://issues.apache.org/jira/browse/JCR-2648">JCR-2648</ulink>, 
			  <ulink url="https://issues.apache.org/jira/browse/JCR-2661">JCR-2661</ulink>, 
			  <ulink url="https://issues.apache.org/jira/browse/JCR-2662">JCR-2662</ulink>, and
			  <ulink url="https://issues.apache.org/jira/browse/JCR-2663">JCR-2663</ulink>). The remaining 2 failures are
			  due to a known issue (see 
			  <ulink url="&MODE;-760">MODE-760</ulink>).
		  </para>
		</sect2>
		<sect2 id="modeshape_jcr_security">
			<title>JCR Security</title>
			<para>
				Although the <ulink url="&JSR283;">JSR-283</ulink> specification requires implementation of the <code>Session.checkPermission(String, String)</code> method,
				it allows implementors to choose the granularity of their access controls.  ModeShape supports coarse-grained, role-based access control at the repository 
				and workspace level.
			</para>
			<para>
				ModeShape has extended the set of JCR-defined actions ("add_node", "set_property", "remove", and "read") with additional actions ("register_type",  
				"register_namespace", "unlock_any", "create_workspace" and "delete_workspace").  The "register_type" and "register_namespace" permissions control 
				the ability to register (and unregister) node types and namespaces, respectively.
				The "unlock_any"" permission grants the user the ability to unlock any locked node or branch (as opposed to users without that permission 
				who can only unlock nodes or branches that they have locked themselves or for which they hold the lock token).
				Finally, the "create_workspace" and "delete_workspace" permissions grant the user the ability to create workspaces and delete workspaces, respectively,
				using the corresponding methods on &Workspace;.
				Permissions to perform these actions are aggregated in roles that can be assigned to users. 
			</para>
			<para>
				ModeShape currently defines three roles: <code>readonly</code>, <code>readwrite</code>, and <code>admin</code>.  If the &Credentials; passed into 
				<code>Repository.login(...)</code> (or the &Subject; from the &AccessControlContext;, if one of the no-credential <code>login</code> methods were used) have any of these roles, 
				the session will have the corresponding access to all workspaces within the repository.  The mapping from the roles to the actions that they allow is provided below,
				for any values of <code>path</code>.  
				  
				<table frame='all'>
		<title>Role / Action Mapping</title>
		<tgroup cols='4' align='left' colsep='1' rowsep='1'>
      <colspec colname='c1' colwidth="1*"/>
      <colspec colname='c2' colwidth="1*"/>
      <colspec colname='c3' colwidth="1*"/>
      <colspec colname='c4' colwidth="1*"/>
			<thead>
				<row>
		  		<entry>Action Name</entry>
		  		<entry>readonly</entry>
		  		<entry>readwrite</entry>
		  		<entry>admin</entry>
				</row>
			</thead>
			<tbody>
				<row>
					<entry>read</entry>
					<entry>Allows</entry>
					<entry>Allows</entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>add_node</entry>
					<entry></entry>
					<entry>Allows</entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>set_property</entry>
					<entry></entry>
					<entry>Allows</entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>remove</entry>
					<entry></entry>
					<entry>Allows</entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>register_namespace</entry>
					<entry></entry>
					<entry></entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>register_type</entry>
					<entry></entry>
					<entry></entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>unlock_any</entry>
					<entry></entry>
					<entry></entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>create_workspace</entry>
					<entry></entry>
					<entry></entry>
					<entry>Allows</entry>
				</row>
				<row>
					<entry>delete_workspace</entry>
					<entry></entry>
					<entry></entry>
					<entry>Allows</entry>
				</row>
			</tbody>
		</tgroup>
	</table>
        </para>
				  
				<note>
					<para> In this release, ModeShape does <emphasis>not</emphasis> check that the <code>actions</code> parameter passed into 
						<code>Session.checkPermission(...)</code> contains only valid actions. This check may be added in a future release.
					</para>
				</note> 
			  <para>
				  It is also possible to grant access only to one or more repositories on a single ModeShape server or to one or more named workspaces within a repository.  The format for 
				  role names is defined below:
			  </para>
				<table frame='all' id="role-formats">
		<title>Role Formats</title>
		<tgroup cols='3' align='left' colsep='1' rowsep='1'>
			<thead>
				<row>
		  		<entry>Role Pattern</entry>
		  		<entry>Examples</entry>
		  		<entry>Description</entry>
				</row>
			</thead>
			<tbody>
				<row>
					<entry>ROLE_NAME</entry>
					<entry><code>readonly</code>, <code>admin</code></entry>
					<entry>Grants the named role to the assigned user on every workspace in any repository on the ModeShape server.</entry>
				</row>
				<row>
					<entry>ROLE_NAME.REPOSITORY_NAME</entry>
					<entry><code>readonly.modeshape_repo</code>, <code>admin.localRepository</code></entry>
					<entry>Grants the named role to the assigned user on every workspace in the named repository on the ModeShape server.</entry>
				</row>
				<row>
					<entry>ROLE_NAME.REPOSITORY_NAME.WORKSPACE_NAME</entry>
					<entry><code>readonly.modeshape_repo.jsmith</code>, <code>admin.localRepository.default</code></entry>
					<entry>Grants the named role to the assigned user on the named workspace in the named repository on the ModeShape server.</entry>
				</row>
			</tbody>
		</tgroup>
	</table>			
			<para>
				It is also possible to grant more than one role to the same user.  For example, the user "jsmith" could be granted the roles 
				"<code>readonly.production</code>", "<code>readwrite.production.jsmith</code>",
				and "<code>readwrite.staging</code>" to allow read-only access to any workspace on a production repository, 
				read/write access to a personal workspace on the same production repository,
				and read/write access to any workspace in a staging repository.    
			</para>
			<para>
				As a final note, the ModeShape JCR implementation may have additional security roles added in the future.  A <code>CONNECT</code> role
				is already being used by the ModeShape REST Server to control whether users have access to the repository through that means.   
			</para>
		</sect2>
		<sect2>
			<title>Built-In Node Types</title>
			<para>ModeShape supports all of the built-in node types described in the <ulink url="&JSR283;">JSR-283</ulink> specification.
			ModeShape also defines some custom node types in the <code>mode</code> namespace, but none of these
			node types (other than <code>mode:resource</code>) are intended to be used by developers integrating with ModeShape and may be changed or removed
			at any time.
			</para>
		</sect2>
		<sect2>
			<title>Custom Node Type Registration</title>
			<para>
				Although the <ulink url="&JSR283;">JSR-283</ulink> specification does not require support for registration and unregistration of custom types, ModeShape supports this extremely
				useful feature.  Custom node types can be added at startup, as noted above, at runtime using the standard JCR API for managing node types,
				or at runtime by reading CND files or Jackrabbit XML files.
				These node type registration mechanisms are supported equally within ModeShape, although defining node types in standard CND files
				is recommended for portability.
				<note>
					<para>ModeShape also supports defining custom node types to load at startup.  This is discussed in more detail
					in the <link linkend="programmatically_configuring_repositories">previous chapter</link>.
					</para>
				</note>
			</para>
			<sect3>
				<title>Managing Node Types Using the JCR API</title>
			<para>
				The JCR 2.0 API provides a mechanism for registering and unregistering node types. Registration is done by creating &NodeTypeTemplate; objects,
				&NodeDefinitionTemplate; objects (for child node definitions), and &PropertyDefinitionTemplate; objects (for property definitions).
				Use the setter methods to set the various attributes, and then register the node type definition with the &NodeTypeManager;:
	    <programlisting>
&Session; session = ... ;
&Workspace; workspace = session.getWorkspace();

// Obtain the ModeShape-specific node type manager ...
&NodeTypeManager; nodeTypeManager = workspace.getNodeTypeManager();

// Declare a mixin node type named "searchable" (with no namespace)
&NodeTypeTemplate; nodeType = nodeTypeManager.createNodeTypeTemplate();
nodeType.setName("searchable");
nodeType.setMixin(true);

// Add a mandatory child named "source" with a required primary type of "nt:file" 
&NodeDefinitionTemplate; childNode = nodeTypeManager.createNodeDefinitionTemplate();
childNode.setName("source");
childNode.setMandatory(true);
childNode.setRequiredPrimaryTypesNames(new String[] { "nt:file" });
childNode.setDefaultPrimaryTypeName("nt:file");
nodeType.getNodeDefinitionTemplates().add(childNode);

// Add a multi-valued STRING property named "keywords"
&PropertyDefinitionTemplate; property = nodeTypeManager.createPropertyDefinitionTemplate();
property.setName("keywords");
property.setMultiple(true);
property.setRequiredType(PropertyType.STRING);
nodeType.getPropertyDefinitionTemplates().add(property);

// Register the custom node type
nodeTypeManager.registerNodeType(nodeType,false);
</programlisting>	
			Residual properties and child node definitions can also be defined simply by not calling <code>setName</code> on 
			the template.
			</para>
			<para> 
				ModeShape also supports a simple means of unregistering types, although it is not possible to unregister types that are
				currently being used by nodes or as required primary types or supertypes of other types.  Unused node types can be unregistered 
				with the following code, using the standard JCR 2.0 API:
<programlisting>
String[] unusedNodeTypeNames = ...;

&Session; session = ... ;
&NodeTypeManager; nodeTypeManager = session.getWorkspace().getNodeTypeManager();
nodeTypeManager.unregisterNodeTypes(unusedNodeTypeNames);
</programlisting>

			</para>
			<para>
				This approach is often used to register custom node types within an application, when the application knows the node type
				definitions or retrieves these definitions from some persisted format (e.g., file, database, etc.). However, ModeShape
				provides some utilities if you want to programmatically register node types defined in certain file formats. We'll see
				in the next section how to use these.
			</para>
		</sect3>
		<sect3>
				<title>Reading JCR CND files</title>
			<para>
			Custom node types can be defined more succinctly through the CND file format defined by the JCR 2.0 specification.  In fact, this is how JBoss
			ModeShape defines its built-in node types. An example CND file that declares the same node type as above would be:
<programlisting>
[searchable] mixin
- keywords (string) multiple
+ source (nt:file) = nt:file mandatory
</programlisting>	
			This definition could then be registered as part of the repository configuration
			(see the <link linkend="programmatically_configuring_repositories">previous chapter</link>).  Or, you can also
			use a Session to programmatically register the node types in a CND file, but this requires ModeShape-specific class to read this file:
<programlisting>&Session; session = ...
&CndNodeTypeReader; reader = new &CndNodeTypeReader;(session);
reader.read(cndFile); // from file, file system path, classpath resource, URL, etc.

if (!reader.getProblems().isEmpty()) {
  for (&Problem; problem : nodeTypeSource.getProblems()) {
    // report or record problem
  }
} else {
  boolean allowUpdate = ...
  &NodeTypeManager; nodeTypeManager = session.getWorkspace().getNodeTypeManager();
  nodeTypeManager.registerNodeTypes(reader.getNodeTypeDefinitions(), allowUpdate);
}</programlisting>

      The &CndNodeTypeReader; class provides a number of <code>read(...)</code> methods that accept &File;s, paths to files on the file system,
      the names of resources on the classpath, &URLs;, and &InputStream;s. And &CndNodeTypeReader; will also register any namespace mappings
      defined in the CND file but not yet registered in the session or workspace. For details, see the JavaDoc for &CndNodeTypeReader;.
			If you have multiple CND files, you can either call <code>read(...)</code> multiple times before
      registering (as long as the CND files don't contain duplicate node type definitions), or you can simply create and use a new reader
      for each CND file. The choice is yours.
	  </para>
	</sect3>
	<sect3>
			<title>Reading Jackrabbit XML Node Type Files</title>
  	<para>
			ModeShape also provides a class that reads the node types defined in a Jackrabbit XML format. This is useful if you've been using Jackrabbit,
			have defined your custom node types in the Jackrabbit-specific format, but want to switch to ModeShape and don't want to have to manually
			convert your node types in the standard CND format. This class is used almost identically to the &CndNodeTypeReader; class described above:
<programlisting>&Session; session = ...
&JackrabbitXmlNodeTypeReader; reader = new &JackrabbitXmlNodeTypeReader;(session);
reader.read(cndFile); // from file, file system path, classpath resource, URL, etc.

if (!reader.getProblems().isEmpty()) {
  for (&Problem; problem : nodeTypeSource.getProblems()) {
    // report or record problem
  }
} else {
  boolean allowUpdate = ...
  &NodeTypeManager; nodeTypeManager = session.getWorkspace().getNodeTypeManager();
  nodeTypeManager.registerNodeTypes(reader.getNodeTypeDefinitions(), allowUpdate);
}</programlisting>
			</para>
		</sect3>
	</sect2>
	</sect1>
	<sect1>
		<title>Summary</title>
		<para>
			In this chapter, we covered how to use JCR with ModeShape and learned about how it implements the JCR specification.  
			Now that you know how ModeShape repositories work and how to use JCR to work with ModeShape repositories, we'll move on in 
			the <link linkend="jcr-query-and-search">next chapter</link> to show how you can use ModeShape to query and search your JCR data.
		</para>
	</sect1>
</chapter>
