Package org.jboss.dna.jcr

Source Code of org.jboss.dna.jcr.JcrEngine

/*
* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
* individual contributors.
*
* Unless otherwise indicated, all code in JBoss DNA is licensed
* to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.dna.jcr;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.common.util.Logger;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
import org.jboss.dna.graph.Location;
import org.jboss.dna.graph.Node;
import org.jboss.dna.graph.Subgraph;
import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
import org.jboss.dna.graph.connector.RepositorySource;
import org.jboss.dna.graph.connector.RepositorySourceCapabilities;
import org.jboss.dna.graph.property.Name;
import org.jboss.dna.graph.property.Path;
import org.jboss.dna.graph.property.PathFactory;
import org.jboss.dna.graph.property.PathNotFoundException;
import org.jboss.dna.graph.property.Property;
import org.jboss.dna.graph.property.basic.GraphNamespaceRegistry;
import org.jboss.dna.jcr.JcrRepository.Option;
import org.jboss.dna.repository.DnaConfiguration;
import org.jboss.dna.repository.DnaEngine;

/**
* The basic component that encapsulates the JBoss DNA services, including the {@link Repository} instances.
*/
@ThreadSafe
public class JcrEngine extends DnaEngine {

    final static int LOCK_SWEEP_INTERVAL_IN_MILLIS = 30000;
    final static int LOCK_EXTENSION_INTERVAL_IN_MILLIS = LOCK_SWEEP_INTERVAL_IN_MILLIS * 2;

    private final Logger log = Logger.getLogger(DnaEngine.class);

    private final Map<String, JcrRepository> repositories;
    private final Lock repositoriesLock;

    /**
     * Provides the ability to schedule lock clean-up
     */
    private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(2);

    JcrEngine( ExecutionContext context,
               DnaConfiguration.ConfigurationDefinition configuration ) {
        super(context, configuration);
        this.repositories = new HashMap<String, JcrRepository>();
        this.repositoriesLock = new ReentrantLock();
    }

    /**
     * Clean up session-scoped locks created by session that are no longer active by iterating over the {@link JcrRepository
     * repositories} and calling their {@link JcrRepository#cleanUpLocks() clean-up method}.
     * <p>
     * It should not be possible for a session to be terminated without cleaning up its locks, but this method will help clean-up
     * dangling locks should a session terminate abnormally.
     * </p>
     */
    void cleanUpLocks() {
        Collection<JcrRepository> repos;

        try {
            // Make a copy of the repositories to minimize the time that the lock needs to be held
            repositoriesLock.lock();
            repos = new ArrayList<JcrRepository>(repositories.values());
        } finally {
            repositoriesLock.unlock();
        }

        for (JcrRepository repository : repos) {
            try {
                repository.cleanUpLocks();
            } catch (Throwable t) {
                log.error(t, JcrI18n.errorCleaningUpLocks, repository.getRepositorySourceName());
            }
        }
    }

    @Override
    public void shutdown() {
        scheduler.shutdown();
        super.shutdown();

        try {
            this.repositoriesLock.lock();
            // Shut down all of the repositories ...
            for (JcrRepository repository : repositories.values()) {
                repository.close();
            }
            this.repositories.clear();
        } finally {
            this.repositoriesLock.unlock();
        }
    }

    @Override
    public boolean awaitTermination( long timeout,
                                     TimeUnit unit ) throws InterruptedException {
        if (!scheduler.awaitTermination(timeout, unit)) return false;

        return super.awaitTermination(timeout, unit);
    }

    @Override
    public void start() {
        super.start();

        final JcrEngine engine = this;
        Runnable cleanUpTask = new Runnable() {

            public void run() {
                engine.cleanUpLocks();
            }

        };
        scheduler.scheduleAtFixedRate(cleanUpTask,
                                      LOCK_SWEEP_INTERVAL_IN_MILLIS,
                                      LOCK_SWEEP_INTERVAL_IN_MILLIS,
                                      TimeUnit.MILLISECONDS);
    }

    /**
     * Get the {@link Repository} implementation for the named repository.
     *
     * @param repositoryName the name of the repository, which corresponds to the name of a configured {@link RepositorySource}
     * @return the named repository instance
     * @throws IllegalArgumentException if the repository name is null, blank or invalid
     * @throws RepositoryException if there is no repository with the specified name
     * @throws IllegalStateException if this engine was not {@link #start() started}
     */
    public final JcrRepository getRepository( String repositoryName ) throws RepositoryException {
        CheckArg.isNotEmpty(repositoryName, "repositoryName");
        checkRunning();
        try {
            repositoriesLock.lock();
            JcrRepository repository = repositories.get(repositoryName);
            if (repository == null) {
                try {
                    repository = doCreateJcrRepository(repositoryName);
                } catch (PathNotFoundException e) {
                    // The repository name is not a valid repository ...
                    String msg = JcrI18n.repositoryDoesNotExist.text(repositoryName);
                    throw new RepositoryException(msg);
                }
                repositories.put(repositoryName, repository);
            }
            return repository;
        } finally {
            repositoriesLock.unlock();
        }
    }

