exo-jcr SVN: r4435 - jcr/trunk/exo.jcr.component.core.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-27 03:49:03 -0400 (Fri, 27 May 2011)
New Revision: 4435
Modified:
jcr/trunk/exo.jcr.component.core/pom.xml
Log:
EXOJCR-1360: move test back to exclude list
Modified: jcr/trunk/exo.jcr.component.core/pom.xml
===================================================================
--- jcr/trunk/exo.jcr.component.core/pom.xml 2011-05-26 16:49:50 UTC (rev 4434)
+++ jcr/trunk/exo.jcr.component.core/pom.xml 2011-05-27 07:49:03 UTC (rev 4435)
@@ -395,6 +395,7 @@
<include>org/exoplatform/services/jcr/impl/**/Test*.java</include>
</includes>
<excludes>
+ <exclude>org/exoplatform/services/jcr/**/TestQueryUsecases.java</exclude>
<exclude>org/exoplatform/services/jcr/**/api/TestAll.java</exclude>
<exclude>org/exoplatform/services/jcr/**/TestErrorMultithreading.java</exclude>
<exclude>org/exoplatform/services/jcr/**/TestRollbackBigFiles.java</exclude>
12 years, 11 months
exo-jcr SVN: r4434 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2011-05-26 12:49:50 -0400 (Thu, 26 May 2011)
New Revision: 4434
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
Log:
EXOJCR-1352: close the connection to prevent application deadlock
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-26 16:26:13 UTC (rev 4433)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-26 16:49:50 UTC (rev 4434)
@@ -904,11 +904,13 @@
public void start()
{
// if isolation level lesser then TRANSACTION_READ_COMMITTED, print a warning
+ Connection con = null;
try
{
- if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
+ con = getConnectionFactory().getJdbcConnection();
+ if (con.getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
{
- LOG.warn("Wrong default isolation level, please set the default isolation level to READ_COMMITTED or higher. Other default isolation levels are not supported.");
+ 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)
@@ -919,6 +921,20 @@
{
LOG.error("Error checking isolation level configuration.", e);
}
+ finally
+ {
+ if (con != null)
+ {
+ try
+ {
+ con.close();
+ }
+ catch (SQLException e)
+ {
+ // ignore me
+ }
+ }
+ }
}
/**
12 years, 11 months
exo-jcr SVN: r4433 - jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2011-05-26 12:26:13 -0400 (Thu, 26 May 2011)
New Revision: 4433
Modified:
jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
Log:
JCR-1618: close the connection to prevent application deadlock
Modified: jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java
===================================================================
--- jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-26 15:31:18 UTC (rev 4432)
+++ jcr/branches/1.12.x/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCWorkspaceDataContainer.java 2011-05-26 16:26:13 UTC (rev 4433)
@@ -837,9 +837,11 @@
public void start()
{
// if isolation level lesser then TRANSACTION_READ_COMMITTED, print a warning
+ Connection con = null;
try
{
- if (getConnectionFactory().getJdbcConnection().getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
+ con = getConnectionFactory().getJdbcConnection();
+ if (con.getTransactionIsolation() < Connection.TRANSACTION_READ_COMMITTED)
{
LOG.warn("Wrong default isolation level, please set the default isolation level to READ_COMMITTED or higher. Other default isolation levels are not supported");
}
@@ -852,6 +854,20 @@
{
LOG.error("Error checking isolation level configuration.", e);
}
+ finally
+ {
+ if (con != null)
+ {
+ try
+ {
+ con.close();
+ }
+ catch (SQLException e)
+ {
+ // ignore me
+ }
+ }
+ }
}
/**
12 years, 11 months
exo-jcr SVN: r4432 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2011-05-26 11:31:18 -0400 (Thu, 26 May 2011)
New Revision: 4432
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
Log:
EXOJCR-1103: appendPattern fixed
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-05-26 13:05:22 UTC (rev 4431)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-05-26 15:31:18 UTC (rev 4432)
@@ -847,9 +847,8 @@
if (indexConstraint && entry.getIndex() != -1)
{
- sb.append(" and I_INDEX=");
+ sb.append(" and I.I_INDEX=");
sb.append(entry.getIndex());
-
}
sb.append(")");
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-05-26 13:05:22 UTC (rev 4431)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-05-26 15:31:18 UTC (rev 4432)
@@ -877,7 +877,7 @@
if (indexConstraint && entry.getIndex() != -1)
{
- sb.append(" and I_INDEX=");
+ sb.append(" and I.I_INDEX=");
sb.append(entry.getIndex());
}
sb.append(")");
12 years, 11 months
exo-jcr SVN: r4431 - ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/management.
by do-not-reply@jboss.org
Author: areshetnyak
Date: 2011-05-26 09:05:22 -0400 (Thu, 26 May 2011)
New Revision: 4431
Added:
ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/management/RestManagementProvider.java
Log:
EXOJCR-769 : The RestManagementProvider was ported.
Added: ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/management/RestManagementProvider.java
===================================================================
--- ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/management/RestManagementProvider.java (rev 0)
+++ ws/trunk/exo.ws.rest.ext/src/main/java/org/exoplatform/services/rest/ext/management/RestManagementProvider.java 2011-05-26 13:05:22 UTC (rev 4431)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.exoplatform.services.rest.ext.management;
+
+import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.management.rest.annotations.RESTEndpoint;
+import org.exoplatform.management.spi.ManagedResource;
+import org.exoplatform.management.spi.ManagementProvider;
+import org.exoplatform.services.rest.resource.ResourceContainer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
+ * @version $Revision$
+ */
+@Path("management")
+public class RestManagementProvider implements ResourceContainer, ManagementProvider
+{
+
+ /** . */
+ private final ExoContainerContext context;
+
+ /** . */
+ private final Map<ResourceKey, RestResource> resourceMap = new HashMap<ResourceKey, RestResource>();
+
+ public RestManagementProvider(ExoContainerContext context)
+ {
+ this.context = context;
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @RolesAllowed("administrators")
+ public Object list()
+ {
+ List<String> list = new ArrayList<String>();
+ for (RestResource mr : resourceMap.values())
+ {
+ list.add(mr.getName());
+ }
+ return ValueWrapper.wrap(list);
+ }
+
+ @RolesAllowed("administrators")
+ @Path("{resource}")
+ public Object dispatch(@PathParam("resource") String resourceName)
+ {
+ return resourceMap.get(new ResourceKey(resourceName));
+ }
+
+ // ManagementProvider implementation ********************************************************************************
+
+ public Object manage(ManagedResource managedResource)
+ {
+ Object resource = managedResource.getResource();
+
+ //
+ RESTEndpoint annotation = resource.getClass().getAnnotation(RESTEndpoint.class);
+
+ //
+ if (annotation != null)
+ {
+ String name = annotation.path();
+ ResourceKey key = new ResourceKey(name);
+ resourceMap.put(key, new RestResource(name, managedResource));
+ return key;
+ }
+
+ //
+ return null;
+ }
+
+ public void unmanage(Object key)
+ {
+ resourceMap.remove(key);
+ }
+}
12 years, 11 months
exo-jcr SVN: r4430 - ws/trunk/exo.ws.rest.core.
by do-not-reply@jboss.org
Author: dkuleshov
Date: 2011-05-26 04:40:48 -0400 (Thu, 26 May 2011)
New Revision: 4430
Modified:
ws/trunk/exo.ws.rest.core/pom.xml
Log:
EXOJCR-944: changed copy with ant plugin for add source with build helper plugin
Modified: ws/trunk/exo.ws.rest.core/pom.xml
===================================================================
--- ws/trunk/exo.ws.rest.core/pom.xml 2011-05-26 07:00:26 UTC (rev 4429)
+++ ws/trunk/exo.ws.rest.core/pom.xml 2011-05-26 08:40:48 UTC (rev 4430)
@@ -113,6 +113,25 @@
<build>
<plugins>
<plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <id>add-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>target/generated-test-sources</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
@@ -168,23 +187,6 @@
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
- <id>0</id>
- <goals>
- <goal>run</goal>
- </goals>
- <phase>generate-test-sources</phase>
- <configuration>
- <tasks>
- <echo>copy files gnerated by JAXB to test source directory</echo>
- <copy todir="src/test/java">
- <fileset dir="target/generated-test-sources">
- <include name="org/**" />
- </fileset>
- </copy>
- </tasks>
- </configuration>
- </execution>
- <execution>
<id>prepare-test-policy</id>
<phase>process-test-resources</phase>
<configuration>
12 years, 11 months
exo-jcr SVN: r4429 - in jcr/trunk/exo.jcr.component.core/src: main/java/org/exoplatform/services/jcr/dataflow/persistent and 19 other directories.
by do-not-reply@jboss.org
Author: sergiykarpenko
Date: 2011-05-26 03:00:26 -0400 (Thu, 26 May 2011)
New Revision: 4429
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/AbstractNamePatternFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ExactQPathEntryFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/NodeNamePatternFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntry.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntryFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PropertyNamePatternFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/QPathEntryFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternNodesId.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternPropsId.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreConnectionFactory.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreMultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreSingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseMultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseSingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/itemfilters/
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/itemfilters/TestPatternQPathEntryFilter.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPattern.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPatternAndIndex.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetPropertiesByPattern.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java
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/datamodel/QPathEntry.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataNamePatternFilter.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LocalWorkspaceDataManagerStub.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.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/BufferedJBossCache.java
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/session/LocalWorkspaceStorageDataManagerProxy.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLMultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLSingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleMultiDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleSingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseConnectionFactory.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/reading/TestNode.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestJBossCacheWorkspaceStorageCache.java
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java
Log:
EXOJCR-1103: getNodes and getProperties by pattern now uses own queries and cache instead to use getChildNodes or getChildProperties
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/ItemDataConsumer.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -23,6 +23,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import java.util.List;
@@ -86,6 +87,16 @@
List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException;
/**
+ * Get child Nodes of the parent node.ItemDataFilter used to reduce count of returned items.
+ * But not guarantee that only items matching filter will be returned.
+ *
+ * @param parent NodeData
+ * @param patternFilters
+ * @return List of children Nodes
+ */
+ List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> patternFilters) throws RepositoryException;
+
+ /**
* Get children nodes count of the parent node.
* @param parent NodeData
* @return int, child nodes count
@@ -110,6 +121,17 @@
List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException;
/**
+ * Get child Properties of the parent node. ItemDataFilter used to reduce count of returned items.
+ * But not guarantee that only items matching filter will be returned.
+ *
+ * @param parent NodeData
+ * @param itemDataFilters String
+ *
+ * @return List of children Properties
+ */
+ List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters) throws RepositoryException;
+
+ /**
* List child Properties, returned list will contains Properties without actual Values.
*
* @param parent NodeData
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-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/dataflow/persistent/WorkspaceStorageCache.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -27,6 +27,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import java.util.List;
@@ -81,6 +82,8 @@
ItemData get(String identifier);
/**
+ * Get child nodes.
+ *
* @param parent
* @return child nodes for parent if found; empty list if no items found; null if no items
* initialized
@@ -88,7 +91,19 @@
List<NodeData> getChildNodes(NodeData parent);
/**
+ * Get child nodes by pattern.
+ *
* @param parent
+ * @param pattern
+ * @return child nodes for parent if found; empty list if no items found; null if no items
+ * initialized
+ */
+ List<NodeData> getChildNodes(NodeData parent, QPathEntryFilter pattern);
+
+ /**
+ * Get child nodes count.
+ *
+ * @param parent
* @return child nodes count for parent if found; 0 if no items found; -1 if no items
* initialized
*/
@@ -104,6 +119,16 @@
List<PropertyData> getChildProperties(NodeData parent);
/**
+ * Get node child properties by pattern.<br/>
+ *
+ * @param parent
+ * @param pattern
+ * @return child properties for parent if found; empty list if no items found; null if no items
+ * initialized
+ */
+ List<PropertyData> getChildProperties(NodeData parent, QPathEntryFilter pattern);
+
+ /**
* List node child properties.<br/> A difference from {@link getChildProperties()} it's that the
* method may return list of node properties (PropertyData) which contains no data
* (ValueData).<br/> Used for Node.hasProperties(), NodeIndexer.createDoc().
@@ -150,15 +175,35 @@
void addChildNodes(NodeData parent, List<NodeData> childNodes);
/**
+ * Adds (update should not be the case!) list of child nodes. The list can be empty. If list is
+ * null the operation is ignored.
+ *
+ * @param parent
+ * @param pattern
+ * @param childNodes
+ */
+ void addChildNodes(NodeData parent, QPathEntryFilter pattern, List<NodeData> childNodes);
+
+ /**
* Adds (update should not be the case!) list of child properties. The list can be empty. If list
* is null the operation is ignored.
*
* @param parent
- * @param childNodes
+ * @param childProperties
*/
void addChildProperties(NodeData parent, List<PropertyData> childProperties);
/**
+ * Adds (update should not be the case!) list of child properties. The list can be empty. If list
+ * is null the operation is ignored.
+ *
+ * @param parent
+ * @param pattern
+ * @param childProperties
+ */
+ void addChildProperties(NodeData parent, QPathEntryFilter pattern, List<PropertyData> childProperties);
+
+ /**
* Adds (update should not be the case!) list of child properties with empty values. The list can
* be empty. If list is null the operation is ignored.
*
@@ -183,6 +228,12 @@
boolean isEnabled();
/**
+ *
+ * @return isPatternSupported status flag, if true then cache can store pattern results
+ */
+ boolean isPatternSupported();
+
+ /**
* Cache size.
*
* @return long value
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPathEntry.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPathEntry.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/QPathEntry.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -151,7 +151,7 @@
String res;
if (showIndex)
{
- res = super.getAsString() + QPath.PREFIX_DELIMITER + this.index;
+ res = super.getAsString() + QPath.PREFIX_DELIMITER + getIndex();
}
else
{
@@ -206,7 +206,7 @@
if (result == true && (o instanceof QPathEntry))
{
- return result && (index == ((QPathEntry)o).getIndex());
+ return result && (getIndex() == ((QPathEntry)o).getIndex());
}
else
{
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -44,7 +44,8 @@
import org.exoplatform.services.jcr.datamodel.ValueData;
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.core.itemfilters.ItemDataFilter;
-import org.exoplatform.services.jcr.impl.core.itemfilters.ItemDataNamePatternFilter;
+import org.exoplatform.services.jcr.impl.core.itemfilters.NodeNamePatternFilter;
+import org.exoplatform.services.jcr.impl.core.itemfilters.PropertyNamePatternFilter;
import org.exoplatform.services.jcr.impl.core.lock.LockImpl;
import org.exoplatform.services.jcr.impl.core.nodetype.ItemAutocreator;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeDefinitionImpl;
@@ -1095,10 +1096,20 @@
try
{
- List<NodeData> childs = childNodesData();
- ItemDataFilter filter = new ItemDataNamePatternFilter(namePattern, session);
+ NodeNamePatternFilter filter = new NodeNamePatternFilter(namePattern, session);
+ List<NodeData> childs = null;
+ if (filter.isLookingAllData())
+ {
+ childs = childNodesData();
+ }
+ else
+ {
+ childs = new ArrayList<NodeData>(dataManager.getChildNodesData(nodeData(), filter.getQPathEntryFilters()));
+ Collections.sort(childs, new NodeDataOrderComparator());
+ }
+
if (childs.size() < session.getLazyReadThreshold())
{
// full iterator
@@ -1120,7 +1131,7 @@
else
{
// lazy iterator
- return new LazyNodeIterator(childNodesData(), filter);
+ return new LazyNodeIterator(childs, filter);
}
}
finally
@@ -1251,13 +1262,25 @@
try
{
- List<PropertyData> childs = childPropertiesData();
-
- ItemDataFilter filter = new ItemDataNamePatternFilter(namePattern, session);
-
if (session.getAccessManager().hasPermission(nodeData().getACL(), new String[]{PermissionType.READ},
session.getUserState().getIdentity()))
{
+
+ PropertyNamePatternFilter filter = new PropertyNamePatternFilter(namePattern, session);
+
+ List<PropertyData> childs = null;
+ if (filter.isLookingAllData())
+ {
+ childs = childPropertiesData();
+ }
+ else
+ {
+ childs =
+ new ArrayList<PropertyData>(dataManager.getChildPropertiesData(nodeData(),
+ filter.getQPathEntryFilters()));
+ Collections.sort(childs, new PropertiesDataOrderComparator<PropertyData>());
+ }
+
if (childs.size() < session.getLazyReadThreshold())
{
// full iterator
@@ -1278,7 +1301,7 @@
else
{
// lazy iterator
- return new LazyPropertyIterator(childPropertiesData(), filter);
+ return new LazyPropertyIterator(childs, filter);
}
}
else
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-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -36,6 +36,7 @@
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeManagerImpl;
import org.exoplatform.services.jcr.impl.core.version.ChildVersionRemoveVisitor;
import org.exoplatform.services.jcr.impl.core.version.VersionHistoryImpl;
@@ -963,6 +964,36 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> patternFilters)
+ throws RepositoryException
+ {
+ long start = System.currentTimeMillis();
+ if (log.isDebugEnabled())
+ {
+ log.debug("getChildNodesData(" + parent.getQPath().getAsString() + " , itemDataFilter) >>>>>");
+ }
+
+ try
+ {
+ List<NodeData> persistChildNodes =
+ (isNew(parent.getIdentifier())) ? new ArrayList<NodeData>() : transactionableManager.getChildNodesData(
+ parent, patternFilters);
+ return (List<NodeData>)mergeNodes(parent, persistChildNodes);
+ }
+ finally
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("getChildNodesData(" + parent.getQPath().getAsString() + ") <<<<< "
+ + ((System.currentTimeMillis() - start) / 1000d) + "sec");
+ }
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getLastOrderNumber(NodeData parent) throws RepositoryException
{
int lastOrderNumber = changesLog.getLastChildOrderNumber(parent.getIdentifier());
@@ -1016,6 +1047,38 @@
/**
* {@inheritDoc}
*/
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ long start = 0;
+ if (log.isDebugEnabled())
+ {
+ start = System.currentTimeMillis();
+ log.debug("getChildPropertiesData(" + parent.getQPath().getAsString() + ") >>>>>");
+ }
+
+ try
+ {
+ List<PropertyData> childProperties =
+ (isNew(parent.getIdentifier())) ? new ArrayList<PropertyData>() : transactionableManager
+ .getChildPropertiesData(parent, itemDataFilters);
+
+ return (List<PropertyData>)mergeProps(parent, childProperties, transactionableManager);
+ }
+ finally
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("getChildPropertiesData(" + parent.getQPath().getAsString() + ") <<<<< "
+ + ((System.currentTimeMillis() - start) / 1000d) + "sec");
+ }
+ }
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException
{
long start = 0;
@@ -1957,6 +2020,55 @@
/**
* Merges incoming node with changes stored in this log i.e: 1. incoming data still not modified
* if there are no corresponding changes 2. incoming data is refreshed with corresponding changes
+ * if any 3. new data is added from changes 4. if changed data is marked as "deleted" it removes
+ * from outgoing list WARN. THIS METHOD HAS SIBLING - mergeList, see below.
+ *
+ * @param rootData
+ * @param persistChildNodes persisted child nodes, that will be merged with transient data
+ *
+ * @return merged nodes list
+ */
+ protected List<? extends ItemData> mergeNodes(ItemData rootData, List<NodeData> persistChildNodes)
+ throws RepositoryException
+ {
+ // 1 get all transient descendants
+ Collection<ItemState> transientDescendants = changesLog.getLastChildrenStates(rootData, true);
+
+ if (!transientDescendants.isEmpty())
+ {
+ // 2 get ALL persisted descendants
+ Map<String, ItemData> descendants = new LinkedHashMap<String, ItemData>();
+ for (int i = 0, length = persistChildNodes.size(); i < length; i++)
+ {
+ NodeData childNode = persistChildNodes.get(i);
+ descendants.put(childNode.getIdentifier(), childNode);
+ }
+
+ // merge data
+ for (ItemState state : transientDescendants)
+ {
+ ItemData data = state.getData();
+ if (!state.isDeleted())
+ {
+ descendants.put(data.getIdentifier(), data);
+ }
+ else
+ {
+ descendants.remove(data.getIdentifier());
+ }
+ }
+ Collection<ItemData> desc = descendants.values();
+ return new ArrayList<ItemData>(desc);
+ }
+ else
+ {
+ return persistChildNodes;
+ }
+ }
+
+ /**
+ * Merges incoming node with changes stored in this log i.e: 1. incoming data still not modified
+ * if there are no corresponding changes 2. incoming data is refreshed with corresponding changes
* if any 3. new datas is added from changes 4. if chaged data is marked as "deleted" it removes
* from outgoing list WARN. THIS METHOD HAS SIBLING - mergeList, see below.
*
@@ -2010,6 +2122,62 @@
* @param listOnly
* @return
*/
+ protected List<? extends ItemData> mergeProps(ItemData rootData, List<PropertyData> childProperties,
+ DataManager dataManager) throws RepositoryException
+ {
+ // 1 get all transient descendants
+ Collection<ItemState> transientDescendants = changesLog.getLastChildrenStates(rootData, false);
+
+ if (!transientDescendants.isEmpty())
+ {
+ Map<String, ItemData> descendants = new LinkedHashMap<String, ItemData>();
+ outer : for (int i = 0, length = childProperties.size(); i < length; i++)
+ {
+ ItemData childProp = childProperties.get(i);
+ for (ItemState transientState : transientDescendants)
+ {
+ if (!transientState.isNode() && !transientState.isDeleted()
+ && transientState.getData().getQPath().getDepth() == childProp.getQPath().getDepth()
+ && transientState.getData().getQPath().getName().equals(childProp.getQPath().getName()))
+ {
+ continue outer;
+ }
+ }
+ descendants.put(childProp.getIdentifier(), childProp);
+ }
+
+ // merge data
+ for (ItemState state : transientDescendants)
+ {
+ ItemData data = state.getData();
+ if (!state.isDeleted())
+ {
+ descendants.put(data.getIdentifier(), data);
+ }
+ else
+ {
+ descendants.remove(data.getIdentifier());
+ }
+ }
+ Collection<ItemData> desc = descendants.values();
+ return new ArrayList<ItemData>(desc);
+ }
+ else
+ {
+ return childProperties;
+ }
+ }
+
+ /**
+ * Merges incoming property data with changes stored in this log i.e: 1. incoming data still not modified
+ * if there are no corresponding changes 2. incoming data is refreshed with corresponding changes
+ * if any 3. new datas is added from changes 4. if chaged data is marked as "deleted" it removes
+ * from outgoing list WARN. THIS METHOD HAS SIBLING - mergeList, see below.
+ *
+ * @param rootData
+ * @param listOnly
+ * @return
+ */
protected List<? extends ItemData> mergeProps(ItemData rootData, boolean listOnly, DataManager dataManager)
throws RepositoryException
{
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/AbstractNamePatternFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/AbstractNamePatternFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/AbstractNamePatternFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.core.JCRPath;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * @author <a href="mailto:geaz@users.sourceforge.net">Gennady Azarenkov</a>
+ * @version $Id: AbstractNamePatternFilter.java 2137 2010-03-25 15:31:56Z sergiykarpenko $
+ */
+public abstract class AbstractNamePatternFilter implements ItemDataFilter
+{
+ /**
+ * Logger.
+ */
+ protected static final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.ItemDataNamePatternFilter");
+
+ private final SessionImpl session;
+
+ private final boolean getAllItems;
+
+ private final List<QPathEntryFilter> subFilters;
+
+ /**
+ * Exact names.
+ */
+ private final QPathEntry[] exactNames;
+
+ /**
+ * Not parsed names with wildcard symbols.
+ */
+ private final String[] wildcardExpressions;
+
+ /**
+ * wildcardExpressions parsed into Pattern.
+ */
+ private Pattern[] expressionNamePatterns = null;
+
+ public AbstractNamePatternFilter(String namePattern, SessionImpl session) throws RepositoryException
+ {
+ this.session = session;
+
+ StringTokenizer parser = new StringTokenizer(namePattern, "|");
+ boolean getAll = false;
+
+ List<QPathEntryFilter> filters = new ArrayList<QPathEntryFilter>();
+ List<QPathEntry> exactNamesList = new ArrayList<QPathEntry>();
+ List<String> wildcardExpressionsList = new ArrayList<String>();
+
+ while (parser.hasMoreTokens())
+ {
+ String token = parser.nextToken().trim();
+ if (token.equals("*") || token.equals("*:*") || token.equals("*:*[*]"))
+ {
+ getAll = true;
+ filters.clear();
+ break;
+ }
+ if (token.startsWith(":"))
+ {
+ throw new RepositoryException("Name pattern can not start with colon.");
+ }
+ else
+ {
+ QPathEntry entry = null;
+ if (isExactName(token))
+ {
+
+ JCRPath path = session.getLocationFactory().parseRelPath(token);
+ QPathEntry[] entries = path.getInternalPath().getEntries();
+ entry = entries[entries.length - 1];
+ exactNamesList.add(entry);
+ filters.add(new ExactQPathEntryFilter(entry));
+ }
+ else
+ {
+ entry = parsePatternQPathEntry(token, session);
+ wildcardExpressionsList.add(token);
+ filters.add(new PatternQPathEntryFilter(entry));
+ }
+ }
+ }
+
+ getAllItems = getAll;
+ if (getAllItems)
+ {
+ subFilters = null;
+ exactNames = null;
+ wildcardExpressions = null;
+ }
+ else
+ {
+ subFilters = filters;
+ exactNames = new QPathEntry[exactNamesList.size()];
+ exactNamesList.toArray(exactNames);
+ wildcardExpressions = new String[wildcardExpressionsList.size()];
+ wildcardExpressionsList.toArray(wildcardExpressions);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean accept(ItemData item)
+ {
+ if (getAllItems)
+ {
+ return true;
+ }
+
+ if (expressionNamePatterns == null)
+ {
+ initializePatterns();
+ }
+
+ try
+ {
+ // check exact names for first
+ QPathEntry itemEntry = item.getQPath().getEntries()[item.getQPath().getDepth()];
+
+ for (QPathEntry entry : exactNames)
+ {
+ if (entry.equals(itemEntry))
+ {
+ return true;
+ }
+ }
+
+ JCRPath.PathElement[] pathElements = session.getLocationFactory().createRelPath(new QPathEntry[]{itemEntry});
+ // prefix:name[index]
+ String name = pathElements[0].getAsString(true);
+
+ for (Pattern pattern : expressionNamePatterns)
+ {
+ if (pattern.matcher(name).matches())
+ {
+ return true;
+ }
+ }
+ }
+ catch (RepositoryException e)
+ {
+ // if error - just log and don't accept it
+ LOG.error("Cannot parse JCR name for " + item.getQPath().getAsString(), e);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<? extends ItemData> accept(List<? extends ItemData> itemData)
+ {
+ if (getAllItems)
+ {
+ return itemData;
+ }
+
+ if (expressionNamePatterns == null)
+ {
+ initializePatterns();
+ }
+
+ List<ItemData> result = new ArrayList<ItemData>();
+ for (int i = 0; i < itemData.size(); i++)
+ {
+ if (accept(itemData.get(i)))
+ {
+ result.add(itemData.get(i));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Check does pattern looking all data.
+ * @return
+ */
+ public boolean isLookingAllData()
+ {
+ return getAllItems;
+ }
+
+ /**
+ * Get sub filters. Each Pattern name stored in own subfilter.
+ * @return
+ */
+ public List<QPathEntryFilter> getQPathEntryFilters()
+ {
+ return subFilters;
+ }
+
+ private void initializePatterns()
+ {
+ expressionNamePatterns = new Pattern[wildcardExpressions.length];
+ for (int i = 0; i < wildcardExpressions.length; i++)
+ {
+ StringBuilder sb = new StringBuilder();
+ for (char c : wildcardExpressions[i].toCharArray())
+ {
+ switch (c)
+ {
+ case '*' :
+ sb.append(".*");
+ break;
+ case '\\' :
+ case ':' :
+ case '+' :
+ case '-' :
+ case '=' :
+ case '.' :
+ case ',' :
+ case '{' :
+ case '}' :
+ case '(' :
+ case ')' :
+ case '[' :
+ case ']' :
+ case '^' :
+ case '&' :
+ case '$' :
+ case '?' :
+ case '<' :
+ case '>' :
+ case '!' :
+ sb.append('\\');
+ default :
+ sb.append(c);
+ }
+ }
+
+ if (wildcardExpressions[i].indexOf('[') == -1)
+ {
+ sb.append("\\[.*\\]");
+ }
+
+ expressionNamePatterns[i] = Pattern.compile(sb.toString());
+ }
+ }
+
+ /**
+ * Parse QPathEntry from string namePattern. NamePattern may contain wildcard symbols in
+ * namespace and local name. And may not contain index, which means look all samename siblings.
+ * So ordinary QPathEntry parser is not acceptable.
+ *
+ * @param namePattern string pattern
+ * @param session session used to fetch namespace URI
+ * @return PatternQPathEntry
+ * @throws RepositoryException if namePattern is malformed or there is some namespace problem.
+ */
+ private QPathEntry parsePatternQPathEntry(String namePattern, SessionImpl session) throws RepositoryException
+ {
+ int colonIndex = namePattern.indexOf(':');
+ int bracketIndex = namePattern.lastIndexOf('[');
+
+ String namespaceURI;
+ String localName;
+ int index = getDefaultIndex();
+ if (bracketIndex != -1)
+ {
+ int rbracketIndex = namePattern.lastIndexOf(']');
+ if (rbracketIndex < bracketIndex)
+ {
+ throw new RepositoryException("Malformed pattern expression " + namePattern);
+ }
+ index = Integer.parseInt(namePattern.substring(bracketIndex + 1, rbracketIndex));
+ }
+
+ if (colonIndex == -1)
+ {
+ namespaceURI = "";
+ localName = (bracketIndex == -1) ? namePattern : namePattern.substring(0, bracketIndex);
+ }
+ else
+ {
+ String prefix = namePattern.substring(0, colonIndex);
+ localName =
+ (bracketIndex == -1) ? namePattern.substring(colonIndex + 1) : namePattern.substring(0, bracketIndex);
+
+ if (prefix.indexOf("*") != -1)
+ {
+ namespaceURI = "*";
+ }
+ else
+ {
+ namespaceURI = session.getNamespaceURI(prefix);
+ }
+ }
+
+ return new PatternQPathEntry(namespaceURI, localName, index);
+ }
+
+ /**
+ * Check is token exact name.
+ * @param token
+ * @return
+ */
+ protected abstract boolean isExactName(String token);
+
+ /**
+ * Returns index that will be used, if pattern has no index.
+ * @return index
+ */
+ protected abstract int getDefaultIndex();
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ExactQPathEntryFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ExactQPathEntryFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ExactQPathEntryFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * @author <a href="mailto:skarpenko@exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: ExactQPathEntryFilter.java 34360 19.05.2011 skarpenko $
+ */
+public class ExactQPathEntryFilter implements QPathEntryFilter
+{
+ private QPathEntry entry;
+
+ public ExactQPathEntryFilter()
+ {
+ }
+
+ public ExactQPathEntryFilter(QPathEntry entry)
+ {
+ this.entry = entry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isExactName()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public QPathEntry getQPathEntry()
+ {
+ return entry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean accept(ItemData item)
+ {
+ QPathEntry itemEntry = item.getQPath().getEntries()[item.getQPath().getDepth()];
+ return entry.equals(itemEntry);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<? extends ItemData> accept(List<? extends ItemData> itemData)
+ {
+ List<ItemData> result = new ArrayList<ItemData>();
+ for (int i = 0; i < itemData.size(); i++)
+ {
+ if (accept(itemData.get(i)))
+ {
+ result.add(itemData.get(i));
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ return true;
+
+ if (o == null)
+ return false;
+
+ if (o instanceof QPathEntryFilter)
+ {
+
+ QPathEntryFilter that = (QPathEntryFilter)o;
+ return this.getQPathEntry().equals(that.getQPathEntry());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return entry.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ byte[] buf = entry.getNamespace().getBytes(Constants.DEFAULT_ENCODING);
+ out.writeInt(buf.length);
+ out.write(buf);
+
+ buf = entry.getName().getBytes(Constants.DEFAULT_ENCODING);
+ out.writeInt(buf.length);
+ out.write(buf);
+
+ out.writeInt(entry.getIndex());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ byte[] buf = new byte[in.readInt()];
+ in.readFully(buf);
+ String namespace = new String(buf, Constants.DEFAULT_ENCODING);
+
+ buf = new byte[in.readInt()];
+ in.readFully(buf);
+ String localName = new String(buf, Constants.DEFAULT_ENCODING);
+
+ int index = in.readInt();
+ entry = new QPathEntry(namespace, localName, index);
+ }
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataFilter.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -20,6 +20,8 @@
import org.exoplatform.services.jcr.datamodel.ItemData;
+import java.util.List;
+
public interface ItemDataFilter
{
@@ -31,5 +33,8 @@
* The item to be tested for inclusion in the returned set.
* @return a <code>boolean</code>.
*/
- public boolean accept(ItemData item);
+ boolean accept(ItemData item);
+
+ List<? extends ItemData> accept(List<? extends ItemData> item);
+
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataNamePatternFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataNamePatternFilter.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/ItemDataNamePatternFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -98,4 +98,14 @@
return Pattern.compile(regexp).matcher(name).matches();
}
+ /**
+ * @see org.exoplatform.services.jcr.impl.core.itemfilters.ItemDataFilter#accept(java.util.List)
+ */
+ @Override
+ public List<? extends ItemData> accept(List<? extends ItemData> item)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/NodeNamePatternFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/NodeNamePatternFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/NodeNamePatternFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: NodeNamePatternFilter.java 111 12.05.2011 serg $
+ */
+public class NodeNamePatternFilter extends AbstractNamePatternFilter
+{
+
+ public NodeNamePatternFilter(String namePattern, SessionImpl session) throws RepositoryException
+ {
+ super(namePattern, session);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected int getDefaultIndex()
+ {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isExactName(String token)
+ {
+ return (token.indexOf('*') == -1 && token.indexOf('[') != -1);
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntry.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntry.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntry.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+
+/**
+ * Ordinary QPathEntry do not allows index equal to -1. Such index will be replaced with 1.
+ * So PatternQPathEntry allows any index number. And Index -1 means that PatternQPathEntry cowers
+ * all samename siblings.
+ *
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: PatternQPathEntry.java 111 12.05.2011 serg $
+ */
+public class PatternQPathEntry extends QPathEntry
+{
+ private final int index;
+
+ public PatternQPathEntry(String namespace, String name)
+ {
+ this(namespace, name, -1);
+ }
+
+ public PatternQPathEntry(String namespace, String name, int index)
+ {
+ super(namespace, name, index);
+ this.index = index;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getIndex()
+ {
+ return this.index;
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntryFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntryFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PatternQPathEntryFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * @author <a href="mailto:skarpenko@exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: PatternQPathEntryFilter.java 34360 19.05.2011 skarpenko $
+ */
+public class PatternQPathEntryFilter implements QPathEntryFilter
+{
+ private QPathEntry entry;
+
+ private boolean namespaceIsWildcard;
+
+ private boolean localNameHasWildcard;
+
+ private Pattern localNamePattern = null;
+
+ public PatternQPathEntryFilter()
+ {
+ }
+
+ public PatternQPathEntryFilter(QPathEntry entry)
+ {
+ this.entry = entry;
+ namespaceIsWildcard = entry.getNamespace().equals("*");
+ localNameHasWildcard = entry.getName().indexOf('*') != -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isExactName()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public QPathEntry getQPathEntry()
+ {
+ return entry;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean accept(ItemData item)
+ {
+ if (localNameHasWildcard && localNamePattern == null)
+ {
+ initializePattern();
+ }
+
+ QPathEntry itemEntry = item.getQPath().getEntries()[item.getQPath().getDepth()];
+
+ if (entry.getIndex() != -1 && entry.getIndex() != itemEntry.getIndex())
+ {
+ return false;
+ }
+
+ if (!namespaceIsWildcard && !entry.getNamespace().equals(itemEntry.getNamespace()))
+ {
+ return false;
+ }
+
+ if (!localNameHasWildcard)
+ {
+ return entry.getName().equals(itemEntry.getName());
+ }
+ else
+ {
+ return localNamePattern.matcher(itemEntry.getName()).matches();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<? extends ItemData> accept(List<? extends ItemData> itemData)
+ {
+
+ List<ItemData> result = new ArrayList<ItemData>();
+ for (int i = 0; i < itemData.size(); i++)
+ {
+ if (accept(itemData.get(i)))
+ {
+ result.add(itemData.get(i));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ return true;
+
+ if (o == null)
+ return false;
+
+ if (o instanceof QPathEntryFilter)
+ {
+
+ QPathEntryFilter that = (QPathEntryFilter)o;
+ return this.getQPathEntry().equals(that.getQPathEntry());
+ }
+ return false;
+ }
+
+ private void initializePattern()
+ {
+ StringBuilder sb = new StringBuilder();
+ for (char c : entry.getName().toCharArray())
+ {
+ switch (c)
+ {
+ case '*' :
+ sb.append(".*");
+ break;
+ case '\\' :
+ case ':' :
+ case '+' :
+ case '-' :
+ case '=' :
+ case '.' :
+ case ',' :
+ case '[' :
+ case ']' :
+ case '{' :
+ case '}' :
+ case '(' :
+ case ')' :
+ case '^' :
+ case '&' :
+ case '$' :
+ case '?' :
+ case '<' :
+ case '>' :
+ case '!' :
+ sb.append('\\');
+ default :
+ sb.append(c);
+ }
+ }
+ localNamePattern = Pattern.compile(sb.toString());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return entry.hashCode();
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ byte[] buf = entry.getNamespace().getBytes(Constants.DEFAULT_ENCODING);
+ out.writeInt(buf.length);
+ out.write(buf);
+
+ buf = entry.getName().getBytes(Constants.DEFAULT_ENCODING);
+ out.writeInt(buf.length);
+ out.write(buf);
+
+ out.writeInt(entry.getIndex());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ byte[] buf = new byte[in.readInt()];
+ in.readFully(buf);
+ String namespace = new String(buf, Constants.DEFAULT_ENCODING);
+ namespaceIsWildcard = namespace.equals("*");
+
+ buf = new byte[in.readInt()];
+ in.readFully(buf);
+ String localName = new String(buf, Constants.DEFAULT_ENCODING);
+ localNameHasWildcard = localName.indexOf('*') != -1;
+
+ int index = in.readInt();
+ entry = new PatternQPathEntry(namespace, localName, index);
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PropertyNamePatternFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PropertyNamePatternFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/PropertyNamePatternFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: PropertyNamePatternFilter.java 111 12.05.2011 serg $
+ */
+public class PropertyNamePatternFilter extends AbstractNamePatternFilter
+{
+
+ public PropertyNamePatternFilter(String namePattern, SessionImpl session) throws RepositoryException
+ {
+ super(namePattern, session);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected int getDefaultIndex()
+ {
+ return 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isExactName(String token)
+ {
+ return (token.indexOf('*') == -1);
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/QPathEntryFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/QPathEntryFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/itemfilters/QPathEntryFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.core.itemfilters;
+
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+
+import java.io.Externalizable;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * @author <a href="mailto:skarpenko@exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: QPathEntryFilter.java 19.05.2011 skarpenko $
+ */
+public interface QPathEntryFilter extends ItemDataFilter, Externalizable
+{
+ /**
+ * Return is this filter for exact name.
+ *
+ * @return
+ */
+ boolean isExactName();
+
+ /**
+ * Return QPathEntry used by filter.
+ *
+ * @return QPathEntry
+ */
+ QPathEntry getQPathEntry();
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/ACLInheritanceSupportedWorkspaceDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -26,6 +26,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -158,6 +159,19 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> patternFilters) throws RepositoryException
+ {
+ final List<NodeData> nodes = persistentManager.getChildNodesData(parent, patternFilters);
+ for (int i = 0; i < nodes.size(); i++)
+ {
+ nodes.set(i, (NodeData)initACL(parent, nodes.get(i)));
+ }
+ return nodes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getLastOrderNumber(final NodeData parent) throws RepositoryException
{
return persistentManager.getLastOrderNumber(parent);
@@ -208,6 +222,15 @@
/**
* {@inheritDoc}
*/
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ return persistentManager.getChildPropertiesData(parent, itemDataFilters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException
{
return persistentManager.listChildPropertiesData(parent);
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -35,6 +35,7 @@
import org.exoplatform.services.jcr.impl.backup.ResumeException;
import org.exoplatform.services.jcr.impl.backup.SuspendException;
import org.exoplatform.services.jcr.impl.backup.Suspendable;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManagerListener;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
@@ -51,7 +52,12 @@
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
@@ -501,6 +507,16 @@
* {@inheritDoc}
*/
@Override
+ public List<NodeData> getChildNodesData(NodeData parentData, List<QPathEntryFilter> patternFilters)
+ throws RepositoryException
+ {
+ return getChildNodesDataByPattern(parentData, patternFilters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public List<PropertyData> getChildPropertiesData(NodeData nodeData) throws RepositoryException
{
List<PropertyData> childs = getChildPropertiesData(nodeData, false);
@@ -516,6 +532,22 @@
* {@inheritDoc}
*/
@Override
+ public List<PropertyData> getChildPropertiesData(NodeData nodeData, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ List<PropertyData> childs = getChildPropertiesDataByPattern(nodeData, itemDataFilters);
+ for (PropertyData prop : childs)
+ {
+ fixPropertyValues(prop);
+ }
+
+ return childs;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public ItemData getItemData(NodeData parentData, QPathEntry name) throws RepositoryException
{
return getItemData(parentData, name, ItemType.UNKNOWN);
@@ -950,6 +982,174 @@
}
}
+ protected List<NodeData> getChildNodesDataByPattern(NodeData parentData, List<QPathEntryFilter> patternFilters)
+ throws RepositoryException
+ {
+ if (!cache.isEnabled())
+ {
+ return super.getChildNodesData(parentData, patternFilters);
+ }
+
+ if (!cache.isPatternSupported())
+ {
+ return getChildNodesData(parentData);
+ }
+
+ // 1. check cache - outside data request
+
+ List<NodeData> childNodesList = cache.getChildNodes(parentData);
+ if (childNodesList != null)
+ {
+ return childNodesList;
+ }
+
+ Map<String, NodeData> childNodesMap = new HashMap<String, NodeData>();
+
+ Set<QPathEntryFilter> uncachedPatterns = new HashSet<QPathEntryFilter>();
+ for (int i = 0; i < patternFilters.size(); i++)
+ {
+ if (patternFilters.get(i).isExactName())
+ {
+ ItemData data = getCachedItemData(parentData, patternFilters.get(i).getQPathEntry(), ItemType.NODE);
+ if (data != null)
+ {
+ if (!(data instanceof NullItemData))
+ {
+ childNodesMap.put(data.getIdentifier(), (NodeData)data);
+ }
+ }
+ else
+ {
+ uncachedPatterns.add(patternFilters.get(i));
+ }
+ }
+ else
+ {
+ // get nodes list by pattern
+ List<NodeData> cachedItemList = cache.getChildNodes(parentData, patternFilters.get(i));
+ if (cachedItemList != null)
+ {
+ //merge results
+ for (int j = 0, length = cachedItemList.size(); j < length; j++)
+ {
+ childNodesMap.put(cachedItemList.get(j).getIdentifier(), cachedItemList.get(j));
+ }
+ }
+ else
+ {
+ uncachedPatterns.add(patternFilters.get(i));
+ }
+ }
+ }
+
+ // 2. check cache - inside data requests
+ if (!uncachedPatterns.isEmpty())
+ {
+ List<DataRequest> requests = new ArrayList<DataRequest>();
+ try
+ {
+ final DataRequest request = new DataRequest(parentData.getIdentifier(), DataRequest.GET_NODES);
+ request.start();
+ requests.add(request);
+ // Try first to get the value from the cache since a
+ // request could have been launched just before
+ childNodesList = cache.getChildNodes(parentData);
+ if (childNodesList != null)
+ {
+ return childNodesList;
+ }
+
+ Iterator<QPathEntryFilter> patternIterator = uncachedPatterns.iterator();
+ while (patternIterator.hasNext())
+ {
+ QPathEntryFilter pattern = patternIterator.next();
+ if (pattern.isExactName())
+ {
+ DataRequest exactNameRequest = new DataRequest(parentData.getIdentifier(), pattern.getQPathEntry());
+ exactNameRequest.start();
+ requests.add(exactNameRequest);
+
+ ItemData data = getCachedItemData(parentData, pattern.getQPathEntry(), ItemType.NODE);
+ if (data != null)
+ {
+ if (!(data instanceof NullItemData))
+ {
+ childNodesMap.put(data.getIdentifier(), (NodeData)data);
+ }
+ patternIterator.remove();
+ }
+ }
+ else
+ {
+ // get node list by pattern
+ List<NodeData> cachedItemList = cache.getChildNodes(parentData, pattern);
+ if (cachedItemList != null)
+ {
+ //merge results
+ for (int j = 0, length = cachedItemList.size(); j < length; j++)
+ {
+ childNodesMap.put(cachedItemList.get(j).getIdentifier(), cachedItemList.get(j));
+ }
+ patternIterator.remove();
+ }
+ }
+ }
+ patternIterator = null;
+
+ // execute all patterns and put result in cache
+ if (!uncachedPatterns.isEmpty())
+ {
+ List<NodeData> persistedItemList =
+ super.getChildNodesData(parentData, new ArrayList<QPathEntryFilter>(uncachedPatterns));
+
+ if (persistedItemList.size() > 0)
+ {
+ NodeData parent = (NodeData)getItemData(parentData.getIdentifier());
+ if (parent != null)
+ {
+ // filter nodes list for each exact name
+ patternIterator = uncachedPatterns.iterator();
+ while (patternIterator.hasNext())
+ {
+ QPathEntryFilter pattern = patternIterator.next();
+ List<NodeData> persistedNodeData = (List<NodeData>)pattern.accept(persistedItemList);
+ if (pattern.isExactName())
+ {
+ if (persistedNodeData.isEmpty())
+ {
+ cache.put(new NullNodeData(parentData, pattern.getQPathEntry()));
+ }
+ else
+ {
+ cache.put(persistedNodeData.get(0));
+ }
+ }
+ else
+ {
+ cache.addChildNodes(parent, pattern, persistedNodeData);
+ }
+ for (NodeData node : persistedItemList)
+ {
+ childNodesMap.put(node.getIdentifier(), node);
+ }
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ for (DataRequest rq : requests)
+ {
+ rq.done();
+ }
+ requests.clear();
+ }
+ }
+
+ return new ArrayList<NodeData>(childNodesMap.values());
+ }
+
/**
* Get referenced properties data.
*
@@ -1057,6 +1257,177 @@
}
}
+ protected List<PropertyData> getChildPropertiesDataByPattern(NodeData nodeData, List<QPathEntryFilter> patternFilters)
+ throws RepositoryException
+ {
+ if (!cache.isEnabled())
+ {
+ return super.getChildPropertiesData(nodeData, patternFilters);
+ }
+
+ if (!cache.isPatternSupported())
+ {
+ return getChildPropertiesData(nodeData);
+ }
+
+ // 1. check cache - outside data request
+ List<PropertyData> childPropsList = cache.getChildProperties(nodeData);
+ if (childPropsList != null)
+ {
+ return childPropsList;
+ }
+
+ Map<String, PropertyData> childPropsMap = new HashMap<String, PropertyData>();
+
+ Set<QPathEntryFilter> uncachedPatterns = new HashSet<QPathEntryFilter>();
+ for (int i = 0; i < patternFilters.size(); i++)
+ {
+ if (patternFilters.get(i).isExactName())
+ {
+ ItemData data = getCachedItemData(nodeData, patternFilters.get(i).getQPathEntry(), ItemType.PROPERTY);
+ if (data != null)
+ {
+ if (!(data instanceof NullPropertyData))
+ {
+ childPropsMap.put(data.getIdentifier(), (PropertyData)data);
+ }
+ }
+ else
+ {
+ uncachedPatterns.add(patternFilters.get(i));
+ }
+ }
+ else
+ {
+
+ // get property list by pattern
+ List<PropertyData> cachedItemList = cache.getChildProperties(nodeData, patternFilters.get(i));
+ if (cachedItemList != null)
+ {
+ //merge results
+ for (int j = 0, length = cachedItemList.size(); j < length; j++)
+ {
+ childPropsMap.put(cachedItemList.get(j).getIdentifier(), cachedItemList.get(j));
+ }
+ }
+ else
+ {
+ uncachedPatterns.add(patternFilters.get(i));
+ }
+ }
+ }
+
+ // 2. check cache - inside data requests
+ if (!uncachedPatterns.isEmpty())
+ {
+ List<DataRequest> requests = new ArrayList<DataRequest>();
+ try
+ {
+
+ final DataRequest request = new DataRequest(nodeData.getIdentifier(), DataRequest.GET_PROPERTIES);
+ request.start();
+ requests.add(request);
+
+ // Try first to get the value from the cache since a
+ // request could have been launched just before
+ childPropsList = cache.getChildProperties(nodeData);
+ if (childPropsList != null)
+ {
+ return childPropsList;
+ }
+
+ Iterator<QPathEntryFilter> patternIterator = uncachedPatterns.iterator();
+ while (patternIterator.hasNext())
+ {
+ QPathEntryFilter pattern = patternIterator.next();
+ if (pattern.isExactName())
+ {
+ DataRequest exactNameRequest = new DataRequest(nodeData.getIdentifier(), pattern.getQPathEntry());
+ exactNameRequest.start();
+ requests.add(exactNameRequest);
+
+ ItemData data = getCachedItemData(nodeData, pattern.getQPathEntry(), ItemType.PROPERTY);
+ if (data != null)
+ {
+ if (!(data instanceof NullPropertyData))
+ {
+ childPropsMap.put(data.getIdentifier(), (PropertyData)data);
+ }
+ patternIterator.remove();
+ }
+ }
+ else
+ {
+ // get properties list by pattern
+ List<PropertyData> cachedItemList = cache.getChildProperties(nodeData, pattern);
+ if (cachedItemList != null)
+ {
+ //merge results
+ for (int j = 0, length = cachedItemList.size(); j < length; j++)
+ {
+ childPropsMap.put(cachedItemList.get(j).getIdentifier(), cachedItemList.get(j));
+ }
+ patternIterator.remove();
+ }
+ }
+ }
+ patternIterator = null;
+
+ // execute all patterns and put result in cache
+ if (!uncachedPatterns.isEmpty())
+ {
+ List<PropertyData> persistedItemList =
+ super.getChildPropertiesData(nodeData, new ArrayList<QPathEntryFilter>(uncachedPatterns));
+
+ if (persistedItemList.size() > 0)
+ {
+ NodeData parent = (NodeData)getItemData(nodeData.getIdentifier());
+ if (parent != null)
+ {
+ // filter properties list for each exact name
+ patternIterator = uncachedPatterns.iterator();
+ while (patternIterator.hasNext())
+ {
+ QPathEntryFilter pattern = patternIterator.next();
+ List<PropertyData> persistedPropData = (List<PropertyData>)pattern.accept(persistedItemList);
+ if (pattern.isExactName())
+ {
+ if (persistedPropData.isEmpty())
+ {
+ cache.put(new NullPropertyData(parent, pattern.getQPathEntry()));
+ }
+ else
+ {
+ cache.put(persistedPropData.get(0));
+ }
+ }
+ else
+ {
+ cache.addChildProperties(parent, pattern, persistedPropData);
+ }
+
+ for (PropertyData node : persistedItemList)
+ {
+ childPropsMap.put(node.getIdentifier(), node);
+ }
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ for (DataRequest rq : requests)
+ {
+ rq.done();
+ }
+ requests.clear();
+ }
+ }
+
+ return new ArrayList<PropertyData>(childPropsMap.values());
+ }
+
/**
* Get persisted ItemData.
*
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -32,6 +32,7 @@
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.log.ExoLogger;
@@ -1702,6 +1703,14 @@
}
/**
+ * {@inheritDoc}
+ */
+ public boolean isPatternSupported()
+ {
+ return false;
+ }
+
+ /**
* Enable cache.
*
* @param enabled
@@ -2172,4 +2181,27 @@
propertiesCache.clear();
cache.clear();
}
+
+ public void addChildProperties(NodeData parent, QPathEntryFilter pattern, List<PropertyData> childProperties)
+ {
+ // TODO Auto-generated method stub
+ }
+
+ public List<PropertyData> getChildProperties(NodeData parent, QPathEntryFilter pattern)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void addChildNodes(NodeData parent, QPathEntryFilter pattern, List<NodeData> childNodes)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public List<NodeData> getChildNodes(NodeData parent, QPathEntryFilter pattern)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LocalWorkspaceDataManagerStub.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LocalWorkspaceDataManagerStub.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LocalWorkspaceDataManagerStub.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -20,6 +20,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -58,6 +59,15 @@
* {@inheritDoc}
*/
@Override
+ public List<NodeData> getChildNodesData(NodeData nodeData, List<QPathEntryFilter> patternFilters) throws RepositoryException
+ {
+ return Collections.unmodifiableList(super.getChildNodesData(nodeData, patternFilters));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException
{
return Collections.unmodifiableList(super.getChildPropertiesData(parent));
@@ -67,6 +77,16 @@
* {@inheritDoc}
*/
@Override
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ return Collections.unmodifiableList(super.getChildPropertiesData(parent, itemDataFilters));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public List<PropertyData> listChildPropertiesData(final NodeData parent) throws RepositoryException
{
return Collections.unmodifiableList(super.listChildPropertiesData(parent));
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -33,6 +33,7 @@
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.util.IdGenerator;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -90,6 +91,20 @@
* {@inheritDoc}
*/
@Override
+ public List<NodeData> getChildNodesData(final NodeData nodeData, final List<QPathEntryFilter> patternFilters)
+ throws RepositoryException
+ {
+ if (isSystemDescendant(nodeData.getQPath()) && !this.equals(versionDataManager))
+ {
+ return versionDataManager.getChildNodesData(nodeData, patternFilters);
+ }
+ return super.getChildNodesData(nodeData, patternFilters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public int getChildNodesCount(final NodeData parent) throws RepositoryException
{
if (isSystemDescendant(parent.getQPath()) && !this.equals(versionDataManager))
@@ -116,6 +131,20 @@
* {@inheritDoc}
*/
@Override
+ public List<PropertyData> getChildPropertiesData(final NodeData nodeData, final List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ if (isSystemDescendant(nodeData.getQPath()) && !this.equals(versionDataManager))
+ {
+ return versionDataManager.getChildPropertiesData(nodeData, itemDataFilters);
+ }
+ return super.getChildPropertiesData(nodeData, itemDataFilters);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public List<PropertyData> listChildPropertiesData(final NodeData nodeData) throws RepositoryException
{
if (isSystemDescendant(nodeData.getQPath()) && !this.equals(versionDataManager))
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -40,6 +40,7 @@
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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManager;
import org.exoplatform.services.jcr.impl.dataflow.session.TransactionableResourceManagerListener;
@@ -625,6 +626,25 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(final NodeData nodeData, List<QPathEntryFilter> patternFilters)
+ throws RepositoryException
+ {
+
+ final WorkspaceStorageConnection con = dataContainer.openConnection();
+ try
+ {
+ return con.getChildNodesData(nodeData, patternFilters);
+ }
+ finally
+ {
+ con.close();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public int getLastOrderNumber(final NodeData nodeData) throws RepositoryException
{
final WorkspaceStorageConnection con = dataContainer.openConnection();
@@ -673,6 +693,23 @@
/**
* {@inheritDoc}
*/
+ public List<PropertyData> getChildPropertiesData(final NodeData nodeData, final List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ final WorkspaceStorageConnection con = dataContainer.openConnection();
+ try
+ {
+ return con.getChildPropertiesData(nodeData, itemDataFilters);
+ }
+ finally
+ {
+ con.close();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> listChildPropertiesData(final NodeData nodeData) throws RepositoryException
{
final WorkspaceStorageConnection con = dataContainer.openConnection();
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -18,6 +18,8 @@
*/
package org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.infinispan.AdvancedCache;
@@ -32,7 +34,9 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -270,6 +274,63 @@
}
/**
+ * It tries to get Map{filter, Set{itemIds}} by given key. If Map exists then adds itemDatas ID to all acceptable pattern lists.
+ */
+ public static class AddToPatternListContainer extends ChangesContainer
+ {
+ private final ItemData itemData;
+
+ public AddToPatternListContainer(CacheKey key, ItemData value, AdvancedCache<CacheKey, Object> cache,
+ int historicalIndex, boolean local, Boolean allowLocalChanges)
+ {
+ super(key, ChangesType.PUT, cache, historicalIndex, local, allowLocalChanges);
+ this.itemData = value;
+ }
+
+ @Override
+ public void apply()
+ {
+ // force writeLock on next read
+ cache.withFlags(Flag.FORCE_WRITE_LOCK);
+
+ Object existingObject = cache.get(key);
+
+ // if Map found , perform add
+ if (existingObject instanceof Map)
+ {
+ Map<QPathEntryFilter, Set<String>> newMap =
+ new HashMap<QPathEntryFilter, Set<String>>((Map<QPathEntryFilter, Set<String>>)existingObject);
+
+ Iterator<QPathEntryFilter> iterator = newMap.keySet().iterator();
+ while (iterator.hasNext())
+ {
+ QPathEntryFilter pattern = iterator.next();
+ if (pattern.accept(itemData))
+ {
+ Set<String> newSet = newMap.get(pattern);
+ newSet.add(itemData.getIdentifier());
+ newMap.put(pattern, newSet);
+ }
+ }
+
+ setCacheLocalMode();
+ cache.put(key, newMap);
+ }
+ else if (existingObject != null)
+ {
+ LOG.error("Unexpected object found by key " + key.toString() + ". Expected Map, but found:"
+ + existingObject.getClass().getName());
+ }
+ }
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return true;
+ }
+ }
+
+ /**
* It tries to get set by given key. If it is set then removes value and puts new modified set
* back.
*/
@@ -312,6 +373,59 @@
}
/**
+ * It tries to get Map{filter, Set{itemIds}} by given key. IfMap exists then removes item IDs from all acceptable pattern lists.
+ */
+ public static class RemoveFromPatternListContainer extends ChangesContainer
+ {
+ private final ItemData itemData;
+
+ public RemoveFromPatternListContainer(CacheKey key, ItemData value, AdvancedCache<CacheKey, Object> cache,
+ int historicalIndex, boolean local, Boolean allowLocalChanges)
+ {
+ super(key, ChangesType.REMOVE, cache, historicalIndex, local, allowLocalChanges);
+ this.itemData = value;
+ }
+
+ @Override
+ public void apply()
+ {
+ // force writeLock on next read
+ cache.withFlags(Flag.FORCE_WRITE_LOCK);
+
+ setCacheLocalMode();
+ Object existingObject = cache.get(key);
+
+ // if found value is really set! add to it.
+ if (existingObject instanceof Map)
+ {
+ Map<QPathEntryFilter, Set<String>> newMap =
+ new HashMap<QPathEntryFilter, Set<String>>((HashMap<QPathEntryFilter, Set<String>>)existingObject);
+
+ Iterator<QPathEntryFilter> patternInterator = newMap.keySet().iterator();
+ while (patternInterator.hasNext())
+ {
+ QPathEntryFilter pattern = patternInterator.next();
+ if (pattern.accept(itemData))
+ {
+ Set<String> newSet = new HashSet<String>(newMap.get(pattern));
+ newSet.remove(itemData.getIdentifier());
+ newMap.put(pattern, newSet);
+ }
+ }
+
+ setCacheLocalMode();
+ cache.put(key, newMap);
+ }
+ }
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return true;
+ }
+ }
+
+ /**
* Remove container.
*/
public static class RemoveObjectContainer extends ChangesContainer
@@ -1105,6 +1219,20 @@
local.get(), allowLocalChanges));
}
+ public void removeFromPatternList(CacheKey key, ItemData value)
+ {
+ CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+ changesContainer.add(new RemoveFromPatternListContainer(key, value, parentCache, changesContainer
+ .getHistoryIndex(), local.get(), allowLocalChanges));
+ }
+
+ public void addToPatternList(CacheKey key, ItemData value)
+ {
+ CompressedISPNChangesBuffer changesContainer = getChangesBufferSafe();
+ changesContainer.add(new AddToPatternListContainer(key, value, parentCache, changesContainer.getHistoryIndex(),
+ local.get(), allowLocalChanges));
+ }
+
public Object getFromBuffer(CacheKey key)
{
//look at buffer for first
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternNodesId.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternNodesId.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternNodesId.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: CachePatternNodesId.java 111 10.05.2011 serg $
+ */
+public class CachePatternNodesId extends CacheKey
+{
+
+ CachePatternNodesId()
+ {
+ super();
+ }
+
+ CachePatternNodesId(String id)
+ {
+ super(id);
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof CachePatternNodesId)
+ {
+ CachePatternNodesId cacheNodesId = (CachePatternNodesId)obj;
+ return (cacheNodesId.hash == hash && cacheNodesId.fullId.equals(fullId));
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternPropsId.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternPropsId.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/CachePatternPropsId.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.dataflow.persistent.infinispan;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: CachePatternPropsId.java 111 28 ���. 2011 serg $
+ */
+public class CachePatternPropsId extends CacheKey
+{
+
+ CachePatternPropsId()
+ {
+ super();
+ }
+
+ CachePatternPropsId(String parentId)
+ {
+ super(parentId);
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof CachePatternPropsId)
+ {
+ CachePatternPropsId cachePatternPropsId = (CachePatternPropsId)obj;
+ return (cachePatternPropsId.hash == hash && cachePatternPropsId.fullId.equals(fullId));
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
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-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -44,6 +44,7 @@
import org.exoplatform.services.jcr.impl.backup.BackupException;
import org.exoplatform.services.jcr.impl.backup.Backupable;
import org.exoplatform.services.jcr.impl.backup.DataRestore;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.infinispan.ISPNCacheFactory;
@@ -58,9 +59,11 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -629,6 +632,47 @@
/**
* {@inheritDoc}
*/
+ public void addChildNodes(NodeData parent, QPathEntryFilter pattern, List<NodeData> childs)
+ {
+ boolean inTransaction = cache.isTransactionActive();
+ try
+ {
+ if (!inTransaction)
+ {
+ cache.beginTransaction();
+ }
+
+ cache.setLocal(true);
+ Set<String> set = new HashSet<String>();
+
+ for (NodeData child : childs)
+ {
+ putNode(child, ModifyChildOption.NOT_MODIFY);
+ set.add(child.getIdentifier());
+ }
+
+ CachePatternNodesId cacheId = new CachePatternNodesId(parent.getIdentifier());
+ Map<QPathEntryFilter, Set<String>> patterns = (Map<QPathEntryFilter, Set<String>>)cache.get(cacheId);
+ if (patterns == null)
+ {
+ patterns = new HashMap<QPathEntryFilter, Set<String>>();
+ }
+ patterns.put(pattern, set);
+ cache.put(cacheId, patterns);
+ }
+ finally
+ {
+ cache.setLocal(false);
+ if (!inTransaction)
+ {
+ dedicatedTxCommit();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void addChildProperties(NodeData parent, List<PropertyData> childs)
{
boolean inTransaction = cache.isTransactionActive();
@@ -669,6 +713,49 @@
/**
* {@inheritDoc}
*/
+ public void addChildProperties(NodeData parent, QPathEntryFilter pattern, List<PropertyData> childs)
+ {
+ boolean inTransaction = cache.isTransactionActive();
+ try
+ {
+ if (!inTransaction)
+ {
+ cache.beginTransaction();
+ }
+ cache.setLocal(true);
+ if (childs.size() > 0)
+ {
+ // add all new
+ Set<String> set = new HashSet<String>();
+ for (PropertyData child : childs)
+ {
+ putProperty(child, ModifyChildOption.NOT_MODIFY);
+ set.add(child.getIdentifier());
+ }
+
+ CachePatternPropsId cacheId = new CachePatternPropsId(parent.getIdentifier());
+ Map<QPathEntryFilter, Set<String>> patterns = (Map<QPathEntryFilter, Set<String>>)cache.get(cacheId);
+ if (patterns == null)
+ {
+ patterns = new HashMap<QPathEntryFilter, Set<String>>();
+ }
+ patterns.put(pattern, set);
+ cache.put(cacheId, patterns);
+ }
+ }
+ finally
+ {
+ cache.setLocal(false);
+ if (!inTransaction)
+ {
+ dedicatedTxCommit();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void addChildPropertiesList(NodeData parent, List<PropertyData> childProperties)
{
// TODO not implemented, will force read from DB
@@ -709,6 +796,45 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodes(final NodeData parent, final QPathEntryFilter pattern)
+ {
+ // get list of children uuids
+ final Map<QPathEntryFilter, Set<String>> patterns =
+ (Map<QPathEntryFilter, Set<String>>)cache.get(new CachePatternNodesId(parent.getIdentifier()));
+
+ if (patterns == null)
+ {
+ return null;
+ }
+
+ Set<String> set = patterns.get(pattern);
+ if (set == null)
+ {
+ return null;
+ }
+
+ final List<NodeData> childs = new ArrayList<NodeData>();
+
+ for (String childId : set)
+ {
+ NodeData child = (NodeData)cache.get(new CacheId(childId));
+ if (child == null)
+ {
+ return null;
+ }
+
+ childs.add(child);
+ }
+
+ // order children by orderNumber, as HashSet returns children in other order
+ Collections.sort(childs, new NodesOrderComparator<NodeData>());
+ return childs;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(NodeData parent)
{
return getChildNodesCount.run(parent);
@@ -722,6 +848,43 @@
return getChildProps(parent.getIdentifier(), true);
}
+ public List<PropertyData> getChildProperties(NodeData parent, QPathEntryFilter pattern)
+ {
+ // get list of children uuids
+ final Map<QPathEntryFilter, Set<String>> patterns =
+ (Map<QPathEntryFilter, Set<String>>)cache.get(new CachePatternPropsId(parent.getIdentifier()));
+
+ if (patterns == null)
+ {
+ return null;
+ }
+
+ Set<String> set = patterns.get(pattern);
+ if (set == null)
+ {
+ return null;
+ }
+
+ final List<PropertyData> childs = new ArrayList<PropertyData>();
+
+ for (String childId : set)
+ {
+ PropertyData child = (PropertyData)cache.get(new CacheId(childId));
+
+ if (child == null)
+ {
+ return null;
+ }
+ if (child.getValues().size() <= 0)
+ {
+ return null;
+ }
+ childs.add(child);
+ }
+ return childs;
+
+ }
+
/**
* {@inheritDoc}
*/
@@ -759,6 +922,14 @@
}
/**
+ * {@inheritDoc}
+ */
+ public boolean isPatternSupported()
+ {
+ return true;
+ }
+
+ /**
* Internal put Item.
*
* @param item ItemData, new data to put in the cache
@@ -812,6 +983,7 @@
// if MODIFY and List present OR FORCE_MODIFY, then write
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
+ cache.addToPatternList(new CachePatternNodesId(node.getParentIdentifier()), node);
cache.addToList(new CacheNodesId(node.getParentIdentifier()), node.getIdentifier(),
modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
}
@@ -893,6 +1065,7 @@
// if MODIFY and List present OR FORCE_MODIFY, then write
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
+ cache.addToPatternList(new CachePatternPropsId(prop.getParentIdentifier()), prop);
cache.addToList(new CachePropsId(prop.getParentIdentifier()), prop.getIdentifier(),
modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
}
@@ -955,12 +1128,15 @@
{
cache.remove(new CacheNodesId(item.getIdentifier()));
cache.remove(new CachePropsId(item.getIdentifier()));
-
+ cache.removeFromPatternList(new CachePatternNodesId(item.getParentIdentifier()), item);
+ cache.remove(new CachePatternNodesId(item.getIdentifier()));
+ cache.remove(new CachePatternPropsId(item.getIdentifier()));
cache.removeFromList(new CacheNodesId(item.getParentIdentifier()), item.getIdentifier());
cache.remove(new CacheRefsId(item.getIdentifier()));
}
else
{
+ cache.removeFromPatternList(new CachePatternPropsId(item.getParentIdentifier()), item);
cache.removeFromList(new CachePropsId(item.getParentIdentifier()), item.getIdentifier());
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -18,6 +18,8 @@
*/
package org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.jbosscache.PrivilegedJBossCacheHelper;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -39,6 +41,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -784,6 +787,13 @@
.getHistoryIndex(), local.get(), useExpiration, expirationTimeOut));
}
+ public void addToPatternList(Fqn fqn, String patternKey, String listKey, ItemData value)
+ {
+ CompressedChangesBuffer changesContainer = getChangesBufferSafe();
+ changesContainer.add(new AddToPatternListContainer(fqn, patternKey, listKey, value, parentCache, changesContainer
+ .getHistoryIndex(), local.get(), useExpiration, expirationTimeOut));
+ }
+
/**
* It tries to get set by given key. If it is set then removes value and puts new modified set back.
*
@@ -798,6 +808,13 @@
changesContainer.getHistoryIndex(), local.get(), useExpiration, expirationTimeOut));
}
+ public void removeFromPatternList(Fqn fqn, String patternKey, String listKey, ItemData value)
+ {
+ CompressedChangesBuffer changesContainer = getChangesBufferSafe();
+ changesContainer.add(new RemoveFromPatternListContainer(fqn, patternKey, listKey, value, parentCache,
+ changesContainer.getHistoryIndex(), local.get(), useExpiration, expirationTimeOut));
+ }
+
public static enum ChangesType {
REMOVE, REMOVE_KEY, PUT, PUT_KEY, PUT_TO_LIST;
}
@@ -1054,6 +1071,68 @@
}
/**
+ * It tries to get all child pattern nodes. Then iterate patterns and adds item ID to acceptable pattern nodes list.
+ */
+ public static class AddToPatternListContainer extends ChangesContainer
+ {
+ private final Serializable patternKey;
+
+ private final Serializable listKey;
+
+ private final ItemData value;
+
+ public AddToPatternListContainer(Fqn fqn, Serializable patternKey, Serializable listKey, ItemData value,
+ Cache<Serializable, Object> cache, int historicalIndex, boolean local, boolean useExpiration, long timeOut)
+ {
+ super(fqn, ChangesType.PUT_KEY, cache, historicalIndex, local, useExpiration, timeOut);
+ this.patternKey = patternKey;
+ this.listKey = listKey;
+ this.value = value;
+ }
+
+ @Override
+ public void apply()
+ {
+ // force writeLock on next read
+ cache.getInvocationContext().getOptionOverrides().setForceWriteLock(true);
+
+ Iterator<Object> patternNames = cache.getChildrenNames(fqn).iterator();
+ while (patternNames.hasNext())
+ {
+ Object name = patternNames.next();
+ Fqn<Object> patternFqn = Fqn.fromRelativeElements(fqn, name);
+ Object patternObject = cache.get(patternFqn, patternKey);
+ if (!(patternObject instanceof QPathEntryFilter))
+ {
+ LOG.error("Unexpected object found by FQN:" + patternFqn + " and key:" + patternKey
+ + ". Expected QPathEntryFilter, but found:" + patternObject.getClass().getName());
+ continue;
+ }
+ QPathEntryFilter nameFilter = (QPathEntryFilter)patternObject;
+ if (nameFilter.accept((ItemData)value))
+ {
+ Object setObject = cache.get(patternFqn, listKey);
+ if (!(setObject instanceof Set))
+ {
+ LOG.error("Unexpected object found by FQN:" + patternFqn + " and key:" + listKey
+ + ". Expected Set, but found:" + setObject.getClass().getName());
+ continue;
+ }
+ Set<String> newSet = new HashSet<String>((Set<String>)setObject);
+ newSet.add(value.getIdentifier());
+ cache.put(patternFqn, listKey, newSet);
+ }
+ }
+ }
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return true;
+ }
+ }
+
+ /**
* It tries to get set by given key. If it is set then removes value and puts new modified set back.
*/
public static class RemoveFromListContainer extends ChangesContainer
@@ -1102,6 +1181,69 @@
}
/**
+ * It tries to get all child pattern nodes. Then iterate patterns and removes item IDs from acceptable pattern nodes list.
+ */
+ public static class RemoveFromPatternListContainer extends ChangesContainer
+ {
+ private final Serializable patternKey;
+
+ private final Serializable listKey;
+
+ private final ItemData value;
+
+ public RemoveFromPatternListContainer(Fqn fqn, Serializable patternKey, Serializable listKey, ItemData value,
+ Cache<Serializable, Object> cache, int historicalIndex, boolean local, boolean useExpiration, long timeOut)
+ {
+ super(fqn, ChangesType.REMOVE_KEY, cache, historicalIndex, local, useExpiration, timeOut);
+ this.patternKey = patternKey;
+ this.listKey = listKey;
+ this.value = value;
+ }
+
+ @Override
+ public void apply()
+ {
+ // force writeLock on next read
+ cache.getInvocationContext().getOptionOverrides().setForceWriteLock(true);
+ // object found by FQN and key;
+ setCacheLocalMode();
+
+ Iterator<Object> patternNames = cache.getChildrenNames(fqn).iterator();
+ while (patternNames.hasNext())
+ {
+ Fqn<Object> patternFqn = Fqn.fromRelativeElements(fqn, patternNames.next());
+ Object patternObject = cache.get(patternFqn, patternKey);
+ if (!(patternObject instanceof QPathEntryFilter))
+ {
+ LOG.error("Unexpected object found by FQN:" + patternFqn + " and key:" + patternKey
+ + ". Expected QPathEntryFilter, but found:" + patternObject.getClass().getName());
+ continue;
+ }
+ QPathEntryFilter nameFilter = (QPathEntryFilter)patternObject;
+ if (nameFilter.accept((ItemData)value))
+ {
+ Object setObject = cache.get(patternFqn, listKey);
+ if (!(setObject instanceof Set))
+ {
+ LOG.error("Unexpected object found by FQN:" + patternFqn + " and key:" + listKey
+ + ". Expected Set, but found:" + setObject.getClass().getName());
+ continue;
+ }
+ Set<String> newSet = new HashSet<String>((Set<String>)setObject);
+ newSet.remove(value.getIdentifier());
+ cache.put(patternFqn, listKey, newSet);
+ }
+ }
+ }
+
+ @Override
+ public boolean isTxRequired()
+ {
+ return false;
+ }
+ }
+
+ /**
* Remove container.
*/
public static class RemoveKeyContainer extends ChangesContainer
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-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -43,6 +43,7 @@
import org.exoplatform.services.jcr.impl.backup.BackupException;
import org.exoplatform.services.jcr.impl.backup.Backupable;
import org.exoplatform.services.jcr.impl.backup.DataRestore;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
import org.exoplatform.services.jcr.jbosscache.ExoJBossCacheFactory;
@@ -140,6 +141,10 @@
public static final String CHILD_PROPS_LIST = "$CHILD_PROPS_LIST".intern();
+ public static final String CHILD_PROPS_BY_PATTERN_LIST = "$CHILD_PROPS_BY_PATTERN_LIST".intern();
+
+ public static final String CHILD_NODES_BY_PATTERN_LIST = "$CHILD_NODES_BY_PATTERN_LIST".intern();
+
public static final String LOCKS = "$LOCKS".intern();
public static final String REFERENCE = "$REFERENCE".intern();
@@ -150,6 +155,8 @@
public static final String ITEM_LIST = "$lists".intern();
+ public static final String PATTERN_OBJ = "$pattern".intern();
+
protected final BufferedJBossCache cache;
protected final Fqn<String> itemsRoot;
@@ -164,8 +171,12 @@
protected final Fqn<String> childPropsList;
+ protected final Fqn<String> childPropsByPatternList;
+
+ protected final Fqn<String> childNodesByPatternList;
+
protected final Fqn<String> rootFqn;
-
+
private final CacheActionNonTxAware<Void, Void> commitTransaction = new CacheActionNonTxAware<Void, Void>()
{
@Override
@@ -389,7 +400,7 @@
protected Long execute(Void arg) throws RuntimeException
{
// Total number of JBC nodes in the cache - the total amount of resident nodes
- return numNodes(cache.getNode(rootFqn)) - 7;
+ return numNodes(cache.getNode(rootFqn)) - 9;
}
};
@@ -590,6 +601,8 @@
this.childProps = Fqn.fromRelativeElements(rootFqn, CHILD_PROPS);
this.childNodesList = Fqn.fromRelativeElements(rootFqn, CHILD_NODES_LIST);
this.childPropsList = Fqn.fromRelativeElements(rootFqn, CHILD_PROPS_LIST);
+ this.childPropsByPatternList = Fqn.fromRelativeElements(rootFqn, CHILD_PROPS_BY_PATTERN_LIST);
+ this.childNodesByPatternList = Fqn.fromRelativeElements(rootFqn, CHILD_NODES_BY_PATTERN_LIST);
if (cache.getConfiguration().getCacheMode() == CacheMode.LOCAL)
{
@@ -630,6 +643,8 @@
createResidentNode(childNodesList);
createResidentNode(childProps);
createResidentNode(childPropsList);
+ createResidentNode(childPropsByPatternList);
+ createResidentNode(childNodesByPatternList);
createResidentNode(itemsRoot);
this.initialized = true;
@@ -852,6 +867,50 @@
/**
* {@inheritDoc}
*/
+ public void addChildNodes(NodeData parent, QPathEntryFilter pattern, List<NodeData> childs)
+ {
+ boolean inTransaction = cache.isTransactionActive();
+ try
+ {
+
+ if (!inTransaction)
+ {
+ cache.beginTransaction();
+ }
+
+ cache.setLocal(true);
+ Fqn<String> fqn = makeChildFqn(childNodesByPatternList, parent.getIdentifier(), pattern.getQPathEntry());
+ if (childs.size() > 0)
+ {
+ Set<Object> set = new HashSet<Object>();
+ for (NodeData child : childs)
+ {
+ putNode(child, ModifyChildOption.NOT_MODIFY);
+ set.add(child.getIdentifier());
+ }
+
+ cache.putIfAbsent(fqn, PATTERN_OBJ, pattern);
+ cache.putIfAbsent(fqn, ITEM_LIST, set);
+ }
+ else
+ {
+ // cache fact of empty childs list
+ cache.putIfAbsent(fqn, ITEM_LIST, new HashSet<Object>());
+ }
+ }
+ finally
+ {
+ cache.setLocal(false);
+ if (!inTransaction)
+ {
+ dedicatedTxCommit();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void addChildProperties(NodeData parent, List<PropertyData> childs)
{
boolean inTransaction = cache.isTransactionActive();
@@ -892,6 +951,44 @@
/**
* {@inheritDoc}
*/
+ public void addChildProperties(NodeData parent, QPathEntryFilter pattern, List<PropertyData> childProperties)
+ {
+ boolean inTransaction = cache.isTransactionActive();
+ try
+ {
+ if (!inTransaction)
+ {
+ cache.beginTransaction();
+ }
+ cache.setLocal(true);
+ if (childProperties.size() > 0)
+ {
+ // add all new
+ Set<Object> set = new HashSet<Object>();
+ for (PropertyData child : childProperties)
+ {
+ putProperty(child, ModifyChildOption.NOT_MODIFY);
+ set.add(child.getIdentifier());
+ }
+
+ Fqn<String> fqn = makeChildFqn(childPropsByPatternList, parent.getIdentifier(), pattern.getQPathEntry());
+ cache.putIfAbsent(fqn, PATTERN_OBJ, pattern);
+ cache.putIfAbsent(fqn, ITEM_LIST, set);
+ }
+ }
+ finally
+ {
+ cache.setLocal(false);
+ if (!inTransaction)
+ {
+ dedicatedTxCommit();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public void addChildPropertiesList(NodeData parent, List<PropertyData> childProperties)
{
// TODO not implemented, will force read from DB
@@ -932,6 +1029,45 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodes(final NodeData parent, final QPathEntryFilter pattern)
+ {
+ // empty Set<Object> marks that there is no child nodes
+ // get list of children uuids
+
+ final Set<Object> set =
+ (Set<Object>)cache.get(makeChildFqn(childNodesByPatternList, parent.getIdentifier(), pattern.getQPathEntry()),
+ ITEM_LIST);
+
+ if (set != null)
+ {
+ final List<NodeData> childs = new ArrayList<NodeData>();
+
+ for (Object child : set)
+ {
+ NodeData node = (NodeData)cache.get(makeItemFqn((String)child), ITEM_DATA);
+
+ if (node == null || node instanceof NullItemData)
+ {
+ return null;
+ }
+
+ childs.add(node);
+ }
+
+ // order children by orderNumber, as HashSet returns children in other order
+ Collections.sort(childs, new NodesOrderComparator<NodeData>());
+
+ return childs;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getChildNodesCount(NodeData parent)
{
return getChildNodesCount.run(parent);
@@ -948,6 +1084,41 @@
/**
* {@inheritDoc}
*/
+ public List<PropertyData> getChildProperties(NodeData parent, QPathEntryFilter pattern)
+ {
+ // get set of property uuids
+ final Set<Object> set =
+ (Set<Object>)cache.get(makeChildFqn(childPropsByPatternList, parent.getIdentifier(), pattern.getQPathEntry()),
+ ITEM_LIST);
+ if (set != null)
+ {
+ final List<PropertyData> childs = new ArrayList<PropertyData>();
+
+ for (Object child : set)
+ {
+ PropertyData prop = (PropertyData)cache.get(makeItemFqn((String)child), ITEM_DATA);
+ if (prop == null || prop instanceof NullItemData)
+ {
+ return null;
+ }
+ if (prop.getValues().size() <= 0)
+ {
+ // don't return list of empty-valued props (but listChildProperties() can)
+ return null;
+ }
+ childs.add(prop);
+ }
+ return childs;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> listChildProperties(NodeData parent)
{
return getChildProps(parent.getIdentifier(), false);
@@ -1038,6 +1209,14 @@
return enabled && initialized;
}
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isPatternSupported()
+ {
+ return true;
+ }
+
// non-public members
/**
@@ -1159,8 +1338,10 @@
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
- cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()), ITEM_LIST, node
- .getIdentifier(), modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
+ cache.addToPatternList(makeChildListFqn(childNodesByPatternList, node.getParentIdentifier()), PATTERN_OBJ,
+ ITEM_LIST, node);
+ cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()), ITEM_LIST,
+ node.getIdentifier(), modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
}
}
@@ -1252,6 +1433,8 @@
if (modifyListsOfChild != ModifyChildOption.NOT_MODIFY)
{
+ cache.addToPatternList(makeChildListFqn(childPropsByPatternList, prop.getParentIdentifier()), PATTERN_OBJ,
+ ITEM_LIST, prop);
cache.addToList(makeChildListFqn(childPropsList, prop.getParentIdentifier()), ITEM_LIST, prop.getIdentifier(),
modifyListsOfChild == ModifyChildOption.FORCE_MODIFY);
}
@@ -1319,6 +1502,10 @@
cache.removeNode(makeChildListFqn(childPropsList, item.getIdentifier()));
}
+ cache.removeFromPatternList(makeChildListFqn(childNodesByPatternList, item.getParentIdentifier()),
+ PATTERN_OBJ, ITEM_LIST, item);
+ cache.removeNode(makeChildListFqn(childNodesByPatternList, item.getIdentifier()));
+ cache.removeNode(makeChildListFqn(childPropsByPatternList, item.getIdentifier()));
cache.removeNode(makeRefFqn(item.getIdentifier()));
}
else
@@ -1330,6 +1517,9 @@
// remove from CHILD_PROPS_LIST
cache.removeFromList(makeChildListFqn(childPropsList, item.getParentIdentifier()), ITEM_LIST, item
.getIdentifier());
+
+ cache.removeFromPatternList(makeChildListFqn(childPropsByPatternList, item.getParentIdentifier()),
+ PATTERN_OBJ, ITEM_LIST, item);
}
// remove from ITEMS
cache.removeNode(makeItemFqn(item.getIdentifier()));
@@ -1704,6 +1894,8 @@
cache.removeNode(childProps);
cache.removeNode(childNodesList);
cache.removeNode(childPropsList);
+ cache.removeNode(childNodesByPatternList);
+ cache.removeNode(childPropsByPatternList);
cache.commitTransaction();
@@ -1712,6 +1904,8 @@
createResidentNode(childNodesList);
createResidentNode(childProps);
createResidentNode(childPropsList);
+ createResidentNode(childNodesByPatternList);
+ createResidentNode(childPropsByPatternList);
createResidentNode(itemsRoot);
}
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/LocalWorkspaceStorageDataManagerProxy.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -32,6 +32,7 @@
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
import org.exoplatform.services.jcr.impl.dataflow.AbstractPersistedValueData;
import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
@@ -135,6 +136,14 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> patternFilters) throws RepositoryException
+ {
+ return copyNodes(storageDataManager.getChildNodesData(parent, patternFilters));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getLastOrderNumber(final NodeData parent) throws RepositoryException
{
return storageDataManager.getLastOrderNumber(parent);
@@ -159,6 +168,15 @@
/**
* {@inheritDoc}
*/
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ return copyProperties(storageDataManager.getChildPropertiesData(parent, itemDataFilters));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException
{
return copyPropertiesWithoutValues(storageDataManager.listChildPropertiesData(parent));
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/session/TransactionableDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -30,6 +30,7 @@
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.persistent.LocalWorkspaceDataManagerStub;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -101,6 +102,34 @@
return nodes;
}
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> patternFilters) throws RepositoryException
+ {
+ List<NodeData> nodes = storageDataManager.getChildNodesData(parent, patternFilters);
+
+ if (txStarted())
+ {
+ // merge data
+ List<ItemState> txChanges = transactionLog.getChildrenChanges(parent.getIdentifier(), true);
+ if (txChanges.size() > 0)
+ {
+ List<NodeData> res = new ArrayList<NodeData>(nodes);
+
+ for (ItemState state : txChanges)
+ {
+ res.remove(state.getData());
+ if (!state.isDeleted())
+ {
+ res.add((NodeData)state.getData());
+ }
+ }
+
+ return Collections.unmodifiableList(res);
+ }
+ }
+
+ return nodes;
+ }
+
/**
* {@inheritDoc}
*/
@@ -204,6 +233,37 @@
/**
* {@inheritDoc}
*/
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException
+ {
+ List<PropertyData> props = storageDataManager.getChildPropertiesData(parent, itemDataFilters);
+
+ if (txStarted())
+ {
+ // merge data
+ List<ItemState> txChanges = transactionLog.getChildrenChanges(parent.getIdentifier(), false);
+ if (txChanges.size() > 0)
+ {
+ List<PropertyData> res = new ArrayList<PropertyData>(props);
+ for (ItemState state : txChanges)
+ {
+ res.remove(state.getData());
+ if (!state.isDeleted())
+ {
+ res.add((PropertyData)state.getData());
+ }
+ }
+
+ return Collections.unmodifiableList(res);
+ }
+ }
+
+ return props;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException
{
List<PropertyData> props = storageDataManager.listChildPropertiesData(parent);
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/inmemory/InmemoryStorageConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -25,6 +25,7 @@
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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -119,11 +120,23 @@
return null;
}
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ return getChildNodesData(parent);
+ }
+
public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException
{
return null;
}
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern)
+ throws RepositoryException, IllegalStateException
+ {
+ return getChildPropertiesData(parent);
+ }
+
public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException
{
return null;
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/JDBCStorageConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -36,6 +36,7 @@
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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.persistent.ByteArrayPersistedValueData;
import org.exoplatform.services.jcr.impl.dataflow.persistent.CleanableFilePersistedValueData;
import org.exoplatform.services.jcr.impl.dataflow.persistent.StreamPersistedValueData;
@@ -942,6 +943,16 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ //return all child nodes by default
+ return getChildNodesData(parent);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public int getLastOrderNumber(NodeData parent) throws RepositoryException
{
checkIfOpened();
@@ -1056,6 +1067,16 @@
}
/**
+ * {@inheritDoc}
+ */
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilter)
+ throws RepositoryException, IllegalStateException
+ {
+ //return all child properties by default
+ return getChildPropertiesData(parent);
+ }
+
+ /**
* GetNodesAndProperties.
*
* @param lastNodeId the id if the last doc get from the db
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCStorageConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -33,6 +33,7 @@
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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.persistent.StreamPersistedValueData;
import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCStorageConnection;
@@ -53,6 +54,7 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -98,6 +100,16 @@
protected String FIND_NODE_MAIN_PROPERTIES_BY_PARENTID_CQ;
/**
+ * FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE;
+ */
+ protected String FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE;
+
+ /**
+ * FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE;
+ */
+ protected String FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE;
+
+ /**
* FIND_ITEM_QPATH_BY_ID_CQ.
*/
protected String FIND_ITEM_QPATH_BY_ID_CQ;
@@ -131,6 +143,10 @@
protected PreparedStatement updateValue;
+ protected Statement findPropertiesByParentIdAndComplexPatternCQ;
+
+ protected Statement findNodesByParentIdAndComplexPatternCQ;
+
/**
* JDBCStorageConnection constructor.
*
@@ -226,6 +242,73 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ checkIfOpened();
+ ResultSet resultSet = null;
+ try
+ {
+ // query will return nodes and properties in same result set
+ resultSet = findChildNodesByParentIdentifierCQ(getInternalId(parent.getIdentifier()), pattern);
+ TempNodeData data = null;
+ List<NodeData> childNodes = new ArrayList<NodeData>();
+ while (resultSet.next())
+ {
+ if (data == null)
+ {
+ data = new TempNodeData(resultSet);
+ }
+ else if (!resultSet.getString(COLUMN_ID).equals(data.cid))
+ {
+ NodeData nodeData = loadNodeFromTemporaryNodeData(data, parent.getQPath(), parent.getACL());
+ childNodes.add(nodeData);
+ data = new TempNodeData(resultSet);
+ }
+ Map<String, SortedSet<TempPropertyData>> properties = data.properties;
+ String key = resultSet.getString("PROP_NAME");
+ SortedSet<TempPropertyData> values = properties.get(key);
+ if (values == null)
+ {
+ values = new TreeSet<TempPropertyData>();
+ properties.put(key, values);
+ }
+ values.add(new TempPropertyData(resultSet));
+ }
+ if (data != null)
+ {
+ NodeData nodeData = loadNodeFromTemporaryNodeData(data, parent.getQPath(), parent.getACL());
+ childNodes.add(nodeData);
+ }
+ return childNodes;
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryException(e);
+ }
+ finally
+ {
+ if (resultSet != null)
+ {
+ try
+ {
+ resultSet.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the ResultSet: " + e);
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
@Override
public void update(PropertyData data) throws RepositoryException, UnsupportedOperationException,
InvalidItemStateException, IllegalStateException
@@ -518,7 +601,107 @@
}
}
}
+ }
+ /**
+ * {@inheritDoc}
+ */
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> itemDataFilters)
+ throws RepositoryException, IllegalStateException
+ {
+ checkIfOpened();
+ ResultSet resultSet = null;
+ try
+ {
+ resultSet = findChildPropertiesByParentIdentifierCQ(getInternalId(parent.getIdentifier()), itemDataFilters);
+ List<PropertyData> children = new ArrayList<PropertyData>();
+
+ QPath parentPath = parent.getQPath();
+
+ if (resultSet.next())
+ {
+ boolean isNotLast = true;
+
+ do
+ {
+ // read property data
+ String cid = resultSet.getString(COLUMN_ID);
+ String identifier = getIdentifier(cid);
+
+ String cname = resultSet.getString(COLUMN_NAME);
+ int cversion = resultSet.getInt(COLUMN_VERSION);
+
+ String cpid = resultSet.getString(COLUMN_PARENTID);
+ // if parent ID is empty string - it's a root node
+
+ int cptype = resultSet.getInt(COLUMN_PTYPE);
+ boolean cpmultivalued = resultSet.getBoolean(COLUMN_PMULTIVALUED);
+ QPath qpath;
+ try
+ {
+ qpath =
+ QPath.makeChildPath(parentPath == null ? traverseQPath(cpid) : parentPath,
+ InternalQName.parse(cname));
+ }
+ catch (IllegalNameException e)
+ {
+ throw new RepositoryException(e.getMessage(), e);
+ }
+
+ // read values
+ List<ValueData> data = new ArrayList<ValueData>();
+ do
+ {
+ int orderNum = resultSet.getInt(COLUMN_VORDERNUM);
+ // check is there value columns
+ if (!resultSet.wasNull())
+ {
+ final String storageId = resultSet.getString(COLUMN_VSTORAGE_DESC);
+ ValueData vdata =
+ resultSet.wasNull() ? readValueData(cid, orderNum, cversion,
+ resultSet.getBinaryStream(COLUMN_VDATA)) : readValueData(identifier, orderNum, storageId);
+ data.add(vdata);
+ }
+
+ isNotLast = resultSet.next();
+ }
+ while (isNotLast && resultSet.getString(COLUMN_ID).equals(cid));
+
+ // To avoid using a temporary table, we sort the values manually
+ Collections.sort(data, COMPARATOR_VALUE_DATA);
+ //create property
+ PersistedPropertyData pdata =
+ new PersistedPropertyData(identifier, qpath, getIdentifier(cpid), cversion, cptype, cpmultivalued,
+ data);
+
+ children.add(pdata);
+ }
+ while (isNotLast);
+ }
+ return children;
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ catch (IOException e)
+ {
+ throw new RepositoryException(e);
+ }
+ finally
+ {
+ if (resultSet != null)
+ {
+ try
+ {
+ resultSet.close();
+ }
+ catch (SQLException e)
+ {
+ LOG.error("Can't close the ResultSet: " + e);
+ }
+ }
+ }
}
/**
@@ -925,6 +1108,16 @@
{
updateValue.close();
}
+
+ if (findPropertiesByParentIdAndComplexPatternCQ != null)
+ {
+ findPropertiesByParentIdAndComplexPatternCQ.close();
+ }
+
+ if (findNodesByParentIdAndComplexPatternCQ != null)
+ {
+ findNodesByParentIdAndComplexPatternCQ.close();
+ }
}
catch (SQLException e)
{
@@ -936,8 +1129,14 @@
protected abstract ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier) throws SQLException;
+ protected abstract ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier,
+ List<QPathEntryFilter> patternList) throws SQLException;
+
protected abstract ResultSet findChildPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException;
+ protected abstract ResultSet findChildPropertiesByParentIdentifierCQ(String parentIdentifier,
+ List<QPathEntryFilter> patternList) throws SQLException;
+
protected abstract ResultSet findNodeMainPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException;
protected abstract ResultSet findPropertyById(String id) throws SQLException;
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/CQJDBCWorkspaceDataContainer.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -35,6 +35,7 @@
import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db.MSSQLConnectionFactory;
import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db.MySQLConnectionFactory;
import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db.OracleConnectionFactory;
+import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db.PostgreConnectionFactory;
import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db.SybaseConnectionFactory;
import org.exoplatform.services.jcr.impl.util.io.FileCleanerHolder;
import org.exoplatform.services.jcr.impl.util.jdbc.DBInitializerException;
@@ -46,7 +47,9 @@
import java.io.IOException;
import javax.jcr.RepositoryException;
+import javax.naming.InitialContext;
import javax.naming.NamingException;
+import javax.sql.DataSource;
/**
* Created by The eXo Platform SAS.
@@ -134,6 +137,25 @@
else if (dbDialect == DBConstants.DB_DIALECT_PGSQL)
{
this.connFactory = defaultConnectionFactory();
+
+ if (dbSourceName != null)
+ {
+ DataSource ds = (DataSource)new InitialContext().lookup(dbSourceName);
+ if (ds != null)
+ this.connFactory =
+ new PostgreConnectionFactory(ds, containerName, multiDb, valueStorageProvider, maxBufferSize,
+ swapDirectory, swapCleaner);
+ else
+ throw new RepositoryException("Datasource '" + dbSourceName + "' is not bound in this context.");
+ }
+ else
+ this.connFactory =
+ new PostgreConnectionFactory(dbDriver, dbUrl, dbUserName, dbPassword, containerName, multiDb,
+ valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+
+ sqlPath = "/conf/storage/jcr-" + (multiDb ? "m" : "s") + "jdbc.mysql.sql";
+ dbInitilizer = defaultDBInitializer(sqlPath);
+
sqlPath = "/conf/storage/jcr-" + (multiDb ? "m" : "s") + "jdbc.pgsql.sql";
dbInitilizer = new PgSQLDBInitializer(containerName, this.connFactory.getJdbcConnection(), sqlPath, multiDb);
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBMultiDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -21,6 +21,7 @@
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.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
@@ -31,6 +32,7 @@
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.List;
import javax.jcr.InvalidItemStateException;
@@ -218,7 +220,47 @@
});
}
+ /**
+ * {@inheritDoc}
+ */
@Override
+ protected ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findNodesByParentIdAndComplexPatternCQ == null)
+ {
+ findNodesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.PARENT_ID='");
+ query.append(parentIdentifier);
+ query.append("' and I.I_CLASS=1 and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), true);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), true);
+ }
+ query.append(" ) and (P.PARENT_ID=I.ID and P.I_CLASS=2 and (P.NAME='[http://www.jcp.org/jcr/1.0]primaryType'");
+ query.append(" or P.NAME='[http://www.jcp.org/jcr/1.0]mixinTypes'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]owner'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]permissions')");
+ query.append(" and V.PROPERTY_ID=P.ID) order by I.N_ORDER_NUM, I.ID");
+
+ return findNodesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+
+ }
+
+ @Override
protected ResultSet findLastOrderNumberByParentIdentifier(final String parentIdentifier) throws SQLException
{
return SecurityHelper.doPrivilegedSQLExceptionAction(new PrivilegedExceptionAction<ResultSet>()
@@ -254,7 +296,42 @@
});
}
+ /**
+ * {@inheritDoc}
+ */
@Override
+ protected ResultSet findChildPropertiesByParentIdentifierCQ(String parentCid, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findPropertiesByParentIdAndComplexPatternCQ == null)
+ {
+ findPropertiesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.PARENT_ID='");
+ query.append(parentCid);
+ query.append("' and I.I_CLASS=2 and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), false);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), false);
+ }
+ query.append(" ) order by I.NAME");
+
+ return findPropertiesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+ }
+
+ @Override
protected ResultSet findChildPropertiesByParentIdentifierCQ(final String parentIdentifier) throws SQLException
{
return SecurityHelper.doPrivilegedSQLExceptionAction(new PrivilegedExceptionAction<ResultSet>()
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/HSQLDBSingleDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -21,6 +21,7 @@
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.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
@@ -31,6 +32,7 @@
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.List;
import javax.jcr.InvalidItemStateException;
@@ -296,6 +298,49 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findNodesByParentIdAndComplexPatternCQ == null)
+ {
+ findNodesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.PARENT_ID='");
+ query.append(parentIdentifier);
+ query.append("' and I.I_CLASS=1 and I.CONTAINER_NAME='");
+ query.append(containerName);
+ query.append("' and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), true);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), true);
+ }
+ query.append(" ) and P.PARENT_ID=I.ID and P.I_CLASS=2 and P.CONTAINER_NAME='");
+ query.append(containerName);
+ query.append("' and (P.NAME='[http://www.jcp.org/jcr/1.0]primaryType'");
+ query.append(" or P.NAME='[http://www.jcp.org/jcr/1.0]mixinTypes'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]owner'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]permissions')");
+ query.append(" and V.PROPERTY_ID=P.ID order by I.N_ORDER_NUM, I.ID");
+
+ return findNodesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException
{
if (findPropertiesByParentIdCQ == null)
@@ -320,6 +365,43 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findChildPropertiesByParentIdentifierCQ(String parentCid, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findPropertiesByParentIdAndComplexPatternCQ == null)
+ {
+ findPropertiesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.PARENT_ID='");
+ query.append(parentCid);
+ query.append("' and I.I_CLASS=2 and I.CONTAINER_NAME='");
+ query.append(containerName);
+ query.append("' and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), false);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), false);
+ }
+ query.append(" ) order by I.NAME");
+
+ return findPropertiesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected int addNodeRecord(final NodeData data) throws SQLException
{
PrivilegedExceptionAction<Integer> action = new PrivilegedExceptionAction<Integer>()
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MultiDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -20,8 +20,10 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
+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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.ValueDataConvertor;
import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCStorageConnection;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
@@ -62,6 +64,8 @@
+ " V.ORDER_NUM, V.DATA, V.STORAGE_DESC from JCR_MITEM I LEFT OUTER JOIN JCR_MVALUE V ON (V.PROPERTY_ID=I.ID)"
+ " where I.I_CLASS=2 and I.PARENT_ID=? order by I.NAME";
+ protected String PATTERN_ESCAPE_STRING = "\\"; //valid for HSQL, Sybase, DB2, MSSQL, ORACLE
+
/**
* Multidatabase JDBC Connection constructor.
*
@@ -163,6 +167,13 @@
// property may contain no values
FIND_PROPERTIES_BY_PARENTID_CQ = FIND_PROPERTIES_BY_PARENTID_CQ_QUERY;
+ FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE =
+ "select I.ID, I.PARENT_ID, I.NAME, I.VERSION, I.I_CLASS, I.I_INDEX, I.N_ORDER_NUM, I.P_TYPE, I.P_MULTIVALUED,"
+ + " V.ORDER_NUM, V.DATA, V.STORAGE_DESC from JCR_MITEM I LEFT OUTER JOIN JCR_MVALUE V ON (V.PROPERTY_ID=I.ID)";
+
+ FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE =
+ "select I.*, P.NAME AS PROP_NAME, V.ORDER_NUM, V.DATA from JCR_MITEM I, JCR_MITEM P, JCR_MVALUE V";
+
INSERT_NODE =
"insert into JCR_MITEM(ID, PARENT_ID, NAME, VERSION, I_CLASS, I_INDEX, N_ORDER_NUM) VALUES(?,?,?,?,"
+ I_CLASS_NODE + ",?,?)";
@@ -431,6 +442,45 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findNodesByParentIdAndComplexPatternCQ == null)
+ {
+ findNodesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.I_CLASS=1 and I.PARENT_ID='");
+ query.append(parentIdentifier);
+ query.append("' and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), true);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), true);
+ }
+ query.append(" ) and P.I_CLASS=2 and P.PARENT_ID=I.ID and (P.NAME='[http://www.jcp.org/jcr/1.0]primaryType'");
+ query.append(" or P.NAME='[http://www.jcp.org/jcr/1.0]mixinTypes'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]owner'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]permissions')");
+ query.append(" and V.PROPERTY_ID=P.ID order by I.N_ORDER_NUM, I.ID");
+
+ return findNodesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findLastOrderNumberByParentIdentifier(String parentIdentifier) throws SQLException
{
if (findLastOrderNumberByParentId == null)
@@ -472,6 +522,42 @@
return findPropertiesByParentId.executeQuery();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected ResultSet findChildPropertiesByParentIdentifierCQ(String parentCid, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findPropertiesByParentIdAndComplexPatternCQ == null)
+ {
+ findPropertiesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.I_CLASS=2 and I.PARENT_ID='");
+ query.append(parentCid);
+ query.append("' and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), false);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), false);
+ }
+ query.append(" ) order by I.NAME");
+
+ return findPropertiesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+
+ }
+ }
+
// -------- values processing ------------
/**
@@ -703,4 +789,78 @@
return findNodesAndProperties.executeQuery();
}
+
+ /**
+ * Replace underscore in pattern with escaped symbol. Replace jcr-wildcard '*' with sql-wildcard '%'.
+ *
+ * @param pattern
+ * @return pattern with escaped underscore and fixed wildcard symbols
+ */
+ protected String fixEscapeSymbols(String pattern)
+ {
+ char[] chars = pattern.toCharArray();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < chars.length; i++)
+ {
+ switch (chars[i])
+ {
+ case '*' :
+ sb.append('%');
+ break;
+ case '_' :
+ case '%' :
+ sb.append(getWildcardEscapeSymbold());
+ default :
+ sb.append(chars[i]);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Append pattern expression.
+ * Appends String "I.NAME LIKE 'escaped pattern' ESCAPE 'escapeString'" or "I.NAME='pattern'"
+ * to String builder sb.
+ *
+ * @param sb StringBuilder
+ * @param indexConstraint
+ * @param pattern
+ */
+ protected void appendPattern(StringBuilder sb, QPathEntry entry, boolean indexConstraint)
+ {
+ String pattern = entry.getAsString(false);
+ sb.append("(I.NAME");
+ if (pattern.contains("*"))
+ {
+ sb.append(" LIKE '");
+ sb.append(fixEscapeSymbols(pattern));
+ sb.append("' ESCAPE '");
+ sb.append(getLikeExpressionEscape());
+ sb.append("'");
+ }
+ else
+ {
+ sb.append("='");
+ sb.append(pattern);
+ sb.append("'");
+ }
+
+ if (indexConstraint && entry.getIndex() != -1)
+ {
+ sb.append(" and I_INDEX=");
+ sb.append(entry.getIndex());
+
+ }
+ sb.append(")");
+ }
+
+ protected String getWildcardEscapeSymbold()
+ {
+ return PATTERN_ESCAPE_STRING;
+ }
+
+ protected String getLikeExpressionEscape()
+ {
+ return PATTERN_ESCAPE_STRING;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLMultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLMultiDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLMultiDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -39,6 +39,8 @@
public class MySQLMultiDbJDBCConnection extends MultiDbJDBCConnection
{
+ protected String PATTERN_ESCAPE_STRING = "\\\\";
+
/**
* MySQL Multidatabase JDBC Connection constructor.
*
@@ -72,6 +74,15 @@
* {@inheritDoc}
*/
@Override
+ protected void prepareQueries() throws SQLException
+ {
+ super.prepareQueries();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected int addNodeRecord(NodeData data) throws SQLException
{
// check if parent exists
@@ -128,4 +139,10 @@
return super.addPropertyRecord(data);
}
+ @Override
+ protected String getLikeExpressionEscape()
+ {
+ // must be .. LIKE 'prop\\_name' ESCAPE '\\\\'
+ return this.PATTERN_ESCAPE_STRING;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLSingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLSingleDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/MySQLSingleDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -39,6 +39,8 @@
public class MySQLSingleDbJDBCConnection extends SingleDbJDBCConnection
{
+ protected static final String PATTERN_ESCAPE_STRING = "\\\\";
+
/**
* MySQL Singledatabase JDBC Connection constructor.
*
@@ -72,6 +74,15 @@
* {@inheritDoc}
*/
@Override
+ protected void prepareQueries() throws SQLException
+ {
+ super.prepareQueries();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected int addNodeRecord(NodeData data) throws SQLException
{
// check if parent exists
@@ -128,4 +139,9 @@
return super.addPropertyRecord(data);
}
+ protected String getLikeExpressionEscape()
+ {
+ // must be .. LIKE 'prop\\_name' ESCAPE '\\\\'
+ return this.PATTERN_ESCAPE_STRING;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleMultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleMultiDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleMultiDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -80,6 +80,10 @@
super.prepareQueries();
FIND_NODES_BY_PARENTID_CQ = FIND_NODES_BY_PARENTID_CQ_QUERY;
FIND_PROPERTIES_BY_PARENTID_CQ = FIND_PROPERTIES_BY_PARENTID_CQ_QUERY;
+ FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE =
+ "select /*+ INDEX(I JCR_IDX_MITEM_PARENT_ID) INDEX(V JCR_IDX_MVALUE_PROPERTY)*/ I.ID, I.PARENT_ID, I.NAME, I.VERSION, I.I_CLASS, I.I_INDEX, I.N_ORDER_NUM, I.P_TYPE, I.P_MULTIVALUED,"
+ + " V.ORDER_NUM, V.DATA, V.STORAGE_DESC from JCR_MITEM I LEFT OUTER JOIN JCR_MVALUE V ON (V.PROPERTY_ID=I.ID)";
+
FIND_NODES_AND_PROPERTIES =
"select J.*, P.ID AS P_ID, P.NAME AS P_NAME, P.VERSION AS P_VERSION, P.P_TYPE, P.P_MULTIVALUED,"
+ " V.DATA, V.ORDER_NUM, V.STORAGE_DESC from JCR_MVALUE V, JCR_MITEM P"
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleSingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleSingleDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/OracleSingleDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -81,6 +81,10 @@
super.prepareQueries();
FIND_NODES_BY_PARENTID_CQ = FIND_NODES_BY_PARENTID_CQ_QUERY;
FIND_PROPERTIES_BY_PARENTID_CQ = FIND_PROPERTIES_BY_PARENTID_CQ_QUERY;
+ FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE =
+ "select /*+ INDEX(I JCR_IDX_SITEM_PARENT_ID) INDEX(V JCR_IDX_SVALUE_PROPERTY)*/ I.ID, I.PARENT_ID, I.NAME, I.VERSION, I.I_CLASS, I.I_INDEX, I.N_ORDER_NUM, I.P_TYPE, I.P_MULTIVALUED, V.ORDER_NUM,"
+ + " V.DATA, V.STORAGE_DESC from JCR_SITEM I LEFT OUTER JOIN JCR_SVALUE V ON (V.PROPERTY_ID=I.ID)";
+
FIND_NODES_AND_PROPERTIES =
"select J.*, P.ID AS P_ID, P.NAME AS P_NAME, P.VERSION AS P_VERSION, P.P_TYPE, P.P_MULTIVALUED,"
+ " V.DATA, V.ORDER_NUM, V.STORAGE_DESC from JCR_SVALUE V, JCR_SITEM P"
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreConnectionFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreConnectionFactory.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreConnectionFactory.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db;
+
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+
+import java.io.File;
+import java.sql.SQLException;
+
+import javax.jcr.RepositoryException;
+import javax.sql.DataSource;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: PostgreConnectionFactory.java 111 4.05.2011 serg $
+ */
+public class PostgreConnectionFactory extends GenericCQConnectionFactory
+{
+ /**
+ * PostgreConnectionFactory constructor.
+ *
+ *@param dataSource
+ * - DataSource
+ * @param dbDriver
+ * - JDBC Driver
+ * @param dbUrl
+ * - JDBC URL
+ * @param dbUserName
+ * - database username
+ * @param dbPassword
+ * - database user password
+ * @param containerName
+ * - Container name (see configuration)
+ * @param multiDb
+ * - multidatabase state flag
+ * @param valueStorageProvider
+ * - external Value Storages provider
+ * @param maxBufferSize
+ * - Maximum buffer size (see configuration)
+ * @param swapDirectory
+ * - Swap directory (see configuration)
+ * @param swapCleaner
+ * - Swap cleaner (internal FileCleaner).
+ * @throws RepositoryException
+ * if error eccurs
+ */
+ public PostgreConnectionFactory(String dbDriver, String dbUrl, String dbUserName, String dbPassword,
+ String containerName, boolean multiDb, ValueStoragePluginProvider valueStorageProvider, int maxBufferSize,
+ File swapDirectory, FileCleaner swapCleaner) throws RepositoryException
+ {
+
+ super(dbDriver, dbUrl, dbUserName, dbPassword, containerName, multiDb, valueStorageProvider, maxBufferSize,
+ swapDirectory, swapCleaner);
+ }
+
+ /**
+ * PostgreConnectionFactory constructor.
+ *
+ * @param dataSource
+ * - DataSource
+ * @param containerName
+ * - Container name (see configuration)
+ * @param multiDb
+ * - multidatabase state flag
+ * @param valueStorageProvider
+ * - external Value Storages provider
+ * @param maxBufferSize
+ * - Maximum buffer size (see configuration)
+ * @param swapDirectory
+ * - Swap directory (see configuration)
+ * @param swapCleaner
+ * - Swap cleaner (internal FileCleaner).
+ */
+ public PostgreConnectionFactory(DataSource dbDataSource, String containerName, boolean multiDb,
+ ValueStoragePluginProvider valueStorageProvider, int maxBufferSize, File swapDirectory, FileCleaner swapCleaner)
+ {
+
+ super(dbDataSource, containerName, multiDb, valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public WorkspaceStorageConnection openConnection(boolean readOnly) throws RepositoryException
+ {
+ try
+ {
+
+ if (multiDb)
+ {
+ return new PostgreMultiDbJDBCConnection(getJdbcConnection(readOnly), readOnly, containerName,
+ valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ return new PostgreSingleDbJDBCConnection(getJdbcConnection(readOnly), readOnly, containerName,
+ valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreMultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreMultiDbJDBCConnection.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreMultiDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db;
+
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: PostgreMultiDBJDBCConnection.java 111 4.05.2011 serg $
+ */
+public class PostgreMultiDbJDBCConnection extends MultiDbJDBCConnection
+{
+ protected String PATTERN_ESCAPE_STRING = "\\\\";
+
+ public PostgreMultiDbJDBCConnection(Connection dbConnection, boolean readOnly, String containerName,
+ ValueStoragePluginProvider valueStorageProvider, int maxBufferSize, File swapDirectory, FileCleaner swapCleaner)
+ throws SQLException
+ {
+ super(dbConnection, readOnly, containerName, valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void prepareQueries() throws SQLException
+ {
+ super.prepareQueries();
+ }
+
+ @Override
+ protected String getLikeExpressionEscape()
+ {
+ // must be .. LIKE 'prop\\_name' ESCAPE '\\\\'
+ return this.PATTERN_ESCAPE_STRING;
+ }
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreSingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreSingleDbJDBCConnection.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/PostgreSingleDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db;
+
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: PostgreSingleDbJDBCConnection.java 111 4.05.2011 serg $
+ */
+public class PostgreSingleDbJDBCConnection extends SingleDbJDBCConnection
+{
+ protected static final String PATTERN_ESCAPE_STRING = "\\\\";
+
+ public PostgreSingleDbJDBCConnection(Connection dbConnection, boolean readOnly, String containerName,
+ ValueStoragePluginProvider valueStorageProvider, int maxBufferSize, File swapDirectory, FileCleaner swapCleaner)
+ throws SQLException
+ {
+ super(dbConnection, readOnly, containerName, valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void prepareQueries() throws SQLException
+ {
+ super.prepareQueries();
+ }
+
+ protected String getLikeExpressionEscape()
+ {
+ // must be .. LIKE 'prop\\_name' ESCAPE '\\\\'
+ return this.PATTERN_ESCAPE_STRING;
+ }
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SingleDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -20,8 +20,10 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
+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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCStorageConnection;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
@@ -60,6 +62,8 @@
+ " V.DATA, V.STORAGE_DESC from JCR_SITEM I LEFT OUTER JOIN JCR_SVALUE V ON (V.PROPERTY_ID=I.ID)"
+ " where I.I_CLASS=2 and I.CONTAINER_NAME=? and I.PARENT_ID=? order by I.NAME";
+ protected static final String PATTERN_ESCAPE_STRING = "\\"; //valid for HSQL, Sybase, DB2, MSSQL, ORACLE
+
/**
* Singledatabase JDBC Connection constructor.
*
@@ -169,7 +173,13 @@
"select * from JCR_SITEM" + " where I_CLASS=2 and CONTAINER_NAME=? and PARENT_ID=?" + " order by NAME";
FIND_PROPERTIES_BY_PARENTID_CQ = FIND_PROPERTIES_BY_PARENTID_CQ_QUERY;
+ FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE =
+ "select I.ID, I.PARENT_ID, I.NAME, I.VERSION, I.I_CLASS, I.I_INDEX, I.N_ORDER_NUM, I.P_TYPE, I.P_MULTIVALUED, V.ORDER_NUM,"
+ + " V.DATA, V.STORAGE_DESC from JCR_SITEM I LEFT OUTER JOIN JCR_SVALUE V ON (V.PROPERTY_ID=I.ID)";
+ FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE =
+ "select I.*, P.NAME AS PROP_NAME, V.ORDER_NUM, V.DATA from JCR_SITEM I, JCR_SITEM P, JCR_SVALUE V";
+
INSERT_NODE =
"insert into JCR_SITEM(ID, PARENT_ID, NAME, CONTAINER_NAME, VERSION, I_CLASS, I_INDEX, N_ORDER_NUM) VALUES(?,?,?,?,?,"
+ I_CLASS_NODE + ",?,?)";
@@ -610,6 +620,48 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findChildNodesByParentIdentifierCQ(String parentIdentifier, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findNodesByParentIdAndComplexPatternCQ == null)
+ {
+ findNodesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_NODES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.I_CLASS=1 and I.CONTAINER_NAME='");
+ query.append(containerName);
+ query.append("' and I.PARENT_ID='");
+ query.append(parentIdentifier);
+ query.append("' and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), true);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), true);
+ }
+ query.append(" ) and P.I_CLASS=2 and P.CONTAINER_NAME='");
+ query.append(containerName);
+ query.append("' and P.PARENT_ID=I.ID and (P.NAME='[http://www.jcp.org/jcr/1.0]primaryType'");
+ query.append(" or P.NAME='[http://www.jcp.org/jcr/1.0]mixinTypes'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]owner'");
+ query.append(" or P.NAME='[http://www.exoplatform.com/jcr/exo/1.0]permissions')");
+ query.append(" and V.PROPERTY_ID=P.ID order by I.N_ORDER_NUM, I.ID");
+
+ return findNodesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findChildPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException
{
if (findPropertiesByParentIdCQ == null)
@@ -627,6 +679,42 @@
* {@inheritDoc}
*/
@Override
+ protected ResultSet findChildPropertiesByParentIdentifierCQ(String parentCid, List<QPathEntryFilter> pattern)
+ throws SQLException
+ {
+ if (pattern.isEmpty())
+ {
+ throw new SQLException("Pattern list is empty.");
+ }
+ else
+ {
+ if (findPropertiesByParentIdAndComplexPatternCQ == null)
+ {
+ findPropertiesByParentIdAndComplexPatternCQ = dbConnection.createStatement();
+ }
+ //create query from list
+ StringBuilder query = new StringBuilder(FIND_PROPERTIES_BY_PARENTID_AND_PATTERN_CQ_TEMPLATE);
+ query.append(" where I.I_CLASS=2 and I.CONTAINER_NAME='");
+ query.append(containerName);
+ query.append("' and I.PARENT_ID='");
+ query.append(parentCid);
+ query.append("' and ( ");
+ appendPattern(query, pattern.get(0).getQPathEntry(), false);
+ for (int i = 1; i < pattern.size(); i++)
+ {
+ query.append(" or ");
+ appendPattern(query, pattern.get(i).getQPathEntry(), false);
+ }
+ query.append(" ) order by I.NAME");
+
+ return findPropertiesByParentIdAndComplexPatternCQ.executeQuery(query.toString());
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected ResultSet findNodeMainPropertiesByParentIdentifierCQ(String parentIdentifier) throws SQLException
{
if (findNodeMainPropertiesByParentIdentifierCQ == null)
@@ -731,4 +819,77 @@
updateValue.setInt(4, orderNumber);
return updateValue.executeUpdate();
}
+
+ /**
+ * Replace underscore in pattern with escaped symbol. Replace jcr-wildcard '*' with sql-wildcard '%'.
+ *
+ * @param pattern
+ * @return pattern with escaped underscore and fixed wildcard symbols
+ */
+ protected String fixEscapeSymbols(String pattern)
+ {
+ char[] chars = pattern.toCharArray();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < chars.length; i++)
+ {
+ switch (chars[i])
+ {
+ case '*' :
+ sb.append('%');
+ break;
+ case '_' :
+ case '%' :
+ sb.append(getWildcardEscapeSymbold());
+ default :
+ sb.append(chars[i]);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Append pattern expression.
+ * Appends String "I.NAME LIKE 'escaped pattern' ESCAPE 'escapeString'" or "I.NAME='pattern'"
+ * to String builder sb.
+ *
+ * @param sb StringBuilder
+ * @param indexConstraint
+ * @param pattern
+ */
+ protected void appendPattern(StringBuilder sb, QPathEntry entry, boolean indexConstraint)
+ {
+ String pattern = entry.getAsString(false);
+ sb.append("(I.NAME");
+ if (pattern.contains("*"))
+ {
+ sb.append(" LIKE '");
+ sb.append(fixEscapeSymbols(pattern));
+ sb.append("' ESCAPE '");
+ sb.append(getLikeExpressionEscape());
+ sb.append("'");
+ }
+ else
+ {
+ sb.append("='");
+ sb.append(pattern);
+ sb.append("'");
+ }
+
+ if (indexConstraint && entry.getIndex() != -1)
+ {
+ sb.append(" and I_INDEX=");
+ sb.append(entry.getIndex());
+ }
+ sb.append(")");
+ }
+
+ protected String getWildcardEscapeSymbold()
+ {
+ return PATTERN_ESCAPE_STRING;
+ }
+
+ protected String getLikeExpressionEscape()
+ {
+ return PATTERN_ESCAPE_STRING;
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseConnectionFactory.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseConnectionFactory.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseConnectionFactory.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -19,9 +19,11 @@
package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db;
import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
import java.io.File;
+import java.sql.SQLException;
import javax.jcr.RepositoryException;
import javax.sql.DataSource;
@@ -101,6 +103,31 @@
* {@inheritDoc}
*/
@Override
+ public WorkspaceStorageConnection openConnection(boolean readOnly) throws RepositoryException
+ {
+ try
+ {
+
+ if (multiDb)
+ {
+ return new SybaseMultiDbJDBCConnection(getJdbcConnection(readOnly), readOnly, containerName,
+ valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ return new SybaseSingleDbJDBCConnection(getJdbcConnection(readOnly), readOnly, containerName,
+ valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public boolean isReindexingSupport()
{
return false;
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseMultiDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseMultiDbJDBCConnection.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseMultiDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db;
+
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: SybaseMultiDbJDBCConnection.java 111 4.05.2011 serg $
+ */
+public class SybaseMultiDbJDBCConnection extends MultiDbJDBCConnection
+{
+
+ public SybaseMultiDbJDBCConnection(Connection dbConnection, boolean readOnly, String containerName,
+ ValueStoragePluginProvider valueStorageProvider, int maxBufferSize, File swapDirectory, FileCleaner swapCleaner)
+ throws SQLException
+ {
+ super(dbConnection, readOnly, containerName, valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String fixEscapeSymbols(String pattern)
+ {
+ char[] chars = pattern.toCharArray();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < chars.length; i++)
+ {
+ switch (chars[i])
+ {
+ case '*' :
+ sb.append('%');
+ break;
+ case '_' :
+ case '%' :
+ case '[' : //Sybase pattern special symbol
+ case ']' : //Sybase pattern special symbol
+ sb.append(this.getWildcardEscapeSymbold());
+ default :
+ sb.append(chars[i]);
+ }
+ }
+ return sb.toString();
+ }
+
+}
Added: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseSingleDbJDBCConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseSingleDbJDBCConnection.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/optimisation/db/SybaseSingleDbJDBCConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.db;
+
+import org.exoplatform.services.jcr.impl.util.io.FileCleaner;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: SybaseSingleDBJDBCConnection.java 111 4.05.2011 serg $
+ */
+public class SybaseSingleDbJDBCConnection extends SingleDbJDBCConnection
+{
+
+ public SybaseSingleDbJDBCConnection(Connection dbConnection, boolean readOnly, String containerName,
+ ValueStoragePluginProvider valueStorageProvider, int maxBufferSize, File swapDirectory, FileCleaner swapCleaner)
+ throws SQLException
+ {
+ super(dbConnection, readOnly, containerName, valueStorageProvider, maxBufferSize, swapDirectory, swapCleaner);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String fixEscapeSymbols(String pattern)
+ {
+ char[] chars = pattern.toCharArray();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < chars.length; i++)
+ {
+ switch (chars[i])
+ {
+ case '*' :
+ sb.append('%');
+ break;
+ case '_' :
+ case '%' :
+ case '[' : //Sybase pattern special symbol
+ case ']' : //Sybase pattern special symbol
+ sb.append(getWildcardEscapeSymbold());
+ default :
+ sb.append(chars[i]);
+ }
+ }
+ return sb.toString();
+ }
+
+}
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/storage/jdbc/statistics/StatisticsJDBCStorageConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -21,6 +21,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
import org.exoplatform.services.jcr.statistics.JCRStatisticsManager;
import org.exoplatform.services.jcr.statistics.Statistics;
@@ -106,12 +107,16 @@
*/
private static final String GET_CHILD_PROPERTIES_DATA_DESCR = "getChildPropertiesData";
+ private static final String GET_CHILD_PROPERTIES_DATA_PATTERN_DESCR = "getChildPropertiesDataPattern";
+
/**
* The description of the statistics corresponding to the method
* <code>getChildNodesData(NodeData parent)</code>
*/
private static final String GET_CHILD_NODES_DATA_DESCR = "getChildNodesData";
+ private static final String GET_CHILD_NODES_DATA_PATTERN_DESCR = "getChildNodesData";
+
/**
* The description of the statistics corresponding to the method
* <code>getChildNodesCount(NodeData parent)</code>
@@ -176,11 +181,14 @@
ALL_STATISTICS.put(GET_ITEM_DATA_BY_NODE_DATA_NQ_PATH_ENTRY_DESCR, new Statistics(GLOBAL_STATISTICS,
GET_ITEM_DATA_BY_NODE_DATA_NQ_PATH_ENTRY_DESCR));
ALL_STATISTICS.put(GET_CHILD_NODES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, GET_CHILD_NODES_DATA_DESCR));
+ ALL_STATISTICS.put(GET_CHILD_NODES_DATA_PATTERN_DESCR, new Statistics(GLOBAL_STATISTICS,
+ GET_CHILD_NODES_DATA_PATTERN_DESCR));
ALL_STATISTICS.put(GET_CHILD_NODES_COUNT_DESCR, new Statistics(GLOBAL_STATISTICS, GET_CHILD_NODES_COUNT_DESCR));
ALL_STATISTICS.put(GET_LAST_ORDER_NUMBER_DESCR, new Statistics(GLOBAL_STATISTICS, GET_LAST_ORDER_NUMBER_DESCR));
-
ALL_STATISTICS.put(GET_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS,
GET_CHILD_PROPERTIES_DATA_DESCR));
+ ALL_STATISTICS.put(GET_CHILD_PROPERTIES_DATA_PATTERN_DESCR, new Statistics(GLOBAL_STATISTICS,
+ GET_CHILD_PROPERTIES_DATA_PATTERN_DESCR));
ALL_STATISTICS.put(LIST_CHILD_PROPERTIES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS,
LIST_CHILD_PROPERTIES_DATA_DESCR));
ALL_STATISTICS.put(GET_REFERENCES_DATA_DESCR, new Statistics(GLOBAL_STATISTICS, GET_REFERENCES_DATA_DESCR));
@@ -394,6 +402,24 @@
/**
* {@inheritDoc}
*/
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ Statistics s = ALL_STATISTICS.get(GET_CHILD_NODES_DATA_PATTERN_DESCR);
+ try
+ {
+ s.begin();
+ return wcs.getChildNodesData(parent, pattern);
+ }
+ finally
+ {
+ s.end();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException
{
Statistics s = ALL_STATISTICS.get(GET_CHILD_PROPERTIES_DATA_DESCR);
@@ -409,6 +435,24 @@
}
/**
+ * @see org.exoplatform.services.jcr.storage.WorkspaceStorageConnection#getChildPropertiesData(org.exoplatform.services.jcr.datamodel.NodeData, java.lang.String[] pattern)
+ */
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern)
+ throws RepositoryException, IllegalStateException
+ {
+ Statistics s = ALL_STATISTICS.get(GET_CHILD_PROPERTIES_DATA_PATTERN_DESCR);
+ try
+ {
+ s.begin();
+ return wcs.getChildPropertiesData(parent, pattern);
+ }
+ finally
+ {
+ s.end();
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
public ItemData getItemData(NodeData parentData, QPathEntry name) throws RepositoryException, IllegalStateException
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/storage/WorkspaceStorageConnection.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -23,6 +23,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import java.util.List;
@@ -117,6 +118,21 @@
List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException, IllegalStateException;
/**
+ * Reads <code>List</code> of <code>NodeData</code> from the storage using item's parent location, and name filter.
+ *
+ * @param parent
+ * NodeData
+ * @param pattern - list of QPathEntryFilters
+ * @return child nodes data or empty <code>List</code>
+ * @throws RepositoryException
+ * if some exception occured
+ * @throws IllegalStateException
+ * if connection is closed
+ */
+ List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException;
+
+ /**
* Reads count of <code>parent<code/> child nodes.
*
* @param parent NodeData
@@ -149,6 +165,23 @@
List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException, IllegalStateException;
/**
+ * Reads <code>List</code> of <code>PropertyData</code> from the storage using item's parent
+ * location.
+ *
+ * @param parent
+ * NodeData
+ * @param pattern
+ * String[] list of wildcard names
+ * @return child properties data or empty <code>List</code>
+ * @throws RepositoryException
+ * if some exception occured
+ * @throws IllegalStateException
+ * if connection is closed
+ */
+ List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException;
+
+ /**
* Reads <code>List</code> of <code>PropertyData</code> with empty <code>ValueData</code> from the
* storage using item's parent location.
*
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/BaseStandaloneTest.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -25,6 +25,7 @@
import org.exoplatform.services.jcr.core.CredentialsImpl;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.core.WorkspaceContainerFacade;
+import org.exoplatform.services.jcr.impl.core.ItemImpl;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
import org.exoplatform.services.jcr.impl.core.SessionImpl;
@@ -41,6 +42,9 @@
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import java.util.Random;
import javax.jcr.Node;
@@ -477,4 +481,32 @@
}
}
}
+
+ protected void testNames(Iterator iterator, String[] expectedNames) throws RepositoryException
+ {
+
+ List<String> names = new ArrayList<String>();
+ while (iterator.hasNext())
+ {
+ ItemImpl item = (ItemImpl)iterator.next();
+ names.add(item.getName());
+ }
+
+ //compare names
+ assertEquals(expectedNames.length, names.size());
+
+ for (String expectedName : expectedNames)
+ {
+ boolean finded = false;
+ for (String name : names)
+ {
+ if (expectedName.equals(name))
+ {
+ finded = true;
+ break;
+ }
+ }
+ assertTrue(finded);
+ }
+ }
}
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/reading/TestNode.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/reading/TestNode.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/api/reading/TestNode.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -395,6 +395,49 @@
}
+ public void testGetPropertiesWithNamePatternStoredData() throws RepositoryException
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ // Node node = root.getNode("/childNode/childNode2/jcr:content");
+
+ Node node = root.addNode("testNode", "nt:unstructured");
+
+ node.setProperty("property1", "prop1Value");
+ node.setProperty("property2", "prop2Value");
+ root.save();
+
+ PropertyIterator iterator = node.getProperties("property1 | property2");
+
+ while (iterator.hasNext())
+ {
+ Property property = iterator.nextProperty();
+ if (!("property1".equals(property.getName()) || "property2".equals(property.getName())))
+ fail("returned non expected properties");
+ }
+
+ iterator = node.getProperties("property1 | jcr:*");
+
+ while (iterator.hasNext())
+ {
+ Property property = iterator.nextProperty();
+ if (!("property1".equals(property.getName()) || "jcr:primaryType".equals(property.getName())))
+ fail("returned non expected properties");
+ }
+
+ node.setProperty("proper_ty", "prop_value");
+ node.setProperty("properAty", "propAvalue");
+ root.save();
+
+ iterator = node.getProperties("proper_t%");
+ while (iterator.hasNext())
+ {
+ Property property = iterator.nextProperty();
+ if (!("proper_ty".equals(property.getName())))
+ fail("returned non expected properties");
+ }
+ }
+
public void testGetPrimaryItem() throws RepositoryException
{
Node root = session.getRootNode();
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/itemfilters/TestPatternQPathEntryFilter.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/itemfilters/TestPatternQPathEntryFilter.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/itemfilters/TestPatternQPathEntryFilter.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,75 @@
+/*
+ * 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.core.itemfilters;
+
+import org.exoplatform.services.jcr.JcrAPIBaseTest;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:skarpenko@exoplatform.com">Sergiy Karpenko</a>
+ * @version $Id: exo-jboss-codetemplates.xml 34360 24 ����. 2011 skarpenko $
+ *
+ */
+public class TestPatternQPathEntryFilter extends JcrAPIBaseTest
+{
+ public void testPatternMap()
+ {
+ PatternQPathEntryFilter filter = new PatternQPathEntryFilter(new PatternQPathEntry("", "local*name", -1));
+
+ Map<PatternQPathEntryFilter, String> map = new HashMap<PatternQPathEntryFilter, String>();
+
+ map.put(new PatternQPathEntryFilter(new PatternQPathEntry("", "local*name", 3)), "secondvalue");
+ map.put(filter, "value");
+ map.put(new PatternQPathEntryFilter(new PatternQPathEntry("", "local*name", 31)), "thirdvalue");
+
+ PatternQPathEntryFilter newfilter = new PatternQPathEntryFilter(new PatternQPathEntry("", "local*name", -1));
+
+ String val = map.get(newfilter);
+
+ assertEquals("value", val);
+ }
+
+ public void testPatternQPathEntryFilterExtrnalization() throws Exception
+ {
+ PatternQPathEntryFilter filter = new PatternQPathEntryFilter(new PatternQPathEntry("", "local*name", -1));
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(bout);
+
+ filter.writeExternal(out);
+ out.close();
+ bout.close();
+
+ ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bin);
+
+ PatternQPathEntryFilter newFilter = new PatternQPathEntryFilter();
+ newFilter.readExternal(in);
+ in.close();
+ bin.close();
+
+ assertEquals(filter, newFilter);
+ }
+}
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestCacheableWorkspaceDataManager.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -29,6 +29,7 @@
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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
@@ -353,6 +354,14 @@
return true;
}
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isPatternSupported()
+ {
+ return false;
+ }
+
public List<PropertyData> listChildProperties(NodeData parentData)
{
return childPropertiesList;
@@ -395,6 +404,24 @@
{
}
+ public void addChildProperties(NodeData parent, QPathEntryFilter pattern, List<PropertyData> childProperties)
+ {
+ }
+
+ public List<PropertyData> getChildProperties(NodeData parent, QPathEntryFilter pattern)
+ {
+ return null;
+ }
+
+ public void addChildNodes(NodeData parent, QPathEntryFilter pattern, List<NodeData> childNodes)
+ {
+ }
+
+ public List<NodeData> getChildNodes(NodeData parent, QPathEntryFilter pattern)
+ {
+ return null;
+ }
+
}
private static class MyWorkspaceStorageConnection implements WorkspaceStorageConnection
@@ -456,6 +483,16 @@
Arrays.asList((ValueData)new ByteArrayPersistedValueData(1, "foo".getBytes()))));
}
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern)
+ throws RepositoryException, IllegalStateException
+ {
+ getChildPropertiesDataCalls.incrementAndGet();
+ return Arrays
+ .asList((PropertyData)new PersistedPropertyData("getChildPropertiesDataByPattern", null, null, 0,
+ PropertyType.STRING, false, Arrays
+ .asList((ValueData)new ByteArrayPersistedValueData(1, "foo".getBytes()))));
+ }
+
public AtomicInteger getItemDataByNodeDataNQPathEntryCalls = new AtomicInteger();
/**
@@ -539,6 +576,12 @@
return -1;
}
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ return null;
+ }
+
};
private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestJBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestJBossCacheWorkspaceStorageCache.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestJBossCacheWorkspaceStorageCache.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -33,6 +33,7 @@
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.JBossCacheWorkspaceStorageCache;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase;
@@ -228,6 +229,12 @@
return null;
}
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern)
+ throws RepositoryException, IllegalStateException
+ {
+ return null;
+ }
+
/**
* {@inheritDoc}
*/
@@ -300,6 +307,12 @@
return -1;
}
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ return getChildNodesData(parent);
+ }
+
};
private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
Modified: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java 2011-05-25 15:04:58 UTC (rev 4428)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TestWorkspaceStorageCacheInClusterMode.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -34,6 +34,7 @@
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.core.itemfilters.QPathEntryFilter;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
@@ -461,6 +462,12 @@
return children;
}
+ public List<PropertyData> getChildPropertiesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ return getChildPropertiesData(parent);
+ }
+
/**
* {@inheritDoc}
*/
@@ -584,6 +591,12 @@
{
return 0;
}
+
+ public List<NodeData> getChildNodesData(NodeData parent, List<QPathEntryFilter> pattern) throws RepositoryException,
+ IllegalStateException
+ {
+ return getChildNodesData(parent);
+ }
};
private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPattern.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPattern.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPattern.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.usecases;
+
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: TestGetNodesByPattern.java 111 11 ����. 2011 serg $
+ */
+public class TestGetNodesByPattern extends BaseUsecasesTest
+{
+ public void testPatternWithEscapedSymbols() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.addNode("node.txt");
+ node.addNode("node_txt");
+ node.addNode("node3txt");
+ root.save();
+
+ NodeIterator iterator = node.getNodes("node.tx*");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextNode().getName(), "node.txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("node_tx*");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextNode().getName(), "node_txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("node_tx* | boo");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextNode().getName(), "node_txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("node.txt");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextNode().getName(), "node.txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("nodata.txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("nodata.t*t");
+ assertFalse(iterator.hasNext());
+
+ }
+
+ public void testCaching() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.addNode("cassiopeia");
+ node.addNode("casio");
+ node.addNode("cassandra");
+ node.addNode("libra");
+ node.addNode("equilibrium");
+ node.addNode("equality");
+ root.save();
+ for (int i = 0; i < 100; i++)
+ {
+ node.addNode("node" + i);
+ }
+ root.save();
+
+ long executionTime = System.currentTimeMillis();
+ NodeIterator iterator = node.getNodes("cass* | *lib*");
+ executionTime = System.currentTimeMillis() - executionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassiopeia", "cassandra", "libra", "equilibrium"});
+
+ long nextExecutionTime = System.currentTimeMillis();
+ iterator = node.getNodes("cass* | *lib*");
+ nextExecutionTime = System.currentTimeMillis() - nextExecutionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassiopeia", "cassandra", "libra", "equilibrium"});
+
+ if (nextExecutionTime * 1.1 < executionTime)
+ {
+ log.warn("Fetching data from DataBase takes less time than from cache - " + executionTime + " "
+ + nextExecutionTime);
+ }
+ }
+
+ public void testNamespaces() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.addNode("exo:cassiopeia");
+ node.addNode("jcr:casio");
+ node.addNode("nt:cassandra");
+ node.addNode("exo:libra");
+ node.addNode("jcr:equilibrium");
+ node.addNode("exo:equality");
+ root.save();
+ for (int i = 0; i < 100; i++)
+ {
+ node.addNode("node" + i);
+ }
+ root.save();
+
+ long executionTime = System.currentTimeMillis();
+ NodeIterator iterator = node.getNodes("*:cass* | *:*lib*");
+ executionTime = System.currentTimeMillis() - executionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"exo:cassiopeia", "nt:cassandra", "exo:libra", "jcr:equilibrium"});
+
+ long nextExecutionTime = System.currentTimeMillis();
+ iterator = node.getNodes("*:cass* | *:*lib*");
+ nextExecutionTime = System.currentTimeMillis() - nextExecutionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"exo:cassiopeia", "nt:cassandra", "exo:libra", "jcr:equilibrium"});
+ if (nextExecutionTime * 1.1 < executionTime)
+ {
+ log.warn("Fetching data from DataBase takes less time than from cache - " + executionTime + " "
+ + nextExecutionTime);
+ }
+ }
+
+ public void testCacheUpdate() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.addNode("cassiopeia");
+ node.addNode("casio");
+ node.addNode("cassandra");
+ node.addNode("libra");
+ node.addNode("equilibrium");
+ node.addNode("equality");
+ root.save();
+ for (int i = 0; i < 100; i++)
+ {
+ node.addNode("node" + i);
+ }
+ root.save();
+
+ NodeIterator iterator = node.getNodes("cass* ");
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassiopeia", "cassandra"});
+
+ // add new node
+ node.addNode("cassa");
+ root.save();
+
+ iterator = node.getNodes("cass*");
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassiopeia", "cassandra", "cassa"});
+
+ // remove node
+ node.getNode("cassiopeia").remove();
+ root.save();
+
+ iterator = node.getNodes("cass*");
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassandra", "cassa"});
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ Node root = session.getRootNode();
+ root.addNode("childNode");
+ root.save();
+ }
+
+ public void tearDown() throws Exception
+ {
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode");
+ node.remove();
+ session.save();
+
+ super.tearDown();
+ }
+
+}
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPatternAndIndex.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPatternAndIndex.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetNodesByPatternAndIndex.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.usecases;
+
+import org.exoplatform.services.jcr.impl.core.ItemImpl;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: TestGetNodesByPatternAndIndex.java 111 13 ����. 2011 serg $
+ */
+public class TestGetNodesByPatternAndIndex extends BaseUsecasesTest
+{
+ public void testPatternWithEscapedSymbols() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.addNode("node.txt");
+ node.addNode("node.txt");
+ node.addNode("node.txt");
+ node.addNode("node_txt");
+ node.addNode("node3txt");
+ root.save();
+
+ NodeIterator iterator = node.getNodes("node.tx*");
+ assertTrue(iterator.hasNext());
+ testNamesWithIndex(iterator, new String[]{"[]node.txt:1", "[]node.txt:2", "[]node.txt:3"});
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("node.txt");
+ assertTrue(iterator.hasNext());
+ testNamesWithIndex(iterator, new String[]{"[]node.txt:1", "[]node.txt:2", "[]node.txt:3"});
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getNodes("node.txt[1] | node.txt[3] | london[6]");
+ assertTrue(iterator.hasNext());
+ testNamesWithIndex(iterator, new String[]{"[]node.txt:1", "[]node.txt:3"});
+ assertFalse(iterator.hasNext());
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ Node root = session.getRootNode();
+ root.addNode("childNode");
+ root.save();
+ }
+
+ public void tearDown() throws Exception
+ {
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode");
+ node.remove();
+ session.save();
+
+ super.tearDown();
+ }
+
+ protected void testNamesWithIndex(Iterator iterator, String[] expectedNames) throws RepositoryException
+ {
+
+ List<String> names = new ArrayList<String>();
+ while (iterator.hasNext())
+ {
+ ItemImpl item = (ItemImpl)iterator.next();
+ names.add(item.getInternalPath().getEntries()[item.getInternalPath().getDepth()].getAsString(true));
+ }
+
+ //compare names
+ assertEquals(expectedNames.length, names.size());
+
+ for (String expectedName : expectedNames)
+ {
+ boolean finded = false;
+ for (String name : names)
+ {
+ if (expectedName.equals(name))
+ {
+ finded = true;
+ break;
+ }
+ }
+ assertTrue(finded);
+ }
+ }
+
+}
Added: jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetPropertiesByPattern.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetPropertiesByPattern.java (rev 0)
+++ jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/usecases/TestGetPropertiesByPattern.java 2011-05-26 07:00:26 UTC (rev 4429)
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2003-2011 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.usecases;
+
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+
+import javax.jcr.Node;
+import javax.jcr.PropertyIterator;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: TestGetPropertiesByPattern.java 111 4.05.2011 serg $
+ */
+public class TestGetPropertiesByPattern extends BaseUsecasesTest
+{
+ public void testPatternWithEscapedSymbols() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.setProperty("property.txt", "prop1Value");
+ node.setProperty("property_txt", "prop2Value");
+ node.setProperty("property3txt", "prop3Value");
+ root.save();
+
+ PropertyIterator iterator = node.getProperties("property.tx*");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextProperty().getName(), "property.txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getProperties("property_tx*");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextProperty().getName(), "property_txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getProperties("property_tx* | boo");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextProperty().getName(), "property_txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getProperties("property.txt");
+ assertTrue(iterator.hasNext());
+ assertEquals(iterator.nextProperty().getName(), "property.txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getProperties("nodata.txt");
+ assertFalse(iterator.hasNext());
+
+ iterator = node.getProperties("no*.txt");
+ assertFalse(iterator.hasNext());
+ }
+
+ public void testCaching() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.setProperty("cassiopeia", "cassiopeiaValue");
+ node.setProperty("casio", "casioValue");
+ node.setProperty("cassandra", "cassandraValue");
+ node.setProperty("libra", "libraValue");
+ node.setProperty("equilibrium", "equilibriumValue");
+ node.setProperty("equality", "cassandraValue");
+ root.save();
+ for (int i = 0; i < 100; i++)
+ {
+ String name = "property" + i;
+ node.setProperty(name, name);
+ }
+ root.save();
+
+ long executionTime = System.currentTimeMillis();
+ PropertyIterator iterator = node.getProperties("cass* | *lib*");
+ executionTime = System.currentTimeMillis() - executionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassiopeia", "cassandra", "libra", "equilibrium"});
+
+ long nextExecutionTime = System.currentTimeMillis();
+ iterator = node.getProperties("cass* | *lib*");
+ nextExecutionTime = System.currentTimeMillis() - nextExecutionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"cassiopeia", "cassandra", "libra", "equilibrium"});
+
+ if (nextExecutionTime * 1.1 < executionTime)
+ {
+ log.warn("Fetching data from DataBase takes less time than from cache - " + executionTime + " "
+ + nextExecutionTime);
+ }
+ }
+
+ public void testNamespaces() throws Exception
+ {
+ session = (SessionImpl)repository.login(credentials, WORKSPACE);
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode").addNode("testNode", "nt:unstructured");
+
+ node.setProperty("exo:cassiopeia", "cassiopeiaValue");
+ node.setProperty("jcr:casio", "casioValue");
+ node.setProperty("nt:cassandra", "cassandraValue");
+ node.setProperty("exo:libra", "libraValue");
+ node.setProperty("jcr:equilibrium", "equilibriumValue");
+ node.setProperty("exo:equality", "cassandraValue");
+ root.save();
+ for (int i = 0; i < 100; i++)
+ {
+ String name = "property" + i;
+ node.setProperty(name, name);
+ }
+ root.save();
+
+ long executionTime = System.currentTimeMillis();
+ PropertyIterator iterator = node.getProperties("*:cass* | *:*lib*");
+ executionTime = System.currentTimeMillis() - executionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"exo:cassiopeia", "nt:cassandra", "exo:libra", "jcr:equilibrium"});
+
+ long nextExecutionTime = System.currentTimeMillis();
+ iterator = node.getProperties("*:cass* | *:*lib*");
+ nextExecutionTime = System.currentTimeMillis() - nextExecutionTime;
+ assertTrue(iterator.hasNext());
+ testNames(iterator, new String[]{"exo:cassiopeia", "nt:cassandra", "exo:libra", "jcr:equilibrium"});
+ if (nextExecutionTime * 1.1 < executionTime)
+ {
+ log.warn("Fetching data from DataBase takes less time than from cache - " + executionTime + " "
+ + nextExecutionTime);
+ }
+ }
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ Node root = session.getRootNode();
+ root.addNode("childNode");
+ root.save();
+ }
+
+ public void tearDown() throws Exception
+ {
+ Node root = session.getRootNode();
+ Node node = root.getNode("childNode");
+ node.remove();
+ session.save();
+
+ super.tearDown();
+ }
+}
12 years, 11 months
exo-jcr SVN: r4428 - jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.
by do-not-reply@jboss.org
Author: nfilotto
Date: 2011-05-25 11:04:58 -0400 (Wed, 25 May 2011)
New Revision: 4428
Modified:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/statistics.xml
Log:
EXOJCR-1357: Add to the documentation the name of the existing categories of statistics
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/statistics.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2011-05-25 11:11:18 UTC (rev 4427)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/statistics.xml 2011-05-25 15:04:58 UTC (rev 4428)
@@ -63,6 +63,10 @@
<para>The format of each column header is ${method-alias}-${metric-alias}.
The metric alias are described in the statistics manager section.</para>
+ <para>The name of the category of statistics corresponding to these
+ statistics is <emphasis>JDBCStorageConnection</emphasis>, this name is
+ mostly needed to access to the statistics through JMX.</para>
+
<table>
<title>Method Alias</title>
@@ -313,6 +317,11 @@
<para>The metric alias are described in the statistics manager
section.</para>
+ <para>The name of the category of statistics corresponding to these
+ statistics is the simple name of the monitored interface (e.g.
+ ExtendedSession for org.exoplatform.services.jcr.core.ExtendedSession),
+ this name is mostly needed to access to the statistics through JMX.</para>
+
<remark>Please note that this feature will affect the performances of eXo
JCR so it must be used with caution.</remark>
</section>
@@ -343,25 +352,29 @@
<row>
<entry>Min</entry>
- <entry>The minimum time spent into the method.</entry>
+ <entry>The minimum time spent into the method expressed in
+ milliseconds.</entry>
</row>
<row>
<entry>Max</entry>
- <entry>The maximum time spent into the method.</entry>
+ <entry>The maximum time spent into the method expressed in
+ milliseconds.</entry>
</row>
<row>
<entry>Total</entry>
- <entry>The total amount of time spent into the method.</entry>
+ <entry>The total amount of time spent into the method expressed
+ in milliseconds.</entry>
</row>
<row>
<entry>Avg</entry>
- <entry>The average time spent into the method.</entry>
+ <entry>The average time spent into the method expressed in
+ milliseconds.</entry>
</row>
<row>
@@ -395,7 +408,7 @@
<entry>Give the minimum time spent into the method corresponding
to the given category name and statistics name. The expected
- arguments are the name of the category of the statistics (e.g.
+ arguments are the name of the category of statistics (e.g.
JDBCStorageConnection) and the name of the expected method or
global for the global value.</entry>
</row>
@@ -405,7 +418,7 @@
<entry>Give the maximum time spent into the method corresponding
to the given category name and statistics name. The expected
- arguments are the name of the category of the statistics (e.g.
+ arguments are the name of the category of statistics (e.g.
JDBCStorageConnection) and the name of the expected method or
global for the global value.</entry>
</row>
@@ -415,7 +428,7 @@
<entry>Give the total amount of time spent into the method
corresponding to the given category name and statistics name.
- The expected arguments are the name of the category of the
+ The expected arguments are the name of the category of
statistics (e.g. JDBCStorageConnection) and the name of the
expected method or global for the global value.</entry>
</row>
@@ -425,7 +438,7 @@
<entry>Give the average time spent into the method corresponding
to the given category name and statistics name. The expected
- arguments are the name of the category of the statistics (e.g.
+ arguments are the name of the category of statistics (e.g.
JDBCStorageConnection) and the name of the expected method or
global for the global value.</entry>
</row>
@@ -435,7 +448,7 @@
<entry>Give the total amount of times the method has been called
corresponding to the given ,category name and statistics name.
- The expected arguments are the name of the category of the
+ The expected arguments are the name of the category of
statistics (e.g. JDBCStorageConnection) and the name of the
expected method or global for the global value.</entry>
</row>
@@ -445,16 +458,15 @@
<entry>Reset the statistics for the given category name and
statistics name. The expected arguments are the name of the
- category of the statistics (e.g. JDBCStorageConnection) and the
- name of the expected method or global for the global
- value.</entry>
+ category of statistics (e.g. JDBCStorageConnection) and the name
+ of the expected method or global for the global value.</entry>
</row>
<row>
<entry>resetAll</entry>
<entry>Reset all the statistics for the given category name. The
- expected argument is the name of the category of the statistics
+ expected argument is the name of the category of statistics
(e.g. JDBCStorageConnection).</entry>
</row>
</tbody>
12 years, 11 months
exo-jcr SVN: r4427 - jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-25 07:11:18 -0400 (Wed, 25 May 2011)
New Revision: 4427
Modified:
jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
Log:
EXOJCR-1187: Increase memory consuming of JCR, OutOfMemoryError: PermGen space
Modified: jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
===================================================================
--- jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml 2011-05-25 07:52:19 UTC (rev 4426)
+++ jcr/trunk/exo.jcr.docs/exo.jcr.docs.developer/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml 2011-05-25 11:11:18 UTC (rev 4427)
@@ -325,10 +325,13 @@
<para><citetitle>PermGen space size</citetitle></para>
- <para>if it is used ISPN, needs to increase the PermGen size to 256M due
- to the latest versions of JGroups that are required for ISPN. In case is
- it is used JBC can keep on using JGroups 2.6.13.GA thus doesn't need to
- increase the PermGen size.</para>
+ <para>If you intend to use Infinispan, you will have to increase the
+ PermGen size to at least 256 Mo due to the latest versions of JGroups
+ that are needed by Infinispan (please note that Infinspan is only
+ dedicated to the community for now, no support will be provided). In
+ case, you intend to use JBoss Cache, you can keep on using JGroups
+ 2.6.13.GA which means that you don't need to increase the PermGen
+ size.</para>
</section>
</section>
</chapter>
12 years, 11 months
exo-jcr SVN: r4426 - jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene.
by do-not-reply@jboss.org
Author: tolusha
Date: 2011-05-25 03:52:19 -0400 (Wed, 25 May 2011)
New Revision: 4426
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
Log:
EXOJCR-1337: Do not check MultiIndex.checkIndexingQueue for finished documents
Modified: jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-05-25 06:24:01 UTC (rev 4425)
+++ jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/query/lucene/MultiIndex.java 2011-05-25 07:52:19 UTC (rev 4426)
@@ -56,11 +56,11 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
-import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
@@ -2131,49 +2131,50 @@
*/
private void checkIndexingQueue(boolean transactionPresent)
{
- Document[] docs = indexingQueue.getFinishedDocuments();
- Map<String, Document> finished = new HashMap<String, Document>();
- for (int i = 0; i < docs.length; i++)
- {
- String uuid = docs[i].get(FieldNames.UUID);
- finished.put(uuid, docs[i]);
- }
-
- // now update index with the remaining ones if there are any
- if (!finished.isEmpty())
- {
- log.info("updating index with {} nodes from indexing queue.", new Long(finished.size()));
-
- // remove documents from the queue
- for (Iterator<String> it = finished.keySet().iterator(); it.hasNext();)
- {
- indexingQueue.removeDocument(it.next().toString());
- }
-
- try
- {
- if (transactionPresent)
- {
- for (Iterator<String> it = finished.keySet().iterator(); it.hasNext();)
- {
- executeAndLog(new DeleteNode(getTransactionId(), it.next()));
- }
- for (Iterator<Document> it = finished.values().iterator(); it.hasNext();)
- {
- executeAndLog(new AddNode(getTransactionId(), it.next()));
- }
- }
- else
- {
- update(finished.keySet(), finished.values());
- }
- }
- catch (IOException e)
- {
- // update failed
- log.warn("Failed to update index with deferred text extraction", e);
- }
- }
+ // EXOJCR-1337, have been commented since it is not used
+ // Document[] docs = indexingQueue.getFinishedDocuments();
+ // Map<String, Document> finished = new HashMap<String, Document>();
+ // for (int i = 0; i < docs.length; i++)
+ // {
+ // String uuid = docs[i].get(FieldNames.UUID);
+ // finished.put(uuid, docs[i]);
+ // }
+ //
+ // // now update index with the remaining ones if there are any
+ // if (!finished.isEmpty())
+ // {
+ // log.info("updating index with {} nodes from indexing queue.", new Long(finished.size()));
+ //
+ // // remove documents from the queue
+ // for (Iterator<String> it = finished.keySet().iterator(); it.hasNext();)
+ // {
+ // indexingQueue.removeDocument(it.next().toString());
+ // }
+ //
+ // try
+ // {
+ // if (transactionPresent)
+ // {
+ // for (Iterator<String> it = finished.keySet().iterator(); it.hasNext();)
+ // {
+ // executeAndLog(new DeleteNode(getTransactionId(), it.next()));
+ // }
+ // for (Iterator<Document> it = finished.values().iterator(); it.hasNext();)
+ // {
+ // executeAndLog(new AddNode(getTransactionId(), it.next()));
+ // }
+ // }
+ // else
+ // {
+ // update(finished.keySet(), finished.values());
+ // }
+ // }
+ // catch (IOException e)
+ // {
+ // // update failed
+ // log.warn("Failed to update index with deferred text extraction", e);
+ // }
+ // }
}
// ------------------------< Actions
12 years, 11 months