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:
Derek Hulley
2010-06-22 13:44:03 +00:00
parent db40093488
commit 472fde8509
53 changed files with 420 additions and 7687 deletions

View File

@@ -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);
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}