exo-jcr SVN: r4270 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2011-04-21 14:32:09 -0400 (Thu, 21 Apr 2011)
New Revision: 4270
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPath.java
Log:
EXOJCR-1314: Improve QPath.isDescendantOf by using reverse order
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPath.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPath.java 2011-04-21 14:58:32 UTC (rev 4269)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPath.java 2011-04-21 18:32:09 UTC (rev 4270)
@@ -173,7 +173,7 @@
if (names.length - ancestorNames.length <= 0)
return false;
- for (int i = 0; i < ancestorNames.length; i++)
+ for (int i = ancestorNames.length - 1; i >= 0; i--)
{
if (!names[i].equals(ancestorNames[i]))
return false;
@@ -191,13 +191,11 @@
{
final InternalQName[] anotherNames = anotherPath.names;
- // int depthDiff = getDepth() - anotherPath.getDepth();
int depthDiff = names.length - anotherNames.length;
if (depthDiff <= 0 || (childOnly && depthDiff != 1))
return false;
- // InternalQName[] anotherNames = anotherPath.getEntries();
- for (int i = 0; i < anotherNames.length; i++)
+ for (int i = anotherNames.length - 1; i >= 0; i--)
{
if (!anotherNames[i].equals(names[i]))
return false;
15 years
exo-jcr SVN: r4269 - in jcr/trunk: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl and 23 other directories.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2011-04-21 10:58:32 -0400 (Thu, 21 Apr 2011)
New Revision: 4269
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/DefaulStringConversion.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionReference.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/IndexingConfigurationEntityResolver.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NodeTypeVirtualTableResolver.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SharedFieldSortComparator.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/PropertyDataOrderComparator.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionCatalog.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionInterceptor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerThread.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/update/StorageUpdateManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewContentExporter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupScheduler.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/FileNameProducer.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/server/HTTPBackupAgent.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/registry/RegistryService.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/AbstractXMLViewNodeRepresentation.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtFileNodeRepresentationFactory.java
jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtResourceNodeRepresentationFactory.java
jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/common/DynamicSessionProviderTest.java
jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpTextUtils.java
jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientCommandThread.java
jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/command/CmdStor.java
jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java
jcr/trunk/exo.jcr.connectors.localadapter/src/main/java/org/exoplatform/connectors/jcr/adapters/local/JcrResourceAdapter.java
jcr/trunk/exo.jcr.framework.ftpclient/src/main/java/org/exoplatform/frameworks/ftpclient/data/FtpDataTransiverImpl.java
Log:
EXOJCR-1221 : The same violations was fixed in JCR.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/DefaulStringConversion.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/DefaulStringConversion.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/DefaulStringConversion.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -18,7 +18,8 @@
*/
package org.exoplatform.services.jcr.core.nodetype;
-import java.util.ArrayList;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
/**
* Serialization/Deserialization for simple java types and Strings. For JiBX binding process only.
@@ -28,6 +29,8 @@
public class DefaulStringConversion
{
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.DefaulStringConversion");
+
public static String serializeString(String stringValue)
{
@@ -38,7 +41,7 @@
}
catch (Exception e)
{
- System.err.println("serializeString.Exception: " + e);
+ LOG.error("serializeString.Exception: " + e, e);
}
return r;
}
@@ -53,7 +56,7 @@
}
catch (Exception e)
{
- System.err.println("deserializeString.Exception: " + e);
+ LOG.error("deserializeString.Exception: " + e, e);
}
return r;
}
@@ -67,6 +70,7 @@
}
catch (Exception e)
{
+ LOG.error("serializeInt.Exception: " + e, e);
}
return r;
}
@@ -81,6 +85,7 @@
}
catch (Exception e)
{
+ LOG.error("deserializeInt.Exception: " + e, e);
}
return r;
}
@@ -95,6 +100,7 @@
}
catch (Exception e)
{
+ LOG.error("serializeLong.Exception: " + e, e);
}
return r;
}
@@ -109,6 +115,7 @@
}
catch (Exception e)
{
+ LOG.error("deserializeLong.Exception: " + e, e);
}
return r;
}
@@ -123,6 +130,7 @@
}
catch (Exception e)
{
+ LOG.error("serializeLong.Exception: " + e, e);
}
return r;
}
@@ -133,36 +141,12 @@
boolean r = false;
try
{
- System.err.println("deserializeBoolean: " + boolString);
r = Boolean.parseBoolean(boolString);
- System.err.println("deserializeBoolean: res: " + r);
}
catch (Exception e)
{
- System.err.println("deserializeBoolean.Exception: " + e);
+ LOG.error("deserializeBoolean.Exception: " + e, e);
}
return r;
}
-
- public static String serializeArrayList(ArrayList arrayList)
- {
-
- String r = ""; // default
- try
- {
- if (arrayList != null)
- {
-
- }
- }
- catch (IllegalArgumentException e)
- {
- // r = PropertyType.TYPENAME_UNDEFINED;
- }
- catch (Exception e)
- {
- // r = PropertyType.TYPENAME_UNDEFINED;
- }
- return r;
- }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/Constants.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -21,6 +21,8 @@
import org.exoplatform.services.jcr.datamodel.IllegalPathException;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
/**
* Created by The eXo Platform SAS.
@@ -31,6 +33,8 @@
public class Constants
{
+ private static Log log = ExoLogger.getLogger("exo.jcr.component.core.Constants");
+
/**
* Default namespace prefix (empty uri).
*/
@@ -708,8 +712,7 @@
}
catch (IllegalPathException e)
{
- e.printStackTrace();
- System.err.println("ERROR: Can't parse JCR_SYSTEM_URI for constant JCR_SYSTEM (" + JCR_SYSTEM_URI + "): " + e);
+ log.error("ERROR: Can't parse JCR_SYSTEM_URI for constant JCR_SYSTEM (" + JCR_SYSTEM_URI + "): " + e, e);
}
try
@@ -718,9 +721,8 @@
}
catch (IllegalPathException e)
{
- e.printStackTrace();
- System.err.println("ERROR: Can't parse JCR_VERSION_STORAGE_URI for constant JCR_VERSION_STORAGE_PATH ("
- + JCR_VERSION_STORAGE_URI + "): " + e);
+ log.error("ERROR: Can't parse JCR_VERSION_STORAGE_URI for constant JCR_VERSION_STORAGE_PATH ("
+ + JCR_VERSION_STORAGE_URI + "): " + e, e);
}
try
@@ -729,9 +731,8 @@
}
catch (IllegalPathException e)
{
- e.printStackTrace();
- System.err.println("ERROR: Can't parse JCR_NODETYPES_URI for constant JCR_NODETYPES_PATH ("
- + JCR_NODETYPES_URI + "): " + e);
+ log.error("ERROR: Can't parse JCR_NODETYPES_URI for constant JCR_NODETYPES_PATH ("
+ + JCR_NODETYPES_URI + "): " + e, e);
}
String nsUri = JCR_SYSTEM_URI + EXO_NAMESPACES.getAsString() + ":1";
@@ -741,8 +742,7 @@
}
catch (IllegalPathException e)
{
- e.printStackTrace();
- System.err.println("ERROR: Can't parse EXO_NAMESPACES_URI for constant EXO_NAMESPACES (" + nsUri + "): " + e);
+ log.error("ERROR: Can't parse EXO_NAMESPACES_URI for constant EXO_NAMESPACES (" + nsUri + "): " + e, e);
}
try
@@ -751,8 +751,7 @@
}
catch (IllegalPathException e)
{
- e.printStackTrace();
- System.err.println("ERROR: Can't parse ROOT_URI " + e);
+ log.error("ERROR: Can't parse ROOT_URI " + e, e);
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/PropertyImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -28,6 +28,8 @@
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.impl.core.nodetype.PropertyDefinitionImpl;
import org.exoplatform.services.jcr.impl.core.value.BaseValue;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.io.InputStream;
import java.util.Calendar;
@@ -54,6 +56,11 @@
{
/**
+ * Logger.
+ */
+ protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.PropertyImpl");
+
+ /**
* Value type.
*/
protected int type;
@@ -580,7 +587,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
return vals;
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -2457,7 +2457,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
return str;
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionFactory.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -44,7 +44,7 @@
public class SessionFactory
{
- protected static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.SessionFactory");
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.SessionFactory");
private final ExoContainer container;
@@ -99,7 +99,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionReference.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionReference.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionReference.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -18,6 +18,9 @@
*/
package org.exoplatform.services.jcr.impl.core;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
@@ -36,6 +39,11 @@
public class SessionReference extends WeakReference<Session>
{
+ /**
+ * The logger instance for this class.
+ */
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.SessionReference");
+
//
private static final int INITIAL_DELAY = 10;
@@ -75,7 +83,7 @@
{
public void run()
{
- System.out.println("Starting detector task");
+ LOG.info("Starting detector task");
//
ArrayList<SessionReference> list;
@@ -117,13 +125,13 @@
objects.remove(ref.key);
Exception e = new Exception();
e.setStackTrace(ref.stack);
- System.out.println("<" + error + ">");
- e.printStackTrace();
- System.out.println("</" + error + ">");
+ LOG.error("<" + error + ">");
+ LOG.error(e.getLocalizedMessage(), e);
+ LOG.error("</" + error + ">");
}
}
}
- System.out.println("Finished detector task");
+ LOG.info("Finished detector task");
}
};
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -20,6 +20,8 @@
import org.exoplatform.services.jcr.core.lock.ExtendedLock;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
@@ -34,6 +36,11 @@
public class LockImpl implements ExtendedLock
{
+ /**
+ * Logger.
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.LockImpl");
+
private LockData lockData;
private SessionImpl session;
@@ -79,14 +86,13 @@
}
catch (RepositoryException e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
return null;
}
public boolean isDeep()
{
-
return lockData.isDeep();
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/cacheable/CacheLockImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -18,6 +18,8 @@
import org.exoplatform.services.jcr.impl.core.SessionImpl;
import org.exoplatform.services.jcr.impl.core.lock.LockImpl;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
@@ -33,6 +35,8 @@
*/
public class CacheLockImpl extends LockImpl
{
+ private static final Log log = ExoLogger.getLogger("exo.jcr.component.core.CacheLockImpl");
+
private boolean live;
private LockData lockData;
@@ -113,8 +117,7 @@
}
catch (RepositoryException e)
{
- //TODO
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
return null;
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -376,11 +376,11 @@
}
catch (NoSuchNodeTypeException e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
catch (RepositoryException e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
}
return superTypes;
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/IndexingConfigurationEntityResolver.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/IndexingConfigurationEntityResolver.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/IndexingConfigurationEntityResolver.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -30,42 +30,38 @@
* <code>IndexingConfigurationEntityResolver</code> implements an entity
* resolver for the indexing configuration DTD.
*/
-public class IndexingConfigurationEntityResolver implements EntityResolver {
+public class IndexingConfigurationEntityResolver
+ implements EntityResolver
+{
- /**
- * Maps system ids to DTD resource names.
- */
- private static final Map<String, String> SYSTEM_IDS;
+ /**
+ * Maps system ids to DTD resource names.
+ */
+ private static final Map<String, String> SYSTEM_IDS;
- static {
- Map<String, String> systemIds = new HashMap<String, String>();
- systemIds
- .put(
- "http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd",
- "indexing-configuration-1.0.dtd");
- systemIds
- .put(
- "http://www.exoplatform.org/dtd/indexing-configuration-1.1.dtd",
- "indexing-configuration-1.1.dtd");
- systemIds
- .put(
- "http://www.exoplatform.org/dtd/indexing-configuration-1.2.dtd",
- "indexing-configuration-1.2.dtd");
- SYSTEM_IDS = Collections.unmodifiableMap(systemIds);
- }
+ static
+ {
+ Map<String, String> systemIds = new HashMap<String, String>();
+ systemIds.put("http://www.exoplatform.org/dtd/indexing-configuration-1.0.dtd", "indexing-configuration-1.0.dtd");
+ systemIds.put("http://www.exoplatform.org/dtd/indexing-configuration-1.1.dtd", "indexing-configuration-1.1.dtd");
+ systemIds.put("http://www.exoplatform.org/dtd/indexing-configuration-1.2.dtd", "indexing-configuration-1.2.dtd");
+ SYSTEM_IDS = Collections.unmodifiableMap(systemIds);
+ }
- /**
- * {@inheritDoc}
- */
- public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException, IOException {
- String resourceName = SYSTEM_IDS.get(systemId);
- if (resourceName != null) {
- InputStream in = getClass().getResourceAsStream(resourceName);
- if (in != null) {
- return new InputSource(in);
- }
- }
- return null;
- }
+ /**
+ * {@inheritDoc}
+ */
+ public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
+ {
+ String resourceName = SYSTEM_IDS.get(systemId);
+ if (resourceName != null)
+ {
+ InputStream in = getClass().getResourceAsStream(resourceName);
+ if (in != null)
+ {
+ return new InputSource(in);
+ }
+ }
+ return null;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NodeTypeVirtualTableResolver.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NodeTypeVirtualTableResolver.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/NodeTypeVirtualTableResolver.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -32,45 +32,45 @@
* @version $Id: exo-jboss-codetemplates.xml 34027 2009-07-15 23:26:43Z
* aheritier $
*/
-public abstract class NodeTypeVirtualTableResolver<Q> implements
- VirtualTableResolver<Q> {
- private final NodeTypeDataManager nodeTypeDataManager;
+public abstract class NodeTypeVirtualTableResolver<Q>
+ implements VirtualTableResolver<Q>
+{
+ private final NodeTypeDataManager nodeTypeDataManager;
- /**
- * @param nodeTypeDataManager
- */
- public NodeTypeVirtualTableResolver(
- final NodeTypeDataManager nodeTypeDataManager) {
- super();
- this.nodeTypeDataManager = nodeTypeDataManager;
- }
+ /**
+ * @param nodeTypeDataManager
+ */
+ public NodeTypeVirtualTableResolver(final NodeTypeDataManager nodeTypeDataManager)
+ {
+ super();
+ this.nodeTypeDataManager = nodeTypeDataManager;
+ }
- /**
- * @param nodeTypeName
- * name.
- * @return Returns all subtypes of node type <code>nodeTypeName</code> in
- * the node type inheritance hierarchy.
- * @throws RepositoryException
- */
- protected Set<InternalQName> getSubTypes(final InternalQName nodeTypeName)
- throws RepositoryException {
- return this.nodeTypeDataManager.getSubtypes(nodeTypeName);
- }
+ /**
+ * @param nodeTypeName
+ * name.
+ * @return Returns all subtypes of node type <code>nodeTypeName</code> in
+ * the node type inheritance hierarchy.
+ * @throws RepositoryException
+ */
+ protected Set<InternalQName> getSubTypes(final InternalQName nodeTypeName) throws RepositoryException
+ {
+ return this.nodeTypeDataManager.getSubtypes(nodeTypeName);
+ }
- /**
- * @param nodeTypeName
- * name.
- * @return true if node type with name <code>nodeTypeName</code> is mixin.
- * @throws RepositoryException
- */
- protected boolean isMixin(final InternalQName nodeTypeName)
- throws RepositoryException {
- final NodeTypeData nodeType = this.nodeTypeDataManager
- .getNodeType(nodeTypeName);
- if (nodeType == null) {
- throw new NoSuchNodeTypeException("Node type "
- + nodeTypeName.getAsString() + " not found");
- }
- return nodeType.isMixin();
- }
+ /**
+ * @param nodeTypeName
+ * name.
+ * @return true if node type with name <code>nodeTypeName</code> is mixin.
+ * @throws RepositoryException
+ */
+ protected boolean isMixin(final InternalQName nodeTypeName) throws RepositoryException
+ {
+ final NodeTypeData nodeType = this.nodeTypeDataManager.getNodeType(nodeTypeName);
+ if (nodeType == null)
+ {
+ throw new NoSuchNodeTypeException("Node type " + nodeTypeName.getAsString() + " not found");
+ }
+ return nodeType.isMixin();
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/OfflinePersistentIndex.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -23,6 +23,8 @@
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Similarity;
import org.exoplatform.services.jcr.impl.core.query.lucene.directory.DirectoryManager;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.io.IOException;
import java.util.ArrayList;
@@ -40,6 +42,12 @@
*/
public class OfflinePersistentIndex extends PersistentIndex
{
+
+ /**
+ * The logger
+ */
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.OfflinePersistentIndex");
+
public static final String NAME = "offline";
private List<String> processedIDs;
@@ -73,7 +81,7 @@
{
int count = super.removeDocument(idTerm);
processedIDs.add(idTerm.text());
- System.out.println("RM: " + idTerm.text());
+ LOG.info("RM: " + idTerm.text());
return count;
}
@@ -83,7 +91,7 @@
super.addDocuments(docs);
for (Document doc : docs)
{
- System.out.println("add: " + doc.get(FieldNames.UUID));
+ LOG.info("add: " + doc.get(FieldNames.UUID));
processedIDs.add(doc.get(FieldNames.UUID));
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/RowIteratorImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -708,8 +708,7 @@
}
catch (RepositoryException e)
{
- // TODO Auto-generated catch block
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
return false;
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SharedFieldSortComparator.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SharedFieldSortComparator.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SharedFieldSortComparator.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -35,6 +35,8 @@
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.JCRPath;
import org.exoplatform.services.jcr.impl.core.LocationFactory;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.io.IOException;
import java.util.ArrayList;
@@ -51,6 +53,11 @@
{
/**
+ * The logger
+ */
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.SharedFieldSortComparator");
+
+ /**
* The name of the shared field in the lucene index.
*/
private final String field;
@@ -336,7 +343,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
return null;
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/SpellSuggestion.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -47,8 +47,8 @@
* the abstract query tree.
*/
SpellSuggestion(SpellChecker spellChecker, QueryRootNode root) {
- this.spellChecker = spellChecker;
- this.root = root;
+ this.spellChecker = spellChecker;
+ this.root = root;
}
/**
@@ -62,10 +62,13 @@
* @throws RepositoryException
*/
public String getSuggestion() throws IOException, RepositoryException {
- if (spellChecker != null) {
- return spellChecker.check(root);
- } else {
- return null;
- }
- }
+ if (spellChecker != null)
+ {
+ return spellChecker.check(root);
+ }
+ else
+ {
+ return null;
+ }
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/PropertyDataOrderComparator.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/PropertyDataOrderComparator.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/PropertyDataOrderComparator.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -21,6 +21,8 @@
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.util.Comparator;
@@ -30,6 +32,10 @@
*/
public class PropertyDataOrderComparator implements Comparator<PropertyData>
{
+ /**
+ * Logger.
+ */
+ protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.PropertyDataOrderComparator");
public int compare(PropertyData p1, PropertyData p2)
{
@@ -69,7 +75,7 @@
}
catch (Exception e)
{
- System.err.println("PropertiesOrderComparator error: " + e);
+ LOG.error("PropertiesOrderComparator error: " + e, e);
}
return r;
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -798,7 +798,7 @@
}
catch (Throwable e)
{
- System.err.println(this.name + " cache, finalyze error " + e);
+ LOG.error(this.name + " cache, finalyze error " + e, e);
}
nodesCache.clear();
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionCatalog.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionCatalog.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionCatalog.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -77,7 +77,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionInterceptor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionInterceptor.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/ext/action/SessionActionInterceptor.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -48,12 +48,15 @@
public class SessionActionInterceptor
{
+ /**
+ * Logger
+ */
+ private static Log log = ExoLogger.getLogger("exo.jcr.component.core.SessionActionInterceptor");
+
private final ActionCatalog catalog;
private final ExoContainer container;
- private static Log log = ExoLogger.getLogger("exo.jcr.component.core.SessionActionInterceptor");
-
/**
* SessionActionInterceptor is per session, and only one action per session/time can be active.
*/
@@ -403,10 +406,7 @@
InternalQName[] nodeTypeNames = new InternalQName[mixinNames.length + 1];
nodeTypeNames[0] = primaryTypeName;
- for (int i = 1; i <= mixinNames.length; i++)
- {
- nodeTypeNames[i] = mixinNames[i - 1];
- }
+ System.arraycopy(mixinNames, 0, nodeTypeNames, 1, mixinNames.length);
return nodeTypeNames;
}
@@ -425,7 +425,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerThread.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerThread.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/proccess/WorkerThread.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -18,6 +18,9 @@
*/
package org.exoplatform.services.jcr.impl.proccess;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
/**
* Created by The eXo Platform SAS.
*
@@ -27,6 +30,10 @@
public abstract class WorkerThread extends Thread
{
+ /**
+ * Logger.
+ */
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.core.WorkerThread");
protected boolean stopped = false;
@@ -57,8 +64,9 @@
catch (Exception e)
{
if (!(e instanceof InterruptedException))
- e.printStackTrace();
-
+ {
+ LOG.error(e.getLocalizedMessage(), e);
+ }
}
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/update/StorageUpdateManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/update/StorageUpdateManager.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/update/StorageUpdateManager.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -18,6 +18,11 @@
*/
package org.exoplatform.services.jcr.impl.storage.jdbc.update;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.util.IdGenerator;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -30,11 +35,6 @@
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.util.IdGenerator;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
/**
* Created by The eXo Platform SAS.
*
@@ -416,7 +416,7 @@
}
catch (SQLException e)
{
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
finally
{
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewContentExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewContentExporter.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewContentExporter.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -109,7 +109,7 @@
for (ValueData valueData : property.getValues())
{
String strVal = getValueAsStringForExport(valueData, property.getType());
- if (strVal == "")
+ if (strVal.equals(""))
{
continue;
}
@@ -124,7 +124,7 @@
InternalQName internalPropName = ISO9075.encode(property.getQPath().getName());
currentAttr.addAttribute(internalPropName.getNamespace(), internalPropName.getName(), getExportName(
- property, true), "CDATA", strValue != "" ? strValue.substring(1) : strValue);
+ property, true), "CDATA", !strValue.equals("") ? strValue.substring(1) : strValue);
}
if (Constants.ROOT_PATH.equals(node.getQPath()))
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/xml/exporting/DocumentViewStreamExporter.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -113,7 +113,7 @@
for (ValueData valueData : property.getValues())
{
String strVal = getValueAsStringForExport(valueData, property.getType());
- if (strVal == "")
+ if (strVal.equals(""))
{
continue;
}
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupManagerImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -1291,7 +1291,8 @@
if (!log.getBackupConfig().getRepository().equals(repositoryName))
{
throw new WorkspaceRestoreException("If workspaceEntry is null, so will be restored with original configuration. " +
- "The repositoryName (\"" + repositoryName +"\") should be equals original repository name (\"" + log.getBackupConfig().getRepository() +"\"). " );
+ "The repositoryName (\"" + repositoryName +"\") should be equals original repository name (\""
+ + log.getBackupConfig().getRepository() +"\"). " );
}
if (log.getOriginalWorkspaceEntry() == null)
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupScheduler.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupScheduler.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/BackupScheduler.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -499,7 +499,7 @@
backupConfig = conf;
}
- // TODO use cycle to read CHARACTERS
+ // Read CHARACTERS
private String readContent() throws XMLStreamException
{
String content = null;
@@ -853,26 +853,6 @@
// registerShutdownHook();
}
- private void registerShutdownHook()
- {
- // register shutdownhook for final cancel all taskes scheduled
- try
- {
- Runtime.getRuntime().addShutdownHook(new Thread()
- {
- @Override
- public void run()
- {
- timer.cancel();
- }
- });
- }
- catch (IllegalStateException e)
- {
- // can't register shutdownhook
- }
- }
-
public BackupMessage[] getErrors()
{
return messages.getMessages();
@@ -908,7 +888,7 @@
{
// by stop time
- // TODO restore without scheduler now. Add task search capabilities to the scheduler and add
+ // Restore without scheduler now. Add task search capabilities to the scheduler and add
// listener to a task
schedule(tconf.backupConfig, tconf.startTime, tconf.stopTime, tconf.chainPeriod, tconf.incrPeriod, null);
} // else - the start time in past and no periodic configuration found
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/FileNameProducer.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/FileNameProducer.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/impl/FileNameProducer.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -19,6 +19,8 @@
package org.exoplatform.services.jcr.ext.backup.impl;
import org.exoplatform.commons.utils.PrivilegedFileHelper;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.io.File;
import java.io.FilenameFilter;
@@ -31,6 +33,11 @@
*/
public class FileNameProducer
{
+ /**
+ * Logger.
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.ext.FileNameProducer");
+
class SkipBackupLogFilter
implements FilenameFilter
{
@@ -183,7 +190,7 @@
}
catch (IOException e)
{
- e.printStackTrace();
+ LOG.error("Can nit get next file : " + e.getLocalizedMessage(), e);
}
return nextFile;
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/server/HTTPBackupAgent.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/server/HTTPBackupAgent.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/backup/server/HTTPBackupAgent.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -2790,7 +2790,8 @@
for (JobWorkspaceRestore job : backupManager.getRestores())
if (repositoryName.equals(job.getRepositoryName())
&& workspaceName.endsWith(job.getWorkspaceName())
- && (job.getStateRestore() == JobWorkspaceRestore.RESTORE_INITIALIZED || job.getStateRestore() == JobWorkspaceRestore.RESTORE_STARTED))
+ && (job.getStateRestore() == JobWorkspaceRestore.RESTORE_INITIALIZED
+ || job.getStateRestore() == JobWorkspaceRestore.RESTORE_STARTED))
{
throw new WorkspaceRestoreExeption("The workspace '" + "/" + repositoryName + "/" + workspaceName
+ "' is already restoring.");
@@ -2810,7 +2811,8 @@
for (JobRepositoryRestore job : backupManager.getRepositoryRestores())
{
if (repositoryName.equals(job.getRepositoryName())
- && (job.getStateRestore() == JobWorkspaceRestore.RESTORE_INITIALIZED || job.getStateRestore() == JobWorkspaceRestore.RESTORE_STARTED))
+ && (job.getStateRestore() == JobWorkspaceRestore.RESTORE_INITIALIZED
+ || job.getStateRestore() == JobWorkspaceRestore.RESTORE_STARTED))
{
throw new RepositoryRestoreExeption("The repository '" + "/" + repositoryName + "' is already restoring.");
}
@@ -2818,25 +2820,6 @@
}
/**
- * validateOneRestoreInstants.
- *
- * @param repositoryName
- * the repository name
- * @throws WorkspaceRestoreExeption
- * will be generated WorkspaceRestoreExeption
- */
- private void validateOneRestoreInstants(String repositoryName) throws WorkspaceRestoreExeption
- {
-
- for (JobWorkspaceRestore job : backupManager.getRestores())
- if (repositoryName.equals(job.getRepositoryName())
- && (job.getStateRestore() == JobWorkspaceRestore.RESTORE_INITIALIZED || job.getStateRestore() == JobWorkspaceRestore.RESTORE_STARTED))
- {
- throw new WorkspaceRestoreExeption("The workspace '" + "/" + repositoryName + "' is already restoring.");
- }
- }
-
- /**
* forceCloseSession. Close sessions on specific workspace.
*
* @param repositoryName
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/registry/RegistryService.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/registry/RegistryService.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/registry/RegistryService.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -375,13 +375,11 @@
}
catch (RepositoryConfigurationException e)
{
- log.error(e.getLocalizedMessage());
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
catch (RepositoryException e)
{
- log.error(e.getLocalizedMessage());
- e.printStackTrace();
+ log.error(e.getLocalizedMessage(), e);
}
else if (log.isDebugEnabled())
log.warn("Registry service already started");
@@ -443,19 +441,19 @@
Throwable cause = pae.getCause();
if (cause instanceof ParserConfigurationException)
{
- cause.printStackTrace();
+ log.error(cause.getLocalizedMessage(), cause);
}
else if (cause instanceof IOException)
{
- cause.printStackTrace();
+ log.error(cause.getLocalizedMessage(), cause);
}
else if (cause instanceof SAXException)
{
- cause.printStackTrace();
+ log.error(cause.getLocalizedMessage(), cause);
}
else if (cause instanceof TransformerException)
{
- cause.printStackTrace();
+ log.error(cause.getLocalizedMessage(), cause);
}
else if (cause instanceof RuntimeException)
{
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/AbstractXMLViewNodeRepresentation.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/AbstractXMLViewNodeRepresentation.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/AbstractXMLViewNodeRepresentation.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -20,6 +20,8 @@
import org.exoplatform.common.util.HierarchicalProperty;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.io.IOException;
import java.io.InputStream;
@@ -41,6 +43,11 @@
public abstract class AbstractXMLViewNodeRepresentation implements NodeRepresentation
{
+ /**
+ * Logger.
+ */
+ private static final Log LOG = ExoLogger.getLogger("exo.jcr.component.ext.AbstractXMLViewNodeRepresentation");
+
private Node node;
protected boolean isSystem;
@@ -176,7 +183,7 @@
}
catch (Exception e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
throw new IOException("can't get input stream");
}
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtFileNodeRepresentationFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtFileNodeRepresentationFactory.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtFileNodeRepresentationFactory.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -21,6 +21,8 @@
import org.exoplatform.services.jcr.ext.resource.NodeRepresentation;
import org.exoplatform.services.jcr.ext.resource.NodeRepresentationFactory;
import org.exoplatform.services.jcr.ext.resource.NodeRepresentationService;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
@@ -32,6 +34,11 @@
public class NtFileNodeRepresentationFactory implements NodeRepresentationFactory
{
+ /**
+ * Logger.
+ */
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.ext.NtFileNodeRepresentationFactory");
+
protected NodeRepresentationService nodeRepresentationService;
/**
@@ -64,7 +71,7 @@
}
catch (RepositoryException e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
return null;
}
Modified: jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtResourceNodeRepresentationFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtResourceNodeRepresentationFactory.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/main/java/org/exoplatform/services/jcr/ext/resource/representation/NtResourceNodeRepresentationFactory.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -20,6 +20,8 @@
import org.exoplatform.services.jcr.ext.resource.NodeRepresentation;
import org.exoplatform.services.jcr.ext.resource.NodeRepresentationFactory;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
@@ -30,6 +32,10 @@
*/
public class NtResourceNodeRepresentationFactory implements NodeRepresentationFactory
{
+ /**
+ * Logger.
+ */
+ private static Log LOG = ExoLogger.getLogger("exo.jcr.component.ext.NtFileNodeRepresentationFactory");
/**
* {@inheritDoc}
@@ -45,7 +51,7 @@
}
catch (RepositoryException e)
{
- e.printStackTrace();
+ LOG.error(e.getLocalizedMessage(), e);
}
return null;
}
Modified: jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/common/DynamicSessionProviderTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/common/DynamicSessionProviderTest.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ext/src/test/java/org/exoplatform/services/jcr/ext/common/DynamicSessionProviderTest.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -21,8 +21,9 @@
import org.exoplatform.services.jcr.access.SystemIdentity;
import org.exoplatform.services.jcr.core.CredentialsImpl;
import org.exoplatform.services.jcr.ext.BaseStandaloneTest;
-import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
import java.util.ArrayList;
import java.util.List;
@@ -52,6 +53,8 @@
root.save();
}
+ private static final Log log = ExoLogger.getLogger("exo.jcr.component.ext.DynamicTest");
+
public void testDynamicSession() throws Exception
{
// Mary only node, Mary membership is '*:/platform/users', seems it's user
Modified: jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpTextUtils.java
===================================================================
--- jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpTextUtils.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/FtpTextUtils.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -52,8 +52,7 @@
}
catch (Exception exc)
{
- log.info("Unhandled exception. " + exc.getMessage());
- exc.printStackTrace();
+ log.info("Unhandled exception. " + exc.getMessage(), exc);
}
String resStr = "";
for (int i = 0; i < reqLen; i++)
Modified: jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientCommandThread.java
===================================================================
--- jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientCommandThread.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/client/FtpClientCommandThread.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -185,8 +185,7 @@
}
catch (Exception exc)
{
- log.info("Unahdled exception. " + exc.getMessage());
- exc.printStackTrace();
+ log.info("Unahdled exception. " + exc.getMessage(), exc);
}
}
Modified: jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/command/CmdStor.java
===================================================================
--- jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/command/CmdStor.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.ftp/src/main/java/org/exoplatform/services/ftp/command/CmdStor.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -240,7 +240,6 @@
}
catch (Exception exc)
{
- exc.printStackTrace();
log.info("Unhandled exception. " + exc.getMessage(), exc);
}
Modified: jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java
===================================================================
--- jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -192,10 +192,7 @@
}
catch (Exception exc)
{
-
- System.out.println("Unhandled Exception. " + exc.getMessage());
log.error(exc.getMessage(), exc);
-
throw new IOException(exc.getMessage());
}
}
Modified: jcr/trunk/exo.jcr.connectors.localadapter/src/main/java/org/exoplatform/connectors/jcr/adapters/local/JcrResourceAdapter.java
===================================================================
--- jcr/trunk/exo.jcr.connectors.localadapter/src/main/java/org/exoplatform/connectors/jcr/adapters/local/JcrResourceAdapter.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.connectors.localadapter/src/main/java/org/exoplatform/connectors/jcr/adapters/local/JcrResourceAdapter.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -53,7 +53,7 @@
public synchronized void start(BootstrapContext ctx) throws ResourceAdapterInternalException
{
- System.out.println("<<<<<<<<<<<<<<<<<< JcrResourceAdapter.start(), " + containerConfig + " >>>>>>>>>>>>>>>>>>>");
+ log.info("<<<<<<<<<<<<<<<<<< JcrResourceAdapter.start(), " + containerConfig + " >>>>>>>>>>>>>>>>>>>");
log.info("Container config: " + containerConfig);
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
@@ -68,8 +68,7 @@
}
catch (MalformedURLException e)
{
- log.warn("Invalid containerConfig URL, ignored: " + containerConfig);
- e.printStackTrace();
+ log.warn("Invalid containerConfig URL, ignored: " + containerConfig, e);
}
try
@@ -78,8 +77,7 @@
}
catch (Exception e)
{
- log.error("Standalone container start error: " + e);
- e.printStackTrace();
+ log.error("Standalone container start error: " + e, e);
}
}
@@ -89,7 +87,7 @@
*/
public void stop()
{
- System.out.println("<<<<<<<<<<<<<<<<<< JcrResourceAdapter.stop(), " + containerConfig + " >>>>>>>>>>>>>>>>>>>");
+ log.info("<<<<<<<<<<<<<<<<<< JcrResourceAdapter.stop(), " + containerConfig + " >>>>>>>>>>>>>>>>>>>");
try
{
StandaloneContainer sc = StandaloneContainer.getInstance();
@@ -97,8 +95,7 @@
}
catch (Exception e)
{
- log.error("Standalone container stop error: " + e);
- e.printStackTrace();
+ log.error("Standalone container stop error: " + e, e);
}
}
Modified: jcr/trunk/exo.jcr.framework.ftpclient/src/main/java/org/exoplatform/frameworks/ftpclient/data/FtpDataTransiverImpl.java
===================================================================
--- jcr/trunk/exo.jcr.framework.ftpclient/src/main/java/org/exoplatform/frameworks/ftpclient/data/FtpDataTransiverImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
+++ jcr/trunk/exo.jcr.framework.ftpclient/src/main/java/org/exoplatform/frameworks/ftpclient/data/FtpDataTransiverImpl.java 2011-04-21 14:58:32 UTC (rev 4269)
@@ -127,7 +127,7 @@
}
catch (Exception exc)
{
- exc.printStackTrace();
+ log.error(exc.getLocalizedMessage(), exc);
}
try
15 years
exo-jcr SVN: r4268 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/impl/core and 4 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-04-21 09:27:25 -0400 (Thu, 21 Apr 2011)
New Revision: 4268
Added:
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/nodetypes/TestNodeDefinition.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java
jcr/trunk/exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml
Log:
JCR-1310: Error when get node definition for node
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -100,6 +100,19 @@
InternalQName[] mixinTypes) throws RepositoryException;
/**
+ * Found node definition based on node name and node type. In case when
+ * suitable node definition not found first occurred residual definition will
+ * be returned.
+ *
+ * @param nodeName
+ * @param parentNodeType
+ * @param parentMixinTypes
+ * @return
+ */
+ NodeDefinitionData getChildNodeDefinition(InternalQName nodeName, InternalQName nodeType,
+ InternalQName parentNodeType, InternalQName[] parentMixinTypes) throws RepositoryException;
+
+ /**
* Returns the <i>direct</i> subtypes of this node type in the node type
* inheritance hierarchy, that is, those which actually declared this node
* type in their list of supertypes.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -299,7 +299,7 @@
primaryTypeName = nodeDef.getDefaultPrimaryType();
}
// try to make new node
- return doAddNode(parent, name, primaryTypeName);
+ return doAddNode(parent, name, primaryTypeName, nodeDef);
}
@@ -345,7 +345,7 @@
InternalQName ptName = locationFactory.parseJCRName(nodeTypeName).getInternalName();
// try to make new node
- return doAddNode(parent, name, ptName);
+ return doAddNode(parent, name, ptName, null);
}
/**
@@ -897,8 +897,8 @@
NodeData parent = (NodeData)dataManager.getItemData(getParentIdentifier());
this.definition =
- nodeTypesHolder.getChildNodeDefinition(getInternalName(), parent.getPrimaryTypeName(), parent
- .getMixinTypeNames());
+ nodeTypesHolder.getChildNodeDefinition(getInternalName(), nodeData().getPrimaryTypeName(),
+ parent.getPrimaryTypeName(), parent.getMixinTypeNames());
if (definition == null)
{
@@ -1591,8 +1591,11 @@
}
this.definition =
- session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(getInternalName(),
- parent.getPrimaryTypeName(), parent.getMixinTypeNames());
+ session
+ .getWorkspace()
+ .getNodeTypesHolder()
+ .getChildNodeDefinition(getInternalName(), nodeData().getPrimaryTypeName(), parent.getPrimaryTypeName(),
+ parent.getMixinTypeNames());
if (definition == null)
{
@@ -2513,8 +2516,11 @@
}
// Check if node is not protected
NodeDefinitionData childNodeDefinition =
- session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(name, nodeData().getPrimaryTypeName(),
- nodeData().getMixinTypeNames());
+ session
+ .getWorkspace()
+ .getNodeTypesHolder()
+ .getChildNodeDefinition(name, primaryTypeName, nodeData().getPrimaryTypeName(),
+ nodeData().getMixinTypeNames());
if (childNodeDefinition == null)
{
throw new ConstraintViolationException("Can't find child node definition for "
@@ -2987,14 +2993,23 @@
return dataManager.getLastOrderNumber(nodeData()) + 1;
}
- private int getNextChildIndex(InternalQName nameToAdd, NodeData parentNode) throws RepositoryException,
- ItemExistsException
+ /**
+ * Calculates next child node index. Is used existed node definition, if no - get one based on node name
+ * and node type.
+ */
+ private int getNextChildIndex(InternalQName nameToAdd, InternalQName primaryTypeName, NodeData parentNode,
+ NodeDefinitionData def) throws RepositoryException, ItemExistsException
{
+ if (def == null)
+ {
+ def =
+ session
+ .getWorkspace()
+ .getNodeTypesHolder()
+ .getChildNodeDefinition(nameToAdd, primaryTypeName, parentNode.getPrimaryTypeName(),
+ parentNode.getMixinTypeNames());
+ }
- NodeDefinitionData def =
- session.getWorkspace().getNodeTypesHolder().getChildNodeDefinition(nameToAdd, parentNode.getPrimaryTypeName(),
- parentNode.getMixinTypeNames());
-
boolean allowSns = def.isAllowsSameNameSiblings();
int ind = 1;
@@ -3015,27 +3030,16 @@
};
return ind;
-
- // int ind = 0;
- // for (NodeData sibling : siblings)
- // {
- // if (sibling.getQPath().getName().equals(nameToAdd))
- // {
- // if (allowSns)
- // ind++;
- // else
- // throw new ItemExistsException("The node " + nameToAdd + " already exists in " + getPath()
- // + " and same name sibling is not allowed ");
- // }
- // }
- // return ind + 1;
-
}
- private NodeImpl doAddNode(NodeImpl parentNode, InternalQName name, InternalQName primaryTypeName)
- throws ItemExistsException, RepositoryException, ConstraintViolationException, VersionException, LockException
+ /**
+ * Do add node internally. If nodeDef not null it is used in getNextChildIndex() method to
+ * avoid double calculation.
+ */
+ private NodeImpl doAddNode(NodeImpl parentNode, InternalQName name, InternalQName primaryTypeName,
+ NodeDefinitionData nodeDef) throws ItemExistsException, RepositoryException, ConstraintViolationException,
+ VersionException, LockException
{
-
validateChildNode(name, primaryTypeName);
// Initialize data
@@ -3043,7 +3047,7 @@
String identifier = IdGenerator.generate();
int orderNum = parentNode.getNextChildOrderNum();
- int index = parentNode.getNextChildIndex(name, parentNode.nodeData());
+ int index = parentNode.getNextChildIndex(name, primaryTypeName, parentNode.nodeData(), nodeDef);
QPath path = QPath.makeChildPath(parentNode.getInternalPath(), name, index);
@@ -3067,7 +3071,6 @@
{
dataManager.updateItemState(autoCreatedState);
}
- // addAutoCreatedItems(node.nodeData(), primaryTypeName);
if (LOG.isDebugEnabled())
{
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -186,7 +186,6 @@
* @throws RepositoryException
*/
public NodeDefinitionData[] getAllChildNodeDefinitions(final InternalQName... nodeTypeNames)
-
{
final Collection<NodeDefinitionData> defsAny = new ArrayList<NodeDefinitionData>();
final HashMap<InternalQName, NodeDefinitionData> defs = new HashMap<InternalQName, NodeDefinitionData>();
@@ -224,7 +223,7 @@
}
defsAny.addAll(defs.values());
-
+
return defsAny.toArray(new NodeDefinitionData[defsAny.size()]);
}
@@ -301,16 +300,7 @@
public NodeDefinitionData getChildNodeDefinition(final InternalQName nodeName, final InternalQName... nodeTypeNames)
throws RepositoryException
{
-
- NodeDefinitionData ndResidual = this.nodeTypeRepository.getDefaultChildNodeDefinition(nodeName, nodeTypeNames);
-
- if (ndResidual == null && !Constants.JCR_ANY_NAME.equals(nodeName))
- {
- ndResidual = getChildNodeDefinition(Constants.JCR_ANY_NAME, nodeTypeNames);
- }
-
- return ndResidual;
-
+ return this.nodeTypeRepository.getDefaultChildNodeDefinition(nodeName, nodeTypeNames);
}
/**
@@ -320,19 +310,53 @@
public NodeDefinitionData getChildNodeDefinition(final InternalQName nodeName, final InternalQName primaryNodeType,
final InternalQName[] mixinTypes) throws RepositoryException
{
+ return getChildNodeDefinition(nodeName, getNodeTypeNames(primaryNodeType, mixinTypes));
+ }
- if (mixinTypes != null)
+ /**
+ * {@inheritDoc}
+ */
+ public NodeDefinitionData getChildNodeDefinition(InternalQName nodeName, InternalQName nodeType,
+ InternalQName parentNodeType, InternalQName[] parentMixinTypes) throws RepositoryException
+ {
+ NodeDefinitionData[] defs = getAllChildNodeDefinitions(getNodeTypeNames(parentNodeType, parentMixinTypes));
+
+ NodeDefinitionData residualDef = null;
+ NodeDefinitionData firstResidualDef = null;
+
+ outer : for (NodeDefinitionData nodeDef : defs)
{
- final InternalQName[] nts = new InternalQName[mixinTypes.length + 1];
- nts[0] = primaryNodeType;
- for (int i = 0; i < mixinTypes.length; i++)
+ if (nodeDef.getName().equals(nodeName))
{
- nts[i + 1] = mixinTypes[i];
+ return nodeDef;
}
- return getChildNodeDefinition(nodeName, nts);
+ else if (nodeDef.isResidualSet())
+ {
+ // store first residual definition to be able to return
+ if (firstResidualDef == null)
+ {
+ firstResidualDef = nodeDef;
+ }
+
+ // check required primary types
+ for (InternalQName requiredPrimaryType : nodeDef.getRequiredPrimaryTypes())
+ {
+ if (!isNodeType(requiredPrimaryType, nodeType))
+ {
+ continue outer;
+ }
+ }
+
+ // when there are several suitable definitions take the most older
+ if (residualDef == null
+ || isNodeType(residualDef.getRequiredPrimaryTypes()[0], nodeDef.getRequiredPrimaryTypes()[0]))
+ {
+ residualDef = nodeDef;
+ }
+ }
}
- return getChildNodeDefinition(nodeName, primaryNodeType);
+ return residualDef != null ? residualDef : firstResidualDef;
}
/**
@@ -1017,4 +1041,21 @@
return changesLog;
}
+
+ private InternalQName[] getNodeTypeNames(final InternalQName primaryNodeType, final InternalQName[] mixinTypes)
+ throws RepositoryException
+ {
+ InternalQName[] ntn = new InternalQName[1 + (mixinTypes == null ? 0 : mixinTypes.length)];
+ ntn[0] = primaryNodeType;
+
+ if (mixinTypes != null)
+ {
+ for (int i = 0; i < mixinTypes.length; i++)
+ {
+ System.arraycopy(mixinTypes, 0, ntn, 1, mixinTypes.length);
+ }
+ }
+
+ return ntn;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -228,7 +228,8 @@
NodeData parent = (NodeData)dataManager.getItemData(node.getParentIdentifier());
NodeDefinitionData ndef =
- ntManager.getChildNodeDefinition(qname, parent.getPrimaryTypeName(), parent.getMixinTypeNames());
+ ntManager.getChildNodeDefinition(qname, node.getPrimaryTypeName(), parent.getPrimaryTypeName(),
+ parent.getMixinTypeNames());
if (ndef == null)
{
throw new ConstraintViolationException("Definition not found for " + qname.getAsString());
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -57,6 +57,7 @@
this.restoredChanges = changes;
}
+ @Override
protected void entering(PropertyData property, int level) throws RepositoryException
{
@@ -108,6 +109,7 @@
}
}
+ @Override
protected void entering(NodeData node, int level) throws RepositoryException
{
@@ -122,8 +124,8 @@
{
NodeData existedParent = (NodeData)dataManager.getItemData(node.getParentIdentifier());
NodeDefinitionData ndef =
- ntManager.getChildNodeDefinition(node.getQPath().getName(), existedParent.getPrimaryTypeName(),
- existedParent.getMixinTypeNames());
+ ntManager.getChildNodeDefinition(node.getQPath().getName(), node.getPrimaryTypeName(),
+ existedParent.getPrimaryTypeName(), existedParent.getMixinTypeNames());
// the node can be stored as IGNOREd in restore set, check an action
if (ndef.getOnParentVersion() == OnParentVersionAction.IGNORE)
@@ -164,6 +166,7 @@
parents.push(null); // skip this node as we hasn't parent in restore result
}
+ @Override
protected void leaving(NodeData node, int level) throws RepositoryException
{
if (parents.size() > 0)
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -199,8 +199,8 @@
{
NodeData parent = parents.peek();
int onParentVersion =
- nodeTypeDataManager.getChildNodeDefinition(node.getQPath().getName(), parent.getPrimaryTypeName(),
- parent.getMixinTypeNames()).getOnParentVersion();
+ nodeTypeDataManager.getChildNodeDefinition(node.getQPath().getName(), node.getPrimaryTypeName(),
+ parent.getPrimaryTypeName(), parent.getMixinTypeNames()).getOnParentVersion();
if (onParentVersion == OnParentVersionAction.VERSION
&& nodeTypeDataManager.isNodeType(Constants.MIX_VERSIONABLE, node.getPrimaryTypeName(),
@@ -675,7 +675,8 @@
// current C in the workspace will be left unchanged.
int action =
- nodeTypeDataManager.getChildNodeDefinition(qname, currentNode().getPrimaryTypeName(),
+ nodeTypeDataManager.getChildNodeDefinition(qname, frozen.getPrimaryTypeName(),
+ currentNode().getPrimaryTypeName(),
currentNode().getMixinTypeNames()).getOnParentVersion();
if (log.isDebugEnabled())
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/nodetypes/TestNodeDefinition.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/nodetypes/TestNodeDefinition.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/nodetypes/TestNodeDefinition.java 2011-04-21 13:27:25 UTC (rev 4268)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2003-2007 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * 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, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.api.nodetypes;
+
+import org.exoplatform.services.jcr.JcrAPIBaseTest;
+import org.exoplatform.services.jcr.impl.core.NodeImpl;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import java.util.GregorianCalendar;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.version.Version;
+
+/**
+ * @author <a href="mailto:anatoliy.bazko@gmail.com">Anatoliy Bazko</a>
+ * @version $Id: TestNodeDefinitionWCM.java 34360 2009-07-22 23:58:59Z tolusha $
+ */
+public class TestNodeDefinition extends JcrAPIBaseTest
+{
+
+ public void testNodeTypeWCM1() throws Exception
+ {
+ NodeImpl someNode = (NodeImpl)session.getRootNode().addNode("someNode");
+ someNode.addMixin("mix:referenceable");
+
+ NodeImpl exoWebContent = (NodeImpl)session.getRootNode().addNode("exoWebContent", "exo:webContent");
+ exoWebContent.setProperty("exo:title", "tit");
+ session.save();
+
+ // add nt:file
+ NodeImpl ntFile1 = (NodeImpl)exoWebContent.addNode("ntFile-1", "nt:file");
+ NodeImpl jcrContent = (NodeImpl)ntFile1.addNode("jcr:content", "nt:resource");
+ jcrContent.setProperty("jcr:data", "");
+ jcrContent.setProperty("jcr:mimeType", "");
+ jcrContent.setProperty("jcr:lastModified", new GregorianCalendar());
+ session.save();
+
+ exoWebContent.addMixin("exo:actionable");
+ exoWebContent.setProperty("exo:actions", someNode);
+ session.save();
+
+ // add exo:actionStorage
+ NodeImpl actionStorage = (NodeImpl)exoWebContent.addNode("actionStorage", "exo:actionStorage");
+ session.save();
+
+ // add nt:file
+ NodeImpl ntFile2 = (NodeImpl)exoWebContent.addNode("ntFile-2", "nt:file");
+ jcrContent = (NodeImpl)ntFile2.addNode("jcr:content", "nt:resource");
+ jcrContent.setProperty("jcr:data", "");
+ jcrContent.setProperty("jcr:mimeType", "");
+ jcrContent.setProperty("jcr:lastModified", new GregorianCalendar());
+ session.save();
+
+ SessionImpl session = (SessionImpl)repository.login(credentials, WORKSPACE);
+
+ ntFile1 = (NodeImpl)session.getRootNode().getNode("exoWebContent").getNode("ntFile-1");
+ assertEquals(ntFile1.getDefinition().getRequiredPrimaryTypes()[0].getName(), "nt:base");
+
+ ntFile2 = (NodeImpl)session.getRootNode().getNode("exoWebContent").getNode("ntFile-2");
+ assertEquals(ntFile2.getDefinition().getRequiredPrimaryTypes()[0].getName(), "nt:base");
+
+ actionStorage = (NodeImpl)session.getRootNode().getNode("exoWebContent").getNode("actionStorage");
+ assertEquals(actionStorage.getDefinition().getRequiredPrimaryTypes()[0].getName(), "exo:actionStorage");
+ }
+
+ public void testNodeTypeWCM2() throws Exception
+ {
+ Node parent = session.getRootNode().addNode("parent", "exo:newsletterCategory");
+ parent.addNode("child", "nt:unstructured");
+ parent.setProperty("exo:newsletterCategoryTitle", "title");
+ session.save();
+ }
+
+ public void testNTVersionedChild() throws Exception
+ {
+ Node folder1 = session.getRootNode().addNode("folder1", "nt:folder");
+ Node folder2 = folder1.addNode("folder2", "nt:folder");
+ Node folder3 = folder2.addNode("folder3", "nt:folder");
+ folder1.addMixin("mix:versionable");
+ folder3.addMixin("mix:versionable");
+ session.save();
+
+ Version ver1 = folder1.checkin();
+ folder1.checkout();
+
+ folder3 =
+ (NodeImpl)session.getItem("/jcr:system/jcr:versionStorage/" + ver1.getParent().getUUID()
+ + "/1/jcr:frozenNode/folder2/folder3");
+
+ try
+ {
+ folder3.getDefinition();
+ }
+ catch (RepositoryException e)
+ {
+ fail();
+ }
+ }
+}
Modified: jcr/trunk/exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml 2011-04-21 13:09:24 UTC (rev 4267)
+++ jcr/trunk/exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml 2011-04-21 13:27:25 UTC (rev 4268)
@@ -253,4 +253,90 @@
</propertyDefinitions>
</nodeType>
+ <nodeType name="exo:newsletterEntry" isMixin="true" hasOrderableChildNodes="true" primaryItemName="">
+ <propertyDefinitions>
+ <propertyDefinition name="exo:newsletterEntryCategoryName" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterEntrySubscriptionName" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterEntryType" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterEntryDate" requiredType="Date" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterEntryStatus" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ </propertyDefinitions>
+ </nodeType>
+
+ <nodeType name="exo:newsletterSubscription" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
+ <supertypes>
+ <supertype>nt:unstructured</supertype>
+ <supertype>mix:referenceable</supertype>
+ </supertypes>
+ <propertyDefinitions>
+ <propertyDefinition name="exo:newsletterSubscribedUser" requiredType="Reference" autoCreated="true" mandatory="false" onParentVersion="COPY" protected="false" multiple="true">
+ <valueConstraints/>
+ </propertyDefinition>
+ </propertyDefinitions>
+ <childNodeDefinitions>
+ <childNodeDefinition name="*" defaultPrimaryType="nt:base" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="false" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>nt:base</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ </childNodeDefinitions>
+ </nodeType>
+
+ <nodeType name="exo:newsletterCategory" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
+ <supertypes>
+ <supertype>nt:unstructured</supertype>
+ </supertypes>
+ <propertyDefinitions>
+ <propertyDefinition name="exo:newsletterCategoryTitle" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterCategoryDescription" requiredType="String" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ </propertyDefinitions>
+ <childNodeDefinitions>
+ <childNodeDefinition name="*" defaultPrimaryType="nt:unstructured" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="false" sameNameSiblings="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>nt:base</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ <childNodeDefinition name="*" defaultPrimaryType="exo:newsletterSubscription" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="false" sameNameSiblings="true">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>exo:newsletterSubscription</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDefinition>
+ </childNodeDefinitions>
+ </nodeType>
+
+ <nodeType name="exo:newsletterUser" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
+ <supertypes>
+ <supertype>nt:unstructured</supertype>
+ <supertype>mix:referenceable</supertype>
+ </supertypes>
+ <propertyDefinitions>
+ <propertyDefinition name="exo:newsletterUserMail" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterUserConfirm" requiredType="Boolean" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterUserBanned" requiredType="Boolean" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ <propertyDefinition name="exo:newsletterUserValidationCode" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
+ <valueConstraints/>
+ </propertyDefinition>
+ </propertyDefinitions>
+ </nodeType>
+
</nodeTypes>
15 years
exo-jcr SVN: r4267 - in jcr/branches/1.12.x/patch/1.12.9-GA: JCR-1616 and 1 other directory.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-04-21 09:09:24 -0400 (Thu, 21 Apr 2011)
New Revision: 4267
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1616/
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1616/JCR-1616.patch
Log:
JCR-1616: patch proposed
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1616/JCR-1616.patch
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1616/JCR-1616.patch (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1616/JCR-1616.patch 2011-04-21 13:09:24 UTC (rev 4267)
@@ -0,0 +1,451 @@
+Index: exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml
+===================================================================
+--- exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml (revision 4266)
++++ exo.jcr.component.core/src/test/resources/conf/test/wcm-nodetypes.xml (working copy)
+@@ -253,4 +253,90 @@
+ </propertyDefinitions>
+ </nodeType>
+
++ <nodeType name="exo:newsletterEntry" isMixin="true" hasOrderableChildNodes="true" primaryItemName="">
++ <propertyDefinitions>
++ <propertyDefinition name="exo:newsletterEntryCategoryName" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterEntrySubscriptionName" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterEntryType" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterEntryDate" requiredType="Date" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterEntryStatus" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ </propertyDefinitions>
++ </nodeType>
++
++ <nodeType name="exo:newsletterSubscription" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
++ <supertypes>
++ <supertype>nt:unstructured</supertype>
++ <supertype>mix:referenceable</supertype>
++ </supertypes>
++ <propertyDefinitions>
++ <propertyDefinition name="exo:newsletterSubscribedUser" requiredType="Reference" autoCreated="true" mandatory="false" onParentVersion="COPY" protected="false" multiple="true">
++ <valueConstraints/>
++ </propertyDefinition>
++ </propertyDefinitions>
++ <childNodeDefinitions>
++ <childNodeDefinition name="*" defaultPrimaryType="nt:base" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="false" sameNameSiblings="false">
++ <requiredPrimaryTypes>
++ <requiredPrimaryType>nt:base</requiredPrimaryType>
++ </requiredPrimaryTypes>
++ </childNodeDefinition>
++ </childNodeDefinitions>
++ </nodeType>
++
++ <nodeType name="exo:newsletterCategory" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
++ <supertypes>
++ <supertype>nt:unstructured</supertype>
++ </supertypes>
++ <propertyDefinitions>
++ <propertyDefinition name="exo:newsletterCategoryTitle" requiredType="String" autoCreated="false" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterCategoryDescription" requiredType="String" autoCreated="false" mandatory="false" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ </propertyDefinitions>
++ <childNodeDefinitions>
++ <childNodeDefinition name="*" defaultPrimaryType="nt:unstructured" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="false" sameNameSiblings="false">
++ <requiredPrimaryTypes>
++ <requiredPrimaryType>nt:base</requiredPrimaryType>
++ </requiredPrimaryTypes>
++ </childNodeDefinition>
++ <childNodeDefinition name="*" defaultPrimaryType="exo:newsletterSubscription" autoCreated="false" mandatory="false" onParentVersion="VERSION" protected="false" sameNameSiblings="true">
++ <requiredPrimaryTypes>
++ <requiredPrimaryType>exo:newsletterSubscription</requiredPrimaryType>
++ </requiredPrimaryTypes>
++ </childNodeDefinition>
++ </childNodeDefinitions>
++ </nodeType>
++
++ <nodeType name="exo:newsletterUser" isMixin="false" hasOrderableChildNodes="true" primaryItemName="">
++ <supertypes>
++ <supertype>nt:unstructured</supertype>
++ <supertype>mix:referenceable</supertype>
++ </supertypes>
++ <propertyDefinitions>
++ <propertyDefinition name="exo:newsletterUserMail" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterUserConfirm" requiredType="Boolean" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterUserBanned" requiredType="Boolean" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ <propertyDefinition name="exo:newsletterUserValidationCode" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY" protected="false" multiple="false">
++ <valueConstraints/>
++ </propertyDefinition>
++ </propertyDefinitions>
++ </nodeType>
++
+ </nodeTypes>
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java (revision 4266)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java (working copy)
+@@ -275,7 +275,7 @@
+
+ primaryTypeName = nodeDef.getDefaultPrimaryType();
+ // try to make new node
+- return doAddNode(parent, name, primaryTypeName);
++ return doAddNode(parent, name, primaryTypeName, nodeDef);
+
+ }
+
+@@ -313,7 +313,7 @@
+ InternalQName ptName = locationFactory.parseJCRName(nodeTypeName).getInternalName();
+
+ // try to make new node
+- return doAddNode(parent, name, ptName);
++ return doAddNode(parent, name, ptName, null);
+ }
+
+ /**
+@@ -832,8 +832,8 @@
+ NodeData parent = (NodeData)dataManager.getItemData(getParentIdentifier());
+
+ this.definition =
+- nodeTypesHolder.getChildNodeDefinition(getInternalName(), parent.getPrimaryTypeName(),
+- parent.getMixinTypeNames());
++ nodeTypesHolder.getChildNodeDefinition(getInternalName(), nodeData().getPrimaryTypeName(),
++ parent.getPrimaryTypeName(), parent.getMixinTypeNames());
+
+ if (definition == null)
+ {
+@@ -1513,8 +1513,11 @@
+ }
+
+ this.definition =
+- session.getWorkspace().getNodeTypesHolder()
+- .getChildNodeDefinition(getInternalName(), parent.getPrimaryTypeName(), parent.getMixinTypeNames());
++ session
++ .getWorkspace()
++ .getNodeTypesHolder()
++ .getChildNodeDefinition(getInternalName(), nodeData().getPrimaryTypeName(), parent.getPrimaryTypeName(),
++ parent.getMixinTypeNames());
+
+ if (definition == null)
+ {
+@@ -2371,8 +2374,12 @@
+ }
+ // Check if node is not protected
+ NodeDefinitionData childNodeDefinition =
+- session.getWorkspace().getNodeTypesHolder()
+- .getChildNodeDefinition(name, nodeData().getPrimaryTypeName(), nodeData().getMixinTypeNames());
++ session
++ .getWorkspace()
++ .getNodeTypesHolder()
++ .getChildNodeDefinition(name, primaryTypeName, nodeData().getPrimaryTypeName(),
++ nodeData().getMixinTypeNames());
++
+ if (childNodeDefinition == null)
+ throw new ConstraintViolationException("Can't find child node definition for "
+ + sysLocFactory.createJCRName(name).getAsString() + " in " + getPath());
+@@ -2827,14 +2834,23 @@
+ return dataManager.getChildNodesCount(nodeData());
+ }
+
+- private int getNextChildIndex(InternalQName nameToAdd, NodeData parentNode) throws RepositoryException,
+- ItemExistsException
++ /**
++ * Calculates next child node index. Is used existed node definition, if no - get one based on node name
++ * and node type.
++ */
++ private int getNextChildIndex(InternalQName nameToAdd, InternalQName primaryTypeName, NodeData parentNode,
++ NodeDefinitionData def) throws RepositoryException, ItemExistsException
+ {
++ if (def == null)
++ {
++ def =
++ session
++ .getWorkspace()
++ .getNodeTypesHolder()
++ .getChildNodeDefinition(nameToAdd, primaryTypeName, parentNode.getPrimaryTypeName(),
++ parentNode.getMixinTypeNames());
++ }
+
+- NodeDefinitionData def =
+- session.getWorkspace().getNodeTypesHolder()
+- .getChildNodeDefinition(nameToAdd, parentNode.getPrimaryTypeName(), parentNode.getMixinTypeNames());
+-
+ boolean allowSns = def.isAllowsSameNameSiblings();
+
+ int ind = 1;
+@@ -2855,27 +2871,16 @@
+ };
+
+ return ind;
+-
+- // int ind = 0;
+- // for (NodeData sibling : siblings)
+- // {
+- // if (sibling.getQPath().getName().equals(nameToAdd))
+- // {
+- // if (allowSns)
+- // ind++;
+- // else
+- // throw new ItemExistsException("The node " + nameToAdd + " already exists in " + getPath()
+- // + " and same name sibling is not allowed ");
+- // }
+- // }
+- // return ind + 1;
+-
+ }
+
+- private NodeImpl doAddNode(NodeImpl parentNode, InternalQName name, InternalQName primaryTypeName)
+- throws ItemExistsException, RepositoryException, ConstraintViolationException, VersionException, LockException
++ /**
++ * Do add node internally. If nodeDef not null it is used in getNextChildIndex() method to
++ * avoid double calculation.
++ */
++ private NodeImpl doAddNode(NodeImpl parentNode, InternalQName name, InternalQName primaryTypeName,
++ NodeDefinitionData nodeDef) throws ItemExistsException, RepositoryException, ConstraintViolationException,
++ VersionException, LockException
+ {
+-
+ validateChildNode(name, primaryTypeName);
+
+ // Initialize data
+@@ -2883,7 +2888,7 @@
+ String identifier = IdGenerator.generate();
+
+ int orderNum = parentNode.getNextChildOrderNum();
+- int index = parentNode.getNextChildIndex(name, parentNode.nodeData());
++ int index = parentNode.getNextChildIndex(name, primaryTypeName, parentNode.nodeData(), nodeDef);
+
+ QPath path = QPath.makeChildPath(parentNode.getInternalPath(), name, index);
+
+@@ -2907,7 +2912,6 @@
+ {
+ dataManager.updateItemState(autoCreatedState);
+ }
+- // addAutoCreatedItems(node.nodeData(), primaryTypeName);
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("new node : " + node.getPath() + " name: " + " primaryType: " + node.getPrimaryNodeType().getName()
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java (revision 4266)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataCopyIgnoredVisitor.java (working copy)
+@@ -57,6 +57,7 @@
+ this.restoredChanges = changes;
+ }
+
++ @Override
+ protected void entering(PropertyData property, int level) throws RepositoryException
+ {
+
+@@ -108,6 +109,7 @@
+ }
+ }
+
++ @Override
+ protected void entering(NodeData node, int level) throws RepositoryException
+ {
+
+@@ -122,8 +124,8 @@
+ {
+ NodeData existedParent = (NodeData)dataManager.getItemData(node.getParentIdentifier());
+ NodeDefinitionData ndef =
+- ntManager.getChildNodeDefinition(node.getQPath().getName(), existedParent.getPrimaryTypeName(),
+- existedParent.getMixinTypeNames());
++ ntManager.getChildNodeDefinition(node.getQPath().getName(), node.getPrimaryTypeName(),
++ existedParent.getPrimaryTypeName(), existedParent.getMixinTypeNames());
+
+ // the node can be stored as IGNOREd in restore set, check an action
+ if (ndef.getOnParentVersion() == OnParentVersionAction.IGNORE)
+@@ -164,6 +166,7 @@
+ parents.push(null); // skip this node as we hasn't parent in restore result
+ }
+
++ @Override
+ protected void leaving(NodeData node, int level) throws RepositoryException
+ {
+ if (parents.size() > 0)
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java (revision 4266)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/ItemDataRestoreVisitor.java (working copy)
+@@ -536,7 +536,8 @@
+ // current C in the workspace will be left unchanged.
+
+ int action =
+- nodeTypeDataManager.getChildNodeDefinition(qname, currentNode().getPrimaryTypeName(),
++ nodeTypeDataManager.getChildNodeDefinition(qname, frozen.getPrimaryTypeName(),
++ currentNode().getPrimaryTypeName(),
+ currentNode().getMixinTypeNames()).getOnParentVersion();
+
+ if (log.isDebugEnabled())
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java (revision 4266)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/version/FrozenNodeInitializer.java (working copy)
+@@ -228,7 +228,8 @@
+
+ NodeData parent = (NodeData)dataManager.getItemData(node.getParentIdentifier());
+ NodeDefinitionData ndef =
+- ntManager.getChildNodeDefinition(qname, parent.getPrimaryTypeName(), parent.getMixinTypeNames());
++ ntManager.getChildNodeDefinition(qname, node.getPrimaryTypeName(), parent.getPrimaryTypeName(),
++ parent.getMixinTypeNames());
+ if (ndef == null)
+ {
+ throw new ConstraintViolationException("Definition not found for " + qname.getAsString());
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java (revision 4266)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/nodetype/NodeTypeDataManagerImpl.java (working copy)
+@@ -184,7 +184,6 @@
+ * @throws RepositoryException
+ */
+ public NodeDefinitionData[] getAllChildNodeDefinitions(final InternalQName... nodeTypeNames)
+-
+ {
+ final Collection<NodeDefinitionData> defsAny = new ArrayList<NodeDefinitionData>();
+ final HashMap<InternalQName, NodeDefinitionData> defs = new HashMap<InternalQName, NodeDefinitionData>();
+@@ -224,6 +223,7 @@
+ defsAny.addAll(defs.values());
+
+ return defsAny.toArray(new NodeDefinitionData[defsAny.size()]);
++
+ }
+
+ /**
+@@ -299,16 +299,7 @@
+ public NodeDefinitionData getChildNodeDefinition(final InternalQName nodeName, final InternalQName... nodeTypeNames)
+ throws RepositoryException
+ {
+-
+- NodeDefinitionData ndResidual = this.nodeTypeRepository.getDefaultChildNodeDefinition(nodeName, nodeTypeNames);
+-
+- if (ndResidual == null && !Constants.JCR_ANY_NAME.equals(nodeName))
+- {
+- ndResidual = getChildNodeDefinition(Constants.JCR_ANY_NAME, nodeTypeNames);
+- }
+-
+- return ndResidual;
+-
++ return this.nodeTypeRepository.getDefaultChildNodeDefinition(nodeName, nodeTypeNames);
+ }
+
+ /**
+@@ -318,19 +309,53 @@
+ public NodeDefinitionData getChildNodeDefinition(final InternalQName nodeName, final InternalQName primaryNodeType,
+ final InternalQName[] mixinTypes) throws RepositoryException
+ {
++ return getChildNodeDefinition(nodeName, getNodeTypeNames(primaryNodeType, mixinTypes));
++ }
+
+- if (mixinTypes != null)
++ /**
++ * {@inheritDoc}
++ */
++ public NodeDefinitionData getChildNodeDefinition(InternalQName nodeName, InternalQName nodeType,
++ InternalQName parentNodeType, InternalQName[] parentMixinTypes) throws RepositoryException
++ {
++ NodeDefinitionData[] defs = getAllChildNodeDefinitions(getNodeTypeNames(parentNodeType, parentMixinTypes));
++
++ NodeDefinitionData residualDef = null;
++ NodeDefinitionData firstResidualDef = null;
++
++ outer : for (NodeDefinitionData nodeDef : defs)
+ {
+- final InternalQName[] nts = new InternalQName[mixinTypes.length + 1];
+- nts[0] = primaryNodeType;
+- for (int i = 0; i < mixinTypes.length; i++)
++ if (nodeDef.getName().equals(nodeName))
+ {
+- nts[i + 1] = mixinTypes[i];
++ return nodeDef;
+ }
+- return getChildNodeDefinition(nodeName, nts);
++ else if (nodeDef.isResidualSet())
++ {
++ // store first residual definition to be able to return
++ if (firstResidualDef == null)
++ {
++ firstResidualDef = nodeDef;
++ }
++
++ // check required primary types
++ for (InternalQName requiredPrimaryType : nodeDef.getRequiredPrimaryTypes())
++ {
++ if (!isNodeType(requiredPrimaryType, nodeType))
++ {
++ continue outer;
++ }
++ }
++
++ // when there are several suitable definitions take the most older
++ if (residualDef == null
++ || isNodeType(residualDef.getRequiredPrimaryTypes()[0], nodeDef.getRequiredPrimaryTypes()[0]))
++ {
++ residualDef = nodeDef;
++ }
++ }
+ }
+
+- return getChildNodeDefinition(nodeName, primaryNodeType);
++ return residualDef != null ? residualDef : firstResidualDef;
+ }
+
+ /**
+@@ -1009,4 +1034,21 @@
+
+ return changesLog;
+ }
++
++ private InternalQName[] getNodeTypeNames(final InternalQName primaryNodeType, final InternalQName[] mixinTypes)
++ throws RepositoryException
++ {
++ InternalQName[] ntn = new InternalQName[1 + (mixinTypes == null ? 0 : mixinTypes.length)];
++ ntn[0] = primaryNodeType;
++
++ if (mixinTypes != null)
++ {
++ for (int i = 0; i < mixinTypes.length; i++)
++ {
++ System.arraycopy(mixinTypes, 0, ntn, 1, mixinTypes.length);
++ }
++ }
++
++ return ntn;
++ }
+ }
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java (revision 4266)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/core/nodetype/NodeTypeDataManager.java (working copy)
+@@ -100,6 +100,19 @@
+ InternalQName[] mixinTypes) throws RepositoryException;
+
+ /**
++ * Found node definition based on node name and node type. In case when
++ * suitable node definition not found first occurred residual definition will
++ * be returned.
++ *
++ * @param nodeName
++ * @param parentNodeType
++ * @param parentMixinTypes
++ * @return
++ */
++ NodeDefinitionData getChildNodeDefinition(InternalQName nodeName, InternalQName nodeType,
++ InternalQName parentNodeType, InternalQName[] parentMixinTypes) throws RepositoryException;
++
++ /**
+ * Returns the <i>direct</i> subtypes of this node type in the node type
+ * inheritance hierarchy, that is, those which actually declared this node
+ * type in their list of supertypes.
15 years
exo-jcr SVN: r4266 - in jcr/branches/1.12.x: exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/propfind and 5 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-04-21 07:43:46 -0400 (Thu, 21 Apr 2011)
New Revision: 4266
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1605/readme.txt
Modified:
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/propfind/PropFindResponseEntity.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/proppatch/PropPatchResponseEntity.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/xml/PropertyWriteUtil.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropPatch.java
jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestSearch.java
Log:
JCR-1605
What is the problem to fix?
Can't open file containing special characters (e.g Japanese characters) in file name/path via WebDav in Nautilus. In case of cadaver, when using "ls" command, cadaver can't list such files.
How is the problem fixed?
Set the selected tab after user add any permission to the wanted one.
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/dasl/SearchResultResponseEntity.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -35,7 +35,6 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
-import java.net.URLDecoder;
import java.util.HashSet;
import java.util.Set;
@@ -172,7 +171,7 @@
xmlStreamWriter.writeStartElement("DAV:", "response");
xmlStreamWriter.writeStartElement("DAV:", "href");
- xmlStreamWriter.writeCharacters(URLDecoder.decode(resource.getIdentifier().toASCIIString(), "UTF-8"));
+ xmlStreamWriter.writeCharacters(resource.getIdentifier().toASCIIString());
xmlStreamWriter.writeEndElement();
PropstatGroupedRepresentation propstat = new PropstatGroupedRepresentation(resource, properties, false);
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/propfind/PropFindResponseEntity.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/propfind/PropFindResponseEntity.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/propfind/PropFindResponseEntity.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -32,7 +32,6 @@
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
-import java.net.URLDecoder;
import java.util.Set;
import javax.jcr.RepositoryException;
@@ -172,7 +171,7 @@
xmlStreamWriter.writeStartElement("DAV:", "response");
xmlStreamWriter.writeStartElement("DAV:", "href");
- String href = URLDecoder.decode(resource.getIdentifier().toASCIIString(), "UTF-8");
+ String href = resource.getIdentifier().toASCIIString();
if (resource.isCollection())
{
xmlStreamWriter.writeCharacters(href + "/");
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/proppatch/PropPatchResponseEntity.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/proppatch/PropPatchResponseEntity.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/command/proppatch/PropPatchResponseEntity.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -37,7 +37,6 @@
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
-import java.net.URLDecoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -155,7 +154,7 @@
xmlStreamWriter.writeStartElement("DAV:", "response");
xmlStreamWriter.writeStartElement("DAV:", "href");
- xmlStreamWriter.writeCharacters(URLDecoder.decode(uri.toASCIIString(), "UTF-8"));
+ xmlStreamWriter.writeCharacters(uri.toASCIIString());
xmlStreamWriter.writeEndElement();
Map<String, Set<HierarchicalProperty>> propStats = getPropStat();
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/resource/CollectionResource.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -29,9 +29,7 @@
import java.io.InputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
-import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
@@ -418,10 +416,8 @@
writer.writeStartElement(XML_NODE);
writer.writeAttribute(PREFIX_XMLNS, PREFIX_LINK);
writer.writeAttribute(XLINK_XMLNS, XLINK_LINK);
- String itemName = URLDecoder.decode(node.getName(), "UTF-8");
- writer.writeAttribute(XML_NAME, itemName);
- String itemPath = node.getPath();
- writer.writeAttribute(XML_HREF, rootHref + itemPath);
+ writer.writeAttribute(XML_NAME, node.getName());
+ writer.writeAttribute(XML_HREF, rootHref + TextUtil.escape(node.getPath(), '%', true));
// add properties
for (PropertyIterator pi = node.getProperties(); pi.hasNext();)
{
@@ -437,8 +433,8 @@
{
Node childNode = ni.nextNode();
writer.writeStartElement(XML_NODE);
- writer.writeAttribute(XML_NAME, URLDecoder.decode(childNode.getName(), "UTF-8"));
- String childNodeHref = rootHref + URLDecoder.decode(childNode.getPath(), "UTF-8");
+ writer.writeAttribute(XML_NAME, childNode.getName());
+ String childNodeHref = rootHref + TextUtil.escape(childNode.getPath(), '%', true);
writer.writeAttribute(XML_HREF, childNodeHref);
writer.writeEndElement();
}
@@ -453,10 +449,6 @@
{
LOG.error("Error has occured while xml processing : ", e);
}
- catch (UnsupportedEncodingException e)
- {
- LOG.warn(e.getMessage());
- }
finally
{
try
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/xml/PropertyWriteUtil.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/xml/PropertyWriteUtil.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/xml/PropertyWriteUtil.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -20,8 +20,6 @@
import org.exoplatform.common.util.HierarchicalProperty;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -135,21 +133,8 @@
}
writeAttributes(xmlStreamWriter, prop);
+ xmlStreamWriter.writeCharacters(prop.getValue());
- if (prop.getName().getLocalPart().equals("displayname") && containsEncodedChar(prop.getValue()))
- {
- try
- {
- xmlStreamWriter.writeCharacters(URLDecoder.decode(prop.getValue(), "UTF-8"));
- }
- catch (UnsupportedEncodingException e)
- {
- e.printStackTrace();
- }
- } else {
- xmlStreamWriter.writeCharacters(prop.getValue());
- }
-
xmlStreamWriter.writeEndElement();
}
}
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropFind.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -30,6 +30,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.net.URLDecoder;
import javax.jcr.Node;
import javax.ws.rs.core.HttpHeaders;
@@ -101,6 +102,42 @@
assertEquals(HTTPStatus.MULTISTATUS, containerResponseFind.getStatus());
}
+ /**
+ * Here we test WebDAV PROPFIND method implementation for correct response
+ * if request contains encoded non-latin characters. We send a request with
+ * corresponding character sequence and expect to receive response containing
+ * 'href' element with URL encoded characters and 'displayname' element containing
+ * non-latin characters.
+ * @throws Exception
+ */
+ public void testSimplePropFindWithNonLatin() throws Exception
+ {
+ // prepare file name and content
+ String encodedfileName = "%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a";
+ String decodedfileName = URLDecoder.decode(encodedfileName, "UTF-8");
+ String content = TestUtils.getFileContent();
+ TestUtils.addContent(session, decodedfileName, new ByteArrayInputStream(content.getBytes()), nt_webdave_file, "");
+ TestUtils.addNodeProperty(session, decodedfileName, authorProp, author);
+
+ ContainerResponse response =
+ service(WebDAVMethods.PROPFIND, getPathWS() + "/" + encodedfileName, "", null, allPropsXML.getBytes());
+
+ // serialize response entity to string
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ PropFindResponseEntity entity = (PropFindResponseEntity)response.getEntity();
+ entity.write(outputStream);
+ String resp = outputStream.toString();
+
+ System.out.println("=======PropFind response==========");
+ System.out.println(resp);
+ System.out.println("=======Decoded file name==========");
+ System.out.println(decodedfileName);
+ System.out.println("==================================");
+
+ assertTrue(resp.contains(encodedfileName));
+ assertTrue(resp.contains(decodedfileName));
+ }
+
public void testPropFind() throws Exception
{
String content = TestUtils.getFileContent();
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropPatch.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropPatch.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestPropPatch.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -25,6 +25,7 @@
import org.exoplatform.services.rest.impl.ContainerResponse;
import java.io.ByteArrayOutputStream;
+import java.net.URLDecoder;
import java.util.Calendar;
import javax.jcr.Node;
@@ -159,6 +160,52 @@
}
+ /**
+ * Here we test WebDAV PROPPATCH method implementation for correct response
+ * if request contains encoded non-latin characters. We send a request with
+ * corresponding character sequence and expect to receive response containing
+ * 'href' element with URL encoded characters.
+ * @throws Exception
+ */
+ public void testPropPatchWithNonLatin() throws Exception
+ {
+
+ // prepare file names, content
+ String encodedfileName = "%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a";
+ String decodedfileName = URLDecoder.decode(encodedfileName, "UTF-8");
+
+ Node node = session.getRootNode().addNode(decodedfileName, nt_webdave_file);
+ node.setProperty(authorProp, author);
+
+ node.addNode("jcr:content", "nt:resource");
+ Node content = node.getNode("jcr:content");
+ content.setProperty("jcr:mimeType", "text/xml");
+ content.setProperty("jcr:lastModified", Calendar.getInstance());
+ content.setProperty("jcr:data", "data");
+ node.addMixin("mix:lockable");
+ session.save();
+ node.lock(true, true);
+ session.save();
+
+ ContainerResponse response =
+ service(WebDAVMethods.PROPPATCH, getPathWS() + "/" + encodedfileName, "", null, patch.getBytes());
+
+ // serialize response entity to string
+ PropPatchResponseEntity entity = (PropPatchResponseEntity)response.getEntity();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ entity.write(outputStream);
+ String resp = outputStream.toString();
+
+ System.out.println("=======PropPatch response=========");
+ System.out.println(resp);
+ System.out.println("=======Decoded file name==========");
+ System.out.println(decodedfileName);
+ System.out.println("==================================");
+
+ assertTrue(resp.contains(encodedfileName));
+ assertFalse(resp.contains(decodedfileName));
+ }
+
// public void testPropPatch() throws Exception {
// String description = "test description property";
// String rights = "test rights property";
Modified: jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestSearch.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestSearch.java 2011-04-21 11:38:57 UTC (rev 4265)
+++ jcr/branches/1.12.x/exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestSearch.java 2011-04-21 11:43:46 UTC (rev 4266)
@@ -28,6 +28,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
+import java.net.URLDecoder;
import javax.ws.rs.core.MediaType;
@@ -45,6 +46,10 @@
private final String fileContent = "TEST FILE CONTENT...";
+ private final String sql = "<D:searchrequest xmlns:D='DAV:'>" + "<D:sql>"
+ + "SELECT * FROM nt:resource WHERE contains(*, 'TEST')" + "</D:sql>" + "</D:searchrequest>";
+
+
public void testBasicSearch() throws Exception
{
@@ -55,9 +60,6 @@
// "</D:xpath>" +
// "</D:searchrequest>";
- String sql =
- "<D:searchrequest xmlns:D='DAV:'>" + "<D:sql>" + "SELECT * FROM nt:resource WHERE contains(*, 'TEST')"
- + "</D:sql>" + "</D:searchrequest>";
InputStream inputStream = new ByteArrayInputStream(fileContent.getBytes());
TestUtils.addContent(session, fileName, inputStream, defaultFileNodeType, MediaType.TEXT_PLAIN);
@@ -70,6 +72,41 @@
assertTrue(result.contains(fileName));
}
+ /**
+ * Here we test WebDAV SEARCH method implementation for correct response
+ * if request contains encoded non-latin characters. We send a request with
+ * corresponding character sequence and expect to receive response containing
+ * 'href' element with URL encoded characters and 'displayname' element containing
+ * non-latin characters.
+ * @throws Exception
+ */
+ public void testBasicSearchWithNonLatin() throws Exception
+ {
+ // prepare file name, content
+ String encodedfileName = "%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a";
+ String decodedfileName = URLDecoder.decode(encodedfileName, "UTF-8");
+ InputStream inputStream = new ByteArrayInputStream(fileContent.getBytes());
+ TestUtils.addContent(session, decodedfileName, inputStream, defaultFileNodeType, MediaType.TEXT_PLAIN);
+
+ ContainerResponse response = service(WebDAVMethods.SEARCH, getPathWS(), "", null, sql.getBytes());
+
+ // serialize response entity to string
+ SearchResultResponseEntity entity = (SearchResultResponseEntity)response.getEntity();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ entity.write(outputStream);
+ String resp = outputStream.toString();
+
+ System.out.println("=======Search response============");
+ System.out.println(resp);
+ System.out.println("=======Decoded file name==========");
+ System.out.println(decodedfileName);
+ System.out.println("==================================");
+
+ assertTrue(resp.contains(encodedfileName));
+ assertTrue(resp.contains(decodedfileName));
+
+ }
+
@Override
protected String getRepositoryName()
{
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1605/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1605/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1605/readme.txt 2011-04-21 11:43:46 UTC (rev 4266)
@@ -0,0 +1,83 @@
+Summary
+
+ Status: Can't access file containing special characters in file name via Webdav
+ CCP Issue: CCP-875, Product Jira Issue: JCR-1605.
+ Complexity: Low
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+
+ Can't open file containing special characters (e.g Japanese characters) in file name/path via WebDav in Nautilus. In case of cadaver, when using "ls" command, cadaver can't list such files.
+
+Fix description
+
+How is the problem fixed?
+
+ Set the selected tab after user add any permission to the wanted one.
+
+Patch information: JCR-1605.patch
+
+Tests to perform
+
+Reproduction test
+* Steps to reproduce:
+With WebDav, Ubuntu:
+
+1. Go to Sites Management/acme/documents, upload a file containing Japanese characters in file name (e.g あいうえお.txt)
+2. Open http://localhost:8080/ecmdemo/rest-ecmdemo/jcr/repository/collaboration in WebDav Nautilus
+3. Can't open あいうえお.txt file
+Similar problem occurs if opening a file containing accented characters (e.g é)
+
+With WebDav, Windows XP:
+
+1. With file containing Japanese characters in filename: can't open folder containing the file.
+2. With file containing accented characters (e.g é): can open folder containing the file but can't open the file.
+
+With cadaver:
+
+1. Upload a file containing Japanese characters in file name (e.g あいうえお.txt) in Site Explorer/collaboration
+2. Open http://localhost:8080/ecmdemo/rest-ecmdemo/jcr/repository/collaboration in cadaver
+3. Use "ls" command: the file isn't listed: not OK
+Similar problem occurs if opening a file containing accented characters (e.g é)
+
+Tests performed at DevLevel
+*
+
+Tests performed at QA/Support Level
+*
+
+Documentation changes
+
+Documentation changes:
+* No
+
+Configuration changes
+
+Configuration changes:
+* No
+
+Will previous configuration continue to work?
+* Yes
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+
+ Function or ClassName change
+
+Is there a performance risk/cost?
+*
+
+Validation (PM/Support/QA)
+
+PM Comment
+*
+
+Support Comment
+*
+
+QA Feedbacks
+*
+
15 years
exo-jcr SVN: r4265 - in jcr/branches/1.12.x: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache and 4 other directories.
by do-not-reply@jboss.org
Author: paristote
Date: 2011-04-21 07:38:57 -0400 (Thu, 21 Apr 2011)
New Revision: 4265
Added:
jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
jcr/branches/1.12.x/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/readme.txt
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/pom.xml
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java
Log:
JCR-1604
What is the problem to fix?
JCR addNode within a transaction causes javax.transaction.HeuristicMixedException (internally, org.exoplatform.services.transaction.TransactionException caused by org.jboss.cache.lock.TimeoutException) in the first access to the node
How is the problem fixed?
Perform loading data in cache outside the current transaction
Modified: jcr/branches/1.12.x/exo.jcr.component.core/pom.xml
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/pom.xml 2011-04-20 14:29:25 UTC (rev 4264)
+++ jcr/branches/1.12.x/exo.jcr.component.core/pom.xml 2011-04-21 11:38:57 UTC (rev 4265)
@@ -383,11 +383,26 @@
<name>emma.coverage.out.file</name>
<value>target/emma/coverage.ec</value>
</property>
- <!-- Uncomment the line below if you want to enable the statistics -->
- <!--property>
- <name>JDBCWorkspaceDataContainer.statistics.enabled</name>
- <value>true</value>
- </property-->
+ <!-- Uncomment the line below if you want to enable the statistics -->
+ <!--property>
+ <name>JDBCWorkspaceDataContainer.statistics.enabled</name>
+ <value>true</value>
+ </property-->
+ <!-- We add this system property due to some incompatibility between IPv6 and
+ some JVM of Linux distributions such as Ubuntu and Fedora-->
+ <property>
+ <name>java.net.preferIPv4Stack</name>
+ <value>true</value>
+ </property>
+ <!-- Avoid the firewall -->
+ <property>
+ <name>bind.address</name>
+ <value>127.0.0.1</value>
+ </property>
+ <property>
+ <name>jgroups.stack</name>
+ <value>udp</value>
+ </property>
</systemProperties>
<includes>
<include>org/exoplatform/services/jcr/api/**/Test*.java</include>
@@ -575,6 +590,21 @@
<name>JDBCWorkspaceDataContainer.statistics.enabled</name>
<value>true</value>
</property-->
+ <!-- We add this system property due to some incompatibility between IPv6 and
+ some JVM of Linux distributions such as Ubuntu and Fedora-->
+ <property>
+ <name>java.net.preferIPv4Stack</name>
+ <value>true</value>
+ </property>
+ <!-- Avoid the firewall -->
+ <property>
+ <name>bind.address</name>
+ <value>127.0.0.1</value>
+ </property>
+ <property>
+ <name>jgroups.stack</name>
+ <value>udp</value>
+ </property>
</systemProperties>
<includes>
<include>org/apache/jackrabbit/test/api/*Test.java</include>
@@ -647,6 +677,21 @@
<name>JDBCWorkspaceDataContainer.statistics.enabled</name>
<value>true</value>
</property-->
+ <!-- We add this system property due to some incompatibility between IPv6 and
+ some JVM of Linux distributions such as Ubuntu and Fedora-->
+ <property>
+ <name>java.net.preferIPv4Stack</name>
+ <value>true</value>
+ </property>
+ <!-- Avoid the firewall -->
+ <property>
+ <name>bind.address</name>
+ <value>127.0.0.1</value>
+ </property>
+ <property>
+ <name>jgroups.stack</name>
+ <value>udp</value>
+ </property>
</systemProperties>
<includes>
<!-- From default tests -->
@@ -725,6 +770,21 @@
<name>JDBCWorkspaceDataContainer.statistics.enabled</name>
<value>true</value>
</property-->
+ <!-- We add this system property due to some incompatibility between IPv6 and
+ some JVM of Linux distributions such as Ubuntu and Fedora-->
+ <property>
+ <name>java.net.preferIPv4Stack</name>
+ <value>true</value>
+ </property>
+ <!-- Avoid the firewall -->
+ <property>
+ <name>bind.address</name>
+ <value>127.0.0.1</value>
+ </property>
+ <property>
+ <name>jgroups.stack</name>
+ <value>udp</value>
+ </property>
</systemProperties>
<includes>
<include>**/**/reading_/Test*.java</include>
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-04-20 14:29:25 UTC (rev 4264)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-04-21 11:38:57 UTC (rev 4265)
@@ -40,6 +40,7 @@
import java.util.Map;
import java.util.Set;
+import javax.transaction.Status;
import javax.transaction.TransactionManager;
/**
@@ -64,6 +65,8 @@
private final boolean useExpiration;
private final long expirationTimeOut;
+
+ private final TransactionManager tm;
protected static final Log LOG =
ExoLogger.getLogger("org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.BufferedJBossCache");
@@ -71,6 +74,7 @@
public BufferedJBossCache(Cache<Serializable, Object> parentCache, boolean useExpiration, long expirationTimeOut)
{
super();
+ this.tm = ((CacheSPI<Serializable, Object>)parentCache).getTransactionManager();
this.parentCache = parentCache;
this.useExpiration = useExpiration;
this.expirationTimeOut = expirationTimeOut;
@@ -109,7 +113,53 @@
//log.info("After=" + changesContainer.toString());
for (ChangesContainer cacheChange : containers)
{
- cacheChange.apply();
+ boolean isTxCreated = false;
+ try
+ {
+ if (cacheChange.isTxRequired() && tm != null && tm.getStatus() == Status.STATUS_NO_TRANSACTION)
+ {
+ // No tx exists so we create a new tx
+ if (LOG.isTraceEnabled()) LOG.trace("No Tx is active we then create a new tx");
+ tm.begin();
+ isTxCreated = true;
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Could not create a new tx", e);
+ }
+ try
+ {
+ cacheChange.apply();
+ }
+ catch (RuntimeException e)
+ {
+ if (isTxCreated)
+ {
+ try
+ {
+ if (LOG.isTraceEnabled()) LOG.trace("An error occurs the tx will be rollbacked");
+ tm.rollback();
+ }
+ catch (Exception e1)
+ {
+ LOG.warn("Could not rollback the tx", e1);
+ }
+ }
+ throw e;
+ }
+ if (isTxCreated)
+ {
+ try
+ {
+ if (LOG.isTraceEnabled()) LOG.trace("The tx will be committed");
+ tm.commit();
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Could not commit the tx", e);
+ }
+ }
}
}
finally
@@ -118,6 +168,7 @@
changesContainer = null;
}
}
+
/**
* Tries to get buffer and if it is null throws an exception otherwise returns buffer.
@@ -471,6 +522,31 @@
return parentCache.get(fqn, key);
}
+ /**
+ * in case putIfAbsent is set to <code>true</code> this method will call cache.putIfAbsent(Fqn fqn, Serializable key, Object value)
+ * otherwise it will call cache.put(Fqn fqn, Serializable key, Object value)
+ */
+ protected Object put(Fqn fqn, Serializable key, Object value, boolean putIfAbsent)
+ {
+ if (putIfAbsent)
+ {
+ putIfAbsent(fqn, key, value);
+ return null;
+ }
+ return put(fqn, key, value);
+ }
+
+ /**
+ * This method will create and add a ChangesContainer that will put the value only if no value has been added
+ */
+ protected Object putIfAbsent(Fqn fqn, Serializable key, Object value)
+ {
+ CompressedChangesBuffer changesContainer = getChangesBufferSafe();
+ changesContainer.add(new PutIfAbsentKeyValueContainer(fqn, key, value, parentCache, changesContainer
+ .getHistoryIndex(), local.get(), useExpiration, expirationTimeOut));
+ return null;
+ }
+
public Object putInBuffer(Fqn fqn, Serializable key, Object value)
{
CompressedChangesBuffer changesContainer = getChangesBufferSafe();
@@ -758,6 +834,11 @@
}
public abstract void apply();
+
+ public boolean isTxRequired()
+ {
+ return false;
+ }
}
/**
@@ -789,6 +870,48 @@
}
/**
+ * PutIfAbsent container.
+ */
+ public static class PutIfAbsentKeyValueContainer extends ChangesContainer
+ {
+ private final Serializable key;
+
+ private final Object value;
+
+ public PutIfAbsentKeyValueContainer(Fqn fqn, Serializable key, Object value, Cache<Serializable, Object> cache,
+ int historicalIndex, boolean local, boolean useExpiration, long timeOut)
+ {
+ super(fqn, ChangesType.PUT_KEY, cache, historicalIndex, local, useExpiration, timeOut);
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public void apply()
+ {
+ cache.getInvocationContext().getOptionOverrides().setForceWriteLock(true);
+ if (cache.get(fqn, key) != null)
+ {
+ // skip
+ return;
+ }
+ if (useExpiration)
+ {
+ putExpiration(fqn);
+ }
+
+ setCacheLocalMode();
+ cache.put(fqn, key, value);
+ }
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return true;
+ }
+ }
+
+ /**
* Put container.
*/
public static class PutKeyValueContainer extends ChangesContainer
@@ -871,6 +994,12 @@
+ existingObject.getClass().getName());
}
}
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return true;
+ }
}
/**
@@ -913,6 +1042,12 @@
cache.put(fqn, key, newSet);
}
}
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return false;
+ }
}
/**
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-04-20 14:29:25 UTC (rev 4264)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-04-21 11:38:57 UTC (rev 4265)
@@ -60,6 +60,7 @@
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
+import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
/**
@@ -417,7 +418,7 @@
cache.setLocal(false);
if (!inTransaction)
{
- cache.commitTransaction();
+ dedicatedTxCommit();
}
}
}
@@ -556,23 +557,20 @@
cache.setLocal(true);
- // remove previous all
- cache.removeNode(makeRefFqn(identifier));
-
Set<Object> set = new HashSet<Object>();
for (PropertyData prop : refProperties)
{
putProperty(prop, ModifyChildOption.NOT_MODIFY);
set.add(prop.getIdentifier());
}
- cache.put(makeRefFqn(identifier), ITEM_LIST, set);
+ cache.putIfAbsent(makeRefFqn(identifier), ITEM_LIST, set);
}
finally
{
cache.setLocal(false);
if (!inTransaction)
{
- cache.commitTransaction();
+ dedicatedTxCommit();
}
}
}
@@ -592,8 +590,6 @@
}
cache.setLocal(true);
- // remove previous all (to be sure about consistency)
- cache.removeNode(makeChildListFqn(childNodesList, parent.getIdentifier()));
if (childs.size() > 0)
{
@@ -603,12 +599,13 @@
putNode(child, ModifyChildOption.NOT_MODIFY);
set.add(child.getIdentifier());
}
- cache.put(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST, set);
+ cache.putIfAbsent(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST, set);
}
else
{
// cache fact of empty childs list
- cache.put(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST, new HashSet<Object>());
+ cache.putIfAbsent(makeChildListFqn(childNodesList, parent.getIdentifier()), ITEM_LIST,
+ new HashSet<Object>());
}
}
finally
@@ -616,7 +613,7 @@
cache.setLocal(false);
if (!inTransaction)
{
- cache.commitTransaction();
+ dedicatedTxCommit();
}
}
}
@@ -634,8 +631,6 @@
cache.beginTransaction();
}
cache.setLocal(true);
- // remove previous all (to be sure about consistency)
- cache.removeNode(makeChildListFqn(childPropsList, parent.getIdentifier()));
if (childs.size() > 0)
{
// add all new
@@ -645,7 +640,7 @@
putProperty(child, ModifyChildOption.NOT_MODIFY);
set.add(child.getIdentifier());
}
- cache.put(makeChildListFqn(childPropsList, parent.getIdentifier()), ITEM_LIST, set);
+ cache.putIfAbsent(makeChildListFqn(childPropsList, parent.getIdentifier()), ITEM_LIST, set);
}
else
@@ -658,7 +653,7 @@
cache.setLocal(false);
if (!inTransaction)
{
- cache.commitTransaction();
+ dedicatedTxCommit();
}
}
}
@@ -669,17 +664,6 @@
public void addChildPropertiesList(NodeData parent, List<PropertyData> childProperties)
{
// TODO not implemented, will force read from DB
- // try
- // {
- // cache.beginTransaction();
- // cache.setLocal(true);
- //
- // }
- // finally
- // {
- // cache.setLocal(false);
- // cache.commitTransaction();
- // }
}
/**
@@ -945,18 +929,19 @@
if (node.getParentIdentifier() != null)
{
// add in CHILD_NODES
- cache.put(
- makeChildFqn(childNodes, node.getParentIdentifier(), node.getQPath().getEntries()[node.getQPath()
- .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
+ cache.put(makeChildFqn(childNodes, node.getParentIdentifier(), node.getQPath().getEntries()[node.getQPath()
+ .getEntries().length - 1]), ITEM_ID, node.getIdentifier(),
+ modifyListsOfChild == ModifyChildOption.NOT_MODIFY);
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
- cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()), ITEM_LIST,
- node.getIdentifier(), modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+ cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()), ITEM_LIST, node
+ .getIdentifier(), modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
}
}
// add in ITEMS
- return (ItemData)cache.put(makeItemFqn(node.getIdentifier()), ITEM_DATA, node);
+ return (ItemData)cache.put(makeItemFqn(node.getIdentifier()), ITEM_DATA, node,
+ modifyListsOfChild == ModifyChildOption.NOT_MODIFY);
}
protected ItemData putNodeInBufferedCache(NodeData node, ModifyChildOption modifyListsOfChild)
@@ -965,14 +950,13 @@
if (node.getParentIdentifier() != null)
{
// add in CHILD_NODES
- cache.put(
- makeChildFqn(childNodes, node.getParentIdentifier(), node.getQPath().getEntries()[node.getQPath()
- .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
+ cache.put(makeChildFqn(childNodes, node.getParentIdentifier(), node.getQPath().getEntries()[node.getQPath()
+ .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
- cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()), ITEM_LIST,
- node.getIdentifier(), modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+ cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()), ITEM_LIST, node
+ .getIdentifier(), modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
}
}
// add in ITEMS
@@ -988,9 +972,8 @@
protected PropertyData putProperty(PropertyData prop, ModifyChildOption modifyListsOfChild)
{
// add in CHILD_PROPS
- cache.put(
- makeChildFqn(childProps, prop.getParentIdentifier(),
- prop.getQPath().getEntries()[prop.getQPath().getEntries().length - 1]), ITEM_ID, prop.getIdentifier());
+ cache.put(makeChildFqn(childProps, prop.getParentIdentifier(), prop.getQPath().getEntries()[prop.getQPath()
+ .getEntries().length - 1]), ITEM_ID, prop.getIdentifier(), modifyListsOfChild == ModifyChildOption.NOT_MODIFY);
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
@@ -1025,7 +1008,8 @@
}
// add in ITEMS
- return (PropertyData)cache.put(makeItemFqn(prop.getIdentifier()), ITEM_DATA, prop);
+ return (PropertyData)cache.put(makeItemFqn(prop.getIdentifier()), ITEM_DATA, prop,
+ modifyListsOfChild == ModifyChildOption.NOT_MODIFY);
}
protected void removeItem(ItemData item)
@@ -1041,8 +1025,8 @@
.getQPath().getEntries().length - 1]));
// remove from CHILD_NODES_LIST of parent
- cache.removeFromList(makeChildListFqn(childNodesList, item.getParentIdentifier()), ITEM_LIST,
- item.getIdentifier());
+ cache.removeFromList(makeChildListFqn(childNodesList, item.getParentIdentifier()), ITEM_LIST, item
+ .getIdentifier());
// remove from CHILD_NODES as parent
cache.removeNode(makeChildListFqn(childNodes, item.getIdentifier()));
@@ -1066,8 +1050,8 @@
.getQPath().getEntries().length - 1]));
// remove from CHILD_PROPS_LIST
- cache.removeFromList(makeChildListFqn(childPropsList, item.getParentIdentifier()), ITEM_LIST,
- item.getIdentifier());
+ cache.removeFromList(makeChildListFqn(childPropsList, item.getParentIdentifier()), ITEM_LIST, item
+ .getIdentifier());
}
// remove from ITEMS
cache.removeNode(makeItemFqn(item.getIdentifier()));
@@ -1096,10 +1080,10 @@
}
/**
- * Update Node hierachy in case of same-name siblings reorder.
- * Assumes the new (updated) nodes already putted in the cache. Previous name of updated nodes will be calculated
- * and that node will be deleted (if has same id as the new node). Childs paths will be updated to a new node path.
- *
+ * Update Node hierarchy in case of same-name siblings reorder.
+ * Assumes the new (updated) nodes already put in the cache. Previous name of updated nodes will be calculated
+ * and that node will be deleted (if has same id as the new node). Children paths will be updated to a new node path. *
+ *
* @param node NodeData
* @param prevNode NodeData
*/
@@ -1205,9 +1189,9 @@
NodeData prevNode = (NodeData)data;
TransientNodeData newNode =
- new TransientNodeData(newPath, prevNode.getIdentifier(), prevNode.getPersistedVersion(),
- prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(),
- prevNode.getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); // TODO check ACL
+ new TransientNodeData(newPath, prevNode.getIdentifier(), prevNode.getPersistedVersion(), prevNode
+ .getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(), prevNode
+ .getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); // TODO check ACL
// update this node
cache.put(makeItemFqn(newNode.getIdentifier()), ITEM_DATA, newNode);
}
@@ -1225,8 +1209,8 @@
}
TransientPropertyData newProp =
- new TransientPropertyData(newPath, prevProp.getIdentifier(), prevProp.getPersistedVersion(),
- prevProp.getType(), prevProp.getParentIdentifier(), prevProp.isMultiValued(), prevProp.getValues());
+ new TransientPropertyData(newPath, prevProp.getIdentifier(), prevProp.getPersistedVersion(), prevProp
+ .getType(), prevProp.getParentIdentifier(), prevProp.isMultiValued(), prevProp.getValues());
cache.put(makeItemFqn(newProp.getIdentifier()), ITEM_DATA, newProp);
}
}
@@ -1260,8 +1244,8 @@
QPath
.makeChildPath(rootPath, prevProp.getQPath().getEntries()[prevProp.getQPath().getEntries().length - 1]);
TransientPropertyData newProp =
- new TransientPropertyData(newPath, prevProp.getIdentifier(), prevProp.getPersistedVersion(),
- prevProp.getType(), prevProp.getParentIdentifier(), prevProp.isMultiValued(), prevProp.getValues());
+ new TransientPropertyData(newPath, prevProp.getIdentifier(), prevProp.getPersistedVersion(), prevProp
+ .getType(), prevProp.getParentIdentifier(), prevProp.isMultiValued(), prevProp.getValues());
cache.put(makeItemFqn(newProp.getIdentifier()), ITEM_DATA, newProp);
}
@@ -1274,9 +1258,9 @@
QPath
.makeChildPath(rootPath, prevNode.getQPath().getEntries()[prevNode.getQPath().getEntries().length - 1]);
TransientNodeData newNode =
- new TransientNodeData(newPath, prevNode.getIdentifier(), prevNode.getPersistedVersion(),
- prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(),
- prevNode.getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); // TODO check ACL
+ new TransientNodeData(newPath, prevNode.getIdentifier(), prevNode.getPersistedVersion(), prevNode
+ .getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(), prevNode
+ .getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); // TODO check ACL
// update this node
cache.put(makeItemFqn(newNode.getIdentifier()), ITEM_DATA, newNode);
// update childs recursive
@@ -1292,22 +1276,22 @@
*/
protected void updateChildsACL(final String parentId, final AccessControlList acl)
{
- for (Iterator<NodeData> iter = new ChildNodesIterator<NodeData>(parentId); iter.hasNext();)
+ loop : for (Iterator<NodeData> iter = new ChildNodesIterator<NodeData>(parentId); iter.hasNext();)
{
NodeData prevNode = iter.next();
- // is ACL changes on this node (i.e. ACL inheritance brokes)
+ // is ACL changes on this node (i.e. ACL inheritance broken)
for (InternalQName mixin : prevNode.getMixinTypeNames())
{
if (mixin.equals(Constants.EXO_PRIVILEGEABLE) || mixin.equals(Constants.EXO_OWNEABLE))
{
- continue;
+ continue loop;
}
}
// recreate with new path for child Nodes only
TransientNodeData newNode =
new TransientNodeData(prevNode.getQPath(), prevNode.getIdentifier(), prevNode.getPersistedVersion(),
- prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(),
- prevNode.getParentIdentifier(), acl);
+ prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(), prevNode.getOrderNumber(), prevNode
+ .getParentIdentifier(), acl);
// update this node
cache.put(makeItemFqn(newNode.getIdentifier()), ITEM_DATA, newNode);
// update childs recursive
@@ -1347,4 +1331,44 @@
NOT_MODIFY, MODIFY, FORCE_MODIFY
}
+ /**
+ * Allows to commit the cache changes in a dedicated XA Tx in order to avoid potential
+ * deadlocks
+ */
+ private void dedicatedTxCommit()
+ {
+ // Ensure that the commit is done in a dedicated tx to avoid deadlock due
+ // to global XA Tx
+ TransactionManager tm = getTransactionManager();
+ Transaction tx = null;
+ try
+ {
+ if (tm != null)
+ {
+ try
+ {
+ tx = tm.suspend();
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot suspend the current transaction", e);
+ }
+ }
+ cache.commitTransaction();
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ try
+ {
+ tm.resume(tx);
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot resume the current transaction", e);
+ }
+ }
+ }
+ }
}
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java 2011-04-20 14:29:25 UTC (rev 4264)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java 2011-04-21 11:38:57 UTC (rev 4265)
@@ -71,6 +71,60 @@
return ntFile;
}
+ public void testSpecialCharacters() throws Exception
+ {
+ Node queryNode = testNode.addNode("node-testSpecialCharacters");
+ String[] specialChar = {"a", "+", "-", "&&", "||", "!", "(", ")", "{", "}", "[", "]", "^","\"", "~", "*", "?", ":", "\\", "&", "$", "@", "%", "|", "(1+1):2", "\\(1\\+1\\)\\:2"};
+ StringBuilder buffer = new StringBuilder();
+ for (String sChar : specialChar)
+ {
+ buffer.append(' ').append(sChar);
+ }
+ queryNode.setProperty("full-content", buffer.toString());
+ session.save();
+ for (String sChar : specialChar)
+ {
+ QueryManager manager = session.getWorkspace().getQueryManager();
+ String sqlQuery = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testNode.getPath() + "/%' and contains(*, '" + sChar + "')";
+ Query query = manager.createQuery(sqlQuery, Query.SQL);
+
+ QueryResult queryResult;
+ try
+ {
+ queryResult = query.execute();
+ assertNotNull(queryResult.getNodes());
+ if (queryResult.getNodes().hasNext())
+ System.out.println("It works well with '" + sChar + "' path =" + queryResult.getNodes().nextNode().getPath());
+ else
+ System.err.println("No results could be found for '" + sChar + "'");
+ }
+ catch (Exception e)
+ {
+ System.err.println("It fails with '" + sChar + "' let's escape it");
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < sChar.length(); i++)
+ {
+ sb.append('\\').append(sChar.charAt(i));
+ }
+ sChar = sb.toString();
+ sqlQuery = "SELECT * FROM nt:base WHERE jcr:path LIKE '" + testNode.getPath() + "/%' and contains(*, '" + sChar + "')";
+ query = manager.createQuery(sqlQuery, Query.SQL);
+ try
+ {
+ queryResult = query.execute();
+ assertNotNull(queryResult.getNodes());
+ if (queryResult.getNodes().hasNext())
+ System.out.println("It works well with '" + sChar + "' path =" + queryResult.getNodes().nextNode().getPath());
+ else
+ System.err.println("No results could be found for '" + sChar + "'");
+ }
+ catch (Exception e1)
+ {
+ System.out.println("It fails also with '" + sChar + "'");
+ }
+ }
+ }
+ }
public void testAllofNodeType() throws Exception
{
Added: jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java (rev 0)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java 2011-04-21 11:38:57 UTC (rev 4265)
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2011 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache;
+
+import org.exoplatform.container.configuration.ConfigurationManagerImpl;
+import org.exoplatform.services.jcr.JcrImplBaseTest;
+import org.exoplatform.services.jcr.config.CacheEntry;
+import org.exoplatform.services.jcr.config.SimpleParameterEntry;
+import org.exoplatform.services.jcr.config.WorkspaceEntry;
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
+import org.exoplatform.services.jcr.dataflow.persistent.PersistedNodeData;
+import org.exoplatform.services.jcr.dataflow.persistent.PersistedPropertyData;
+import org.exoplatform.services.jcr.datamodel.InternalQName;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.ItemType;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPath;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.ByteArrayPersistedValueData;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager;
+import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
+import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase;
+import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
+import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
+import org.exoplatform.services.transaction.TransactionService;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+/**
+ * @author <a href="mailto:nicolas.filotto@exoplatform.com">Nicolas Filotto</a>
+ * @version $Id$
+ */
+public class TestJBossCacheWorkspaceStorageCacheInClusterMode extends JcrImplBaseTest
+{
+
+ public JBossCacheWorkspaceStorageCache getCacheImpl() throws Exception
+ {
+ TransactionService transactionService =
+ (TransactionService)container.getComponentInstanceOfType(TransactionService.class);
+
+ ArrayList<SimpleParameterEntry> list = new ArrayList<SimpleParameterEntry>();
+ list.add(new SimpleParameterEntry(JBossCacheWorkspaceStorageCache.JBOSSCACHE_CONFIG,
+ "jar:/conf/standalone/cluster/test-jbosscache-data-no-mux.xml"));
+ list.add(new SimpleParameterEntry("jbosscache-cluster-name", "TestJBossCacheWorkspaceStorageCacheInClusterMode"));
+
+ CacheEntry entry = new CacheEntry(list);
+ WorkspaceEntry workspaceEntry = new WorkspaceEntry();
+ workspaceEntry.setCache(entry);
+ return new JBossCacheWorkspaceStorageCache(workspaceEntry,
+ transactionService == null ? null : transactionService, new ConfigurationManagerImpl());
+ }
+
+ public void testRaceConditions() throws Exception
+ {
+ JBossCacheWorkspaceStorageCache cache1 = null, cache2 = null;
+ try
+ {
+ MyWorkspaceStorageConnection con = new MyWorkspaceStorageConnection();
+ WorkspaceDataContainer wdc = new MyWorkspaceDataContainer(con);
+ CacheableWorkspaceDataManager cwdmNode1 =
+ new CacheableWorkspaceDataManager(wdc, cache1 = getCacheImpl(), new SystemDataContainerHolder(wdc));
+ CacheableWorkspaceDataManager cwdmNode2 =
+ new CacheableWorkspaceDataManager(wdc, cache2 = getCacheImpl(), new SystemDataContainerHolder(wdc));
+ NodeData parentNode = new PersistedNodeData("parent-id", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ // Test getChildNodesData
+ Action readAction = new Action(cwdmNode2)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ cwdm.getChildNodesData(parentNode);
+ }
+ };
+ Action writeAction = new Action(cwdmNode1)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ PlainChangesLog chlog = new PlainChangesLogImpl();
+ cwdm.getChildNodesData(parentNode);
+ chlog.add(ItemState.createAddedState(new PersistedNodeData("id-node" + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), new InternalQName(null, "node")), parentNode.getIdentifier(), 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null)));
+ cwdm.save(chlog);
+ }
+ };
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getChildNodesData(parentNode));
+ assertEquals(2, cwdmNode1.getChildNodesData(parentNode).size());
+ assertNotNull(cwdmNode2.getChildNodesData(parentNode));
+ assertEquals(2, cwdmNode2.getChildNodesData(parentNode).size());
+ parentNode = new PersistedNodeData("parent-id2", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node2")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getChildNodesData(parentNode));
+ assertEquals(2, cwdmNode1.getChildNodesData(parentNode).size());
+ assertNotNull(cwdmNode2.getChildNodesData(parentNode));
+ assertEquals(2, cwdmNode2.getChildNodesData(parentNode).size());
+ // Test getChildPropertiesData
+ readAction = new Action(cwdmNode2)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ cwdm.getChildPropertiesData(parentNode);
+ }
+ };
+ writeAction = new Action(cwdmNode1)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ PlainChangesLog chlog = new PlainChangesLogImpl();
+ cwdm.getChildPropertiesData(parentNode);
+ chlog.add(ItemState.createAddedState(new PersistedPropertyData("id-property" + parentNode.getIdentifier(), QPath.makeChildPath(
+ parentNode.getQPath(), new InternalQName(null, "property")), parentNode.getIdentifier(), 0,
+ PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, "some data".getBytes("UTF-8"))))));
+ cwdm.save(chlog);
+ }
+ };
+ parentNode = new PersistedNodeData("parent-id3", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node3")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getChildPropertiesData(parentNode));
+ assertEquals(2, cwdmNode1.getChildPropertiesData(parentNode).size());
+ assertNotNull(cwdmNode2.getChildPropertiesData(parentNode));
+ assertEquals(2, cwdmNode2.getChildPropertiesData(parentNode).size());
+ parentNode = new PersistedNodeData("parent-id4", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node4")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getChildPropertiesData(parentNode));
+ assertEquals(2, cwdmNode1.getChildPropertiesData(parentNode).size());
+ assertNotNull(cwdmNode2.getChildPropertiesData(parentNode));
+ assertEquals(2, cwdmNode2.getChildPropertiesData(parentNode).size());
+ // Test getReferencesData
+ readAction = new Action(cwdmNode2)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ cwdm.getReferencesData(parentNode.getIdentifier(), false);
+ }
+ };
+ writeAction = new Action(cwdmNode1)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ PlainChangesLog chlog = new PlainChangesLogImpl();
+ cwdm.getReferencesData(parentNode.getIdentifier(), false);
+ chlog.add(ItemState.createAddedState(new PersistedPropertyData("id-reference" + parentNode.getIdentifier(), QPath.makeChildPath(
+ parentNode.getQPath(), new InternalQName(null, "reference")), parentNode.getIdentifier(), 0,
+ PropertyType.REFERENCE, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, parentNode.getIdentifier().getBytes("UTF-8"))))));
+ cwdm.save(chlog);
+ }
+ };
+ parentNode = new PersistedNodeData("parent-id5", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node5")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getReferencesData(parentNode.getIdentifier(), false));
+ assertEquals(2, cwdmNode1.getReferencesData(parentNode.getIdentifier(), false).size());
+ assertNotNull(cwdmNode2.getReferencesData(parentNode.getIdentifier(), false));
+ assertEquals(2, cwdmNode2.getReferencesData(parentNode.getIdentifier(), false).size());
+ parentNode = new PersistedNodeData("parent-id6", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node6")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getReferencesData(parentNode.getIdentifier(), false));
+ assertEquals(2, cwdmNode1.getReferencesData(parentNode.getIdentifier(), false).size());
+ assertNotNull(cwdmNode2.getReferencesData(parentNode.getIdentifier(), false));
+ assertEquals(2, cwdmNode2.getReferencesData(parentNode.getIdentifier(), false).size());
+
+ // Test getItemData by Id
+ readAction = new Action(cwdmNode2)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ cwdm.getItemData(parentNode.getIdentifier());
+ }
+ };
+ writeAction = new Action(cwdmNode1)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ PlainChangesLog chlog = new PlainChangesLogImpl();
+ cwdm.getItemData(parentNode.getIdentifier());
+ chlog.add(ItemState.createUpdatedState(new PersistedNodeData(parentNode.getIdentifier(), parentNode.getQPath(), Constants.ROOT_UUID, 2, 1,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null)));
+ cwdm.save(chlog);
+ }
+ };
+ parentNode = new PersistedNodeData("parent-id7", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node7")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getItemData(parentNode.getIdentifier()));
+ assertEquals(2, cwdmNode1.getItemData(parentNode.getIdentifier()).getPersistedVersion());
+ assertNotNull(cwdmNode2.getItemData(parentNode.getIdentifier()));
+ assertEquals(2, cwdmNode2.getItemData(parentNode.getIdentifier()).getPersistedVersion());
+ parentNode = new PersistedNodeData("parent-id8", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node8")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getItemData(parentNode.getIdentifier()));
+ assertEquals(2, cwdmNode1.getItemData(parentNode.getIdentifier()).getPersistedVersion());
+ assertNotNull(cwdmNode2.getItemData(parentNode.getIdentifier()));
+ assertEquals(2, cwdmNode2.getItemData(parentNode.getIdentifier()).getPersistedVersion());
+
+ // Test getItemData by Path
+ final QPathEntry qpe = new QPathEntry(null, "my-property", 1);
+ readAction = new Action(cwdmNode2)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ cwdm.getItemData(parentNode, qpe, ItemType.PROPERTY);
+ }
+ };
+ writeAction = new Action(cwdmNode1)
+ {
+ public void execute(NodeData parentNode) throws Exception
+ {
+ PlainChangesLog chlog = new PlainChangesLogImpl();
+ cwdm.getItemData(parentNode, qpe, ItemType.PROPERTY);
+ chlog.add(ItemState.createUpdatedState(new PersistedPropertyData("property-by-path"
+ + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), qpe), parentNode
+ .getIdentifier(), 2, PropertyType.STRING, false, Arrays
+ .asList((ValueData)new ByteArrayPersistedValueData(0, "some new data".getBytes("UTF-8"))))));
+ cwdm.save(chlog);
+ }
+ };
+ parentNode = new PersistedNodeData("parent-id9", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node9")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY));
+ assertEquals(2, cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
+ assertNotNull(cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY));
+ assertEquals(2, cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
+ parentNode = new PersistedNodeData("parent-id10", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node10")), Constants.ROOT_UUID, 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
+ assertNotNull(cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY));
+ assertEquals(2, cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
+ assertNotNull(cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY));
+ assertEquals(2, cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
+ }
+ finally
+ {
+ if (cache1 != null)
+ {
+ try
+ {
+ cache1.cache.stop();
+ }
+ catch (Exception e)
+ {
+ // ignore me
+ }
+ }
+ if (cache2 != null)
+ {
+ try
+ {
+ cache2.cache.stop();
+ }
+ catch (Exception e)
+ {
+ // ignore me
+ }
+ }
+ }
+ }
+
+ /**
+ * @param con
+ * @param cwdm
+ * @param mode
+ * @param idNode
+ * @throws InterruptedException
+ */
+ private void executeConcurrentReadNWrite(final MyWorkspaceStorageConnection con, final Action readAction,
+ final Action writeAction, final Mode mode, final NodeData parentNode) throws InterruptedException
+ {
+ final CountDownLatch goSignal = con.initCountDownLatch();
+ con.setParentNode(parentNode);
+ final AtomicReference<Exception> ex = new AtomicReference<Exception>();
+ final CountDownLatch startSignal = new CountDownLatch(1);
+ final CountDownLatch doneSignal = new CountDownLatch(2);
+ Thread writer = new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ startSignal.await();
+ con.wait.set(mode != Mode.WRITE_FIRST);
+ writeAction.execute(parentNode);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ ex.set(e);
+ }
+ finally
+ {
+ if (mode == Mode.WRITE_FIRST) goSignal.countDown();
+ doneSignal.countDown();
+ }
+ }
+ };
+ writer.start();
+ Thread reader = new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ startSignal.await();
+ con.wait.set(mode != Mode.READ_FIRST);
+ readAction.execute(parentNode);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ ex.set(e);
+ }
+ finally
+ {
+ if (mode == Mode.READ_FIRST) goSignal.countDown();
+ doneSignal.countDown();
+ }
+ }
+ };
+ reader.start();
+ startSignal.countDown();
+ doneSignal.await();
+ assertNull(ex.get());
+ }
+
+ private abstract class Action
+ {
+
+ protected final CacheableWorkspaceDataManager cwdm;
+ public Action(CacheableWorkspaceDataManager cwdm)
+ {
+ this.cwdm = cwdm;
+ }
+ protected abstract void execute(NodeData parentNode) throws Exception;
+ }
+ private static enum Mode
+ {
+ READ_FIRST, WRITE_FIRST;
+ }
+ private static class MyWorkspaceStorageConnection implements WorkspaceStorageConnection
+ {
+ public ThreadLocal<Boolean> wait = new ThreadLocal<Boolean>();
+ private NodeData parentNode;
+ private CountDownLatch goSignal;
+
+ public CountDownLatch initCountDownLatch()
+ {
+ return this.goSignal = new CountDownLatch(1);
+ }
+
+ public void setParentNode(NodeData parentNode)
+ {
+ this.parentNode = parentNode;
+ }
+
+ public void add(NodeData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+
+ public void add(PropertyData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+
+ public void close() throws IllegalStateException, RepositoryException
+ {
+ }
+
+ public void commit() throws IllegalStateException, RepositoryException
+ {
+ if (wait.get() != null && wait.get())
+ {
+ try
+ {
+ goSignal.await();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ public void delete(NodeData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+
+ public void delete(PropertyData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+
+ public int getChildNodesCount(NodeData parent) throws RepositoryException
+ {
+ return -1;
+ }
+
+ public List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException, IllegalStateException
+ {
+ if (wait.get() != null && wait.get())
+ {
+ try
+ {
+ goSignal.await();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ List<NodeData> children = new ArrayList<NodeData>();
+ children.add(new PersistedNodeData("id-node2" + parentNode.getIdentifier(), QPath.makeChildPath(parent.getQPath(), new InternalQName(null, "node2")), parent.getIdentifier(), 1, 0,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null));
+ return children;
+ }
+
+ public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException,
+ IllegalStateException
+ {
+ if (wait.get() != null && wait.get())
+ {
+ try
+ {
+ goSignal.await();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ List<PropertyData> children = new ArrayList<PropertyData>();
+ try
+ {
+ children.add(new PersistedPropertyData("id-property2" + parentNode.getIdentifier(), QPath.makeChildPath(
+ parentNode.getQPath(), new InternalQName(null, "property2")), parentNode.getIdentifier(), 0,
+ PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, "some data".getBytes("UTF-8")))));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ }
+ return children;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ItemData getItemData(NodeData parentData, QPathEntry name) throws RepositoryException,
+ IllegalStateException
+ {
+ return getItemData(parentData, name, ItemType.UNKNOWN);
+ }
+
+ public ItemData getItemData(NodeData parentData, QPathEntry name, ItemType itemType) throws RepositoryException,
+ IllegalStateException
+ {
+ if (wait.get() != null && wait.get())
+ {
+ try
+ {
+ goSignal.await();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ if (itemType == ItemType.NODE)
+ {
+ return new PersistedNodeData("my-node" + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), name), Constants.ROOT_UUID, 1, 1,
+ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
+ }
+ try
+ {
+ return new PersistedPropertyData("property-by-path"
+ + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), name), parentNode
+ .getIdentifier(), 1, PropertyType.STRING, false, Arrays
+ .asList((ValueData)new ByteArrayPersistedValueData(0, "some new data".getBytes("UTF-8"))));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public ItemData getItemData(String identifier) throws RepositoryException, IllegalStateException
+ {
+ if (wait.get() != null && wait.get())
+ {
+ try
+ {
+ goSignal.await();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ return parentNode;
+ }
+
+ public List<PropertyData> getReferencesData(String nodeIdentifier) throws RepositoryException,
+ IllegalStateException, UnsupportedOperationException
+ {
+ if (wait.get() != null && wait.get())
+ {
+ try
+ {
+ goSignal.await();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ List<PropertyData> children = new ArrayList<PropertyData>();
+ try
+ {
+ children.add(new PersistedPropertyData("id-reference2" + parentNode.getIdentifier(), QPath.makeChildPath(
+ parentNode.getQPath(), new InternalQName(null, "reference2")), parentNode.getIdentifier(), 0,
+ PropertyType.REFERENCE, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, parentNode.getIdentifier().getBytes("UTF-8")))));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ }
+ return children;
+ }
+
+ public boolean isOpened()
+ {
+ return true;
+ }
+
+ public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException,
+ IllegalStateException
+ {
+ return null;
+ }
+
+ public void rename(NodeData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+
+ public void rollback() throws IllegalStateException, RepositoryException
+ {
+ }
+
+ public void update(NodeData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+
+ public void update(PropertyData data) throws RepositoryException, UnsupportedOperationException,
+ InvalidItemStateException, IllegalStateException
+ {
+ }
+ };
+
+ private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
+ {
+
+ private WorkspaceStorageConnection con;
+
+ public MyWorkspaceDataContainer(WorkspaceStorageConnection con)
+ {
+ this.con = con;
+ }
+
+ public boolean isCheckSNSNewConnection()
+ {
+ return false;
+ }
+
+ public boolean isSame(WorkspaceDataContainer another)
+ {
+ return false;
+ }
+
+ public WorkspaceStorageConnection openConnection() throws RepositoryException
+ {
+ return con;
+ }
+
+ public WorkspaceStorageConnection openConnection(boolean readOnly) throws RepositoryException
+ {
+ return con;
+ }
+
+ public WorkspaceStorageConnection reuseConnection(WorkspaceStorageConnection original) throws RepositoryException
+ {
+ return con;
+ }
+
+ public String getInfo()
+ {
+ return "MyWorkspaceDataContainer";
+ }
+
+ public String getName()
+ {
+ return "MyWorkspaceDataContainer";
+ }
+
+ public String getStorageVersion()
+ {
+ return "0";
+ }
+ };
+}
\ No newline at end of file
Added: jcr/branches/1.12.x/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml (rev 0)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml 2011-04-21 11:38:57 UTC (rev 4265)
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1">
+
+ <locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
+ lockAcquisitionTimeout="20000" />
+ <transaction syncRollbackPhase="true" syncCommitPhase="true" />
+
+ <clustering mode="replication" clusterName="${jbosscache-cluster-name}">
+ <stateRetrieval timeout="20000" fetchInMemoryState="false" />
+ <sync replTimeout="20000"/>
+ <jgroupsConfig configFile="udp.xml">
+ </jgroupsConfig>
+ </clustering>
+
+ <!-- Eviction configuration -->
+ <eviction wakeUpInterval="5000">
+ <default algorithmClass="org.jboss.cache.eviction.ExpirationAlgorithm"
+ actionPolicyClass="org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.ParentNodeEvictionActionPolicy"
+ eventQueueSize="1000000">
+ <property name="maxNodes" value="1000000" />
+ <property name="warnNoExpirationKey" value="false" />
+ </default>
+ </eviction>
+</jbosscache>
\ No newline at end of file
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/readme.txt
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/readme.txt (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/readme.txt 2011-04-21 11:38:57 UTC (rev 4265)
@@ -0,0 +1,74 @@
+Summary
+
+ Status: JCR addNode within a transaction causes javax.transaction.HeuristicMixedException in the first access to the node
+ CCP Issue: CCP-870, Product Jira Issue: JCR-1604.
+ Complexity: High
+
+The Proposal
+Problem description
+
+What is the problem to fix?
+
+ JCR addNode within a transaction causes javax.transaction.HeuristicMixedException (internally, org.exoplatform.services.transaction.TransactionException caused by org.jboss.cache.lock.TimeoutException) in the first access to the node
+
+Fix description
+
+How is the problem fixed?
+
+ Perform loading data in cache outside the current transaction
+
+Patch information: JCR-1604.patch
+
+Tests to perform
+
+Reproduction test
+* Steps to reproduce:
+
+ Copy test-jcr.bsh to $JBOSS_HOME/server/$PROFILE/deploy
+ Start EPP (during the startup sequence, test-jcr.bsh will be executed once first=true)
+ Edit the test-jcr.bsh to set first=false and save (Then redeploy will be triggered and test-jcr.bsh will be executed again first=false)
+ Reboot EPP (during the startup sequence, test-jcr.bsh will be executed first=false)
+
+Tests performed at DevLevel
+* Do the same tasks like reproduction test => the scroll bar appears
+
+Tests performed at QA/Support Level
+*
+
+
+Documentation changes
+
+Documentation changes:
+ * No
+
+
+Configuration changes
+
+Configuration changes:
+ * No
+
+Will previous configuration continue to work?
+*Yes
+
+
+Risks and impacts
+
+Can this bug fix have any side effects on current client projects?
+
+ No
+
+Is there a performance risk/cost?
+ * No
+
+Validation (PM/Support/QA)
+
+PM Comment
+
+*Patch approved by the PM
+
+Support Comment
+*Support patch review: patch tested and approved
+
+QA Feedbacks
+*
+
15 years
exo-jcr SVN: r4263 - in jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules: core and 1 other directory.
by do-not-reply@jboss.org
Author: dkuleshov
Date: 2011-04-20 09:37:34 -0400 (Wed, 20 Apr 2011)
New Revision: 4263
Added:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core/digest-auth.xml
Modified:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core.xml
Log:
EXOJCR-1019: added digest auth chapter
Added: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core/digest-auth.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core/digest-auth.xml (rev 0)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core/digest-auth.xml 2011-04-20 13:37:34 UTC (rev 4263)
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter>
+ <title>Digest Authentication</title>
+
+ <section>
+ <title>Overview</title>
+
+ <para>Digest access authentication is one of the agreed methods a web
+ server can use to negotiate credentials with a web user's browser. It uses
+ encryption to send the password over the network which is safer than the
+ Basic access authentication that sends plaintext.</para>
+
+ <para>Technically digest authentication is an application of MD5
+ cryptographic hashing with usage of nonce values to discourage
+ cryptanalysis. It uses the HTTP protocol.</para>
+ </section>
+
+ <section>
+ <title>Server configuration</title>
+
+ <para>To configure you server to use DIGEST authentication we need to edit
+ serverside JAAS module implementation configuration file.</para>
+
+ <section>
+ <title>Tomcat Server configuration</title>
+
+ <para>Edit config file located here:
+ exo-tomcat/webapps/rest.war/WEB-INF/web.xml</para>
+
+ <para>Replace</para>
+
+ <para><programlisting><login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>eXo REST services</realm-name>
+</login-config></programlisting>for</para>
+
+ <para><programlisting><login-config>
+ <auth-method>DIGEST</auth-method>
+ <realm-name>eXo REST services</realm-name>
+</login-config></programlisting>More information about tomcat
+ configuration can be found at <ulink
+ url="http://tomcat.apache.org/tomcat-6.0-doc/config/realm.html">Apache
+ Tomcat Configuration Reference</ulink>.</para>
+ </section>
+
+ <section>
+ <title>Jetty server configuration</title>
+
+ <para>Edit config file located here:
+ exo-jetty/webapps/rest.war/WEB-INF/web.xml</para>
+
+ <para>Replace</para>
+
+ <para><programlisting><login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>eXo REST services</realm-name>
+</login-config></programlisting>for</para>
+
+ <para><programlisting><login-config>
+ <auth-method>DIGEST</auth-method>
+ <realm-name>eXo REST services</realm-name>
+</login-config></programlisting></para>
+ </section>
+
+ <section>
+ <title>JBoss server configuration</title>
+
+ <para>Edit config file located here:
+ exo-jboss/server/default/deploy/exo.jcr.ear.ear/rest.war/WEB-INF/web.xml</para>
+
+ <para>Replace</para>
+
+ <para><programlisting><login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>eXo REST services</realm-name>
+</login-config></programlisting>for</para>
+
+ <para><programlisting><login-config>
+ <auth-method>DIGEST</auth-method>
+ <realm-name>eXo REST services</realm-name>
+</login-confi</programlisting></para>
+
+ <para>You also need to edit login configuration file located here:
+ exo-jboss/server/default/conf/login-config.xml</para>
+
+ <para><programlisting><application-policy name="exo-domain">
+ <authentication>
+ <login-module code="org.exoplatform.services.security.j2ee.JbossLoginModule"
+ flag="required">
+ <module-option name="usersProperties">props/jmx-console-users.properties</module-option>
+ <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option>
+ <module-option name="hashAlgorithm">MD5</module-option>
+ <module-option name="hashEncoding">rfc2617</module-option>
+ <module-option name="hashUserPassword">false</module-option>
+ <module-option name="hashStorePassword">true</module-option>
+ <module-option name="passwordIsA1Hash">true</module-option>
+ <module-option name="storeDigestCallback">
+ org.jboss.security.auth.spi.RFC2617Digest
+ </module-option>
+ </login-module>
+ </authentication>
+</application-policy></programlisting>You probably should define
+ users.properties and role.properties according to your own needs.</para>
+
+ <para>More information about jboss server Digest authentication
+ configuration can be found at <ulink
+ url="http://docs.jboss.org/jbossas/guides/webguide/r2/en/html/ch05.html">JBoss
+ quide chapter</ulink>.</para>
+ </section>
+ </section>
+
+ <section>
+ <title>OrganizationService implementation requirements</title>
+
+ <para>To make your own
+ <literal>org.exoplatform.services.organization.OrganizationService</literal>
+ implementation able to use DIGEST authentication you need to make your
+ UserHandler implementation also implement
+ <literal>org.exoplatform.services.organization.DigestAuthenticator</literal>
+ interface which provide more flexible authenticate method. As it is called
+ from
+ <literal>org.exoplatform.services.organization.auth.OrganizationAuthenticatorImpl</literal>
+ it receive a
+ <literal>org.exoplatform.services.security.Credential</literal> instances,
+ you can get more information from
+ <literal>org.exoplatform.services.security.PasswordCredential.getPasswordContext()</literal>.
+ It can be used to calculate md5 digest of original password to compare it
+ with recieved from clientside.</para>
+ </section>
+</chapter>
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core.xml 2011-04-20 13:28:47 UTC (rev 4262)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/core.xml 2011-04-20 13:37:34 UTC (rev 4263)
@@ -1,44 +1,46 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
-"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
-<part>
- <?dbhtml filename="part-core.html"?>
-
- <title>eXoCore</title>
-
- <xi:include href="core/core.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/db-creator-service.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/security-service.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/spring-security-integration.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/organization-service.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/organization-service-initalizer.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/organization-service-listener.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/conversationstate-when-membership-changed.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/db-schema-creator-service.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/db-configuration-hibernate.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/ldap-configuration.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="core/tika-document-reader-service.xml"
- xmlns:xi="http://www.w3.org/2001/XInclude" />
-</part>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<part>
+ <?dbhtml filename="part-core.html"?>
+
+ <title>eXoCore</title>
+
+ <xi:include href="core/core.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/db-creator-service.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/security-service.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/spring-security-integration.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/organization-service.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/organization-service-initalizer.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/organization-service-listener.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/conversationstate-when-membership-changed.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/db-schema-creator-service.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/db-configuration-hibernate.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/ldap-configuration.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/tika-document-reader-service.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="core/digest-auth.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+</part>
15 years
exo-jcr SVN: r4262 - in core/trunk: exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization and 9 other directories.
by do-not-reply@jboss.org
Author: dkuleshov
Date: 2011-04-20 09:28:47 -0400 (Wed, 20 Apr 2011)
New Revision: 4262
Added:
core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/DigestAuthenticator.java
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/DigestAuthenticationHelper.java
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/DigestCallbackHandler.java
Modified:
core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/auth/OrganizationAuthenticatorImpl.java
core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/impl/mock/DummyOrganizationService.java
core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/UserDAOImpl.java
core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/UserDAOImpl.java
core/trunk/exo.core.component.security.core/pom.xml
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/PasswordCredential.java
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JbossLoginModule.java
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JettyLoginModule.java
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/TomcatLoginModule.java
core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/BasicCallbackHandler.java
core/trunk/exo.core.component.security.core/src/test/java/org/exoplatform/services/security/TestLoginModule.java
core/trunk/pom.xml
Log:
EXOJCR-1019: added digest auth
Added: core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/DigestAuthenticator.java
===================================================================
--- core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/DigestAuthenticator.java (rev 0)
+++ core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/DigestAuthenticator.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.services.organization;
+
+import org.exoplatform.services.security.Credential;
+
+/**
+ * Created by The eXo Platform SAS .
+ *
+ * @author Dmitry Kuleshov
+ * @version $Id: $
+ */
+
+public interface DigestAuthenticator
+{
+ /**
+ * Checks if user's credentials are valid.
+ * It is more flexible because Credential may contain password context
+ * or some other useful data.
+ * @param credentials
+ * @return return true if the username and the password matches
+ * the database record, else return false.
+ * @throws Exception throw an exception if cannot access the database
+ */
+ public boolean authenticate(Credential[] credentials) throws Exception;
+}
Modified: core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/auth/OrganizationAuthenticatorImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/auth/OrganizationAuthenticatorImpl.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/auth/OrganizationAuthenticatorImpl.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -22,8 +22,10 @@
import org.exoplatform.container.component.RequestLifeCycle;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import org.exoplatform.services.organization.DigestAuthenticator;
import org.exoplatform.services.organization.Membership;
import org.exoplatform.services.organization.OrganizationService;
+import org.exoplatform.services.organization.UserHandler;
import org.exoplatform.services.security.Authenticator;
import org.exoplatform.services.security.Credential;
import org.exoplatform.services.security.Identity;
@@ -128,7 +130,16 @@
password = new String(encrypter.encrypt(password.getBytes()));
begin(orgService);
- boolean success = orgService.getUserHandler().authenticate(user, password);
+ boolean success;
+ Object userHandler = orgService.getUserHandler();
+ if (userHandler instanceof DigestAuthenticator)
+ {
+ success = ((DigestAuthenticator)userHandler).authenticate(credentials);
+ }
+ else
+ {
+ success = ((UserHandler)userHandler).authenticate(user, password);
+ }
end(orgService);
if (!success)
Modified: core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/impl/mock/DummyOrganizationService.java
===================================================================
--- core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/impl/mock/DummyOrganizationService.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/impl/mock/DummyOrganizationService.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -23,9 +23,9 @@
import org.exoplatform.commons.utils.LazyPageList;
import org.exoplatform.commons.utils.ListAccess;
-import org.exoplatform.commons.utils.ObjectPageList;
import org.exoplatform.commons.utils.PageList;
import org.exoplatform.services.organization.BaseOrganizationService;
+import org.exoplatform.services.organization.DigestAuthenticator;
import org.exoplatform.services.organization.Group;
import org.exoplatform.services.organization.GroupEventListener;
import org.exoplatform.services.organization.GroupHandler;
@@ -43,11 +43,16 @@
import org.exoplatform.services.organization.impl.MembershipImpl;
import org.exoplatform.services.organization.impl.UserImpl;
import org.exoplatform.services.organization.impl.UserProfileImpl;
+import org.exoplatform.services.security.Credential;
+import org.exoplatform.services.security.DigestAuthenticationHelper;
+import org.exoplatform.services.security.PasswordCredential;
+import org.exoplatform.services.security.UsernameCredential;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
/**
* @author benjaminmestrallet
@@ -149,7 +154,7 @@
}
}
- static public class UserHandlerImpl implements UserHandler
+ static public class UserHandlerImpl implements UserHandler, DigestAuthenticator
{
private static final int DEFAULT_LIST_SIZE = 6;
@@ -300,6 +305,27 @@
public boolean authenticate(String username, String password) throws Exception
{
+ return authenticate(new Credential[]{new UsernameCredential(username), new PasswordCredential(password)});
+ }
+
+ public boolean authenticate(Credential[] credentials) throws Exception
+ {
+ String username = null;
+ String password = null;
+ Map<String, String> passwordContext = null;
+ for (Credential cred : credentials)
+ {
+ if (cred instanceof UsernameCredential)
+ {
+ username = ((UsernameCredential)cred).getUsername();
+ }
+ if (cred instanceof PasswordCredential)
+ {
+ password = ((PasswordCredential)cred).getPassword();
+ passwordContext = ((PasswordCredential)cred).getPasswordContext();
+ }
+ }
+
Iterator<User> it = users.iterator();
User usr = null;
@@ -317,14 +343,33 @@
if (usr != null)
{
if (usr.getUserName().equals("__anonim"))
+ {
return true;
-
- if (usr.getPassword().equals(password))
- return true;
+ }
+ if (passwordContext == null)
+ {
+ if (usr.getPassword().equals(password))
+ {
+ return true;
+ }
+ }
+ // passwordContext != null means that digest authentication is used
+ else
+ {
+ // so we need calculate MD5 cast
+ String dp = DigestAuthenticationHelper.calculatePassword(username, usr.getPassword(), passwordContext);
+ // to compare it to sent by client
+ if (dp.equals(password))
+ {
+ return true;
+ }
+ }
}
return false;
}
+
+
}
public static class GroupHandlerImpl implements GroupHandler
Modified: core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/UserDAOImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/UserDAOImpl.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/UserDAOImpl.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -25,12 +25,17 @@
import org.exoplatform.services.cache.ExoCache;
import org.exoplatform.services.database.HibernateService;
import org.exoplatform.services.database.ObjectQuery;
+import org.exoplatform.services.organization.DigestAuthenticator;
import org.exoplatform.services.organization.Query;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.organization.UserEventListener;
import org.exoplatform.services.organization.UserEventListenerHandler;
import org.exoplatform.services.organization.UserHandler;
import org.exoplatform.services.organization.impl.UserImpl;
+import org.exoplatform.services.security.Credential;
+import org.exoplatform.services.security.DigestAuthenticationHelper;
+import org.exoplatform.services.security.PasswordCredential;
+import org.exoplatform.services.security.UsernameCredential;
import org.hibernate.Session;
import org.hibernate.Transaction;
@@ -40,12 +45,13 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* Created by The eXo Platform SAS Author : Mestrallet Benjamin benjmestrallet(a)users.sourceforge.net
* Author : Tuan Nguyen tuan08(a)users.sourceforge.net Date: Aug 22, 2003 Time: 4:51:21 PM
*/
-public class UserDAOImpl implements UserHandler, UserEventListenerHandler
+public class UserDAOImpl implements UserHandler, UserEventListenerHandler, DigestAuthenticator
{
public static final String queryFindUserByName =
"from u in class org.exoplatform.services.organization.impl.UserImpl " + "where u.userName = ?";
@@ -173,10 +179,41 @@
public boolean authenticate(String username, String password) throws Exception
{
+ return authenticate(new Credential[]{new UsernameCredential(username), new PasswordCredential(password)});
+ }
+
+ public boolean authenticate(Credential[] credentials) throws Exception
+ {
+ String username = null;
+ String password = null;
+ Map<String, String> passwordContext= null;
+ for (Credential cred : credentials)
+ {
+ if (cred instanceof UsernameCredential)
+ {
+ username = ((UsernameCredential)cred).getUsername();
+ }
+ if (cred instanceof PasswordCredential)
+ {
+ password = ((PasswordCredential)cred).getPassword();
+ passwordContext = ((PasswordCredential)cred).getPasswordContext();
+ }
+ }
+
User user = findUserByName(username);
if (user == null)
return false;
- boolean authenticated = user.getPassword().equals(password);
+
+ boolean authenticated;
+ if (passwordContext == null)
+ {
+ authenticated = user.getPassword().equals(password);
+ }
+ else
+ {
+ authenticated =
+ DigestAuthenticationHelper.calculatePassword(username, user.getPassword(), passwordContext).equals(password);
+ }
if (authenticated)
{
UserImpl userImpl = (UserImpl)user;
Modified: core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/UserDAOImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/UserDAOImpl.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/UserDAOImpl.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -28,15 +28,29 @@
import org.exoplatform.services.listener.ListenerService;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
-import org.exoplatform.services.organization.*;
+import org.exoplatform.services.organization.DigestAuthenticator;
+import org.exoplatform.services.organization.Group;
+import org.exoplatform.services.organization.GroupHandler;
+import org.exoplatform.services.organization.Membership;
+import org.exoplatform.services.organization.MembershipHandler;
+import org.exoplatform.services.organization.OrganizationService;
+import org.exoplatform.services.organization.Query;
+import org.exoplatform.services.organization.User;
+import org.exoplatform.services.organization.UserEventListener;
+import org.exoplatform.services.organization.UserHandler;
+import org.exoplatform.services.security.Credential;
+import org.exoplatform.services.security.DigestAuthenticationHelper;
+import org.exoplatform.services.security.PasswordCredential;
+import org.exoplatform.services.security.UsernameCredential;
import java.util.Calendar;
import java.util.List;
+import java.util.Map;
/**
* Created by The eXo Platform SAS Apr 7, 2007
*/
-public class UserDAOImpl extends StandardSQLDAO<UserImpl> implements UserHandler
+public class UserDAOImpl extends StandardSQLDAO<UserImpl> implements UserHandler, DigestAuthenticator
{
protected static Log log = ExoLogger.getLogger("exo.core.component.organization.jdbc.UserDAOImpl");
@@ -73,11 +87,42 @@
public boolean authenticate(String username, String password) throws Exception
{
+ return authenticate(new Credential[]{new UsernameCredential(username), new PasswordCredential(password)});
+ }
+
+ public boolean authenticate(Credential[] credentials) throws Exception
+ {
+ String username = null;
+ String password = null;
+ Map<String, String> passwordContext = null;
+ for (Credential cred : credentials)
+ {
+ if (cred instanceof UsernameCredential)
+ {
+ username = ((UsernameCredential)cred).getUsername();
+ }
+ if (cred instanceof PasswordCredential)
+ {
+ password = ((PasswordCredential)cred).getPassword();
+ passwordContext = ((PasswordCredential)cred).getPasswordContext();
+ }
+ }
+
User user = findUserByName(username);
if (user == null)
return false;
- boolean authenticated = user.getPassword().equals(password);
+ boolean authenticated;
+ if (passwordContext == null)
+ {
+ authenticated = user.getPassword().equals(password);
+ }
+ else
+ {
+ authenticated =
+ DigestAuthenticationHelper.calculatePassword(username, user.getPassword(), passwordContext).equals(password);
+ }
+
if (log.isDebugEnabled())
log.debug("+++++++++++AUTHENTICATE USERNAME " + username + " AND PASS " + password + " - " + authenticated);
if (authenticated)
Modified: core/trunk/exo.core.component.security.core/pom.xml
===================================================================
--- core/trunk/exo.core.component.security.core/pom.xml 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/pom.xml 2011-04-20 13:28:47 UTC (rev 4262)
@@ -53,6 +53,14 @@
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.jboss.security</groupId>
+ <artifactId>jbosssx</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.aggregate</groupId>
+ <artifactId>jetty-plus</artifactId>
+ </dependency>
</dependencies>
<build>
Added: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/DigestAuthenticationHelper.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/DigestAuthenticationHelper.java (rev 0)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/DigestAuthenticationHelper.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.security;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map;
+
+/**
+ * @author Dmitry Kuleshov
+ * @version $Id:$
+ */
+
+public class DigestAuthenticationHelper
+{
+
+ /**
+ * Number of HEX digits used for A1, A2 strings and password encoding.
+ * More information is settled in<a href=http://www.apps.ietf.org/rfc/rfc2617.html#sec-3.2.2>RFC-2617</a>.
+ */
+ private static int HASH_HEX_LENGTH = 32;
+
+ public static String calculatePassword(String username, String originalPassword, Map<String, String> passwordContext)
+ throws NoSuchAlgorithmException
+ {
+ // fetch needed data
+ String nc = passwordContext.get("nc");
+ String a2 = passwordContext.get("md5a2");
+ String uri = passwordContext.get("uri");
+ String qop = passwordContext.get("qop");
+ String nonce = passwordContext.get("nonce");
+ String realm = passwordContext.get("realmName");
+ String cnonce = passwordContext.get("cnonce");
+ String entity = passwordContext.get("entity");
+ String method = passwordContext.get("method");
+ if (realm == null)
+ {
+ // in case we have a jboss server, it uses 'realm' name
+ realm = passwordContext.get("realm");
+ }
+ if (a2 == null)
+ {
+ // in case we have a jboss server, it uses 'a2hash' name
+ a2 = passwordContext.get("a2hash");
+ }
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ // calculate MD5 hash of A1 string
+ String a1 = username + ":" + realm + ":" + originalPassword;
+ md.update(a1.getBytes());
+ // encode A1 in HEX digits
+ a1 = convertToHex(md.digest());
+
+ // if encoded A2 MD5 hash is not supplied by server
+ // we need to calculate it manually
+ if (a2 == null)
+ {
+ if (qop.equals("auth"))
+ {
+ md.update((method + ":" + uri).getBytes());
+ a2 = convertToHex(md.digest());
+ }
+ else if (qop.equals("auth-int"))
+ {
+ md.update((method + ":" + uri + ":" + convertToHex(entity.getBytes())).getBytes());
+ a2 = convertToHex(md.digest());
+ }
+ }
+
+ // create a digest using provided data
+ String digest = a1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2;
+ md.update(digest.getBytes());
+ // return encoded hash using HEX digits digest
+ return convertToHex(md.digest());
+ }
+
+ public static String convertToHex(byte[] bin)
+ {
+ StringBuffer tmpStr = new StringBuffer(HASH_HEX_LENGTH);
+ int digit;
+
+ for (int i = 0; i < HASH_HEX_LENGTH / 2; i++)
+ {
+ // get integer presentation of left 4 bits of byte
+ digit = (bin[i] >> 4) & 0xf;
+ // append HEX digit
+ tmpStr.append(Integer.toHexString(digit));
+ // get integer presentation of right 4 bits of byte
+ digit = bin[i] & 0xf;
+ tmpStr.append(Integer.toHexString(digit));
+
+ };
+ return tmpStr.toString();
+ }
+}
Modified: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/PasswordCredential.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/PasswordCredential.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/PasswordCredential.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -18,6 +18,8 @@
*/
package org.exoplatform.services.security;
+import java.util.Map;
+
/**
* Created by The eXo Platform SAS .
*
@@ -39,6 +41,14 @@
private String password;
/**
+ * Digest Authorization Request Context.
+ * Here we're going to keep some information passed through request:
+ * qop, nonce, cnonce, algorithm, ns, etc. All context is defined in
+ * <a href=http://www.apps.ietf.org/rfc/rfc2617.html#sec-3.2.2>RFC-2617</a>.
+ */
+ private Map<String, String> passwordContext = null;
+
+ /**
* Create new PasswordCredential.
* @param password password
*/
@@ -48,6 +58,25 @@
}
/**
+ * Create new PasswordCredential.
+ * @param password password
+ * @param passwordContext password context passed through Digest Authorization request
+ */
+ public PasswordCredential(String password, Map<String, String> passwordContext)
+ {
+ this.password = password;
+ this.passwordContext = passwordContext;
+ }
+
+ /**
+ * @return password context
+ */
+ public Map<String, String> getPasswordContext()
+ {
+ return this.passwordContext;
+ }
+
+ /**
* @return password
*/
public String getPassword()
Modified: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JbossLoginModule.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JbossLoginModule.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JbossLoginModule.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -21,20 +21,33 @@
import org.exoplatform.container.monitor.jvm.J2EEServerInfo;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
+import org.exoplatform.services.security.Authenticator;
+import org.exoplatform.services.security.Credential;
+import org.exoplatform.services.security.Identity;
+import org.exoplatform.services.security.PasswordCredential;
+import org.exoplatform.services.security.UsernameCredential;
import org.exoplatform.services.security.jaas.DefaultLoginModule;
import org.exoplatform.services.security.jaas.JAASGroup;
import org.exoplatform.services.security.jaas.RolePrincipal;
import org.exoplatform.services.security.jaas.UserPrincipal;
+import org.jboss.security.auth.callback.MapCallback;
+import java.io.IOException;
import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
/**
@@ -50,6 +63,11 @@
private static Log log = ExoLogger.getLogger("exo.core.component.security.core.JbossLoginModule.class");
/**
+ * To retrieve password context during Digest Authentication.
+ */
+ private MapCallback[] mapCallback = {new MapCallback()};
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -81,6 +99,190 @@
}
/**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean login() throws LoginException
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("In login of JbossLoginModule.");
+ }
+ try
+ {
+ if (sharedState.containsKey("exo.security.identity"))
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Use Identity from previous LoginModule");
+ }
+ identity = (Identity)sharedState.get("exo.security.identity");
+ }
+ else
+ {
+ if (!digestAuthenticationIsUsed())
+ {
+ return super.login();
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Try create identity");
+ }
+
+ Authenticator authenticator = (Authenticator)getContainer().getComponentInstanceOfType(Authenticator.class);
+
+ if (authenticator == null)
+ {
+ throw new LoginException("No Authenticator component found, check your configuration");
+ }
+
+ String userId = authenticator.validateUser(getCredentials());
+
+ identity = authenticator.createIdentity(userId);
+ sharedState.put("javax.security.auth.login.name", userId);
+ subject.getPrivateCredentials().add(getPassword());
+ subject.getPublicCredentials().add(getUsername());
+ }
+ return true;
+
+ }
+ catch (final Throwable e)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug(e.getMessage(), e);
+ }
+
+ throw new LoginException(e.getMessage());
+ }
+ }
+
+ /**
+ * An utility method handles mapCallback and also checks if digest authentication is used.
+ * @return true if digest authentication is used, otherwise - false
+ * @throws IOException
+ */
+ private boolean digestAuthenticationIsUsed() throws IOException
+ {
+ try
+ {
+ // here we're trying to handle mapCallback
+ // if it is handled successfully than digest
+ // authentication is used
+ callbackHandler.handle(mapCallback);
+ return true;
+ }
+ catch (UnsupportedCallbackException uce)
+ {
+ // otherwise UnsupportedCallbackException is thrown
+ return false;
+ }
+ }
+
+ /**
+ * An utility method to retrieve credentials. All needed for password hashing information
+ * is retrieved from MapCallback. NameCallback and PasswordCallback are used to correspondingly
+ * retrieve username and password.
+ * @return Credential
+ * @throws IOException
+ * @throws Exception
+ */
+ private Credential[] getCredentials() throws IOException
+ {
+ String username = null;
+ String password = null;
+ Map<String, String> passwordContext = new HashMap<String, String>();
+
+ passwordContext.put("qop", (String)mapCallback[0].getInfo("qop"));
+ passwordContext.put("nonce", (String)mapCallback[0].getInfo("nonce"));
+ passwordContext.put("cnonce", (String)mapCallback[0].getInfo("cnonce"));
+ passwordContext.put("a2hash", (String)mapCallback[0].getInfo("a2hash"));
+ passwordContext.put("nc", (String)mapCallback[0].getInfo("nc"));
+ passwordContext.put("realm", (String)mapCallback[0].getInfo("realm"));
+
+ try
+ {
+ Callback[] nameCallback = {new NameCallback("Username")};
+ callbackHandler.handle(nameCallback);
+ username = ((NameCallback)nameCallback[0]).getName();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving username from callback handler! ", e);
+ }
+ }
+
+ try
+ {
+ Callback[] passwordCallback = {new PasswordCallback("Password", false)};
+ callbackHandler.handle(passwordCallback);
+ password = new String(((PasswordCallback)passwordCallback[0]).getPassword());
+ ((PasswordCallback)passwordCallback[0]).clearPassword();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving password from callback handler! ", e);
+ }
+ }
+
+ if (username == null || password == null)
+ {
+ return null;
+ }
+
+ return new Credential[]{new UsernameCredential(username), new PasswordCredential(password, passwordContext)};
+ }
+
+ private UsernameCredential getUsername() throws IOException
+ {
+ String username = null;
+
+ try
+ {
+ Callback[] nameCallback = {new NameCallback("Username")};
+ callbackHandler.handle(nameCallback);
+ username = ((NameCallback)nameCallback[0]).getName();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving username from callback handler! ", e);
+ }
+ }
+
+ return new UsernameCredential(username);
+ }
+
+ private String getPassword() throws IOException
+ {
+ String password = null;
+
+ try
+ {
+ Callback[] passwordCallback = {new PasswordCallback("Password", false)};
+ callbackHandler.handle(passwordCallback);
+ password = new String(((PasswordCallback)passwordCallback[0]).getPassword());
+ ((PasswordCallback)passwordCallback[0]).clearPassword();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving password from callback handler! ", e);
+ }
+ }
+
+ return password;
+ }
+
+ /**
* Attempts eviction of the subject in the JBoss security manager cache.
*
* @return a boolean
Modified: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JettyLoginModule.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JettyLoginModule.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/JettyLoginModule.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -1,16 +1,35 @@
package org.exoplatform.services.security.j2ee;
+import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
+import org.eclipse.jetty.security.authentication.DigestAuthenticator;
+import org.exoplatform.services.security.Authenticator;
+import org.exoplatform.services.security.Credential;
+import org.exoplatform.services.security.Identity;
+import org.exoplatform.services.security.PasswordCredential;
+import org.exoplatform.services.security.UsernameCredential;
import org.exoplatform.services.security.jaas.DefaultLoginModule;
import org.exoplatform.services.security.jaas.RolePrincipal;
import org.exoplatform.services.security.jaas.UserPrincipal;
+import java.io.IOException;
+import java.lang.reflect.Field;
import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
public class JettyLoginModule extends DefaultLoginModule
{
+ /**
+ * To retrieve an object instance containing needed password context.
+ */
+ private Callback[] objectCallback = {new ObjectCallback()};
@Override
public boolean commit() throws LoginException
@@ -35,4 +54,199 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean login() throws LoginException
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("In login of JettyLoginModule.");
+ }
+ try
+ {
+ if (sharedState.containsKey("exo.security.identity"))
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Use Identity from previous LoginModule");
+ }
+ identity = (Identity)sharedState.get("exo.security.identity");
+ }
+ else
+ {
+ if (!digestAuthenticationIsUsed())
+ {
+ return super.login();
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Try create identity");
+ }
+
+ Authenticator authenticator = (Authenticator)getContainer().getComponentInstanceOfType(Authenticator.class);
+
+ if (authenticator == null)
+ {
+ throw new LoginException("No Authenticator component found, check your configuration");
+ }
+
+ String userId = authenticator.validateUser(getCredentials());
+
+ identity = authenticator.createIdentity(userId);
+ sharedState.put("javax.security.auth.login.name", userId);
+ // TODO use PasswordCredential wrapper
+ subject.getPrivateCredentials().add(getPassword());
+ subject.getPublicCredentials().add(getUsername());
+ }
+ return true;
+
+ }
+ catch (final Throwable e)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug(e.getMessage(), e);
+ }
+
+ throw new LoginException(e.getMessage());
+ }
+ }
+
+ /**
+ * An utility method to handle object callback and also to checks if
+ * digest authentication is used during login operation.
+ * @return true if digest authentication is used, otherwise - false
+ * @throws IOException
+ * @throws UnsupportedCallbackException
+ */
+ private boolean digestAuthenticationIsUsed() throws IOException, UnsupportedCallbackException
+ {
+ callbackHandler.handle(objectCallback);
+ // in case we have a digest authentication
+ // objectCallback should contain a structured instance
+ // in case we have a basic authentication
+ // objectCallback should contain only a string with a password
+ return !(((ObjectCallback)objectCallback[0]).getObject() instanceof String);
+ }
+
+ /**
+ * An utility method to get Credentials from object callback instance.
+ * It uses reflection mechanism to get access to Digest inner class of
+ * DigestAuthenticator, which is provided by object callback as it
+ * contains all needed information for password hashing.
+ * @return Credential
+ * @throws NoSuchFieldException
+ * @throws SecurityException
+ * @throws IllegalAccessException
+ * @throws IllegalArgumentException
+ * @throws Exception
+ */
+ private Credential[] getCredentials()
+ {
+ Map<String, String> passwordContext = new HashMap<String, String>();
+ Set<String> contextElements = new HashSet<String>();
+ // object to contain DigestAuthenticator$Digest instance to get
+ // needed data from instance's fields
+ Object objectFromCallback = ((ObjectCallback)objectCallback[0]).getObject();
+ String username = null;
+ String password = null;
+ // to keep DigestAuthenticator$Digest representation
+ Class<?> digestAuthenticatorClazz = DigestAuthenticator.class.getDeclaredClasses()[0];
+
+ contextElements.add("cnonce");
+ contextElements.add("method");
+ contextElements.add("nc");
+ contextElements.add("nonce");
+ contextElements.add("qop");
+ contextElements.add("realm");
+ contextElements.add("uri");
+
+ try
+ {
+ // here we're going to retrieve needed information from Digest class fields
+ Iterator<String> elementIterator = contextElements.iterator();
+ String element;
+ Field field;
+ while (elementIterator.hasNext())
+ {
+ element = elementIterator.next();
+ field = digestAuthenticatorClazz.getDeclaredField(element);
+ // need to set true as all needed fields are in private class, thus are private
+ field.setAccessible(true);
+ passwordContext.put(element, (String)field.get(objectFromCallback));
+ }
+
+ // get username
+ field = digestAuthenticatorClazz.getDeclaredField("username");
+ field.setAccessible(true);
+ username = (String)field.get(objectFromCallback);
+
+ // get password
+ field = digestAuthenticatorClazz.getDeclaredField("response");
+ field.setAccessible(true);
+ password = (String)field.get(objectFromCallback);
+ }
+ catch (Exception e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Could not get credentials.", e);
+ }
+ }
+
+ if (username == null || password == null)
+ {
+ return null;
+ }
+
+ return new Credential[]{new UsernameCredential(username), new PasswordCredential(password, passwordContext)};
+ }
+
+ private UsernameCredential getUsername()
+ {
+ String username = null;
+ Class<?> digestAuthenticatorClazz = DigestAuthenticator.class.getDeclaredClasses()[0];
+ try
+ {
+ Field field = digestAuthenticatorClazz.getDeclaredField("username");
+ field.setAccessible(true);
+ username = (String)field.get((((ObjectCallback)objectCallback[0]).getObject()));
+ }
+ catch (Exception e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Could not get username.", e);
+ }
+ }
+
+ return new UsernameCredential(username);
+ }
+
+ private String getPassword() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
+ IllegalAccessException
+ {
+ String password = null;
+ Class<?> digestAuthenticatorClazz = DigestAuthenticator.class.getDeclaredClasses()[0];
+ try
+ {
+ Field field = digestAuthenticatorClazz.getDeclaredField("response");
+ field.setAccessible(true);
+ password = (String)field.get((((ObjectCallback)objectCallback[0]).getObject()));
+ }
+ catch (Exception e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Could not get password.", e);
+ }
+ }
+
+ return password;
+ }
+
}
Modified: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/TomcatLoginModule.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/TomcatLoginModule.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/j2ee/TomcatLoginModule.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -18,13 +18,28 @@
*/
package org.exoplatform.services.security.j2ee;
+import org.exoplatform.services.security.Authenticator;
+import org.exoplatform.services.security.Credential;
+import org.exoplatform.services.security.Identity;
+import org.exoplatform.services.security.PasswordCredential;
+import org.exoplatform.services.security.UsernameCredential;
import org.exoplatform.services.security.jaas.DefaultLoginModule;
import org.exoplatform.services.security.jaas.RolePrincipal;
import org.exoplatform.services.security.jaas.UserPrincipal;
+import java.io.IOException;
import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Set;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
/**
@@ -63,4 +78,206 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean login() throws LoginException
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("In login of TomcatLoginModule.");
+ }
+ try
+ {
+ if (sharedState.containsKey("exo.security.identity"))
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Use Identity from previous LoginModule");
+ }
+ identity = (Identity)sharedState.get("exo.security.identity");
+ }
+ else
+ {
+ if (!digestAuthenticationIsUsed())
+ {
+ return super.login();
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Try create identity");
+ }
+
+ Authenticator authenticator = (Authenticator)getContainer().getComponentInstanceOfType(Authenticator.class);
+
+ if (authenticator == null)
+ {
+ throw new LoginException("No Authenticator component found, check your configuration");
+ }
+
+ String userId = authenticator.validateUser(getCredentials());
+
+ identity = authenticator.createIdentity(userId);
+ sharedState.put("javax.security.auth.login.name", userId);
+ subject.getPrivateCredentials().add(getPassword());
+ subject.getPublicCredentials().add(getUsername());
+ }
+ return true;
+
+ }
+ catch (final Throwable e)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug(e.getMessage(), e);
+ }
+
+ throw new LoginException(e.getMessage());
+ }
+ }
+
+ /**
+ * An utility class to get credentials. To retrieve password context we use TextInputCallback.
+ * NameCallback and PasswordCallback are used to correspondingly retrieve username and password.
+ * @return Credential
+ * @throws IOException
+ * @throws Exception
+ */
+ private Credential[] getCredentials() throws IOException
+ {
+
+ Map<String, String> passwordContext = new HashMap<String, String>();
+ Set<String> contextElements = new HashSet<String>();
+ Callback[] digestCallback = new Callback[1];
+ String username = null;
+ String password = null;
+
+ contextElements.add("cnonce");
+ contextElements.add("nc");
+ contextElements.add("nonce");
+ contextElements.add("qop");
+ contextElements.add("realmName");
+ contextElements.add("md5a2");
+
+ Iterator<String> elementIterator = contextElements.iterator();
+
+ String element;
+ while (elementIterator.hasNext())
+ {
+ element = elementIterator.next();
+ try
+ {
+ digestCallback[0] = new TextInputCallback(element);
+ callbackHandler.handle(digestCallback);
+ passwordContext.put(element, ((TextInputCallback)digestCallback[0]).getText());
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Unsupported callback type.", e);
+ }
+ }
+
+ }
+
+ try
+ {
+ Callback[] nameCallback = {new NameCallback("Username")};
+ callbackHandler.handle(nameCallback);
+ username = ((NameCallback)nameCallback[0]).getName();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving username from callback handler! ", e);
+ }
+ }
+
+ try
+ {
+ Callback[] passwordCallback = {new PasswordCallback("Password", false)};
+ callbackHandler.handle(passwordCallback);
+ password = new String(((PasswordCallback)passwordCallback[0]).getPassword());
+ ((PasswordCallback)passwordCallback[0]).clearPassword();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving password from callback handler! ", e);
+ }
+ }
+
+ if (username == null || password == null)
+ {
+ return null;
+ }
+
+ return new Credential[]{new UsernameCredential(username), new PasswordCredential(password, passwordContext)};
+ }
+
+ /**
+ * An utility method to check if digest authentication is used.
+ * @return true if digest authentication is used, otherwise - false
+ * @throws IOException
+ * @throws UnsupportedCallbackException
+ */
+ private boolean digestAuthenticationIsUsed() throws IOException, UnsupportedCallbackException
+ {
+ Callback[] authCallback = {new TextInputCallback("authMethod")};
+ callbackHandler.handle(authCallback);
+ String authMethod = (String)(((TextInputCallback)authCallback[0]).getText());
+
+ return "DIGEST".equalsIgnoreCase(authMethod);
+ }
+
+ private UsernameCredential getUsername() throws IOException
+ {
+ String username = null;
+
+ try
+ {
+ Callback[] nameCallback = {new NameCallback("Username")};
+ callbackHandler.handle(nameCallback);
+ username = ((NameCallback)nameCallback[0]).getName();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving username from callback handler! ", e);
+ }
+ }
+
+ return new UsernameCredential(username);
+ }
+
+ private String getPassword() throws IOException
+ {
+ String password = null;
+
+ try
+ {
+ Callback[] passwordCallback = {new PasswordCallback("Password", false)};
+ callbackHandler.handle(passwordCallback);
+ password = new String(((PasswordCallback)passwordCallback[0]).getPassword());
+ ((PasswordCallback)passwordCallback[0]).clearPassword();
+ }
+ catch (UnsupportedCallbackException e)
+ {
+ if (log.isErrorEnabled())
+ {
+ log.error("Error on retrieving password from callback handler! ", e);
+ }
+ }
+
+ return password;
+ }
+
+
}
Modified: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/BasicCallbackHandler.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/BasicCallbackHandler.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/BasicCallbackHandler.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -24,6 +24,7 @@
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
public class BasicCallbackHandler implements CallbackHandler
@@ -43,6 +44,12 @@
* @param login name
* @param password password
*/
+
+ /**
+ * Authentication method.
+ */
+ private final String authMethod = "BASIC";
+
public BasicCallbackHandler(String login, char[] password)
{
this.login = login;
@@ -64,6 +71,13 @@
{
((PasswordCallback)callbacks[i]).setPassword(password);
}
+ else if (callbacks[i] instanceof TextInputCallback)
+ {
+ if ("authMethod".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(authMethod);
+ }
+ }
else
{
throw new UnsupportedCallbackException(callbacks[i], "Callback class not supported");
Added: core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/DigestCallbackHandler.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/DigestCallbackHandler.java (rev 0)
+++ core/trunk/exo.core.component.security.core/src/main/java/org/exoplatform/services/security/jaas/DigestCallbackHandler.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This 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 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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 this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.security.jaas;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextInputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+public class DigestCallbackHandler implements CallbackHandler
+{
+ /**
+ * Name.
+ */
+ private String login;
+
+ /**
+ * Password.
+ */
+ private char[] password;
+
+ /**
+ * @param login name
+ * @param password password
+ */
+
+ /**
+ * Authentication method.
+ */
+ private final String authMethod = "DIGEST";
+
+ /**
+ * Here we pass all needed password context to be retrieved later on Callback handling.
+ */
+ private final Map<String, String> passwordContext;
+
+ public DigestCallbackHandler(String login, char[] password, Map<String, String> passwordContext)
+ {
+ this.login = login;
+ this.password = password;
+ this.passwordContext = passwordContext;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
+ {
+ for (int i = 0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] instanceof NameCallback)
+ {
+ ((NameCallback)callbacks[i]).setName(login);
+ }
+ else if (callbacks[i] instanceof PasswordCallback)
+ {
+ ((PasswordCallback)callbacks[i]).setPassword(password);
+ }
+ else if (callbacks[i] instanceof TextInputCallback)
+ {
+ if ("authMethod".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(authMethod);
+ }
+ else if ("cnonce".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(passwordContext.get("cnonce"));
+ }
+ else if ("md5a2".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(passwordContext.get("md5a2"));
+ }
+ else if ("nc".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(passwordContext.get("nc"));
+ }
+ else if ("nonce".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(passwordContext.get("nonce"));
+ }
+ else if ("qop".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(passwordContext.get("qop"));
+ }
+ else if ("realmName".equals(((TextInputCallback)callbacks[i]).getPrompt()))
+ {
+ ((TextInputCallback)callbacks[i]).setText(passwordContext.get("realmName"));
+ }
+ }
+ else
+ {
+ throw new UnsupportedCallbackException(callbacks[i], "Callback class not supported");
+ }
+ }
+ }
+}
+
Modified: core/trunk/exo.core.component.security.core/src/test/java/org/exoplatform/services/security/TestLoginModule.java
===================================================================
--- core/trunk/exo.core.component.security.core/src/test/java/org/exoplatform/services/security/TestLoginModule.java 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/exo.core.component.security.core/src/test/java/org/exoplatform/services/security/TestLoginModule.java 2011-04-20 13:28:47 UTC (rev 4262)
@@ -22,8 +22,12 @@
import org.exoplatform.container.StandaloneContainer;
import org.exoplatform.services.security.jaas.BasicCallbackHandler;
+import org.exoplatform.services.security.jaas.DigestCallbackHandler;
import java.net.URL;
+import java.security.MessageDigest;
+import java.util.HashMap;
+import java.util.Map;
import javax.security.auth.login.LoginContext;
@@ -73,7 +77,7 @@
conversationRegistry.clear();
}
- public void testLogin() throws Exception
+ public void testBasicLogin() throws Exception
{
BasicCallbackHandler handler = new BasicCallbackHandler("exo", "exo".toCharArray());
LoginContext loginContext = new LoginContext("exo", handler);
@@ -90,4 +94,66 @@
}
+ /**
+ * Here we test Digest Authorization. We artificially create a password context, to emulate
+ * Authorize request environment. Than we login and expect to have "exo" identity registered
+ * and corresponding group created. More information about Digest Authorization is settled
+ * <a href=http://www.apps.ietf.org/rfc/rfc2617.html>here</a>.
+ * @throws Exception
+ */
+ public void testDigestLogin() throws Exception
+ {
+ /**
+ * Number of hex digits.
+ * Hex digits are needed to encode A2, A1 elements as defined in RFC-2617.
+ */
+ int HASH_HEX_LENGTH = 32;
+
+ /**
+ * Here we are going to keep all password context information
+ */
+ Map<String, String> passwordContext = new HashMap<String, String>();
+
+ passwordContext.put("realmName", "eXo REST services");
+ passwordContext.put("nonce", "2c613333aa4cc017d358c09f61977718");
+ passwordContext.put("cnonce", "bFaGgjcb+QP47nzPpxtonQ28Kgbz22WsBqmKjHU49q9=");
+ passwordContext.put("qop", "auth");
+ passwordContext.put("nc", "00000001");
+ passwordContext.put("response", "303c5080ac28ed876ea138d207fdf2cd");
+
+ // encrypt A2 string using MD5
+ String md5a2 = "Method:" + "/rest/jcr/repository/production";
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ md.update(md5a2.getBytes());
+
+ // encode encrypted A2 string using HEX digits
+ byte[] bin = md.digest();
+ StringBuffer tmpStr = new StringBuffer(HASH_HEX_LENGTH);
+ int digit;
+ for (int i = 0; i < HASH_HEX_LENGTH / 2; i++)
+ {
+ digit = (bin[i] >> 4) & 0xf;
+ tmpStr.append(Integer.toHexString(digit));
+ digit = bin[i] & 0xf;
+ tmpStr.append(Integer.toHexString(digit));
+
+ };
+
+ passwordContext.put("md5a2", tmpStr.toString());
+
+ DigestCallbackHandler handler = new DigestCallbackHandler("exo", "exo".toCharArray(), passwordContext);
+ LoginContext loginContext = new LoginContext("exo", handler);
+ loginContext.login();
+
+ assertNotNull(identityRegistry.getIdentity("exo"));
+ assertEquals("exo", identityRegistry.getIdentity("exo").getUserId());
+
+ assertEquals(1, identityRegistry.getIdentity("exo").getGroups().size());
+
+ StateKey key = new SimpleStateKey("exo");
+ conversationRegistry.register(key, new ConversationState(identityRegistry.getIdentity("exo")));
+ assertNotNull(conversationRegistry.getState(key));
+
+ }
+
}
Modified: core/trunk/pom.xml
===================================================================
--- core/trunk/pom.xml 2011-04-20 10:44:24 UTC (rev 4261)
+++ core/trunk/pom.xml 2011-04-20 13:28:47 UTC (rev 4262)
@@ -131,6 +131,20 @@
<artifactId>exo.core.component.security.core</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.jboss.security</groupId>
+ <artifactId>jbosssx</artifactId>
+ <scope>provided</scope>
+ <version>2.0.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty.aggregate</groupId>
+ <artifactId>jetty-plus</artifactId>
+ <version>7.1.5.v20100705</version>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>javax.resource</groupId>
15 years
exo-jcr SVN: r4261 - ws/tags.
by do-not-reply@jboss.org
Author: pnedonosko
Date: 2011-04-20 06:44:24 -0400 (Wed, 20 Apr 2011)
New Revision: 4261
Removed:
ws/tags/exo.ws.frameworks.servlet-2.1.8-GA-bonita/
Log:
WS-264 useless tag created by Arnaud removed, use tag 2.1.8-bonita instead
15 years