Merged PATCHES/V3.2.r to HEAD

19546: (RECORD ONLY) Merged V3.2 to PATCHES/V3.2.r
      19432: Merged V3.1 to V3.2
         19427: Merged V3.0 to V3.1
            19423: Merged V2.2 to V3.0
               19391: Fix for ALF-2076: AUTO does not work if a document has been added and deleted since the index backup
               19419: V2.2 Build Fix
               19421: Fix for ALF-2076: AUTO does not work if a document has been added and deleted since the index backup
      19463: Merged V3.1 to V3.2
         19459: Merged V3.0 to V3.1
            19457: Merged V2.2 to V3.0
               19449: Addition Fix for ALF-2076: AUTO does not work if a document has been added and deleted since the index backup
      19493 Merged V3.1 to V3.2
         19471: Build fix after changes for ALF-2076 were merged forward. Index checker correctly understands INDETERMINATE state of indexed transactions
   19547: (RECORD ONLY) Incremented version label
   19555: (RECORD ONLY) Merged V3.2 to PATCHES/V3.2.r
      19552: Merged V3.1 to V3.2
         19551: Further fix after changes for ALF-2076 were merged forward. Final fix to check for InIndex.No
   19566: (RECORD ONLY) Merged V3.2 to PATCHES/V3.2.r
      19539: Merged HEAD to V3.2
         19538: ALF-2076: Build fix - fix build speed
   19802: (RECORD ONLY) ALF-2382, ALF-2383: Merged V3.2 to PATCHES/V3.2.r
      19647: ALF-2231: Merged DEV/BELARUS/V2.2-2009_12_01 to V3.2 
         17704: ENH-681: alfresco webdav does not respect webdav locks 
      19624: ALF-2231: Merged DEV/BELARUS/V2.2-2009_12_01 to V3.2
         17704: ENH-681: alfresco webdav does not respect webdav locks
      19623: ALF-1890: Correction to previous checkin to allow defaulting of request body charset
      19617: ALF-1890: Improvements to make ALL WebDAV methods retryable
         - Solution from PutMethod promoted to request wrapper that will handle ALL calls to getInputStream and getReader
      19614: ALF-1890: Merged V2.2 to V3.2
         17709: Merged DEV_TEMPORARY to V2.2
            17700: ETWOTWO-1393: concurrent writes to webdav lead to data loss (0kb resulting file)
         19613: Merged DEV/BELARUS/V2.2-2010_02_03 to V2.2
            19157: ALF-1890: concurrent writes to webdav lead to data loss (0kb resulting file)
   19803: ALF-558: File servers (CIFS / FTP / NFS) can now handle concurrent write operations on Alfresco repository
      - ContentDiskDriver / AVMDiskDriver now use retrying transactions for write operations
      - Disable EagerContentStoreCleaner on ContentDiskDriver / AVMDiskDriver closeFile() operations so that they may be retried after rollback (Sony zero byte problem)
      - Allow manual association of AVM ContentData with nodes so that closeFile() may be retried
      - Propagation of new argument through AVM interfaces
   19804: (RECORD ONLY) Merged PATCHES/V3.2.0 to PATCHES/V3.2.r
      Merged HEAD to V3.2.0
         19786: Refactor of previous test fix. I have pushed down the OOo-specific parts of the change from AbstractContentTransformerTest to OpenOfficeContentTransformerTest leaving an extension point in the base class should other transformations need to be excluded in the future.
         19785: Fix for failing test OpenOfficeContentTransformerTest.testAllConversions.
            Various OOo-related transformations are returned as available but fail on our test server with OOo on it.
            Pending further work on these failings, I am disabling those transformations in test code whilst leaving them available in the product code. This is because in the wild a different OOo version may succeed with these transformations.
            I had previously explicitly disabled 3 transformations in the product and I am moving that restriction from product to test code for the same reason.
         19707: Return value from isTransformationBlocked was inverted. Fixed now.
         19705: Refinement of previous check-in re OOo transformations.
            I have pulled up the code that handles blocked transformations into a superclass so that the JodConverter-based transformer worker can inherit the same list of blocked transformations. To reiterate, blocked transformations are those that the OOo integration code believes should work but which are broken in practice. These are blocked by the transformers and will always be unavailable regardless of the OOo connection state.
         19702: Fix for HEAD builds running on panda build server.
            OOo was recently installed on panda which has activated various OOo-related transformations/extractions in the test code.
            It appears that OOo does not support some transformations from Office 97 to Office 2007. Specifically doc to docx and xls to xlsx. These transformations have now been marked as unavailable.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20004 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2010-04-27 10:57:47 +00:00
parent 9a7df0ed38
commit 051508c21d
24 changed files with 1464 additions and 1111 deletions

