protected synchronized FederatedRepositoryConfig getRepositoryConfiguration( ExecutionContext context,
RepositoryConnectionFactory connectionFactory ) {
Problems problems = new SimpleProblems();
ValueFactories valueFactories = context.getValueFactories();
PathFactory pathFactory = valueFactories.getPathFactory();
NameFactory nameFactory = valueFactories.getNameFactory();
ValueFactory<Long> longFactory = valueFactories.getLongFactory();
// Create the configuration projection ...
ProjectionParser projectionParser = ProjectionParser.getInstance();
String ruleStr = "/dna:system => " + this.getConfigurationSourcePath();
Projection.Rule[] rules = projectionParser.rulesFromStrings(context, ruleStr);
Projection configurationProjection = new Projection(this.getConfigurationSourceName(), rules);
// Create a federating command executor to execute the commands and merge the results into a single set of
// commands.
final String configurationSourceName = configurationProjection.getSourceName();
List<Projection> projections = Collections.singletonList(configurationProjection);
CommandExecutor executor = null;
if (configurationProjection.getRules().size() == 0) {
// There is no projection for the configuration repository, so just use a no-op executor
executor = new NoOpCommandExecutor(context, configurationSourceName);
} else if (configurationProjection.isSimple()) {
// There is just a single projection for the configuration repository, so just use an executor that
// translates the paths using the projection
executor = new SingleProjectionCommandExecutor(context, configurationSourceName, configurationProjection,
connectionFactory);
} else {
// The configuration repository has more than one projection, so we need to merge the results
executor = new FederatingCommandExecutor(context, configurationSourceName, projections, connectionFactory);
}
// Wrap the executor with a logging executor ...
executor = new LoggingCommandExecutor(executor, context.getLogger(getClass()), Logger.Level.DEBUG);
// The configuration projection (via "executor") will convert this path into a path that exists in the configuration
// repository
Path configNode = pathFactory.create(PATH_TO_CONFIGURATION_INFORMATION);
try {
// Get the repository node ...
BasicGetNodeCommand getRepository = new BasicGetNodeCommand(configNode);
executor.execute(getRepository);
if (getRepository.hasError()) {
throw new FederationException(FederationI18n.federatedRepositoryCannotBeFound.text(repositoryName));
}
// Get the first child node of the "dna:cache" node, since this represents the source used as the cache ...
Path cacheNode = pathFactory.create(configNode, nameFactory.create(DNA_CACHE_SEGMENT));
BasicGetChildrenCommand getCacheSource = new BasicGetChildrenCommand(cacheNode);
executor.execute(getCacheSource);
if (getCacheSource.hasError() || getCacheSource.getChildren().size() < 1) {
I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
throw new FederationException(msg.text(DNA_CACHE_SEGMENT, configNode));
}
// Add a command to get the projection defining the cache ...
Path pathToCacheRegion = pathFactory.create(cacheNode, getCacheSource.getChildren().get(0));
BasicGetNodeCommand getCacheRegion = new BasicGetNodeCommand(pathToCacheRegion);
executor.execute(getCacheRegion);
Projection cacheProjection = createProjection(context,
projectionParser,
getCacheRegion.getPath(),
getCacheRegion.getPropertiesByName(),
problems);
if (getCacheRegion.hasError()) {
I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
throw new FederationException(msg.text(DNA_CACHE_SEGMENT, configNode));
}
// Get the source projections for the repository ...
Path projectionsNode = pathFactory.create(configNode, nameFactory.create(DNA_PROJECTIONS_SEGMENT));
BasicGetChildrenCommand getProjections = new BasicGetChildrenCommand(projectionsNode);
executor.execute(getProjections);
if (getProjections.hasError()) {
I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
throw new FederationException(msg.text(DNA_PROJECTIONS_SEGMENT, configNode));
}
// Build the commands to get each of the projections (children of the "dna:projections" node) ...
List<Projection> sourceProjections = new LinkedList<Projection>();
if (getProjections.hasNoError() && !getProjections.getChildren().isEmpty()) {
BasicCompositeCommand commands = new BasicCompositeCommand();
for (Path.Segment child : getProjections.getChildren()) {
final Path pathToSource = pathFactory.create(projectionsNode, child);
commands.add(new BasicGetNodeCommand(pathToSource));
}
// Now execute these commands ...
executor.execute(commands);
// Iterate over each region node obtained ...
for (GraphCommand command : commands) {
BasicGetNodeCommand getProjectionCommand = (BasicGetNodeCommand)command;
if (getProjectionCommand.hasNoError()) {
Projection projection = createProjection(context,
projectionParser,
getProjectionCommand.getPath(),
getProjectionCommand.getPropertiesByName(),
problems);
if (projection != null) {
Logger logger = context.getLogger(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Adding projection to federated repository {0}: {1}",
getRepositoryName(),
projection);
}
sourceProjections.add(projection);
}
}
}
}
// Look for the default cache policy ...
BasicCachePolicy cachePolicy = new BasicCachePolicy();
Property timeToLiveProperty = getRepository.getPropertiesByName().get(nameFactory.create(CACHE_POLICY_TIME_TO_LIVE_CONFIG_PROPERTY_NAME));
if (timeToLiveProperty != null && !timeToLiveProperty.isEmpty()) {
cachePolicy.setTimeToLive(longFactory.create(timeToLiveProperty.getValues().next()), TimeUnit.MILLISECONDS);
}
CachePolicy defaultCachePolicy = cachePolicy.isEmpty() ? null : cachePolicy.getUnmodifiable();
return new FederatedRepositoryConfig(repositoryName, cacheProjection, sourceProjections, defaultCachePolicy);