Package org.openrdf.repository.manager

Source Code of org.openrdf.repository.manager.LocalRepositoryManager$ConfigChangeListener

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 2007-2009.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.repository.manager;

import static org.openrdf.repository.manager.SystemRepository.REPOSITORYID;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import info.aduna.io.FileUtil;

import org.openrdf.OpenRDFUtil;
import org.openrdf.model.Model;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.LinkedHashModel;
import org.openrdf.repository.DelegatingRepository;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.config.DelegatingRepositoryImplConfig;
import org.openrdf.repository.config.RepositoryConfig;
import org.openrdf.repository.config.RepositoryConfigSchema;
import org.openrdf.repository.config.RepositoryFactory;
import org.openrdf.repository.config.RepositoryImplConfig;
import org.openrdf.repository.config.RepositoryRegistry;
import org.openrdf.repository.event.base.RepositoryConnectionListenerAdapter;
import org.openrdf.repository.manager.config.LocalConfigManager;
import org.openrdf.repository.manager.config.SystemConfigManager;
import org.openrdf.repository.manager.templates.LocalTemplateManager;
import org.openrdf.store.StoreConfigException;
import org.openrdf.store.StoreException;

/**
* An implementation of the {@link RepositoryManager} interface that operates
* directly on the repository data files in the local file system.
*
* @author Arjohn Kampman
*/
public class LocalRepositoryManager extends RepositoryManager {

  /*-----------*
   * Constants *
   *-----------*/

  private static final String TEMPLATES = "templates";

  private static final String CONFIGURATIONS = "configurations";

  public static final String REPOSITORIES_DIR = "repositories";

  /*-----------*
   * Variables *
   *-----------*/

  /**
   * The base dir to resolve any relative paths against.
   */
  private final File baseDir;

  /*--------------*
   * Constructors *
   *--------------*/

  /**
   * Creates a new RepositoryManager that operates on the specfified base
   * directory.
   *
   * @param baseDir
   *        The base directory where data for repositories can be stored, among
   *        other things.
   */
  public LocalRepositoryManager(File baseDir) {
    super();

    assert baseDir != null : "baseDir must not be null";
    this.baseDir = baseDir;
  }

  /*---------*
   * Methods *
   *---------*/

  /**
   * Initializes the repository manager.
   *
   * @throws StoreException
   *         If the manager failed to initialize the SYSTEM repository.
   */
  @Override
  public void initialize()
    throws StoreConfigException
  {
    LocalTemplateManager templates = new LocalTemplateManager(new File(baseDir, TEMPLATES));
    templates.init();
    setConfigTemplateManager(templates);
    try {
      if (getRepositoryDir(SystemRepository.ID).isDirectory()) {
        // Sesame 2.0 directory
        File systemDir = getRepositoryDir(SystemRepository.ID);
        SystemRepository systemRepos = new SystemRepository(systemDir);
        systemRepos.initialize();

        systemRepos.addRepositoryConnectionListener(new ConfigChangeListener());
        Repository systemRepository = systemRepos;
        setRepositoryConfigManager(new SystemConfigManager(systemRepository));

        assignSystemRepository(systemRepository);
      }
      else {
        // Sesame 3.0 directory
        setRepositoryConfigManager(new LocalConfigManager(new File(baseDir, CONFIGURATIONS)));
      }
    }
    catch (StoreException e) {
      throw new StoreConfigException(e);
    }
  }

  /**
   * Gets the base dir against which to resolve relative paths.
   */
  public File getBaseDir() {
    return baseDir;
  }

  /**
   * Gets the base dir against which to resolve relative paths.
   *
   * @throws MalformedURLException
   *         If the path cannot be parsed as a URL
   */
  @Override
  public URL getLocation()
    throws MalformedURLException
  {
    return baseDir.toURI().toURL();
  }

  /**
   * Resolves the specified path against the manager's base directory.
   *
   * @see #getBaseDir
   */
  public File resolvePath(String path) {
    return new File(getBaseDir(), path);
  }

