mirror of
				https://github.com/Alfresco/alfresco-community-repo.git
				synced 2025-10-29 15:21:53 +00:00 
			
		
		
		
	12994: Merged V3.0 to V3.1
      12931: Merged V2.2 to V3.0
         12635: Fix for ETWOTWO-995: Diff performance degrades on large data sets
         12742: Fix for ETWOTWO-981: WCM - regression - revert fails (eg. for content publisher)
         12743: AVM - add missing tests to test suite & fix existing tests (including base setup)
         12759: AVM - build/test fix - follow-on to r12742
         12781: Fix PersonDAO - fixes AuthorityServiceTest which failed after adding AVMServicePermissionsTest
      12932: Merged V2.2 to V3.0   
         12763: Support for ETWOTWO-975: AVMDifference now implements Comparable<AVMDifference>
         12782: Fix for ETWOTWO-939: Content Contributor cannot edit their own items
         12809: Test fixes after r 12782
         12818: ETWOTWO-977 (Orphan Reaper) - removal of comment questioning cache interaction.
      12933: Merged V2.2 to V3.0
         12306: (record-only) Final set of XSS and HTML encoding fixes for ETWOONE-90 - already merged (see r12310)
      12934: Merged V2.2 to V3.0
         12311: (record-only) Fix for ETWOONE-389 - Current page number not always visible on the browse screen - already merged (see r12312)
      12935: Merged V2.2 to V3.0
         12320: (record-only) Fix for ETWOONE-87: Behavior of delete cascade - already merged (see r12324)
         12322: (record-only) Fix merge issue (marked as Do Not Merge - see CHK-5607)
      12936: Merged V2.2 to V3.0
         12775: (record-only) ETHREEOH-872: Editing Email-notify-rules fails w/ ClassCastException (back-port of r11966)
      12937: Merged V2.2 to V3.0
         12780: Fixed ETWOTWO-1003: DuplicateChildNameException not generated correctly (on Oracle)
         12820: Update to ETWOTWO-926 (WCM Form Inline callouts to Web Scripts)
         12825: Further ETWOTWO-926 update: provide compatibility with old token scheme as the original patch has already made its way into 3.0.1
         12850: ETWOTWO-975 - Show Conflicts in Modified Items List
         12938: Fix merge typo (follow on from r12931)
         12941: Fix merge typo (follow on from r12931)
   12998: Cleaned up svn:mergeinfo entries
   ___________________________________________________________________
   Modified: svn:mergeinfo
      Merged /alfresco/BRANCHES/V3.0:r12931-12938,12941
      Merged /alfresco/BRANCHES/V2.2:r12306,12311,12320,12322,12635,12742-12743,12759,12763,12775,12780-12782,12809,12818,12820,12825,12850
      Merged /alfresco/BRANCHES/V3.1:r12994,12998
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13549 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
		
	
		
			
				
	
	
		
			340 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			340 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C) 2005-2009 Alfresco Software Limited.
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU General Public License
 | |
|  * as published by the Free Software Foundation; either version 2
 | |
|  * of the License, or (at your option) any later version.
 | |
| 
 | |
|  * This program 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 General Public License for more details.
 | |
| 
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | |
| 
 | |
|  * As a special exception to the terms and conditions of version 2.0 of 
 | |
|  * the GPL, you may redistribute this Program in connection with Free/Libre 
 | |
|  * and Open Source Software ("FLOSS") applications as described in Alfresco's 
 | |
|  * FLOSS exception.  You should have recieved a copy of the text describing 
 | |
|  * the FLOSS exception, and it is also available here: 
 | |
|  * http://www.alfresco.com/legal/licensing"
 | |
|  */
 | |
| package org.alfresco.repo.avm;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.List;
 | |
| 
 | |
| import org.alfresco.repo.avm.util.SimplePath;
 | |
| import org.alfresco.repo.cache.SimpleCache;
 | |
