diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index e379a0afb4..777d40903c 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -278,3 +278,6 @@ patch.authorityMigration.result=Migrated {0} authorities to the spaces store.
patch.authorityDefaultZonesPatch.description=Adds groups and people to the appropriate zones for wcm, share and everything else.
patch.authorityDefaultZonesPatch.result=Unzoned groups and people added to the default zones.
+patch.fixNameCrcValues.description=Fixes name CRC32 values to match UTF-8 encoding.
+patch.fixNameCrcValues.result=Fixed {0} name CRC32 values for UTF-8 encoding. See file {1} for details.
+patch.fixNameCrcValues.fixed=Updated CRC32 value for node ID {0}, name ''{1}'': {2} -> {3}.
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 80cd95e18e..e717157221 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -1646,8 +1646,8 @@
-
-
+
+
patch.db-V2.2-Person-2
patch.schemaUpgradeScript.description
0
@@ -1833,4 +1833,28 @@
+
+ patch.fixNameCrcValues
+ patch.fixNameCrcValues.description
+ 0
+ 2014
+ 2015
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties
index 900c70e119..841c0fa1ed 100644
--- a/config/alfresco/version.properties
+++ b/config/alfresco/version.properties
@@ -19,4 +19,4 @@ version.build=@build-number@
# Schema number
-version.schema=2014
+version.schema=2015
diff --git a/source/java/org/alfresco/jcr/exporter/JCRDocumentXMLExporter.java b/source/java/org/alfresco/jcr/exporter/JCRDocumentXMLExporter.java
index 9c1c7fc049..b97f51765e 100644
--- a/source/java/org/alfresco/jcr/exporter/JCRDocumentXMLExporter.java
+++ b/source/java/org/alfresco/jcr/exporter/JCRDocumentXMLExporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -29,6 +29,7 @@ import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Locale;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
@@ -376,7 +377,15 @@ public class JCRDocumentXMLExporter implements Exporter
public void endReference(NodeRef nodeRef)
{
}
-
+
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ }
+
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ }
+
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#warning(java.lang.String)
*/
diff --git a/source/java/org/alfresco/jcr/exporter/JCRSystemXMLExporter.java b/source/java/org/alfresco/jcr/exporter/JCRSystemXMLExporter.java
index 55906380cc..67b7292c46 100644
--- a/source/java/org/alfresco/jcr/exporter/JCRSystemXMLExporter.java
+++ b/source/java/org/alfresco/jcr/exporter/JCRSystemXMLExporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,6 +26,7 @@ package org.alfresco.jcr.exporter;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Locale;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -436,7 +437,15 @@ public class JCRSystemXMLExporter implements Exporter
public void endReference(NodeRef nodeRef)
{
}
-
+
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ }
+
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ }
+
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#warning(java.lang.String)
*/
diff --git a/source/java/org/alfresco/repo/admin/patch/impl/FixNameCrcValuesPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/FixNameCrcValuesPatch.java
new file mode 100644
index 0000000000..f797183af4
--- /dev/null
+++ b/source/java/org/alfresco/repo/admin/patch/impl/FixNameCrcValuesPatch.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have recieved a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+package org.alfresco.repo.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.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.zip.CRC32;
+
+import org.alfresco.i18n.I18NUtil;
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.admin.patch.AbstractPatch;
+import org.alfresco.repo.domain.ChildAssoc;
+import org.alfresco.repo.domain.Node;
+import org.alfresco.repo.domain.QNameDAO;
+import org.alfresco.repo.domain.hibernate.ChildAssocImpl;
+import org.alfresco.repo.node.db.NodeDaoService;
+import org.alfresco.service.cmr.admin.PatchException;
+import org.hibernate.SQLQuery;
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.type.LongType;
+import org.hibernate.type.StringType;
+import org.springframework.orm.hibernate3.HibernateCallback;
+import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
+
+/**
+ * Fixes ETWOTWO-1133.
+ * Checks all CRC values for alf_child_assoc.child_node_name_crc.
+ *
+ * @author Derek Hulley
+ * @since V2.2SP4
+ */
+public class FixNameCrcValuesPatch extends AbstractPatch
+{
+ private static final String MSG_SUCCESS = "patch.fixNameCrcValues.result";
+ private static final String MSG_REWRITTEN = "patch.fixNameCrcValues.fixed";
+
+ private SessionFactory sessionFactory;
+ private NodeDaoService nodeDaoService;
+ private QNameDAO qnameDAO;
+
+ public FixNameCrcValuesPatch()
+ {
+ }
+
+ public void setSessionFactory(SessionFactory sessionFactory)
+ {
+ this.sessionFactory = sessionFactory;
+ }
+
+ /**
+ * @param nodeDaoService The service that generates the CRC values
+ */
+ public void setNodeDaoService(NodeDaoService nodeDaoService)
+ {
+ this.nodeDaoService = nodeDaoService;
+ }
+
+ /**
+ * @param qnameDAO resolved QNames
+ */
+ public void setQnameDAO(QNameDAO qnameDAO)
+ {
+ this.qnameDAO = qnameDAO;
+ }
+
+ @Override
+ protected void checkProperties()
+ {
+ super.checkProperties();
+ checkPropertyNotNull(sessionFactory, "sessionFactory");
+ checkPropertyNotNull(nodeDaoService, "nodeDaoService");
+ checkPropertyNotNull(qnameDAO, "qnameDAO");
+ }
+
+ @Override
+ protected String applyInternal() throws Exception
+ {
+ // initialise the helper
+ HibernateHelper helper = new HibernateHelper();
+ helper.setSessionFactory(sessionFactory);
+
+ try
+ {
+ String msg = helper.fixCrcValues();
+ // done
+ return msg;
+ }
+ finally
+ {
+ helper.closeWriter();
+ }
+ }
+
+ private class HibernateHelper extends HibernateDaoSupport
+ {
+ private File logFile;
+ private FileChannel channel;
+
+ private HibernateHelper() throws IOException
+ {
+ logFile = new File("./FixNameCrcValuesPatch.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("FixNameCrcValuesPatch executing on " + new Date());
+ }
+
+ private HibernateHelper write(Object obj) throws IOException
+ {
+ channel.write(ByteBuffer.wrap(obj.toString().getBytes("UTF-8")));
+ 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 fixCrcValues() throws Exception
+ {
+ // get the association types to check
+ @SuppressWarnings("unused")
+ List childAssocIds = findMismatchedCrcs();
+
+ int updated = 0;
+ for (Long childAssocId : childAssocIds)
+ {
+ ChildAssoc assoc = (ChildAssoc) getHibernateTemplate().get(ChildAssocImpl.class, childAssocId);
+ if (assoc == null)
+ {
+ // Missing now ...
+ continue;
+ }
+ // Get the old CRC
+ long oldCrc = assoc.getChildNodeNameCrc();
+ // Get the child node
+ Node childNode = assoc.getChild();
+ // Get the name
+ String childName = (String) nodeDaoService.getNodeProperty(childNode.getId(), ContentModel.PROP_NAME);
+ if (childName == null)
+ {
+ childName = childNode.getUuid();
+ }
+ // Update the CRC
+ long crc = getCrc(childName);
+ // Update the assoc
+ assoc.setChildNodeNameCrc(crc);
+ // Persist
+ updated++;
+ getSession().flush();
+ getSession().clear();
+ // Record
+ writeLine(I18NUtil.getMessage(MSG_REWRITTEN, childNode.getId(), childName, oldCrc, crc));
+ }
+
+ String msg = I18NUtil.getMessage(MSG_SUCCESS, updated, logFile);
+ return msg;
+ }
+
+ @SuppressWarnings("unchecked")
+ private List findMismatchedCrcs() throws Exception
+ {
+ final Long qnameId = qnameDAO.getOrCreateQName(ContentModel.PROP_NAME).getFirst();
+
+ final List childAssocIds = new ArrayList(1000);
+ HibernateCallback callback = new HibernateCallback()
+ {
+ public Object doInHibernate(Session session)
+ {
+ SQLQuery query = session
+ .createSQLQuery(
+ " SELECT " +
+ " ca.id AS child_assoc_id," +
+ " ca.child_node_name_crc AS child_assoc_crc," +
+ " np.string_value AS node_name," +
+ " n.uuid as node_uuid" +
+ " FROM" +
+ " alf_child_assoc ca" +
+ " JOIN alf_node n ON (ca.child_node_id = n.id AND ca.child_node_name_crc > 0)" +
+ " JOIN alf_node_properties np on (np.node_id = n.id AND np.qname_id = :qnameId)" +
+ "");
+ query.setLong("qnameId", qnameId);
+ query.addScalar("child_assoc_id", new LongType());
+ query.addScalar("child_assoc_crc", new LongType());
+ query.addScalar("node_name", new StringType());
+ query.addScalar("node_uuid", new StringType());
+ return query.scroll(ScrollMode.FORWARD_ONLY);
+ }
+ };
+ ScrollableResults rs = null;
+ try
+ {
+ rs = (ScrollableResults) getHibernateTemplate().execute(callback);
+ while (rs.next())
+ {
+ Long assocId = (Long) rs.get(0);
+ Long dbCrc = (Long) rs.get(1);
+ String name = (String) rs.get(2);
+ String uuid = (String) rs.get(3);
+ long utf8Crc = -1L;
+ if (name != null)
+ {
+ utf8Crc = getCrc(name);
+ }
+ else
+ {
+ utf8Crc = getCrc(uuid);
+ }
+ // Check
+ if (dbCrc != null && utf8Crc == dbCrc.longValue())
+ {
+ // It is a match, so ignore
+ continue;
+ }
+ childAssocIds.add(assocId);
+ }
+ }
+ catch (Throwable e)
+ {
+ logger.error("Failed to query for child name CRCs", e);
+ writeLine("Failed to query for child name CRCs: " + e.getMessage());
+ throw new PatchException("Failed to query for child name CRCs", e);
+ }
+ finally
+ {
+ if (rs != null)
+ {
+ try { rs.close(); } catch (Throwable e) { writeLine("Failed to close resultset: " + e.getMessage()); }
+ }
+ }
+ return childAssocIds;
+ }
+
+ /**
+ * @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();
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/exporter/ChainedExporter.java b/source/java/org/alfresco/repo/exporter/ChainedExporter.java
index c3a04bb667..5c251d9234 100644
--- a/source/java/org/alfresco/repo/exporter/ChainedExporter.java
+++ b/source/java/org/alfresco/repo/exporter/ChainedExporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -27,6 +27,7 @@ package org.alfresco.repo.exporter;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -350,7 +351,23 @@ import org.alfresco.service.namespace.QName;
exporter.endReference(nodeRef);
}
}
-
+
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ for (Exporter exporter : exporters)
+ {
+ exporter.startValueMLText(nodeRef, locale);
+ }
+ }
+
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ for (Exporter exporter : exporters)
+ {
+ exporter.endValueMLText(nodeRef);
+ }
+ }
+
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#warning(java.lang.String)
*/
diff --git a/source/java/org/alfresco/repo/exporter/ExporterComponent.java b/source/java/org/alfresco/repo/exporter/ExporterComponent.java
index 4a1a9e99cb..f001d1bd15 100644
--- a/source/java/org/alfresco/repo/exporter/ExporterComponent.java
+++ b/source/java/org/alfresco/repo/exporter/ExporterComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -34,10 +34,12 @@ import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.alfresco.model.ContentModel;
+import org.alfresco.repo.node.MLPropertyInterceptor;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -46,6 +48,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
@@ -427,7 +430,9 @@ public class ExporterComponent
// Export node properties
exporter.startProperties(nodeRef);
+ boolean aware = MLPropertyInterceptor.setMLAware(true);
Map properties = nodeService.getProperties(nodeRef);
+ MLPropertyInterceptor.setMLAware(aware);
for (QName property : properties.keySet())
{
// filter out properties whose namespace is excluded
@@ -459,7 +464,27 @@ public class ExporterComponent
}
else
{
- walkProperty(nodeRef, property, value, -1, parameters, exporter);
+ if (value instanceof MLText)
+ {
+ MLText valueMLT = (MLText) value;
+ Set locales = valueMLT.getLocales();
+ for (Locale locale : locales)
+ {
+ String localeValue = valueMLT.getValue(locale);
+ if (localeValue == null)
+ {
+ walkProperty(nodeRef, property, localeValue, -1, parameters, exporter);
+ continue;
+ }
+ exporter.startValueMLText(nodeRef, locale);
+ walkProperty(nodeRef, property, localeValue, -1, parameters, exporter);
+ exporter.endValueMLText(nodeRef);
+ }
+ }
+ else
+ {
+ walkProperty(nodeRef, property, value, -1, parameters, exporter);
+ }
}
// end export of property
diff --git a/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java b/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java
index f472c36116..8a6b66a7a5 100644
--- a/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java
+++ b/source/java/org/alfresco/repo/exporter/ExporterComponentTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -28,7 +28,9 @@ import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.util.Locale;
+import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentData;
@@ -96,7 +98,10 @@ public class ExporterComponentTest extends BaseSpringTest
InputStream test = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml");
InputStreamReader testReader = new InputStreamReader(test, "UTF-8");
importerService.importView(testReader, location, null, null);
- System.out.println(NodeStoreInspector.dumpNodeStore((NodeService)applicationContext.getBean("NodeService"), storeRef));
+
+ dumpNodeStore(Locale.ENGLISH);
+ dumpNodeStore(Locale.FRENCH);
+ dumpNodeStore(Locale.GERMAN);
// now export
location.setPath("/system");
@@ -108,6 +113,13 @@ public class ExporterComponentTest extends BaseSpringTest
output.close();
}
+ private void dumpNodeStore(Locale locale)
+ {
+
+ System.out.println(locale.getDisplayLanguage() + " LOCALE: ");
+ I18NUtil.setLocale(locale);
+ System.out.println(NodeStoreInspector.dumpNodeStore((NodeService) applicationContext.getBean("NodeService"), storeRef));
+ }
private static class TestProgress
implements Exporter
@@ -253,6 +265,16 @@ public class ExporterComponentTest extends BaseSpringTest
// System.out.println("TestProgress: endReference: " + nodeRef);
}
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ System.out.println("TestProgress: end MLValue.");
+ }
+
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ System.out.println("TestProgress: start MLValue for locale: " + locale);
+ }
+
}
}
diff --git a/source/java/org/alfresco/repo/exporter/URLExporter.java b/source/java/org/alfresco/repo/exporter/URLExporter.java
index a3b31c0ca2..cdd1236a11 100644
--- a/source/java/org/alfresco/repo/exporter/URLExporter.java
+++ b/source/java/org/alfresco/repo/exporter/URLExporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
package org.alfresco.repo.exporter;
import java.io.InputStream;
+import java.util.Locale;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -276,6 +277,16 @@ import org.alfresco.util.ParameterCheck;
exporter.endReference(nodeRef);
}
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ exporter.startValueMLText(nodeRef, locale);
+ }
+
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ exporter.endValueMLText(nodeRef);
+ }
+
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#warning(java.lang.String)
*/
diff --git a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java
index 1dfa11eec8..f886768840 100644
--- a/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java
+++ b/source/java/org/alfresco/repo/exporter/ViewXMLExporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,6 +26,7 @@ package org.alfresco.repo.exporter;
import java.io.InputStream;
import java.util.List;
+import java.util.Locale;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -74,6 +75,8 @@ import org.xml.sax.helpers.AttributesImpl;
private static final String EXPORTEDDATE_LOCALNAME = "exportDate";
private static final String EXPORTERVERSION_LOCALNAME = "exporterVersion";
private static final String EXPORTOF_LOCALNAME = "exportOf";
+ private static final String MLVALUE_LOCALNAME = "mlvalue";
+ private static final String LOCALE_LOCALNAME = "locale";
private static final String ACL_LOCALNAME = "acl";
private static final String ACE_LOCALNAME = "ace";
private static final String ACCESS_LOCALNAME = "access";
@@ -106,6 +109,8 @@ import org.xml.sax.helpers.AttributesImpl;
private static QName REFERENCE_QNAME;
private static QName PATHREF_QNAME;
private static QName NODEREF_QNAME;
+ private static QName LOCALE_QNAME;
+ private static QName MLVALUE_QNAME;
private static final AttributesImpl EMPTY_ATTRIBUTES = new AttributesImpl();
// Service dependencies
@@ -164,6 +169,9 @@ import org.xml.sax.helpers.AttributesImpl;
REFERENCE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, REFERENCE_LOCALNAME, namespaceService);
PATHREF_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, PATHREF_LOCALNAME, namespaceService);
NODEREF_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, NODEREF_LOCALNAME, namespaceService);
+ LOCALE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, LOCALE_LOCALNAME, namespaceService);
+ MLVALUE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, MLVALUE_LOCALNAME, namespaceService);
+
}
@@ -718,7 +726,34 @@ import org.xml.sax.helpers.AttributesImpl;
throw new ExporterException("Failed to process end reference", e);
}
}
-
+
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ AttributesImpl attrs = new AttributesImpl();
+ attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, LOCALE_LOCALNAME, LOCALE_QNAME.toPrefixString(), null, locale.toString());
+ try
+ {
+ contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, MLVALUE_LOCALNAME, MLVALUE_QNAME.toPrefixString(), attrs);
+ }
+ catch (SAXException e)
+ {
+ throw new ExporterException("Failed to process start mlvalue", e);
+ }
+ }
+
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ try
+ {
+ contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, MLVALUE_LOCALNAME, MLVALUE_QNAME.toPrefixString());
+ }
+ catch (SAXException e)
+ {
+ throw new ExporterException("Failed to process end mltext", e);
+ }
+
+ }
+
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#warning(java.lang.String)
*/
diff --git a/source/java/org/alfresco/repo/importer/ImporterComponent.java b/source/java/org/alfresco/repo/importer/ImporterComponent.java
index 4309b2386c..9abda6caaa 100644
--- a/source/java/org/alfresco/repo/importer/ImporterComponent.java
+++ b/source/java/org/alfresco/repo/importer/ImporterComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -945,7 +945,7 @@ public class ImporterComponent
if (value instanceof Collection)
{
List boundCollection = new ArrayList();
- for (String collectionValue : (Collection)value)
+ for (Serializable collectionValue : (Collection)value)
{
Serializable objValue = bindValue(context, property, valueDataType, collectionValue);
boundCollection.add(objValue);
@@ -954,7 +954,7 @@ public class ImporterComponent
}
else
{
- value = bindValue(context, property, valueDataType, (String)value);
+ value = bindValue(context, property, valueDataType, value);
}
// choose to provide property on node creation or at end of import for lazy binding
@@ -1002,19 +1002,22 @@ public class ImporterComponent
* @param value string form of value
* @return the bound value
*/
- private Serializable bindValue(ImportNode context, QName property, DataTypeDefinition valueType, String value)
+ private Serializable bindValue(ImportNode context, QName property, DataTypeDefinition valueType, Serializable value)
{
Serializable objValue = null;
if (value != null && valueType != null)
{
- String strValue = bindPlaceHolder(value, binding);
+ if (value instanceof String)
+ {
+ value = bindPlaceHolder(value.toString(), binding);
+ }
if ((valueType.getName().equals(DataTypeDefinition.NODE_REF) || valueType.getName().equals(DataTypeDefinition.CATEGORY)))
{
- objValue = strValue;
+ objValue = value;
}
else
{
- objValue = (Serializable)DefaultTypeConverter.INSTANCE.convert(valueType, strValue);
+ objValue = (Serializable) DefaultTypeConverter.INSTANCE.convert(valueType, value);
}
}
diff --git a/source/java/org/alfresco/repo/importer/importercomponent_test.xml b/source/java/org/alfresco/repo/importer/importercomponent_test.xml
index eb794f2d37..f7837d4202 100644
--- a/source/java/org/alfresco/repo/importer/importercomponent_test.xml
+++ b/source/java/org/alfresco/repo/importer/importercomponent_test.xml
@@ -77,11 +77,32 @@
Some content
contentUrl=classpath:org/alfresco/repo/importer/importercomponent_testfile.txt|mimetype=text|size=|encoding=
+
+
+
+
+
+
+ ML Text
+
+ FR_TITLE
+ GE_TITLE
+ ENG_TITLE
+
+
+ FR_DESCRIPTION
+ GE_DESCRIPTION
+ ENG_DESCRIPTION
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/importer/view/NodeContext.java b/source/java/org/alfresco/repo/importer/view/NodeContext.java
index 0bdf792ad2..f0e622cb27 100644
--- a/source/java/org/alfresco/repo/importer/view/NodeContext.java
+++ b/source/java/org/alfresco/repo/importer/view/NodeContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -247,7 +247,7 @@ public class NodeContext extends ElementContext
* @param property the property name
* @param value the property value
*/
- public void addProperty(QName property, String value)
+ public void addProperty(QName property, Serializable value)
{
// Process "special" properties
// TODO: Make this configurable...
@@ -256,7 +256,7 @@ public class NodeContext extends ElementContext
// Process Alfresco UUID
if (uuid == null && propDef != null && propDef.getName().equals(ContentModel.PROP_NODE_UUID))
{
- uuid = value;
+ uuid = value.toString();
}
// Do not import properties of sys:referenceable or cm:versionable
diff --git a/source/java/org/alfresco/repo/importer/view/ViewParser.java b/source/java/org/alfresco/repo/importer/view/ViewParser.java
index b2ac1c3101..8454c73eaa 100644
--- a/source/java/org/alfresco/repo/importer/view/ViewParser.java
+++ b/source/java/org/alfresco/repo/importer/view/ViewParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,7 +26,9 @@ package org.alfresco.repo.importer.view;
import java.io.IOException;
import java.io.Reader;
+import java.io.Serializable;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
@@ -35,11 +37,14 @@ import org.alfresco.repo.importer.Importer;
import org.alfresco.repo.importer.Parser;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
+import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.dictionary.TypeDefinition;
+import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.view.ImporterException;
import org.alfresco.service.namespace.NamespaceService;
@@ -71,6 +76,7 @@ public class ViewParser implements Parser
private static final String VIEW_IDREF_ATTR = "idref";
private static final String VIEW_PATHREF_ATTR = "pathref";
private static final String VIEW_NODEREF_ATTR = "noderef";
+ private static final String VIEW_LOCALE_ATTR = "locale";
private static final QName VIEW_METADATA = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "metadata");
private static final QName VIEW_VALUE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "value");
private static final QName VIEW_VALUES_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "values");
@@ -82,7 +88,7 @@ public class ViewParser implements Parser
private static final QName VIEW_AUTHORITY = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "authority");
private static final QName VIEW_PERMISSION = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "permission");
private static final QName VIEW_REFERENCE = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "reference");
-
+ private static final QName VIEW_ML_VALUE = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "mlvalue");
// XML Pull Parser Factory
private XmlPullParserFactory factory;
@@ -670,6 +676,7 @@ public class ViewParser implements Parser
{
// Extract collection, if specified
boolean isCollection = false;
+ boolean isMLProperty = false;
if (eventType == XmlPullParser.START_TAG)
{
QName name = getName(xpp);
@@ -683,6 +690,66 @@ public class ViewParser implements Parser
eventType = xpp.next();
}
}
+ else if (name.equals(VIEW_ML_VALUE))
+ {
+ isMLProperty = true;
+ }
+ }
+
+ // Extract ML value
+
+ if (isMLProperty)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Start parsing MLValue for property: " + propertyName);
+ }
+ value = "";
+ String locale = "";
+ node.addDatatype(propertyName, dictionaryService.getDataType(DataTypeDefinition.MLTEXT));
+ MLText mlText = new MLText();
+ while (isMLProperty)
+ {
+ isMLProperty = false;
+
+ locale = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_LOCALE_ATTR);
+ eventType = xpp.next();
+ if (eventType == XmlPullParser.TEXT)
+ {
+ value = xpp.getText();
+ eventType = xpp.next();
+ }
+ if (eventType == XmlPullParser.END_TAG)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("Found ML entry: " + locale + "=" + value);
+ }
+ mlText.addValue(DefaultTypeConverter.INSTANCE.convert(Locale.class, locale), value);
+
+ eventType = xpp.next();
+ if (eventType == XmlPullParser.TEXT)
+ {
+ eventType = xpp.next();
+ }
+ }
+
+ if (eventType == XmlPullParser.START_TAG)
+ {
+ QName name = getName(xpp);
+ if (name.equals(VIEW_ML_VALUE))
+ {
+ isMLProperty = true;
+ }
+ }
+ }
+
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("End parsing MLValue for property: " + propertyName);
+ }
+ node.addProperty(propertyName, mlText);
+
}
// Extract decorated value
diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java
index 981f0951c6..90869cdb72 100644
--- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java
+++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImplTest.java
@@ -29,12 +29,14 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.dictionary.DictionaryDAO;
import org.alfresco.repo.dictionary.M2Model;
@@ -44,6 +46,7 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
+import org.alfresco.service.cmr.model.FileFolderServiceType;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.ContentReader;
@@ -651,4 +654,14 @@ public class FileFolderServiceImplTest extends TestCase
assertNotNull("Long filename not found", fileNodeRef);
assertEquals(fileInfo.getNodeRef(), fileNodeRef);
}
+
+ /**
+ * Validates ACT-7225
+ */
+ public void testGetType() throws Exception
+ {
+ I18NUtil.setContentLocale(Locale.CANADA);
+ FileFolderServiceType type = fileFolderService.getType(ContentModel.TYPE_FOLDER);
+ assertEquals("Type incorrect for folder", FileFolderServiceType.FOLDER, type);
+ }
}
diff --git a/source/java/org/alfresco/repo/model/filefolder/MLTranslationInterceptor.java b/source/java/org/alfresco/repo/model/filefolder/MLTranslationInterceptor.java
index 9e195545ff..e90f4fc4fa 100644
--- a/source/java/org/alfresco/repo/model/filefolder/MLTranslationInterceptor.java
+++ b/source/java/org/alfresco/repo/model/filefolder/MLTranslationInterceptor.java
@@ -91,6 +91,7 @@ public class MLTranslationInterceptor implements MethodInterceptor
METHOD_NAMES_OTHER.add("delete");
METHOD_NAMES_OTHER.add("getReader");
METHOD_NAMES_OTHER.add("getWriter");
+ METHOD_NAMES_OTHER.add("getType");
}
private static Log logger = LogFactory.getLog(MLTranslationInterceptor.class);
diff --git a/source/java/org/alfresco/service/cmr/view/Exporter.java b/source/java/org/alfresco/service/cmr/view/Exporter.java
index 5b559f5dfe..b78ea3a51c 100644
--- a/source/java/org/alfresco/service/cmr/view/Exporter.java
+++ b/source/java/org/alfresco/service/cmr/view/Exporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,6 +25,7 @@
package org.alfresco.service.cmr.view;
import java.io.InputStream;
+import java.util.Locale;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -178,6 +179,21 @@ public interface Exporter
*/
public void startValueCollection(NodeRef nodeRef, QName property);
+ /**
+ * Start export MLText
+ *
+ * @param nodeRef the node reference
+ * @param locale
+ */
+ public void startValueMLText(NodeRef nodeRef, Locale locale);
+
+ /**
+ * End export MLText
+ *
+ * @param nodeRef
+ */
+ public void endValueMLText(NodeRef nodeRef);
+
/**
* Export property value
*
diff --git a/source/java/org/alfresco/tools/Export.java b/source/java/org/alfresco/tools/Export.java
index 748d9cc269..2d3e7d9199 100644
--- a/source/java/org/alfresco/tools/Export.java
+++ b/source/java/org/alfresco/tools/Export.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Alfresco Software Limited.
+ * Copyright (C) 2005-2009 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -26,6 +26,7 @@ package org.alfresco.tools;
import java.io.File;
import java.io.InputStream;
+import java.util.Locale;
import org.alfresco.repo.exporter.ACPExportPackageHandler;
import org.alfresco.repo.exporter.FileExportPackageHandler;
@@ -645,6 +646,14 @@ public final class Export extends Tool
public void endReference(NodeRef nodeRef)
{
}
+
+ public void endValueMLText(NodeRef nodeRef)
+ {
+ }
+
+ public void startValueMLText(NodeRef nodeRef, Locale locale)
+ {
+ }
}
}