Merged V3.1 to HEAD

13484: ETHREEOH-1547: Do not set requiresNew flag and propagate exceptions in BaseDialogBean
   13383: ETHREEOH-1220: Update LDAP-authentication-context to include allowGetEnabled entry to support Share
   13381: ETHREEOH-1181: NTLM authentication periodically fails over CIFS - "Read-Write transaction started within read-only transaction"
   13376: ETHREEOH-279: Friendly error message when cm:filename regular expression constraint is violated
   13364: ETHREEOH-814: Correct character encoding issues in LDAP synchronization
   13353: ETHREEOH-1444: Ability to run Alfresco from unexploded .war file with embedded license
   13328: ETHREEOH-1400: Prevent TLD warnings on Weblogic startup
   13183: Follow up to 13177: Fixes for Weblogic compatibility
   13177: Fixes for Weblogic compatibility
   13109: Build/test fix (to avoid unintentional import via application-context.xml)
   13100: Checkpoint for new DM index check (enterprise-only)


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13525 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2009-03-10 14:27:09 +00:00
parent 054d6d46b0
commit 1264fca386
14 changed files with 295 additions and 47 deletions

View File

@@ -20,6 +20,9 @@
<property name="allowDeleteUser"> <property name="allowDeleteUser">
<value>true</value> <value>true</value>
</property> </property>
<property name="allowGetEnabled">
<value>true</value>
</property>
</bean> </bean>

View File

@@ -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.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.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_min_value=Invalid 'minValue' property: {0}
d_dictionary.constraint.numeric_range.invalid_max_value=Invalid 'maxValue' property: {0} d_dictionary.constraint.numeric_range.invalid_max_value=Invalid 'maxValue' property: {0}

View File

@@ -308,7 +308,7 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi
{ {
// TODO Need to find out if this is important and if so // TODO Need to find out if this is important and if so
// need to capture Transaction IDs. // need to capture Transaction IDs.
return new NodeRef.Status("Unknown", !exists(nodeRef)); return new NodeRef.Status("Unknown", null, !exists(nodeRef));
} }
/** /**

View File

@@ -226,6 +226,24 @@ import org.springframework.beans.PropertyAccessException;
throw new DictionaryException(ERR_PROPERTY_MISMATCH, e, namedValue.getName(), shortName); 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 // now initialize
constraint.initialize(); constraint.initialize();

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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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 * 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 * the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's * 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: * the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing" * 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_PROP_NOT_SET = "d_dictionary.constraint.err.property_not_set";
public static final String ERR_EVALUATE_EXCEPTION = "d_dictionary.constraint.err.evaluate_exception"; 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() * @see org.alfresco.service.cmr.dictionary.Constraint#getType()

View File

@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.service.cmr.dictionary.ConstraintException; import org.alfresco.service.cmr.dictionary.ConstraintException;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; 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_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_MATCH = "d_dictionary.constraint.regex.match";
public static final String CONSTRAINT_REGEX_MSG_PREFIX = "d_dictionary.constraint.regex.error.";
private String expression; private String expression;
private Pattern patternMatcher; private Pattern patternMatcher;
@@ -127,7 +129,14 @@ public class RegexConstraint extends AbstractConstraint
boolean matches = matcher.matches(); boolean matches = matcher.matches();
if (matches != requiresMatch) 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); throw new ConstraintException(RegexConstraint.CONSTRAINT_REGEX_NO_MATCH, value, expression);
} }

View File

@@ -27,8 +27,10 @@ package org.alfresco.repo.importer;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileInputStream;
import java.io.FileWriter; import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader; import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.util.List; import java.util.List;
@@ -173,12 +175,12 @@ public class ExportSourceImporter implements ImporterJobSPI
} }
File tempFile = TempFileProvider.createTempFile("ExportSourceImporter-", ".xml"); 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); XMLWriter xmlWriter = createXMLExporter(writer);
exportSource.generateExport(xmlWriter); exportSource.generateExport(xmlWriter);
xmlWriter.close(); 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 location = new Location(storeRef);
location.setPath(path); location.setPath(path);

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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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.cmr.module.ModuleDetails;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO8601DateFormat;
/** /**
* Place for general and miscellaneous utility functions not already found in generic JavaScript. * 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; 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);
}
} }

View File

@@ -570,4 +570,10 @@ public interface NodeDaoService
@DirtySessionAnnotation(markDirty=true) @DirtySessionAnnotation(markDirty=true)
public void purgeTxn(Long txnId); public void purgeTxn(Long txnId);
@DirtySessionAnnotation(markDirty=false)
public Long getMinTxnCommitTime();
@DirtySessionAnnotation(markDirty=false)
public Long getMaxTxnCommitTime();
} }

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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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( return new NodeRef.Status(
node.getTransaction().getChangeTxnId(), node.getTransaction().getChangeTxnId(),
node.getTransaction().getId(),
node.getDeleted()); node.getDeleted());
} }
} }

View File

@@ -240,6 +240,12 @@ public abstract class AbstractReindexComponent implements IndexRecovery
{ {
try try
{ {
// started
if (logger.isDebugEnabled())
{
logger.debug("Reindex work started: " + this);
}
AuthenticationUtil.pushAuthentication(); AuthenticationUtil.pushAuthentication();
// authenticate as the system user // authenticate as the system user
AuthenticationUtil.setRunAsUserSystem(); AuthenticationUtil.setRunAsUserSystem();
@@ -284,7 +290,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
} }
} }
protected enum InIndex public enum InIndex
{ {
YES, NO, INDETERMINATE; YES, NO, INDETERMINATE;
} }
@@ -348,7 +354,7 @@ public abstract class AbstractReindexComponent implements IndexRecovery
* @param txn a specific transaction * @param txn a specific transaction
* @return Returns <tt>true</tt> if the transaction is definitely in the index * @return Returns <tt>true</tt> if the transaction is definitely in the index
*/ */
protected InIndex isTxnPresentInIndex(final Transaction txn) public InIndex isTxnPresentInIndex(final Transaction txn)
{ {
if (txn == null) if (txn == null)
{ {
@@ -356,9 +362,9 @@ public abstract class AbstractReindexComponent implements IndexRecovery
} }
final Long txnId = txn.getId(); 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 // 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 // There were deleted nodes only. Check that all the deleted nodes were
// removed from the index otherwise it is out of date. // removed from the index otherwise it is out of date.
result = InIndex.YES;
for (StoreRef storeRef : storeRefs) for (StoreRef storeRef : storeRefs)
{ {
if (!haveNodesBeenRemovedFromIndex(storeRef, txn)) if (!haveNodesBeenRemovedFromIndex(storeRef, txn))
@@ -444,17 +451,17 @@ public abstract class AbstractReindexComponent implements IndexRecovery
if (results.length() > 0) 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 return true; // there were updates/creates and results for the txn were found
} }
else 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; return false;
} }
@@ -474,9 +481,9 @@ public abstract class AbstractReindexComponent implements IndexRecovery
boolean foundNodeRef = false; boolean foundNodeRef = false;
for (NodeRef nodeRef : nodeRefs) 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" + " node: " + nodeRef + "\n" +
" txn: " + txnId); " txn: " + txnId);
} }
@@ -514,9 +521,9 @@ public abstract class AbstractReindexComponent implements IndexRecovery
else else
{ {
// No nodes found // No nodes found
if (logger.isDebugEnabled()) if (logger.isTraceEnabled())
{ {
logger.debug(" --> Node not found (OK)"); logger.trace(" --> Node not found (OK)");
} }
} }
return !foundNodeRef; return !foundNodeRef;

