View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors. 
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   *
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.graph.connector;
25  
26  import java.io.Serializable;
27  import java.math.BigDecimal;
28  import java.net.URI;
29  import java.util.UUID;
30  import javax.naming.Referenceable;
31  import net.jcip.annotations.ThreadSafe;
32  import org.modeshape.graph.ExecutionContext;
33  import org.modeshape.graph.property.Binary;
34  import org.modeshape.graph.property.DateTime;
35  import org.modeshape.graph.property.Name;
36  import org.modeshape.graph.property.Path;
37  import org.modeshape.graph.property.PropertyType;
38  import org.modeshape.graph.property.Reference;
39  import org.modeshape.graph.request.CacheableRequest;
40  
41  /**
42   * A repository source is a description of a resource that can be used to access or store repository information. This class
43   * serves as a factory for {@link RepositoryConnection} instances and provides some basic configuration information.
44   * <p>
45   * Typically this interface is implemented by classes that provide standard-style getters and setters for the various properties
46   * necessary for proper configuration via reflection or introspection. This interface expects nor defines any such properties,
47   * leaving that entirely to the implementation classes. Although any types can be used for these setters, other ModeShape
48   * components use reflection to set these properties and work best when the setters accept a single parameter that is a primitive,
49   * an array of primitives, a value compatible with {@link PropertyType} (e.g., {@link Path}, {@link Name}, {@link URI},
50   * {@link UUID}, {@link Reference}, {@link Binary}, {@link Long}, {@link Double}, {@link BigDecimal}, {@link DateTime}, etc.), or
51   * an array of values that are compatible with {@link PropertyType}.
52   * </p>
53   * <p>
54   * Implementations should also provide a no-arg constructor so that it is possible to easily create instances and initialize using
55   * the standard getters and setters. One example where this is required is when a RepositorySource instance is recorded in a
56   * repository (e.g., in a configuration area), and needs to be reinstantiated.
57   * </p>
58   * <p>
59   * Objects that implement this <code>RepositorySource</code> interface are typically registered with a naming service such as Java
60   * Naming and Directory Interface<sup><font size=-3>TM</font></sup> (JNDI). This interface extends both {@link Referenceable} and
61   * {@link Serializable} so that such objects can be stored in any JNDI naming context and enable proper system recovery,
62   * </p>
63   * <h3>Pooling connections</h3>
64   * <p>
65   * If the connections created by a RepositorySource are expensive to create, then connection pooling is recommended. ModeShape
66   * provides this capability with a powerful and flexible {@link RepositoryConnectionPool} class. This is the pooling mechanism
67   * used by ModeShape, but you are free to use your own pools.
68   * </p>
69   * <h3>Cache Policy</h3>
70   * <p>
71   * Each connector is responsible for determining whether and how long ModeShape is to cache the content made available by the
72   * connector. This is referred to as the caching policy, and consists of a time to live value representing the number of
73   * milliseconds that a piece of data may be cached. After the TTL has passed, the information is no longer used.
74   * </p>
75   * <p>
76   * ModeShape allows a connector to use a flexible and powerful caching policy. First, each connection returns the default caching
77   * policy for all information returned by that connection. Often this policy can be configured via properties on the
78   * {@link RepositorySource} implementation. This is optional, meaning the connector can return null if it does not wish to have a
79   * default caching policy.
80   * </p>
81   * <p>
82   * Second, the connector is able to override its default caching policy on {@link CacheableRequest individual requests}. Again,
83   * this is optional, meaning that a null caching policy on a request implies that the request has no overridden caching policy.
84   * </p>
85   * <p>
86   * Third, if the connector has no default caching policy and none is set on the individual requests, ModeShape uses whatever
87   * caching policy is set up for that component using the connector. For example, the federating connector allows a default caching
88   * policy to be specified, and this policy is used should the sources being federated not define their own caching policy.
89   * </p>
90   * <p>
91   * In summary, a connector has total control over whether and for how long the information it provides is cached.
92   * </p>
93   * <h3>Leveraging JNDI</h3>
94   * <p>
95   * Sometimes it is necessary (or easier) for a RepositorySource implementation to look up an object in JNDI. One example of this
96   * is the JBoss Cache connector: while the connector can instantiate a new JBoss Cache instance, more interesting use cases
97   * involve JBoss Cache instances that are set up for clustering and replication, something that is generally difficult to
98   * configure in a single JavaBean. Therefore the JBossCacheSource has optional JavaBean properties that define how it is to look
99   * up a JBoss Cache instance in JNDI.
100  * </p>
101  * <p>
102  * This is a simple pattern that you may find useful in your connector. Basically, if your source implementation can look up an
103  * object in JNDI, simply use a single JavaBean String property that defines the full name that should be used to locate that
104  * object in JNDI. Usually it's best to include "Jndi" in the JavaBean property name so that administrative users understand the
105  * purpose of the property. (And some may suggest that any optional property also use the word "optional" in the property name.)
106  * </p>
107  * <h3>Capabilities</h3>
108  * <p>
109  * Each RepositorySource implementation provides some hint as to its capabilities by returning a
110  * {@link RepositorySourceCapabilities} object. This class currently provides methods that say whether the connector supports
111  * updates, whether it supports same-name-siblings (SNS), and whether the connector supports listeners and events. These may be
112  * hard-coded values, or the capabilities object {@link #getCapabilities() returned by the connector} may determine them at
113  * runtime based upon the system its connecting to. For example, a connector may interrogate the underlying system to decide
114  * whether it can support updates. The only criteria is that the capabilities must remain constant throughout the lifetime of the
115  * RepositorySource instance (assuming it doesn't change).
116  * </p>
117  * <p>
118  * The {@link RepositorySourceCapabilities} can be used as is (the class is immutable), or it can be subclassed to provide more
119  * complex behavior. Why is this a concrete class and not an interface? By using a concrete class, connectors inherit the default
120  * behavior. If additional capabilities need to be added to the class in future releases, connectors may not have to override the
121  * defaults. This provides some insulation against future enhancements to the connector framework.
122  * </p>
123  * <h3>Security and authentication</h3>
124  * <p>
125  * The main method connectors have to process requests takes an {@link ExecutionContext}, which contains the JAAS security
126  * information of the subject performing the request. This means that the connector can use this to determine authentication and
127  * authorization information for each request.
128  * </p>
129  * <p>
130  * Sometimes that is not sufficient. For example, it may be that the connector needs its own authorization information so that it
131  * can establish a connection (even if user-level privileges still use the {@link ExecutionContext} provided with each request).
132  * In this case, the RepositorySource implementation will probably need JavaBean properties that represent the connector's
133  * authentication information. This may take the form of a username and password, or it may be properties that are used to
134  * delegate authentication to JAAS. Either way, just realize that it's perfectly acceptable for the connector to require its own
135  * security properties.
136  * </p>
137  */
138 @ThreadSafe
139 public interface RepositorySource extends Referenceable, Serializable {
140 
141     /**
142      * Initialize this source to use the supplied {@link RepositoryContext}, from which this source can obtain the
143      * {@link RepositoryContext#getConfiguration(int) configuration} defining this source,
144      * {@link RepositoryContext#getRepositoryConnectionFactory() connections} to other {@link RepositorySource sources}, and the
145      * {@link RepositoryContext#getExecutionContext() execution context}.
146      * <p>
147      * This method may be called each time the configuration changes, allowing the source to update itself.
148      * </p>
149      * 
150      * @param context
151      * @throws RepositorySourceException
152      */
153     void initialize( RepositoryContext context ) throws RepositorySourceException;
154 
155     /**
156      * Get the name for this repository source.
157      * 
158      * @return the name; never null or empty
159      */
160     String getName();
161 
162     /**
163      * Get a connection from this source. Even though each RepositorySource need not be thread safe, this method should be safe to
164      * be called concurrently by multiple threads.
165      * 
166      * @return a connection
167      * @throws RepositorySourceException if there is a problem obtaining a connection
168      * @throws IllegalStateException if the factory is not in a state to create or return connections
169      */
170     RepositoryConnection getConnection() throws RepositorySourceException;
171 
172     /**
173      * Get the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
174      * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
175      * user is not required to retry any operations.
176      * 
177      * @return the maximum number of allowable retries, or 0 if the source has no limit
178      */
179     int getRetryLimit();
180 
181     /**
182      * Set the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
183      * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
184      * user is not required to retry any operations.
185      * 
186      * @param limit the maximum number of allowable retries, or 0 if the source has no limit
187      */
188     void setRetryLimit( int limit );
189 
190     /**
191      * Get the capabilities for this source.
192      * 
193      * @return the capabilities for this source; never null
194      */
195     RepositorySourceCapabilities getCapabilities();
196 
197     /**
198      * Signal this source that it is no longer needed and should begin the process of reclaiming or closing all resources that it
199      * has acquired. Because {@link #getConnection() connections} may still be in use, this method may not necessarily close all
200      * resources immediately.
201      * <p>
202      * This is a required method, and must be called when this source is no longer needed if one or more {@link #getConnection()
203      * connections} have been obtained since the previous call to this method.
204      * </p>
205      * <p>
206      * Note that calling this method also does not preclude {@link #getConnection() obtaining more connections} after this method
207      * is called. If that happens, this source should simply reacquire any resources necessary to provide additional connections,
208      * and this method needs to be called once again.
209      * </p>
210      */
211     void close();
212 
213 }