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 * Unless otherwise indicated, all code in JBoss DNA is licensed 010 * 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.jcr; 025 026 import java.util.Collections; 027 import java.util.HashMap; 028 import java.util.HashSet; 029 import java.util.Map; 030 import java.util.Set; 031 import java.util.concurrent.locks.Lock; 032 import java.util.concurrent.locks.ReentrantLock; 033 import javax.jcr.Repository; 034 import javax.jcr.RepositoryException; 035 import org.jboss.dna.common.util.CheckArg; 036 import org.jboss.dna.graph.ExecutionContext; 037 import org.jboss.dna.graph.Graph; 038 import org.jboss.dna.graph.Location; 039 import org.jboss.dna.graph.Node; 040 import org.jboss.dna.graph.Subgraph; 041 import org.jboss.dna.graph.connector.RepositoryConnectionFactory; 042 import org.jboss.dna.graph.connector.RepositorySource; 043 import org.jboss.dna.graph.property.Name; 044 import org.jboss.dna.graph.property.Path; 045 import org.jboss.dna.graph.property.PathFactory; 046 import org.jboss.dna.graph.property.PathNotFoundException; 047 import org.jboss.dna.graph.property.Property; 048 import org.jboss.dna.graph.property.basic.GraphNamespaceRegistry; 049 import org.jboss.dna.jcr.JcrRepository.Option; 050 import org.jboss.dna.repository.DnaConfiguration; 051 import org.jboss.dna.repository.DnaEngine; 052 053 /** 054 * The basic component that encapsulates the JBoss DNA services, including the {@link Repository} instances. 055 */ 056 public class JcrEngine extends DnaEngine { 057 058 private final Map<String, JcrRepository> repositories; 059 private final Lock repositoriesLock; 060 061 JcrEngine( ExecutionContext context, 062 DnaConfiguration.ConfigurationDefinition configuration ) { 063 super(context, configuration); 064 this.repositories = new HashMap<String, JcrRepository>(); 065 this.repositoriesLock = new ReentrantLock(); 066 } 067 068 /** 069 * Get the {@link Repository} implementation for the named repository. 070 * 071 * @param repositoryName the name of the repository, which corresponds to the name of a configured {@link RepositorySource} 072 * @return the named repository instance 073 * @throws IllegalArgumentException if the repository name is null, blank or invalid 074 * @throws RepositoryException if there is no repository with the specified name 075 * @throws IllegalStateException if this engine was not {@link #start() started} 076 */ 077 public final JcrRepository getRepository( String repositoryName ) throws RepositoryException { 078 CheckArg.isNotEmpty(repositoryName, "repositoryName"); 079 checkRunning(); 080 try { 081 repositoriesLock.lock(); 082 JcrRepository repository = repositories.get(repositoryName); 083 if (repository == null) { 084 try { 085 repository = doCreateJcrRepository(repositoryName); 086 } catch (PathNotFoundException e) { 087 // The repository name is not a valid repository ... 088 String msg = JcrI18n.repositoryDoesNotExist.text(repositoryName); 089 throw new RepositoryException(msg); 090 } 091 repositories.put(repositoryName, repository); 092 } 093 return repository; 094 } finally { 095 repositoriesLock.unlock(); 096 } 097 } 098 099 /** 100 * Get the names of each of the JCR repositories. 101 * 102 * @return the immutable names of the repositories that exist at the time this method is called 103 */ 104 public Set<String> getRepositoryNames() { 105 checkRunning(); 106 Set<String> results = new HashSet<String>(); 107 // Read the names of the JCR repositories from the configuration (not from the Repository objects used so far) ... 108 PathFactory pathFactory = getExecutionContext().getValueFactories().getPathFactory(); 109 Path repositoriesPath = pathFactory.create(configuration.getPath(), DnaLexicon.REPOSITORIES); 110 Graph configuration = getConfigurationGraph(); 111 for (Location child : configuration.getChildren().of(repositoriesPath)) { 112 Name repositoryName = child.getPath().getLastSegment().getName(); 113 results.add(readable(repositoryName)); 114 } 115 return Collections.unmodifiableSet(results); 116 } 117 118 protected JcrRepository doCreateJcrRepository( String repositoryName ) throws RepositoryException, PathNotFoundException { 119 RepositoryConnectionFactory connectionFactory = getRepositoryConnectionFactory(); 120 Map<String, String> descriptors = null; 121 Map<Option, String> options = new HashMap<Option, String>(); 122 123 // Read the subgraph that represents the repository ... 124 PathFactory pathFactory = getExecutionContext().getValueFactories().getPathFactory(); 125 Path repositoriesPath = pathFactory.create(configuration.getPath(), DnaLexicon.REPOSITORIES); 126 Path repositoryPath = pathFactory.create(repositoriesPath, repositoryName); 127 Graph configuration = getConfigurationGraph(); 128 Subgraph subgraph = configuration.getSubgraphOfDepth(6).at(repositoryPath); 129 130 // Read the options ... 131 Node optionsNode = subgraph.getNode(DnaLexicon.OPTIONS); 132 if (optionsNode != null) { 133 for (Location optionLocation : optionsNode.getChildren()) { 134 Node optionNode = configuration.getNodeAt(optionLocation); 135 Path.Segment segment = optionLocation.getPath().getLastSegment(); 136 Property valueProperty = optionNode.getProperty(DnaLexicon.VALUE); 137 if (valueProperty == null) continue; 138 Option option = Option.findOption(segment.getName().getLocalName()); 139 if (option == null) continue; 140 options.put(option, valueProperty.getFirstValue().toString()); 141 } 142 } 143 144 // Read the namespaces ... 145 ExecutionContext context = getExecutionContext(); 146 Node namespacesNode = subgraph.getNode(DnaLexicon.NAMESPACES); 147 if (namespacesNode != null) { 148 GraphNamespaceRegistry registry = new GraphNamespaceRegistry(configuration, namespacesNode.getLocation().getPath(), 149 DnaLexicon.NAMESPACE_URI); 150 context = context.with(registry); 151 } 152 153 // Get the name of the source ... 154 Property property = subgraph.getRoot().getProperty(DnaLexicon.SOURCE_NAME); 155 if (property == null || property.isEmpty()) { 156 String readableName = readable(DnaLexicon.SOURCE_NAME); 157 String readablePath = readable(subgraph.getLocation()); 158 String msg = JcrI18n.propertyNotFoundOnNode.text(readableName, readablePath, configuration.getCurrentWorkspaceName()); 159 throw new RepositoryException(msg); 160 } 161 String sourceName = context.getValueFactories().getStringFactory().create(property.getFirstValue()); 162 163 // Create the repository ... 164 JcrRepository repository = new JcrRepository(context, connectionFactory, sourceName, descriptors, options); 165 166 // Register all the the node types ... 167 Node nodeTypesNode = subgraph.getNode(DnaLexicon.NODE_TYPES); 168 if (nodeTypesNode != null) { 169 repository.getRepositoryTypeManager().registerNodeTypes(subgraph, nodeTypesNode.getLocation());// throws exception 170 } 171 172 return repository; 173 } 174 175 protected final String readable( Name name ) { 176 return name.getString(context.getNamespaceRegistry()); 177 } 178 179 protected final String readable( Path path ) { 180 return path.getString(context.getNamespaceRegistry()); 181 } 182 183 protected final String readable( Location location ) { 184 return location.getString(context.getNamespaceRegistry()); 185 } 186 }