exo-jcr SVN: r4395 - in core/trunk: exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate and 3 other directories.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-19 06:07:48 -0400 (Thu, 19 May 2011)
New Revision: 4395
Modified:
core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/MembershipHandler.java
core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/MembershipDAOImpl.java
core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/OrganizationServiceImpl.java
core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/MembershipDAOImpl.java
core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/OrganizationServiceImpl.java
core/trunk/exo.core.component.organization.jdbc/src/test/java/org/exoplatform/services/organization/TestOrganizationService.java
core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/ADMembershipDAOImpl.java
core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/MembershipDAOImpl.java
core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/OrganizationServiceImpl.java
Log:
EXOJCR-1009: check if membership type is present before membership is created
Modified: core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/MembershipHandler.java
===================================================================
--- core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/MembershipHandler.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.api/src/main/java/org/exoplatform/services/organization/MembershipHandler.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -54,10 +54,9 @@
* @param m The MembershipType of the memebership
* @param broadcast Broadcast the event if the value of the broadcast is
* 'true'
- * @throws Exception An exception is throwed if the method is fail to access
- * the database, a membership record with the same user , group and
- * membership type exisited or any listener fail to handle the
- * event.
+ * @throws Exception An exception is thrown if the method is fail to access
+ * the database, membership type not existed, a membership record with the same user,
+ * group and membership type existed, or any listener fail to handle the event.
*/
public void linkMembership(User user, Group group, MembershipType m, boolean broadcast) throws Exception;
Modified: core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/MembershipDAOImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/MembershipDAOImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/MembershipDAOImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -27,6 +27,7 @@
import org.exoplatform.services.organization.MembershipEventListenerHandler;
import org.exoplatform.services.organization.MembershipHandler;
import org.exoplatform.services.organization.MembershipType;
+import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.organization.impl.MembershipImpl;
import org.hibernate.Session;
@@ -66,10 +67,16 @@
private List listeners_;
- public MembershipDAOImpl(HibernateService service)
+ /**
+ * Organization service.
+ */
+ protected final OrganizationService orgService;
+
+ public MembershipDAOImpl(HibernateService service, OrganizationService orgService)
{
- service_ = service;
- listeners_ = new ListenerStack(5);
+ this.service_ = service;
+ this.orgService = orgService;
+ this.listeners_ = new ListenerStack(5);
}
public void addMembershipEventListener(MembershipEventListener listener)
@@ -84,26 +91,28 @@
public void createMembership(Membership m, boolean broadcast) throws Exception
{
+ if (orgService.getMembershipTypeHandler().findMembershipType(m.getMembershipType()) == null)
+ {
+ throw new InvalidNameException("Can not create membership record " + m.getId()
+ + " because membership type " + m.getMembershipType() + " is not exists.");
+ }
+
if (broadcast)
preSave(m, true);
Session session = service_.openSession();
- session.save(IdentifierUtil.generateUUID(m), m);
+ session.save(m);
if (broadcast)
postSave(m, true);
session.flush();
}
- // static void createMembershipEntries(Collection c, Session session) throws
- // Exception {
- // Iterator i = c.iterator() ;
- // while(i.hasNext()) {
- // Membership impl = (Membership) i.next() ;
- // session.save(impl, impl.getId());
- // }
- // }
-
public void linkMembership(User user, Group g, MembershipType mt, boolean broadcast) throws Exception
{
+ if (user == null)
+ {
+ throw new InvalidNameException("Can not create membership record because user is null");
+ }
+
if (g == null)
{
throw new InvalidNameException("Can not create membership record for " + user.getUserName()
@@ -117,25 +126,15 @@
}
MembershipImpl membership = new MembershipImpl();
- // User user
- // =(User)service_.findExactOne(session,UserHandlerImpl.queryFindUserByName,
- // userName);
membership.setUserName(user.getUserName());
membership.setMembershipType(mt.getName());
membership.setGroupId(g.getId());
- if (membership.getId() != null)
- throw new Exception(" Membership id isn't null!");
+ membership.setId(IdentifierUtil.generateUUID(membership));
+
if (findMembershipByUserGroupAndType(user.getUserName(), g.getId(), mt.getName()) != null)
return;
- String id = IdentifierUtil.generateUUID(membership);
- if (broadcast)
- preSave(membership, true);
- membership.setId(id);
- Session session = service_.openSession();
- session.save(membership);
- if (broadcast)
- postSave(membership, true);
- session.flush();
+
+ createMembership(membership, broadcast);
}
public void saveMembership(Membership m, boolean broadcast) throws Exception
Modified: core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/OrganizationServiceImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/OrganizationServiceImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/hibernate/OrganizationServiceImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -36,7 +36,7 @@
userDAO_ = new UserDAOImpl(hservice, cservice);
userProfileDAO_ = new UserProfileDAOImpl(hservice, cservice);
groupDAO_ = new GroupDAOImpl(hservice);
- membershipDAO_ = new MembershipDAOImpl(hservice);
membershipTypeDAO_ = new MembershipTypeDAOImpl(hservice);
+ membershipDAO_ = new MembershipDAOImpl(hservice, this);
}
}
Modified: core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/MembershipDAOImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/MembershipDAOImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/MembershipDAOImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -32,6 +32,7 @@
import org.exoplatform.services.organization.MembershipEventListener;
import org.exoplatform.services.organization.MembershipHandler;
import org.exoplatform.services.organization.MembershipType;
+import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import java.sql.Connection;
@@ -49,12 +50,16 @@
protected static Log log = ExoLogger.getLogger("exo.core.component.organization.jdbc.MembershipDAOImpl");
+ protected final OrganizationService service;
+
protected ListenerService listenerService_;
- public MembershipDAOImpl(ListenerService lService, ExoDatasource datasource, DBObjectMapper<MembershipImpl> mapper)
+ public MembershipDAOImpl(ListenerService lService, ExoDatasource datasource, DBObjectMapper<MembershipImpl> mapper,
+ OrganizationService service)
{
super(datasource, mapper, MembershipImpl.class);
- listenerService_ = lService;
+ this.service = service;
+ this.listenerService_ = lService;
}
public Membership createMembershipInstance()
@@ -64,6 +69,12 @@
public void createMembership(Membership membership, boolean broadcast) throws Exception
{
+ if (service.getMembershipTypeHandler().findMembershipType(membership.getMembershipType()) == null)
+ {
+ throw new InvalidNameException("Can not create membership record " + membership.getId()
+ + " because membership type " + membership.getMembershipType() + " not exists.");
+ }
+
MembershipImpl membershipImpl = (MembershipImpl)membership;
if (broadcast)
listenerService_.broadcast("organization.membership.preSave", this, membershipImpl);
@@ -75,6 +86,11 @@
public void linkMembership(User user, Group group, MembershipType mt, boolean broadcast) throws Exception
{
+ if (user == null)
+ {
+ throw new InvalidNameException("Can not create membership record because group is null");
+ }
+
if (group == null)
{
throw new InvalidNameException("Can not create membership record for " + user.getUserName()
@@ -239,5 +255,4 @@
{
throw new RuntimeException("This method is not supported anymore, please use the new api");
}
-
}
Modified: core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/OrganizationServiceImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/OrganizationServiceImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.jdbc/src/main/java/org/exoplatform/services/organization/jdbc/OrganizationServiceImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -45,7 +45,7 @@
groupDAO_ = new GroupDAOImpl(listenerService, datasource, new GroupMapper());
membershipTypeDAO_ = new MembershipTypeDAOImpl(listenerService, datasource, new MembershipTypeMapper());
- membershipDAO_ = new MembershipDAOImpl(listenerService, datasource, new MembershipMapper());
+ membershipDAO_ = new MembershipDAOImpl(listenerService, datasource, new MembershipMapper(), this);
userProfileDAO_ = new UserProfileDAOImpl(listenerService, datasource, new UserProfileMapper());
DBTableManager dbManager = datasource.getDBTableManager();
Modified: core/trunk/exo.core.component.organization.jdbc/src/test/java/org/exoplatform/services/organization/TestOrganizationService.java
===================================================================
--- core/trunk/exo.core.component.organization.jdbc/src/test/java/org/exoplatform/services/organization/TestOrganizationService.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.jdbc/src/test/java/org/exoplatform/services/organization/TestOrganizationService.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -26,6 +26,8 @@
import java.util.Calendar;
import java.util.List;
+import javax.naming.InvalidNameException;
+
/**
* Created by The eXo Platform SAS Author : Hoa Pham hoapham@exoplatform.com,phamvuxuanhoa(a)yahoo.com
* Oct 27, 2005
@@ -284,7 +286,13 @@
mt = mtHandler_.createMembershipTypeInstance();
mt.setName("membershipType3");
- membershipHandler_.linkMembership(userBenj, group2, mt, true);
+ try
+ {
+ membershipHandler_.linkMembership(userBenj, group2, mt, true);
+ }
+ catch (InvalidNameException e)
+ {
+ }
/*
* find all memberships in group2 Expect result: 4 membership: 3 for
Modified: core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/ADMembershipDAOImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/ADMembershipDAOImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/ADMembershipDAOImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -21,6 +21,7 @@
import org.exoplatform.services.ldap.LDAPService;
import org.exoplatform.services.organization.Group;
import org.exoplatform.services.organization.Membership;
+import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.impl.MembershipImpl;
import java.util.ArrayList;
@@ -50,10 +51,10 @@
* @param ad See {@link ADSearchBySID}
* @throws Exception if any errors occurs
*/
- public ADMembershipDAOImpl(LDAPAttributeMapping ldapAttrMapping, LDAPService ldapService, ADSearchBySID ad)
- throws Exception
+ public ADMembershipDAOImpl(LDAPAttributeMapping ldapAttrMapping, LDAPService ldapService, ADSearchBySID ad,
+ OrganizationService service) throws Exception
{
- super(ldapAttrMapping, ldapService);
+ super(ldapAttrMapping, ldapService, service);
adSearch = ad;
}
@@ -184,7 +185,7 @@
results = ctx.search(userDN, filter, constraints);
while (results.hasMore())
{
- SearchResult sr = (SearchResult)results.next();
+ SearchResult sr = results.next();
Attributes attrs = sr.getAttributes();
Attribute attr = attrs.get("tokenGroups");
for (int x = 0; x < attr.size(); x++)
Modified: core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/MembershipDAOImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/MembershipDAOImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/MembershipDAOImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -27,6 +27,7 @@
import org.exoplatform.services.organization.MembershipEventListenerHandler;
import org.exoplatform.services.organization.MembershipHandler;
import org.exoplatform.services.organization.MembershipType;
+import org.exoplatform.services.organization.OrganizationService;
import org.exoplatform.services.organization.User;
import org.exoplatform.services.organization.impl.MembershipImpl;
@@ -64,19 +65,28 @@
* See {@link MembershipEventListener}.
*/
protected List<MembershipEventListener> listeners;
+
+ /**
+ * Organization service;
+ */
+ protected final OrganizationService service;
/**
* @param ldapAttrMapping
* mapping LDAP attributes to eXo organization service items (users, groups, etc)
* @param ldapService
* {@link LDAPService}
+ * @param service
+ * Organization service implementation covering the handler.
* @throws Exception
* if any errors occurs
*/
- public MembershipDAOImpl(LDAPAttributeMapping ldapAttrMapping, LDAPService ldapService) throws Exception
+ public MembershipDAOImpl(LDAPAttributeMapping ldapAttrMapping, LDAPService ldapService, OrganizationService service)
+ throws Exception
{
super(ldapAttrMapping, ldapService);
this.listeners = new ArrayList<MembershipEventListener>(3);
+ this.service = service;
}
/**
@@ -104,6 +114,12 @@
LdapContext ctx = ldapService.getLdapContext();
try
{
+ if (service.getMembershipTypeHandler().findMembershipType(m.getMembershipType()) == null)
+ {
+ throw new InvalidNameException("Can not create membership record " + m.getId()
+ + " because membership type " + m.getMembershipType() + " is not exists.");
+ }
+
for (int err = 0;; err++)
{
try
@@ -171,6 +187,11 @@
*/
public void linkMembership(User user, Group group, MembershipType mt, boolean broadcast) throws Exception
{
+ if (user == null)
+ {
+ throw new InvalidNameException("Can not create membership record because user is null");
+ }
+
if (group == null)
{
throw new InvalidNameException("Can not create membership record for " + user.getUserName()
@@ -182,7 +203,7 @@
throw new InvalidNameException("Can not create membership record for " + user.getUserName()
+ " because membership type is null");
}
-
+
MembershipImpl membership = new MembershipImpl();
membership.setMembershipType(mt.getName());
membership.setUserName(user.getUserName());
Modified: core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/OrganizationServiceImpl.java
===================================================================
--- core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/OrganizationServiceImpl.java 2011-05-19 08:09:58 UTC (rev 4394)
+++ core/trunk/exo.core.component.organization.ldap/src/main/java/org/exoplatform/services/organization/ldap/OrganizationServiceImpl.java 2011-05-19 10:07:48 UTC (rev 4395)
@@ -53,7 +53,7 @@
// ADSearchBySID adSearch = new ADSearchBySID(ldapAttrMapping, ldapService);
ADSearchBySID adSearch = new ADSearchBySID(ldapAttrMapping);
groupDAO_ = new ADGroupDAOImpl(ldapAttrMapping, ldapService, adSearch);
- membershipDAO_ = new ADMembershipDAOImpl(ldapAttrMapping, ldapService, adSearch);
+ membershipDAO_ = new ADMembershipDAOImpl(ldapAttrMapping, ldapService, adSearch, this);
}
else
{
@@ -61,7 +61,7 @@
// ldapAttrMapping.userDNKey = param.getValue();
userDAO_ = new UserDAOImpl(ldapAttrMapping, ldapService);
groupDAO_ = new GroupDAOImpl(ldapAttrMapping, ldapService);
- membershipDAO_ = new MembershipDAOImpl(ldapAttrMapping, ldapService);
+ membershipDAO_ = new MembershipDAOImpl(ldapAttrMapping, ldapService, this);
}
// userProfileHandler_ = new UserProfileHandlerImpl(ldapAttrMapping, ldapService) ;
userProfileDAO_ = new UserProfileDAOImpl(hservice, cservice);
13 years
exo-jcr SVN: r4394 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-19 04:09:58 -0400 (Thu, 19 May 2011)
New Revision: 4394
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
Log:
EXOJCR-1352: Warning if wrong IL database configuration changed
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-19 07:50:36 UTC (rev 4393)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-19 08:09:58 UTC (rev 4394)
@@ -930,7 +930,7 @@
{
if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
{
- LOG.warn("Wrong RDBMS configuration, please check and set READ_COMMITTED or higher isolation level.");
+ LOG.warn("Wrong default isolation level, please set the default isolation level to READ_COMMITTED or higher. Other default isolation levels are not supported.");
}
}
catch (SQLException e)
13 years
exo-jcr SVN: r4393 - jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-19 03:50:36 -0400 (Thu, 19 May 2011)
New Revision: 4393
Modified:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch
Log:
JCR-1618: patch updated
Modified: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch 2011-05-19 06:03:47 UTC (rev 4392)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch 2011-05-19 07:50:36 UTC (rev 4393)
@@ -61,7 +61,7 @@
+ {
+ if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
+ {
-+ LOG.warn("Wrong RDBMS configuration, please check and set READ_COMMITTED or higher isolation level.");
++ LOG.warn("Wrong default isolation level, please set the default isolation level to READ_COMMITTED or higher. Other default isolation levels are not supported");
+ }
+ }
+ catch (SQLException e)
13 years
exo-jcr SVN: r4392 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2011-05-19 02:03:47 -0400 (Thu, 19 May 2011)
New Revision: 4392
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
Log:
EXOJCR-1343 : The patch for avoid data accesses in case of new created nodes was checked and committed.
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-05-18 15:17:22 UTC (rev 4391)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java 2011-05-19 06:03:47 UTC (rev 4392)
@@ -966,7 +966,7 @@
public int getLastOrderNumber(NodeData parent) throws RepositoryException
{
int lastOrderNumber = changesLog.getLastChildOrderNumber(parent.getIdentifier());
- int lastPersistedNodeOrderNumber = transactionableManager.getLastOrderNumber(parent);
+ int lastPersistedNodeOrderNumber = isNew(parent.getIdentifier()) ? -1 : transactionableManager.getLastOrderNumber(parent);
return Math.max(lastPersistedNodeOrderNumber, lastOrderNumber);
}
@@ -977,7 +977,7 @@
public int getChildNodesCount(NodeData parent) throws RepositoryException
{
int childsCount =
- changesLog.getChildNodesCount(parent.getIdentifier()) + transactionableManager.getChildNodesCount(parent);
+ changesLog.getChildNodesCount(parent.getIdentifier()) + (isNew(parent.getIdentifier()) ? 0 : transactionableManager.getChildNodesCount(parent));
if (childsCount < 0)
{
throw new InvalidItemStateException("Node's child nodes were changed in another Session "
@@ -1992,6 +1992,10 @@
}
else
{
+ if (isNew(rootData.getIdentifier()))
+ {
+ return Collections.emptyList();
+ }
return dataManager.getChildNodesData((NodeData)rootData);
}
}
@@ -2121,7 +2125,7 @@
throws RepositoryException
{
- if (parent.isNode())
+ if (parent.isNode() && !isNew(parent.getIdentifier()))
{
if (action != MERGE_PROPS)
{
13 years
exo-jcr SVN: r4391 - jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618.
by do-not-reply@jboss.org
Author: nzamosenchuk
Date: 2011-05-18 11:17:22 -0400 (Wed, 18 May 2011)
New Revision: 4391
Modified:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch
Log:
JCR-1618 : patch updated
Modified: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch 2011-05-18 14:19:40 UTC (rev 4390)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1618/JCR-1618.patch 2011-05-18 15:17:22 UTC (rev 4391)
@@ -1,26 +1,77 @@
+Index: exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml
+===================================================================
+--- exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml (revision 4390)
++++ exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml (working copy)
+@@ -96,18 +96,6 @@
+ <programlisting>boolean isCheckSNSNewConnection();
+ </programlisting>
+
+- <important>
+- <title>New connection for SNS</title>
+-
+- <para>It is neccessary to check the name of nodes when they have the
+- same names. Usually, new Workspace Storage Connection is used for this
+- purpose. The improvement came from JDBC Workspace Data Container,
+- which shows a better performance on Oracle RDBMS when using new
+- connection for checking SNS existence. But later, this causes to
+- deadlocks on Sybase RDBMS, so this feature is made as an optional and
+- configurable one.</para>
+- </important>
+-
+ <para>Container initialization is only based on a configuration. After
+ the container has been created, it's not possible to change parameters.
+ Configuration consists of implementation class and set of properties and
Index: exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
===================================================================
---- exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml (revision 4367)
-+++ exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml (revision 4368)
-@@ -56,11 +56,16 @@
+--- exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml (revision 4390)
++++ exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml (working copy)
+@@ -56,6 +56,13 @@
</listitem>
</itemizedlist></para>
-- <para>Each database software supports ANSI SQL standards but also has its
-- own specifics. So, each database has its own configuration in eXo JCR as a
-- database dialect parameter. If you need a more detailed configuration of
-- the database, it's possible to do that by editing the metadata SQL-script
-- files.</para>
-+ <para><note>
-+ <para>Please note, that JCR supports only READ_COMMITED isolation
-+ level and any other RDBMS configurations can cause some side-effects
-+ and issues. So, please, make sure proper isolation level is configured
-+ on database server side.</para>
-+ </note>Each database software supports ANSI SQL standards but also has
-+ its own specifics. So, each database has its own configuration in eXo JCR
-+ as a database dialect parameter. If you need a more detailed configuration
-+ of the database, it's possible to do that by editing the metadata
-+ SQL-script files.</para>
++ <note>
++ <para>Please note, that JCR requires at least READ_COMMITED isolation
++ level and other RDBMS configurations can cause some side-effects and
++ issues. So, please, make sure proper isolation level is configured on
++ database server side.</para>
++ </note>
++
+ <para>Each database software supports ANSI SQL standards but also has its
+ own specifics. So, each database has its own configuration in eXo JCR as a
+ database dialect parameter. If you need a more detailed configuration of
+Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
+===================================================================
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java (revision 4390)
++++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java (working copy)
+@@ -370,7 +370,7 @@
+ }
+ catch (RepositoryConfigurationException e)
+ {
+- this.checkSNSNewConnection = DBConstants.DB_DIALECT_SYBASE.equals(this.dbDialect) ? false : true;
++ this.checkSNSNewConnection = false;
+ }
- <para>In case the non-ANSI node name is used, it's necessary to use a
- database with MultiLanguage support[TODO link to MultiLanguage]. Some JDBC
+ // ------------- Values swap config ------------------
+@@ -836,6 +836,22 @@
+ */
+ public void start()
+ {
++ // if isolation level lesser then TRANSACTION_READ_COMMITTED, print a warning
++ try
++ {
++ if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
++ {
++ LOG.warn("Wrong RDBMS configuration, please check and set READ_COMMITTED or higher isolation level.");
++ }
++ }
++ catch (SQLException e)
++ {
++ LOG.error("Error checking isolation level configuration.", e);
++ }
++ catch (RepositoryException e)
++ {
++ LOG.error("Error checking isolation level configuration.", e);
++ }
+ }
+
+ /**
13 years
exo-jcr SVN: r4390 - in jcr/trunk: exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr and 1 other directories.
by do-not-reply@jboss.org
Author: nzamosenchuk
Date: 2011-05-18 10:19:40 -0400 (Wed, 18 May 2011)
New Revision: 4390
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml
Log:
EXOJCR-1352: Warning if wrong IL database configuration added, Use-sns-new-connection set to false by default.
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-18 14:12:54 UTC (rev 4389)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-18 14:19:40 UTC (rev 4390)
@@ -420,9 +420,8 @@
}
catch (RepositoryConfigurationException e)
{
- this.checkSNSNewConnection =
- DBConstants.DB_DIALECT_SYBASE.equals(this.dbDialect)
- || DBConstants.DB_DIALECT_HSQLDB.equals(this.dbDialect) ? false : true;
+ // don't use new connection by default
+ this.checkSNSNewConnection = false;
}
// ------------- Values swap config ------------------
@@ -890,7 +889,7 @@
{
return containerName;
}
-
+
/**
* {@inheritDoc}
*/
@@ -926,6 +925,22 @@
*/
public void start()
{
+ // if isolation level lesser then TRANSACTION_READ_COMMITTED, print a warning
+ try
+ {
+ if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
+ {
+ LOG.warn("Wrong RDBMS configuration, please check and set READ_COMMITTED or higher isolation level.");
+ }
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Error checking isolation level configuration.", e);
+ }
+ catch (RepositoryException e)
+ {
+ LOG.error("Error checking isolation level configuration.", e);
+ }
}
/**
@@ -1279,7 +1294,7 @@
restoreTableRule.setConvertColumnIndex(convertColumnIndex);
}
tables.put(dstTableName, restoreTableRule);
-
+
restorers.add(new DBRestore(storageDir, jdbcConn, tables, wsConfig, swapCleaner));
// prepare value storage restorer
@@ -1394,11 +1409,11 @@
{
if (isReindexingSupport())
{
- return new JdbcNodeDataIndexingIterator(connFactory, pageSize);
+ return new JdbcNodeDataIndexingIterator(connFactory, pageSize);
}
throw new UnsupportedOperationException(
- "The method getNodeDataIndexingIterator is not supported for this type of connection "
- + "use the complex queries instead");
+ "The method getNodeDataIndexingIterator is not supported for this type of connection "
+ + "use the complex queries instead");
}
/**
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml 2011-05-18 14:12:54 UTC (rev 4389)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/configuration/jdbc-data-container-config.xml 2011-05-18 14:19:40 UTC (rev 4390)
@@ -57,10 +57,10 @@
</itemizedlist></para>
<para><note>
- <para>Please note, that JCR supports only READ_COMMITED isolation
- level and any other RDBMS configurations can cause some side-effects
- and issues. So, please, make sure proper isolation level is configured
- on database server side.</para>
+ <para>Please note, that JCR requires at least READ_COMMITED isolation
+ level and other RDBMS configurations can cause some side-effects and
+ issues. So, please, make sure proper isolation level is configured on
+ database server side.</para>
</note>Each database software supports ANSI SQL standards but also has
its own specifics. So, each database has its own configuration in eXo JCR
as a database dialect parameter. If you need a more detailed configuration
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml 2011-05-18 14:12:54 UTC (rev 4389)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/data-container.xml 2011-05-18 14:19:40 UTC (rev 4390)
@@ -96,18 +96,6 @@
<programlisting>boolean isCheckSNSNewConnection();
</programlisting>
- <important>
- <title>New connection for SNS</title>
-
- <para>It is neccessary to check the name of nodes when they have the
- same names. Usually, new Workspace Storage Connection is used for this
- purpose. The improvement came from JDBC Workspace Data Container,
- which shows a better performance on Oracle RDBMS when using new
- connection for checking SNS existence. But later, this causes to
- deadlocks on Sybase RDBMS, so this feature is made as an optional and
- configurable one.</para>
- </important>
-
<para>Container initialization is only based on a configuration. After
the container has been created, it's not possible to change parameters.
Configuration consists of implementation class and set of properties and
13 years
exo-jcr SVN: r4389 - in jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr: impl/dataflow/persistent/infinispan and 1 other directories.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2011-05-18 10:12:54 -0400 (Wed, 18 May 2011)
New Revision: 4389
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/persistent/WorkspaceStorageCache.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
Log:
EXOJCR-1351: Allow to manage the JCR Cache from JMX
getSize, isEnabled and clean are now available through JMX
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/persistent/WorkspaceStorageCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/persistent/WorkspaceStorageCache.java 2011-05-18 05:08:48 UTC (rev 4388)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/persistent/WorkspaceStorageCache.java 2011-05-18 14:12:54 UTC (rev 4389)
@@ -18,6 +18,10 @@
*/
package org.exoplatform.services.jcr.dataflow.persistent;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
+import org.exoplatform.management.jmx.annotations.NameTemplate;
+import org.exoplatform.management.jmx.annotations.Property;
import org.exoplatform.services.jcr.datamodel.ItemData;
import org.exoplatform.services.jcr.datamodel.ItemType;
import org.exoplatform.services.jcr.datamodel.NodeData;
@@ -34,6 +38,8 @@
* @author <a href="mailto:geaz@users.sourceforge.net">Gennady Azarenkov</a>
* @version $Id: WorkspaceStorageCache.java 13869 2008-05-05 08:40:10Z pnedonosko $
*/
+@Managed
+@NameTemplate(@Property(key = "service", value = "Cache"))
public interface WorkspaceStorageCache extends MandatoryItemsPersistenceListener
{
@@ -172,6 +178,8 @@
*
* @return enabled status flag, if true then cache is enabled
*/
+ @Managed
+ @ManagedDescription("Indicates whether the cache is enabled or not")
boolean isEnabled();
/**
@@ -179,6 +187,8 @@
*
* @return long value
*/
+ @Managed
+ @ManagedDescription("Indicates the total amount of items into the cache")
long getSize();
/**
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2011-05-18 05:08:48 UTC (rev 4388)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2011-05-18 14:12:54 UTC (rev 4389)
@@ -20,6 +20,8 @@
import org.exoplatform.commons.utils.SecurityHelper;
import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
import org.exoplatform.services.jcr.access.AccessControlList;
import org.exoplatform.services.jcr.config.CacheEntry;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
@@ -1179,6 +1181,8 @@
/**
* {@inheritDoc}
*/
+ @Managed
+ @ManagedDescription("Remove all the existing items from the cache")
public void clean() throws BackupException
{
if (cache.getStatus() == ComponentStatus.RUNNING)
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-05-18 05:08:48 UTC (rev 4388)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-05-18 14:12:54 UTC (rev 4389)
@@ -19,6 +19,8 @@
package org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache;
import org.exoplatform.container.configuration.ConfigurationManager;
+import org.exoplatform.management.annotations.Managed;
+import org.exoplatform.management.annotations.ManagedDescription;
import org.exoplatform.services.jcr.access.AccessControlList;
import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
import org.exoplatform.services.jcr.config.WorkspaceEntry;
@@ -52,8 +54,8 @@
import org.jboss.cache.CacheStatus;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
+import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.config.EvictionRegionConfig;
-import org.jboss.cache.config.Configuration.CacheMode;
import org.jboss.cache.eviction.ExpirationAlgorithmConfig;
import org.picocontainer.Startable;
@@ -1581,6 +1583,8 @@
/**
* {@inheritDoc}
*/
+ @Managed
+ @ManagedDescription("Remove all the existing items from the cache")
public void clean() throws BackupException
{
cleanCache();
13 years
exo-jcr SVN: r4388 - in jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core: src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache and 3 other directories.
by do-not-reply@jboss.org
Author: tkobayas(a)redhat.com
Date: 2011-05-18 01:08:48 -0400 (Wed, 18 May 2011)
New Revision: 4388
Added:
jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml
Modified:
jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/pom.xml
jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java
Log:
[JBEPP-878] JCR addNode within a transaction causes javax.transaction.HeuristicMixedException in the first access to the node
Modified: jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/pom.xml
===================================================================
--- jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/pom.xml 2011-05-18 02:02:59 UTC (rev 4387)
+++ jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/pom.xml 2011-05-18 05:08:48 UTC (rev 4388)
@@ -388,6 +388,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/exoplatform/services/jcr/api/**/Test*.java</include>
@@ -574,6 +589,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>
@@ -646,6 +676,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 -->
@@ -723,6 +768,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.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
--- jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-05-18 02:02:59 UTC (rev 4387)
+++ jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-05-18 05:08:48 UTC (rev 4388)
@@ -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.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-05-18 02:02:59 UTC (rev 4387)
+++ jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-05-18 05:08:48 UTC (rev 4388)
@@ -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.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java
===================================================================
--- jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java 2011-05-18 02:02:59 UTC (rev 4387)
+++ jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/search/TestSearch.java 2011-05-18 05:08:48 UTC (rev 4388)
@@ -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.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
===================================================================
--- jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java (rev 0)
+++ jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java 2011-05-18 05:08:48 UTC (rev 4388)
@@ -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";
+ }
+ };
+}
Added: jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml
===================================================================
--- jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml (rev 0)
+++ jcr/branches/1.12.6-GA_JBEPP-878/exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml 2011-05-18 05:08:48 UTC (rev 4388)
@@ -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>
13 years
exo-jcr SVN: r4387 - jcr/branches.
by do-not-reply@jboss.org
Author: tkobayas(a)redhat.com
Date: 2011-05-17 22:02:59 -0400 (Tue, 17 May 2011)
New Revision: 4387
Added:
jcr/branches/1.12.6-GA_JBEPP-878/
Log:
[JBEPP-878] JCR addNode within a transaction causes javax.transaction.HeuristicMixedException in the first access to the node
13 years
exo-jcr SVN: r4385 - in jcr/branches/1.12.x/patch/1.12.9-GA: JCR-1630 and 1 other directory.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-17 08:30:18 -0400 (Tue, 17 May 2011)
New Revision: 4385
Added:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1630/
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1630/JCR-1630.patch
Log:
JCR-1630: patch proposed
Added: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1630/JCR-1630.patch
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1630/JCR-1630.patch (rev 0)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1630/JCR-1630.patch 2011-05-17 12:30:18 UTC (rev 4385)
@@ -0,0 +1,329 @@
+Index: exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestMove.java
+===================================================================
+--- exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestMove.java (revision 4383)
++++ exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestMove.java (working copy)
+@@ -182,6 +182,98 @@
+
+ }
+
++ public void testMoveHeaderBeginsFromWorkspaceName() throws Exception
++ {
++ String content = TestUtils.getFileContent();
++ String filename = TestUtils.getFileName();
++ InputStream inputStream = new ByteArrayInputStream(content.getBytes());
++ TestUtils.addContent(session, filename, inputStream, defaultFileNodeType, "");
++ String destFilename = TestUtils.getFileName();
++
++ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
++
++ headers.add(ExtHttpHeaders.DESTINATION, WORKSPACE + destFilename);
++ ContainerResponse response = service(WebDAVMethods.MOVE, getPathWS() + filename, host, headers, null);
++
++ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(destFilename)));
++
++ Node nodeDest = session.getRootNode().getNode(TextUtil.relativizePath(destFilename));
++ assertTrue(nodeDest.hasNode("jcr:content"));
++
++ Node nodeDestContent = nodeDest.getNode("jcr:content");
++ assertTrue(nodeDestContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamDest = (ByteArrayInputStream)nodeDestContent.getProperty("jcr:data").getStream();
++ String getContentDest = TestUtils.stream2string(streamDest, null);
++ assertEquals(content, getContentDest);
++ assertFalse(session.getRootNode().hasNode(TextUtil.relativizePath(filename)));
++ }
++
++ public void testMoveToFolderWithSpace() throws Exception
++ {
++ String folderNameWithSpace = "new folder - testMoveToFolderWithSpace";
++ session.getRootNode().addNode(folderNameWithSpace, "nt:folder");
++ session.save();
++
++ String content = TestUtils.getFileContent();
++ String filename = TestUtils.getFileName();
++ InputStream inputStream = new ByteArrayInputStream(content.getBytes());
++ TestUtils.addContent(session, filename, inputStream, defaultFileNodeType, "");
++ String destFilename = "/" + folderNameWithSpace + TestUtils.getFileName();
++
++ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
++
++ headers.add(ExtHttpHeaders.DESTINATION, WORKSPACE + destFilename);
++ ContainerResponse response = service(WebDAVMethods.MOVE, getPathWS() + filename, host, headers, null);
++
++ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(destFilename)));
++
++ Node nodeDest = session.getRootNode().getNode(TextUtil.relativizePath(destFilename));
++ assertTrue(nodeDest.hasNode("jcr:content"));
++
++ Node nodeDestContent = nodeDest.getNode("jcr:content");
++ assertTrue(nodeDestContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamDest = (ByteArrayInputStream)nodeDestContent.getProperty("jcr:data").getStream();
++ String getContentDest = TestUtils.stream2string(streamDest, null);
++ assertEquals(content, getContentDest);
++ assertFalse(session.getRootNode().hasNode(TextUtil.relativizePath(filename)));
++ }
++
++ public void testMoveToFolderWithSpaceUnescapedChars() throws Exception
++ {
++ String folderNameWithSpace = "new folder - testMoveToFolderWithSpaceUnescapedChars";
++ session.getRootNode().addNode(folderNameWithSpace, "nt:folder");
++ session.save();
++
++ String content = TestUtils.getFileContent();
++ String filename = TestUtils.getFileName();
++ InputStream inputStream = new ByteArrayInputStream(content.getBytes());
++ TestUtils.addContent(session, filename, inputStream, defaultFileNodeType, "");
++ String destFilename = TextUtil.unescape("/" + folderNameWithSpace + TestUtils.getFileName(), '%');
++
++ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
++
++ headers.add(ExtHttpHeaders.DESTINATION, WORKSPACE + destFilename);
++ ContainerResponse response = service(WebDAVMethods.MOVE, getPathWS() + filename, host, headers, null);
++
++ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(destFilename)));
++
++ Node nodeDest = session.getRootNode().getNode(TextUtil.relativizePath(destFilename));
++ assertTrue(nodeDest.hasNode("jcr:content"));
++
++ Node nodeDestContent = nodeDest.getNode("jcr:content");
++ assertTrue(nodeDestContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamDest = (ByteArrayInputStream)nodeDestContent.getProperty("jcr:data").getStream();
++ String getContentDest = TestUtils.stream2string(streamDest, null);
++ assertEquals(content, getContentDest);
++ assertFalse(session.getRootNode().hasNode(TextUtil.relativizePath(filename)));
++ }
++
+ @Override
+ protected String getRepositoryName()
+ {
+Index: exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestCopy.java
+===================================================================
+--- exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestCopy.java (revision 4383)
++++ exo.jcr.component.webdav/src/test/java/org/exoplatform/services/jcr/webdav/command/TestCopy.java (working copy)
+@@ -194,9 +194,130 @@
+ ContainerResponse response = service(WebDAVMethods.COPY, getPathWS() + filename, host, headers, null);
+ // check if operation completed successfully, we expect a new resource to be created
+ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ }
+
++ public void testCopyDestinationHeaderBeginsFromWorkspaceName() throws Exception
++ {
++ String content = TestUtils.getFileContent();
++ String filename = TestUtils.getFileName();
++ InputStream inputStream = new ByteArrayInputStream(content.getBytes());
++ TestUtils.addContent(session, filename, inputStream, defaultFileNodeType, "");
++ String destFilename = TestUtils.getFileName();
++
++ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
++ headers.add(ExtHttpHeaders.DESTINATION, WORKSPACE + destFilename);
++
++ ContainerResponse response = service(WebDAVMethods.COPY, getPathWS() + filename, host, headers, null);
++
++ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(destFilename)));
++
++ Node nodeDest = session.getRootNode().getNode(TextUtil.relativizePath(destFilename));
++ assertTrue(nodeDest.hasNode("jcr:content"));
++
++ Node nodeDestContent = nodeDest.getNode("jcr:content");
++ assertTrue(nodeDestContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamDest = (ByteArrayInputStream)nodeDestContent.getProperty("jcr:data").getStream();
++ String getContentDest = TestUtils.stream2string(streamDest, null);
++ assertEquals(content, getContentDest);
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(filename)));
++
++ Node nodeBase = session.getRootNode().getNode(TextUtil.relativizePath(filename));
++ assertTrue(nodeBase.hasNode("jcr:content"));
++
++ Node nodeBaseContent = nodeBase.getNode("jcr:content");
++ assertTrue(nodeBaseContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamBase = (ByteArrayInputStream)nodeBaseContent.getProperty("jcr:data").getStream();
++ String getContentBase = TestUtils.stream2string(streamBase, null);
++ assertEquals(content, getContentBase);
+ }
+
++ public void testCopyToFolderWithSpace() throws Exception
++ {
++ String folderNameWithSpace = "new folder - testCopyToFolderWithSpace";
++ session.getRootNode().addNode(folderNameWithSpace, "nt:folder");
++ session.save();
++
++ String content = TestUtils.getFileContent();
++ String filename = TestUtils.getFileName();
++ InputStream inputStream = new ByteArrayInputStream(content.getBytes());
++ TestUtils.addContent(session, filename, inputStream, defaultFileNodeType, "");
++ String destFilename = "/" + folderNameWithSpace + TestUtils.getFileName();
++
++ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
++ headers.add(ExtHttpHeaders.DESTINATION, WORKSPACE + destFilename);
++
++ ContainerResponse response = service(WebDAVMethods.COPY, getPathWS() + filename, host, headers, null);
++
++ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(destFilename)));
++
++ Node nodeDest = session.getRootNode().getNode(TextUtil.relativizePath(destFilename));
++ assertTrue(nodeDest.hasNode("jcr:content"));
++
++ Node nodeDestContent = nodeDest.getNode("jcr:content");
++ assertTrue(nodeDestContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamDest = (ByteArrayInputStream)nodeDestContent.getProperty("jcr:data").getStream();
++ String getContentDest = TestUtils.stream2string(streamDest, null);
++ assertEquals(content, getContentDest);
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(filename)));
++
++ Node nodeBase = session.getRootNode().getNode(TextUtil.relativizePath(filename));
++ assertTrue(nodeBase.hasNode("jcr:content"));
++
++ Node nodeBaseContent = nodeBase.getNode("jcr:content");
++ assertTrue(nodeBaseContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamBase = (ByteArrayInputStream)nodeBaseContent.getProperty("jcr:data").getStream();
++ String getContentBase = TestUtils.stream2string(streamBase, null);
++ assertEquals(content, getContentBase);
++ }
++
++ public void testCopyToFolderWithSpaceUnescapedChars() throws Exception
++ {
++ String folderNameWithSpace = "new folder - testCopyToFolderWithSpaceUnescapedChars";
++ session.getRootNode().addNode(folderNameWithSpace, "nt:folder");
++ session.save();
++
++ String content = TestUtils.getFileContent();
++ String filename = TestUtils.getFileName();
++ InputStream inputStream = new ByteArrayInputStream(content.getBytes());
++ TestUtils.addContent(session, filename, inputStream, defaultFileNodeType, "");
++ String destFilename = TextUtil.unescape("/" + folderNameWithSpace + TestUtils.getFileName(), '%');
++
++ MultivaluedMap<String, String> headers = new MultivaluedMapImpl();
++ headers.add(ExtHttpHeaders.DESTINATION, WORKSPACE + destFilename);
++
++ ContainerResponse response = service(WebDAVMethods.COPY, getPathWS() + filename, host, headers, null);
++
++ assertEquals(HTTPStatus.CREATED, response.getStatus());
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(destFilename)));
++
++ Node nodeDest = session.getRootNode().getNode(TextUtil.relativizePath(destFilename));
++ assertTrue(nodeDest.hasNode("jcr:content"));
++
++ Node nodeDestContent = nodeDest.getNode("jcr:content");
++ assertTrue(nodeDestContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamDest = (ByteArrayInputStream)nodeDestContent.getProperty("jcr:data").getStream();
++ String getContentDest = TestUtils.stream2string(streamDest, null);
++ assertEquals(content, getContentDest);
++ assertTrue(session.getRootNode().hasNode(TextUtil.relativizePath(filename)));
++
++ Node nodeBase = session.getRootNode().getNode(TextUtil.relativizePath(filename));
++ assertTrue(nodeBase.hasNode("jcr:content"));
++
++ Node nodeBaseContent = nodeBase.getNode("jcr:content");
++ assertTrue(nodeBaseContent.hasProperty("jcr:data"));
++
++ ByteArrayInputStream streamBase = (ByteArrayInputStream)nodeBaseContent.getProperty("jcr:data").getStream();
++ String getContentBase = TestUtils.stream2string(streamBase, null);
++ assertEquals(content, getContentBase);
++ }
++
+ @Override
+ protected String getRepositoryName()
+ {
+Index: exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java
+===================================================================
+--- exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java (revision 4383)
++++ exo.jcr.component.webdav/src/main/java/org/exoplatform/services/jcr/webdav/WebDavServiceImpl.java (working copy)
+@@ -72,6 +72,7 @@
+ import java.lang.annotation.Annotation;
+ import java.lang.reflect.Method;
+ import java.net.URI;
++import java.net.URISyntaxException;
+ import java.net.URLEncoder;
+ import java.util.ArrayList;
+ import java.util.HashMap;
+@@ -384,9 +385,12 @@
+ try
+ {
+ String serverURI = uriInfo.getBaseUriBuilder().path(getClass()).path(repoName).build().toString();
+- URI dest = new URI(destinationHeader);
+- URI base = new URI(serverURI);
+
++ // destinationHeader could begins from workspace name (passed from cms
++ // WebDAVServiceImpl) and doesn't contain neither host no repository name
++ URI dest = buildURI(destinationHeader);
++ URI base = buildURI(serverURI);
++
+ String destPath = dest.getPath();
+ int repoIndex = destPath.indexOf(repoName);
+
+@@ -395,12 +399,12 @@
+ // or destination header is malformed
+ // we return BAD_GATEWAY(502) HTTP status
+ // more info here http://www.webdav.org/specs/rfc2518.html#METHOD_COPY
+- if (!base.getHost().equals(dest.getHost()) || repoIndex == -1)
++ if (dest.getHost() != null && !base.getHost().equals(dest.getHost()))
+ {
+ return Response.status(HTTPStatus.BAD_GATEWAY).entity("Bad Gateway").build();
+ }
+
+- destPath = normalizePath(dest.getPath().substring(repoIndex + repoName.length() + 1));
++ destPath = normalizePath(repoIndex == -1 ? destPath : destPath.substring(repoIndex + repoName.length() + 1));
+
+ String srcWorkspace = workspaceName(repoPath);
+ String srcNodePath = path(repoPath);
+@@ -776,8 +780,10 @@
+ {
+ String serverURI = uriInfo.getBaseUriBuilder().path(getClass()).path(repoName).build().toString();
+
+- URI dest = new URI(destinationHeader);
+- URI base = new URI(serverURI);
++ // destinationHeader could begins from workspace name (passed from cms
++ // WebDAVServiceImpl) and doesn't contain neither host no repository name
++ URI dest = buildURI(destinationHeader);
++ URI base = buildURI(serverURI);
+
+ String destPath = dest.getPath();
+ int repoIndex = destPath.indexOf(repoName);
+@@ -787,14 +793,12 @@
+ // or destination header is malformed
+ // we return BAD_GATEWAY(502) HTTP status
+ // more info here http://www.webdav.org/specs/rfc2518.html#METHOD_MOVE
+- if (!base.getHost().equals(dest.getHost()) || repoIndex == -1)
+-
+- if (!destinationHeader.startsWith(serverURI))
++ if (dest.getHost() != null && !base.getHost().equals(dest.getHost()))
+ {
+ return Response.status(HTTPStatus.BAD_GATEWAY).entity("Bad Gateway").build();
+ }
+
+- destPath = normalizePath(dest.getPath().substring(repoIndex + repoName.length() + 1));
++ destPath = normalizePath(repoIndex == -1 ? destPath : destPath.substring(repoIndex + repoName.length() + 1));
+
+ String destWorkspace = workspaceName(destPath);
+ String destNodePath = path(destPath);
+@@ -1335,4 +1339,18 @@
+ return lockTokens;
+ }
+
++ /**
++ * Build URI from string.
++ */
++ private URI buildURI(String path) throws URISyntaxException
++ {
++ try
++ {
++ return new URI(path);
++ }
++ catch (URISyntaxException e)
++ {
++ return new URI(TextUtil.escape(path, '%', true));
++ }
++ }
+ }
13 years