/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nuxeo - initial API and implementation * * $Id$ */ package org.eclipse.ecr.core.repository; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.ecr.core.model.Repository; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> * */ public class RepositoryManager { public static final String REPOSITORY_EVENT = "repository"; private static final Log log = LogFactory.getLog(RepositoryManager.class); // repository descriptors - used to prevent registering repositories twice private final Set<RepositoryDescriptor> descriptors = new HashSet<RepositoryDescriptor>(); // registered repositories - map the repository name to the repository // reference private final Map<String, Ref> repositories = new HashMap<String, Ref>(); private final RepositoryService repositoryService; // TODO: is this really needed? // currently is used to remove dependency between jca adapter and // nxframework public RepositoryManager(RepositoryService repositoryService) { this.repositoryService = repositoryService; } /** * Gets a repository given its name. * <p> * Null is returned if no repository with that name was registered. * * @param name the repository name * @return the repository instance or null if no repository with that name * was registered * @throws Exception if any error occurs when trying to initialize the * repository */ public Repository getRepository(String name) throws Exception { if (log.isTraceEnabled()) { log.trace("Entering getRepository : " + name); } Ref ref; synchronized (repositories) { ref = repositories.get(name); } if (ref != null) { return ref.get(); } else { return null; } } /** * Releases the reference to the repository. * <p> * When the repository reference count becomes 0, the repository is * shutdown. * * @param name the repository name */ public void releaseRepository(String name) { if (log.isTraceEnabled()) { log.trace("Entering releaseRepository : " + name); } Ref ref; synchronized (repositories) { ref = repositories.remove(name); } if (ref != null) { ref.release(); } } public Collection<RepositoryDescriptor> getDescriptors() { return Collections.unmodifiableCollection(descriptors); } public String[] getRepositoryNames() { synchronized (repositories) { return repositories.keySet().toArray( new String[repositories.size()]); } } public RepositoryDescriptor getDescriptor(String name) { synchronized (repositories) { Ref ref = repositories.get(name); if (ref != null) { return ref.descriptor; } } return null; } public void registerRepository(RepositoryDescriptor rd) { log.info("Registering repository: " + rd.getName()); if (!descriptors.contains(rd)) { synchronized (repositories) { if (!descriptors.contains(rd)) { String name = rd.getName(); descriptors.add(rd); repositories.put(name, new Ref(rd)); repositoryService.fireRepositoryRegistered(rd); } } } } public Repository getOrRegisterRepository(RepositoryDescriptor rd) throws Exception { synchronized (repositories) { Ref ref = repositories.get(rd.getName()); if (ref == null) { String name = rd.getName(); log.info("Registering repository: " + name); descriptors.add(rd); ref = new Ref(rd); repositories.put(name, ref); repositoryService.fireRepositoryRegistered(rd); } return ref.get(); } } public void unregisterRepository(RepositoryDescriptor rd) { log.info("Unregistering repository: " + rd.getName()); if (descriptors.contains(rd)) { synchronized (repositories) { descriptors.remove(rd); Ref ref = repositories.remove(rd.getName()); if (ref != null) { log.info("Unregistering repository: " + rd.getName()); repositoryService.fireRepositoryUnRegistered(rd); ref.dispose(); } } } } public void shutdown() { log.info("Shutting down repository manager"); synchronized (repositories) { Iterator<Ref> it = repositories.values().iterator(); while (it.hasNext()) { Ref ref = it.next(); ref.dispose(); it.remove(); } descriptors.clear(); } } public static final class Ref { private int refcnt; private RepositoryDescriptor descriptor; private Repository repository; private Ref(RepositoryDescriptor descriptor) { this.descriptor = descriptor; } public synchronized Repository get() throws Exception { if (repository == null) { refcnt = 0; repository = descriptor.create(); } refcnt++; return repository; } public synchronized void release() { if (repository != null) { if (--refcnt == 0) { repository.shutdown(); repository = null; } } } public void dispose() { if (repository != null) { repository.shutdown(); repository = null; } refcnt = 0; descriptor = null; } } }