Merged V3.4-BUG-FIX to HEAD

28741: Merged DEV/TEMPORARY to V3.4-BUG-FIX
      28740: ALF-8993: IMAP favourite star is not visible if imap is enabled via JMX
         The org.alfresco.repo.imap.ImapService interface was extended to expose getEnabled() and made the webscript to call ImapService.getEnabled().
   28742: ALF-8801: Broken French strings
   28745: ALF-6470: French string correction
   28746: ALF-5607: Installer deletion of directories on installation cancel.
   28756: ALF-9211: Install fails when path selected that contains accents or double byte chars (e.g. Japanese)
   - Fix from Bitrock
   - Not internationalized yet
   28758: Merged DEV to V3.4-BUG-FIX
      28743: ALF-8029: JSON returned by some audit queries not valide
             Quote user in query.get.json.ftl if it has value.
   28761: Merged DEV to V3.4-BUG-FIX
      28739: ALF-9123 : "Content URL conversion failed" error being thrown
      Note: Actually changed the implementation but the principle remains.
      In future, use a thread-safe boolean e.g. AtomicBoolean to carry data
      around about the running state; don't use a class member variable as
      it can be manipulated by competing threads, etc.
   28762: Fix ALF-9376: Typo in Version2Model
   28763: Merged DEV to V3.4-BUG-FIX
      28754: ALF-8461: Invalid property cm:source (cm:copiedFrom) causes not be become sys:incomplete
             Configurable property called 'propertiesToIgnore' was added to IncompleteNodeTagger,and configured to ignore "cm:source".
      Merge note: I fixed the stored 'propertiesToIgnore' to be a Set<QName> to prevent unnecessary conversions
   28764: ALF-9036: Fix NPE on XForm session timeout
   28765: ALF-9211: Externalized new installer message
   - Needs localizing
   28789: ALF-9407: Single quote characters in messages containing {} need to be doubled


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@28793 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Dave Ward
2011-07-04 15:00:07 +00:00
parent 212e229c73
commit 629bfa0735
29 changed files with 145 additions and 129 deletions

View File