  public File getRepositoryDir(String repositoryID) {
    File repositoriesDir = resolvePath(REPOSITORIES_DIR);
    return new File(repositoriesDir, repositoryID);
  }

  @Override
  protected Repository createRepository(String id)
    throws StoreConfigException, StoreException
  {
    Model config = getRepositoryConfig(id);

    if (config != null) {
      RepositoryConfig repConfig = parse(config);

      Repository repository = createRepositoryStack(repConfig.getRepositoryImplConfig());
      try {
        repository.setDataDir(getRepositoryDir(id));
        repository.initialize();
        return repository;
      }
      catch (StoreException e) {
        repository.shutDown();
        throw e;
      }
      catch (RuntimeException e) {
        repository.shutDown();
        throw e;
      }
    }

    return null;
  }

  /**
   * Creates the stack of Repository objects for the repository represented by
   * the supplied configuration.
   *
   * @param config
   *        The repository configuration.
   * @return The created repository.
   * @throws StoreConfigException
   *         If no repository could be created due to invalid or incomplete
   *         configuration data.
   */
  private Repository createRepositoryStack(RepositoryImplConfig config)
    throws StoreConfigException
  {
    RepositoryFactory factory = RepositoryRegistry.getInstance().get(config.getType());
    if (factory == null) {
      throw new StoreConfigException("Unsupported repository type: " + config.getType());
    }

    Repository repository = factory.getRepository(config);

    if (config instanceof DelegatingRepositoryImplConfig) {
      RepositoryImplConfig delegateConfig = ((DelegatingRepositoryImplConfig)config).getDelegate();

      Repository delegate = createRepositoryStack(delegateConfig);

      try {
        ((DelegatingRepository)repository).setDelegate(delegate);
      }
      catch (ClassCastException e) {
        throw new StoreConfigException(
            "Delegate specified for repository that is not a DelegatingRepository: "
                + delegate.getClass());
      }
    }

    return repository;
  }

  @Override
  public String addRepositoryConfig(String id, Model config)
    throws StoreConfigException, StoreException
  {
    parse(config);
    return super.addRepositoryConfig(id, config);
  }

  private RepositoryConfig parse(Model config)
    throws StoreConfigException
  {
    RepositoryConfig repConfig = RepositoryConfig.create(config);
    repConfig.validate();
    return repConfig;
  }

  @Override
  public RepositoryInfo getRepositoryInfo(String id)
    throws StoreConfigException
  {
    RepositoryInfo repInfo = null;

    if (id.equals(SystemRepository.ID)) {
      repInfo = new RepositoryInfo(id, SystemRepository.TITLE);
    }
    else {
      Model model = getRepositoryConfig(id);

      if (model != null) {
        repInfo = new RepositoryInfo(id);

        try {
          RepositoryConfig config = parse(model);
          repInfo.setDescription(config.getTitle());
        }
        catch (StoreConfigException e) {
          logger.warn("Failed to parse configuration for store {}: {})", id, e.getMessage());
        }
      }
    }

    if (repInfo != null) {
      try {
        repInfo.setLocation(getRepositoryDir(id).toURI().toURL());
      }
      catch (MalformedURLException e) {
        throw new StoreConfigException("Location of repository does not resolve to a valid URL", e);
      }
    }

    return repInfo;
  }

  @Override
  public List<RepositoryInfo> getAllRepositoryInfos(boolean skipSystemRepo)
    throws StoreConfigException
  {
    List<RepositoryInfo> result = new ArrayList<RepositoryInfo>();

    for (String id : getRepositoryIDs()) {
      if (!skipSystemRepo || !id.equals(SystemRepository.ID)) {
        result.add(getRepositoryInfo(id));
      }
    }

    return result;
  }

  class ConfigChangeListener extends RepositoryConnectionListenerAdapter {

    private Map<RepositoryConnection, Set<Resource>> modifiedContextsByConnection = new HashMap<RepositoryConnection, Set<Resource>>();

