Package org.openrdf.sail.nativerdf

Source Code of org.openrdf.sail.nativerdf.NamespaceStore

/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006.
*
* Licensed under the Aduna BSD-style license.
*/
package org.openrdf.sail.nativerdf;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import info.aduna.io.IOUtil;

import org.openrdf.model.Namespace;
import org.openrdf.model.impl.NamespaceImpl;

/**
* An in-memory store for namespace prefix information that uses a file for
* persistence. Namespaces are encoded in the file as records as follows:
*
* <pre>
*   byte 1 - 2     : the length of the encoded namespace name
*   byte 3 - A     : the UTF-8 encoded namespace name
*   byte A+1 - A+2 : the length of the encoded namespace prefix
*   byte A+3 - end : the UTF-8 encoded namespace prefix
* </pre>
*
* @author Arjohn Kampman
*/
class NamespaceStore implements Iterable<NamespaceImpl> {

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

  private static final String FILE_NAME = "namespaces.dat";

  /**
   * Magic number "Native Namespace File" to detect whether the file is
   * actually a namespace file. The first three bytes of the file should be
   * equal to this magic number.
   */
  private static final byte[] MAGIC_NUMBER = new byte[] { 'n', 'n', 'f' };

  /**
   * File format version, stored as the fourth byte in namespace files.
   */
  private static final byte FILE_FORMAT_VERSION = 1;

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

  /**
   * The data file for this NamespaceStore.
   */
  private final File file;

  /**
   * Map storing namespace information by their prefix.
   */
  private final Map<String, NamespaceImpl> namespacesMap;

  /**
   * Flag indicating whether the contents of this NamespaceStore are different
   * from what is stored on disk.
   */
  private volatile boolean contentsChanged;

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

  public NamespaceStore(File dataDir)
    throws IOException
  {
    file = new File(dataDir, FILE_NAME);

    namespacesMap = new LinkedHashMap<String, NamespaceImpl>(16);

    if (file.exists()) {
      readNamespacesFromFile();
    }
    else {
      // Make sure the file exists
      writeNamespacesToFile();
    }

    contentsChanged = false;
  }

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

  public String getNamespace(String prefix) {
    String result = null;
    NamespaceImpl namespace = namespacesMap.get(prefix);
    if (namespace != null) {
      result = namespace.getName();
    }
    return result;
  }

  public void setNamespace(String prefix, String name) {
    NamespaceImpl newNS = new NamespaceImpl(prefix, name);
    NamespaceImpl old = namespacesMap.put(prefix, newNS);

    if (!newNS.equals(old)) {
      contentsChanged = true;
    }
  }

  public void removeNamespace(String prefix) {
    NamespaceImpl ns = namespacesMap.remove(prefix);

    if (ns != null) {
      contentsChanged = true;
    }
  }

  public Iterator<NamespaceImpl> iterator() {
    return namespacesMap.values().iterator();
  }

  public void clear() {
    if (!namespacesMap.isEmpty()) {
      namespacesMap.clear();
      contentsChanged = true;
    }
  }

  public void sync()
    throws IOException
  {
    if (contentsChanged) {
      // Flush the changes to disk
      writeNamespacesToFile();
      contentsChanged = false;
    }
  }

  public void close() {
  }

  /*----------*
   * File I/O *
   *----------*/

  private void writeNamespacesToFile()
    throws IOException
  {
    synchronized (file) {
      DataOutputStream out = new DataOutputStream(new FileOutputStream(file));

      try {
        out.write(MAGIC_NUMBER);
        out.writeByte(FILE_FORMAT_VERSION);

        for (Namespace ns : namespacesMap.values()) {
          out.writeUTF(ns.getName());
          out.writeUTF(ns.getPrefix());
        }
      }
      finally {
        out.close();
      }
    }
  }

  private void readNamespacesFromFile()
    throws IOException
  {
    synchronized (file) {
      DataInputStream in = new DataInputStream(new FileInputStream(file));

      try {
        byte[] magicNumber = IOUtil.readBytes(in, MAGIC_NUMBER.length);
        if (!Arrays.equals(magicNumber, MAGIC_NUMBER)) {
          throw new IOException("File doesn't contain compatible namespace data");
        }

        byte version = in.readByte();
        if (version > FILE_FORMAT_VERSION) {
          throw new IOException("Unable to read namespace file; it uses a newer file format");
        }
        else if (version != FILE_FORMAT_VERSION) {
          throw new IOException("Unable to read namespace file; invalid file format version: " + version);
        }

        while (true) {
          try {
            String name = in.readUTF();
            String prefix = in.readUTF();

            NamespaceImpl ns = new NamespaceImpl(prefix, name);
            namespacesMap.put(prefix, ns);
          }
          catch (EOFException e) {
            break;
          }
        }
      }
      finally {
        in.close();
      }
    }
  }

  /*-------------------*
   * Debugging methods *
   *-------------------*/

  public static void main(String[] args)
    throws Exception
  {
    NamespaceStore nsStore = new NamespaceStore(new File(args[0]));

    for (Namespace ns : nsStore) {
      System.out.println(ns.getPrefix() + " = " + ns.getName());
    }
  }
}
TOP

Related Classes of org.openrdf.sail.nativerdf.NamespaceStore

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.