mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
SAIL-294: DAO refactoring - Ripping out Hibernate entity classes and refactor patches
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20753 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -23,10 +23,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.admin.patch.PatchExecuter;
|
||||
import org.alfresco.repo.domain.hibernate.HibernateSessionHelper;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
@@ -35,6 +33,7 @@ import org.alfresco.service.cmr.site.SiteInfo;
|
||||
import org.alfresco.service.cmr.site.SiteService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
/**
|
||||
* Patch to assign users and groups to default zones
|
||||
@@ -51,13 +50,9 @@ public class AuthorityDefaultZonesPatch extends AbstractPatch
|
||||
|
||||
/** The authority service. */
|
||||
private AuthorityService authorityService;
|
||||
|
||||
private AVMService avmService;
|
||||
|
||||
private SiteService siteService;
|
||||
|
||||
private HibernateSessionHelper hibernateSessionHelper;
|
||||
|
||||
/**
|
||||
* Sets the authority service.
|
||||
*
|
||||
@@ -87,14 +82,6 @@ public class AuthorityDefaultZonesPatch extends AbstractPatch
|
||||
this.siteService = siteService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hibernateSessionHelper
|
||||
*/
|
||||
public void setHibernateSessionHelper(HibernateSessionHelper hibernateSessionHelper)
|
||||
{
|
||||
this.hibernateSessionHelper = hibernateSessionHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
@@ -167,9 +154,7 @@ public class AuthorityDefaultZonesPatch extends AbstractPatch
|
||||
private int setZones(AuthorityType authorityType, List<Action> actions, int total, int start)
|
||||
{
|
||||
int count = start;
|
||||
hibernateSessionHelper.mark();
|
||||
Set<String> authorities = authorityService.getAllAuthorities(authorityType);
|
||||
hibernateSessionHelper.reset();
|
||||
for (String authority : authorities)
|
||||
{
|
||||
for (Action action : actions)
|
||||
@@ -188,7 +173,6 @@ public class AuthorityDefaultZonesPatch extends AbstractPatch
|
||||
break;
|
||||
}
|
||||
}
|
||||
hibernateSessionHelper.reset();
|
||||
count++;
|
||||
reportProgress(total, count);
|
||||
}
|
||||
|
@@ -21,45 +21,31 @@ package org.alfresco.repo.admin.patch.impl;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.sql.Savepoint;
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.admin.patch.PatchExecuter;
|
||||
import org.alfresco.repo.batch.BatchProcessWorkProvider;
|
||||
import org.alfresco.repo.batch.BatchProcessor;
|
||||
import org.alfresco.repo.batch.BatchProcessor.BatchProcessWorker;
|
||||
import org.alfresco.repo.domain.ChildAssoc;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.domain.control.ControlDAO;
|
||||
import org.alfresco.repo.domain.hibernate.ChildAssocImpl;
|
||||
import org.alfresco.repo.domain.node.NodeDAO;
|
||||
import org.alfresco.repo.domain.node.ChildAssocEntity;
|
||||
import org.alfresco.repo.domain.patch.PatchDAO;
|
||||
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryException;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hibernate.SQLQuery;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.type.LongType;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
/**
|
||||
* Fixes <a href=https://issues.alfresco.com/jira/browse/ETWOTWO-1133>ETWOTWO-1133</a>.
|
||||
@@ -74,27 +60,21 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
private static final String MSG_REWRITTEN = "patch.fixNameCrcValues.fixed";
|
||||
private static final String MSG_UNABLE_TO_CHANGE = "patch.fixNameCrcValues.unableToChange";
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
private NodeDAO nodeDAO;
|
||||
private PatchDAO patchDAO;
|
||||
private QNameDAO qnameDAO;
|
||||
private ControlDAO controlDAO;
|
||||
private RuleService ruleService;
|
||||
private Dialect dialect;
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
private static Log logger = LogFactory.getLog(FixNameCrcValuesPatch.class);
|
||||
private static Log progress_logger = LogFactory.getLog(PatchExecuter.class);
|
||||
|
||||
public FixNameCrcValuesPatch()
|
||||
{
|
||||
}
|
||||
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
public void setPatchDAO(PatchDAO patchDAO)
|
||||
{
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
public void setNodeDAO(NodeDAO nodeDAO)
|
||||
{
|
||||
this.nodeDAO = nodeDAO;
|
||||
this.patchDAO = patchDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,26 +92,20 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
{
|
||||
this.controlDAO = controlDAO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ruleService the rule service
|
||||
*/
|
||||
public void setRuleService(RuleService ruleService)
|
||||
{
|
||||
this.ruleService = ruleService;
|
||||
}
|
||||
|
||||
public void setDialect(Dialect dialect)
|
||||
/**
|
||||
* @param dictionaryService used to check the child associations for unique checking
|
||||
*/
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dialect = dialect;
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkProperties()
|
||||
{
|
||||
super.checkProperties();
|
||||
checkPropertyNotNull(sessionFactory, "sessionFactory");
|
||||
checkPropertyNotNull(nodeDAO, "nodeDAO");
|
||||
checkPropertyNotNull(patchDAO, "patchDAO");
|
||||
checkPropertyNotNull(qnameDAO, "qnameDAO");
|
||||
checkPropertyNotNull(applicationEventPublisher, "applicationEventPublisher");
|
||||
}
|
||||
@@ -140,9 +114,7 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
// initialise the helper
|
||||
HibernateHelper helper = new HibernateHelper();
|
||||
helper.setSessionFactory(sessionFactory);
|
||||
|
||||
FixNameCrcValuesHelper helper = new FixNameCrcValuesHelper();
|
||||
try
|
||||
{
|
||||
String msg = helper.fixCrcValues();
|
||||
@@ -155,12 +127,14 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
}
|
||||
}
|
||||
|
||||
private class HibernateHelper extends HibernateDaoSupport
|
||||
private class FixNameCrcValuesHelper
|
||||
{
|
||||
private File logFile;
|
||||
private FileChannel channel;
|
||||
private Integer assocCount;
|
||||
private Long minAssocId = 0L;
|
||||
|
||||
private HibernateHelper() throws IOException
|
||||
private FixNameCrcValuesHelper() throws IOException
|
||||
{
|
||||
// put the log file into a long life temp directory
|
||||
File tempDir = TempFileProvider.getLongLifeTempDir("patches");
|
||||
@@ -176,12 +150,12 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
writeLine("FixNameCrcValuesPatch executing on " + new Date());
|
||||
}
|
||||
|
||||
private HibernateHelper write(Object obj) throws IOException
|
||||
private FixNameCrcValuesHelper write(Object obj) throws IOException
|
||||
{
|
||||
channel.write(ByteBuffer.wrap(obj.toString().getBytes("UTF-8")));
|
||||
return this;
|
||||
}
|
||||
private HibernateHelper writeLine(Object obj) throws IOException
|
||||
private FixNameCrcValuesHelper writeLine(Object obj) throws IOException
|
||||
{
|
||||
write(obj);
|
||||
write("\n");
|
||||
@@ -194,76 +168,118 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
|
||||
public String fixCrcValues() throws Exception
|
||||
{
|
||||
BatchProcessWorkProvider<Map<String, Object>> workProvider = new BatchProcessWorkProvider<Map<String,Object>>()
|
||||
{
|
||||
public synchronized int getTotalEstimatedWorkSize()
|
||||
{
|
||||
if (assocCount == null)
|
||||
{
|
||||
assocCount = patchDAO.getChildAssocCount();
|
||||
}
|
||||
return assocCount.intValue();
|
||||
}
|
||||
|
||||
public Collection<Map<String, Object>> getNextWork()
|
||||
{
|
||||
// Get the next collection
|
||||
List<Map<String, Object>> results = patchDAO.getChildAssocsForCrcFix(minAssocId, 1000);
|
||||
// Find out what the last ID is
|
||||
int resultsSize = results.size();
|
||||
if (resultsSize > 0)
|
||||
{
|
||||
Map<String, Object> lastResult = results.get(resultsSize - 1);
|
||||
Long id = (Long) lastResult.get("id");
|
||||
minAssocId = id + 1L;
|
||||
}
|
||||
// Hand back the results
|
||||
return results;
|
||||
}
|
||||
};
|
||||
|
||||
// get the association types to check
|
||||
BatchProcessor<Long> batchProcessor = new BatchProcessor<Long>(
|
||||
BatchProcessor<Map<String, Object>> batchProcessor = new BatchProcessor<Map<String, Object>>(
|
||||
"FixNameCrcValuesPatch",
|
||||
transactionService.getRetryingTransactionHelper(),
|
||||
getChildAssocIdCollection(),
|
||||
workProvider,
|
||||
2, 20,
|
||||
applicationEventPublisher,
|
||||
logger, 1000);
|
||||
progress_logger, 1000);
|
||||
|
||||
// Precautionary flush and clear so that we have an empty session
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
|
||||
int updated = batchProcessor.process(new BatchProcessWorker<Long>()
|
||||
BatchProcessWorker<Map<String, Object>> worker = new BatchProcessWorker<Map<String, Object>>()
|
||||
{
|
||||
public String getIdentifier(Long entry)
|
||||
public String getIdentifier(Map<String, Object> entry)
|
||||
{
|
||||
return entry.toString();
|
||||
}
|
||||
|
||||
public void beforeProcess() throws Throwable
|
||||
{
|
||||
// Switch rules off
|
||||
ruleService.disableRules();
|
||||
// Authenticate as system
|
||||
String systemUsername = AuthenticationUtil.getSystemUserName();
|
||||
AuthenticationUtil.setFullyAuthenticatedUser(systemUsername);
|
||||
}
|
||||
|
||||
public void process(Long childAssocId) throws Throwable
|
||||
public void process(Map<String, Object> row) throws Throwable
|
||||
{
|
||||
ChildAssoc assoc = (ChildAssoc) getHibernateTemplate().get(ChildAssocImpl.class, childAssocId);
|
||||
if (assoc == null)
|
||||
Long assocId = (Long) row.get("id");
|
||||
Long typeQNameId = (Long) row.get("typeQNameId");
|
||||
Long qnameNamespaceId = (Long) row.get("qnameNamespaceId");
|
||||
String qnameLocalName = (String) row.get("qnameLocalName");
|
||||
Long childNodeNameCrc = (Long) row.get("childNodeNameCrc");
|
||||
Long qnameCrc = (Long) row.get("qnameCrc");
|
||||
String childNodeUuid = (String) row.get("childNodeUuid");
|
||||
String childNodeName = (String) row.get("childNodeName");
|
||||
// Use the UUID if there is no cm:name
|
||||
childNodeName = (childNodeName == null) ? childNodeUuid : childNodeName;
|
||||
// Resolve QNames
|
||||
QName typeQName = qnameDAO.getQName(typeQNameId).getSecond();
|
||||
String namespace = qnameDAO.getNamespace(qnameNamespaceId).getSecond();
|
||||
QName qname = QName.createQName(namespace, qnameLocalName);
|
||||
|
||||
ChildAssocEntity entity = new ChildAssocEntity();
|
||||
entity.setChildNodeNameAll(dictionaryService, typeQName, childNodeName);
|
||||
entity.setQNameAll(qnameDAO, qname, false);
|
||||
// Check the CRC values for cm:name
|
||||
if (entity.getChildNodeNameCrc().equals(childNodeNameCrc))
|
||||
{
|
||||
// Missing now ...
|
||||
return;
|
||||
// Check the CRC for the QName
|
||||
if (entity.getQnameCrc().equals(qnameCrc))
|
||||
{
|
||||
// This child assoc is good
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Get the old CRCs
|
||||
long oldChildCrc = assoc.getChildNodeNameCrc();
|
||||
long oldQNameCrc = assoc.getQnameCrc();
|
||||
|
||||
// Get the child node
|
||||
Node childNode = assoc.getChild();
|
||||
// Get the name
|
||||
String childName = (String) nodeDAO.getNodeProperty(childNode.getId(), ContentModel.PROP_NAME);
|
||||
if (childName == null)
|
||||
{
|
||||
childName = childNode.getUuid();
|
||||
}
|
||||
// Update the CRCs
|
||||
long childCrc = getCrc(childName);
|
||||
QName qname = assoc.getQName(qnameDAO);
|
||||
long qnameCrc = ChildAssocImpl.getCrc(qname);
|
||||
|
||||
// Update the assoc
|
||||
assoc.setChildNodeNameCrc(childCrc);
|
||||
assoc.setQnameCrc(qnameCrc);
|
||||
// Persist
|
||||
Savepoint savepoint = controlDAO.createSavepoint("FixNameCrcValuesPatch");
|
||||
Savepoint savepoint = null;
|
||||
try
|
||||
{
|
||||
getSession().flush();
|
||||
AssociationDefinition assocDef = dictionaryService.getAssociation(typeQName);
|
||||
if (assocDef == null)
|
||||
{
|
||||
throw new DictionaryException("Association type not defined: " + typeQName);
|
||||
}
|
||||
|
||||
// Being here indicates that the association needs to be updated
|
||||
savepoint = controlDAO.createSavepoint("FixNameCrcValuesPatch");
|
||||
patchDAO.updateChildAssocCrc(assocId, childNodeNameCrc, qnameCrc);
|
||||
controlDAO.releaseSavepoint(savepoint);
|
||||
|
||||
String msg = I18NUtil.getMessage(
|
||||
MSG_REWRITTEN,
|
||||
assocId,
|
||||
childNodeName, childNodeNameCrc, entity.getChildNodeNameCrc(),
|
||||
qname, qnameCrc, entity.getQnameCrc());
|
||||
writeLine(msg);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
controlDAO.rollbackToSavepoint(savepoint);
|
||||
|
||||
String msg = I18NUtil.getMessage(MSG_UNABLE_TO_CHANGE, childNode.getId(), childName, oldChildCrc,
|
||||
childCrc, qname, oldQNameCrc, qnameCrc, e.getMessage());
|
||||
if (savepoint != null)
|
||||
{
|
||||
controlDAO.rollbackToSavepoint(savepoint);
|
||||
}
|
||||
String msg = I18NUtil.getMessage(
|
||||
MSG_UNABLE_TO_CHANGE,
|
||||
assocId,
|
||||
childNodeName, childNodeNameCrc, entity.getChildNodeNameCrc(),
|
||||
qname, qnameCrc, entity.getQnameCrc(),
|
||||
e.getMessage());
|
||||
// We just log this and add details to the message file
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
@@ -275,134 +291,17 @@ public class FixNameCrcValuesPatch extends AbstractPatch
|
||||
}
|
||||
writeLine(msg);
|
||||
}
|
||||
getSession().clear();
|
||||
// Record
|
||||
writeLine(I18NUtil.getMessage(MSG_REWRITTEN, childNode.getId(), childName, oldChildCrc, childCrc,
|
||||
qname, oldQNameCrc, qnameCrc));
|
||||
}
|
||||
|
||||
public void afterProcess() throws Throwable
|
||||
{
|
||||
ruleService.enableRules();
|
||||
}
|
||||
}, true);
|
||||
|
||||
};
|
||||
|
||||
int updated = batchProcessor.process(worker, true);
|
||||
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, updated, logFile);
|
||||
return msg;
|
||||
}
|
||||
|
||||
private Collection<Long> getChildAssocIdCollection() throws Exception
|
||||
{
|
||||
HibernateCallback<ScrollableResults> callback = new HibernateCallback<ScrollableResults>()
|
||||
{
|
||||
public ScrollableResults doInHibernate(Session session)
|
||||
{
|
||||
SQLQuery query = session
|
||||
.createSQLQuery(
|
||||
"SELECT ca.id AS child_assoc_id FROM alf_child_assoc ca");
|
||||
|
||||
// For MySQL databases we must set this unusual fetch size to force result set paging. See
|
||||
// http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html
|
||||
if (dialect instanceof MySQLDialect)
|
||||
{
|
||||
query.setFetchSize(Integer.MIN_VALUE);
|
||||
}
|
||||
query.addScalar("child_assoc_id", new LongType());
|
||||
return query.scroll(ScrollMode.FORWARD_ONLY);
|
||||
}
|
||||
};
|
||||
final ScrollableResults rs;
|
||||
try
|
||||
{
|
||||
final int sizeEstimate = getHibernateTemplate().execute(new HibernateCallback<Integer>()
|
||||
{
|
||||
public Integer doInHibernate(Session session)
|
||||
{
|
||||
SQLQuery query = session.createSQLQuery("SELECT COUNT(*) FROM alf_child_assoc");
|
||||
return ((Number) query.uniqueResult()).intValue();
|
||||
}
|
||||
});
|
||||
|
||||
rs = getHibernateTemplate().execute(callback);
|
||||
return new AbstractCollection<Long>()
|
||||
{
|
||||
@Override
|
||||
public Iterator<Long> iterator()
|
||||
{
|
||||
return new Iterator<Long>(){
|
||||
|
||||
private Long next = fetchNext();
|
||||
|
||||
private Long fetchNext()
|
||||
{
|
||||
Long next;
|
||||
if (rs.next())
|
||||
{
|
||||
next = rs.getLong(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
next = null;
|
||||
rs.close();
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
public boolean hasNext()
|
||||
{
|
||||
return next != null;
|
||||
}
|
||||
|
||||
public Long next()
|
||||
{
|
||||
if (!hasNext())
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
Long oldNext = next;
|
||||
next = fetchNext();
|
||||
return oldNext;
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size()
|
||||
{
|
||||
return sizeEstimate;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
logger.error("Failed to query for child association IDs", e);
|
||||
writeLine("Failed to query for child association IDs: " + e.getMessage());
|
||||
throw new PatchException("Failed to query for child association IDs", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param str the name that will be converted to lowercase
|
||||
* @return the CRC32 calcualted on the lowercase version of the string
|
||||
*/
|
||||
private long getCrc(String str)
|
||||
{
|
||||
CRC32 crc = new CRC32();
|
||||
try
|
||||
{
|
||||
crc.update(str.toLowerCase().getBytes("UTF-8")); // https://issues.alfresco.com/jira/browse/ALFCOM-1335
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException("UTF-8 encoding is not supported");
|
||||
}
|
||||
return crc.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.admin.patch.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
/**
|
||||
* Checks that all names do not end with ' ' or '.'
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class InvalidNameEndingPatch extends AbstractPatch
|
||||
{
|
||||
private static final String MSG_SUCCESS = "patch.invalidNameEnding.result";
|
||||
private static final String MSG_REWRITTEN = "patch.invalidNameEnding.rewritten";
|
||||
private static final String ERR_UNABLE_TO_FIX = "patch.invalidNameEnding.err.unable_to_fix";
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String name = "fred. ... ";
|
||||
|
||||
int i = (name.length() == 0) ? 0 : name.length() - 1;
|
||||
while (i >= 0 && (name.charAt(i) == '.' || name.charAt(i) == ' '))
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
String updatedName = (i == 0) ? "unnamed" : name.substring(0, i + 1);
|
||||
System.out.println(updatedName);
|
||||
}
|
||||
|
||||
|
||||
public InvalidNameEndingPatch()
|
||||
{
|
||||
}
|
||||
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
{
|
||||
this.sessionFactory = sessionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkProperties()
|
||||
{
|
||||
super.checkProperties();
|
||||
checkPropertyNotNull(sessionFactory, "sessionFactory");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
// initialise the helper
|
||||
HibernateHelper helper = new HibernateHelper();
|
||||
helper.setSessionFactory(sessionFactory);
|
||||
|
||||
try
|
||||
{
|
||||
String msg = helper.fixNames();
|
||||
// done
|
||||
return msg;
|
||||
}
|
||||
finally
|
||||
{
|
||||
helper.closeWriter();
|
||||
}
|
||||
}
|
||||
|
||||
private class HibernateHelper extends HibernateDaoSupport
|
||||
{
|
||||
private File logFile;
|
||||
private FileChannel channel;
|
||||
|
||||
private HibernateHelper() throws IOException
|
||||
{
|
||||
File tempDir = TempFileProvider.getLongLifeTempDir("patches");
|
||||
logFile = new File(tempDir, "InvalidNameEndingPatch.log");
|
||||
|
||||
// open the file for appending
|
||||
RandomAccessFile outputFile = new RandomAccessFile(logFile, "rw");
|
||||
channel = outputFile.getChannel();
|
||||
// move to the end of the file
|
||||
channel.position(channel.size());
|
||||
// add a newline and it's ready
|
||||
writeLine("").writeLine("");
|
||||
writeLine("InvalidNameEndingPatch executing on " + new Date());
|
||||
}
|
||||
|
||||
private HibernateHelper write(Object obj) throws IOException
|
||||
{
|
||||
channel.write(ByteBuffer.wrap(obj.toString().getBytes()));
|
||||
return this;
|
||||
}
|
||||
private HibernateHelper writeLine(Object obj) throws IOException
|
||||
{
|
||||
write(obj);
|
||||
write("\n");
|
||||
return this;
|
||||
}
|
||||
private void closeWriter()
|
||||
{
|
||||
try { channel.close(); } catch (Throwable e) {}
|
||||
}
|
||||
|
||||
public String fixNames() throws Exception
|
||||
{
|
||||
// get the association types to check
|
||||
List<Node> nodes = getInvalidNames();
|
||||
|
||||
int updated = 0;
|
||||
for (Node node : nodes)
|
||||
{
|
||||
NodeRef nodeRef = node.getNodeRef();
|
||||
String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
if (name != null && (name.endsWith(".") || name.endsWith(" ")))
|
||||
{
|
||||
int i = (name.length() == 0) ? 0 : name.length() - 1;
|
||||
while (i >= 0 && (name.charAt(i) == '.' || name.charAt(i) == ' '))
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
String updatedName = (i == 0) ? "unnamed" : name.substring(0, i + 1);
|
||||
int idx = 0;
|
||||
boolean applied = false;
|
||||
while (!applied)
|
||||
{
|
||||
try
|
||||
{
|
||||
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, updatedName);
|
||||
applied = true;
|
||||
}
|
||||
catch(DuplicateChildNodeNameException e)
|
||||
{
|
||||
idx++;
|
||||
if (idx > 10)
|
||||
{
|
||||
writeLine(I18NUtil.getMessage(ERR_UNABLE_TO_FIX, name ,updatedName));
|
||||
throw new PatchException(ERR_UNABLE_TO_FIX, logFile);
|
||||
}
|
||||
updatedName += "_" + idx;
|
||||
}
|
||||
}
|
||||
writeLine(I18NUtil.getMessage(MSG_REWRITTEN, name ,updatedName));
|
||||
updated++;
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
}
|
||||
}
|
||||
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, updated, logFile);
|
||||
return msg;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<Node> getInvalidNames()
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
Query query = session
|
||||
.createQuery(
|
||||
"select node from org.alfresco.repo.domain.hibernate.NodeImpl as node " +
|
||||
"join node.properties prop where " +
|
||||
" prop.stringValue like '%.' or " +
|
||||
" prop.stringValue like '% ' ");
|
||||
return query.list();
|
||||
}
|
||||
};
|
||||
List<Node> results = (List<Node>) getHibernateTemplate().execute(callback);
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -22,21 +22,20 @@ import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.sql.Savepoint;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.admin.patch.AbstractPatch;
|
||||
import org.alfresco.repo.domain.hibernate.NodeImpl;
|
||||
import org.alfresco.service.cmr.admin.PatchException;
|
||||
import org.alfresco.repo.domain.control.ControlDAO;
|
||||
import org.alfresco.repo.domain.patch.PatchDAO;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
/**
|
||||
@@ -50,45 +49,47 @@ public class LinkNodeFileExtensionPatch extends AbstractPatch
|
||||
private static final String MSG_REWRITTEN = "patch.linkNodeExtension.rewritten";
|
||||
private static final String ERR_UNABLE_TO_FIX = "patch.linkNodeExtension.err.unable_to_fix";
|
||||
|
||||
private SessionFactory sessionFactory;
|
||||
private PatchDAO patchDAO;
|
||||
private ControlDAO controlDAO;
|
||||
private NodeService nodeService;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
*/
|
||||
public LinkNodeFileExtensionPatch()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the session factory
|
||||
*
|
||||
* @param sessionFactory SessionFactory
|
||||
*/
|
||||
public void setSessionFactory(SessionFactory sessionFactory)
|
||||
public void setPatchDAO(PatchDAO patchDAO)
|
||||
{
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.patchDAO = patchDAO;
|
||||
}
|
||||
|
||||
public void setControlDAO(ControlDAO controlDAO)
|
||||
{
|
||||
this.controlDAO = controlDAO;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkProperties()
|
||||
{
|
||||
super.checkProperties();
|
||||
checkPropertyNotNull(sessionFactory, "sessionFactory");
|
||||
checkPropertyNotNull(patchDAO, "patchDAO");
|
||||
checkPropertyNotNull(nodeService, "nodeService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String applyInternal() throws Exception
|
||||
{
|
||||
// Initialise the helper
|
||||
|
||||
HibernateHelper helper = new HibernateHelper();
|
||||
helper.setSessionFactory(sessionFactory);
|
||||
LinkNodeFileExtensionHelper helper = new LinkNodeFileExtensionHelper();
|
||||
|
||||
try
|
||||
{
|
||||
// Fix the link node file names
|
||||
|
||||
return helper.fixNames();
|
||||
}
|
||||
finally
|
||||
@@ -97,12 +98,12 @@ public class LinkNodeFileExtensionPatch extends AbstractPatch
|
||||
}
|
||||
}
|
||||
|
||||
private class HibernateHelper extends HibernateDaoSupport
|
||||
private class LinkNodeFileExtensionHelper extends HibernateDaoSupport
|
||||
{
|
||||
private File logFile;
|
||||
private FileChannel channel;
|
||||
|
||||
private HibernateHelper() throws IOException
|
||||
private LinkNodeFileExtensionHelper() throws IOException
|
||||
{
|
||||
// Open a log file
|
||||
File tempDir = TempFileProvider.getLongLifeTempDir("patches");
|
||||
@@ -119,12 +120,12 @@ public class LinkNodeFileExtensionPatch extends AbstractPatch
|
||||
writeLine("LinkNodeExtensionPatch executing on " + new Date());
|
||||
}
|
||||
|
||||
private HibernateHelper write(Object obj) throws IOException
|
||||
private LinkNodeFileExtensionHelper write(Object obj) throws IOException
|
||||
{
|
||||
channel.write(ByteBuffer.wrap(obj.toString().getBytes()));
|
||||
return this;
|
||||
}
|
||||
private HibernateHelper writeLine(Object obj) throws IOException
|
||||
private LinkNodeFileExtensionHelper writeLine(Object obj) throws IOException
|
||||
{
|
||||
write(obj);
|
||||
write("\n");
|
||||
@@ -137,78 +138,46 @@ public class LinkNodeFileExtensionPatch extends AbstractPatch
|
||||
|
||||
public String fixNames() throws Exception
|
||||
{
|
||||
// Get the list of nodes to be updated
|
||||
|
||||
List<NodeImpl> nodes = getInvalidNames();
|
||||
List<Pair<NodeRef, String>> names = patchDAO.getNodesOfTypeWithNamePattern(ContentModel.TYPE_LINK, "%.lnk");
|
||||
|
||||
int updated = 0;
|
||||
for (NodeImpl node : nodes)
|
||||
for (Pair<NodeRef, String> pair : names)
|
||||
{
|
||||
// Check that the node is a link node
|
||||
|
||||
NodeRef nodeRef = node.getNodeRef();
|
||||
|
||||
if ( nodeService.getProperty(nodeRef, ContentModel.PROP_LINK_DESTINATION) != null)
|
||||
NodeRef nodeRef = pair.getFirst();
|
||||
String name = pair.getSecond();
|
||||
// Update the name string, replace '.lnk' with '.url'
|
||||
String updatedName = name.substring(0, name.length() - 4) + ".url";
|
||||
int idx = 0;
|
||||
boolean applied = false;
|
||||
while (!applied && idx < 10)
|
||||
{
|
||||
// Get the current file name
|
||||
|
||||
String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
if (name != null && name.length() >= 4 && name.endsWith(".lnk"))
|
||||
{
|
||||
// Update the name string, replace '.lnk' with '.url'
|
||||
|
||||
String updatedName = name.substring(0, name.length() - 4) + ".url";
|
||||
|
||||
int idx = 0;
|
||||
boolean applied = false;
|
||||
while (!applied)
|
||||
{
|
||||
try
|
||||
{
|
||||
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, updatedName);
|
||||
applied = true;
|
||||
}
|
||||
catch(DuplicateChildNodeNameException e)
|
||||
{
|
||||
idx++;
|
||||
if (idx > 10)
|
||||
{
|
||||
writeLine(I18NUtil.getMessage(ERR_UNABLE_TO_FIX, name, updatedName));
|
||||
throw new PatchException(ERR_UNABLE_TO_FIX, logFile);
|
||||
}
|
||||
updatedName += "_" + idx;
|
||||
}
|
||||
}
|
||||
writeLine(I18NUtil.getMessage(MSG_REWRITTEN, name ,updatedName));
|
||||
updated++;
|
||||
getSession().flush();
|
||||
getSession().clear();
|
||||
}
|
||||
Savepoint savepoint = controlDAO.createSavepoint("LinkNodeFileExtensionsFix");
|
||||
try
|
||||
{
|
||||
nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, updatedName);
|
||||
controlDAO.releaseSavepoint(savepoint);
|
||||
applied = true;
|
||||
}
|
||||
catch(DuplicateChildNodeNameException e)
|
||||
{
|
||||
controlDAO.rollbackToSavepoint(savepoint);
|
||||
idx++;
|
||||
updatedName += "_" + idx;
|
||||
}
|
||||
}
|
||||
if (applied)
|
||||
{
|
||||
writeLine(I18NUtil.getMessage(MSG_REWRITTEN, name ,updatedName));
|
||||
}
|
||||
else
|
||||
{
|
||||
writeLine(I18NUtil.getMessage(ERR_UNABLE_TO_FIX, name, updatedName));
|
||||
}
|
||||
updated++;
|
||||
}
|
||||
|
||||
String msg = I18NUtil.getMessage(MSG_SUCCESS, updated, logFile);
|
||||
return msg;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<NodeImpl> getInvalidNames()
|
||||
{
|
||||
HibernateCallback callback = new HibernateCallback()
|
||||
{
|
||||
public Object doInHibernate(Session session)
|
||||
{
|
||||
Query query = session
|
||||
.createQuery(
|
||||
"select node from org.alfresco.repo.domain.hibernate.NodeImpl as node " +
|
||||
"join node.properties prop where " +
|
||||
" prop.stringValue like '%.lnk' ");
|
||||
return query.list();
|
||||
}
|
||||
};
|
||||
List<NodeImpl> results = (List<NodeImpl>) getHibernateTemplate().execute(callback);
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user