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 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 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; 025 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; 039 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 { 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. 164 * 165 * @return a connection 166 * @throws RepositorySourceException if there is a problem obtaining a connection 167 * @throws IllegalStateException if the factory is not in a state to create or return connections 168 */ 169 RepositoryConnection getConnection() throws RepositorySourceException; 170 171 /** 172 * Get the maximum number of retries that may be performed on a given operation when using {@link #getConnection() 173 * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection 174 * user is not required to retry any operations. 175 * 176 * @return the maximum number of allowable retries, or 0 if the source has no limit 177 */ 178 int getRetryLimit(); 179 180 /** 181 * Set the maximum number of retries that may be performed on a given operation when using {@link #getConnection() 182 * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection 183 * user is not required to retry any operations. 184 * 185 * @param limit the maximum number of allowable retries, or 0 if the source has no limit 186 */ 187 void setRetryLimit( int limit ); 188 189 /** 190 * Get the capabilities for this source. 191 * 192 * @return the capabilities for this source; never null 193 */ 194 RepositorySourceCapabilities getCapabilities(); 195 196 }