diff --git a/config/alfresco/extension/ldap-authentication-context.xml.sample b/config/alfresco/extension/ldap-authentication-context.xml.sample
index efab14b064..d024f42463 100644
--- a/config/alfresco/extension/ldap-authentication-context.xml.sample
+++ b/config/alfresco/extension/ldap-authentication-context.xml.sample
@@ -20,6 +20,9 @@
true
+
+ true
+
diff --git a/config/alfresco/messages/dictionary-messages.properties b/config/alfresco/messages/dictionary-messages.properties
index 7bbe0556bb..27e8f1e966 100644
--- a/config/alfresco/messages/dictionary-messages.properties
+++ b/config/alfresco/messages/dictionary-messages.properties
@@ -25,6 +25,7 @@ d_dictionary.property.err.cannot_relax_mandatory_enforcement=Cannot relax mandat
d_dictionary.constraint.regex.no_match=Value ''{0}'' does not match regular expression: {1}
d_dictionary.constraint.regex.match=Value ''{0}'' matches regular expression: {1}
+d_dictionary.constraint.regex.error.cm\:filename=Value ''{0}'' is not valid as a file name. This property must be a valid file name.
d_dictionary.constraint.numeric_range.invalid_min_value=Invalid 'minValue' property: {0}
d_dictionary.constraint.numeric_range.invalid_max_value=Invalid 'maxValue' property: {0}
diff --git a/source/java/org/alfresco/repo/avm/AVMNodeService.java b/source/java/org/alfresco/repo/avm/AVMNodeService.java
index 04c1ce9456..3012f46e54 100644
--- a/source/java/org/alfresco/repo/avm/AVMNodeService.java
+++ b/source/java/org/alfresco/repo/avm/AVMNodeService.java
@@ -308,7 +308,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi
{
// TODO Need to find out if this is important and if so
// need to capture Transaction IDs.
- return new NodeRef.Status("Unknown", !exists(nodeRef));
+ return new NodeRef.Status("Unknown", null, !exists(nodeRef));
}
/**
diff --git a/source/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java b/source/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java
index dc016d34d6..176cc3f46e 100644
--- a/source/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java
+++ b/source/java/org/alfresco/repo/dictionary/M2ConstraintDefinition.java
@@ -226,6 +226,24 @@ import org.springframework.beans.PropertyAccessException;
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValue.getName(), shortName);
}
}
+
+ // Pass in the name as a special property, if it is available
+ if (beanWrapper.isWritableProperty("_shortName"))
+ {
+ try
+ {
+ beanWrapper.setPropertyValue("_shortName", shortName);
+ }
+ catch (PropertyAccessException e)
+ {
+ throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName);
+ }
+ catch (InvalidPropertyException e)
+ {
+ throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, shortName, shortName);
+ }
+
+ }
}
// now initialize
constraint.initialize();
diff --git a/source/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java b/source/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java
index b7de444c4e..88718f5db7 100644
--- a/source/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java
+++ b/source/java/org/alfresco/repo/dictionary/constraint/AbstractConstraint.java
@@ -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
@@ -18,7 +18,7 @@
* 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
+ * FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
@@ -40,6 +40,31 @@ public abstract class AbstractConstraint implements Constraint
{
public static final String ERR_PROP_NOT_SET = "d_dictionary.constraint.err.property_not_set";
public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.constraint.err.evaluate_exception";
+
+
+ /** The constraint name. May be useful in error messages */
+ private String shortName;
+
+ /**
+ * Sets the constraint name. Automatically called after construction. Please excuse the strange method name as we
+ * want the property name to begin with an underscore to avoid property name clashes.
+ *
+ * @param shortName
+ */
+ public void set_shortName(String shortName)
+ {
+ this.shortName = shortName;
+ }
+
+ /**
+ * Gets the constraint name. May be useful in error messages.
+ *
+ * @return the constraint name.
+ */
+ public String getShortName()
+ {
+ return this.shortName;
+ }
/*
* @see org.alfresco.service.cmr.dictionary.Constraint#getType()
diff --git a/source/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java b/source/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java
index 177a4e46da..11299e1e01 100644
--- a/source/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java
+++ b/source/java/org/alfresco/repo/dictionary/constraint/RegexConstraint.java
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.alfresco.i18n.I18NUtil;
import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
@@ -51,6 +52,7 @@ public class RegexConstraint extends AbstractConstraint
{
public static final String CONSTRAINT_REGEX_NO_MATCH = "d_dictionary.constraint.regex.no_match";
public static final String CONSTRAINT_REGEX_MATCH = "d_dictionary.constraint.regex.match";
+ public static final String CONSTRAINT_REGEX_MSG_PREFIX = "d_dictionary.constraint.regex.error.";
private String expression;
private Pattern patternMatcher;
@@ -127,7 +129,14 @@ public class RegexConstraint extends AbstractConstraint
boolean matches = matcher.matches();
if (matches != requiresMatch)
{
- if (requiresMatch)
+ // Look for a message corresponding to this constraint name
+ String messageId = CONSTRAINT_REGEX_MSG_PREFIX + getShortName();
+ if (I18NUtil.getMessage(messageId, value) != null)
+ {
+ throw new ConstraintException(messageId, value);
+ }
+ // Otherwise, fall back to a generic (but unfriendly) message
+ else if (requiresMatch)
{
throw new ConstraintException(RegexConstraint.CONSTRAINT_REGEX_NO_MATCH, value, expression);
}
diff --git a/source/java/org/alfresco/repo/importer/ExportSourceImporter.java b/source/java/org/alfresco/repo/importer/ExportSourceImporter.java
index be41b10a38..2d9f3af4e0 100644
--- a/source/java/org/alfresco/repo/importer/ExportSourceImporter.java
+++ b/source/java/org/alfresco/repo/importer/ExportSourceImporter.java
@@ -27,8 +27,10 @@ package org.alfresco.repo.importer;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.List;
@@ -173,12 +175,12 @@ public class ExportSourceImporter implements ImporterJobSPI
}
File tempFile = TempFileProvider.createTempFile("ExportSourceImporter-", ".xml");
- Writer writer = new BufferedWriter(new FileWriter(tempFile));
+ Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile), "UTF-8"));
XMLWriter xmlWriter = createXMLExporter(writer);
exportSource.generateExport(xmlWriter);
xmlWriter.close();
- Reader reader = new BufferedReader(new FileReader(tempFile));
+ Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(tempFile), "UTF-8"));
Location location = new Location(storeRef);
location.setPath(path);
diff --git a/source/java/org/alfresco/repo/jscript/ScriptUtils.java b/source/java/org/alfresco/repo/jscript/ScriptUtils.java
index 28ca5d595a..de917e6a6d 100644
--- a/source/java/org/alfresco/repo/jscript/ScriptUtils.java
+++ b/source/java/org/alfresco/repo/jscript/ScriptUtils.java
@@ -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
@@ -33,6 +33,7 @@ import org.alfresco.service.cmr.module.ModuleService;
import org.alfresco.service.cmr.module.ModuleDetails;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
+import org.alfresco.util.ISO8601DateFormat;
/**
* Place for general and miscellaneous utility functions not already found in generic JavaScript.
@@ -126,4 +127,37 @@ public final class ScriptUtils extends BaseScopableProcessorExtension
}
return false;
}
+
+ /**
+ * Format timeInMillis to ISO 8601 formatted string
+ *
+ * @param timeInMillis
+ * @return
+ */
+ public String toISO8601(long timeInMillis)
+ {
+ return ISO8601DateFormat.format(new Date(timeInMillis));
+ }
+
+ /**
+ * Format date to ISO 8601 formatted string
+ *
+ * @param date
+ * @return
+ */
+ public String toISO8601(Date date)
+ {
+ return ISO8601DateFormat.format(date);
+ }
+
+ /**
+ * Parse date from ISO formatted string
+ *
+ * @param isoDateString
+ * @return
+ */
+ public Date fromISO8601(String isoDateString)
+ {
+ return ISO8601DateFormat.parse(isoDateString);
+ }
}
diff --git a/source/java/org/alfresco/repo/node/db/NodeDaoService.java b/source/java/org/alfresco/repo/node/db/NodeDaoService.java
index 730f638e30..1b445742bd 100644
--- a/source/java/org/alfresco/repo/node/db/NodeDaoService.java
+++ b/source/java/org/alfresco/repo/node/db/NodeDaoService.java
@@ -570,4 +570,10 @@ public interface NodeDaoService
@DirtySessionAnnotation(markDirty=true)
public void purgeTxn(Long txnId);
+
+ @DirtySessionAnnotation(markDirty=false)
+ public Long getMinTxnCommitTime();
+
+ @DirtySessionAnnotation(markDirty=false)
+ public Long getMaxTxnCommitTime();
}
diff --git a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java
index 2ad9b88ffd..ad2e06fb37 100644
--- a/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java
+++ b/source/java/org/alfresco/repo/node/db/hibernate/HibernateNodeDaoServiceImpl.java
@@ -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
@@ -672,6 +672,7 @@ public class HibernateNodeDaoServiceImpl extends HibernateDaoSupport implements
{
return new NodeRef.Status(
node.getTransaction().getChangeTxnId(),
+ node.getTransaction().getId(),
node.getDeleted());
}
}
diff --git a/source/java/org/alfresco/repo/node/index/AbstractReindexComponent.java b/source/java/org/alfresco/repo/node/index/AbstractReindexComponent.java
index d3a8dbf302..e7a6afc15a 100644
--- a/source/java/org/alfresco/repo/node/index/AbstractReindexComponent.java
+++ b/source/java/org/alfresco/repo/node/index/AbstractReindexComponent.java
@@ -240,6 +240,12 @@ public abstract class AbstractReindexComponent implements IndexRecovery
{
try
{
+ // started
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Reindex work started: " + this);
+ }
+
AuthenticationUtil.pushAuthentication();
// authenticate as the system user
AuthenticationUtil.setRunAsUserSystem();
@@ -284,7 +290,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
}
}
- protected enum InIndex
+ public enum InIndex
{
YES, NO, INDETERMINATE;
}
@@ -348,7 +354,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
* @param txn a specific transaction
* @return Returns true if the transaction is definitely in the index
*/
- protected InIndex isTxnPresentInIndex(final Transaction txn)
+ public InIndex isTxnPresentInIndex(final Transaction txn)
{
if (txn == null)
{
@@ -356,9 +362,9 @@ public abstract class AbstractReindexComponent implements IndexRecovery
}
final Long txnId = txn.getId();
- if (logger.isDebugEnabled())
+ if (logger.isTraceEnabled())
{
- logger.debug("Checking for transaction in index: " + txnId);
+ logger.trace("Checking for transaction in index: " + txnId);
}
// Check if the txn ID is present in any store's index
@@ -398,6 +404,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
{
// There were deleted nodes only. Check that all the deleted nodes were
// removed from the index otherwise it is out of date.
+ result = InIndex.YES;
for (StoreRef storeRef : storeRefs)
{
if (!haveNodesBeenRemovedFromIndex(storeRef, txn))
@@ -444,17 +451,17 @@ public abstract class AbstractReindexComponent implements IndexRecovery
if (results.length() > 0)
{
- if (logger.isDebugEnabled())
+ if (logger.isTraceEnabled())
{
- logger.debug("Index has results for txn " + txnId + " for store " + storeRef);
+ logger.trace("Index has results for txn " + txnId + " for store " + storeRef);
}
return true; // there were updates/creates and results for the txn were found
}
else
{
- if (logger.isDebugEnabled())
+ if (logger.isTraceEnabled())
{
- logger.debug("Transaction " + txnId + " not in index for store " + storeRef + ". Possibly out of date.");
+ logger.trace("Transaction " + txnId + " not in index for store " + storeRef + ". Possibly out of date.");
}
return false;
}
@@ -474,9 +481,9 @@ public abstract class AbstractReindexComponent implements IndexRecovery
boolean foundNodeRef = false;
for (NodeRef nodeRef : nodeRefs)
{
- if (logger.isDebugEnabled())
+ if (logger.isTraceEnabled())
{
- logger.debug("Searching for node in index: \n" +
+ logger.trace("Searching for node in index: \n" +
" node: " + nodeRef + "\n" +
" txn: " + txnId);
}
@@ -514,9 +521,9 @@ public abstract class AbstractReindexComponent implements IndexRecovery
else
{
// No nodes found
- if (logger.isDebugEnabled())
+ if (logger.isTraceEnabled())
{
- logger.debug(" --> Node not found (OK)");
+ logger.trace(" --> Node not found (OK)");
}
}
return !foundNodeRef;
diff --git a/source/java/org/alfresco/repo/node/index/IndexTransactionTracker.java b/source/java/org/alfresco/repo/node/index/IndexTransactionTracker.java
index 2e874601c9..7f3d129b95 100644
--- a/source/java/org/alfresco/repo/node/index/IndexTransactionTracker.java
+++ b/source/java/org/alfresco/repo/node/index/IndexTransactionTracker.java
@@ -1,18 +1,26 @@
/*
- * Copyright (C) 2005-2006 Alfresco, Inc.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
- * Licensed under the Mozilla Public License version 1.1
- * with a permitted attribution clause. You may obtain a
- * copy of the License at
- *
- * http://www.alfresco.org/legal/license.txt
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the
- * License.
+ * 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.index;
@@ -56,6 +64,10 @@ public class IndexTransactionTracker extends AbstractReindexComponent
private Map voids;
private boolean forceReindex;
+ private long fromTxnId;
+ private String statusMsg;
+ private static final String NO_REINDEX = "No reindex in progress";
+
/**
* Set the defaults.
*
@@ -73,11 +85,16 @@ public class IndexTransactionTracker extends AbstractReindexComponent
maxRecordSetSize = 1000;
maxTransactionsPerLuceneCommit = 100;
disableInTransactionIndexing = false;
+
+ started = false;
previousTxnIds = Collections.emptyList();
lastMaxTxnId = Long.MAX_VALUE;
fromTimeInclusive = -1L;
voids = new TreeMap();
forceReindex = false;
+
+ fromTxnId = 0L;
+ statusMsg = NO_REINDEX;
}
public synchronized void setListener(IndexTransactionTrackerListener listener)
@@ -177,12 +194,38 @@ public class IndexTransactionTracker extends AbstractReindexComponent
return reindexInTransaction();
}
};
+
+ public void reindexFromTxn(long txnId)
+ {
+ try
+ {
+ logger.info("reindexFromTxn: "+txnId);
+
+ this.fromTxnId = txnId;
+ this.started = false;
+
+ reindex();
+
+ this.started = false;
+ }
+ finally
+ {
+ this.fromTxnId = 0L;
+
+ }
+ }
@Override
protected void reindexImpl()
{
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("reindexImpl started: " + this);
+ }
+
RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
- if (!started)
+
+ if ((!started) || (this.fromTxnId != 0L))
{
// Disable in-transaction indexing
if (disableInTransactionIndexing && nodeIndexer != null)
@@ -194,8 +237,29 @@ public class IndexTransactionTracker extends AbstractReindexComponent
voids.clear();
previousTxnIds = new ArrayList(maxRecordSetSize);
lastMaxTxnId = null; // So that it is ignored at first
- fromTimeInclusive = retryingTransactionHelper.doInTransaction(getStartingCommitTimeWork, true, true);
+
+ if (this.fromTxnId != 0L)
+ {
+ Long fromTxnCommitTime = getTxnCommitTime(this.fromTxnId);
+
+ if (fromTxnCommitTime == null)
+ {
+ return;
+ }
+
+ fromTimeInclusive = fromTxnCommitTime;
+ }
+ else
+ {
+ fromTimeInclusive = retryingTransactionHelper.doInTransaction(getStartingCommitTimeWork, true, true);
+ }
+
started = true;
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("reindexImpl: fromTimeInclusive: "+fromTimeInclusive+" "+this);
+ }
}
while (true)
@@ -209,7 +273,36 @@ public class IndexTransactionTracker extends AbstractReindexComponent
}
// Wait for the asynchronous reindexing to complete
waitForAsynchronousReindexing();
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("reindexImpl: completed: " + this);
+ }
+
+ statusMsg = NO_REINDEX;
}
+
+ private Long getTxnCommitTime(final long txnId)
+ {
+ RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
+
+ RetryingTransactionCallback getTxnCommitTimeWork = new RetryingTransactionCallback()
+ {
+ public Long execute() throws Exception
+ {
+ Transaction txn = nodeDaoService.getTxnById(txnId);
+ if (txn != null)
+ {
+ return txn.getCommitTimeMs();
+ }
+
+ logger.warn("Txn not found: "+txnId);
+ return null;
+ }
+ };
+
+ return retryingTransactionHelper.doInTransaction(getTxnCommitTimeWork, true, true);
+ }
/**
* @return Returns true if the reindex process can exit otherwise false if
@@ -217,6 +310,8 @@ public class IndexTransactionTracker extends AbstractReindexComponent
*/
private boolean reindexInTransaction()
{
+ List txns = null;
+
long toTimeExclusive = System.currentTimeMillis() - reindexLagMs;
// Check that the voids haven't been filled
@@ -232,7 +327,7 @@ public class IndexTransactionTracker extends AbstractReindexComponent
}
// get next transactions to index
- List txns = getNextTransactions(fromTimeInclusive, toTimeExclusive, previousTxnIds);
+ txns = getNextTransactions(fromTimeInclusive, toTimeExclusive, previousTxnIds);
// If there are no transactions, then all the work is done
if (txns.size() == 0)
@@ -243,14 +338,15 @@ public class IndexTransactionTracker extends AbstractReindexComponent
return false;
}
+ statusMsg = String.format(
+ "Reindexing batch of %d transactions from %s (txnId=%s)",
+ txns.size(),
+ (new Date(fromTimeInclusive)).toString(),
+ txns.isEmpty() ? "---" : txns.get(0).getId().toString());
+
if (logger.isDebugEnabled())
{
- String msg = String.format(
- "Reindexing %d transactions from %s (%s)",
- txns.size(),
- (new Date(fromTimeInclusive)).toString(),
- txns.isEmpty() ? "---" : txns.get(0).getId().toString());
- logger.debug(msg);
+ logger.debug(statusMsg);
}
// Reindex the transactions. Voids between the last set of transactions and this
@@ -299,6 +395,11 @@ public class IndexTransactionTracker extends AbstractReindexComponent
}
}
+ public String getReindexStatus()
+ {
+ return statusMsg;
+ }
+
private static final long ONE_HOUR_MS = 3600*1000;
/**
* Find a transaction time to start indexing from (inclusive). The last recorded transaction by ID
diff --git a/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java b/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
index 69b8638f83..262e523117 100644
--- a/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
+++ b/source/java/org/alfresco/repo/security/authentication/AbstractAuthenticationComponent.java
@@ -35,7 +35,9 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
@@ -165,7 +167,20 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
else
{
SetCurrentUserCallback callback = new SetCurrentUserCallback(userName);
- Authentication auth = transactionService.getRetryingTransactionHelper().doInTransaction(callback, transactionService.isReadOnly(), false);
+ Authentication auth;
+ // If the repository is read only, we have to settle for a read only transaction. Auto user creation will
+ // not be possible.
+ if (transactionService.isReadOnly())
+ {
+ auth = transactionService.getRetryingTransactionHelper().doInTransaction(callback, true, false);
+ }
+ // Otherwise, we want a writeable transaction, so if the current transaction is read only we set the
+ // requiresNew flag to true
+ else
+ {
+ auth = transactionService.getRetryingTransactionHelper().doInTransaction(callback, false,
+ AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY);
+ }
if ((auth == null) || (callback.ae != null))
{
throw callback.ae;
diff --git a/source/java/org/alfresco/service/cmr/repository/NodeRef.java b/source/java/org/alfresco/service/cmr/repository/NodeRef.java
index b2065f5bf5..62ac9ab64e 100644
--- a/source/java/org/alfresco/service/cmr/repository/NodeRef.java
+++ b/source/java/org/alfresco/service/cmr/repository/NodeRef.java
@@ -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
@@ -166,11 +166,13 @@ public final class NodeRef implements EntityRef, Serializable
public static class Status
{
private final String changeTxnId;
+ private final Long dbTxnId;
private final boolean deleted;
- public Status(String changeTxnId, boolean deleted)
+ public Status(String changeTxnId, Long dbTxnId, boolean deleted)
{
this.changeTxnId = changeTxnId;
+ this.dbTxnId = dbTxnId;
this.deleted = deleted;
}
/**
@@ -181,11 +183,35 @@ public final class NodeRef implements EntityRef, Serializable
return changeTxnId;
}
/**
+ * @return Returns the db ID of the last transaction to change the node
+ */
+ public Long getDbTxnId()
+ {
+ return dbTxnId;
+ }
+ /**
* @return Returns true if the node has been deleted, otherwise false
*/
public boolean isDeleted()
{
return deleted;
}
+
+ // debug display string
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder(50);
+
+ sb.append("Status[")
+ .append("changeTxnId=")
+ .append(changeTxnId)
+ .append(", dbTxnId=")
+ .append(dbTxnId)
+ .append(", deleted=")
+ .append(deleted)
+ .append("]");
+
+ return sb.toString();
+ }
}
}
\ No newline at end of file