mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged V2.1 to HEAD
6500: Office 2003 Add-ins: Fix for AWC-1505 6501: Fix for AWC-1361 6502: Fixes for locking issues regrading expired content 6503: Fix for AR-1615 6504: WCM-444, WCM-288, WCM-735, WCM-480 6505: WCM-498 wasn't fully fixed 6506: Fix for AWC-1462 6507: Fix for WCM-741 (link validation report for staging sandbox can get stuck) 6508: AR-1650: WS Unit tests fail 6509: Fix for WCM-751 which also solves WCM-570 - also fixed issue to allow deletion of any "broken" webprojects created due to either of those bugs. 6510: Fix for WCM-546 (workflow history panel should be expanded by default) 6511: Fix AWC-1128 6512: Fixes to several to a couple of bugs found under concurrent load. 6513: Build fix for test using an invalid noderef (now stripped out as it does not exist) 6514: Add support for the QueryFile transact request to the IPC$ named pipe handler. Fix for AR-1687. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6740 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -24,11 +24,15 @@
|
||||
*/
|
||||
package org.alfresco.filesys.smb.server;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.filesys.server.filesys.FileInfo;
|
||||
import org.alfresco.filesys.server.filesys.NetworkFile;
|
||||
import org.alfresco.filesys.server.filesys.PathNotFoundException;
|
||||
import org.alfresco.filesys.server.filesys.TooManyFilesException;
|
||||
import org.alfresco.filesys.server.filesys.TreeConnection;
|
||||
import org.alfresco.filesys.server.filesys.UnsupportedInfoLevelException;
|
||||
import org.alfresco.filesys.smb.PacketType;
|
||||
import org.alfresco.filesys.smb.SMBStatus;
|
||||
import org.alfresco.filesys.smb.TransactionNames;
|
||||
@@ -186,6 +190,12 @@ class IPCHandler
|
||||
DCERPCHandler.processDCERPCRequest(sess, vc, tbuf, outPkt);
|
||||
break;
|
||||
|
||||
// Query file information via handle
|
||||
|
||||
case PacketType.Trans2QueryFile:
|
||||
procTrans2QueryFile(sess, vc, tbuf, outPkt);
|
||||
break;
|
||||
|
||||
// Unknown command
|
||||
|
||||
default:
|
||||
@@ -661,4 +671,134 @@ class IPCHandler
|
||||
|
||||
sess.sendResponseSMB(outPkt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a transact2 query file information (via handle) request.
|
||||
*
|
||||
* @param sess SMBSrvSession
|
||||
* @param vc VirtualCircuit
|
||||
* @param tbuf Transaction request details
|
||||
* @param outPkt SMBSrvPacket
|
||||
* @exception java.io.IOException The exception description.
|
||||
* @exception org.alfresco.aifs.smb.SMBSrvException SMB protocol exception
|
||||
*/
|
||||
protected static final void procTrans2QueryFile(SMBSrvSession sess, VirtualCircuit vc, SrvTransactBuffer tbuf, SMBSrvPacket outPkt)
|
||||
throws java.io.IOException, SMBSrvException {
|
||||
|
||||
// Get the tree connection details
|
||||
|
||||
int treeId = tbuf.getTreeId();
|
||||
TreeConnection conn = vc.findConnection(treeId);
|
||||
|
||||
if (conn == null) {
|
||||
sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.DOSInvalidDrive, SMBStatus.ErrDos);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the user has the required access permission
|
||||
|
||||
if (conn.hasReadAccess() == false) {
|
||||
|
||||
// User does not have the required access rights
|
||||
|
||||
sess.sendErrorResponseSMB(SMBStatus.NTAccessDenied, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the file id and query path information level
|
||||
|
||||
DataBuffer paramBuf = tbuf.getParameterBuffer();
|
||||
|
||||
int fid = paramBuf.getShort();
|
||||
int infoLevl = paramBuf.getShort();
|
||||
|
||||
// Get the file details via the file id
|
||||
|
||||
NetworkFile netFile = conn.findFile(fid);
|
||||
|
||||
if (netFile == null) {
|
||||
sess.sendErrorResponseSMB(SMBStatus.DOSInvalidHandle, SMBStatus.ErrDos);
|
||||
return;
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
||||
if (logger.isDebugEnabled() && sess.hasDebug(SMBSrvSession.DBG_IPC))
|
||||
logger.debug("IPC$ Query File - level=0x" + Integer.toHexString(infoLevl) + ", fid=" + fid + ", name=" + netFile.getFullName());
|
||||
|
||||
// Access the shared device disk interface
|
||||
|
||||
try {
|
||||
|
||||
// Set the return parameter count, so that the data area position can be calculated.
|
||||
|
||||
outPkt.setParameterCount(10);
|
||||
|
||||
// Pack the file information into the data area of the transaction reply
|
||||
|
||||
byte[] buf = outPkt.getBuffer();
|
||||
int prmPos = DataPacker.longwordAlign(outPkt.getByteOffset());
|
||||
int dataPos = prmPos + 4;
|
||||
|
||||
// Pack the return parametes, EA error offset
|
||||
|
||||
outPkt.setPosition(prmPos);
|
||||
outPkt.packWord(0);
|
||||
|
||||
// Create a data buffer using the SMB packet. The response should always fit into a single
|
||||
// reply packet.
|
||||
|
||||
DataBuffer replyBuf = new DataBuffer(buf, dataPos, buf.length - dataPos);
|
||||
|
||||
// Build the file information from the network file details
|
||||
|
||||
FileInfo fileInfo = new FileInfo(netFile.getName(), netFile.getFileSize(), netFile.getFileAttributes());
|
||||
|
||||
fileInfo.setAccessDateTime(netFile.getAccessDate());
|
||||
fileInfo.setCreationDateTime(netFile.getCreationDate());
|
||||
fileInfo.setModifyDateTime(netFile.getModifyDate());
|
||||
fileInfo.setChangeDateTime(netFile.getModifyDate());
|
||||
|
||||
fileInfo.setFileId(netFile.getFileId());
|
||||
|
||||
// Pack the file information into the return data packet
|
||||
|
||||
int dataLen = QueryInfoPacker.packInfo(fileInfo, replyBuf, infoLevl, true);
|
||||
|
||||
// Check if any data was packed, if not then the information level is not supported
|
||||
|
||||
if (dataLen == 0) {
|
||||
sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv);
|
||||
return;
|
||||
}
|
||||
|
||||
SMBSrvTransPacket.initTransactReply(outPkt, 2, prmPos, dataLen, dataPos);
|
||||
outPkt.setByteCount(replyBuf.getPosition() - outPkt.getByteOffset());
|
||||
|
||||
// Send the transact reply
|
||||
|
||||
sess.sendResponseSMB(outPkt);
|
||||
}
|
||||
catch (FileNotFoundException ex) {
|
||||
|
||||
// Requested file does not exist
|
||||
|
||||
sess.sendErrorResponseSMB(SMBStatus.NTObjectNotFound, SMBStatus.DOSFileNotFound, SMBStatus.ErrDos);
|
||||
return;
|
||||
}
|
||||
catch (PathNotFoundException ex) {
|
||||
|
||||
// Requested path does not exist
|
||||
|
||||
sess.sendErrorResponseSMB(SMBStatus.NTObjectPathNotFound, SMBStatus.DOSFileNotFound, SMBStatus.ErrDos);
|
||||
return;
|
||||
}
|
||||
catch (UnsupportedInfoLevelException ex) {
|
||||
|
||||
// Requested information level is not supported
|
||||
|
||||
sess.sendErrorResponseSMB(SMBStatus.NTInvalidParameter, SMBStatus.SRVNonSpecificError, SMBStatus.ErrSrv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@@ -178,6 +178,7 @@ public class LinkValidationAction extends ActionExecuterAbstractBase
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
// capture the error in the report
|
||||
if (report != null)
|
||||
{
|
||||
report.setError(err);
|
||||
@@ -187,6 +188,12 @@ public class LinkValidationAction extends ActionExecuterAbstractBase
|
||||
report = new LinkValidationReport(storeName, webappName, err);
|
||||
}
|
||||
|
||||
// set the monitor object as completed
|
||||
if (monitor != null)
|
||||
{
|
||||
monitor.setDone(true);
|
||||
}
|
||||
|
||||
logger.error("Link Validation Error: ", err);
|
||||
}
|
||||
|
||||
|
@@ -108,7 +108,7 @@ public class ComparePropertyValueEvaluatorTest extends BaseSpringTest
|
||||
+ System.currentTimeMillis());
|
||||
this.rootNodeRef = this.nodeService.getRootNode(this.testStoreRef);
|
||||
|
||||
this.nodeValue = new NodeRef(this.testStoreRef, "1234");
|
||||
this.nodeValue = this.rootNodeRef;
|
||||
|
||||
this.beforeDateValue = new Date();
|
||||
Thread.sleep(2000);
|
||||
|
@@ -41,9 +41,9 @@ public class AVMCrawlTestP extends AVMServiceTestBase
|
||||
*/
|
||||
public void testCrawl()
|
||||
{
|
||||
int n = 3; // Number of Threads.
|
||||
int m = 10; // How many multiples of content to start with.
|
||||
long runTime = 18000000; // 6 hours.
|
||||
int n = 4; // Number of Threads.
|
||||
int m = 2; // How many multiples of content to start with.
|
||||
long runTime = 3600000; // 1 Hour. .
|
||||
fService.purgeStore("main");
|
||||
BulkLoader loader = new BulkLoader();
|
||||
loader.setAvmService(fService);
|
||||
|
@@ -48,6 +48,7 @@ import org.alfresco.sandbox.SandboxConstants;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||
import org.alfresco.service.cmr.avm.locking.AVMLock;
|
||||
import org.alfresco.service.cmr.avm.locking.AVMLockingService;
|
||||
import org.alfresco.service.cmr.avmsync.AVMSyncService;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
@@ -88,6 +89,7 @@ public class AVMExpiredContentProcessor
|
||||
protected AVMService avmService;
|
||||
protected AVMSyncService avmSyncService;
|
||||
protected AVMService avmLockingAwareService;
|
||||
protected AVMLockingService avmLockingService;
|
||||
protected NodeService nodeService;
|
||||
protected WorkflowService workflowService;
|
||||
protected PersonService personService;
|
||||
@@ -120,6 +122,11 @@ public class AVMExpiredContentProcessor
|
||||
this.avmService = avmService;
|
||||
}
|
||||
|
||||
public void setAvmLockingService(AVMLockingService avmLockingService)
|
||||
{
|
||||
this.avmLockingService = avmLockingService;
|
||||
}
|
||||
|
||||
public void setAvmSyncService(AVMSyncService avmSyncService)
|
||||
{
|
||||
this.avmSyncService = avmSyncService;
|
||||
@@ -321,35 +328,53 @@ public class AVMExpiredContentProcessor
|
||||
|
||||
if (expirationDate != null && expirationDate.before(now))
|
||||
{
|
||||
// get the map of expired content for the store
|
||||
Map<String, List<String>> storeExpiredContent = this.expiredContent.get(storeName);
|
||||
if (storeExpiredContent == null)
|
||||
{
|
||||
storeExpiredContent = new HashMap<String, List<String>>(4);
|
||||
this.expiredContent.put(storeName, storeExpiredContent);
|
||||
}
|
||||
|
||||
// get the list of expired content for the last modifier of the node
|
||||
String modifier = node.getLastModifier();
|
||||
List<String> userExpiredContent = storeExpiredContent.get(modifier);
|
||||
if (userExpiredContent == null)
|
||||
{
|
||||
userExpiredContent = new ArrayList<String>(4);
|
||||
storeExpiredContent.put(modifier, userExpiredContent);
|
||||
}
|
||||
|
||||
// add the content to the user's list for the current store
|
||||
userExpiredContent.add(nodePath);
|
||||
|
||||
// before doing anything else see whether the item is locked by any user,
|
||||
// if it is then just log a warning messge and wait until the next time around
|
||||
String[] splitPath = nodePath.split(":");
|
||||
AVMLock lock = this.avmLockingService.getLock(storeName, splitPath[1]);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added " + nodePath + " to " + modifier + "'s list of expired content");
|
||||
logger.debug("lock details for '" + nodePath + "': " + lock);
|
||||
|
||||
if (lock == null)
|
||||
{
|
||||
// get the map of expired content for the store
|
||||
Map<String, List<String>> storeExpiredContent = this.expiredContent.get(storeName);
|
||||
if (storeExpiredContent == null)
|
||||
{
|
||||
storeExpiredContent = new HashMap<String, List<String>>(4);
|
||||
this.expiredContent.put(storeName, storeExpiredContent);
|
||||
}
|
||||
|
||||
// reset the expiration date
|
||||
this.avmService.setNodeProperty(nodePath, WCMAppModel.PROP_EXPIRATIONDATE,
|
||||
new PropertyValue(DataTypeDefinition.DATETIME, null));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Reset expiration date for: " + nodePath);
|
||||
// get the list of expired content for the last modifier of the node
|
||||
String modifier = node.getLastModifier();
|
||||
List<String> userExpiredContent = storeExpiredContent.get(modifier);
|
||||
if (userExpiredContent == null)
|
||||
{
|
||||
userExpiredContent = new ArrayList<String>(4);
|
||||
storeExpiredContent.put(modifier, userExpiredContent);
|
||||
}
|
||||
|
||||
// add the content to the user's list for the current store
|
||||
userExpiredContent.add(nodePath);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added " + nodePath + " to " + modifier + "'s list of expired content");
|
||||
|
||||
// reset the expiration date
|
||||
this.avmService.setNodeProperty(nodePath, WCMAppModel.PROP_EXPIRATIONDATE,
|
||||
new PropertyValue(DataTypeDefinition.DATETIME, null));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Reset expiration date for: " + nodePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("ignoring '" + nodePath + "', although it has expired, it's currently locked");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -708,14 +708,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi
|
||||
{
|
||||
return true;
|
||||
}
|
||||
try
|
||||
{
|
||||
return fAVMService.hasAspect(version, path, aspectTypeQName);
|
||||
}
|
||||
catch (AVMNotFoundException e)
|
||||
{
|
||||
throw new InvalidNodeRefException(nodeRef);
|
||||
}
|
||||
return fAVMService.hasAspect(version, path, aspectTypeQName);
|
||||
}
|
||||
|
||||
private static QName [] fgBuiltinAspects = new QName[] { ContentModel.ASPECT_AUDITABLE,
|
||||
|
@@ -101,6 +101,21 @@ import org.alfresco.util.Pair;
|
||||
*/
|
||||
public class AVMServiceTest extends AVMServiceTestBase
|
||||
{
|
||||
public void testSpacesInStoreNames()
|
||||
{
|
||||
try
|
||||
{
|
||||
fService.createStore("I have spaces");
|
||||
fService.createFile("I have spaces:/", "in my name.txt").close();
|
||||
assertNotNull(fService.lookup(-1, "I have spaces:/in my name.txt"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public void testHeadPathsInLayers()
|
||||
{
|
||||
try
|
||||
|
@@ -291,11 +291,13 @@ public class AVMStoreImpl implements AVMStore, Serializable
|
||||
}
|
||||
VersionRoot versionRoot = new VersionRootImpl(this,
|
||||
fRoot,
|
||||
fNextVersionID,
|
||||
fNextVersionID++,
|
||||
System.currentTimeMillis(),
|
||||
user,
|
||||
tag,
|
||||
description);
|
||||
// Another embarassing flush needed.
|
||||
AVMDAOs.Instance().fAVMNodeDAO.flush();
|
||||
AVMDAOs.Instance().fVersionRootDAO.save(versionRoot);
|
||||
for (AVMNode node : layeredNodes)
|
||||
{
|
||||
@@ -308,7 +310,6 @@ public class AVMStoreImpl implements AVMStore, Serializable
|
||||
}
|
||||
}
|
||||
// Increment the version id.
|
||||
fNextVersionID++;
|
||||
return snapShotMap;
|
||||
}
|
||||
|
||||
@@ -462,6 +463,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
|
||||
RawServices.Instance().getMimetypeService().guessMimetype(name),
|
||||
-1,
|
||||
"UTF-8"));
|
||||
// Yet another flush.
|
||||
AVMDAOs.Instance().fAVMNodeDAO.flush();
|
||||
ContentWriter writer = createContentWriter(AVMNodeConverter.ExtendAVMPath(path, name));
|
||||
writer.putContent(data);
|
||||
}
|
||||
|
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 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.node;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* A method interceptor to clean up node ref properties as they are passed in and out of the node service. For
|
||||
* getProperty and getProperies calls invalid node refs are removed from the returned set (they appear to have be
|
||||
* cleaned up). For setProperty and setProperties calls invalid node refs are removed and thus not set. It only
|
||||
* considers properties of type d:noderef.
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class NodeRefPropertyMethodInterceptor implements MethodInterceptor
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(NodeRefPropertyMethodInterceptor.class);
|
||||
|
||||
private boolean filterOnGet = true;
|
||||
|
||||
private boolean filterOnSet = true;
|
||||
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
private NodeService nodeService;
|
||||
|
||||
public boolean isFilterOnGet()
|
||||
{
|
||||
return filterOnGet;
|
||||
}
|
||||
|
||||
public void setFilterOnGet(boolean filterOnGet)
|
||||
{
|
||||
this.filterOnGet = filterOnGet;
|
||||
}
|
||||
|
||||
public boolean isFilterOnSet()
|
||||
{
|
||||
return filterOnSet;
|
||||
}
|
||||
|
||||
public void setFilterOnSet(boolean filterOnSet)
|
||||
{
|
||||
this.filterOnSet = filterOnSet;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable
|
||||
{
|
||||
String methodName = invocation.getMethod().getName();
|
||||
|
||||
// We are going to change the method arguments as we proceed - so we keep them to set the references back at the
|
||||
// end
|
||||
// Not sure if there would be any side effect but we guard against it in any case.
|
||||
// Audit for example will see the correct values on exit
|
||||
// org.springframework.aop.framework.ReflectiveMethodInvocation does not do any special wrapping and this is
|
||||
// fine
|
||||
|
||||
Object[] args = invocation.getArguments();
|
||||
Object[] in = new Object[args.length];
|
||||
System.arraycopy(args, 0, in, 0, args.length);
|
||||
invocation.getStaticPart();
|
||||
|
||||
try
|
||||
{
|
||||
if (methodName.equals("addAspect"))
|
||||
{
|
||||
if (filterOnSet)
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef) args[0];
|
||||
QName aspectType = (QName) args[1];
|
||||
Map<QName, Serializable> newProperties = (Map<QName, Serializable>) args[2];
|
||||
|
||||
if (newProperties == null)
|
||||
{
|
||||
args[2] = newProperties;
|
||||
return invocation.proceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(newProperties.size() * 2);
|
||||
for (Map.Entry<QName, Serializable> entry : newProperties.entrySet())
|
||||
{
|
||||
QName propertyQName = entry.getKey();
|
||||
Serializable value = entry.getValue();
|
||||
value = getValue(propertyQName, value);
|
||||
convertedProperties.put(propertyQName, value);
|
||||
}
|
||||
args[2] = convertedProperties;
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else if (methodName.equals("createNode") & (args.length == 5))
|
||||
{
|
||||
if (filterOnSet)
|
||||
{
|
||||
NodeRef parentRef = (NodeRef) args[0];
|
||||
QName assocTypeQName = (QName) args[1];
|
||||
QName assocQName = (QName) args[2];
|
||||
QName nodeTypeQName = (QName) args[3];
|
||||
Map<QName, Serializable> newProperties = (Map<QName, Serializable>) args[4];
|
||||
if (newProperties == null)
|
||||
{
|
||||
args[4] = newProperties;
|
||||
return invocation.proceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(newProperties.size() * 2);
|
||||
for (Map.Entry<QName, Serializable> entry : newProperties.entrySet())
|
||||
{
|
||||
QName propertyQName = entry.getKey();
|
||||
Serializable value = entry.getValue();
|
||||
value = getValue(propertyQName, value);
|
||||
convertedProperties.put(propertyQName, value);
|
||||
}
|
||||
args[4] = newProperties;
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else if (methodName.equals("getProperty"))
|
||||
{
|
||||
if (filterOnGet)
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef) args[0];
|
||||
QName propertyQName = (QName) args[1];
|
||||
|
||||
Serializable value = (Serializable) invocation.proceed();
|
||||
return getValue(propertyQName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else if (methodName.equals("getProperties"))
|
||||
{
|
||||
if (filterOnGet)
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef) args[0];
|
||||
|
||||
Map<QName, Serializable> properties = (Map<QName, Serializable>) invocation.proceed();
|
||||
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(properties.size() * 2);
|
||||
for (Map.Entry<QName, Serializable> entry : properties.entrySet())
|
||||
{
|
||||
QName propertyQName = entry.getKey();
|
||||
Serializable value = entry.getValue();
|
||||
Serializable convertedValue = getValue(propertyQName, value);
|
||||
convertedProperties.put(propertyQName, convertedValue);
|
||||
}
|
||||
return convertedProperties;
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else if (methodName.equals("setProperties"))
|
||||
{
|
||||
if (filterOnSet)
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef) args[0];
|
||||
|
||||
Map<QName, Serializable> newProperties = (Map<QName, Serializable>) args[1];
|
||||
Map<QName, Serializable> convertedProperties = new HashMap<QName, Serializable>(newProperties.size() * 2);
|
||||
for (Map.Entry<QName, Serializable> entry : newProperties.entrySet())
|
||||
{
|
||||
QName propertyQName = entry.getKey();
|
||||
Serializable value = entry.getValue();
|
||||
value = getValue(propertyQName, value);
|
||||
convertedProperties.put(propertyQName, value);
|
||||
}
|
||||
args[1] = convertedProperties;
|
||||
return invocation.proceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else if (methodName.equals("setProperty"))
|
||||
{
|
||||
if (filterOnSet)
|
||||
{
|
||||
NodeRef nodeRef = (NodeRef) args[0];
|
||||
QName propertyQName = (QName) args[1];
|
||||
Serializable value = (Serializable) args[2];
|
||||
value = getValue(propertyQName, value);
|
||||
args[2] = value;
|
||||
return invocation.proceed();
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.arraycopy(in, 0, args, 0, in.length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove unknown node ref values Remove unknowen categories - the node will be removed if it does exist and it is
|
||||
* not a category
|
||||
*
|
||||
* @param propertyQName
|
||||
* @param inboundValue
|
||||
* @return
|
||||
*/
|
||||
private Serializable getValue(QName propertyQName, Serializable inboundValue)
|
||||
{
|
||||
PropertyDefinition propertyDef = this.dictionaryService.getProperty(propertyQName);
|
||||
if (propertyDef == null)
|
||||
{
|
||||
return inboundValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((propertyDef.getDataType().getName().equals(DataTypeDefinition.NODE_REF)) || (propertyDef.getDataType().getName().equals(DataTypeDefinition.CATEGORY)))
|
||||
{
|
||||
if (inboundValue instanceof Collection)
|
||||
{
|
||||
Collection in = (Collection) inboundValue;
|
||||
ArrayList<NodeRef> out = new ArrayList<NodeRef>(in.size());
|
||||
for (Object o : in)
|
||||
{
|
||||
Serializable value = (Serializable) o;
|
||||
if (value == null)
|
||||
{
|
||||
out.add(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef test = DefaultTypeConverter.INSTANCE.convert(NodeRef.class, value);
|
||||
if (nodeService.exists(test))
|
||||
{
|
||||
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CATEGORY))
|
||||
{
|
||||
QName type = nodeService.getType(test);
|
||||
if (dictionaryService.isSubClass(type, ContentModel.TYPE_CATEGORY))
|
||||
{
|
||||
out.add(test);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out.add(test);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TypeConversionException e)
|
||||
{
|
||||
// Catch and continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inboundValue == null)
|
||||
{
|
||||
return inboundValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
NodeRef test = DefaultTypeConverter.INSTANCE.convert(NodeRef.class, inboundValue);
|
||||
if (nodeService.exists(test))
|
||||
{
|
||||
if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CATEGORY))
|
||||
{
|
||||
QName type = nodeService.getType(test);
|
||||
if (dictionaryService.isSubClass(type, ContentModel.TYPE_CATEGORY))
|
||||
{
|
||||
return inboundValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return inboundValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
catch (TypeConversionException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return inboundValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
97
source/java/org/alfresco/repo/node/NodeRefTestModel.xml
Normal file
97
source/java/org/alfresco/repo/node/NodeRefTestModel.xml
Normal file
@@ -0,0 +1,97 @@
|
||||
<model name="test:nodeservice"
|
||||
xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<description>Test Model for NodeService tests</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2005-06-05</published>
|
||||
<version>0.1</version>
|
||||
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
|
||||
</imports>
|
||||
|
||||
<namespaces>
|
||||
<namespace uri="http://www.alfresco.org/test/NodeRefTestModel"
|
||||
prefix="test"/>
|
||||
</namespaces>
|
||||
|
||||
<types>
|
||||
<type name="test:testType">
|
||||
<title>Content</title>
|
||||
<parent>cm:content</parent>
|
||||
<archive>false</archive>
|
||||
<properties>
|
||||
<property name="test:category1">
|
||||
<type>d:category</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>false</multiple>
|
||||
</property>
|
||||
<property name="test:categories1">
|
||||
<type>d:category</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
<property name="test:noderef1">
|
||||
<type>d:noderef</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>false</multiple>
|
||||
</property>
|
||||
<property name="test:noderefs1">
|
||||
<type>d:noderef</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
|
||||
<aspect name="test:singleCategory">
|
||||
<title>Single Category</title>
|
||||
<properties>
|
||||
<property name="test:category">
|
||||
<type>d:category</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>false</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
||||
<aspect name="test:multipleCategories">
|
||||
<title>Multiple Categories</title>
|
||||
<properties>
|
||||
<property name="test:categories">
|
||||
<type>d:category</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
||||
<aspect name="test:singleNodeRef">
|
||||
<title>Single Node Ref</title>
|
||||
<properties>
|
||||
<property name="test:noderef">
|
||||
<type>d:noderef</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>false</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
||||
<aspect name="test:multipleNodeRefs">
|
||||
<title>Mutliple Node Refs</title>
|
||||
<properties>
|
||||
<property name="test:noderefs">
|
||||
<type>d:noderef</type>
|
||||
<mandatory>false</mandatory>
|
||||
<multiple>true</multiple>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
||||
</aspects>
|
||||
</model>
|
@@ -183,4 +183,15 @@ public class AVMLock implements Serializable
|
||||
{
|
||||
return fWebProject;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(" (webproject=").append(this.fWebProject);
|
||||
buffer.append(" store=").append(this.fStore);
|
||||
buffer.append(" path=").append(this.fPath);
|
||||
buffer.append(" type=").append(this.fType);
|
||||
buffer.append(" owners=").append(this.fOwners).append(")");
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user