Files
alfresco-community-repo/source/java/org/alfresco/web/bean/clipboard/ClipboardBean.java
Dave Ward 5a4a040e6c Merged V4.1-BUG-FIX to HEAD
40605: ALF-15273: Merged PATCHES/V4.0.1 to V4.1-BUG-FIX
      40132: ALF-15376:  Activiti schema updates fail when hibernate.default_schema is set with ORA-00942. 
         - Corrected schema case to uppercase when database is Oracle.
      40235: ALF-15367: Reverse merged the following revisions because the fix is deemed not robust enough.
         40132: ALF-15376:  Activiti schema updates fail when hibernate.default_schema is set with ORA-00942. 
            - Corrected schema case to uppercase when database is Oracle.
         40041: ALF-15376: Merged V4.1-BUG-FIX to PATCHES/V4.0.1
            39969: Merged DEV/BELARUS-V4.1-BUG-FIX-2012_07_09 to V4.1-BUG-FIX:
               ALF-15273 : Activiti schema updates fail when hibernate.default_schema is set with ORA-00942. The Activiti database is now correctly initialized with the correct "hibernate.default_schema"
      40470: ALF-15376: how to debug the creation of Activiti tables (ACT_) when upgrading to 4.X
         - added more logging to Activiti schema creation
      40471: ALF-15376: Activiti schema updates fail when hibernate.default_schema is set with ORA-00942
         - Ignore hibernate.default_schema and determine default schema from the Connection DatabaseMetaData
         - Provided the Activiti schema initializer with the default schema information
         - Provided countAppliedPatches() with default schema information
      40501: ALF-15376: Improved webapp logging.properties to use a console handler so that it doesn't suppress absolutely everything and we can selectively turn on logging!
   40608: Fix for ALF-4274 - JSF - Paste action does not work when browse.jsp is overrided
   40611: GERMAN: Translation updates based on EN r40604
   40612: SPANISH: Translation updates based on EN r40604
   40613: FRENCH: Translation updates based on EN r40604
   40614: ITALIAN: Translation updates based on EN r40604
   40615: JAPANESE: Translation updates based on EN r40604
   40616: DUTCH: Translation updates based on EN r40604
   40617: CHINESE: Translation updates based on EN r40604
   40629: ALF-15321: upgrade Activiti to fix logging
   40632: Fix for ALF-15487 Search not working for queries containing 3-digit versions
   Fix for ALF-15356 SOLR doesn't support searching by cm:name of file with underscore and dots
   40655: Fix for ALF-14752 - Collapse Links part at the WCM details page lead to error.
   40662: Eclipse classpath fixes
   40663: Merged DEV to V4.1-BUG-FIX
      40661: ALF-15318 (part 2): It's possible to log in by disabled user (NTLM with SSO in a clustered env)
         The onValidateFailed() methods were moved to BaseSSOAuthenticationFilter to response with a 401 for a disabled user.
   40665: ALF-15448: Merged V3.4-BUG-FIX (3.4.11) to V4.1-BUG-FIX (4.1.1)
      40664: ALF-15578 CLONE 3.4.11: LibreOffice 3.6 startup on Mac fails 
   40685: Merged PATCHES/V4.0.2 to V4.1-BUG-FIX
      39274: Merged DEV to V4.0.2 (4.0.2.4)
         << Unable to merge code as supplied as it introduced a change to a public API, which would break alfresco.log
            if the RM AMP was installed See RM-452 >>
         39166: ALF-15583 / ALF-14584: autoVersionOnUpdateProps=true does not increment the version label after checkout/checkin
            'VersionableAspectTest' has been modified in accordance with concept: several modifications of node in
      	  a single transaction are interpreted as a single version. Each operation in the test which should provide
      	  a new version have been made atomic
         39089: ALF-15583 / ALF-14584: autoVersionOnUpdateProps=true does not increment the version label after checkout/checkin
            Check of lock has been corrected since 'cm:lockable' aspect doesn't indicate lock state:
            - 'LockService' service has been extended with 'isLocked(NodRef)' method which returns 'true' if document
              is locked and current user is not an owner of the lock;
            - new 'VersionableAspectTest' has been added to test the use-case described in the issue and to test
              whether 'VersionableAspect' changes version label of a locked document
      39369: ALF-15583 / ALF-14584 autoVersionOnUpdateProps=true does not increment the version label after checkout/checkin
         - Test failures: A READ_ONLY lock was being set because we are adding a versionable aspect. This resulted in an
           Exception when attempting to update the version. Change made to the isLocked method (now called isLockedOrReadOnly)
           to reflect that a node is locked even for the owner and the lock type is not a WRITE lock.
      39939: ALF-15584 / ALF-15001: Gracefully handle stale NodeRefs in query results in DMDiscoveryServicePort
      - SOLR makes this more likely to occur
      40455: ALF-15585 / ALF-15383: Long-running Feed Cleaner
       - Part 1: Limit problems caused by missing indexes
         - Remove all count calls
         - Remove logic requiring calls to SiteService to list all sites
         - Added in an ID range limit to act as a hard-stop to entry growth (set to 1M)
       - TODO: use JobLockService
      40461: ALF-15585 / ALF-15383: Long running Feed Cleaner 
       - Part 2: Added JobLockService usage to ensure only one instance runs at a time
      40463: ALF-15585 / ALF-15383: Long running Feed Cleaner
       - A bit more trace and debug
      40526: ALF-15586: Fixed ALF-15540: CMIS: Synchronized block in service interceptor
      40574: ALF-15585 / ALF-15383: Long running Feed Cleaner
      - Fix MySQL variant of activities-common-SqlMap
      40579: ALF-15585: Fix fallout from rev 40455: ALF-15383: Long-running Feed Cleaner
       - MySQL dialect was duplicating ALL SQL statements
       - Split 'large' SQL selects into activities-select-SqlMap.xml containing 7 statements that are all overridden for MySQL
       - Fixed split in common file between different types of statements
      40588: ALF-15587 / ALF-15385: Merged V3.4-BUG-FIX to PATCHES/V4.0.2 (Lost revision)
         28830: ALF-7622 Refactored JScriptWorkflowTask. Now when setProperties() is called it properly updates the WorkflowTask properties via the WorflowService.updateTask() method.
   40687: Merged V3.4-BUG-FIX to V4.1-BUG-FIX
      40599: ALF-15567: Merged PATCHES/V3.4.10 to V3.4-BUG-FIX
         40511: ALF-12008: Merged DEV to PATCHES/V3.4.10
            Due to Windows Explorer's URL concatenation behaviour, we must present links as shortcuts to the real URL, rather than direct hrefs.
            This is at least consistent with the way the CIFS server handles links. See org.alfresco.filesys.repo.ContentDiskDriver.openFile().
         40518: ALF-12008: Fixed compilation error


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@40691 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2012-08-21 16:31:48 +00:00

