001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.connector;
026    import java.io.Serializable;
027    import java.math.BigDecimal;
028    import java.net.URI;
029    import java.util.UUID;
030    import javax.naming.Referenceable;
031    import org.jboss.dna.graph.ExecutionContext;
032    import org.jboss.dna.graph.property.Binary;
033    import org.jboss.dna.graph.property.DateTime;
034    import org.jboss.dna.graph.property.Name;
035    import org.jboss.dna.graph.property.Path;
036    import org.jboss.dna.graph.property.PropertyType;
037    import org.jboss.dna.graph.property.Reference;
038    import org.jboss.dna.graph.request.CacheableRequest;
040    /**
041     * A repository source is a description of a resource that can be used to access or store repository information. This class
042     * serves as a factory for {@link RepositoryConnection} instances and provides some basic configuration information.
043     * <p>
044     * Typically this interface is implemented by classes that provide standard-style getters and setters for the various properties
045     * necessary for proper configuration via reflection or introspection. This interface expects nor defines any such properties,
046     * leaving that entirely to the implementation classes. Although any types can be used for these setters, other DNA components use
047     * reflection to set these properties and work best when the setters accept a single parameter that is a primitive, an array of
048     * primitives, a value compatible with {@link PropertyType} (e.g., {@link Path}, {@link Name}, {@link URI}, {@link UUID},
049     * {@link Reference}, {@link Binary}, {@link Long}, {@link Double}, {@link BigDecimal}, {@link DateTime}, etc.), or an array of
050     * values that are compatible with {@link PropertyType}.
051     * </p>
052     * <p>
053     * Implementations should also provide a no-arg constructor so that it is possible to easily create instances and initialize using
054     * the standard getters and setters. One example where this is required is when a RepositorySource instance is recorded in a
055     * repository (e.g., in a configuration area), and needs to be reinstantiated.
056     * </p>
057     * <p>
058     * Objects that implement this <code>RepositorySource</code> interface are typically registered with a naming service such as Java
059     * Naming and Directory Interface<sup><font size=-3>TM</font></sup> (JNDI). This interface extends both {@link Referenceable} and
060     * {@link Serializable} so that such objects can be stored in any JNDI naming context and enable proper system recovery,
061     * </p>
062     * <h3>Pooling connections</h3>
063     * <p>
064     * If the connections created by a RepositorySource are expensive to create, then connection pooling is recommended. DNA provides
065     * this capability with a powerful and flexible {@link RepositoryConnectionPool} class. This is the pooling mechanism used by
066     * JBoss DNA, but you are free to use your own pools.
067     * </p>
068     * <h3>Cache Policy</h3>
069     * <p>
070     * Each connector is responsible for determining whether and how long DNA is to cache the content made available by the connector.
071     * This is referred to as the caching policy, and consists of a time to live value representing the number of milliseconds that a
072     * piece of data may be cached. After the TTL has passed, the information is no longer used.
073     * </p>
074     * <p>
075     * DNA allows a connector to use a flexible and powerful caching policy. First, each connection returns the default caching policy
076     * for all information returned by that connection. Often this policy can be configured via properties on the
077     * {@link RepositorySource} implementation. This is optional, meaning the connector can return null if it does not wish to have a
078     * default caching policy.
079     * </p>
080     * <p>
081     * Second, the connector is able to override its default caching policy on {@link CacheableRequest individual requests}. Again,
082     * this is optional, meaning that a null caching policy on a request implies that the request has no overridden caching policy.
083     * </p>
084     * <p>
085     * Third, if the connector has no default caching policy and none is set on the individual requests, DNA uses whatever caching
086     * policy is set up for that component using the connector. For example, the federating connector allows a default caching policy
087     * to be specified, and this policy is used should the sources being federated not define their own caching policy.
088     * </p>
089     * <p>
090     * In summary, a connector has total control over whether and for how long the information it provides is cached.
091     * </p>
092     * <h3>Leveraging JNDI</h3>
093     * <p>
094     * Sometimes it is necessary (or easier) for a RepositorySource implementation to look up an object in JNDI. One example of this
095     * is the JBoss Cache connector: while the connector can instantiate a new JBoss Cache instance, more interesting use cases
096     * involve JBoss Cache instances that are set up for clustering and replication, something that is generally difficult to
097     * configure in a single JavaBean. Therefore the JBossCacheSource has optional JavaBean properties that define how it is to look
098     * up a JBoss Cache instance in JNDI.
099     * </p>
100     * <p>
101     * This is a simple pattern that you may find useful in your connector. Basically, if your source implementation can look up an
102     * object in JNDI, simply use a single JavaBean String property that defines the full name that should be used to locate that
103     * object in JNDI. Usually it's best to include "Jndi" in the JavaBean property name so that administrative users understand the
104     * purpose of the property. (And some may suggest that any optional property also use the word "optional" in the property name.)
105     * </p>
106     * <h3>Capabilities</h3>
107     * <p>
108     * Each RepositorySource implementation provides some hint as to its capabilities by returning a
109     * {@link RepositorySourceCapabilities} object. This class currently provides methods that say whether the connector supports
110     * updates, whether it supports same-name-siblings (SNS), and whether the connector supports listeners and events. These may be
111     * hard-coded values, or the capabilities object {@link #getCapabilities() returned by the connector} may determine them at
112     * runtime based upon the system its connecting to. For example, a connector may interrogate the underlying system to decide
113     * whether it can support updates. The only criteria is that the capabilities must remain constant throughout the lifetime of the
114     * RepositorySource instance (assuming it doesn't change).
115     * </p>
116     * <p>
117     * The {@link RepositorySourceCapabilities} can be used as is (the class is immutable), or it can be subclassed to provide more
118     * complex behavior. Why is this a concrete class and not an interface? By using a concrete class, connectors inherit the default
119     * behavior. If additional capabilities need to be added to the class in future releases, connectors may not have to override the
120     * defaults. This provides some insulation against future enhancements to the connector framework.
121     * </p>
122     * <h3>Security and authentication</h3>
123     * <p>
124     * The main method connectors have to process requests takes an {@link ExecutionContext}, which contains the JAAS security
125     * information of the subject performing the request. This means that the connector can use this to determine authentication and
126     * authorization information for each request.
127     * </p>
128     * <p>
129     * Sometimes that is not sufficient. For example, it may be that the connector needs its own authorization information so that it
130     * can establish a connection (even if user-level privileges still use the {@link ExecutionContext} provided with each request).
131     * In this case, the RepositorySource implementation will probably need JavaBean properties that represent the connector's
132     * authentication information. This may take the form of a username and password, or it may be properties that are used to
133     * delegate authentication to JAAS. Either way, just realize that it's perfectly acceptable for the connector to require its own
134     * security properties.
135     * </p>
136     * 
137     * @author Randall Hauch
138     */
139    public interface RepositorySource extends Referenceable, Serializable {
141        /**
142         * Initialize this source to use the supplied {@link RepositoryContext}, from which this source can obtain
143         * {@link RepositoryContext#getRepositoryConnectionFactory() connections} to other {@link RepositorySource sources} as well as
144         * {@link RepositoryContext#getExecutionContext() execution contexts}.
145         * 
146         * @param context
147         * @throws RepositorySourceException
148         */
149        void initialize( RepositoryContext context ) throws RepositorySourceException;
151        /**
152         * Get the name for this repository source.
153         * 
154         * @return the name; never null or empty
155         */
156        String getName();
158        /**
159         * Get a connection from this source.
160         * 
161         * @return a connection
162         * @throws RepositorySourceException if there is a problem obtaining a connection
163         * @throws IllegalStateException if the factory is not in a state to create or return connections
164         */
165        RepositoryConnection getConnection() throws RepositorySourceException;
167        /**
168         * Get the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
169         * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
170         * user is not required to retry any operations.
171         * 
172         * @return the maximum number of allowable retries, or 0 if the source has no limit
173         */
174        int getRetryLimit();
176        /**
177         * Set the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
178         * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
179         * user is not required to retry any operations.
180         * 
181         * @param limit the maximum number of allowable retries, or 0 if the source has no limit
182         */
183        void setRetryLimit( int limit );
185        /**
186         * Get the capabilities for this source.
187         * 
188         * @return the capabilities for this source; never null
189         */
190        RepositorySourceCapabilities getCapabilities();
192    }