    private Map<RepositoryConnection, Boolean> modifiedAllContextsByConnection = new HashMap<RepositoryConnection, Boolean>();

    private Map<RepositoryConnection, Set<Resource>> removedContextsByConnection = new HashMap<RepositoryConnection, Set<Resource>>();

    private Set<Resource> getModifiedContexts(RepositoryConnection conn) {
      Set<Resource> result = modifiedContextsByConnection.get(conn);
      if (result == null) {
        result = new HashSet<Resource>();
        modifiedContextsByConnection.put(conn, result);
      }
      return result;
    }

    private Set<Resource> getRemovedContexts(RepositoryConnection conn) {
      Set<Resource> result = removedContextsByConnection.get(conn);
      if (result == null) {
        result = new HashSet<Resource>();
        removedContextsByConnection.put(conn, result);
      }
      return result;
    }

    private void registerModifiedContexts(RepositoryConnection conn, Resource... contexts) {
      Set<Resource> modifiedContexts = getModifiedContexts(conn);
      // wildcard used for context
      if (contexts != null && contexts.length == 0) {
        modifiedAllContextsByConnection.put(conn, true);
      }
      else {
        for (Resource context : OpenRDFUtil.notNull(contexts)) {
          modifiedContexts.add(context);
        }
      }
    }

    @Override
    public void add(RepositoryConnection conn, Resource subject, URI predicate, Value object,
        Resource... contexts)
    {
      registerModifiedContexts(conn, contexts);
    }

    @Override
    public void clear(RepositoryConnection conn, Resource... contexts) {
      registerModifiedContexts(conn, contexts);
    }

    @Override
    public void remove(RepositoryConnection conn, Resource subject, URI predicate, Value object,
        Resource... contexts)
    {
      if (object != null && object.equals(RepositoryConfigSchema.REPOSITORY_CONTEXT)) {
        if (subject == null) {
          modifiedAllContextsByConnection.put(conn, true);
        }
        else {
          Set<Resource> removedContexts = getRemovedContexts(conn);
          removedContexts.add(subject);
        }
      }
      registerModifiedContexts(conn, contexts);
    }

    @Override
    public void rollback(RepositoryConnection conn) {
      modifiedContextsByConnection.remove(conn);
      modifiedAllContextsByConnection.remove(conn);
    }

    @Override
    public void commit(RepositoryConnection con) {
      // TODO The SYSTEM repository should be replaced
      try {
        List<String> ids = new ArrayList<String>();

        for (Resource ctx : con.getContextIDs().asList()) {
          Model model = new LinkedHashModel();
          con.match(null, null, null, false, ctx).addTo(model);
          String id = getConfigId(model);
          ids.add(id);

          Model currently = getRepositoryConfig(id);
          if (currently == null || !currently.equals(model)) {
            addRepositoryConfig(id, model);
          }
        }

        Set<String> old = new HashSet<String>(getRepositoryIDs());
        old.removeAll(ids);
        for (String id : old) {
          removeRepositoryConfig(id);
        }
      }
      catch (StoreException e) {
        throw new AssertionError(e);
      }
      catch (StoreConfigException e) {
        throw new AssertionError(e);
      }
    }

    private String getConfigId(Model config)
      throws StoreConfigException
    {
      Set<Value> ids = config.filter(null, REPOSITORYID, null).objects();
      if (ids.size() != 1) {
        throw new StoreConfigException("Repository ID not found");
      }
      return ids.iterator().next().stringValue();
    }
  }

  @Override
  protected void cleanUpRepository(String repositoryID)
    throws IOException
  {
    File dataDir = getRepositoryDir(repositoryID);

    if (dataDir.isDirectory()) {
      logger.debug("Cleaning up data dir {} for repository {}", dataDir.getAbsolutePath(), repositoryID);
      FileUtil.deleteDir(dataDir);
    }
  }
}
TOP

Related Classes of org.openrdf.repository.manager.LocalRepositoryManager$ConfigChangeListener

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.