374 lines
13 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.web.bean.clipboard;
import java.io.Serializable;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.web.app.Application;
import org.alfresco.web.app.context.UIContextService;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.alfresco.web.ui.common.component.UIActionLink;
import org.alfresco.web.ui.repo.component.shelf.UIClipboardShelfItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean backing the Clipboard shelf functionality.
* <p>
* The clipboard bean is responsible for processing Cut/Copy requests to the clipboard
* and for executing the various Paste calls available to the user.
*
* @author Kevin Roast
*/
public class ClipboardBean implements Serializable
{
private static final long serialVersionUID = -6299320341615099651L;
private static Log logger = LogFactory.getLog(ClipboardBean.class);
/** I18N messages */
private static final String MSG_ERROR_PASTE = "error_paste";
private static final String MSG_VIEW_FOR_PASTE_WARN = "not_suitable_view_for_paste_warn";
/** Current state of the clipboard items */
private List<ClipboardItem> items = new ArrayList<ClipboardItem>(4);
transient private NodeService nodeService;
private List<String> customPasteViewIds;
// ------------------------------------------------------------------------------
// Bean property getters and setters
/**
* @return Returns a list representing the items on the user clipboard.
*/
public List<ClipboardItem> getItems()
{
return this.items;
}
/**
* @param items List representing the items on the user clipboard.
*/
public void setItems(List<ClipboardItem> items)
{
this.items = items;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
private NodeService getNodeService()
{
if (nodeService == null)
{
nodeService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getNodeService();
}
return nodeService;
}
public void setCustomPasteViewIds(List<String> customPasteViewIds)
{
this.customPasteViewIds = customPasteViewIds;
}
public List<String> getCustomPasteViewIds()
{
return customPasteViewIds;
}
// ------------------------------------------------------------------------------
// Navigation action event handlers
/**
* Action handler called to add a node to the clipboard for a Copy operation
*/
public void copyNode(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String ref = params.get("ref");
if (ref != null && ref.length() != 0)
{
addClipboardNode(new NodeRef(ref), null, ClipboardStatus.COPY);
}
}
/**
* Action handler called to add a node to the clipboard for a Cut operation
*/
public void cutNode(ActionEvent event)
{
UIActionLink link = (UIActionLink)event.getComponent();
Map<String, String> params = link.getParameterMap();
String ref = params.get("ref");
String parent = params.get("parent");
if (ref != null && ref.length() != 0)
{
NodeRef parentNodeRef = null;
if (parent != null)
{
parentNodeRef = new NodeRef(Repository.getStoreRef(), parent);
// ALF-8885 fix, if copied node is the same as parent node we should use null.
// Primary parent will be used later in FileFolderService#moveOrCopy method
if (parentNodeRef.toString().equals(ref))
{
parentNodeRef = null;
}
}
addClipboardNode(new NodeRef(ref), parentNodeRef, ClipboardStatus.CUT);
}
}
/**
* Action handler call from the browse screen to Paste All clipboard items into the current Space
*/
public void pasteAll(ActionEvent event)
{
performPasteItems(-1, UIClipboardShelfItem.ACTION_PASTE_ALL);
}
/**
* Action handler called to paste one or all items from the clipboard
*/
public void pasteItem(ActionEvent event)
{
UIClipboardShelfItem.ClipboardEvent clipEvent = (UIClipboardShelfItem.ClipboardEvent)event;
int index = clipEvent.Index;
if (index >= this.items.size())
{
throw new IllegalStateException("Clipboard attempting paste a non existent item index: " + index);
}
performPasteItems(index, clipEvent.Action);
}
/**
* Perform a paste for the specified clipboard item(s)
*
* @param index of clipboard item to paste or -1 for all
* @param action the clipboard action to perform (see UIClipboardShelfItem)
*/
private void performPasteItems(int index, int action)
{
FacesContext context = FacesContext.getCurrentInstance();
boolean toClear = false;
try
{
if (index == -1)
{
// paste all
List<ClipboardItem> toRemove = new ArrayList<ClipboardItem>();
for (ClipboardItem item : this.items)
{
if (!getNodeService().exists(item.getNodeRef()))
{
toRemove.add(item);
toClear = true;
continue;
}
if (performClipboardOperation(item, action) == true)
{
// if cut operation then remove item from the clipboard
if (item.getMode() == ClipboardStatus.CUT)
{
// remember which items to remove.
toRemove.add(item);
}
toClear = true;
}
}
// clear the clipboard after a paste all
if (toClear)
{
if (Application.getClientConfig(context).isPasteAllAndClearEnabled())
{
this.items.clear();
}
else if (toRemove.size() > 0)
{
// remove the items that were cut above
for (ClipboardItem item : toRemove)
{
this.items.remove(item);
}
}
}
}
else
{
// single paste operation
ClipboardItem item = this.items.get(index);
if (performClipboardOperation(item, action) == true)
{
// if cut operation then remove item from the clipboard
if (item.getMode() == ClipboardStatus.CUT)
{
this.items.remove(index);
}
}
}
// refresh UI on success
UIContextService.getInstance(context).notifyBeans();
}
catch (Throwable err)
{
Utils.addErrorMessage(Application.getMessage(context, MSG_ERROR_PASTE) + err.getMessage(), err);
}
}
/**
* Perform the operation for the specified clipboard item
*
* @param item the ClipboardItem
* @param action the clipboard action to perform (see UIClipboardShelfItem)
*
* @return true on successful operation
*/
private boolean performClipboardOperation(ClipboardItem item, int action)
throws Throwable
{
boolean success = false;
FacesContext fc = FacesContext.getCurrentInstance();
// test the current JSF view to see if the clipboard item can paste to it
if (logger.isDebugEnabled())
logger.debug("Clipboard destination View Id: " + fc.getViewRoot().getViewId());
if (item.getMode() == ClipboardStatus.CUT)
{
if (item.canMoveToViewId(fc.getViewRoot().getViewId()) == true)
{
success = item.paste(fc, fc.getViewRoot().getViewId(), action);
}
else
{
if (Application.getClientConfig(fc).isClipboardStatusVisible())
{
String pattern = Application.getMessage(fc, MSG_VIEW_FOR_PASTE_WARN);
String msg = MessageFormat.format(pattern, item.getName());
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_WARN, msg, msg);
fc.addMessage(null, facesMsg);
}
// we cannot support this view as a Move paste location
if (logger.isDebugEnabled())
logger.debug("Clipboard Item: " + item.getNodeRef() + " not suitable for Move paste to current View Id.");
}
}
else if (item.getMode() == ClipboardStatus.COPY)
{
if (item.canCopyToViewId(fc.getViewRoot().getViewId()) == true)
{
success = item.paste(fc, fc.getViewRoot().getViewId(), action);
}
else
{
if (Application.getClientConfig(fc).isClipboardStatusVisible())
{
String pattern = Application.getMessage(fc, MSG_VIEW_FOR_PASTE_WARN);
String msg = MessageFormat.format(pattern, item.getName());
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_WARN, msg, msg);
fc.addMessage(null, facesMsg);
}
// we cannot support this view as a Copy paste location
if (logger.isDebugEnabled())
logger.debug("Clipboard Item: " + item.getNodeRef() + " not suitable for Copy paste to current View Id.");
}
}
return success;
}
/**
* Add a clipboard node to the clipboard ready for a cut/copy operation
*
* @param ref NodeRef of the item for the operation
* @param parent Parent of the item for the operation
* @param mode ClipboardStatus for the operation
*/
private void addClipboardNode(NodeRef ref, NodeRef parent, ClipboardStatus mode)
{
// construct item based on store protocol
ClipboardItem item = null;
if (StoreRef.PROTOCOL_WORKSPACE.equals(ref.getStoreRef().getProtocol()))
{
item = new WorkspaceClipboardItem(ref, parent, mode, customPasteViewIds);
}
else if (StoreRef.PROTOCOL_AVM.equals(ref.getStoreRef().getProtocol()))
{
item = new AVMClipboardItem(ref, mode, customPasteViewIds);
}
else
{
logger.warn("Unable to add item to clipboard - unknown store protocol: " + ref.getStoreRef().getProtocol());
}
if (item != null)
{
// check for duplicates first
boolean foundDuplicate = false;
for (int i=0; i<items.size(); i++)
{
if (items.get(i).equals(item))
{
// found a duplicate replace with new instance as copy mode may have changed
items.set(i, item);
foundDuplicate = true;
break;
}
}
// if duplicate not found, then append to list
if (foundDuplicate == false)
{
items.add(item);
}
// add a message to inform the user of the clipboard state now if configured
FacesContext context = FacesContext.getCurrentInstance();
if (Application.getClientConfig(context).isClipboardStatusVisible())
{
String pattern = Application.getMessage(context, StoreRef.PROTOCOL_AVM.equals(ref.getStoreRef().getProtocol()) ? "node_added_clipboard_avm" : "node_added_clipboard");
String msg = MessageFormat.format(pattern, items.size());
FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
context.addMessage(null, facesMsg);
}
}
}
}