View File

@@ -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 * This program is free software; you can redistribute it and/or
* with a permitted attribution clause. You may obtain a * modify it under the terms of the GNU General Public License
* copy of the License at * as published by the Free Software Foundation; either version 2
* * of the License, or (at your option) any later version.
* http://www.alfresco.org/legal/license.txt
* * This program is distributed in the hope that it will be useful,
* Unless required by applicable law or agreed to in writing, * but WITHOUT ANY WARRANTY; without even the implied warranty of
* software distributed under the License is distributed on an * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * GNU General Public License for more details.
* either express or implied. See the License for the specific
* language governing permissions and limitations under the * You should have received a copy of the GNU General Public License
* 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; package org.alfresco.repo.node.index;
@@ -56,6 +64,10 @@ public class IndexTransactionTracker extends AbstractReindexComponent
private Map<Long, TxnRecord> voids; private Map<Long, TxnRecord> voids;
private boolean forceReindex; private boolean forceReindex;
private long fromTxnId;
private String statusMsg;
private static final String NO_REINDEX = "No reindex in progress";
/** /**
* Set the defaults. * Set the defaults.
* <ul> * <ul>
@@ -73,11 +85,16 @@ public class IndexTransactionTracker extends AbstractReindexComponent
maxRecordSetSize = 1000; maxRecordSetSize = 1000;
maxTransactionsPerLuceneCommit = 100; maxTransactionsPerLuceneCommit = 100;
disableInTransactionIndexing = false; disableInTransactionIndexing = false;
started = false;
previousTxnIds = Collections.<Long>emptyList(); previousTxnIds = Collections.<Long>emptyList();
lastMaxTxnId = Long.MAX_VALUE; lastMaxTxnId = Long.MAX_VALUE;
fromTimeInclusive = -1L; fromTimeInclusive = -1L;
voids = new TreeMap<Long, TxnRecord>(); voids = new TreeMap<Long, TxnRecord>();
forceReindex = false; forceReindex = false;
fromTxnId = 0L;
statusMsg = NO_REINDEX;
} }
public synchronized void setListener(IndexTransactionTrackerListener listener) public synchronized void setListener(IndexTransactionTrackerListener listener)
@@ -177,12 +194,38 @@ public class IndexTransactionTracker extends AbstractReindexComponent
return reindexInTransaction(); 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 @Override
protected void reindexImpl() protected void reindexImpl()
{ {
if (logger.isDebugEnabled())
{
logger.debug("reindexImpl started: " + this);
}
RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper(); RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
if (!started)
if ((!started) || (this.fromTxnId != 0L))
{ {
// Disable in-transaction indexing // Disable in-transaction indexing
if (disableInTransactionIndexing && nodeIndexer != null) if (disableInTransactionIndexing && nodeIndexer != null)
@@ -194,8 +237,29 @@ public class IndexTransactionTracker extends AbstractReindexComponent
voids.clear(); voids.clear();
previousTxnIds = new ArrayList<Long>(maxRecordSetSize); previousTxnIds = new ArrayList<Long>(maxRecordSetSize);
lastMaxTxnId = null; // So that it is ignored at first 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; started = true;
if (logger.isDebugEnabled())
{
logger.debug("reindexImpl: fromTimeInclusive: "+fromTimeInclusive+" "+this);
}
} }
while (true) while (true)
@@ -209,7 +273,36 @@ public class IndexTransactionTracker extends AbstractReindexComponent
} }
// Wait for the asynchronous reindexing to complete // Wait for the asynchronous reindexing to complete
waitForAsynchronousReindexing(); waitForAsynchronousReindexing();
if (logger.isDebugEnabled())
{
logger.debug("reindexImpl: completed: " + this);
}
statusMsg = NO_REINDEX;
} }
private Long getTxnCommitTime(final long txnId)
{
RetryingTransactionHelper retryingTransactionHelper = transactionService.getRetryingTransactionHelper();
RetryingTransactionCallback<Long> getTxnCommitTimeWork = new RetryingTransactionCallback<Long>()
{
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 <tt>true</tt> if the reindex process can exit otherwise <tt>false</tt> if * @return Returns <tt>true</tt> if the reindex process can exit otherwise <tt>false</tt> if
@@ -217,6 +310,8 @@ public class IndexTransactionTracker extends AbstractReindexComponent
*/ */
private boolean reindexInTransaction() private boolean reindexInTransaction()
{ {
List<Transaction> txns = null;
long toTimeExclusive = System.currentTimeMillis() - reindexLagMs; long toTimeExclusive = System.currentTimeMillis() - reindexLagMs;
// Check that the voids haven't been filled // Check that the voids haven't been filled
@@ -232,7 +327,7 @@ public class IndexTransactionTracker extends AbstractReindexComponent
} }
// get next transactions to index // get next transactions to index
List<Transaction> txns = getNextTransactions(fromTimeInclusive, toTimeExclusive, previousTxnIds); txns = getNextTransactions(fromTimeInclusive, toTimeExclusive, previousTxnIds);
// If there are no transactions, then all the work is done // If there are no transactions, then all the work is done
if (txns.size() == 0) if (txns.size() == 0)
@@ -243,14 +338,15 @@ public class IndexTransactionTracker extends AbstractReindexComponent
return false; 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()) if (logger.isDebugEnabled())
{ {
String msg = String.format( logger.debug(statusMsg);
"Reindexing %d transactions from %s (%s)",
txns.size(),
(new Date(fromTimeInclusive)).toString(),
txns.isEmpty() ? "---" : txns.get(0).getId().toString());
logger.debug(msg);
} }
// Reindex the transactions. Voids between the last set of transactions and this // 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; private static final long ONE_HOUR_MS = 3600*1000;
/** /**
* Find a transaction time to start indexing from (inclusive). The last recorded transaction by ID * Find a transaction time to start indexing from (inclusive). The last recorded transaction by ID

View File

@@ -35,7 +35,9 @@ import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.tenant.TenantService;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper; 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.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
@@ -165,7 +167,20 @@ public abstract class AbstractAuthenticationComponent implements AuthenticationC
else else
{ {
SetCurrentUserCallback callback = new SetCurrentUserCallback(userName); 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)) if ((auth == null) || (callback.ae != null))
{ {
throw callback.ae; throw callback.ae;

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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * 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 public static class Status
{ {
private final String changeTxnId; private final String changeTxnId;
private final Long dbTxnId;
private final boolean deleted; private final boolean deleted;
public Status(String changeTxnId, boolean deleted) public Status(String changeTxnId, Long dbTxnId, boolean deleted)
{ {
this.changeTxnId = changeTxnId; this.changeTxnId = changeTxnId;
this.dbTxnId = dbTxnId;
this.deleted = deleted; this.deleted = deleted;
} }
/** /**
@@ -181,11 +183,35 @@ public final class NodeRef implements EntityRef, Serializable
return changeTxnId; 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 * @return Returns true if the node has been deleted, otherwise false
*/ */
public boolean isDeleted() public boolean isDeleted()
{ {
return deleted; 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();
}
} }
} }