/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.web.jcr;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.modeshape.common.annotation.ThreadSafe;
import org.modeshape.common.util.CheckArg;
import org.modeshape.jcr.api.Logger;
import org.modeshape.jcr.api.RepositoriesContainer;
import org.modeshape.jcr.api.ServletCredentials;
/**
* Manager for accessing JCR Repository instances. This manager uses the idiomatic way to find JCR Repository (and ModeShape
* Repositories) instances via the {@link ServiceLoader} and {@link org.modeshape.jcr.api.RepositoriesContainer} mechanism.
*/
@ThreadSafe
public class RepositoryManager {
private static final Logger LOGGER = WebLogger.getLogger(RepositoryManager.class);
private static final Map<String, Object> factoryParams = new HashMap<String, Object>();
private static RepositoriesContainer repositoriesContainer;
private RepositoryManager() {
}
/**
* Initializes the repository factory. For more details, please see the {@link RepositoryManager class-level documentation}.
*
* @param context the servlet context; may not be null
* @see RepositoryManager
*/
static synchronized void initialize( ServletContext context ) {
CheckArg.isNotNull(context, "context");
loadFactoryParameters(context);
loadRepositoriesContainer();
}
private static void loadRepositoriesContainer() {
Iterator<RepositoriesContainer> containersIterator = ServiceLoader.load(RepositoriesContainer.class).iterator();
if (!containersIterator.hasNext()) {
throw new IllegalStateException(
WebJcrI18n.repositoriesContainerNotFoundInClasspath.text(RepositoriesContainer.class.getName()));
}
//there shouldn't be more than 1 container
repositoriesContainer = containersIterator.next();
}
private static void loadFactoryParameters( ServletContext context ) {
factoryParams.clear();
Enumeration<?> names = context.getInitParameterNames();
if (names == null) {
addParameter(RepositoriesContainer.URL, context);
addParameter(RepositoriesContainer.REPOSITORY_NAME, context);
} else {
while (names.hasMoreElements()) {
Object next = names.nextElement();
if (next == null) continue;
String name = next.toString();
addParameter(name, context);
}
}
}
private static void addParameter( String name,
ServletContext context ) {
String value = context.getInitParameter(name);
if (value != null) factoryParams.put(name, value);
}
/**
* Get a JCR Session for the named workspace in the named repository, using the supplied HTTP servlet request for
* authentication information.
*
* @param request the servlet request; may not be null or unauthenticated
* @param repositoryName the name of the repository in which the session is created
* @param workspaceName the name of the workspace to which the session should be connected
* @return an active session with the given workspace in the named repository
* @throws RepositoryException if the named repository does not exist or there was a problem obtaining the named repository
*/
public static Session getSession( HttpServletRequest request,
String repositoryName,
String workspaceName ) throws RepositoryException {
// Go through all the RepositoryFactory instances and try to create one ...
Repository repository = getRepository(repositoryName);
// If there's no authenticated user, try an anonymous login
if (request == null || request.getUserPrincipal() == null) {
return repository.login(workspaceName);
}
return repository.login(new ServletCredentials(request), workspaceName);
}
/**
* Returns the {@link Repository} instance with the given name.
* @param repositoryName a {@code non-null} string
* @return a {@link Repository} instance, never {@code null}
* @throws NoSuchRepositoryException if no repository with the given name exists.
*/
public static Repository getRepository( String repositoryName ) throws NoSuchRepositoryException {
Repository repository = null;
try {
repository = repositoriesContainer.getRepository(repositoryName, Collections.unmodifiableMap(factoryParams));
} catch (RepositoryException e) {
throw new NoSuchRepositoryException(WebJcrI18n.cannotInitializeRepository.text(repositoryName), e);
}
if (repository == null) {
throw new NoSuchRepositoryException(WebJcrI18n.repositoryNotFound.text(repositoryName));
}
return repository;
}
/**
* Returns a set with all the names of the available repositories.
* @return a set with the names, never {@code null}
*/
public static Set<String> getJcrRepositoryNames() {
try {
return repositoriesContainer.getRepositoryNames(Collections.unmodifiableMap(factoryParams));
} catch (RepositoryException e) {
LOGGER.error(e, WebJcrI18n.cannotLoadRepositoryNames.text());
return Collections.emptySet();
}
}
static void shutdown() {
repositoriesContainer.shutdown();
}
}