@@ -22,6 +22,7 @@ import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.admin.patch.AbstractPatch;
@@ -39,6 +40,7 @@ import org.alfresco.repo.domain.control.ControlDAO;
import org.alfresco.repo.domain.patch.PatchDAO;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.lock.JobLockService.JobLockRefreshCallback;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
@@ -101,7 +103,6 @@ public class ContentUrlConverterPatch extends AbstractPatch
// Lock as per patching
private static Log logger = LogFactory.getLog(PatchExecuter.class);
private static VmShutdownListener shutdownListener = new VmShutdownListener("ContentUrlConverterPatch");
private RegistryService registryService;
private JobLockService jobLockService;
@@ -255,7 +256,7 @@ public class ContentUrlConverterPatch extends AbstractPatch
logger.info(report);
}
}
/**
* Gets a set of work to do and executes it within this transaction. If kicked off via a job,
* the task will exit before completion, on the assumption that it will be kicked off at regular
@@ -278,7 +279,6 @@ public class ContentUrlConverterPatch extends AbstractPatch
return I18NUtil.getMessage("patch.convertContentUrls.bypassingPatch");
}
boolean completed = false;
// Lock in proportion to the batch size (0.1s per node or 0.8 min per 500)
String lockToken = getLock(batchSize*100L);
if (lockToken == null)
@@ -294,16 +294,32 @@ public class ContentUrlConverterPatch extends AbstractPatch
throw new RuntimeException("Unable to get job lock during patch execution. Only one server should perform the upgrade.");
}
}
// Use a flag to keep track of the running job
final AtomicBoolean running = new AtomicBoolean(true);
jobLockService.refreshLock(lockToken, LOCK, batchSize*100, new JobLockRefreshCallback()
{
@Override
public boolean isActive()
{
return running.get();
}
@Override
public void lockReleased()
{
running.set(false);
}
});
boolean completed = false;
try
{
logger.info(I18NUtil.getMessage("patch.convertContentUrls.start"));
logger.info(I18NUtil.getMessage("patch.convertContentUrls.adm.start"));
boolean admCompleted = applyADM(lockToken);
boolean admCompleted = applyADMLooping(running);
logger.info(I18NUtil.getMessage("patch.convertContentUrls.avm.start"));
boolean avmCompleted = applyAVM(lockToken);
boolean avmCompleted = applyAVMLooping(running);
logger.info(I18NUtil.getMessage("patch.convertContentUrls.store.start", contentStore));
boolean urlLiftingCompleted = applyUrlLifting(lockToken);
boolean urlLiftingCompleted = applyUrlLifting(running);
completed = admCompleted && avmCompleted && urlLiftingCompleted;
}
@@ -316,7 +332,8 @@ public class ContentUrlConverterPatch extends AbstractPatch
}
finally
{
jobLockService.releaseLock(lockToken, LOCK);
// The lock will self-release if answer isActive in the negative
running.set(false);
}
if (completed)
@@ -346,21 +363,7 @@ public class ContentUrlConverterPatch extends AbstractPatch
}
}
/**
* Attempts to get the lock. If it fails, the current transaction is marked for rollback.
*
* @return Returns the lock token
*/
private void refreshLock(String lockToken, long time)
{
if (lockToken == null)
{
throw new IllegalArgumentException("Must provide existing lockToken");
}
jobLockService.refreshLock(lockToken, LOCK, time);
}
private boolean applyADM(final String lockToken)
private boolean applyADMLooping(final AtomicBoolean running)
{
RetryingTransactionCallback<Boolean> callback = new RetryingTransactionCallback<Boolean>()
{
@@ -370,10 +373,8 @@ public class ContentUrlConverterPatch extends AbstractPatch
}
};
boolean done = false;
while (true && !shutdownListener.isVmShuttingDown())
while (running.get())
{
refreshLock(lockToken, batchSize*100L);
done = transactionHelper.doInTransaction(callback, false, true);
if (done)
{
@@ -467,7 +468,7 @@ public class ContentUrlConverterPatch extends AbstractPatch
return false;
}
private boolean applyAVM(final String lockToken)
private boolean applyAVMLooping(final AtomicBoolean running)
{
RetryingTransactionCallback<Boolean> callback = new RetryingTransactionCallback<Boolean>()
{
@@ -477,10 +478,8 @@ public class ContentUrlConverterPatch extends AbstractPatch
}
};
boolean done = false;
while (true && !shutdownListener.isVmShuttingDown())
while (running.get())
{
refreshLock(lockToken, batchSize*100L);
done = transactionHelper.doInTransaction(callback, false, true);
if (done)
{
@@ -565,19 +564,19 @@ public class ContentUrlConverterPatch extends AbstractPatch
return false;
}
private boolean applyUrlLifting(final String lockToken) throws Exception
private boolean applyUrlLifting(final AtomicBoolean running) throws Exception
{
RetryingTransactionCallback<Boolean> callback = new RetryingTransactionCallback<Boolean>()
{
public Boolean execute() throws Throwable
{
return applyUrlLiftingInTxn(lockToken);
return applyUrlLiftingInTxn(running);
}
};
return transactionHelper.doInTransaction(callback, false, true);
}
private boolean applyUrlLiftingInTxn(final String lockToken) throws Exception
private boolean applyUrlLiftingInTxn(final AtomicBoolean running) throws Exception
{
// Check the store
if (!contentStore.isWriteSupported())
@@ -613,8 +612,9 @@ public class ContentUrlConverterPatch extends AbstractPatch
private int allCount = 0;
public void handle(String contentUrl)
{
if (shutdownListener.isVmShuttingDown())
if (!running.get())
{
// Either VM shutdown or lock release. Either way, bug out.
throw new VmShutdownListener.VmShutdownException();
}
@@ -643,8 +643,6 @@ public class ContentUrlConverterPatch extends AbstractPatch
allCount++;
if (allCount % batchSize == 0)
{
// Update our lock
refreshLock(lockToken, batchSize*100L);
if (totalSize < 0)
{
// Report

View File

@@ -279,5 +279,11 @@ public interface ImapService
NodeRef messageFile,
MimeMessage originalMessage)
throws IOException, MessagingException;
/**
* Determines whether the IMAP server is enabled.
*
* @return true if enabled
*/
public boolean getImapServerEnabled();
}

View File

@@ -147,6 +147,8 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
private final static Map<QName, Flags.Flag> qNameToFlag;
private final static Map<Flags.Flag, QName> flagToQname;
private boolean imapServerEnabled = false;
static
{
qNameToFlag = new HashMap<QName, Flags.Flag>();
@@ -175,22 +177,16 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
public static class ImapServiceBootstrap extends AbstractLifecycleBean
{
private ImapServiceImpl service;
private boolean imapServerEnabled;
public void setService(ImapServiceImpl service)
{
this.service = service;
}
public void setImapServerEnabled(boolean imapServerEnabled)
{
this.imapServerEnabled = imapServerEnabled;
}
@Override
protected void onBootstrap(ApplicationEvent event)
{
if (imapServerEnabled)
if (service.getImapServerEnabled())
{
service.startup();
}
@@ -199,7 +195,7 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
@Override
protected void onShutdown(ApplicationEvent event)
{
if (imapServerEnabled)
if (service.getImapServerEnabled())
{
service.shutdown();
}
@@ -305,6 +301,16 @@ public class ImapServiceImpl implements ImapService, OnCreateChildAssociationPol
this.extractAttachmentsEnabled = extractAttachmentsEnabled;
}
public void setImapServerEnabled(boolean enabled)
{
this.imapServerEnabled = enabled;
}
public boolean getImapServerEnabled()
{
return this.imapServerEnabled;
}
// ---------------------- Lifecycle Methods ------------------------------
public void init()

View File

@@ -77,6 +77,7 @@ public class IncompleteNodeTagger
private DictionaryService dictionaryService;
private NodeService nodeService;
private List<String> storesToIgnore = new ArrayList<String>(0);
private Set<QName> propertiesToIgnore = new HashSet<QName>();
public IncompleteNodeTagger()
{
@@ -115,6 +116,19 @@ public class IncompleteNodeTagger
this.storesToIgnore = storesToIgnore;
}
/**
* @param propertiesToIgnore a list of property fully-qualified names to ignore
*/
public void setPropertiesToIgnore(List<String> propertiesToIgnore)
{
this.propertiesToIgnore = new HashSet<QName>();
for (String qnameStr : propertiesToIgnore)
{
QName qname = QName.createQName(qnameStr);
this.propertiesToIgnore.add(qname);
}
}
/**
* Registers the system-level policy behaviours
*/
@@ -493,6 +507,11 @@ public class IncompleteNodeTagger
{
for (PropertyDefinition propertyDef : propertyDefs)
{
if (propertiesToIgnore.contains(propertyDef.getName()))
{
continue;
}
if (!propertyDef.isMandatory())
{
// The property isn't mandatory in any way

View File

@@ -82,7 +82,7 @@ public interface Version2Model extends VersionBaseModel
public static final String PROP_FROZEN_CREATED = "frozenCreated";
public static final QName PROP_QNAME_FROZEN_CREATED = QName.createQName(NAMESPACE_URI, PROP_FROZEN_CREATED);
public static final String PROP_FROZEN_MODIFIER = "frozenModifer";
public static final String PROP_FROZEN_MODIFIER = "frozenModifier";
public static final QName PROP_QNAME_FROZEN_MODIFIER = QName.createQName(NAMESPACE_URI, PROP_FROZEN_MODIFIER);
public static final String PROP_FROZEN_MODIFIED = "frozenModified";