    /**
     * Get the names of each of the JCR repositories.
     *
     * @return the immutable names of the repositories that exist at the time this method is called
     */
    public Set<String> getRepositoryNames() {
        checkRunning();
        Set<String> results = new HashSet<String>();
        // Read the names of the JCR repositories from the configuration (not from the Repository objects used so far) ...
        PathFactory pathFactory = getExecutionContext().getValueFactories().getPathFactory();
        Path repositoriesPath = pathFactory.create(configuration.getPath(), DnaLexicon.REPOSITORIES);
        Graph configuration = getConfigurationGraph();
        for (Location child : configuration.getChildren().of(repositoriesPath)) {
            Name repositoryName = child.getPath().getLastSegment().getName();
            results.add(readable(repositoryName));
        }
        return Collections.unmodifiableSet(results);
    }

    protected JcrRepository doCreateJcrRepository( String repositoryName ) throws RepositoryException, PathNotFoundException {
        RepositoryConnectionFactory connectionFactory = getRepositoryConnectionFactory();
        Map<String, String> descriptors = null;
        Map<Option, String> options = new HashMap<Option, String>();

        // Read the subgraph that represents the repository ...
        PathFactory pathFactory = getExecutionContext().getValueFactories().getPathFactory();
        Path repositoriesPath = pathFactory.create(configuration.getPath(), DnaLexicon.REPOSITORIES);
        Path repositoryPath = pathFactory.create(repositoriesPath, repositoryName);
        Graph configuration = getConfigurationGraph();
        Subgraph subgraph = configuration.getSubgraphOfDepth(6).at(repositoryPath);

        // Read the options ...
        Node optionsNode = subgraph.getNode(DnaLexicon.OPTIONS);
        if (optionsNode != null) {
            for (Location optionLocation : optionsNode.getChildren()) {
                Node optionNode = configuration.getNodeAt(optionLocation);
                Path.Segment segment = optionLocation.getPath().getLastSegment();
                Property valueProperty = optionNode.getProperty(DnaLexicon.VALUE);
                if (valueProperty == null) continue;
                Option option = Option.findOption(segment.getName().getLocalName());
                if (option == null) continue;
                options.put(option, valueProperty.getFirstValue().toString());
            }
        }

        // Read the namespaces ...
        ExecutionContext context = getExecutionContext();
        Node namespacesNode = subgraph.getNode(DnaLexicon.NAMESPACES);
        if (namespacesNode != null) {
            GraphNamespaceRegistry registry = new GraphNamespaceRegistry(configuration, namespacesNode.getLocation().getPath(),
                                                                         DnaLexicon.NAMESPACE_URI);
            context = context.with(registry);
        }

        // Get the name of the source ...
        Property property = subgraph.getRoot().getProperty(DnaLexicon.SOURCE_NAME);
        if (property == null || property.isEmpty()) {
            String readableName = readable(DnaLexicon.SOURCE_NAME);
            String readablePath = readable(subgraph.getLocation());
            String msg = JcrI18n.propertyNotFoundOnNode.text(readableName, readablePath, configuration.getCurrentWorkspaceName());
            throw new RepositoryException(msg);
        }
        String sourceName = context.getValueFactories().getStringFactory().create(property.getFirstValue());

        // Find the capabilities ...
        RepositorySource source = getRepositorySource(sourceName);
        RepositorySourceCapabilities capabilities = source != null ? source.getCapabilities() : null;
        // Create the repository ...
        JcrRepository repository = new JcrRepository(context, connectionFactory, sourceName,
                                                     getRepositoryService().getRepositoryLibrary(), capabilities, descriptors,
                                                     options);

        // Register all the the node types ...
        Node nodeTypesNode = subgraph.getNode(JcrLexicon.NODE_TYPES);
        if (nodeTypesNode != null) {
            repository.getRepositoryTypeManager().registerNodeTypes(subgraph, nodeTypesNode.getLocation());// throws exception
        }

        return repository;
    }

    protected final String readable( Name name ) {
        return name.getString(context.getNamespaceRegistry());
    }

    protected final String readable( Path path ) {
        return path.getString(context.getNamespaceRegistry());
    }

    protected final String readable( Location location ) {
        return location.getString(context.getNamespaceRegistry());
    }
}
TOP

Related Classes of org.jboss.dna.jcr.JcrEngine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.