| import org.alfresco.repo.security.permissions.AccessDeniedException;
 | |
| import org.alfresco.service.cmr.security.PermissionService;
 | |
| import org.alfresco.util.Pair;
 | |
| import org.apache.commons.logging.Log;
 | |
| import org.apache.commons.logging.LogFactory;
 | |
| import org.springframework.beans.factory.InitializingBean;
 | |
| 
 | |
| /**
 | |
|  * A Transactional? implementation of AVM path lookup cache
 | |
|  * 
 | |
|  * @author britt
 | |
|  */
 | |
| public class TransactionalLookupCache implements LookupCache, InitializingBean
 | |
| {
 | |
|     private static Log fgLogger = LogFactory.getLog(TransactionalLookupCache.class);
 | |
|     private static Log fgLoggerInit = LogFactory.getLog(TransactionalLookupCache.class.getName() + ".init");
 | |
|    
 | |
| 
 | |
|     /**
 | |
|      * The Map of of keys to lookups.
 | |
|      */
 | |
|     private SimpleCache<LookupKey, Lookup> fCache;
 | |
| 
 | |
|     /**
 | |
|      * Reference to the Node DAO.
 | |
|      */
 | |
|     private AVMNodeDAO fAVMNodeDAO;
 | |
| 
 | |
|     /**
 | |
|      * Reference to the Store DAO.
 | |
|      */
 | |
|     private AVMStoreDAO fAVMStoreDAO;
 | |
| 
 | |
|     /**
 | |
|      * Make one up.
 | |
|      */
 | |
|     public TransactionalLookupCache()
 | |
|     {
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Set up the node dao.
 | |
|      * @param dao The dao to set.
 | |
|      */
 | |
|     public void setAvmNodeDAO(AVMNodeDAO dao)
 | |
|     {
 | |
|         fAVMNodeDAO = dao;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Set the store dao.
 | |
|      * @param dao The dao to set.
 | |
|      */
 | |
|     public void setAvmStoreDAO(AVMStoreDAO dao)
 | |
|     {
 | |
|         fAVMStoreDAO = dao;
 | |
|     }
 | |
| 
 | |
|     public void setTransactionalCache(SimpleCache<LookupKey, Lookup> cache)
 | |
|     {
 | |
|         fCache = cache;
 | |
|     }
 | |
| 
 | |
|     /* (non-Javadoc)
 | |
|      * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 | |
|      */
 | |
|     public void afterPropertiesSet() throws Exception
 | |
|     {
 | |
|        if (fgLoggerInit.isDebugEnabled())
 | |
|           fgLoggerInit.debug("Transactional AVM lookup cache initialised");
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Lookup a path. Try to fulfill the request from the cache.
 | |
|      * @param store The AVMStore.
 | |
|      * @param version The versions.
 | |
|      * @param path The path we are looking up.
 | |
|      * @param write Whether this is a write lookup.
 | |
|      * @param includeDeleted
 | |
|      * @return
 | |
|      */
 | |
|     public Lookup lookup(AVMStore store, int version, SimplePath path,
 | |
|                          boolean write, boolean includeDeleted)
 | |
|     {
 | |
|         // Create a key object.
 | |
|         LookupKey key = new LookupKey(version, path, store.getName(), write, includeDeleted);
 | |
|         // Is it in the cache?
 | |
|         Lookup found = findInCache(key);
 | |
|         // TODO Testing.
 | |
|         // found = null;
 | |
|         if (found != null)
 | |
|         {
 | |
|             if (fgLogger.isDebugEnabled())
 | |
|             {
 | |
|                 fgLogger.debug("Cache Hit: " + key + ", " + found.getCurrentNode().getId());
 | |
|             }
 | |
|             return found;
 | |
|         }
 | |
|         // Make up a Lookup to hold the results.
 | |
|         if (path.size() == 0)
 | |
|         {
 | |
|             return null;
 | |
|         }
 | |
|         Lookup result = new Lookup(store, store.getName(), version);
 | |
|         // Grab the root node to start the lookup.
 | |
|         DirectoryNode dir = null;
 | |
|         // Versions less than 0 mean get current.
 | |
|         if (version < 0)
 | |
|         {
 | |
|             dir = store.getRoot();
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             VersionRoot vRoot = AVMDAOs.Instance().fVersionRootDAO.getByVersionID(store, version);
 | |
|             if (vRoot != null)
 | |
|             {
 | |
|                 dir = vRoot.getRoot();
 | |
|             }
 | |
| //            dir = fAVMNodeDAO.getAVMStoreRoot(store, version);
 | |
|         }
 | |
|         if (dir == null)
 | |
|         {
 | |
|             return null;
 | |
|         }
 | |
|         dir = (DirectoryNode)AVMNodeUnwrapper.Unwrap(dir);
 | |
|         // Add an entry for the root.
 | |
|         result.add(dir, "", true, write);
 | |
|         dir = (DirectoryNode)result.getCurrentNode();
 | |
|         if (path.size() == 1 && path.get(0).equals(""))
 | |
|         {
 | |
|             fCache.put(key, result);
 | |
|             return result;
 | |
|         }
 | |
|         // Now look up each path element in sequence up to one
 | |
|         // before the end.
 | |
|         for (int i = 0; i < path.size() - 1; i++)
 | |
|         {
 | |
|             if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN, result.getDirectlyContained()))
 | |
|             {
 | |
|                 throw new AccessDeniedException("Not allowed to read children: " + path.get(i));
 | |
|             }
 | |
|             Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(i), includeDeleted);
 | |
|             if (child == null)
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
|             // Every element that is not the last needs to be a directory.
 | |
|             if (child.getFirst().getType() != AVMNodeType.PLAIN_DIRECTORY &&
 | |
|                 child.getFirst().getType() != AVMNodeType.LAYERED_DIRECTORY)
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
|             result.add(child.getFirst(), path.get(i), child.getSecond(), write);
 | |
|             dir = (DirectoryNode)result.getCurrentNode();
 | |
|         }
 | |
|         // Now look up the last element.
 | |
|         if (!AVMRepository.GetInstance().can(null, dir, PermissionService.READ_CHILDREN, result.getDirectlyContained()))
 | |
|         {
 | |
|             throw new AccessDeniedException("Not allowed to read children: " + path.get(path.size() - 1));
 | |
|         }
 | |
|         Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(path.size() - 1),
 | |
|                                         includeDeleted);
 | |
|         if (child == null)
 | |
|         {
 | |
|             return null;
 | |
|         }
 | |
|         result.add(child.getFirst(), path.get(path.size() - 1), child.getSecond(), write);
 | |
|         fCache.put(key, result);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Try to find a match in the cache.
 | |
|      * @param key The lookup key.
 | |
|      * @return A valid for this session Lookup or null if not found.
 | |
|      */
 | |
|     private synchronized Lookup findInCache(LookupKey key)
 | |
|     {
 | |
|         Lookup found = fCache.get(key);
 | |
|         if (found != null)
 | |
|         {
 | |
|             // Get a freshened Lookup.
 | |
|             Lookup result = new Lookup(found, fAVMNodeDAO, fAVMStoreDAO);
 | |
|             // Check that nothing horrible is wrong.  This should
 | |
|             // be assertible, but I'll leave the check in for now.
 | |
|             if (!result.isValid())
 | |
|             {
 | |
|                 fgLogger.error("Invalid entry in cache: " + key);
 | |
|                 return null;
 | |
|             }
 | |
|             return result;
 | |
|         }
 | |
|         // Alternatively for a read lookup a write can match.
 | |
|         if (!key.isWrite())
 | |
|         {
 | |
|             // Make a copy of the key and set it to 'write'
 | |
|             LookupKey newKey = new LookupKey(key);
 | |
|             newKey.setWrite(true);
 | |
|             found = fCache.get(newKey);
 | |
|             if (found != null)
 | |
|             {
 | |
|                 // We found it. Make a freshened copy of the Lookup.
 | |
|                 Lookup result = new Lookup(found, fAVMNodeDAO, fAVMStoreDAO);
 | |
|                 // Check for badness.  This should be assertible but I'll
 | |
|                 // leave the check in for now.
 | |
|                 if (!result.isValid())
 | |
|                 {
 | |
|                     fgLogger.error("Invalid entry in cache: " + newKey);
 | |
|                     return null;
 | |
|                 }
 | |
|                 return result;
 | |
|             }
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     // Following are the cache invalidation calls.
 | |
| 
 | |
|     /**
 | |
|      * Called when a simple write operation occurs.  This
 | |
|      * invalidates all read lookups and all layered lookups.
 | |
|      */
 | |
|     public synchronized void onWrite(String storeName)
 | |
|     {
 | |
|         // Invalidate if it's a read lookup in the store, or
 | |
|         // any read lookup is it's layered.
 | |
|         List<LookupKey> keys = new ArrayList<LookupKey>();
 | |
|         for (LookupKey key : fCache.getKeys())
 | |
|         {
 | |
|             keys.add(key);
 | |
|         }
 | |
|         for (LookupKey key : keys)
 | |
|         {
 | |
|             Lookup value = fCache.get(key);
 | |
|             if ((key.getStoreName().equals(storeName) &&
 | |
|                 !key.isWrite()) || value == null ||
 | |
|                 (!key.isWrite() && value.isLayered()))
 | |
|             {
 | |
|                 if (fgLogger.isDebugEnabled())
 | |
|                 {
 | |
|                     fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
 | |
|                 }
 | |
|                 fCache.remove(key);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Called when a delete has occurred in a store.  This invalidates both
 | |
|      * reads and write lookups in that store.
 | |
|      */
 | |
|     public synchronized void onDelete(String storeName)
 | |
|     {
 | |
|         // Invalidate any entries that are in the store or are layered lookups.
 | |
|         List<LookupKey> keys = new ArrayList<LookupKey>();
 | |
|         for (LookupKey key : fCache.getKeys())
 | |
|         {
 | |
|             keys.add(key);
 | |
|         }
 | |
|         for (LookupKey key : keys)
 | |
|         {
 | |
|             Lookup value = fCache.get(key);
 | |
|             if (key.getStoreName().equals(storeName) ||
 | |
|                 value == null || value.isLayered())
 | |
|             {
 | |
|                 if (fgLogger.isDebugEnabled())
 | |
|                 {
 | |
|                     fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
 | |
|                 }
 | |
|                 fCache.remove(key);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Called when a snapshot occurs in a store.  This invalidates write
 | |
|      * lookups.  Read lookups stay untouched.
 | |
|      */
 | |
|     public synchronized void onSnapshot(String storeName)
 | |
|     {
 | |
|         // Invalidate any entries that in the store and writes or
 | |
|         // any layered lookups.
 | |
|         List<LookupKey> keys = new ArrayList<LookupKey>();
 | |
|         for (LookupKey key : fCache.getKeys())
 | |
|         {
 | |
|             keys.add(key);
 | |
|         }
 | |
|         for (LookupKey key : keys)
 | |
|         {
 | |
|             Lookup value = fCache.get(key);
 | |
|             if ((key.getStoreName().equals(storeName) &&
 | |
|                  key.isWrite()) ||
 | |
|                 value == null || value.isLayered())
 | |
|             {
 | |
|                 if (fgLogger.isDebugEnabled())
 | |
|                 {
 | |
|                     fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
 | |
|                 }
 | |
|                 fCache.remove(key);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public synchronized void reset()
 | |
|     {
 | |
|         fCache.clear();
 | |
|     }
 | |
| }
 |