Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2011 eXo Platform SAS.
   *
   * This is free software; you can redistribute it and/or modify it
   * 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.
   *
   * This software 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.exoplatform.services.jcr.ext.distribution.impl;
 
 
 import java.util.List;
 import java.util.Map;
 
 import javax.jcr.Node;

Author(s):
Nicolas Filotto
Version:
$Id$
 
 public abstract class AbstractDataDistributionType implements DataDistributionType
 {
 
    private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.ext.AbstractDataDistributionType");

   
The default node type to use when we create a new node
 
    private static final String DEFAULT_NODE_TYPE = "nt:unstructured".intern();

   
The map defining all the locks available
 
    private final ConcurrentMap<StringLocklocks = new ConcurrentHashMap<StringLock>(64, 0.75f, 64);

   
 
    public Node getDataNode(Node rootNodeString dataIdthrows PathNotFoundExceptionRepositoryException
    {
       return rootNode.getNode(getRelativePath(dataId));
    }

   
 
    public Node getOrCreateDataNode(Node rootNodeString dataIdthrows RepositoryException
    {
       return getOrCreateDataNode(rootNodedataIdnull);
    }

   
 
    public Node getOrCreateDataNode(Node rootNodeString dataIdString nodeTypethrows RepositoryException
    {
       return getOrCreateDataNode(rootNodedataIdnodeTypenull);
    }

   
 
    public Node getOrCreateDataNode(Node rootNodeString dataIdString nodeTypeList<StringmixinTypes)
       throws RepositoryException
    {
       return getOrCreateDataNode(rootNodedataIdnodeTypemixinTypesnull);
    }

   
 
    public Node getOrCreateDataNode(Node rootNodeString dataIdString nodeTypeList<StringmixinTypes,
       Map<StringString[]> permissionsthrows RepositoryException
    {
       try
       {
          return getDataNode(rootNodedataId);
      }
      catch (PathNotFoundException e)
      {
         if (.isTraceEnabled())
         {
            .trace("An exception occurred: " + e.getMessage());
         }
      }
      // The node could not be found so we need to create it
      Node node = rootNode;
      List<Stringancestors = getAncestors(dataId);
      for (int i = 0, length = ancestors.size(); i < lengthi++)
      {
         String nodeName = ancestors.get(i);
         try
         {
            node = node.getNode(nodeName);
            continue;
         }
         catch (PathNotFoundException e)
         {
            if (.isTraceEnabled())
            {
               .trace("An exception occurred: " + e.getMessage());
            }
         }
         // The node doesn't exist we need to create it
         node = createNode(nodenodeNamenodeTypemixinTypespermissionsi == length - 1, true);
      }
      return node;
   }

   
   public void removeDataNode(Node rootNodeString dataIdthrows RepositoryException
   {      
      Lock lock = getLock(rootNodegetRelativePath(dataId));
      lock.lock();
      try
      {
         Node node = getDataNode(rootNodedataId);
         Node parentNode = node.getParent();
         node.remove();
         parentNode.save();
      }
      catch (PathNotFoundException e)
      {
         if (.isTraceEnabled())
         {
            .trace("An exception occurred: " + e.getMessage());
         }
      }
      finally 
      {
         lock.unlock();
      }     
   }

   
   public void migrate(Node rootNodethrows RepositoryException
   {
      throw new UnsupportedOperationException("The method is not supported");
   }

   
   public void migrate(Node rootNodeString nodeTypeList<StringmixinTypesMap<StringString[]> permissions)
      throws RepositoryException
   {
      throw new UnsupportedOperationException("The method is not supported");
   }

   
Creates the node of the given node type with the given node name directly under the given parent node, using the given mixin types and permissions

Parameters:
parentNode the parent node
nodeName the name of the node to create
nodeType the node type to use
mixinTypes the list of mixin types to use
permissions the map of permissions to use
isLeaf indicates whether or not the current node to create is the leaf node
Returns:
the created node
Throws:
javax.jcr.RepositoryException if any exception occurs while creating the node
   protected Node createNode(final Node parentNodefinal String nodeNamefinal String nodeType,
      final List<StringmixinTypesfinal Map<StringString[]> permissionsfinal boolean isLeaf,
      final boolean callSavethrows RepositoryException
   {
      Lock lock = getLock(parentNodenodeName);
      lock.lock();
      try
      {
         try
         {
            // We ensure that the node has not been created since the last time we checked
            return parentNode.getNode(nodeName);
         }
         catch (PathNotFoundException e)
         {
            if (.isTraceEnabled())
            {
               .trace("An exception occurred: " + e.getMessage());
            }
         }
         
         boolean useParameters = !useParametersOnLeafOnly() || (useParametersOnLeafOnly() && isLeaf);
         Node node;
         if (nodeType == null || nodeType.isEmpty() || !useParameters)
         {
            node = parentNode.addNode(nodeName);
         }
         else
         {
            node = parentNode.addNode(nodeNamenodeType);
         }
         if (useParameters)
         {
            if (permissions != null && !permissions.isEmpty())
            {
               if (node.canAddMixin("exo:privilegeable"))
               {
                  node.addMixin("exo:privilegeable");
               }
               ((ExtendedNode)node).setPermissions(permissions);
            }
            if (mixinTypes != null)
            {
               for (int i = 0, length = mixinTypes.size(); i < lengthi++)
               {
                  String mixin = mixinTypes.get(i);
                  if (node.canAddMixin(mixin))
                  {
                     node.addMixin(mixin);
                  }
               }
            }
         }
         if (callSave)
         {
            parentNode.save();
         }
         return node;         
      }
      finally 
      {
         lock.unlock();
      }
   }

   
Creates the full path of the given node name

Parameters:
parentNode the parent node from which we extract the absolute path
relativePath the relative path of the node for which we want the full path
Returns:
the full path of the node for which we want the path
Throws:
javax.jcr.RepositoryException if any exception occurs while creating the path
   private String createFullPath(Node parentNodeString relativePaththrows RepositoryException
   {
      StringBuilder buffer = new StringBuilder(256);
      buffer.append(((RepositoryImpl)parentNode.getSession().getRepository()).getName());
      buffer.append('/');
      buffer.append(parentNode.getSession().getWorkspace().getName());
      String rootPath = parentNode.getPath();
      buffer.append(rootPath);
      if (!rootPath.endsWith("/"))
      {
         buffer.append('/');
      }
      buffer.append(relativePath);
      return buffer.toString();
   }

   
Get the lock corresponding to the given node name

Parameters:
parentNode the parent node of the node to lock
relativePath the relative path of the node to lock
Returns:
the lock corresponding to the given node name
Throws:
javax.jcr.RepositoryException if any exception occurs while getting the lock
   private Lock getLock(Node parentNodeString relativePaththrows RepositoryException
   {
      String fullPath = createFullPath(parentNoderelativePath);
      Lock lock = .get(fullPath);
      if (lock != null)
      {
         return lock;
      }
      lock = new InternalLock(fullPath);
      Lock prevLock = .putIfAbsent(fullPathlock);
      if (prevLock != null)
      {
         lock = prevLock;
      }
      return lock;
   }
   
   
Gives the relative path corresponding to the given id of the data to find/create

Parameters:
dataId the id of the data to find/create
Returns:
the relative path of the data to find/create
   protected String getRelativePath(String dataId)
   {
      StringBuilder buffer = new StringBuilder(256);
      List<Stringancestors = getAncestors(dataId);
      for (int i = 0, length = ancestors.size(); i < lengthi++)
      {
         buffer.append(ancestors.get(i));
         if (i != length - 1)
         {
            buffer.append('/');
         }
      }
      return buffer.toString();
   }

   
Gives the list of all the name of the ancestors

Parameters:
dataId the id of the data to find/create
Returns:
the list of the ancestor names
   protected abstract List<StringgetAncestors(String dataId);

   
Indicates whether or not the node type, the mixin types and the permissions have to be used on leaf node only.

Returns:
true if only the leaf node has to be created with the parameters false otherwise.
   protected abstract boolean useParametersOnLeafOnly();
   
   
   
This kind of locks can self unregister from the map of locks
   private class InternalLock extends ReentrantLock {
      
      
Serial Version UID
      private static final long serialVersionUID = -3362387346368015145L;
      
      
The id corresponding to the lock in the map
      private final String fullPath;

      
The default constructor

Parameters:
fullId the id corresponding to the lock in the map
      public InternalLock(String fullPath) {
         super();
         this. = fullPath;
      }
      @Override
      public void unlock() {
         if (!hasQueuedThreads()) {
            // No thread is currently waiting for this lock
            // The lock will then be removed
            .remove(this);
         }
         super.unlock();
      }
   }   
New to GrepCode? Check out our FAQ X