View File

@@ -14,13 +14,22 @@
* 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/>.
* 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.filesys.repo.desk;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.alfresco.filesys.alfresco.DesktopAction;
import org.alfresco.filesys.alfresco.DesktopParams;
@@ -31,10 +40,14 @@ import org.alfresco.jlan.server.filesys.FileStatus;
import org.alfresco.jlan.server.filesys.NotifyChange;
import org.alfresco.jlan.server.filesys.cache.FileState;
import org.alfresco.jlan.server.filesys.cache.FileStateCache;
import org.alfresco.jlan.smb.server.notify.NotifyChangeHandler;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.coci.CheckOutCheckInService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.util.Pair;
/**
* Check In/Out Desktop Action Class
@@ -45,10 +58,6 @@ import org.alfresco.service.cmr.repository.NodeService;
*/
public class CheckInOutDesktopAction extends DesktopAction {
// Check in/out service
private CheckOutCheckInService m_checkInOutService;
/**
* Class constructor
*/
@@ -74,109 +83,124 @@ public class CheckInOutDesktopAction extends DesktopAction {
* @return DesktopResponse
*/
@Override
public DesktopResponse runAction(DesktopParams params) {
public DesktopResponse runAction(final DesktopParams params) {
// Check if there are any files/folders to process
if ( params.numberOfTargetNodes() == 0)
return new DesktopResponse(StsSuccess);
// Get required services
NodeService nodeService = getServiceRegistry().getNodeService();
// Start a transaction
params.getDriver().beginWriteTransaction( params.getSession());
// Process the list of target nodes
DesktopResponse response = new DesktopResponse(StsSuccess);
for ( int idx = 0; idx < params.numberOfTargetNodes(); idx++)
class WriteTxn implements Callable<DesktopResponse>
{
// Get the current target node
DesktopTarget target = params.getTarget(idx);
// Check if the node is a working copy
if ( nodeService.hasAspect( target.getNode(), ContentModel.ASPECT_WORKING_COPY))
private List<Pair<Integer, String>> fileChanges;
/* (non-Javadoc)
* @see java.util.concurrent.Callable#call()
*/
public DesktopResponse call() throws Exception
{
try
// Initialize / reset the list of file changes
fileChanges = new LinkedList<Pair<Integer,String>>();
// Get required services
ServiceRegistry serviceRegistry = getServiceRegistry();
NodeService nodeService = serviceRegistry.getNodeService();
CheckOutCheckInService checkOutCheckInService = serviceRegistry.getCheckOutCheckInService();
// Process the list of target nodes
DesktopResponse response = new DesktopResponse(StsSuccess);
for ( int idx = 0; idx < params.numberOfTargetNodes(); idx++)
{
// Check in the file, pass an empty version properties so that versionable nodes create a new version
// Get the current target node
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
getCheckInOutService().checkin( target.getNode(), versionProperties, null, false);
// Check if there are any file/directory change notify requests active
if ( getContext().hasFileServerNotifications()) {
// Build the relative path to the checked in file
String fileName = null;
if ( target.getTarget().startsWith(FileName.DOS_SEPERATOR_STR))
DesktopTarget target = params.getTarget(idx);
// Check if the node is a working copy
if ( nodeService.hasAspect( target.getNode(), ContentModel.ASPECT_WORKING_COPY))
{
try
{
// Path is already relative to filesystem root
fileName = target.getTarget();
// Check in the file, pass an empty version properties so that veriosnable nodes create a new version
Map<String, Serializable> versionProperties = new HashMap<String, Serializable>();
checkOutCheckInService.checkin( target.getNode(), versionProperties, null, false);
// Check if there are any file/directory change notify requests active
if ( getContext().hasFileServerNotifications()) {
// Build the relative path to the checked in file
String fileName = null;
if ( target.getTarget().startsWith(FileName.DOS_SEPERATOR_STR))
{
// Path is already relative to filesystem root
fileName = target.getTarget();
}
else
{
// Build a root relative path for the file
fileName = FileName.buildPath( params.getFolder().getFullName(), null, target.getTarget(), FileName.DOS_SEPERATOR);
}
// Queue a file deleted change notification
fileChanges.add(new Pair<Integer, String>(NotifyChange.ActionRemoved, fileName));
}
}
else
catch (Exception ex)
{
// Build a root relative path for the file
fileName = FileName.buildPath( params.getFolder().getFullName(), null, target.getTarget(), FileName.DOS_SEPERATOR);
// If this is a 'retryable' exception, pass it on
if (RetryingTransactionHelper.extractRetryCause(ex) != null)
{
throw ex;
}
// Dump the error
if ( logger.isErrorEnabled())
logger.error("Desktop action error", ex);
// Return an error status and message
response.setStatus(StsError, "Checkin failed for " + target.getTarget() + ", " + ex.getMessage());
}
// Queue a file deleted change notification
getContext().getChangeHandler().notifyFileChanged(NotifyChange.ActionRemoved, fileName);
}
}
catch (Exception ex)
{
// Dump the error
if ( logger.isErrorEnabled())
logger.error("Desktop action error", ex);
// Return an error status and message
response.setStatus(StsError, "Checkin failed for " + target.getTarget() + ", " + ex.getMessage());
}
}
else
{
try
{
// Check if the file is locked
if ( nodeService.hasAspect( target.getNode(), ContentModel.ASPECT_LOCKABLE)) {
// Get the lock type
String lockTypeStr = (String) nodeService.getProperty( target.getNode(), ContentModel.PROP_LOCK_TYPE);
if ( lockTypeStr != null) {
response.setStatus(StsError, "Checkout failed, file is locked");
return response;
}
}
// Check out the file
NodeRef workingCopyNode = getCheckInOutService().checkout( target.getNode());
else
{
try
{
// Check if the file is locked
if ( nodeService.hasAspect( target.getNode(), ContentModel.ASPECT_LOCKABLE)) {
// Get the lock type
String lockTypeStr = (String) nodeService.getProperty( target.getNode(), ContentModel.PROP_LOCK_TYPE);
if ( lockTypeStr != null) {
response.setStatus(StsError, "Checkout failed, file is locked");
return response;
}
}
// Check out the file
NodeRef workingCopyNode = checkOutCheckInService.checkout( target.getNode());
// Get the working copy file name
String workingCopyName = (String) nodeService.getProperty( workingCopyNode, ContentModel.PROP_NAME);
// Check out was successful, pack the working copy name
// Get the working copy file name
String workingCopyName = (String) nodeService.getProperty( workingCopyNode, ContentModel.PROP_NAME);
// Check out was successful, pack the working copy name
response.setStatus(StsSuccess, "Checked out working copy " + workingCopyName);
response.setStatus(StsSuccess, "Checked out working copy " + workingCopyName);
// Build the relative path to the checked out file
String fileName = FileName.buildPath( params.getFolder().getFullName(), null, workingCopyName, FileName.DOS_SEPERATOR);
@@ -193,50 +217,63 @@ public class CheckInOutDesktopAction extends DesktopAction {
fstate.setFileStatus( FileStatus.FileExists);
}
// Check if there are any file/directory change notify requests active
// Check if there are any file/directory change notify requests active
if ( getContext().hasChangeHandler()) {
if ( getContext().hasChangeHandler()) {
// Queue a file added change notification
getContext().getChangeHandler().notifyFileChanged(NotifyChange.ActionAdded, fileName);
// Build the relative path to the checked in file
// Queue a file added change notification
fileChanges.add(new Pair<Integer, String>(NotifyChange.ActionAdded, fileName));
}
}
catch (Exception ex)
{
// If this is a 'retryable' exception, pass it on
if (RetryingTransactionHelper.extractRetryCause(ex) != null)
{
throw ex;
}
// Dump the error
if ( logger.isErrorEnabled())
logger.error("Desktop action error", ex);
// Return an error status and message
response.setStatus(StsError, "Failed to checkout " + target.getTarget() + ", " + ex.getMessage());
}
}
}
catch (Exception ex)
// Return a success status for now
return response;
}
/**
* Queue the file change notifications resulting from this successfully processed transaction.
*/
public void notifyChanges()
{
NotifyChangeHandler notifyChangeHandler = getContext().getChangeHandler();
for (Pair<Integer, String> fileChange : fileChanges)
{
// Dump the error
if ( logger.isErrorEnabled())
logger.error("Desktop action error", ex);
// Return an error status and message
response.setStatus(StsError, "Failed to checkout " + target.getTarget() + ", " + ex.getMessage());
notifyChangeHandler.notifyFileChanged(fileChange.getFirst(), fileChange.getSecond());
}
}
}
// Return a success status for now
// Process the transaction
WriteTxn callback = new WriteTxn();
DesktopResponse response = params.getDriver().doInWriteTransaction(params.getSession(), callback);
// Queue file change notifications
callback.notifyChanges();
return response;
}
/**
* Get the check in/out service
*
* @return CheckOutCheckInService
*/
protected final CheckOutCheckInService getCheckInOutService()
{
// Check if the service has been cached
if ( m_checkInOutService == null)
{
m_checkInOutService = getServiceRegistry().getCheckOutCheckInService();
}
// Return the check in/out service
return m_checkInOutService;
}
return response;
}
}