Merged V3.1 to HEAD

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
This commit is contained in:
Derek Hulley
2009-03-11 02:50:32 +00:00
parent 45df84aa8f
commit e98e71fb6f
8 changed files with 287 additions and 21 deletions

View File

@@ -1158,6 +1158,7 @@ sandbox_browse=Browse Website
sandbox_revert=Undo
sandbox_revertall=Undo All
sandbox_submitall=Submit All
count_conflicted_items={0} file(s) conflict with changes made by other users
sandbox_submitselected=Submit Selected
sandbox_revertselected=Undo Selected
sandbox_icon=Browse Website
@@ -1295,6 +1296,7 @@ revert_selected_title=Undo Selected Items
revert_selected_desc=To undo the changes to the selected files in the sandbox, click OK.
revert_selected_confirm=Are you sure you want to undo the changes to the selected files in from the sandbox?
revert_all_title=Undo All Items
revert_all_conflicts=Revert all Conflicts
revert_all_desc=To undo the changes to all the files in the sandbox, click OK.
revert_all_confirm=Are you sure you want to undo the changes to all files in the sandbox?
deploy_snapshot_title=Deploy Snapshot

View File

@@ -97,7 +97,7 @@
<permissions>
<permission allow="true">Write</permission>
</permissions>
<evaluator>org.alfresco.web.action.evaluator.WCMWorkflowDeletedEvaluator</evaluator>
<evaluator>org.alfresco.web.action.evaluator.WCMConflictEvaluator</evaluator>
<label-id>submit</label-id>
<image>/images/icons/submit.gif</image>
<action-listener>#{AVMBrowseBean.setupContentAction}</action-listener>

View File

@@ -0,0 +1,53 @@
/*
* 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.web.action.evaluator;
import org.alfresco.service.cmr.avmsync.AVMDifference;
import org.alfresco.web.bean.repository.Node;
public class WCMConflictEvaluator extends WCMWorkflowDeletedEvaluator
{
/* (non-Javadoc)
* @see org.alfresco.web.action.evaluator.WCMWorkflowDeletedEvaluator#evaluate(org.alfresco.web.bean.repository.Node)
*/
public boolean evaluate(final Node node)
{
if (!super.evaluate(node))
{
return false;
}
Integer diff = (Integer)node.getProperties().get("avmDiff");
if (diff == null)
{
return true;
}
if (diff == AVMDifference.CONFLICT)
{
return false;
}
return true;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
* 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
@@ -36,6 +36,8 @@ import java.util.Map;
import java.util.ResourceBundle;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIParameter;
import javax.faces.component.html.HtmlCommandButton;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
@@ -56,6 +58,8 @@ import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avmsync.AVMDifference;
import org.alfresco.service.cmr.avmsync.AVMSyncService;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -70,6 +74,8 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.util.NameMatcher;
import org.alfresco.util.Pair;
import org.alfresco.util.VirtServerUtils;
import org.alfresco.wcm.sandbox.SandboxInfo;
@@ -226,6 +232,9 @@ public class AVMBrowseBean implements IContextListener
/** AVM service bean reference */
transient protected AVMService avmService;
/** AVM sync service bean reference */
transient protected AVMSyncService avmSyncService;
/** Action service bean reference */
transient protected ActionService actionService;
@@ -306,6 +315,23 @@ public class AVMBrowseBean implements IContextListener
return avmService;
}
/**
* @param avmSyncService The AVMSyncService to set.
*/
public void setAvmSyncService(AVMSyncService avmSyncService)
{
this.avmSyncService = avmSyncService;
}
protected AVMSyncService getAvmSyncService()
{
if (avmSyncService == null)
{
avmSyncService = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getAVMSyncService();
}
return avmSyncService;
}
/**
* @param nodeService The NodeService to set.
*/
@@ -2125,4 +2151,57 @@ public class AVMBrowseBean implements IContextListener
this.formName));
}
}
/**
* Revert All Conflicts
*
* @param event
*/
public void revertAllConflict(ActionEvent event)
{
final HtmlCommandButton button = (HtmlCommandButton) event.getComponent();
List<Object> params = button.getChildren();
String userStore = null;
String stagingStore = null;
for (Object obj : params)
{
UIParameter uip = (UIParameter) obj;
if (uip.getName().equals("userStorePath"))
{
userStore = (String) uip.getValue();
}
if (uip.getName().equals("stagingStorePath"))
{
stagingStore = (String) uip.getValue();
}
}
NameMatcher matcher = (NameMatcher) FacesContextUtils.getRequiredWebApplicationContext(FacesContext.getCurrentInstance()).getBean("globalPathExcluder");
// calcluate the list of differences between the user store and the staging area
List<AVMDifference> diffs = this.getAvmSyncService().compare(-1, userStore, -1, stagingStore, matcher);
List<Pair<Integer, String>> versionPaths = new ArrayList<Pair<Integer, String>>();
List<WorkflowTask> tasks = null;
for (AVMDifference diff : diffs)
{
if (diff.getDifferenceCode() == AVMDifference.CONFLICT)
{
AVMNodeDescriptor node = getAvmService().lookup(-1, diff.getSourcePath(), true);
if (tasks == null)
{
tasks = AVMWorkflowUtil.getAssociatedTasksForSandbox(AVMUtil.getStoreName(diff.getSourcePath()));
}
if (AVMWorkflowUtil.getAssociatedTasksForNode(node, tasks).size() == 0)
{
String revertPath = diff.getSourcePath();
versionPaths.add(new Pair<Integer, String>(-1, revertPath));
}
}
}
Map<String, Serializable> args = new HashMap<String, Serializable>(1, 1.0f);
args.put(AVMUndoSandboxListAction.PARAM_NODE_LIST, (Serializable) versionPaths);
Action action = this.getActionService().createAction(AVMUndoSandboxListAction.NAME, args);
this.getActionService().executeAction(action, null);
}
}

