mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	- undeleted and reinstated use of org.alfresco.util.Pair - undeleted org.alfresco.util.PropertyCheck which is used in the deployment code. - undeleted other org.alfresco.util.* classes which probably should never have been moved to spring surf. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@19312 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
			
				
	
	
		
			581 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			581 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2010 Alfresco Software Limited.
 | |
|  *
 | |
|  * This file is part of Alfresco
 | |
|  *
 | |
|  * Alfresco 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 3 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>. */
 | |
| 
 | |
| package org.alfresco.repo.avm;
 | |
| 
 | |
| import java.io.Serializable;
 | |
| import java.util.ArrayList;
 | |
| import java.util.List;
 | |
| 
 | |
| import org.alfresco.repo.avm.util.AVMUtil;
 | |
| import org.alfresco.util.Pair;
 | |
| import org.apache.commons.logging.Log;
 | |
| import org.apache.commons.logging.LogFactory;
 | |
| 
 | |
| /**
 | |
|  * This holds all the information necessary to perform operations
 | |
|  * on AVMNodes, and is structured internally as a list of path components
 | |
|  * from the root directory of a repository.
 | |
|  * @author britt
 | |
|  */
 | |
| class Lookup implements Serializable
 | |
| {
 | |
|     private static final long serialVersionUID = -2844833688622561L;
 | |
|     
 | |
|     private static Log logger = LogFactory.getLog(Lookup.class);
 | |
|     
 | |
|     /**
 | |
|      * Is this lookup valid?
 | |
|      */
 | |
|     private boolean fValid;
 | |
|     
 | |
|     /**
 | |
|      * The AVMStore.
 | |
|      */
 | |
|     private AVMStore fAVMStore;
 | |
| 
 | |
|     /**
 | |
|      * The name of the AVMStore.
 | |
|      */
 | |
|     private String fStoreName;
 | |
|     
 | |
|     /**
 | |
|      * The components that make up this path.
 | |
|      */
 | |
|     private List<LookupComponent> fComponents;
 | |
|     
 | |
|     /**
 | |
|      * The final store in resolving layers.
 | |
|      */
 | |
|     private AVMStore fFinalStore;
 | |
|     
 | |
|     /**
 | |
|      * Whether, at this point, a layered node has been hit.
 | |
|      * Used while building a Lookup.
 | |
|      */
 | |
|     private boolean fLayeredYet;
 | |
|     
 | |
|     /**
 | |
|      * Whether we are directly contained at this point.
 | |
|      */
 | |
|     private boolean fDirectlyContained;
 | |
|  
 | |
|     /**
 | |
|      * The first LayeredDirectoryNode in the path.
 | |
|      */
 | |
|     private LayeredDirectoryNode fTopLayer;
 | |
|     
 | |
|     /**
 | |
|      * The path index of the top LayeredDirectoryNode in the path.
 | |
|      */
 | |
|     private int fTopLayerIndex;
 | |
|     
 | |
|     /**
 | |
|      * The lowest layered directory node's index seen so far.
 | |
|      */
 | |
|     private int fLowestLayerIndex;
 | |
|     
 | |
|     /**
 | |
|      * The current component being looked at by this lookup.
 | |
|      */
 | |
|     private int fPosition;
 | |
|     
 | |
|     /**
 | |
|      * Whether a needs-to-be-copied component has been seen.
 | |
|      */
 | |
|     private boolean fNeedsCopying;
 | |
|     
 | |
|     /**
 | |
|      * The version that is being looked up.
 | |
|      */
 | |
|     private int fVersion;
 | |
|     
 | |
|     public Lookup(Lookup other, AVMNodeDAO nodeDAO, AVMStoreDAO storeDAO)
 | |
|     {
 | |
|         fValid = true;
 | |
|         fAVMStore = storeDAO.getByID(other.fAVMStore.getId());
 | |
|         fVersion = other.fVersion;
 | |
|         if (fAVMStore == null)
 | |
|         {
 | |
|             fValid = false;
 | |
|             return;
 | |
|         }
 | |
|         fStoreName = fAVMStore.getName();
 | |
|         fComponents = new ArrayList<LookupComponent>();
 | |
|         fLayeredYet = other.fLayeredYet;
 | |
|         if (other.fTopLayer != null)
 | |
|         {
 | |
|             fTopLayer = (LayeredDirectoryNode)nodeDAO.getByID(other.fTopLayer.getId());
 | |
|             if (fTopLayer == null)
 | |
|             {
 | |
|                 fValid = false;
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
|         fPosition = other.fPosition;
 | |
|         fTopLayerIndex = other.fTopLayerIndex;
 | |
|         fLowestLayerIndex = other.fLowestLayerIndex;
 | |
|         fNeedsCopying = other.fNeedsCopying;
 | |
|         fDirectlyContained = other.fDirectlyContained;
 | |
|         if (fLayeredYet)
 | |
|         {
 | |
|             for (LookupComponent comp : other.fComponents)
 | |
|             {
 | |
|                 LookupComponent newComp = new LookupComponent();
 | |
|                 newComp.setName(comp.getName());
 | |
|                 newComp.setIndirection(comp.getIndirection());
 | |
|                 newComp.setIndirectionVersion(comp.getIndirectionVersion());
 | |
|                 newComp.setNode(nodeDAO.getByID(comp.getNode().getId()));
 | |
|                 if (newComp.getNode() == null)
 | |
|                 {
 | |
|                     fValid = false;
 | |
|                     return;
 | |
|                 }
 | |
|                 fComponents.add(newComp);
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             // If this is not a layered lookup then we do not
 | |
|             // need to reload any of the actual nodes except for
 | |
|             // the last.
 | |
|             int i = 0;
 | |
|             for (; i < fPosition; ++i)
 | |
|             {
 | |
|                 LookupComponent comp = other.fComponents.get(i);
 | |
|                 LookupComponent newComp = new LookupComponent();
 | |
|                 newComp.setName(comp.getName());
 | |
|                 fComponents.add(newComp);
 | |
|             }
 | |
|             LookupComponent comp = other.fComponents.get(i);
 | |
|             LookupComponent newComp = new LookupComponent();
 | |
|             newComp.setName(comp.getName());
 | |
|             newComp.setNode(nodeDAO.getByID(comp.getNode().getId()));
 | |
|             if (newComp.getNode() == null)
 | |
|             {
 | |
|                 fValid = false;
 | |
|                 return;
 | |
|             }
 | |
|             fComponents.add(newComp);
 | |
|         }
 | |
|         fFinalStore = storeDAO.getByID(other.fFinalStore.getId());
 | |
|         if (fFinalStore == null)
 | |
|         {
 | |
|             fValid = false;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Create a new one.
 | |
|      * @param store The AVMStore that's being looked in.
 | |
|      * @param storeName The name of that AVMStore.
 | |
|      */
 | |
|     public Lookup(AVMStore store, String storeName, int version)
 | |
|     {
 | |
|         fValid = true;
 | |
|         fAVMStore = store;
 | |
|         fStoreName = storeName;
 | |
|         fVersion = version;
 | |
|         fComponents = new ArrayList<LookupComponent>();
 | |
|         fLayeredYet = false;
 | |
|         fTopLayer = null;
 | |
|         fPosition = -1;
 | |
|         fTopLayerIndex = -1;
 | |
|         fLowestLayerIndex = -1;
 | |
|         fNeedsCopying = false;
 | |
|         fDirectlyContained = true;
 | |
|         fFinalStore = store;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Is this a valid lookup?
 | |
|      */
 | |
|     public boolean isValid()
 | |
|     {
 | |
|         return fValid;
 | |
|     }
 | |
|     
 | |
|     // TODO This is badly in need of cleanup.
 | |
|     /**
 | |
|      * Add a new node to the lookup.
 | |
|      * @param node The node to add.
 | |
|      * @param name The name of the node in the path.
 | |
|      * @param write Whether this is in the context of 
 | |
|      * a write operation.
 | |
|      */
 | |
|     public void add(AVMNode node, String name, boolean directlyContained, boolean write)
 | |
|     {
 | |
|         LookupComponent comp = new LookupComponent();
 | |
|         comp.setName(name);
 | |
|         comp.setNode(node);
 | |
|         if (fPosition >= 0 && fDirectlyContained && 
 | |
|                 getCurrentNode().getType() == AVMNodeType.LAYERED_DIRECTORY)
 | |
|         {
 | |
| //            if (directlyContained != ((DirectoryNode)fComponents.get(fPosition).getNode()).directlyContains(node))
 | |
| //            {
 | |
| //                System.err.println("Bloody Murder!");
 | |
| //            }
 | |
|             fDirectlyContained = directlyContained;
 | |
|             
 | |
|             if (logger.isTraceEnabled())
 | |
|             {
 | |
|                 logger.trace("add: fDirectlyContained = "+directlyContained);
 | |
|             }
 | |
|         }
 | |
|         if (!write)
 | |
|         {
 | |
|             if (node.getType() == AVMNodeType.LAYERED_DIRECTORY)
 | |
|             {
 | |
|                 LayeredDirectoryNode oNode = (LayeredDirectoryNode)node;
 | |
|                 if (oNode.getPrimaryIndirection())
 | |
|                 {
 | |
|                     comp.setIndirection(oNode.getIndirection());
 | |
|                     comp.setIndirectionVersion(oNode.getIndirectionVersion());
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Pair<String, Integer> ind = computeIndirection(name);
 | |
|                     comp.setIndirection(ind.getFirst());
 | |
|                     comp.setIndirectionVersion(ind.getSecond());
 | |
|                 }
 | |
|                 fLayeredYet = true;
 | |
|                 // Record the first layer seen.
 | |
|                 if (fTopLayer == null)
 | |
|                 {
 | |
|                     fTopLayer = oNode;
 | |
|                     fTopLayerIndex = fPosition + 1;
 | |
|                 }
 | |
|                 fLowestLayerIndex = fPosition + 1;
 | |
|             }
 | |
|             fComponents.add(comp);
 | |
|             fPosition++;
 | |
|             return;
 | |
|         }
 | |
|         if (!node.getIsNew())
 | |
|         {
 | |
|             fNeedsCopying = true;
 | |
|             
 | |
|             if (logger.isTraceEnabled())
 | |
|             {
 | |
|                 logger.trace("add-cow: "+this+" ("+fPosition+") (not new)");
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (fPosition >= 0 && !fDirectlyContained)
 | |
|             {
 | |
|                 fNeedsCopying = true;
 | |
|                 
 | |
|                 if (logger.isTraceEnabled())
 | |
|                 {
 | |
|                     logger.trace("add: COW: "+this+" ("+fPosition+") (new, not directly contained)");
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         // Record various things if this is layered.
 | |
|         if (node.getType() == AVMNodeType.LAYERED_DIRECTORY)
 | |
|         {
 | |
|             LayeredDirectoryNode oNode = (LayeredDirectoryNode)node;
 | |
|             // Record the indirection path that should be used.
 | |
|             if (oNode.getPrimaryIndirection())
 | |
|             {
 | |
|                 comp.setIndirection(oNode.getIndirection());
 | |
|                 comp.setIndirectionVersion(-1);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 Pair<String, Integer> ind = computeIndirection(name);
 | |
|                 comp.setIndirection(ind.getFirst());
 | |
|                 comp.setIndirectionVersion(-1);
 | |
|             }
 | |
|             fLayeredYet = true;
 | |
|             // Record the first layer seen.
 | |
|             if (fTopLayer == null)
 | |
|             {
 | |
|                 fTopLayer = oNode;
 | |
|                 fTopLayerIndex = fPosition + 1;
 | |
|             }
 | |
|             fLowestLayerIndex = fPosition + 1;
 | |
|         }
 | |
|         // In a write context a plain directory contained in a layer will
 | |
|         // be copied so we will need to compute an indirection path.
 | |
|         else if (fLayeredYet)
 | |
|         {
 | |
|             Pair<String, Integer> ind = computeIndirection(name);
 | |
|             comp.setIndirection(ind.getFirst());
 | |
|             comp.setIndirectionVersion(-1);
 | |
|         }
 | |
|         fComponents.add(comp);
 | |
|         fPosition++;
 | |
|         // If we are in a write context do copy on write.
 | |
|         if (fNeedsCopying)
 | |
|         {
 | |
|             node = node.copy(this);
 | |
|             getCurrentLookupComponent().setNode(node);
 | |
|             if (fPosition == 0)
 | |
|             {
 | |
|                 // Inform the store of a new root.
 | |
|                 fAVMStore.setNewRoot((DirectoryNode)node);
 | |
|                 
 | |
|                 ((DirectoryNode)node).setIsRoot(true);
 | |
|                 AVMDAOs.Instance().fAVMNodeDAO.update(((DirectoryNode)node));
 | |
|                 AVMDAOs.Instance().fAVMStoreDAO.update(fAVMStore);
 | |
|                 return;
 | |
|             }
 | |
|             // Not the root. Check if we are the top layer and insert this into it's parent.
 | |
|             if (fPosition == fTopLayerIndex)
 | |
|             {
 | |
|                 fTopLayer = (LayeredDirectoryNode)node;
 | |
|             }
 | |
|             ((DirectoryNode)fComponents.get(fPosition - 1).getNode()).putChild(name, node);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * A helper for keeping track of indirection.
 | |
|      * @param name The name of the being added node.
 | |
|      * @return The indirection for the being added node.
 | |
|      */
 | |
|     private Pair<String, Integer> computeIndirection(String name)
 | |
|     {
 | |
|         String parentIndirection = getCurrentIndirection();
 | |
|         int parentIndirectionVersion = getCurrentIndirectionVersion();
 | |
|         if (parentIndirection.endsWith("/"))
 | |
|         {
 | |
|             return new Pair<String, Integer>(parentIndirection + name, parentIndirectionVersion);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             return new Pair<String, Integer>(parentIndirection + "/" + name, parentIndirectionVersion);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Return the parent node of the current node in the look up context or null if there is not one yet
 | |
|      * @return
 | |
|      */
 | |
|     public DirectoryNode getCurrentNodeDirectory()
 | |
|     {
 | |
|         int position = fPosition -1;
 | |
|         if( (position >= 0) && (position < fComponents.size()))
 | |
|         {
 | |
|            return ((DirectoryNode)fComponents.get(fPosition - 1).getNode());
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             return null;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private LookupComponent getCurrentLookupComponent()
 | |
|     {
 | |
|         return fComponents.get(fPosition);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the current node we're looking at.
 | |
|      * @return The current node.   
 | |
|      */
 | |
|     public AVMNode getCurrentNode()
 | |
|     {
 | |
|         return getCurrentLookupComponent().getNode();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Is the current path layered.
 | |
|      * @return Whether the current position in the path is layered.
 | |
|      */
 | |
|     public boolean isLayered()
 | |
|     {
 | |
|         return fLayeredYet;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Determine if a node is directly in this layer.
 | |
|      * @return Whether this node is directly in this layer.
 | |
|      */
 | |
|     public boolean isInThisLayer()
 | |
|     {
 | |
|         return fLayeredYet && fDirectlyContained;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the number of nodes.
 | |
|      * @return The number of nodes.
 | |
|      */
 | |
|     public int size()
 | |
|     {
 | |
|         return fComponents.size();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Calculate the indirection path at this node.
 | |
|      * @return The indirection path all the way down to the current node.
 | |
|      */
 | |
|     public String getIndirectionPath()
 | |
|     {
 | |
|         // The path is the underlying path of the lowest layer (in the path sense) 
 | |
|         // that is directly contained by the top layer and is a primary indirection node.
 | |
|         int pos = fLowestLayerIndex;
 | |
|         AVMNode node = fComponents.get(pos).getNode();
 | |
|         LayeredDirectoryNode oNode = null;
 | |
|         while (pos >= fTopLayerIndex && (node.getType() != AVMNodeType.LAYERED_DIRECTORY ||
 | |
|                (oNode = (LayeredDirectoryNode)node).getLayerID() != fTopLayer.getLayerID() ||
 | |
|                !oNode.getPrimaryIndirection()))
 | |
|         {
 | |
|             pos--;
 | |
|             node = fComponents.get(pos).getNode();
 | |
|         }
 | |
|         oNode = (LayeredDirectoryNode)node;
 | |
|         // We've found it.
 | |
|         StringBuilder builder = new StringBuilder();
 | |
|         builder.append(oNode.getIndirection());
 | |
|         for (int i = pos + 1; i <= fPosition; i++)
 | |
|         {
 | |
|             builder.append("/");
 | |
|             builder.append(fComponents.get(i).getName());
 | |
|         }
 | |
|         return builder.toString();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the computed indirection for the current node.
 | |
|      * @return The indirection.
 | |
|      */
 | |
|     public String getCurrentIndirection()
 | |
|     {
 | |
|         return getCurrentLookupComponent().getIndirection();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the computed indirection version for the current node.
 | |
|      * @return The indirection version.
 | |
|      */
 | |
|     public int getCurrentIndirectionVersion()
 | |
|     {
 | |
|         return getCurrentLookupComponent().getIndirectionVersion();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the topmost Layered directory node.  Topmost in the
 | |
|      * path lookup sense.
 | |
|      * @return The topmost layered directory node.
 | |
|      */
 | |
|     public LayeredDirectoryNode getTopLayer()
 | |
|     {
 | |
|         return fTopLayer;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the store that this path is in.
 | |
|      * @return The store.
 | |
|      */
 | |
|     public AVMStore getAVMStore()
 | |
|     {
 | |
|         return fAVMStore;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the path represented by this lookup.
 | |
|      * @return The canonical path for this lookup.
 | |
|      */
 | |
|     public String getRepresentedPath()
 | |
|     {
 | |
|         if (fComponents.size() == 1)
 | |
|         {
 | |
|             return AVMUtil.buildAVMPath(fStoreName, AVMUtil.AVM_PATH_SEPARATOR); // root;
 | |
|         }
 | |
|         StringBuilder builder = new StringBuilder();
 | |
|         builder.append(fStoreName);
 | |
|         builder.append(AVMUtil.AVM_STORE_SEPARATOR_CHAR);
 | |
|         int count = fComponents.size();
 | |
|         for (int i = 1; i < count; i++)
 | |
|         {
 | |
|             builder.append(AVMUtil.AVM_PATH_SEPARATOR_CHAR);
 | |
|             builder.append(fComponents.get(i).getName());
 | |
|         }
 | |
|         return builder.toString();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Gets the final name in the lookup.
 | |
|      * @return The final name in the lookup.
 | |
|      */
 | |
|     public String getBaseName()
 | |
|     {
 | |
|         return getCurrentLookupComponent().getName();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Set the final store the lookup occurred in.
 | |
|      * @param store The store to set.
 | |
|      */
 | |
|     public void setFinalStore(AVMStore store)
 | |
|     {
 | |
|         fFinalStore = store;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the final store traversed during lookup.
 | |
|      * @return The final store traversed.
 | |
|      */
 | |
|     public AVMStore getFinalStore()
 | |
|     {
 | |
|         return fFinalStore;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get whether the node looked up is directly contained from the
 | |
|      * original root.
 | |
|      * @return Whether the node looked up is directly contained.
 | |
|      */
 | |
|     public boolean getDirectlyContained()
 | |
|     {
 | |
|         return fDirectlyContained;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get the version id that this is a lookup for.
 | |
|      * @return The version id.
 | |
|      */
 | |
|     public int getVersion()
 | |
|     {
 | |
|         return fVersion;
 | |
|     }
 | |
|     
 | |
|     // for debug
 | |
|     @Override
 | |
|     public String toString()
 | |
|     {
 | |
|         StringBuilder builder = new StringBuilder();
 | |
|         
 | |
|         builder.append(getRepresentedPath());
 | |
|         builder.append(" [");
 | |
|         
 | |
|         for (int i = 0; i < fComponents.size(); i++)
 | |
|         {
 | |
|             builder.append(AVMUtil.AVM_PATH_SEPARATOR_CHAR);
 | |
|             builder.append(fComponents.get(i).toString());
 | |
|         }
 | |
|         
 | |
|         builder.append("]");
 | |
|         
 | |
|         return builder.toString();
 | |
|     }
 | |
| }
 |