Package org.exoplatform.services.jcr.impl.core.query.lucene

Source Code of org.exoplatform.services.jcr.impl.core.query.lucene.FileBasedNamespaceMappings

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.exoplatform.services.jcr.impl.core.query.lucene;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import javax.jcr.NamespaceException;
import javax.jcr.RepositoryException;

import org.exoplatform.services.log.Log;

import org.exoplatform.services.jcr.datamodel.IllegalNameException;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.impl.core.LocationFactory;
import org.exoplatform.services.log.ExoLogger;

/**
* The class <code>NamespaceMappings</code> implements a
* {@link org.apache.jackrabbit.core.NamespaceResolver} that holds a namespace mapping that is used
* internally in the search index. Storing paths with the full uri of a namespace would require too
* much space in the search index. <p/> Whenever a yet unknown namespace uri to prefix mapping is
* requested, a new prefix is created on the fly and associated with the namespace. Known namespace
* mappings are stored in a properties file.
*/
public class FileBasedNamespaceMappings
   implements NamespaceMappings
{

   /**
    * Default logger instance for this class
    */
   private static Log log = ExoLogger.getLogger(NamespaceMappings.class);

   /**
    * Location of the file that persists the uri / prefix mappings
    */
   private final File storage;

   /**
    * The name resolver used to translate the qualified name to JCR name
    */
   private final LocationFactory nameResolver;

   /**
    * Map of uris indexed by prefixes
    */
   private Map prefixToURI = new HashMap();

   /**
    * Map of prefixes indexed by uris
    */
   private Map uriToPrefix = new HashMap();

   /**
    * Current prefix count.
    */
   private int prefixCount;

   /**
    * Creates <code>NamespaceMappings</code> instance. Initial mappings are loaded from
    * <code>file</code>.
    *
    * @param file
    *          the <code>File</code> to load initial mappings.
    * @throws IOException
    *           if an error occurs while reading initial namespace mappings from <code>file</code>.
    */
   public FileBasedNamespaceMappings(File file) throws IOException
   {
      storage = file;
      load();
      nameResolver = new LocationFactory(this);
   }

   // ----------------------------< NamespaceMappings >-------------------------

   /**
    * Translates a property name from a session local namespace mapping into a search index private
    * namespace mapping.
    *
    * @param qName
    *          the property name to translate
    * @return the translated property name
    */
   public String translatePropertyName(InternalQName qName) throws IllegalNameException
   {
      try
      {
         return nameResolver.createJCRName(qName).getAsString();
      }
      catch (RepositoryException e)
      {
         // should never happen actually, because we create yet unknown
         // uri mappings on the fly.
         throw new IllegalNameException("Internal error.", e);
      }
   }

   // -----------------------< internal >---------------------------------------

   /**
    * Loads currently known mappings from a .properties file.
    *
    * @throws IOException
    *           if an error occurs while reading from the file.
    */
   private void load() throws IOException
   {
      if (storage.exists())
      {
         InputStream in = new FileInputStream(storage);
         try
         {
            Properties props = new Properties();
            log.debug("loading namespace mappings...");
            props.load(in);

            // read mappings from properties
            Iterator iter = props.keySet().iterator();
            while (iter.hasNext())
            {
               String prefix = (String) iter.next();
               String uri = props.getProperty(prefix);
               log.debug(prefix + " -> " + uri);
               prefixToURI.put(prefix, uri);
               uriToPrefix.put(uri, prefix);
            }
            prefixCount = props.size();
            log.debug("namespace mappings loaded.");
         }
         finally
         {
            in.close();
         }
      }
   }

   /**
    * Writes the currently known mappings into a .properties file.
    *
    * @throws IOException
    *           if an error occurs while writing the file.
    */
   private void store() throws IOException
   {
      Properties props = new Properties();

      // store mappings in properties
      Iterator iter = prefixToURI.keySet().iterator();
      while (iter.hasNext())
      {
         String prefix = (String) iter.next();
         String uri = (String) prefixToURI.get(prefix);
         props.setProperty(prefix, uri);
      }

      OutputStream out = new FileOutputStream(storage);
      try
      {
         out = new BufferedOutputStream(out);
         props.store(out, null);
      }
      finally
      {
         // make sure stream is closed
         out.close();
      }
   }

   public String[] getAllNamespacePrefixes() throws RepositoryException
   {
      return (String[]) prefixToURI.keySet().toArray(new String[prefixToURI.keySet().size()]);
   }

   /**
    * Returns a prefix for the namespace <code>uri</code>. If a namespace mapping exists, the already
    * known prefix is returned; otherwise a new prefix is created and assigned to the namespace uri.
    *
    * @param uri
    *          the namespace uri.
    * @return the prefix for the namespace uri.
    * @throws NamespaceException
    *           if an yet unknown namespace uri / prefix mapping could not be stored.
    */
   public String getNamespacePrefixByURI(String uri) throws NamespaceException, RepositoryException
   {
      String prefix = (String) uriToPrefix.get(uri);
      if (prefix == null)
      {
         // make sure prefix is not taken
         while (prefixToURI.get(String.valueOf(prefixCount)) != null)
         {
            prefixCount++;
         }
         prefix = String.valueOf(prefixCount);
         prefixToURI.put(prefix, uri);
         uriToPrefix.put(uri, prefix);
         log.debug("adding new namespace mapping: " + prefix + " -> " + uri);
         try
         {
            store();
         }
         catch (IOException e)
         {
            throw new NamespaceException("Could not obtain a prefix for uri: " + uri, e);
         }
      }
      return prefix;
   }

   /**
    * Returns a namespace uri for a <code>prefix</code>.
    *
    * @param prefix
    *          the namespace prefix.
    * @return the namespace uri.
    * @throws NamespaceException
    *           if no namespace uri is registered for <code>prefix</code>.
    */
   public String getNamespaceURIByPrefix(String prefix) throws NamespaceException, RepositoryException
   {
      if (!prefixToURI.containsKey(prefix))
      {
         throw new NamespaceException(prefix + ": is not a registered namespace prefix.");
      }
      return (String) prefixToURI.get(prefix);
   }

}
TOP

Related Classes of org.exoplatform.services.jcr.impl.core.query.lucene.FileBasedNamespaceMappings

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.