View File

@@ -574,7 +574,12 @@ public class XFormsBean implements Serializable
request.getContextPath() + "/wcservice");
String rewrittenURI = uri;
if (uri.contains("${storeid}"))
if (uri.contains("{storeid}"))
{
final String storeId = AVMUtil.getStoreName(cwdAvmPath);
rewrittenURI = uri.replace("{storeid}", storeId);
}
else if (uri.contains("${storeid}"))
{
final String storeId = AVMUtil.getStoreName(cwdAvmPath);
rewrittenURI = uri.replace("${storeid}", storeId);
@@ -585,11 +590,17 @@ public class XFormsBean implements Serializable
LOGGER.debug("no store id specified in webscript URI " + uri);
}
if (uri.contains("${ticket}"))
if (uri.contains("{ticket}"))
{
AuthenticationService authenticationService = Repository.getServiceRegistry(facesContext).getAuthenticationService();
final String ticket = authenticationService.getCurrentTicket();
rewrittenURI = rewrittenURI.replace("${ticket}", ticket);
rewrittenURI = rewrittenURI.replace("{ticket}", ticket);
}
else if (uri.contains("${ticket}"))
{
AuthenticationService authenticationService = Repository.getServiceRegistry(facesContext).getAuthenticationService();
final String ticket = authenticationService.getCurrentTicket();
rewrittenURI = rewrittenURI.replace("${ticket}", ticket);
}
else
{

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2008 Alfresco Software Limited.
* 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
@@ -27,9 +27,12 @@ package org.alfresco.web.ui.wcm.component;
import java.io.IOException;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -38,6 +41,7 @@ import java.util.Set;
import javax.faces.component.UIComponent;
import javax.faces.component.UIParameter;
import javax.faces.component.html.HtmlCommandButton;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
@@ -48,6 +52,7 @@ import org.alfresco.model.WCMAppModel;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.web.scripts.FileTypeImageUtils;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avmsync.AVMDifference;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AccessStatus;
@@ -145,12 +150,15 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
private static final String MSG_NO_MODIFIED_ITEMS = "sandbox_no_modified_items";
private static final String MSG_NO_WEB_FORMS = "sandbox_no_web_forms";
private static final String MSG_MY_SANDBOX = "sandbox_my_sandbox";
private static final String MSG_COUNT_CONFLICTED_ITEMS="count_conflicted_items";
private static final String MSG_REVERT_ALL_CONFLICTS="revert_all_conflicts";
private static final String REQUEST_FORM_REF = "formref";
private static final String REQUEST_PREVIEW_REF = "prevhref";
private static final String REQUEST_UPDATE_TEST_SERVER = "updatetestserver";
private static final String SPACE_ICON = "/images/icons/" + BrowseBean.SPACE_SMALL_DEFAULT + ".gif";
private static final String CONFLICTED_ICON = "/images/icons/conflict-16.gif";
public static final String PARAM_FORM_NAME = "form-name";
@@ -576,6 +584,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
out.write("&nbsp;<b>");
out.write(bundle.getString(MSG_MODIFIED_ITEMS));
out.write("</b>");
if (this.expandedPanels.contains(username + PANEL_MODIFIED))
{
out.write("<div style='padding:2px'></div>");
@@ -721,10 +730,45 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
// compare user sandbox to staging sandbox - filter by current webapp, include deleted items
String userStore = AVMUtil.buildUserMainStoreName(storeRoot, username);
String userStorePath = AVMUtil.buildStoreWebappPath(userStore, getWebapp());
String stagingStore = AVMUtil.buildStagingStoreName(storeRoot);
String stagingStorePath = AVMUtil.buildStoreWebappPath(stagingStore, getWebapp());
List<AssetInfo> assets = sandboxService.listChangedWebApp(userStore, getWebapp(), true);
if (assets.size() != 0)
{
// output confict header, only if conflicts exist
int diffCount = 0;
for (AssetInfo asset : assets)
{
if (asset.getDiffCode() == AVMDifference.CONFLICT)
{
diffCount++;
}
}
if (diffCount > 0)
{
out.write("<table cellspacing=\"0\" cellpadding=\"2\"");
out.write(" class='conflictItemsList' width=\"100%\"");
out.write(">");
out.write("<tr width=\"100%\">");
out.write("<td width=\"100%\">");
out.write(Utils.buildImageTag(fc, CONFLICTED_ICON, 16, 16, "", null, "-25%"));
out.write("&nbsp;");
out.write(MessageFormat.format(bundle.getString(MSG_COUNT_CONFLICTED_ITEMS), diffCount));
out.write("</td>");
out.write("<td>");
Utils.encodeRecursive(fc, createRevertAllItemsButton(fc, bundle, username, userStorePath, stagingStorePath));
out.write("</td>");
out.write("</tr>");
out.write("</table>");
out.write("<div style='padding:2px'></div>");
}
// info we need to calculate preview paths for assets
int rootPathIndex = AVMUtil.buildSandboxRootPath(userStore).length();
@@ -748,7 +792,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
// output the table of modified items
// TODO: apply tag style - removed hardcoded
out.write("<table class='modifiedItemsList' cellspacing=2 cellpadding=1 border=0 width=100%>");
out.write("<table class='modifiedItemsList' cellspacing=0 cellpadding=2 border=0 width=100%>");
// output multi-select actions for this user
out.write("<tr><td colspan=8>");
@@ -775,7 +819,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
out.write(Integer.toString(index));
out.write("' onclick='");
out.write("javascript:_sb_select(this);");
out.write("'></th><th width=16></th><th>");
out.write("'></th><th></th><th></th><th></th><th>");
out.write(bundle.getString(MSG_NAME));
out.write("</th><th>");
out.write(bundle.getString(MSG_CREATED));
@@ -787,6 +831,23 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
out.write(bundle.getString(MSG_ACTIONS));
out.write("</th></tr>");
// move conflicts to top of list
if (diffCount > 0)
{
List<AssetInfo> conflicted = new ArrayList<AssetInfo>();
for(Iterator<AssetInfo> it = assets.iterator(); it.hasNext();)
{
AssetInfo diff = (AssetInfo) it.next();
if (diff.getDiffCode() == AVMDifference.CONFLICT)
{
conflicted.add(diff);
it.remove();
}
}
assets.addAll(0, conflicted);
}
// output each of the modified files as a row in the table
int rowIndex = 0;
for (AssetInfo node : assets)
@@ -796,7 +857,12 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
String sourcePath = node.getAvmPath();
// output multi-select checkbox
out.write("<tr><td><input type='checkbox' name='");
out.write("<tr");
if (node.getDiffCode() == AVMDifference.CONFLICT)
{
out.write(" class='conflictItem'");
}
out.write("><td><input type='checkbox' name='");
out.write(id);
out.write("' id='");
out.write(id);
@@ -814,23 +880,33 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
fc.getExternalContext().getRequestContextPath() +
DownloadContentServlet.generateBrowserURL(AVMNodeConverter.ToNodeRef(-1, sourcePath), name) +
"\" target='new'>";
out.write("<td width=16>");
if (node.isFile())
{
out.write(linkPrefix);
out.write(Utils.buildImageTag(fc, FileTypeImageUtils.getFileTypeImage(fc, name, true), ""));
out.write("</a></td><td>");
out.write(linkPrefix);
out.write(Utils.encode(name));
UIAVMLockIcon lockIcon = (UIAVMLockIcon)fc.getApplication().createComponent(
UIAVMLockIcon.ALFRESCO_FACES_AVMLOCKICON);
lockIcon.setId("avmlock_" + Integer.toString(rowIndex));
lockIcon.setValue(sourcePath);
Utils.encodeRecursive(fc, lockIcon);
out.write("</a>");
out.write("<td width=16>");
if (node.getDiffCode() == AVMDifference.CONFLICT)
{
out.write(Utils.buildImageTag(fc, CONFLICTED_ICON, 16, 16, ""));
}
out.write("</td><td width=20>");
UIAVMLockIcon lockIcon = (UIAVMLockIcon)fc.getApplication().createComponent(UIAVMLockIcon.ALFRESCO_FACES_AVMLOCKICON);
lockIcon.setId("avmlock_" + Integer.toString(rowIndex));
lockIcon.setValue(sourcePath);
Utils.encodeRecursive(fc, lockIcon);
out.write("</td><td width=16>");
out.write(linkPrefix);
out.write(Utils.buildImageTag(fc, FileTypeImageUtils.getFileTypeImage(fc, name, true), ""));
out.write("</a>");
out.write("</td><td>");
out.write(linkPrefix);
out.write(Utils.encode(name));
out.write("</a>");
}
else
{
out.write("<td width=16></td>");
out.write("<td width=20></td>");
out.write("<td width=16>");
out.write(Utils.buildImageTag(fc, SPACE_ICON, 16, 16, ""));
out.write("</td><td>");
out.write(Utils.encode(name));
@@ -850,6 +926,7 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
String assetPath = sourcePath.substring(rootPathIndex);
String previewUrl = AVMUtil.getPreviewURI(userStore, JNDIConstants.DIR_DEFAULT_WWW_APPBASE + assetPath);
avmNode.getProperties().put("previewUrl", previewUrl);
avmNode.getProperties().put("avmDiff", node.getDiffCode());
// size of files
if (node.isFile())
@@ -874,6 +951,8 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
{
// must have been deleted from this sandbox - show as ghosted
String name = node.getName();
out.write("<td width=16></td>");
out.write("<td width=20></td>");
out.write("<td width=16>");
if (node.isFile() && node.isDeleted())
{
@@ -1107,6 +1186,31 @@ public class UIUserSandboxes extends SelfRenderingComponent implements Serializa
return aquireAction(fc, store, username, name, icon, actionListener, outcome, null, null);
}
private HtmlCommandButton createRevertAllItemsButton(FacesContext fc, ResourceBundle bundle, String name, String userStorePath, String stagingStorePath)
{
javax.faces.application.Application facesApp = fc.getApplication();
String id = "revert_all_conflict" + new Date().getTime() + FacesHelper.makeLegalId(name);
HtmlCommandButton cb = (HtmlCommandButton) facesApp.createComponent(HtmlCommandButton.COMPONENT_TYPE);
cb.setId(id);
cb.setValue(bundle.getString(MSG_REVERT_ALL_CONFLICTS));
cb.setActionListener(facesApp.createMethodBinding(
"#{AVMBrowseBean.revertAllConflict}", UIActions.ACTION_CLASS_ARGS));
UIParameter param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER);
param.setId(id + "_1");
param.setName("userStorePath");
param.setValue(userStorePath);
cb.getChildren().add(param);
param = (UIParameter)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PARAMETER);
param.setId(id + "_2");
param.setName("stagingStorePath");
param.setValue(stagingStorePath);
cb.getChildren().add(param);
this.getChildren().add(cb);
return cb;
}
/**
* Aquire a UIActionLink component for the specified action
*

View File

@@ -602,6 +602,23 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl
border-color: #DDDDDD;
}
.conflictItem
{
background-color: #f7e0e1;
}
.conflictItemsList
{
background-color: #f7e0e1;
border-width: 1px;
border-style: solid;
border-color: #e39295;
padding-left: 5px;
padding-right: 5px;
padding-top: 3px;
padding-bottom: 3px;
}
.snapshotItemsList
{
background-color: #f5f5f5;

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B