Hibernate SVN: r17394 - in beanvalidation/trunk/validation-tck/src/main: java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition and 3 other directories.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 09:05:42 -0400 (Fri, 21 Aug 2009)
New Revision: 17394
Added:
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/DummyLengthValidator.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/ExludeExisistingValidatorsTest.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/IncludeExisistingValidatorsTest.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Length.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/LengthValidator.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Name.java
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-IncludeExisistingValidatorsTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-ExludeExisistingValidatorsTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-IncludeExisistingValidatorsTest.xml
Modified:
beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml
Log:
constraint definition tests
Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/DummyLengthValidator.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/DummyLengthValidator.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/DummyLengthValidator.java 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,26 @@
+// $Id: LengthValidator.java 16748 2009-06-10 18:41:22Z epbernard $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition;
+
+/**
+ * Check that a string's length is between min and max.
+ *
+ * @author Hardy Ferentschik
+ */
+public class DummyLengthValidator extends LengthValidator {
+}
\ No newline at end of file
Copied: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/ExludeExisistingValidatorsTest.java (from rev 17390, beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingTest.java)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/ExludeExisistingValidatorsTest.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/ExludeExisistingValidatorsTest.java 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,73 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition;
+
+import java.lang.annotation.Annotation;
+import java.util.List;
+import java.util.Set;
+import javax.validation.ConstraintValidator;
+import javax.validation.Validator;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.jboss.test.audit.annotations.SpecAssertion;
+import org.jboss.test.audit.annotations.SpecAssertions;
+import org.jboss.testharness.AbstractTest;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.ArtifactType;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.jboss.testharness.impl.packaging.Resource;
+import org.jboss.testharness.impl.packaging.jsr303.ValidationXml;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+import org.hibernate.jsr303.tck.util.TestUtil;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Artifact(artifactType = ArtifactType.JSR303)
+@Classes({ TestUtil.class, TestUtil.PathImpl.class, TestUtil.NodeImpl.class })
+@ValidationXml(value = "validation-ExludeExisistingValidatorsTest.xml")
+@Resource(source = "constraint-definition-ExludeExisistingValidatorsTest.xml",
+ destination = "WEB-INF/classes/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml")
+public class ExludeExisistingValidatorsTest extends AbstractTest {
+
+ @Test
+ @SpecAssertions({
+ @SpecAssertion(section = "7.1.2", id = "b"),
+ @SpecAssertion(section = "7.1.2", id = "e")
+ })
+ public <T extends Annotation> void testExcludeExistingValidators() {
+ Validator validator = TestUtil.getValidatorUnderTest();
+ PropertyDescriptor propDescriptor = validator.getConstraintsForClass( Name.class )
+ .getConstraintsForProperty( "name" );
+
+ Set<ConstraintDescriptor<?>> descriptors = propDescriptor.getConstraintDescriptors();
+ assertEquals( descriptors.size(), 1, "There should only be one constraint." );
+
+ ConstraintDescriptor<T> descriptor = ( ConstraintDescriptor<T> ) descriptors.iterator().next();
+ List<Class<? extends ConstraintValidator<T, ?>>> validators = descriptor.getConstraintValidatorClasses();
+
+ assertEquals(
+ validators.size(),
+ 0,
+ "No xml defined validator and annotations are ignored -> no validator"
+ );
+ }
+}
\ No newline at end of file
Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/IncludeExisistingValidatorsTest.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/IncludeExisistingValidatorsTest.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/IncludeExisistingValidatorsTest.java 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,78 @@
+// $Id: ClassLevelOverridingTest.java 17390 2009-08-21 11:04:54Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition;
+
+import java.util.List;
+import java.util.Set;
+import java.lang.annotation.Annotation;
+import javax.validation.ConstraintValidator;
+import javax.validation.Validator;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.PropertyDescriptor;
+
+import org.jboss.test.audit.annotations.SpecAssertion;
+import org.jboss.test.audit.annotations.SpecAssertions;
+import org.jboss.testharness.AbstractTest;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.ArtifactType;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.jboss.testharness.impl.packaging.Resource;
+import org.jboss.testharness.impl.packaging.jsr303.ValidationXml;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+import org.hibernate.jsr303.tck.util.TestUtil;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Artifact(artifactType = ArtifactType.JSR303)
+@Classes({ TestUtil.class, TestUtil.PathImpl.class, TestUtil.NodeImpl.class })
+@ValidationXml(value = "validation-IncludeExisistingValidatorsTest.xml")
+@Resource(source = "constraint-definition-IncludeExisistingValidatorsTest.xml",
+ destination = "WEB-INF/classes/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-IncludeExisistingValidatorsTest.xml")
+public class IncludeExisistingValidatorsTest extends AbstractTest {
+
+ @Test
+ @SpecAssertions({
+ @SpecAssertion(section = "7.1.2", id = "c"),
+ @SpecAssertion(section = "7.1.2", id = "d"),
+ @SpecAssertion(section = "7.1.2", id = "e")
+ })
+ public <T extends Annotation> void testIncludeExistingValidators() {
+ Validator validator = TestUtil.getValidatorUnderTest();
+ PropertyDescriptor propDescriptor = validator.getConstraintsForClass( Name.class )
+ .getConstraintsForProperty( "name" );
+
+
+ Set<ConstraintDescriptor<?>> descriptors = propDescriptor.getConstraintDescriptors();
+ assertEquals( descriptors.size(), 1, "There should only be one constraint." );
+
+ @SuppressWarnings( "unchecked")
+ ConstraintDescriptor<T> descriptor = ( ConstraintDescriptor<T> ) descriptors.iterator().next();
+ List<Class<? extends ConstraintValidator<T, ?>>> validators = descriptor.getConstraintValidatorClasses();
+
+
+ assertEquals(
+ validators.size(),
+ 2,
+ "One validator should be defined in annotation and one in xml"
+ );
+
+ }
+}
\ No newline at end of file
Copied: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Length.java (from rev 17330, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Length.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Length.java 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,50 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.Constraint;
+import javax.validation.ConstraintPayload;
+
+/**
+ * Validate that the string is between min and max included
+ *
+ * @author Emmanuel Bernard
+ * @author Hardy Ferentschik
+ */
+@Documented
+@Constraint(validatedBy = LengthValidator.class)
+@Target({ METHOD, FIELD, TYPE })
+@Retention(RUNTIME)
+public @interface Length {
+ public abstract int min() default 0;
+
+ public abstract int max() default Integer.MAX_VALUE;
+
+ public abstract String message() default "min length {min}. max length {max}.";
+
+ public abstract Class<?>[] groups() default { };
+
+ Class<? extends ConstraintPayload>[] payload() default { };
+}
\ No newline at end of file
Copied: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/LengthValidator.java (from rev 17330, validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/impl/LengthValidator.java)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/LengthValidator.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/LengthValidator.java 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,59 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.ValidationException;
+
+/**
+ * Check that a string's length is between min and max.
+ *
+ * @author Emmanuel Bernard
+ * @author Gavin King
+ */
+public class LengthValidator implements ConstraintValidator<Length, String> {
+ private int min;
+ private int max;
+
+ public void initialize(Length parameters) {
+ min = parameters.min();
+ max = parameters.max();
+ validateParameters();
+ }
+
+ public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
+ if ( value == null ) {
+ return true;
+ }
+ int length = value.length();
+ return length >= min && length <= max;
+ }
+
+ private void validateParameters() {
+ if ( min < 0 ) {
+ throw new ValidationException( "The min parameter cannot be negative." );
+ }
+ if ( max < 0 ) {
+ throw new ValidationException( "The max paramter cannot be negative." );
+ }
+ if ( max < min ) {
+ throw new ValidationException( "The length cannot be negative." );
+ }
+ }
+}
\ No newline at end of file
Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Name.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Name.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/Name.java 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,26 @@
+// $Id:$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition;
+
+/**
+ * @author Hardy Ferentschik
+ */
+public class Name {
+ @Length(min = 1, max = 3)
+ public String name;
+}
Copied: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml (from rev 17378, beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/user-constraints.xml)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,7 @@
+<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
+ xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
+ <constraint-definition annotation="org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition.Length">
+ <validated-by include-existing-validators="false"/>
+ </constraint-definition>
+</constraint-mappings>
Property changes on: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-IncludeExisistingValidatorsTest.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-IncludeExisistingValidatorsTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-IncludeExisistingValidatorsTest.xml 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,9 @@
+<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
+ xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
+ <constraint-definition annotation="org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition.Length">
+ <validated-by include-existing-validators="true">
+ <value>org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdefinition.DummyLengthValidator</value>
+ </validated-by>
+ </constraint-definition>
+</constraint-mappings>
Copied: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-ExludeExisistingValidatorsTest.xml (from rev 17380, beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/validation-MultipleFieldDefinitionTest.xml)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-ExludeExisistingValidatorsTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-ExludeExisistingValidatorsTest.xml 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <constraint-mapping>
+ org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-ExludeExisistingValidatorsTest.xml
+ </constraint-mapping>
+</validation-config>
\ No newline at end of file
Property changes on: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-ExludeExisistingValidatorsTest.xml
___________________________________________________________________
Name: svn:keywords
+ Id
Added: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-IncludeExisistingValidatorsTest.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-IncludeExisistingValidatorsTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/validation-IncludeExisistingValidatorsTest.xml 2009-08-21 13:05:42 UTC (rev 17394)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <constraint-mapping>
+ org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdefinition/constraint-definition-IncludeExisistingValidatorsTest.xml
+ </constraint-mapping>
+</validation-config>
\ No newline at end of file
Modified: beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml 2009-08-21 12:09:34 UTC (rev 17393)
+++ beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml 2009-08-21 13:05:42 UTC (rev 17394)
@@ -1212,11 +1212,10 @@
the array</text>
</assertion>
<assertion id="e">
- <text>The new list is returned by
+ <text>The validator list is returned by
ConstraintDescriptor.getConstraintValidatorClasses()</text>
</assertion>
</section>
-
<section id="8" title="Exception model">
<assertion id="a">
<text>Every (runtime) exception raised either at initialization time or execution time
14 years, 9 months
Hibernate SVN: r17393 - beanvalidation/trunk/validation-tck/src/main/resources.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 08:09:34 -0400 (Fri, 21 Aug 2009)
New Revision: 17393
Modified:
beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml
Log:
fixed some typos
Modified: beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml 2009-08-21 12:09:02 UTC (rev 17392)
+++ beanvalidation/trunk/validation-tck/src/main/resources/tck-audit.xml 2009-08-21 12:09:34 UTC (rev 17393)
@@ -200,7 +200,7 @@
path to the bean or property hosting the constraint</text>
</assertion>
<assertion id="q">
- <text>You can point an error to a subpath of this default path by using the er- ror
+ <text>You can point an error to a subpath of this default path by using the error
builder fluent API.</text>
</assertion>
</section>
@@ -1135,15 +1135,15 @@
</assertion>
<assertion id="b">
<text>If not declared, the default value defined in the encapsulating bean element is
- con- sidered</text>
+ considered</text>
</assertion>
<assertion id="c">
<text>When ignore-annotations is true, property-level Bean Validation annotations on the
- targeted property are ig- nored (including the @Valid)</text>
+ targeted property are ignored (including the @Valid)</text>
</assertion>
<assertion id="d">
<text>When ignore-annotations is false, constraints declared in XML and constraints
- declared in annotations are added and form the list of property- level declared
+ declared in annotations are added and form the list of property-level declared
constraints.</text>
</assertion>
<assertion id="e">
@@ -1200,7 +1200,7 @@
</assertion>
<assertion id="b">
<text>If include-existing-validator is set to false, ConstraintValidator defined on the
- constraint annotation are ig- nored</text>
+ constraint annotation are ignored</text>
</assertion>
<assertion id="c">
<text>If set to true, the list of ConstraintValidators described in XML are concatenated
@@ -1221,7 +1221,7 @@
<assertion id="a">
<text>Every (runtime) exception raised either at initialization time or execution time
by any of the extension interfaces (ConstraintValidator, ConstraintValidatorFactory,
- MessageInterpolator, TraversableResolver, Valida- tionProviderResolver) is wrapped
+ MessageInterpolator, TraversableResolver, ValidationProviderResolver) is wrapped
in a ValidationException</text>
</assertion>
</section>
14 years, 9 months
Hibernate SVN: r17392 - validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 08:09:02 -0400 (Fri, 21 Aug 2009)
New Revision: 17392
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java
Log:
Added missing payload parameter.
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java 2009-08-21 11:06:00 UTC (rev 17391)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/constraints/Length.java 2009-08-21 12:09:02 UTC (rev 17392)
@@ -25,6 +25,7 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;
import javax.validation.Constraint;
+import javax.validation.ConstraintPayload;
import org.hibernate.validation.constraints.impl.LengthValidator;
@@ -32,6 +33,7 @@
* Validate that the string is between min and max included
*
* @author Emmanuel Bernard
+ * @author Hardy Ferentschik
*/
@Documented
@Constraint(validatedBy = LengthValidator.class)
@@ -45,4 +47,6 @@
String message() default "{org.hibernate.validation.constraints.Length.message}";
Class<?>[] groups() default { };
+
+ Class<? extends ConstraintPayload>[] payload() default { };
}
14 years, 9 months
Hibernate SVN: r17391 - in validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation: xml and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 07:06:00 -0400 (Fri, 21 Aug 2009)
New Revision: 17391
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java
Log:
fixed some class level orverride logic
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java 2009-08-21 11:04:54 UTC (rev 17390)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/AnnotationIgnores.java 2009-08-21 11:06:00 UTC (rev 17391)
@@ -51,7 +51,7 @@
*/
private final Map<Class<?>, List<Member>> ignoreAnnotationOnMember = new HashMap<Class<?>, List<Member>>();
- private final List<Class<?>> ignoreAnnotationOnClass = new ArrayList<Class<?>>();
+ private final Map<Class<?>, Boolean> ignoreAnnotationOnClass = new HashMap<Class<?>, Boolean>();
public void setDefaultIgnoreAnnotation(Class<?> clazz, Boolean b) {
if ( b == null ) {
@@ -105,12 +105,18 @@
log.debug( type + " level annotations are getting ignored for " + clazz.getName() + "." + member.getName() );
}
- public void setIgnoreAnnotationsOnClass(Class<?> clazz) {
- ignoreAnnotationOnClass.add( clazz );
+ public void setIgnoreAnnotationsOnClass(Class<?> clazz, boolean b) {
+ ignoreAnnotationOnClass.put( clazz, b );
}
public boolean isIgnoreAnnotations(Class<?> clazz) {
- boolean ignoreAnnotation = ignoreAnnotationOnClass.contains( clazz ) || getDefaultIgnoreAnnotation( clazz );
+ boolean ignoreAnnotation;
+ if ( ignoreAnnotationOnClass.containsKey( clazz ) ) {
+ ignoreAnnotation = ignoreAnnotationOnClass.get( clazz );
+ }
+ else {
+ ignoreAnnotation = getDefaultIgnoreAnnotation( clazz );
+ }
if ( log.isDebugEnabled() && ignoreAnnotation ) {
log.debug( "Class level annotation are getting ignored for " + clazz.getName() );
}
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java 2009-08-21 11:04:54 UTC (rev 17390)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/xml/XmlMappingParser.java 2009-08-21 11:06:00 UTC (rev 17391)
@@ -157,7 +157,7 @@
if ( !clazz.isAnnotation() ) {
throw new ValidationException( annotationClassName + " is not an annotation" );
}
- Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) clazz;
+ Class<? extends Annotation> annotationClass = ( Class<? extends Annotation> ) clazz;
ValidatedByType validatedByType = constraintDefinition.getValidatedBy();
List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> constraintValidatorClasses = new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();
@@ -328,9 +328,8 @@
}
// ignore annotation
- boolean ignoreClassAnnotation = classType.isIgnoreAnnotations() == null ? false : classType.isIgnoreAnnotations();
- if ( ignoreClassAnnotation ) {
- annotationIgnores.setIgnoreAnnotationsOnClass( beanClass );
+ if ( classType.isIgnoreAnnotations() != null ) {
+ annotationIgnores.setIgnoreAnnotationsOnClass( beanClass, classType.isIgnoreAnnotations() );
}
// group sequence
@@ -370,9 +369,11 @@
private List<Class<?>> createGroupSequence(GroupSequenceType groupSequenceType, String defaultPackage) {
List<Class<?>> groupSequence = new ArrayList<Class<?>>();
- for ( JAXBElement<String> groupName : groupSequenceType.getValue() ) {
- Class<?> group = getClass( groupName.getValue(), defaultPackage );
- groupSequence.add( group );
+ if ( groupSequenceType != null ) {
+ for ( JAXBElement<String> groupName : groupSequenceType.getValue() ) {
+ Class<?> group = getClass( groupName.getValue(), defaultPackage );
+ groupSequence.add( group );
+ }
}
return groupSequence;
}
14 years, 9 months
Hibernate SVN: r17390 - in beanvalidation/trunk/validation-tck/src/main: resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 07:04:54 -0400 (Fri, 21 Aug 2009)
New Revision: 17390
Added:
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingImplicitOverrideTest.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingTest.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingWithAnnotationTest.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ValidPackage.java
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingImplicitOverrideTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingWithAnnotationTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingImplicitOverrideTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingTest.xml
beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingWithAnnotationTest.xml
Modified:
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ConfigurationViaXmlAndAnnotationsTest.java
beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/Package.java
Log:
class level orverride tests
Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingImplicitOverrideTest.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingImplicitOverrideTest.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingImplicitOverrideTest.java 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,57 @@
+// $Id: ConstraintDeclarationTest.java 17380 2009-08-20 16:14:04Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+
+import org.jboss.test.audit.annotations.SpecAssertion;
+import org.jboss.testharness.AbstractTest;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.ArtifactType;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.jboss.testharness.impl.packaging.Resource;
+import org.jboss.testharness.impl.packaging.jsr303.ValidationXml;
+import org.testng.annotations.Test;
+
+import org.hibernate.jsr303.tck.util.TestUtil;
+import static org.hibernate.jsr303.tck.util.TestUtil.assertCorrectConstraintViolationMessages;
+import static org.hibernate.jsr303.tck.util.TestUtil.assertCorrectNumberOfViolations;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Artifact(artifactType = ArtifactType.JSR303)
+@Classes({ TestUtil.class, TestUtil.PathImpl.class, TestUtil.NodeImpl.class })
+@ValidationXml(value = "validation-ClassLevelOverridingImplicitOverrideTest.xml")
+@Resource(source = "package-constraints-ClassLevelOverridingImplicitOverrideTest.xml",
+ destination = "WEB-INF/classes/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingImplicitOverrideTest.xml")
+public class ClassLevelOverridingImplicitOverrideTest extends AbstractTest {
+
+ @Test
+ @SpecAssertion(section = "7.1.1.1", id = "b")
+ public void testIgnoreAnnotationsFromEnclosingBeanIsApplied() {
+ Validator validator = TestUtil.getValidatorUnderTest();
+ Package p = new Package();
+ Set<ConstraintViolation<Package>> violations = validator.validate( p );
+
+ assertCorrectNumberOfViolations( violations, 1 );
+ assertCorrectConstraintViolationMessages( violations, "ValidPackage defined in XML" );
+ }
+}
\ No newline at end of file
Copied: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingTest.java (from rev 17380, beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ConstraintDeclarationTest.java)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingTest.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingTest.java 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,61 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+
+import org.jboss.test.audit.annotations.SpecAssertion;
+import org.jboss.test.audit.annotations.SpecAssertions;
+import org.jboss.testharness.AbstractTest;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.ArtifactType;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.jboss.testharness.impl.packaging.Resource;
+import org.jboss.testharness.impl.packaging.jsr303.ValidationXml;
+import org.testng.annotations.Test;
+
+import org.hibernate.jsr303.tck.util.TestUtil;
+import static org.hibernate.jsr303.tck.util.TestUtil.assertCorrectConstraintViolationMessages;
+import static org.hibernate.jsr303.tck.util.TestUtil.assertCorrectNumberOfViolations;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Artifact(artifactType = ArtifactType.JSR303)
+@Classes({ TestUtil.class, TestUtil.PathImpl.class, TestUtil.NodeImpl.class })
+@ValidationXml(value = "validation-ClassLevelOverridingTest.xml")
+@Resource(source = "package-constraints-ClassLevelOverridingTest.xml",
+ destination = "WEB-INF/classes/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml")
+public class ClassLevelOverridingTest extends AbstractTest {
+
+ @Test
+ @SpecAssertions({
+ @SpecAssertion(section = "7.1.1.1", id = "a"),
+ @SpecAssertion(section = "7.1.1.1", id = "c")
+ })
+ public void testIgnoreClassLevelAnnotations() {
+ Validator validator = TestUtil.getValidatorUnderTest();
+ Package p = new Package();
+ Set<ConstraintViolation<Package>> violations = validator.validate( p );
+
+ assertCorrectNumberOfViolations( violations, 1 );
+ assertCorrectConstraintViolationMessages( violations, "ValidPackage defined in XML" );
+ }
+}
\ No newline at end of file
Property changes on: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingTest.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingWithAnnotationTest.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingWithAnnotationTest.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ClassLevelOverridingWithAnnotationTest.java 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,63 @@
+// $Id: ConstraintDeclarationTest.java 17380 2009-08-20 16:14:04Z hardy.ferentschik $
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+
+import org.jboss.test.audit.annotations.SpecAssertion;
+import org.jboss.test.audit.annotations.SpecAssertions;
+import org.jboss.testharness.AbstractTest;
+import org.jboss.testharness.impl.packaging.Artifact;
+import org.jboss.testharness.impl.packaging.ArtifactType;
+import org.jboss.testharness.impl.packaging.Classes;
+import org.jboss.testharness.impl.packaging.Resource;
+import org.jboss.testharness.impl.packaging.jsr303.ValidationXml;
+import org.testng.annotations.Test;
+
+import org.hibernate.jsr303.tck.util.TestUtil;
+import static org.hibernate.jsr303.tck.util.TestUtil.assertCorrectConstraintViolationMessages;
+import static org.hibernate.jsr303.tck.util.TestUtil.assertCorrectNumberOfViolations;
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Artifact(artifactType = ArtifactType.JSR303)
+@Classes({ TestUtil.class, TestUtil.PathImpl.class, TestUtil.NodeImpl.class })
+@ValidationXml(value = "validation-ClassLevelOverridingWithAnnotationTest.xml")
+@Resource(source = "package-constraints-ClassLevelOverridingWithAnnotationTest.xml",
+ destination = "WEB-INF/classes/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingWithAnnotationTest.xml")
+public class ClassLevelOverridingWithAnnotationTest extends AbstractTest {
+
+ @Test
+ @SpecAssertions({
+ @SpecAssertion(section = "7.1.1.1", id = "a"),
+ @SpecAssertion(section = "7.1.1.1", id = "d")
+ })
+ public void testClassLevelAnnotationsApplied() {
+ Validator validator = TestUtil.getValidatorUnderTest();
+ Package p = new Package();
+ Set<ConstraintViolation<Package>> violations = validator.validate( p );
+
+ assertCorrectNumberOfViolations( violations, 2 );
+ assertCorrectConstraintViolationMessages(
+ violations, "ValidPackage defined in XML", "ValidPackage defined as annotation"
+ );
+ }
+}
\ No newline at end of file
Modified: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ConfigurationViaXmlAndAnnotationsTest.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ConfigurationViaXmlAndAnnotationsTest.java 2009-08-21 09:37:44 UTC (rev 17389)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ConfigurationViaXmlAndAnnotationsTest.java 2009-08-21 11:04:54 UTC (rev 17390)
@@ -22,6 +22,7 @@
import javax.validation.metadata.BeanDescriptor;
import org.jboss.test.audit.annotations.SpecAssertion;
+import org.jboss.test.audit.annotations.SpecAssertions;
import org.jboss.testharness.AbstractTest;
import org.jboss.testharness.impl.packaging.Artifact;
import org.jboss.testharness.impl.packaging.ArtifactType;
@@ -45,11 +46,16 @@
public class ConfigurationViaXmlAndAnnotationsTest extends AbstractTest {
@Test
- @SpecAssertion(section = "7.1.1", id = "e")
+ @SpecAssertions({
+ @SpecAssertion(section = "7.1.1", id = "e"),
+ @SpecAssertion(section = "7.1.1", id = "a")
+ }
+ )
public void testEntityConfiguredViaAnnotationsAndXml() {
Validator validator = TestUtil.getValidatorUnderTest();
BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Package.class );
assertTrue( beanDescriptor.isBeanConstrained(), "With xml configuration there should be two constraints." );
+
assertEquals(
beanDescriptor.getConstraintsForProperty( "maxWeight" ).getConstraintDescriptors().size(),
2,
@@ -60,10 +66,12 @@
config.ignoreXmlConfiguration();
validator = config.buildValidatorFactory().getValidator();
beanDescriptor = validator.getConstraintsForClass( Package.class );
+
assertTrue(
beanDescriptor.isBeanConstrained(),
"Without xml there should be only one constraint."
);
+
assertEquals(
beanDescriptor.getConstraintsForProperty( "maxWeight" ).getConstraintDescriptors().size(),
1,
Modified: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/Package.java
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/Package.java 2009-08-21 09:37:44 UTC (rev 17389)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/Package.java 2009-08-21 11:04:54 UTC (rev 17390)
@@ -22,6 +22,7 @@
/**
* @author Hardy Ferentschik
*/
+@ValidPackage(message = "ValidPackage defined as annotation")
public class Package {
@Max(20)
private int maxWeight;
Copied: beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ValidPackage.java (from rev 17378, beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/ConsistentUserInformation.java)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ValidPackage.java (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/java/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/ValidPackage.java 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,56 @@
+// $Id$
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2008, Red Hat Middleware LLC, and individual contributors
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration;
+
+import java.lang.annotation.Documented;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import java.lang.annotation.Retention;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import java.lang.annotation.Target;
+import javax.validation.Constraint;
+import javax.validation.ConstraintPayload;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+
+
+/**
+ * @author Hardy Ferentschik
+ */
+@Constraint(validatedBy = ValidPackage.ValidPackageValidator.class)
+@Documented
+@Target({ METHOD, FIELD, TYPE })
+@Retention(RUNTIME)
+public @interface ValidPackage {
+ public abstract String message() default "User information is not consistent.";
+
+ public abstract Class<?>[] groups() default { };
+
+ public abstract Class<? extends ConstraintPayload>[] payload() default { };
+
+ public class ValidPackageValidator implements ConstraintValidator<ValidPackage, Package> {
+
+ public void initialize(ValidPackage parameters) {
+ }
+
+ public boolean isValid(Package p, ConstraintValidatorContext constraintValidatorContext) {
+ return false;
+ }
+ }
+}
\ No newline at end of file
Added: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingImplicitOverrideTest.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingImplicitOverrideTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingImplicitOverrideTest.xml 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,12 @@
+<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
+ xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
+ <default-package>org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration</default-package>
+ <bean class="Package" ignore-annotations="true">
+ <class>
+ <constraint annotation="org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration.ValidPackage">
+ <message>ValidPackage defined in XML</message>
+ </constraint>
+ </class>
+ </bean>
+</constraint-mappings>
\ No newline at end of file
Copied: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml (from rev 17380, beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ConstraintDeclarationTest.xml)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,12 @@
+<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
+ xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
+ <default-package>org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration</default-package>
+ <bean class="Package">
+ <class ignore-annotations="true">
+ <constraint annotation="org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration.ValidPackage">
+ <message>ValidPackage defined in XML</message>
+ </constraint>
+ </class>
+ </bean>
+</constraint-mappings>
\ No newline at end of file
Property changes on: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml
___________________________________________________________________
Name: svn:keywords
+ Id
Added: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingWithAnnotationTest.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingWithAnnotationTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingWithAnnotationTest.xml 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,12 @@
+<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd"
+ xmlns="http://jboss.org/xml/ns/javax/validation/mapping">
+ <default-package>org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration</default-package>
+ <bean class="Package">
+ <class ignore-annotations="false">
+ <constraint annotation="org.hibernate.jsr303.tck.tests.xmlconfiguration.constraintdeclaration.ValidPackage">
+ <message>ValidPackage defined in XML</message>
+ </constraint>
+ </class>
+ </bean>
+</constraint-mappings>
\ No newline at end of file
Added: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingImplicitOverrideTest.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingImplicitOverrideTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingImplicitOverrideTest.xml 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <constraint-mapping>/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingImplicitOverrideTest.xml</constraint-mapping>
+</validation-config>
\ No newline at end of file
Copied: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingTest.xml (from rev 17380, beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ConstraintDeclarationTest.xml)
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingTest.xml 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <constraint-mapping>/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingTest.xml</constraint-mapping>
+</validation-config>
\ No newline at end of file
Added: beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingWithAnnotationTest.xml
===================================================================
--- beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingWithAnnotationTest.xml (rev 0)
+++ beanvalidation/trunk/validation-tck/src/main/resources/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/validation-ClassLevelOverridingWithAnnotationTest.xml 2009-08-21 11:04:54 UTC (rev 17390)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
+ xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <constraint-mapping>/org/hibernate/jsr303/tck/tests/xmlconfiguration/constraintdeclaration/package-constraints-ClassLevelOverridingWithAnnotationTest.xml</constraint-mapping>
+</validation-config>
\ No newline at end of file
14 years, 9 months
Hibernate SVN: r17389 - validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 05:37:44 -0400 (Fri, 21 Aug 2009)
New Revision: 17389
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java
Log:
HV-188
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java 2009-08-21 09:19:23 UTC (rev 17388)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/metadata/ElementDescriptorImpl.java 2009-08-21 09:37:44 UTC (rev 17389)
@@ -59,11 +59,6 @@
return Collections.unmodifiableSet( constraintDescriptors );
}
- //FIXME remove when HV depends on BV post CR3 (typo in the method name)
- public Set<ConstraintDescriptor<?>> getUnorderdConstraintDescriptorsMatchingGroups(Class<?>... groups) {
- return getUnorderedConstraintDescriptorsMatchingGroups( groups );
- }
-
public Set<ConstraintDescriptor<?>> getUnorderedConstraintDescriptorsMatchingGroups(Class<?>... groups) {
Set<ConstraintDescriptor<?>> matchingDescriptors = new HashSet<ConstraintDescriptor<?>>();
GroupChain groupChain = new GroupChainGenerator().getGroupChainFor( Arrays.asList( groups ) );
14 years, 9 months
Hibernate SVN: r17388 - in validator/trunk/hibernate-validator/src: test/java/org/hibernate/validation/constraints and 1 other directory.
by hibernate-commits@lists.jboss.org
Author: hardy.ferentschik
Date: 2009-08-21 05:19:23 -0400 (Fri, 21 Aug 2009)
New Revision: 17388
Modified:
validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/ConstraintValidatorContextTest.java
Log:
HV-208
Modified: validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java
===================================================================
--- validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java 2009-08-21 08:45:30 UTC (rev 17387)
+++ validator/trunk/hibernate-validator/src/main/java/org/hibernate/validation/engine/ConstraintValidatorContextImpl.java 2009-08-21 09:19:23 UTC (rev 17388)
@@ -29,12 +29,12 @@
public class ConstraintValidatorContextImpl implements ConstraintValidatorContext {
private final List<ErrorMessage> errorMessages = new ArrayList<ErrorMessage>( 3 );
- private final Path propertyPath;
+ private final PathImpl propertyPath;
private final ConstraintDescriptor<?> constraintDescriptor;
private boolean defaultDisabled;
- public ConstraintValidatorContextImpl(Path propertyPath, ConstraintDescriptor<?> constraintDescriptor) {
+ public ConstraintValidatorContextImpl(PathImpl propertyPath, ConstraintDescriptor<?> constraintDescriptor) {
this.propertyPath = propertyPath;
this.constraintDescriptor = constraintDescriptor;
}
@@ -55,10 +55,6 @@
return constraintDescriptor;
}
- public boolean isDefaultErrorDisabled() {
- return defaultDisabled;
- }
-
public List<ErrorMessage> getErrorMessages() {
List<ErrorMessage> returnedErrorMessages = new ArrayList<ErrorMessage>( errorMessages );
if ( !defaultDisabled ) {
@@ -89,16 +85,22 @@
class ErrorBuilderImpl implements ErrorBuilder {
String messageTemplate;
- Path propertyPath;
+ PathImpl propertyPath;
- ErrorBuilderImpl(String template, Path path) {
+ ErrorBuilderImpl(String template, PathImpl path) {
messageTemplate = template;
propertyPath = path;
}
public NodeBuilderDefinedContext addSubNode(String name) {
- PathImpl path = PathImpl.createShallowCopy( propertyPath );
- path.addNode( new NodeImpl( name ) );
+ PathImpl path;
+ if ( propertyPath.isRootPath() ) {
+ path = PathImpl.createNewPath( name );
+ }
+ else {
+ path = PathImpl.createShallowCopy( propertyPath );
+ path.addNode( new NodeImpl( name ) );
+ }
return new NodeBuilderImpl( messageTemplate, path );
}
Modified: validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/ConstraintValidatorContextTest.java
===================================================================
--- validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/ConstraintValidatorContextTest.java 2009-08-21 08:45:30 UTC (rev 17387)
+++ validator/trunk/hibernate-validator/src/test/java/org/hibernate/validation/constraints/ConstraintValidatorContextTest.java 2009-08-21 09:19:23 UTC (rev 17388)
@@ -36,7 +36,7 @@
* HV-198
*/
@Test
- public void testCorrectAnnotationTypeForWithReportAsSingleViolation() {
+ public void testCorrectSubNodePath() {
Validator validator = TestUtil.getValidator();
Item item = new Item();
@@ -48,4 +48,22 @@
assertNumberOfViolations( constraintViolations, 1 );
assertCorrectPropertyPaths( constraintViolations, "interval.start" );
}
+
+ /**
+ * HV-208
+ */
+ @Test
+ public void testCorrectPath() {
+ Validator validator = TestUtil.getValidator();
+
+ Item item = new Item();
+ Interval interval = new Interval();
+ item.interval = interval;
+ item.interval.start = 10;
+ item.interval.end = 5;
+
+ Set<ConstraintViolation<Interval>> constraintViolations = validator.validate( interval );
+ assertNumberOfViolations( constraintViolations, 1 );
+ assertCorrectPropertyPaths( constraintViolations, "start" );
+ }
}
14 years, 9 months
Hibernate SVN: r17387 - core/trunk.
by hibernate-commits@lists.jboss.org
Author: galder.zamarreno(a)jboss.com
Date: 2009-08-21 04:45:30 -0400 (Fri, 21 Aug 2009)
New Revision: 17387
Modified:
core/trunk/pom.xml
Log:
[HHH-4103] Added cache infinispan to root modules.
Modified: core/trunk/pom.xml
===================================================================
--- core/trunk/pom.xml 2009-08-21 08:39:33 UTC (rev 17386)
+++ core/trunk/pom.xml 2009-08-21 08:45:30 UTC (rev 17387)
@@ -21,6 +21,7 @@
<module>core</module>
<module>cache-ehcache</module>
<module>cache-jbosscache</module>
+ <module>cache-infinispan</module>
<module>cache-oscache</module>
<module>cache-swarmcache</module>
<module>connection-c3p0</module>
14 years, 9 months
Hibernate SVN: r17386 - in core/trunk/cache-infinispan: src and 45 other directories.
by hibernate-commits@lists.jboss.org
Author: galder.zamarreno(a)jboss.com
Date: 2009-08-21 04:39:33 -0400 (Fri, 21 Aug 2009)
New Revision: 17386
Added:
core/trunk/cache-infinispan/pom.xml
core/trunk/cache-infinispan/src/
core/trunk/cache-infinispan/src/main/
core/trunk/cache-infinispan/src/main/java/
core/trunk/cache-infinispan/src/main/java/org/
core/trunk/cache-infinispan/src/main/java/org/hibernate/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeOverrides.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/TransactionalAccessDelegate.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/CollectionRegionImpl.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/ReadOnlyAccess.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/TransactionalAccess.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/EntityRegionImpl.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/ReadOnlyAccess.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/TransactionalAccess.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampsRegionImpl.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/
core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java
core/trunk/cache-infinispan/src/main/resources/
core/trunk/cache-infinispan/src/main/resources/org/
core/trunk/cache-infinispan/src/main/resources/org/hibernate/
core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/
core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/infinispan/
core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/infinispan/builder/
core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/infinispan/builder/infinispan-configs.xml
core/trunk/cache-infinispan/src/test/
core/trunk/cache-infinispan/src/test/java/
core/trunk/cache-infinispan/src/test/java/org/
core/trunk/cache-infinispan/src/test/java/org/hibernate/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractReadOnlyAccessTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractTransactionalAccessTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/InvalidatedTransactionalTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyExtraAPITestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractReadOnlyAccessTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractTransactionalAccessTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/EntityRegionImplTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/InvalidatedTransactionalTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyExtraAPITestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Contact.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Customer.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Item.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/VersionedItem.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/Account.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/AccountHolder.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/CacheAccessListener.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedCacheTestSetup.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedClassLoaderTest.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoader.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoaderTestSetup.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/AbstractDualNodeTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeConnectionProviderImpl.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTransactionManagerLookup.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/SessionRefreshTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java
core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
core/trunk/cache-infinispan/src/test/resources/
core/trunk/cache-infinispan/src/test/resources/hibernate.properties
core/trunk/cache-infinispan/src/test/resources/log4j.properties
core/trunk/cache-infinispan/src/test/resources/org/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Contact.hbm.xml
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Customer.hbm.xml
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Item.hbm.xml
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/classloader/
core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/classloader/Account.hbm.xml
Modified:
core/trunk/cache-infinispan/
Log:
[HHH-4103] Initial commit.
Property changes on: core/trunk/cache-infinispan
___________________________________________________________________
Name: svn:ignore
+ target
.project
.classpath
.settings
Added: core/trunk/cache-infinispan/pom.xml
===================================================================
--- core/trunk/cache-infinispan/pom.xml (rev 0)
+++ core/trunk/cache-infinispan/pom.xml 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,160 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-parent</artifactId>
+ <version>3.5.0-SNAPSHOT</version>
+ <relativePath>../parent/pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-infinispan</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Hibernate Infinispan Integration</name>
+ <description>Integration of Hibernate with Infinispan</description>
+
+ <properties>
+ <version.infinispan>4.0.0-SNAPSHOT</version.infinispan>
+ <version.hsqldb>1.8.0.2</version.hsqldb>
+ <version.cglib>2.2</version.cglib>
+ <version.javassist>3.4.GA</version.javassist>
+ <skipUnitTests>true</skipUnitTests>
+ <!--
+ Following is the default jgroups mcast address. If you find the testsuite runs very slowly, there
+ may be problems with multicast on the interface JGroups uses by default on your machine. You can
+ try to resolve setting 'jgroups.bind_addr' as a system-property to the jvm launching maven and
+ setting the value to an interface where you know multicast works
+ -->
+ <jgroups.bind_addr>127.0.0.1</jgroups.bind_addr>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>${version.infinispan}</version>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>${groupId}</groupId>
+ <artifactId>hibernate-testing</artifactId>
+ <version>${version}</version>
+ <!-- <scope>test</scope> TODO fix this -->
+ </dependency>
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>${version.infinispan}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <version>${version.hsqldb}</version>
+ <scope>test</scope>
+ </dependency>
+ <!-- this is optional on core :( and needed for testing -->
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>${version.cglib}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>${version.javassist}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <!-- Skip a long-running test of a prototype class -->
+ <exclude>**/ClusteredConcurrentTimestampRegionTestCase.java</exclude>
+ </excludes>
+ <systemProperties>
+ <property>
+ <name>hibernate.test.validatefailureexpected</name>
+ <value>true</value>
+ </property>
+ <property>
+ <name>jgroups.bind_addr</name>
+ <value>${jgroups.bind_addr}</value>
+ </property>
+ <!-- There are problems with multicast and IPv6 on some
+ OS/JDK combos, so we tell Java to use IPv4. If you
+ have problems with multicast when running the tests
+ you can try setting this to 'false', although typically
+ that won't be helpful.
+ -->
+ <property>
+ <name>java.net.preferIPv4Stack</name>
+ <value>true</value>
+ </property>
+ <!-- Tell JGroups to only wait a short time for PING
+ responses before determining coordinator. Speeds cluster
+ formation during integration tests. (This is too
+ low a value for a real system; only use for tests.)
+ -->
+ <property>
+ <name>jgroups.ping.timeout</name>
+ <value>500</value>
+ </property>
+ <!-- Tell JGroups to only require one PING response
+ before determining coordinator. Speeds cluster
+ formation during integration tests. (This is too
+ low a value for a real system; only use for tests.)
+ -->
+ <property>
+ <name>jgroups.ping.num_initial_members</name>
+ <value>1</value>
+ </property>
+ <!-- Disable the JGroups message bundling feature
+ to speed tests and avoid FLUSH issue -->
+ <property>
+ <name>jgroups.udp.enable_bundling</name>
+ <value>false</value>
+ </property>
+ </systemProperties>
+ <skipExec>${skipUnitTests}</skipExec>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>test</id>
+ <activation>
+ <activeByDefault>false</activeByDefault>
+ </activation>
+ <properties>
+ <skipUnitTests>false</skipUnitTests>
+ </properties>
+ </profile>
+ </profiles>
+</project>
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,429 @@
+package org.hibernate.cache.infinispan;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
+import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
+import org.hibernate.cache.infinispan.query.QueryResultsRegionImpl;
+import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
+import org.hibernate.cache.infinispan.timestamp.TimestampTypeOverrides;
+import org.hibernate.cache.infinispan.tm.HibernateTransactionManagerLookup;
+import org.hibernate.cfg.Settings;
+import org.hibernate.util.PropertiesHelper;
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.manager.CacheManager;
+import org.infinispan.manager.DefaultCacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link RegionFactory} for <a href="http://www.jboss.org/infinispan">Infinispan</a>-backed cache
+ * regions.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class InfinispanRegionFactory implements RegionFactory {
+
+ private static final Logger log = LoggerFactory.getLogger(InfinispanRegionFactory.class);
+
+ private static final String PREFIX = "hibernate.cache.infinispan.";
+
+ private static final String CONFIG_SUFFIX = ".cfg";
+
+ private static final String STRATEGY_SUFFIX = ".eviction.strategy";
+
+ private static final String WAKE_UP_INTERVAL_SUFFIX = ".eviction.wake_up_interval";
+
+ private static final String MAX_ENTRIES_SUFFIX = ".eviction.max_entries";
+
+ private static final String LIFESPAN_SUFFIX = ".eviction.lifespan";
+
+ private static final String MAX_IDLE_SUFFIX = ".eviction.max_idle";
+
+ /**
+ * Classpath or filesystem resource containing Infinispan configurations the factory should use.
+ *
+ * @see #DEF_INFINISPAN_CONFIG_RESOURCE
+ */
+ public static final String INFINISPAN_CONFIG_RESOURCE_PROP = "hibernate.cache.infinispan.cfg";
+
+ private static final String ENTITY_KEY = "entity";
+
+ /**
+ * Name of the configuration that should be used for entity caches.
+ *
+ * @see #DEF_ENTITY_RESOURCE
+ */
+ public static final String ENTITY_CACHE_RESOURCE_PROP = PREFIX + ENTITY_KEY + CONFIG_SUFFIX;
+
+ private static final String COLLECTION_KEY = "collection";
+
+ /**
+ * Name of the configuration that should be used for collection caches.
+ * No default value, as by default we try to use the same Infinispan cache
+ * instance we use for entity caching.
+ *
+ * @see #ENTITY_CACHE_RESOURCE_PROP
+ * @see #DEF_ENTITY_RESOURCE
+ */
+ public static final String COLLECTION_CACHE_RESOURCE_PROP = PREFIX + COLLECTION_KEY + CONFIG_SUFFIX;
+
+ private static final String TIMESTAMPS_KEY = "timestamps";
+
+ /**
+ * Name of the configuration that should be used for timestamp caches.
+ *
+ * @see #DEF_TS_RESOURCE
+ */
+ public static final String TIMESTAMPS_CACHE_RESOURCE_PROP = PREFIX + TIMESTAMPS_KEY + CONFIG_SUFFIX;
+
+ private static final String QUERY_KEY = "query";
+
+ /**
+ * Name of the configuration that should be used for query caches.
+ *
+ * @see #DEF_QUERY_RESOURCE
+ */
+ public static final String QUERY_CACHE_RESOURCE_PROP = PREFIX + QUERY_KEY + CONFIG_SUFFIX;
+
+ /**
+ * Default value for {@link #INFINISPAN_RESOURCE_PROP}. Specifies the "infinispan-configs.xml" file in this package.
+ */
+ public static final String DEF_INFINISPAN_CONFIG_RESOURCE = "org/hibernate/cache/infinispan/builder/infinispan-configs.xml";
+
+ /**
+ * Default value for {@link #ENTITY_CACHE_RESOURCE_PROP}.
+ */
+ public static final String DEF_ENTITY_RESOURCE = "entity";
+
+ /**
+ * Default value for {@link #TIMESTAMPS_CACHE_RESOURCE_PROP}.
+ */
+ public static final String DEF_TIMESTAMPS_RESOURCE = "timestamps";
+
+ /**
+ * Default value for {@link #QUERY_CACHE_RESOURCE_PROP}.
+ */
+ public static final String DEF_QUERY_RESOURCE = "local-query";
+
+ private CacheManager manager;
+
+ private final Map<String, TypeOverrides> typeOverrides = new HashMap<String, TypeOverrides>();
+
+ private final Set<String> definedConfigurations = new HashSet<String>();
+
+ private org.infinispan.transaction.lookup.TransactionManagerLookup transactionManagerlookup;
+
+ private TransactionManager transactionManager;
+
+ /**
+ * Create a new instance using the default configuration.
+ */
+ public InfinispanRegionFactory() {
+ }
+
+ /**
+ * Create a new instance using conifguration properties in <code>props</code>.
+ *
+ * @param props
+ * Environmental properties; currently unused.
+ */
+ public InfinispanRegionFactory(Properties props) {
+ }
+
+ /** {@inheritDoc} */
+ public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException {
+ log.debug("Building collection cache region [" + regionName + "]");
+ Cache cache = getCache(regionName, COLLECTION_KEY, properties);
+ return new CollectionRegionImpl(cache, regionName, metadata, transactionManager);
+ }
+
+ /** {@inheritDoc} */
+ public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) throws CacheException {
+ if (log.isDebugEnabled()) log.debug("Building entity cache region [" + regionName + "]");
+ Cache cache = getCache(regionName, ENTITY_KEY, properties);
+ return new EntityRegionImpl(cache, regionName, metadata, transactionManager);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties)
+ throws CacheException {
+ log.debug("Building query results cache region [" + regionName + "]");
+ String cacheName = typeOverrides.get(QUERY_KEY).getCacheName();
+ return new QueryResultsRegionImpl(manager.getCache(cacheName), regionName, properties, transactionManager);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties)
+ throws CacheException {
+ log.debug("Building timestamps cache region [" + regionName + "]");
+ String cacheName = typeOverrides.get(TIMESTAMPS_KEY).getCacheName();
+ return new TimestampsRegionImpl(manager.getCache(cacheName), regionName, transactionManager);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isMinimalPutsEnabledByDefault() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long nextTimestamp() {
+ return 0;
+ }
+
+ public void setCacheManager(CacheManager manager) {
+ this.manager = manager;
+ }
+
+ public CacheManager getCacheManager() {
+ return manager;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void start(Settings settings, Properties properties) throws CacheException {
+ log.debug("Starting Infinispan CacheManager");
+ try {
+ transactionManagerlookup = new HibernateTransactionManagerLookup(settings, properties);
+ transactionManager = transactionManagerlookup.getTransactionManager();
+
+ String configLoc = PropertiesHelper.getString(INFINISPAN_CONFIG_RESOURCE_PROP, properties, DEF_INFINISPAN_CONFIG_RESOURCE);
+ manager = createCacheManager(configLoc);
+ initGenericDataTypeOverrides();
+ Enumeration keys = properties.propertyNames();
+ while (keys.hasMoreElements()) {
+ String key = (String) keys.nextElement();
+ int prefixLoc = -1;
+ if ((prefixLoc = key.indexOf(PREFIX)) != -1) {
+ dissectProperty(prefixLoc, key, properties);
+ }
+ }
+ defineGenericDataTypeCacheConfigurations(settings, properties);
+ } catch (CacheException ce) {
+ throw ce;
+ } catch (Throwable t) {
+ throw new CacheException("Unable to start region factory", t);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void stop() {
+ log.debug("Stopping Infinispan CacheManager");
+ manager.stop();
+ }
+
+ /**
+ * Returns an unmodifiable map containing configured entity/collection type configuration overrides.
+ * This method should be used primarily for testing/checking purpouses.
+ *
+ * @return an unmodifiable map.
+ */
+ public Map<String, TypeOverrides> getTypeOverrides() {
+ return Collections.unmodifiableMap(typeOverrides);
+ }
+
+ public Set<String> getDefinedConfigurations() {
+ return Collections.unmodifiableSet(definedConfigurations);
+ }
+
+ protected CacheManager createCacheManager(String configLoc) throws CacheException {
+ try {
+ return new DefaultCacheManager(configLoc);
+ } catch (IOException e) {
+ throw new CacheException("Unable to create default cache manager", e);
+ }
+ }
+
+ private Map<String, TypeOverrides> initGenericDataTypeOverrides() {
+ TypeOverrides entityOverrides = new TypeOverrides();
+ entityOverrides.setCacheName(DEF_ENTITY_RESOURCE);
+ typeOverrides.put(ENTITY_KEY, entityOverrides);
+ TypeOverrides collectionOverrides = new TypeOverrides();
+ collectionOverrides.setCacheName(DEF_ENTITY_RESOURCE);
+ typeOverrides.put(COLLECTION_KEY, collectionOverrides);
+ TypeOverrides timestampOverrides = new TimestampTypeOverrides();
+ timestampOverrides.setCacheName(DEF_TIMESTAMPS_RESOURCE);
+ typeOverrides.put(TIMESTAMPS_KEY, timestampOverrides);
+ TypeOverrides queryOverrides = new TypeOverrides();
+ queryOverrides.setCacheName(DEF_QUERY_RESOURCE);
+ typeOverrides.put(QUERY_KEY, queryOverrides);
+ return typeOverrides;
+ }
+
+// private boolean isGenericDataTypeProperty(String property) {
+// return property.startsWith(PREFIX + ENTITY_KEY) || property.startsWith(PREFIX + COLLECTION_KEY)
+// || property.startsWith(PREFIX + QUERY_KEY) || property.startsWith(PREFIX + TIMESTAMP_KEY);
+// }
+
+ private void dissectProperty(int prefixLoc, String key, Properties properties) {
+ TypeOverrides cfgOverride = null;
+ int suffixLoc = -1;
+ if (!key.equals(INFINISPAN_CONFIG_RESOURCE_PROP) && (suffixLoc = key.indexOf(CONFIG_SUFFIX)) != -1) {
+ cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
+ cfgOverride.setCacheName(PropertiesHelper.extractPropertyValue(key, properties));
+ } else if ((suffixLoc = key.indexOf(STRATEGY_SUFFIX)) != -1) {
+ cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
+ cfgOverride.setEvictionStrategy(PropertiesHelper.extractPropertyValue(key, properties));
+ } else if ((suffixLoc = key.indexOf(WAKE_UP_INTERVAL_SUFFIX)) != -1) {
+ cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
+ cfgOverride.setEvictionWakeUpInterval(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
+ } else if ((suffixLoc = key.indexOf(MAX_ENTRIES_SUFFIX)) != -1) {
+ cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
+ cfgOverride.setEvictionMaxEntries(PropertiesHelper.getInt(key, properties, -1));
+ } else if ((suffixLoc = key.indexOf(LIFESPAN_SUFFIX)) != -1) {
+ cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
+ cfgOverride.setExpirationLifespan(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
+ } else if ((suffixLoc = key.indexOf(MAX_IDLE_SUFFIX)) != -1) {
+ cfgOverride = getOrCreateConfig(prefixLoc, key, suffixLoc);
+ cfgOverride.setExpirationMaxIdle(Long.parseLong(PropertiesHelper.extractPropertyValue(key, properties)));
+ }
+ }
+
+// private Configuration overrideCacheConfig(TypeOverrides config, Configuration baseCacheCfg) {
+// // If eviction strategy is different from null, an override has been defined
+// EvictionStrategy strategy = config.getEvictionStrategy();
+// if (strategy != null) baseCacheCfg.setEvictionStrategy(strategy);
+// // If eviction wake up interval is different from min value, an override has been defined
+// // Checking for -1 might not be enough because user might have defined -1 in the config.
+// // Same applies to other configuration options.
+// long wakeUpInterval = config.getEvictionWakeUpInterval();
+// if (wakeUpInterval != Long.MIN_VALUE) baseCacheCfg.setEvictionWakeUpInterval(wakeUpInterval);
+// int maxEntries = config.getEvictionMaxEntries();
+// if (maxEntries != Integer.MIN_VALUE) baseCacheCfg.setEvictionMaxEntries(maxEntries);
+// long lifespan = config.getExpirationLifespan();
+// if (lifespan != Long.MIN_VALUE) baseCacheCfg.setExpirationLifespan(lifespan);
+// long maxIdle = config.getExpirationMaxIdle();
+// if (maxIdle != Long.MIN_VALUE) baseCacheCfg.setExpirationMaxIdle(maxIdle);
+// return baseCacheCfg;
+// }
+
+ private TypeOverrides getOrCreateConfig(int prefixLoc, String key, int suffixLoc) {
+ String name = key.substring(prefixLoc + PREFIX.length(), suffixLoc);
+ TypeOverrides cfgOverride = typeOverrides.get(name);
+ if (cfgOverride == null) {
+ cfgOverride = new TypeOverrides();
+ typeOverrides.put(name, cfgOverride);
+ }
+ return cfgOverride;
+ }
+
+ private void defineGenericDataTypeCacheConfigurations(Settings settings, Properties properties) throws CacheException {
+ String[] defaultGenericDataTypes = new String[]{ENTITY_KEY, COLLECTION_KEY, TIMESTAMPS_KEY, QUERY_KEY};
+ for (String type : defaultGenericDataTypes) {
+ TypeOverrides override = typeOverrides.get(type);
+ String cacheName = override.getCacheName();
+ Configuration newCacheCfg = override.createInfinispanConfiguration();
+ // Apply overrides
+ Configuration cacheConfig = manager.defineConfiguration(cacheName, cacheName, newCacheCfg);
+ // Configure transaction manager
+ cacheConfig = configureTransactionManager(cacheConfig, cacheName, properties);
+ manager.defineConfiguration(cacheName, cacheName, cacheConfig);
+ definedConfigurations.add(cacheName);
+ override.validateInfinispanConfiguration(cacheConfig);
+ }
+ }
+
+ private Cache getCache(String regionName, String typeKey, Properties properties) {
+ TypeOverrides regionOverride = typeOverrides.get(regionName);
+ if (!definedConfigurations.contains(regionName)) {
+ String templateCacheName = null;
+ Configuration regionCacheCfg = null;
+ if (regionOverride != null) {
+ if (log.isDebugEnabled()) log.debug("Entity cache region specific configuration exists: " + regionOverride);
+ regionCacheCfg = regionOverride.createInfinispanConfiguration();
+ String cacheName = regionOverride.getCacheName();
+ if (cacheName != null) // Region specific override with a given cache name
+ templateCacheName = cacheName;
+ else // Region specific override without cache name, so template cache name is generic for data type.
+ templateCacheName = typeOverrides.get(typeKey).getCacheName();
+ } else {
+ // No region specific overrides, template cache name is generic for data type.
+ templateCacheName = typeOverrides.get(typeKey).getCacheName();
+ regionCacheCfg = typeOverrides.get(typeKey).createInfinispanConfiguration();
+ }
+ // Configure transaction manager
+ regionCacheCfg = configureTransactionManager(regionCacheCfg, templateCacheName, properties);
+ // Apply overrides
+ manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
+ definedConfigurations.add(regionName);
+ }
+ return manager.getCache(regionName);
+
+// if (regionOverride != null) {
+// if (log.isDebugEnabled()) log.debug("Entity cache region specific configuration exists: " + regionOverride);
+// String cacheName = regionOverride.getCacheName();
+// if (cacheName != null) {
+// // Region specific override with a given cache name
+// if (!definedConfigurations.contains(regionName)) {
+// templateCacheName = cacheName;
+// regionCacheCfg = regionOverride.createInfinispanConfiguration();
+// manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
+// definedConfigurations.add(regionName);
+// }
+// return manager.getCache(regionName);
+// } else {
+// // Region specific override without cache name, so template cache name is generic for data type.
+// if (!definedConfigurations.contains(regionName)) {
+// templateCacheName = typeOverrides.get(typeKey).getCacheName();
+// regionCacheCfg = regionOverride.createInfinispanConfiguration();
+// manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
+// definedConfigurations.add(regionName);
+// }
+// return manager.getCache(regionName);
+// }
+// }
+//
+// if (!definedConfigurations.contains(regionName)) {
+// templateCacheName = typeOverrides.get(typeKey).getCacheName();
+// regionCacheCfg = typeOverrides.get(typeKey).createInfinispanConfiguration();
+// manager.defineConfiguration(regionName, templateCacheName, regionCacheCfg);
+// definedConfigurations.add(regionName);
+// }
+// // No region specific overrides, get a cache instance for the generic entity data type region
+// return manager.getCache(regionName);
+ }
+
+ private Configuration configureTransactionManager(Configuration regionOverrides, String templateCacheName, Properties properties) {
+ // Get existing configuration to verify whether a tm was configured or not.
+ Configuration templateConfig = manager.defineConfiguration(templateCacheName, new Configuration());
+ String ispnTmLookupClassName = templateConfig.getTransactionManagerLookupClass();
+ String hbTmLookupClassName = org.hibernate.cache.infinispan.tm.HibernateTransactionManagerLookup.class.getName();
+ if (ispnTmLookupClassName != null && !ispnTmLookupClassName.equals(hbTmLookupClassName)) {
+ log.debug("Infinispan is configured [" + ispnTmLookupClassName + "] with a different transaction manager lookup " +
+ "class than Hibernate [" + hbTmLookupClassName + "]");
+ } else {
+ regionOverrides.setTransactionManagerLookup(transactionManagerlookup);
+ }
+ return regionOverrides;
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeOverrides.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeOverrides.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/TypeOverrides.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,138 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.cache.infinispan;
+
+import java.util.Locale;
+
+import org.hibernate.cache.CacheException;
+import org.infinispan.config.Configuration;
+import org.infinispan.eviction.EvictionStrategy;
+
+/**
+ * This class represents Infinispan cache parameters that can be configured via hibernate configuration properties
+ * for either general entity/collection/query/timestamp data type caches and overrides for individual entity or
+ * collection caches. Configuration these properties override previously defined properties in XML file.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class TypeOverrides {
+
+ private String cacheName;
+
+ private EvictionStrategy evictionStrategy;
+
+ private long evictionWakeUpInterval = Long.MIN_VALUE;
+
+ private int evictionMaxEntries = Integer.MIN_VALUE;
+
+ private long expirationLifespan = Long.MIN_VALUE;
+
+ private long expirationMaxIdle = Long.MIN_VALUE;
+
+ public String getCacheName() {
+ return cacheName;
+ }
+
+ public void setCacheName(String cacheName) {
+ this.cacheName = cacheName;
+ }
+
+ public EvictionStrategy getEvictionStrategy() {
+ return evictionStrategy;
+ }
+
+ public void setEvictionStrategy(String evictionStrategy) {
+ this.evictionStrategy = EvictionStrategy.valueOf(uc(evictionStrategy));
+ }
+
+ public long getEvictionWakeUpInterval() {
+ return evictionWakeUpInterval;
+ }
+
+ public void setEvictionWakeUpInterval(long evictionWakeUpInterval) {
+ this.evictionWakeUpInterval = evictionWakeUpInterval;
+ }
+
+ public int getEvictionMaxEntries() {
+ return evictionMaxEntries;
+ }
+
+ public void setEvictionMaxEntries(int evictionMaxEntries) {
+ this.evictionMaxEntries = evictionMaxEntries;
+ }
+
+ public long getExpirationLifespan() {
+ return expirationLifespan;
+ }
+
+ public void setExpirationLifespan(long expirationLifespan) {
+ this.expirationLifespan = expirationLifespan;
+ }
+
+ public long getExpirationMaxIdle() {
+ return expirationMaxIdle;
+ }
+
+ public void setExpirationMaxIdle(long expirationMaxIdle) {
+ this.expirationMaxIdle = expirationMaxIdle;
+ }
+
+// public boolean isConvertedToInfinispanConfiguration() {
+// return convertedToInfinispanConfiguration;
+// }
+
+ public Configuration createInfinispanConfiguration() {
+ Configuration cacheCfg = new Configuration();
+ // If eviction strategy is different from null, an override has been defined
+ if (evictionStrategy != null) cacheCfg.setEvictionStrategy(evictionStrategy);
+ // If eviction wake up interval is different from min value, an override has been defined
+ // Checking for -1 might not be enough because user might have defined -1 in the config.
+ // Same applies to other configuration options.
+ if (evictionWakeUpInterval != Long.MIN_VALUE) cacheCfg.setEvictionWakeUpInterval(evictionWakeUpInterval);
+ if (evictionMaxEntries != Integer.MIN_VALUE) cacheCfg.setEvictionMaxEntries(evictionMaxEntries);
+ if (expirationLifespan != Long.MIN_VALUE) cacheCfg.setExpirationLifespan(expirationLifespan);
+ if (expirationMaxIdle != Long.MIN_VALUE) cacheCfg.setExpirationMaxIdle(expirationMaxIdle);
+// convertedToInfinispanConfiguration = true;
+ return cacheCfg;
+ }
+
+ public void validateInfinispanConfiguration(Configuration configuration) throws CacheException {
+ // no-op
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append(getClass().getSimpleName()).append('{')
+ .append("cache=").append(cacheName)
+ .append(", strategy=").append(evictionStrategy)
+ .append(", wakeUpInterval=").append(evictionWakeUpInterval)
+ .append(", maxEntries=").append(evictionMaxEntries)
+ .append(", lifespan=").append(expirationLifespan)
+ .append(", maxIdle=").append(expirationMaxIdle)
+ .append('}').toString();
+ }
+
+ private String uc(String s) {
+ return s == null ? null : s.toUpperCase(Locale.ENGLISH);
+ }
+}
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/TransactionalAccessDelegate.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/TransactionalAccessDelegate.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/TransactionalAccessDelegate.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,116 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.infinispan.access;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.infinispan.Cache;
+
+/**
+ * Defines the strategy for transactional access to entity or collection data in a Infinispan instance.
+ * <p>
+ * The intent of this class is to encapsulate common code and serve as a delegate for
+ * {@link EntityRegionAccessStrategy} and {@link CollectionRegionAccessStrategy} implementations.
+ *
+ * @author Brian Stansberry
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class TransactionalAccessDelegate {
+
+ protected final Cache cache;
+
+ public TransactionalAccessDelegate(Cache cache) {
+ this.cache = cache;
+ }
+
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ return cache.get(key);
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+ cache.putForExternalRead(key, value);
+ return true;
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
+ throws CacheException {
+ return putFromLoad(key, value, txTimestamp, version);
+ }
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
+
+ public boolean insert(Object key, Object value, Object version) throws CacheException {
+ cache.put(key, value);
+ return true;
+ }
+
+ public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+ return false;
+ }
+
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
+ cache.put(key, value);
+ return true;
+ }
+
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+ throws CacheException {
+ return false;
+ }
+
+ public void remove(Object key) throws CacheException {
+ cache.remove(key);
+ }
+
+ public void removeAll() throws CacheException {
+ cache.clear();
+ }
+
+// public void evict(Object key) throws CacheException {
+// cache.evict(key);
+// }
+
+ public void evictAll() throws CacheException {
+ evictOrRemoveAll();
+ }
+
+ private void evictOrRemoveAll() throws CacheException {
+ cache.clear();
+ }
+}
Property changes on: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/access/TransactionalAccessDelegate.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/CollectionRegionImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/CollectionRegionImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/CollectionRegionImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,33 @@
+package org.hibernate.cache.infinispan.collection;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
+import org.infinispan.Cache;
+
+/**
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class CollectionRegionImpl extends BaseTransactionalDataRegion implements CollectionRegion {
+
+ public CollectionRegionImpl(Cache<Object, Object> cache, String name, CacheDataDescription metadata, TransactionManager transactionManager) {
+ super(cache, name, metadata, transactionManager);
+ }
+
+ public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+ if (AccessType.READ_ONLY.equals(accessType)) {
+ return new ReadOnlyAccess(this);
+ } else if (AccessType.TRANSACTIONAL.equals(accessType)) {
+ return new TransactionalAccess(this);
+ }
+ throw new CacheException("Unsupported access type [" + accessType.getName() + "]");
+ }
+
+}
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/ReadOnlyAccess.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/ReadOnlyAccess.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/ReadOnlyAccess.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,41 @@
+package org.hibernate.cache.infinispan.collection;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This defines the strategy for transactional access to collection data in a
+ * Infinispan instance.
+ * <p/>
+ * The read-only access to a Infinispan really is still transactional, just with
+ * the extra semantic or guarantee that we will not update data.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+class ReadOnlyAccess extends TransactionalAccess {
+ private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
+
+ ReadOnlyAccess(CollectionRegionImpl region) {
+ super(region);
+ }
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only region");
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
+
+}
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/TransactionalAccess.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/TransactionalAccess.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/collection/TransactionalAccess.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,74 @@
+package org.hibernate.cache.infinispan.collection;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate;
+
+/**
+ * Transactional collection region access for Infinispan.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+class TransactionalAccess implements CollectionRegionAccessStrategy {
+
+ private final CollectionRegionImpl region;
+
+ private final TransactionalAccessDelegate delegate;
+
+ TransactionalAccess(CollectionRegionImpl region) {
+ this.region = region;
+ this.delegate = new TransactionalAccessDelegate(region.getCache());
+ }
+
+ public void evict(Object key) throws CacheException {
+// delegate.evict(key);
+ delegate.remove(key);
+ }
+
+ public void evictAll() throws CacheException {
+ delegate.evictAll();
+ }
+
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ return delegate.get(key, txTimestamp);
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+ return delegate.putFromLoad(key, value, txTimestamp, version);
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException {
+ return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
+ }
+
+ public void remove(Object key) throws CacheException {
+ delegate.remove(key);
+ }
+
+ public void removeAll() throws CacheException {
+ delegate.removeAll();
+ }
+
+ public CollectionRegion getRegion() {
+ return region;
+ }
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/EntityRegionImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/EntityRegionImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/EntityRegionImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,33 @@
+package org.hibernate.cache.infinispan.entity;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
+import org.infinispan.Cache;
+
+/**
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class EntityRegionImpl extends BaseTransactionalDataRegion implements EntityRegion {
+
+ public EntityRegionImpl(Cache<Object, Object> cache, String name, CacheDataDescription metadata, TransactionManager transactionManager) {
+ super(cache, name, metadata, transactionManager);
+ }
+
+ public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
+ if (AccessType.READ_ONLY.equals(accessType)) {
+ return new ReadOnlyAccess(this);
+ } else if (AccessType.TRANSACTIONAL.equals(accessType)) {
+ return new TransactionalAccess(this);
+ }
+ throw new CacheException("Unsupported access type [" + accessType.getName() + "]");
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/ReadOnlyAccess.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/ReadOnlyAccess.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/ReadOnlyAccess.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,49 @@
+package org.hibernate.cache.infinispan.entity;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A specialization of {@link TransactionalAccess} that ensures we never update data. Infinispan
+ * access is always transactional.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+class ReadOnlyAccess extends TransactionalAccess {
+ private static final Logger log = LoggerFactory.getLogger(ReadOnlyAccess.class);
+
+ ReadOnlyAccess(EntityRegionImpl region) {
+ super(region);
+ }
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ log.error("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+
+ @Override
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
+ throws CacheException {
+ throw new UnsupportedOperationException("Illegal attempt to edit read only item");
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/TransactionalAccess.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/TransactionalAccess.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/entity/TransactionalAccess.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,89 @@
+package org.hibernate.cache.infinispan.entity;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.infinispan.access.TransactionalAccessDelegate;
+
+/**
+ * Transactional entity region access for Infinispan.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+class TransactionalAccess implements EntityRegionAccessStrategy {
+
+ private final EntityRegionImpl region;
+
+ private final TransactionalAccessDelegate delegate;
+
+ TransactionalAccess(EntityRegionImpl region) {
+ this.region = region;
+ this.delegate = new TransactionalAccessDelegate(region.getCache());
+ }
+
+ public void evict(Object key) throws CacheException {
+ delegate.remove(key);
+ }
+
+ public void evictAll() throws CacheException {
+ delegate.evictAll();
+ }
+
+ public Object get(Object key, long txTimestamp) throws CacheException {
+ return delegate.get(key, txTimestamp);
+ }
+
+ public EntityRegion getRegion() {
+ return this.region;
+ }
+
+ public boolean insert(Object key, Object value, Object version) throws CacheException {
+ region.getCache().put(key, value);
+ return true; // TODO this is suspect
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
+ return delegate.putFromLoad(key, value, txTimestamp, version);
+ }
+
+ public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride) throws CacheException {
+ return delegate.putFromLoad(key, value, txTimestamp, version, minimalPutOverride);
+ }
+
+ public void remove(Object key) throws CacheException {
+ delegate.remove(key);
+ }
+
+ public void removeAll() throws CacheException {
+ delegate.removeAll();
+ }
+
+ public boolean update(Object key, Object value, Object currentVersion, Object previousVersion) throws CacheException {
+ return delegate.update(key, value, currentVersion, previousVersion);
+ }
+
+ public SoftLock lockItem(Object key, Object version) throws CacheException {
+ return null;
+ }
+
+ public SoftLock lockRegion() throws CacheException {
+ return null;
+ }
+
+ public void unlockItem(Object key, SoftLock lock) throws CacheException {
+ }
+
+ public void unlockRegion(SoftLock lock) throws CacheException {
+ }
+
+ public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
+ return false;
+ }
+
+ public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) throws CacheException {
+ return false;
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseGeneralDataRegion.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,38 @@
+package org.hibernate.cache.infinispan.impl;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.GeneralDataRegion;
+import org.infinispan.Cache;
+
+/**
+ * Support for Infinispan {@link GeneralDataRegion} implementors.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class BaseGeneralDataRegion extends BaseRegion implements GeneralDataRegion {
+
+ public BaseGeneralDataRegion(Cache<Object, Object> cache, String name, TransactionManager transactionManager) {
+ super(cache, name, transactionManager);
+ }
+
+ public void evict(Object key) throws CacheException {
+ getCache().evict(key);
+ }
+
+ public void evictAll() throws CacheException {
+ getCache().clear();
+ }
+
+ public Object get(Object key) throws CacheException {
+ return getCache().get(key);
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+ getCache().put(key, value);
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseRegion.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,182 @@
+package org.hibernate.cache.infinispan.impl;
+
+import java.util.Map;
+
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+
+/**
+ * Support for Infinispan {@link Region}s. Handles common "utility" methods for an underlying named
+ * Cache. In other words, this implementation doesn't actually read or write data. Subclasses are
+ * expected to provide core cache interaction appropriate to the semantics needed.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class BaseRegion implements Region {
+ private final Cache cache;
+ private final String name;
+ protected final TransactionManager transactionManager;
+
+ public BaseRegion(Cache cache, String name, TransactionManager transactionManager) {
+ this.cache = cache;
+ this.name = name;
+ this.transactionManager = transactionManager;
+ }
+
+ public Cache getCache() {
+ return cache;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public long getElementCountInMemory() {
+ return cache.size();
+ }
+
+ /**
+ * Not supported.
+ *
+ * @return -1
+ */
+ public long getElementCountOnDisk() {
+ return -1;
+ }
+
+ /**
+ * Not supported.
+ *
+ * @return -1
+ */
+ public long getSizeInMemory() {
+ return -1;
+ }
+
+ public int getTimeout() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public long nextTimestamp() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public Map toMap() {
+ return cache;
+ }
+
+ public void destroy() throws CacheException {
+ // TODO see if we need to do this even in spite of RF.shutdown()
+ }
+
+ public boolean contains(Object key) {
+ return CacheHelper.containsKey(cache, key, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT);
+ }
+
+ /**
+ * Performs a JBoss Cache <code>get(Fqn, Object)</code> after first
+ * {@link #suspend suspending any ongoing transaction}. Wraps any exception
+ * in a {@link CacheException}. Ensures any ongoing transaction is resumed.
+ *
+ * @param key The key of the item to get
+ * @param opt any option to add to the get invocation. May be <code>null</code>
+ * @param suppressTimeout should any TimeoutException be suppressed?
+ * @return The retrieved object
+ * @throws CacheException issue managing transaction or talking to cache
+ */
+ protected Object suspendAndGet(Object key, Flag opt, boolean suppressTimeout) throws CacheException {
+ Transaction tx = suspend();
+ try {
+ if (suppressTimeout)
+ return CacheHelper.getAllowingTimeout(cache, key);
+ else
+ return CacheHelper.get(cache, key);
+ } finally {
+ resume(tx);
+ }
+ }
+
+ /**
+ * Tell the TransactionManager to suspend any ongoing transaction.
+ *
+ * @return the transaction that was suspended, or <code>null</code> if
+ * there wasn't one
+ */
+ protected Transaction suspend() {
+ Transaction tx = null;
+ try {
+ if (transactionManager != null) {
+ tx = transactionManager.suspend();
+ }
+ } catch (SystemException se) {
+ throw new CacheException("Could not suspend transaction", se);
+ }
+ return tx;
+ }
+
+ /**
+ * Tell the TransactionManager to resume the given transaction
+ *
+ * @param tx
+ * the transaction to suspend. May be <code>null</code>.
+ */
+ protected void resume(Transaction tx) {
+ try {
+ if (tx != null)
+ transactionManager.resume(tx);
+ } catch (Exception e) {
+ throw new CacheException("Could not resume transaction", e);
+ }
+ }
+
+// /**
+// * HACKY WAY TO GET THE TRANSACTION MANAGER, TODO: resolve it!
+// */
+// private static TransactionManager getTransactionManager(Properties properties) {
+//// return cache == null ? null : extractComponent(cache, TransactionManager.class);
+// return TransactionManagerLookupFactory.getTransactionManager(properties);
+// }
+//
+// public static <T> T extractComponent(Cache cache, Class<T> componentType) {
+// ComponentRegistry cr = extractComponentRegistry(cache);
+// return cr.getComponent(componentType);
+// }
+//
+// public static ComponentRegistry extractComponentRegistry(Cache cache) {
+// return (ComponentRegistry) extractField(cache, "componentRegistry");
+// }
+//
+// public static Object extractField(Object target, String fieldName) {
+// return extractField(target.getClass(), target, fieldName);
+// }
+//
+// public static Object extractField(Class type, Object target, String fieldName) {
+// Field field;
+// try {
+// field = type.getDeclaredField(fieldName);
+// field.setAccessible(true);
+// return field.get(target);
+// }
+// catch (Exception e) {
+// if (type.equals(Object.class)) {
+// e.printStackTrace();
+// return null;
+// } else {
+// // try with superclass!!
+// return extractField(type.getSuperclass(), target, fieldName);
+// }
+// }
+// }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/impl/BaseTransactionalDataRegion.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,33 @@
+package org.hibernate.cache.infinispan.impl;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.TransactionalDataRegion;
+import org.infinispan.Cache;
+
+/**
+ * Support for Inifinispan {@link TransactionalDataRegion} implementors.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class BaseTransactionalDataRegion extends BaseRegion implements TransactionalDataRegion {
+
+ private final CacheDataDescription metadata;
+
+ public BaseTransactionalDataRegion(Cache<Object, Object> cache, String name, CacheDataDescription metadata, TransactionManager transactionManager) {
+ super(cache, name, transactionManager);
+ this.metadata = metadata;
+ }
+
+ public CacheDataDescription getCacheDataDescription() {
+ return metadata;
+ }
+
+ public boolean isTransactionAware() {
+ return transactionManager != null;
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/query/QueryResultsRegionImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,85 @@
+package org.hibernate.cache.infinispan.query;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.infinispan.impl.BaseTransactionalDataRegion;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.util.PropertiesHelper;
+import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+
+/**
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class QueryResultsRegionImpl extends BaseTransactionalDataRegion implements QueryResultsRegion {
+ public static final String QUERY_CACHE_LOCAL_ONLY_PROP = "hibernate.cache.infinispan.query.localonly";
+
+ private boolean localOnly;
+
+ public QueryResultsRegionImpl(Cache<Object, Object> cache, String name, Properties properties, TransactionManager transactionManager) {
+ super(cache, name, null, transactionManager);
+
+ // If JBC is using INVALIDATION, we don't want to propagate changes.
+ // We use the Timestamps cache to manage invalidation
+ localOnly = CacheHelper.isClusteredInvalidation(cache);
+ if (!localOnly) {
+ // We don't want to waste effort setting an option if JBC is
+ // already in LOCAL mode. If JBC is REPL_(A)SYNC then check
+ // if they passed an config option to disable query replication
+ localOnly = CacheHelper.isClusteredReplication(cache)
+ && PropertiesHelper.getBoolean(QUERY_CACHE_LOCAL_ONLY_PROP, properties, false);
+ }
+ }
+
+ public void evict(Object key) throws CacheException {
+ if (localOnly)
+ CacheHelper.removeKey(getCache(), key, Flag.CACHE_MODE_LOCAL);
+ else
+ CacheHelper.removeKey(getCache(), key);
+ }
+
+ public void evictAll() throws CacheException {
+ if (localOnly)
+ CacheHelper.removeAll(getCache(), Flag.CACHE_MODE_LOCAL);
+ else
+ CacheHelper.removeAll(getCache());
+ }
+
+ public Object get(Object key) throws CacheException {
+ // Don't hold the JBC node lock throughout the tx, as that
+ // prevents updates
+ // Add a zero (or low) timeout option so we don't block
+ // waiting for tx's that did a put to commit
+ return suspendAndGet(key, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT, true);
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+ // Here we don't want to suspend the tx. If we do:
+ // 1) We might be caching query results that reflect uncommitted
+ // changes. No tx == no WL on cache node, so other threads
+ // can prematurely see those query results
+ // 2) No tx == immediate replication. More overhead, plus we
+ // spread issue #1 above around the cluster
+
+ // Add a zero (or quite low) timeout option so we don't block.
+ // Ignore any TimeoutException. Basically we forego caching the
+ // query result in order to avoid blocking.
+ // Reads are done with suspended tx, so they should not hold the
+ // lock for long. Not caching the query result is OK, since
+ // any subsequent read will just see the old result with its
+ // out-of-date timestamp; that result will be discarded and the
+ // db query performed again.
+ if (localOnly)
+ CacheHelper.putAllowingTimeout(getCache(), key, value, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT, Flag.CACHE_MODE_LOCAL);
+ else
+ CacheHelper.putAllowingTimeout(getCache(), key, value, Flag.ZERO_LOCK_ACQUISITION_TIMEOUT);
+
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampTypeOverrides.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.cache.infinispan.timestamp;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.infinispan.TypeOverrides;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.Configuration.CacheMode;
+import org.infinispan.eviction.EvictionStrategy;
+
+/**
+ * TimestampTypeOverrides.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class TimestampTypeOverrides extends TypeOverrides {
+ @Override
+ public void validateInfinispanConfiguration(Configuration configuration) throws CacheException {
+ CacheMode cacheMode = configuration.getCacheMode();
+ if (cacheMode.equals(CacheMode.INVALIDATION_ASYNC) || cacheMode.equals(CacheMode.INVALIDATION_SYNC)) {
+ throw new CacheException("Timestamp cache cannot be configured with invalidation");
+ }
+ EvictionStrategy strategy = configuration.getEvictionStrategy();
+ if (!strategy.equals(EvictionStrategy.NONE)) {
+ throw new CacheException("Timestamp cache cannot be configured with eviction");
+ }
+ }
+}
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampsRegionImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampsRegionImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/timestamp/TimestampsRegionImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,121 @@
+package org.hibernate.cache.infinispan.timestamp;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.infinispan.impl.BaseGeneralDataRegion;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent;
+
+/**
+ * Defines the behavior of the timestamps cache region for Infinispan.
+ *
+ * @author Chris Bredesen
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+@Listener
+public class TimestampsRegionImpl extends BaseGeneralDataRegion implements TimestampsRegion {
+
+ private Map localCache = new ConcurrentHashMap();
+
+ public TimestampsRegionImpl(Cache<Object, Object> cache, String name, TransactionManager transactionManager) {
+ super(cache, name, transactionManager);
+ cache.addListener(this);
+ populateLocalCache();
+ }
+
+ @Override
+ public void evict(Object key) throws CacheException {
+ // TODO Is this a valid operation on a timestamps cache?
+ CacheHelper.removeKey(getCache(), key);
+ }
+
+ public void evictAll() throws CacheException {
+ // TODO Is this a valid operation on a timestamps cache?
+ CacheHelper.removeAll(getCache());
+ }
+
+ public Object get(Object key) throws CacheException {
+ Object value = localCache.get(key);
+ if (value == null) {
+ value = suspendAndGet(key, null, false);
+ if (value != null)
+ localCache.put(key, value);
+ }
+ return value;
+ }
+
+ public void put(Object key, Object value) throws CacheException {
+ // Don't hold the JBC node lock throughout the tx, as that
+ // prevents reads and other updates
+ Transaction tx = suspend();
+ try {
+ // We ensure ASYNC semantics (JBCACHE-1175)
+ CacheHelper.put(getCache(), key, value, Flag.FORCE_ASYNCHRONOUS);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ } finally {
+ resume(tx);
+ }
+ }
+
+ @Override
+ public void destroy() throws CacheException {
+ localCache.clear();
+ getCache().removeListener(this);
+ super.destroy();
+ }
+
+ /**
+ * Monitors cache events and updates the local cache
+ *
+ * @param event
+ */
+ @CacheEntryModified
+ public void nodeModified(CacheEntryModifiedEvent event) {
+ if (event.isPre()) return;
+ localCache.put(event.getKey(), event.getValue());
+ }
+
+ /**
+ * Monitors cache events and updates the local cache
+ *
+ * @param event
+ */
+ @CacheEntryRemoved
+ public void nodeRemoved(CacheEntryRemovedEvent event) {
+ if (event.isPre()) return;
+ localCache.remove(event.getKey());
+// Fqn fqn = event.getFqn();
+// Fqn regFqn = getRegionFqn();
+// if (fqn.size() == regFqn.size() + 1 && fqn.isChildOf(regFqn)) {
+// Object key = fqn.get(regFqn.size());
+// localCache.remove(key);
+// } else if (fqn.equals(regFqn)) {
+// localCache.clear();
+// }
+ }
+
+ /**
+ * Brings all data from the distributed cache into our local cache.
+ */
+ private void populateLocalCache() {
+ Set children = CacheHelper.getKeySet(getCache());
+ for (Object key : children)
+ get(key);
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/tm/HibernateTransactionManagerLookup.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.cache.infinispan.tm;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.cfg.Settings;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * HibernateTransactionManagerLookup.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class HibernateTransactionManagerLookup implements org.infinispan.transaction.lookup.TransactionManagerLookup {
+ private final TransactionManagerLookup hibernateLookup;
+
+ private final Properties properties;
+
+ public HibernateTransactionManagerLookup(Settings settings, Properties properties) {
+ if (settings != null)
+ this.hibernateLookup = settings.getTransactionManagerLookup();
+ else
+ this.hibernateLookup = null;
+ this.properties = properties;
+ }
+
+ public TransactionManager getTransactionManager() throws Exception {
+ return hibernateLookup == null ? null : hibernateLookup.getTransactionManager(properties);
+ }
+
+}
Added: core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java
===================================================================
--- core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java (rev 0)
+++ core/trunk/cache-infinispan/src/main/java/org/hibernate/cache/infinispan/util/CacheHelper.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,447 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.cache.infinispan.util;
+
+import java.util.Set;
+
+import org.hibernate.cache.CacheException;
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.Flag;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper for dealing with Infinisan cache instances.
+ *
+ * @author Steve Ebersole
+ * @author Brian Stansberry
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class CacheHelper {
+
+ /** Key under which items are cached */
+ public static final String ITEM = "item";
+ /** Key and value used in a hack to create region root nodes */
+ public static final String DUMMY = "dummy";
+
+ private static final Logger log = LoggerFactory.getLogger(CacheHelper.class);
+
+ /**
+ * Disallow external instantiation of CacheHelper.
+ */
+ private CacheHelper() {
+ }
+
+ /**
+ * Is this cache participating in a cluster with invalidation?
+ *
+ * @param cache
+ * The cache to check.
+ * @return True if the cache is configured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredInvalidation(Cache cache) {
+ return isClusteredInvalidation(cache.getConfiguration().getCacheMode());
+ }
+
+ /**
+ * Does this cache mode indicate clustered invalidation?
+ *
+ * @param cacheMode
+ * The cache to check
+ * @return True if the cache mode is confiogured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredInvalidation(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.INVALIDATION_ASYNC
+ || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+ }
+
+ /**
+ * Is this cache participating in a cluster with replication?
+ *
+ * @param cache
+ * The cache to check.
+ * @return True if the cache is configured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredReplication(Cache cache) {
+ return isClusteredReplication(cache.getConfiguration().getCacheMode());
+ }
+
+ /**
+ * Does this cache mode indicate clustered replication?
+ *
+ * @param cacheMode
+ * The cache to check
+ * @return True if the cache mode is confiogured for synchronous/asynchronous invalidation; false
+ * otherwise.
+ */
+ public static boolean isClusteredReplication(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.REPL_ASYNC || cacheMode == Configuration.CacheMode.REPL_SYNC;
+ }
+
+ public static boolean isSynchronous(Cache cache) {
+ return isSynchronous(cache.getConfiguration().getCacheMode());
+ }
+
+ public static boolean isSynchronous(Configuration.CacheMode cacheMode) {
+ return cacheMode == Configuration.CacheMode.REPL_SYNC || cacheMode == Configuration.CacheMode.INVALIDATION_SYNC;
+ }
+
+ public static Set getKeySet(Cache cache) {
+ return cache.keySet();
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>get(Fqn, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ */
+ public static Object get(Cache cache, Object key) throws CacheException {
+ try {
+ return cache.get(key);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>get(Fqn, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ */
+ public static Object getAllowingTimeout(Cache cache, Object key) throws CacheException {
+ try {
+ return cache.get(key);
+ } catch (TimeoutException ignored) {
+ // ignore it
+ return null;
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>put(Object, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ */
+ public static void put(Cache cache, Object key, Object value) throws CacheException {
+ put(cache, key, value, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>put(Object, Object)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void put(Cache cache, Object key, Object value, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().put(key, value, option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>put(Object, Object)</code>, ignoring any {@link TimeoutException} and wrapping any other
+ * exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void putAllowingTimeout(Cache cache, Object key, Object value, Flag... option) throws CacheException {
+ try {
+ cache.getAdvancedCache().put(key, value, option);
+ } catch (TimeoutException allowed) {
+ // ignore it
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>putForExternalRead(Object, Object)</code>, wrapping any exception in a
+ * {@link CacheException}. Ignores any JBoss Cache {@link TimeoutException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ */
+ public static boolean putForExternalRead(Cache cache, Object key, Object value) throws CacheException {
+ return putForExternalRead(cache, key, value, (Flag[])null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>putForExternalRead(Object, Object)</code>, wrapping any exception in a
+ * {@link CacheException}. Ignores any JBoss Cache {@link TimeoutException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param value
+ * data to store in the cache node
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static boolean putForExternalRead(Cache cache, Object key, Object value, Flag... option) throws CacheException {
+ try {
+ cache.getAdvancedCache().putForExternalRead(key, value, option);
+ return true;
+ } catch (TimeoutException te) {
+ // ignore!
+ log.debug("ignoring write lock acquisition failure");
+ return false;
+ } catch (Throwable t) {
+ throw new CacheException(t);
+ }
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>removeNode(Fqn)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ */
+ public static void remove(Cache cache, Object key) throws CacheException {
+ remove(cache, key, null);
+ }
+
+ /**
+ * Builds an {@link Fqn} from <code>region</code> and <code>key</code> and performs a JBoss Cache
+ * <code>removeNode(Fqn)</code>, wrapping any exception in a {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param key
+ * specific key to append to the <code>region</code> to form the full Fqn
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void remove(Cache cache, Object key, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().remove(key, option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any exception in a
+ * {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ */
+ public static void removeAll(Cache cache) throws CacheException {
+ try {
+ cache.clear();
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any exception in a
+ * {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void removeAll(Cache cache, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().clear(option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ /**
+ * Performs a JBoss Cache <code>removeNode(Fqn)</code>, wrapping any exception in a
+ * {@link CacheException}.
+ *
+ * @param cache
+ * the cache to invoke on
+ * @param region
+ * base Fqn for the cache region
+ * @param option
+ * invocation Option to set for this invocation. May be <code>null</code>.
+ */
+ public static void removeKey(Cache cache, Object key, Flag option) throws CacheException {
+ try {
+ cache.getAdvancedCache().remove(key, option);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+ public static void removeKey(Cache cache, Object key) throws CacheException {
+ try {
+ cache.remove(key);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+// public static void evict(Cache cache, Object key) throws CacheException {
+// try {
+// cache.evict(key);
+// } catch (Exception e) {
+// throw new CacheException(e);
+// }
+// }
+
+ public static boolean containsKey(Cache cache, Object key, Flag... flags) {
+ try {
+ return cache.getAdvancedCache().containsKey(key, flags);
+ } catch (Exception e) {
+ throw new CacheException(e);
+ }
+ }
+
+// public static Node addNode(Cache cache, Fqn fqn, boolean localOnly, boolean resident) throws CacheException {
+// try {
+// Option option = null;
+// if (localOnly) {
+// option = new Option();
+// option.setCacheModeLocal(localOnly);
+// }
+//
+// Node root = cache.getRoot();
+// setInvocationOption(cache, option);
+// // FIXME hack to work around fact that calling
+// // Node added = root.addChild( fqn ); doesn't
+// // properly set the version on the node
+// Node added = null;
+// if (version == null) {
+// added = root.addChild(fqn);
+// } else {
+// cache.put(fqn, DUMMY, DUMMY);
+// added = root.getChild(fqn);
+// }
+// if (resident)
+// added.setResident(true);
+// return added;
+// } catch (Exception e) {
+// throw new CacheException(e);
+// }
+// }
+
+ /**
+// * Assigns the given Option to the cache's {@link InvocationContext}. Does nothing if
+// * <code>option</code> is <code>null</code>.
+// *
+// * @param cache
+// * the cache. Cannot be <code>null</code>.
+// * @param option
+// * the option. May be <code>null</code>.
+// *
+// * @see {@link Cache#getInvocationContext()}
+// * @see {@link InvocationContext#setOptionOverrides(Option)}
+// */
+// public static void setInvocationOption(Cache cache, Option option) {
+// if (option != null) {
+// cache.getInvocationContext().setOptionOverrides(option);
+// }
+// }
+
+// /**
+// * Creates an {@link Option} using the given {@link DataVersion} and passes it to
+// * {@link #setInvocationOption(Cache, Option)}.
+// *
+// * @param cache
+// * the cache to set the Option on. Cannot be <code>null</code>.
+// * @param version
+// * the DataVersion to set. Cannot be <code>null</code>.
+// */
+// public static void setDataVersionOption(Cache cache, DataVersion version) {
+// Option option = new Option();
+// option.setDataVersion(version);
+// setInvocationOption(cache, option);
+// }
+}
Added: core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/infinispan/builder/infinispan-configs.xml
===================================================================
--- core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/infinispan/builder/infinispan-configs.xml (rev 0)
+++ core/trunk/cache-infinispan/src/main/resources/org/hibernate/cache/infinispan/builder/infinispan-configs.xml 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:4.0">
+ <global>
+ <transport transportClass = "org.infinispan.remoting.transport.jgroups.JGroupsTransport"
+ clusterName="infinispan-hibernate-cluster" distributedSyncTimeout="50000">
+ <!-- Note that the JGroups transport uses sensible defaults if no configuration property is defined. -->
+ <properties>
+ <!-- TODO: Change to udp.xml once streaming transfer requirement has been removed. -->
+ <property name="configurationFile" value="flush-udp.xml"/>
+ </properties>
+ <!-- See the JGroupsTransport javadocs for more flags -->
+ </transport>
+ <serialization marshallerClass="org.infinispan.marshall.VersionAwareMarshaller" version="4.0"/>
+ </global>
+
+ <default>
+ <!-- Used to register JMX statistics in any available MBean server -->
+ <jmxStatistics enabled="false"/>
+ </default>
+
+ <!-- Default configuration is appropriate for entity/collection caching. -->
+ <namedCache name="entity">
+ <clustering mode="invalidation">
+ <stateRetrieval fetchInMemoryState="false" timeout="20000"/>
+ <sync replTimeout="20000"/>
+ </clustering>
+ <!-- Note: REPEATABLE_READ is only useful if the application evicts/clears entities
+ from the Hibernate Session and then expects to repeatably re-read them in
+ the same transaction. Otherwise, the Session's internal cache provides a
+ repeatable-read semantic. Before choosing this config, carefully read the docs
+ and make sure you really need REPEATABLE_READ.
+ -->
+ <locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000"/>
+ <!-- Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds.
+ 0 means the eviction thread will never run. A separate executor is used for eviction in each cache. -->
+ <eviction wakeUpInterval="5000" maxEntries="10000" strategy="LRU"/>
+ <expiration maxIdle="100000"/>
+ <lazyDeserialization enabled="true"/>
+ </namedCache>
+
+ <!-- A config appropriate for query caching. Does not replicate queries. -->
+ <namedCache name="local-query">
+ <locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000"/>
+ <!--Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds. 0 means
+ the eviction thread will never run. A separate executor is used for eviction in each cache. -->
+ <eviction wakeUpInterval="5000" maxEntries="10000" strategy="LRU"/>
+ <expiration maxIdle="100000"/>
+ </namedCache>
+
+ <!-- A query cache that replicates queries. Replication is asynchronous. -->
+ <namedCache name="replicated-query">
+ <clustering mode="replication">
+ <stateRetrieval fetchInMemoryState="false"/>
+ <async/>
+ </clustering>
+ <locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000"/>
+ <!--Eviction configuration. WakeupInterval defines how often the eviction thread runs, in milliseconds. 0 means
+ the eviction thread will never run. A separate executor is used for eviction in each cache. -->
+ <eviction wakeUpInterval="5000" maxEntries="10000" strategy="LRU"/>
+ <expiration maxIdle="100000"/>
+ </namedCache>
+
+ <!-- Optimized for timestamp caching. A clustered timestamp cache
+ is required if query caching is used, even if the query cache
+ itself is configured with CacheMode=LOCAL. -->
+ <namedCache name="timestamps">
+ <clustering mode="replication">
+ <stateRetrieval fetchInMemoryState="true" timeout="20000"/>
+ <async/>
+ </clustering>
+ <locking isolationLevel="READ_COMMITTED" concurrencyLevel="1000" lockAcquisitionTimeout="15000"/>
+ <lazyDeserialization enabled="true"/>
+ <!-- Don't ever evict modification timestamps -->
+ <eviction wakeUpInterval="0" strategy="NONE"/>
+ </namedCache>
+
+</infinispan>
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractEntityCollectionRegionTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,128 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TransactionalDataRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+/**
+ * Base class for tests of EntityRegion and CollectionRegion implementations.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractEntityCollectionRegionTestCase extends AbstractRegionImplTestCase {
+
+ /**
+ * Create a new EntityCollectionRegionTestCaseBase.
+ *
+ * @param name
+ */
+ public AbstractEntityCollectionRegionTestCase(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a Region backed by an PESSIMISTIC locking JBoss Cache, and then
+ * ensures that it handles calls to buildAccessStrategy as expected when
+ * all the various {@link AccessType}s are passed as arguments.
+ */
+ public void testSupportedAccessTypes() throws Exception {
+ supportedAccessTypeTest();
+ }
+
+ private void supportedAccessTypeTest() throws Exception {
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
+ String entityCfg = "entity";
+ cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, entityCfg);
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ supportedAccessTypeTest(regionFactory, cfg.getProperties());
+ }
+
+ /**
+ * Creates a Region using the given factory, and then ensure that it
+ * handles calls to buildAccessStrategy as expected when all the
+ * various {@link AccessType}s are passed as arguments.
+ */
+ protected abstract void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties);
+
+ /**
+ * Test that the Region properly implements
+ * {@link TransactionalDataRegion#isTransactionAware()}.
+ *
+ * @throws Exception
+ */
+ public void testIsTransactionAware() throws Exception {
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
+// cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ assertTrue("Region is transaction-aware", region.isTransactionAware());
+
+ CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+
+ cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
+// cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+ // Make it non-transactional
+ cfg.getProperties().remove(Environment.TRANSACTION_MANAGER_STRATEGY);
+
+ regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ assertFalse("Region is not transaction-aware", region.isTransactionAware());
+
+ CacheTestUtil.stopRegionFactory(regionFactory, getCacheTestSupport());
+ }
+
+ public void testGetCacheDataDescription() throws Exception {
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, true, false);
+// cfg.setProperty(SharedCacheInstanceManager.CACHE_RESOURCE_PROP, CacheTestUtil.LOCAL_PESSIMISTIC_CACHE);
+
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ TransactionalDataRegion region = (TransactionalDataRegion) createRegion(regionFactory, "test/test", cfg.getProperties(), getCacheDataDescription());
+
+ CacheDataDescription cdd = region.getCacheDataDescription();
+
+ assertNotNull(cdd);
+
+ CacheDataDescription expected = getCacheDataDescription();
+ assertEquals(expected.isMutable(), cdd.isMutable());
+ assertEquals(expected.isVersioned(), cdd.isVersioned());
+ assertEquals(expected.getVersionComparator(), cdd.getVersionComparator());
+
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractGeneralDataRegionTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,195 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import java.util.Set;
+
+import org.hibernate.cache.GeneralDataRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.infinispan.Cache;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of QueryResultsRegion and TimestampsRegion.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractGeneralDataRegionTestCase extends AbstractRegionImplTestCase {
+ protected static final String KEY = "Key";
+
+ protected static final String VALUE1 = "value1";
+ protected static final String VALUE2 = "value2";
+
+ public AbstractGeneralDataRegionTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void putInRegion(Region region, Object key, Object value) {
+ ((GeneralDataRegion) region).put(key, value);
+ }
+
+ @Override
+ protected void removeFromRegion(Region region, Object key) {
+ ((GeneralDataRegion) region).evict(key);
+ }
+
+ /**
+ * Test method for {@link QueryResultsRegion#evict(java.lang.Object)}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * CollectionRegionAccessStrategy API.
+ */
+ public void testEvict() throws Exception {
+ evictOrRemoveTest();
+ }
+
+ private void evictOrRemoveTest() throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache localCache = getInfinispanCache(regionFactory);
+ boolean invalidation = CacheHelper.isClusteredInvalidation(localCache);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+
+ cfg = createConfiguration();
+ regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+
+ assertNull("local is clean", localRegion.get(KEY));
+ assertNull("remote is clean", remoteRegion.get(KEY));
+
+ localRegion.put(KEY, VALUE1);
+ assertEquals(VALUE1, localRegion.get(KEY));
+
+ // allow async propagation
+ sleep(250);
+ Object expected = invalidation ? null : VALUE1;
+ assertEquals(expected, remoteRegion.get(KEY));
+
+ localRegion.evict(KEY);
+
+ // allow async propagation
+ sleep(250);
+ assertEquals(null, localRegion.get(KEY));
+ assertEquals(null, remoteRegion.get(KEY));
+ }
+
+ protected abstract String getStandardRegionName(String regionPrefix);
+
+ /**
+ * Test method for {@link QueryResultsRegion#evictAll()}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * CollectionRegionAccessStrategy API.
+ */
+ public void testEvictAll() throws Exception {
+ evictOrRemoveAllTest("entity");
+ }
+
+ private void evictOrRemoveAllTest(String configName) throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache localCache = getInfinispanCache(regionFactory);
+// boolean invalidation = CacheHelper.isClusteredInvalidation(localCache);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ GeneralDataRegion localRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+
+ cfg = createConfiguration();
+ regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+ Cache remoteCache = getInfinispanCache(regionFactory);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ GeneralDataRegion remoteRegion = (GeneralDataRegion) createRegion(regionFactory,
+ getStandardRegionName(REGION_PREFIX), cfg.getProperties(), null);
+// String regionName = REGION_PREFIX;
+
+ Set children = CacheHelper.getKeySet(localCache);
+ assertEquals("No children in " + children, 0, children.size());
+
+ children = CacheHelper.getKeySet(remoteCache);
+ assertEquals("No children in " + children, 0, children.size());
+
+ assertNull("local is clean", localRegion.get(KEY));
+ assertNull("remote is clean", remoteRegion.get(KEY));
+
+ localRegion.put(KEY, VALUE1);
+ assertEquals(VALUE1, localRegion.get(KEY));
+
+ // Allow async propagation
+ sleep(250);
+
+ remoteRegion.put(KEY, VALUE1);
+ assertEquals(VALUE1, remoteRegion.get(KEY));
+
+ // Allow async propagation
+ sleep(250);
+
+ localRegion.evictAll();
+
+ // allow async propagation
+ sleep(250);
+ // This should re-establish the region root node in the optimistic case
+ assertNull(localRegion.get(KEY));
+
+ // Re-establishing the region root on the local node doesn't
+ // propagate it to other nodes. Do a get on the remote node to re-establish
+ // This only adds a node in the case of optimistic locking
+ assertEquals(null, remoteRegion.get(KEY));
+
+ assertEquals("local is clean", null, localRegion.get(KEY));
+ assertEquals("remote is clean", null, remoteRegion.get(KEY));
+ }
+
+ protected Configuration createConfiguration() {
+ Configuration cfg = CacheTestUtil.buildConfiguration("test", InfinispanRegionFactory.class, false, true);
+ return cfg;
+ }
+
+ protected void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractNonFunctionalTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,97 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.junit.UnitTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestSupport;
+import org.infinispan.Cache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base class for all non-functional tests of Infinispan integration.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractNonFunctionalTestCase extends UnitTestCase {
+
+ public static final String REGION_PREFIX = "test";
+
+ private CacheTestSupport testSupport;
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ public AbstractNonFunctionalTestCase(String name) {
+ super(name);
+ testSupport = new CacheTestSupport(log);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ testSupport.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ testSupport.tearDown();
+ }
+
+ protected void registerCache(Cache cache) {
+ testSupport.registerCache(cache);
+ }
+
+ protected void unregisterCache(Cache cache) {
+ testSupport.unregisterCache(cache);
+ }
+
+ protected void registerFactory(RegionFactory factory) {
+ testSupport.registerFactory(factory);
+ }
+
+ protected void unregisterFactory(RegionFactory factory) {
+ testSupport.unregisterFactory(factory);
+ }
+
+ protected CacheTestSupport getCacheTestSupport() {
+ return testSupport;
+ }
+
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ }
+ catch (InterruptedException e) {
+ log.warn("Interrupted during sleep", e);
+ }
+ }
+
+ protected void avoidConcurrentFlush() {
+ testSupport.avoidConcurrentFlush();
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/AbstractRegionImplTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,59 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.util.ComparableComparator;
+import org.infinispan.Cache;
+
+/**
+ * Base class for tests of Region implementations.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractRegionImplTestCase extends AbstractNonFunctionalTestCase {
+
+ public AbstractRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract Cache getInfinispanCache(InfinispanRegionFactory regionFactory);
+
+ protected abstract Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd);
+
+ protected abstract void putInRegion(Region region, Object key, Object value);
+
+ protected abstract void removeFromRegion(Region region, Object key);
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/InfinispanRegionFactoryTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,418 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.collection.CollectionRegionImpl;
+import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
+import org.hibernate.cache.infinispan.query.QueryResultsRegionImpl;
+import org.hibernate.cache.infinispan.timestamp.TimestampsRegionImpl;
+import org.infinispan.Cache;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.Configuration.CacheMode;
+import org.infinispan.eviction.EvictionStrategy;
+import org.infinispan.manager.CacheManager;
+import org.infinispan.manager.DefaultCacheManager;
+
+import junit.framework.TestCase;
+
+/**
+ * InfinispanRegionFactoryTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class InfinispanRegionFactoryTestCase extends TestCase {
+
+ public void testConfigurationProcessing() {
+ final String person = "com.acme.Person";
+ final String addresses = "com.acme.Person.addresses";
+ Properties p = new Properties();
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.cfg", "person-cache");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.strategy", "LRU");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.wake_up_interval", "2000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.max_entries", "5000 ");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.lifespan", "60000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.max_idle", "30000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.cfg", "person-addresses-cache");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.lifespan", "120000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.max_idle", "60000");
+ p.setProperty("hibernate.cache.infinispan.query.cfg", "my-query-cache");
+ p.setProperty("hibernate.cache.infinispan.query.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.query.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.query.eviction.max_entries", "10000");
+
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+
+ assertEquals("entity", factory.getTypeOverrides().get("entity").getCacheName());
+ assertEquals("entity", factory.getTypeOverrides().get("collection").getCacheName());
+ assertEquals("timestamps", factory.getTypeOverrides().get("timestamps").getCacheName());
+
+ assertEquals("person-cache", factory.getTypeOverrides().get(person).getCacheName());
+ assertEquals(EvictionStrategy.LRU, factory.getTypeOverrides().get(person).getEvictionStrategy());
+ assertEquals(2000, factory.getTypeOverrides().get(person).getEvictionWakeUpInterval());
+ assertEquals(5000, factory.getTypeOverrides().get(person).getEvictionMaxEntries());
+ assertEquals(60000, factory.getTypeOverrides().get(person).getExpirationLifespan());
+ assertEquals(30000, factory.getTypeOverrides().get(person).getExpirationMaxIdle());
+
+ assertEquals("person-addresses-cache", factory.getTypeOverrides().get(addresses).getCacheName());
+ assertEquals(120000, factory.getTypeOverrides().get(addresses).getExpirationLifespan());
+ assertEquals(60000, factory.getTypeOverrides().get(addresses).getExpirationMaxIdle());
+
+ assertEquals("my-query-cache", factory.getTypeOverrides().get("query").getCacheName());
+ assertEquals(EvictionStrategy.FIFO, factory.getTypeOverrides().get("query").getEvictionStrategy());
+ assertEquals(3000, factory.getTypeOverrides().get("query").getEvictionWakeUpInterval());
+ assertEquals(10000, factory.getTypeOverrides().get("query").getEvictionMaxEntries());
+ }
+
+ public void testBuildEntityCollectionRegionsPersonPlusEntityCollectionOverrides() {
+ final String person = "com.acme.Person";
+ final String address = "com.acme.Address";
+ final String car = "com.acme.Car";
+ final String addresses = "com.acme.Person.addresses";
+ final String parts = "com.acme.Car.parts";
+ Properties p = new Properties();
+ // First option, cache defined for entity and overrides for generic entity data type and entity itself.
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.cfg", "person-cache");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.strategy", "LRU");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.wake_up_interval", "2000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.max_entries", "5000 ");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.lifespan", "60000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.max_idle", "30000");
+ p.setProperty("hibernate.cache.infinispan.entity.cfg", "myentity-cache");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.max_entries", "20000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.cfg", "addresses-cache");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.wake_up_interval", "2500");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.max_entries", "5500 ");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.lifespan", "65000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.addresses.eviction.max_idle", "35000");
+ p.setProperty("hibernate.cache.infinispan.collection.cfg", "mycollection-cache");
+ p.setProperty("hibernate.cache.infinispan.collection.eviction.strategy", "LRU");
+ p.setProperty("hibernate.cache.infinispan.collection.eviction.wake_up_interval", "3500");
+ p.setProperty("hibernate.cache.infinispan.collection.eviction.max_entries", "25000");
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+// Configuration config = new Configuration();
+// // Set to local to avoid creating a JGroups channel
+// config.setCacheMode(CacheMode.LOCAL);
+// manager.defineConfiguration("entity", config);
+// manager.defineConfiguration("timestamps", config);
+// manager.defineConfiguration("myentity-cache", config);
+// manager.defineConfiguration("mycollection-cache", config);
+ try {
+ assertNotNull(factory.getTypeOverrides().get(person));
+ assertFalse(factory.getDefinedConfigurations().contains(person));
+ assertNotNull(factory.getTypeOverrides().get(addresses));
+ assertFalse(factory.getDefinedConfigurations().contains(addresses));
+ Cache cache = null;
+
+ EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion(person, p, null);
+ assertNotNull(factory.getTypeOverrides().get(person));
+ assertTrue(factory.getDefinedConfigurations().contains(person));
+ assertNull(factory.getTypeOverrides().get(address));
+ cache = region.getCache();
+ Configuration cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.LRU, cacheCfg.getEvictionStrategy());
+ assertEquals(2000, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(5000, cacheCfg.getEvictionMaxEntries());
+ assertEquals(60000, cacheCfg.getExpirationLifespan());
+ assertEquals(30000, cacheCfg.getExpirationMaxIdle());
+
+ region = (EntityRegionImpl) factory.buildEntityRegion(address, p, null);
+ assertNotNull(factory.getTypeOverrides().get(person));
+ assertTrue(factory.getDefinedConfigurations().contains(person));
+ assertNull(factory.getTypeOverrides().get(address));
+ cache = region.getCache();
+ cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.FIFO, cacheCfg.getEvictionStrategy());
+ assertEquals(3000, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(20000, cacheCfg.getEvictionMaxEntries());
+
+ region = (EntityRegionImpl) factory.buildEntityRegion(car, p, null);
+ assertNotNull(factory.getTypeOverrides().get(person));
+ assertTrue(factory.getDefinedConfigurations().contains(person));
+ assertNull(factory.getTypeOverrides().get(address));
+ cache = region.getCache();
+ cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.FIFO, cacheCfg.getEvictionStrategy());
+ assertEquals(3000, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(20000, cacheCfg.getEvictionMaxEntries());
+
+ CollectionRegionImpl collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(addresses, p, null);
+ assertNotNull(factory.getTypeOverrides().get(addresses));
+ assertTrue(factory.getDefinedConfigurations().contains(person));
+ assertNull(factory.getTypeOverrides().get(parts));
+ cache = collectionRegion .getCache();
+ cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.FIFO, cacheCfg.getEvictionStrategy());
+ assertEquals(2500, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(5500, cacheCfg.getEvictionMaxEntries());
+ assertEquals(65000, cacheCfg.getExpirationLifespan());
+ assertEquals(35000, cacheCfg.getExpirationMaxIdle());
+
+ collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(parts, p, null);
+ assertNotNull(factory.getTypeOverrides().get(addresses));
+ assertTrue(factory.getDefinedConfigurations().contains(addresses));
+ assertNull(factory.getTypeOverrides().get(parts));
+ cache = collectionRegion.getCache();
+ cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.LRU, cacheCfg.getEvictionStrategy());
+ assertEquals(3500, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(25000, cacheCfg.getEvictionMaxEntries());
+
+ collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion(parts, p, null);
+ assertNotNull(factory.getTypeOverrides().get(addresses));
+ assertTrue(factory.getDefinedConfigurations().contains(addresses));
+ assertNull(factory.getTypeOverrides().get(parts));
+ cache = collectionRegion.getCache();
+ cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.LRU, cacheCfg.getEvictionStrategy());
+ assertEquals(3500, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(25000, cacheCfg.getEvictionMaxEntries());
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildEntityCollectionRegionOverridesOnly() {
+ Cache cache = null;
+ Properties p = new Properties();
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.max_entries", "30000");
+ p.setProperty("hibernate.cache.infinispan.collection.eviction.strategy", "LRU");
+ p.setProperty("hibernate.cache.infinispan.collection.eviction.wake_up_interval", "3500");
+ p.setProperty("hibernate.cache.infinispan.collection.eviction.max_entries", "35000");
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion("com.acme.Address", p, null);
+ assertNull(factory.getTypeOverrides().get("com.acme.Address"));
+ cache = region.getCache();
+ Configuration cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.FIFO, cacheCfg.getEvictionStrategy());
+ assertEquals(3000, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(30000, cacheCfg.getEvictionMaxEntries());
+ assertEquals(100000, cacheCfg.getExpirationMaxIdle());
+
+ CollectionRegionImpl collectionRegion = (CollectionRegionImpl) factory.buildCollectionRegion("com.acme.Person.addresses", p, null);
+ assertNull(factory.getTypeOverrides().get("com.acme.Person.addresses"));
+ cache = collectionRegion.getCache();
+ cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.LRU, cacheCfg.getEvictionStrategy());
+ assertEquals(3500, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(35000, cacheCfg.getEvictionMaxEntries());
+ assertEquals(100000, cacheCfg.getExpirationMaxIdle());
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildEntityRegionPersonPlusEntityOverridesWithoutCfg() {
+ final String person = "com.acme.Person";
+ Properties p = new Properties();
+ // Third option, no cache defined for entity and overrides for generic entity data type and entity itself.
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.strategy", "LRU");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.lifespan", "60000");
+ p.setProperty("hibernate.cache.infinispan.com.acme.Person.eviction.max_idle", "30000");
+ p.setProperty("hibernate.cache.infinispan.entity.cfg", "myentity-cache");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.entity.eviction.max_entries", "10000");
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ assertNotNull(factory.getTypeOverrides().get(person));
+ assertFalse(factory.getDefinedConfigurations().contains(person));
+ EntityRegionImpl region = (EntityRegionImpl) factory.buildEntityRegion(person, p, null);
+ assertNotNull(factory.getTypeOverrides().get(person));
+ assertTrue(factory.getDefinedConfigurations().contains(person));
+ Cache cache = region.getCache();
+ Configuration cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.LRU, cacheCfg.getEvictionStrategy());
+ assertEquals(3000, cacheCfg.getEvictionWakeUpInterval());
+ assertEquals(10000, cacheCfg.getEvictionMaxEntries());
+ assertEquals(60000, cacheCfg.getExpirationLifespan());
+ assertEquals(30000, cacheCfg.getExpirationMaxIdle());
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testTimestampValidation() {
+ Properties p = new Properties();
+ final DefaultCacheManager manager = new DefaultCacheManager();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory() {
+ @Override
+ protected CacheManager createCacheManager(String configLoc) throws CacheException {
+ return manager;
+ }
+ };
+ Configuration config = new Configuration();
+ config.setCacheMode(CacheMode.INVALIDATION_SYNC);
+ manager.defineConfiguration("timestamps", config);
+ try {
+ factory.start(null, p);
+ fail("Should have failed saying that invalidation is not allowed for timestamp caches.");
+ } catch(CacheException ce) {
+ }
+ }
+
+ public void testBuildDefaultTimestampsRegion() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ assertTrue(factory.getDefinedConfigurations().contains("timestamps"));
+ assertTrue(factory.getTypeOverrides().get("timestamps").getCacheName().equals("timestamps"));
+ Configuration config = new Configuration();
+ config.setFetchInMemoryState(false);
+ manager.defineConfiguration("timestamps", config);
+ TimestampsRegionImpl region = (TimestampsRegionImpl) factory.buildTimestampsRegion(timestamps, p);
+ Cache cache = region.getCache();
+ Configuration cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.NONE, cacheCfg.getEvictionStrategy());
+ assertEquals(CacheMode.REPL_ASYNC, cacheCfg.getCacheMode());
+ assertTrue(cacheCfg.isUseLazyDeserialization());
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildDiffCacheNameTimestampsRegion() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "unrecommended-timestamps");
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ assertFalse(factory.getDefinedConfigurations().contains("timestamp"));
+ assertTrue(factory.getDefinedConfigurations().contains("unrecommended-timestamps"));
+ assertTrue(factory.getTypeOverrides().get("timestamps").getCacheName().equals("unrecommended-timestamps"));
+ Configuration config = new Configuration();
+ config.setFetchInMemoryState(false);
+ config.setCacheMode(CacheMode.REPL_SYNC);
+ manager.defineConfiguration("unrecommended-timestamps", config);
+ TimestampsRegionImpl region = (TimestampsRegionImpl) factory.buildTimestampsRegion(timestamps, p);
+ Cache cache = region.getCache();
+ Configuration cacheCfg = cache.getConfiguration();
+ assertEquals(EvictionStrategy.NONE, cacheCfg.getEvictionStrategy());
+ assertEquals(CacheMode.REPL_SYNC, cacheCfg.getCacheMode());
+ assertFalse(cacheCfg.isUseLazyDeserialization());
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildTimestamRegionWithCacheNameOverride() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "mytimestamps-cache");
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ factory.buildTimestampsRegion(timestamps, p);
+ assertTrue(factory.getDefinedConfigurations().contains("mytimestamps-cache"));
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildTimestamRegionWithFifoEvictionOverride() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "mytimestamps-cache");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.strategy", "FIFO");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.max_entries", "10000");
+ try {
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ factory.buildTimestampsRegion(timestamps, p);
+ assertTrue(factory.getDefinedConfigurations().contains("mytimestamps-cache"));
+ fail("Should fail cos no eviction configurations are allowed for timestamp caches");
+ } catch(CacheException ce) {
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildTimestamRegionWithNoneEvictionOverride() {
+ final String timestamps = "org.hibernate.cache.UpdateTimestampsCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ p.setProperty("hibernate.cache.infinispan.timestamps.cfg", "timestamps-none-eviction");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.strategy", "NONE");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.wake_up_interval", "3000");
+ p.setProperty("hibernate.cache.infinispan.timestamps.eviction.max_entries", "10000");
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ factory.buildTimestampsRegion(timestamps, p);
+ assertTrue(factory.getDefinedConfigurations().contains("timestamps-none-eviction"));
+ } finally {
+ factory.stop();
+ }
+ }
+
+ public void testBuildQueryRegion() {
+ final String query = "org.hibernate.cache.StandardQueryCache";
+ Properties p = new Properties();
+ InfinispanRegionFactory factory = new InfinispanRegionFactory();
+ factory.start(null, p);
+ CacheManager manager = factory.getCacheManager();
+ manager.getGlobalConfiguration().setTransportClass(null);
+ try {
+ assertTrue(factory.getDefinedConfigurations().contains("local-query"));
+ QueryResultsRegionImpl region = (QueryResultsRegionImpl) factory.buildQueryResultsRegion(query, p);
+ Cache cache = region.getCache();
+ Configuration cacheCfg = cache.getConfiguration();
+ assertEquals(CacheMode.LOCAL, cacheCfg.getCacheMode());
+ } finally {
+ factory.stop();
+ }
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractCollectionRegionAccessStrategyTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,541 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.collection;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.extensions.TestSetup;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.impl.BaseRegion;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of CollectionRegionAccessStrategy impls.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractCollectionRegionAccessStrategyTestCase extends AbstractNonFunctionalTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY_BASE = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ protected static int testCount;
+
+ protected static Configuration localCfg;
+ protected static InfinispanRegionFactory localRegionFactory;
+ protected Cache localCache;
+ protected static Configuration remoteCfg;
+ protected static InfinispanRegionFactory remoteRegionFactory;
+ protected Cache remoteCache;
+
+ protected CollectionRegion localCollectionRegion;
+ protected CollectionRegionAccessStrategy localAccessStrategy;
+
+ protected CollectionRegion remoteCollectionRegion;
+ protected CollectionRegionAccessStrategy remoteAccessStrategy;
+
+ protected boolean invalidation;
+ protected boolean synchronous;
+
+ protected Exception node1Exception;
+ protected Exception node2Exception;
+
+ protected AssertionFailedError node1Failure;
+ protected AssertionFailedError node2Failure;
+
+ public static Test getTestSetup(Class testClass, String configName) {
+ TestSuite suite = new TestSuite(testClass);
+ return new AccessStrategyTestSetup(suite, configName);
+ }
+
+ public static Test getTestSetup(Test test, String configName) {
+ return new AccessStrategyTestSetup(test, configName);
+ }
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public AbstractCollectionRegionAccessStrategyTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract AccessType getAccessType();
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ localCollectionRegion = localRegionFactory.buildCollectionRegion(REGION_NAME, localCfg.getProperties(),
+ getCacheDataDescription());
+ localCache = ((BaseRegion) localCollectionRegion).getCache();
+ localAccessStrategy = localCollectionRegion.buildAccessStrategy(getAccessType());
+ invalidation = CacheHelper.isClusteredInvalidation(localCache);
+ synchronous = CacheHelper.isSynchronous(localCache);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ remoteCollectionRegion = remoteRegionFactory.buildCollectionRegion(REGION_NAME, remoteCfg.getProperties(),
+ getCacheDataDescription());
+ remoteCache = ((BaseRegion) remoteCollectionRegion).getCache();
+ remoteAccessStrategy = remoteCollectionRegion.buildAccessStrategy(getAccessType());
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+
+ if (localCollectionRegion != null)
+ localCollectionRegion.destroy();
+ if (remoteCollectionRegion != null)
+ remoteCollectionRegion.destroy();
+
+ try {
+ localCache.getAdvancedCache().clear(Flag.CACHE_MODE_LOCAL);
+ } catch (Exception e) {
+ log.error("Problem purging local cache", e);
+ }
+
+ try {
+ remoteCache.getAdvancedCache().clear(Flag.CACHE_MODE_LOCAL);
+ } catch (Exception e) {
+ log.error("Problem purging remote cache", e);
+ }
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected static Configuration createConfiguration(String configName, String configResource) {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
+ cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, configName);
+ return cfg;
+ }
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+ protected boolean isUsingInvalidation() {
+ return invalidation;
+ }
+
+ protected boolean isSynchronous() {
+ return synchronous;
+ }
+
+ /**
+ * This is just a setup test where we assert that the cache config is as we expected.
+ */
+ public abstract void testCacheConfiguration();
+
+ /**
+ * Test method for {@link TransactionalAccess#getRegion()}.
+ */
+ public void testGetRegion() {
+ assertEquals("Correct region", localCollectionRegion, localAccessStrategy.getRegion());
+ }
+
+ /**
+ * Test method for
+ * {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}
+ * .
+ */
+ public void testPutFromLoad() throws Exception {
+ putFromLoadTest(false);
+ }
+
+ /**
+ * Test method for
+ * {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}
+ * .
+ */
+ public void testPutFromLoadMinimal() throws Exception {
+ putFromLoadTest(true);
+ }
+
+ /**
+ * Simulate 2 nodes, both start, tx do a get, experience a cache miss, then 'read from db.' First
+ * does a putFromLoad, then an evict (to represent a change). Second tries to do a putFromLoad
+ * with stale data (i.e. it took longer to read from the db). Both commit their tx. Then both
+ * start a new tx and get. First should see the updated data; second should either see the
+ * updated data (isInvalidation()( == false) or null (isInvalidation() == true).
+ *
+ * @param useMinimalAPI
+ * @throws Exception
+ */
+ private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ final CountDownLatch writeLatch1 = new CountDownLatch(1);
+ final CountDownLatch writeLatch2 = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread node1 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertEquals("node1 starts clean", null, localAccessStrategy.get(KEY, txTimestamp));
+
+ writeLatch1.await();
+
+ if (useMinimalAPI) {
+ localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2), true);
+ } else {
+ localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2));
+ }
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ // Let node2 write
+ writeLatch2.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread node2 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("node2 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
+
+ // Let node1 write
+ writeLatch1.countDown();
+ // Wait for node1 to finish
+ writeLatch2.await();
+
+ // Let the first PFER propagate
+ sleep(200);
+
+ if (useMinimalAPI) {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ } else {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+ }
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node2 caught exception", e);
+ node2Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node2Failure = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ node1.setDaemon(true);
+ node2.setDaemon(true);
+
+ node1.start();
+ node2.start();
+
+ assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
+
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+
+ // let the final PFER propagate
+ sleep(100);
+
+ long txTimestamp = System.currentTimeMillis();
+ String msg1 = "Correct node1 value";
+ String msg2 = "Correct node2 value";
+ Object expected1 = null;
+ Object expected2 = null;
+ if (isUsingInvalidation()) {
+ // PFER does not generate any invalidation, so each node should
+ // succeed. We count on database locking and Hibernate removing
+ // the collection on any update to prevent the situation we have
+ // here where the caches have inconsistent data
+ expected1 = VALUE2;
+ expected2 = VALUE1;
+ } else {
+ // the initial VALUE2 should prevent the node2 put
+ expected1 = VALUE2;
+ expected2 = VALUE2;
+ }
+
+ assertEquals(msg1, expected1, localAccessStrategy.get(KEY, txTimestamp));
+ assertEquals(msg2, expected2, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
+ */
+ public void testRemove() {
+ evictOrRemoveTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#removeAll()}.
+ */
+ public void testRemoveAll() {
+ evictOrRemoveAllTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * CollectionRegionAccessStrategy API.
+ */
+ public void testEvict() {
+ evictOrRemoveTest(true);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evictAll()}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * CollectionRegionAccessStrategy API.
+ */
+ public void testEvictAll() {
+ evictOrRemoveAllTest(true);
+ }
+
+ private void evictOrRemoveTest(boolean evict) {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ if (evict)
+ localAccessStrategy.evict(KEY);
+ else
+ localAccessStrategy.remove(KEY);
+
+ assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void evictOrRemoveAllTest(boolean evict) {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ // Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
+ //
+ // Node regionRoot = localCache.getRoot().getChild(regionFqn);
+ // assertFalse(regionRoot == null);
+ // assertEquals(0, getValidChildrenCount(regionRoot));
+ // assertTrue(regionRoot.isResident());
+ assertEquals(0, localCache.keySet().size());
+
+ // regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ // assertFalse(regionRoot == null);
+ // assertEquals(0, getValidChildrenCount(regionRoot));
+ // assertTrue(regionRoot.isResident());
+ assertEquals(0, remoteCache.keySet().size());
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ if (evict)
+ localAccessStrategy.evictAll();
+ else
+ localAccessStrategy.removeAll();
+
+ // This should re-establish the region root node
+ assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // regionRoot = localCache.getRoot().getChild(regionFqn);
+ // assertFalse(regionRoot == null);
+ // assertEquals(0, getValidChildrenCount(regionRoot));
+ // assertTrue(regionRoot.isValid());
+ // assertTrue(regionRoot.isResident());
+ assertEquals(0, localCache.keySet().size());
+
+ // Re-establishing the region root on the local node doesn't
+ // propagate it to other nodes. Do a get on the remote node to re-establish
+ assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ // assertFalse(regionRoot == null);
+ // assertTrue(regionRoot.isValid());
+ // assertTrue(regionRoot.isResident());
+ //
+ // assertEquals(0, getValidChildrenCount(regionRoot));
+ // Not invalidation, so we didn't insert a child above
+ assertEquals(0, remoteCache.keySet().size());
+
+ // Test whether the get above messes up the optimistic version
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // regionRoot = remoteCache.getRoot().getChild(regionFqn);
+ // assertFalse(regionRoot == null);
+ // assertTrue(regionRoot.isValid());
+ // assertTrue(regionRoot.isResident());
+ // // Region root should have 1 child -- the one we added above
+ // assertEquals(1, getValidChildrenCount(regionRoot));
+ // Revalidate the region root
+ assertEquals(1, remoteCache.keySet().size());
+
+ // Wait for async propagation of the putFromLoad
+ sleep(250);
+
+ assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy.get(KEY, System
+ .currentTimeMillis()));
+ assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+
+ }
+
+ private static class AccessStrategyTestSetup extends TestSetup {
+
+ private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
+
+ private final String configResource;
+ private final String configName;
+ private String preferIPv4Stack;
+
+ public AccessStrategyTestSetup(Test test, String configName) {
+ this(test, configName, null);
+ }
+
+ public AccessStrategyTestSetup(Test test, String configName, String configResource) {
+ super(test);
+ this.configName = configName;
+ this.configResource = configResource;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Try to ensure we use IPv4; otherwise cluster formation is very slow
+ preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
+ System.setProperty(PREFER_IPV4STACK, "true");
+
+ localCfg = createConfiguration(configName, configResource);
+ localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
+
+ remoteCfg = createConfiguration(configName, configResource);
+ remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ super.tearDown();
+ } finally {
+ if (preferIPv4Stack == null)
+ System.clearProperty(PREFER_IPV4STACK);
+ else
+ System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
+ }
+
+ if (localRegionFactory != null)
+ localRegionFactory.stop();
+
+ if (remoteRegionFactory != null)
+ remoteRegionFactory.stop();
+ }
+
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractReadOnlyAccessTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractReadOnlyAccessTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractReadOnlyAccessTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,44 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.collection;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ */
+public abstract class AbstractReadOnlyAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
+
+ public AbstractReadOnlyAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractTransactionalAccessTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/AbstractTransactionalAccessTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,48 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.collection;
+
+import org.hibernate.cache.access.AccessType;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ */
+public abstract class AbstractTransactionalAccessTestCase extends AbstractCollectionRegionAccessStrategyTestCase {
+
+ /**
+ * Create a new AbstractTransactionalAccessTestCase.
+ *
+ */
+ public AbstractTransactionalAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/InvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/InvalidatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/InvalidatedTransactionalTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.collection;
+
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * InvalidatedTransactionalTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class InvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ public InvalidatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = CacheTestUtil.createFailureExpectedSuite(InvalidatedTransactionalTestCase.class);
+ return getTestSetup(suite, "entity");
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyExtraAPITestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.collection;
+
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+
+/**
+ * ReadOnlyExtraAPITestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
+
+ public ReadOnlyExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ private static CollectionRegionAccessStrategy localAccessStrategy;
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+ @Override
+ protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ @Override
+ public void testLockItem() {
+ try {
+ getCollectionAccessStrategy().lockItem(KEY, new Integer(1));
+ fail("Call to lockItem did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ @Override
+ public void testLockRegion() {
+ try {
+ getCollectionAccessStrategy().lockRegion();
+ fail("Call to lockRegion did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/ReadOnlyTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.collection;
+
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when invalidation is used.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class ReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+ public ReadOnlyTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = CacheTestUtil.createFailureExpectedSuite(ReadOnlyTestCase.class);
+ return getTestSetup(suite, "entity");
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/collection/TransactionalExtraAPITestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.collection;
+
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+/**
+ * TransactionalExtraAPITestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ private static CollectionRegionAccessStrategy localAccessStrategy;
+
+ public TransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ if (getCollectionAccessStrategy() == null) {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory rf = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ CollectionRegion localCollectionRegion = rf.buildCollectionRegion(REGION_NAME, cfg.getProperties(), null);
+ setCollectionAccessStrategy(localCollectionRegion.buildAccessStrategy(getAccessType()));
+ }
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+ }
+
+ protected Configuration createConfiguration() {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
+ cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
+ return cfg;
+ }
+
+ protected String getCacheConfigName() {
+ return "entity";
+ }
+
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ protected CollectionRegionAccessStrategy getCollectionAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ protected void setCollectionAccessStrategy(CollectionRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ public void testLockItem() {
+ assertNull(getCollectionAccessStrategy().lockItem(KEY, new Integer(1)));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ public void testLockRegion() {
+ assertNull(getCollectionAccessStrategy().lockRegion());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockItem() {
+ getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockRegion() {
+ getCollectionAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ public static class MockSoftLock implements SoftLock {
+
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractEntityRegionAccessStrategyTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,743 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.entity;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.extensions.TestSetup;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.impl.CacheDataDescriptionImpl;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cache.infinispan.impl.BaseRegion;
+import org.hibernate.cache.infinispan.util.CacheHelper;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.hibernate.util.ComparableComparator;
+import org.infinispan.Cache;
+import org.infinispan.context.Flag;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of EntityRegionAccessStrategy impls.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractEntityRegionAccessStrategyTestCase extends AbstractNonFunctionalTestCase {
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY_BASE = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ protected static int testCount;
+
+ protected static Configuration localCfg;
+ protected static InfinispanRegionFactory localRegionFactory;
+ protected Cache localCache;
+ protected static Configuration remoteCfg;
+ protected static InfinispanRegionFactory remoteRegionFactory;
+ protected Cache remoteCache;
+
+ protected boolean invalidation;
+ protected boolean synchronous;
+
+ protected EntityRegion localEntityRegion;
+ protected EntityRegionAccessStrategy localAccessStrategy;
+
+ protected EntityRegion remoteEntityRegion;
+ protected EntityRegionAccessStrategy remoteAccessStrategy;
+
+ protected Exception node1Exception;
+ protected Exception node2Exception;
+
+ protected AssertionFailedError node1Failure;
+ protected AssertionFailedError node2Failure;
+
+ public static Test getTestSetup(Class testClass, String configName) {
+ TestSuite suite = new TestSuite(testClass);
+ return new AccessStrategyTestSetup(suite, configName);
+ }
+
+ public static Test getTestSetup(Test test, String configName) {
+ return new AccessStrategyTestSetup(test, configName);
+ }
+
+ /**
+ * Create a new TransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public AbstractEntityRegionAccessStrategyTestCase(String name) {
+ super(name);
+ }
+
+ protected abstract AccessType getAccessType();
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ localEntityRegion = localRegionFactory.buildEntityRegion(REGION_NAME, localCfg
+ .getProperties(), getCacheDataDescription());
+ localAccessStrategy = localEntityRegion.buildAccessStrategy(getAccessType());
+
+ localCache = ((BaseRegion) localEntityRegion).getCache();
+
+ invalidation = CacheHelper.isClusteredInvalidation(localCache);
+ synchronous = CacheHelper.isSynchronous(localCache);
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ remoteEntityRegion = remoteRegionFactory.buildEntityRegion(REGION_NAME, remoteCfg
+ .getProperties(), getCacheDataDescription());
+ remoteAccessStrategy = remoteEntityRegion.buildAccessStrategy(getAccessType());
+
+ remoteCache = ((BaseRegion) remoteEntityRegion).getCache();
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+
+ if (localEntityRegion != null)
+ localEntityRegion.destroy();
+ if (remoteEntityRegion != null)
+ remoteEntityRegion.destroy();
+
+ try {
+ localCache.getAdvancedCache().clear(Flag.CACHE_MODE_LOCAL);
+ } catch (Exception e) {
+ log.error("Problem purging local cache", e);
+ }
+
+ try {
+ remoteCache.getAdvancedCache().clear(Flag.CACHE_MODE_LOCAL);
+ } catch (Exception e) {
+ log.error("Problem purging remote cache", e);
+ }
+
+ node1Exception = null;
+ node2Exception = null;
+
+ node1Failure = null;
+ node2Failure = null;
+ }
+
+ protected static Configuration createConfiguration(String configName) {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
+ cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, configName);
+ return cfg;
+ }
+
+ protected CacheDataDescription getCacheDataDescription() {
+ return new CacheDataDescriptionImpl(true, true, ComparableComparator.INSTANCE);
+ }
+
+ protected boolean isUsingInvalidation() {
+ return invalidation;
+ }
+
+ protected boolean isSynchronous() {
+ return synchronous;
+ }
+
+ protected void assertThreadsRanCleanly() {
+ if (node1Failure != null)
+ throw node1Failure;
+ if (node2Failure != null)
+ throw node2Failure;
+
+ if (node1Exception != null) {
+ log.error("node1 saw an exception", node1Exception);
+ assertEquals("node1 saw no exceptions", null, node1Exception);
+ }
+
+ if (node2Exception != null) {
+ log.error("node2 saw an exception", node2Exception);
+ assertEquals("node2 saw no exceptions", null, node2Exception);
+ }
+ }
+
+ /**
+ * This is just a setup test where we assert that the cache config is as we expected.
+ */
+ public abstract void testCacheConfiguration();
+
+ /**
+ * Test method for {@link TransactionalAccess#getRegion()}.
+ */
+ public void testGetRegion() {
+ assertEquals("Correct region", localEntityRegion, localAccessStrategy.getRegion());
+ }
+
+ /**
+ * Test method for
+ * {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)}
+ * .
+ */
+ public void testPutFromLoad() throws Exception {
+ putFromLoadTest(false);
+ }
+
+ /**
+ * Test method for
+ * {@link TransactionalAccess#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)}
+ * .
+ */
+ public void testPutFromLoadMinimal() throws Exception {
+ putFromLoadTest(true);
+ }
+
+ /**
+ * Simulate 2 nodes, both start, tx do a get, experience a cache miss, then 'read from db.' First
+ * does a putFromLoad, then an update. Second tries to do a putFromLoad with stale data (i.e. it
+ * took longer to read from the db). Both commit their tx. Then both start a new tx and get.
+ * First should see the updated data; second should either see the updated data (isInvalidation()
+ * == false) or null (isInvalidation() == true).
+ *
+ * @param useMinimalAPI
+ * @throws Exception
+ */
+ private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ final CountDownLatch writeLatch1 = new CountDownLatch(1);
+ final CountDownLatch writeLatch2 = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread node1 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("node1 starts clean", localAccessStrategy.get(KEY, txTimestamp));
+
+ writeLatch1.await();
+
+ if (useMinimalAPI) {
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ } else {
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+ }
+
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ // Let node2 write
+ writeLatch2.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread node2 = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("node1 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));
+
+ // Let node1 write
+ writeLatch1.countDown();
+ // Wait for node1 to finish
+ writeLatch2.await();
+
+ if (useMinimalAPI) {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ } else {
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+ }
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node2 caught exception", e);
+ node2Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node2Failure = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ node1.setDaemon(true);
+ node2.setDaemon(true);
+
+ node1.start();
+ node2.start();
+
+ assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));
+
+ assertThreadsRanCleanly();
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+
+ if (isUsingInvalidation()) {
+ // no data version to prevent the PFER; we count on db locks preventing this
+ assertEquals("Expected node2 value", VALUE1, remoteAccessStrategy.get(KEY, txTimestamp));
+ } else {
+ // The node1 update is replicated, preventing the node2 PFER
+ assertEquals("Correct node2 value", VALUE2, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+ }
+
+ /**
+ * Test method for
+ * {@link TransactionalAccess#insert(java.lang.Object, java.lang.Object, java.lang.Object)}.
+ */
+ public void testInsert() throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ final CountDownLatch readLatch = new CountDownLatch(1);
+ final CountDownLatch commitLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread inserter = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertNull("Correct initial value", localAccessStrategy.get(KEY, txTimestamp));
+
+ localAccessStrategy.insert(KEY, VALUE1, new Integer(1));
+
+ readLatch.countDown();
+ commitLatch.await();
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread reader = new Thread() {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ readLatch.await();
+// Object expected = !isBlockingReads() ? null : VALUE1;
+ Object expected = null;
+
+ assertEquals("Correct initial value", expected, localAccessStrategy.get(KEY,
+ txTimestamp));
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ commitLatch.countDown();
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ inserter.setDaemon(true);
+ reader.setDaemon(true);
+ inserter.start();
+ reader.start();
+
+// if (!isBlockingReads())
+ assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+// else {
+// // Reader should be blocking for lock
+// assertFalse("Threads completed", completionLatch.await(250, TimeUnit.MILLISECONDS));
+// commitLatch.countDown();
+// assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+// }
+
+ assertThreadsRanCleanly();
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+ Object expected = isUsingInvalidation() ? null : VALUE1;
+ assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+
+ /**
+ * Test method for
+ * {@link TransactionalAccess#update(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)}
+ * .
+ */
+ public void testUpdate() throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ // Set up initial state
+ localAccessStrategy.get(KEY, System.currentTimeMillis());
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ remoteAccessStrategy.get(KEY, System.currentTimeMillis());
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+
+ // Let the async put propagate
+ sleep(250);
+
+ final CountDownLatch readLatch = new CountDownLatch(1);
+ final CountDownLatch commitLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(2);
+
+ Thread updater = new Thread("testUpdate-updater") {
+
+ public void run() {
+ boolean readerUnlocked = false;
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+ log.debug("Transaction began, get initial value");
+ assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY, txTimestamp));
+ log.debug("Now update value");
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+ log.debug("Notify the read latch");
+ readLatch.countDown();
+ readerUnlocked = true;
+ log.debug("Await commit");
+ commitLatch.await();
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ if (!readerUnlocked) readLatch.countDown();
+ log.debug("Completion latch countdown");
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread reader = new Thread("testUpdate-reader") {
+
+ public void run() {
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+ log.debug("Transaction began, await read latch");
+ readLatch.await();
+ log.debug("Read latch acquired, verify local access strategy");
+
+ // This will block w/ pessimistic locking and then
+ // read the new value; w/ optimistic it shouldn't
+ // block and will read the old value
+// Object expected = !isBlockingReads() ? VALUE1 : VALUE2;
+ Object expected = VALUE1;
+ assertEquals("Correct value", expected, localAccessStrategy.get(KEY, txTimestamp));
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ commitLatch.countDown();
+ log.debug("Completion latch countdown");
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ updater.setDaemon(true);
+ reader.setDaemon(true);
+ updater.start();
+ reader.start();
+
+// if (!isBlockingReads())
+ // Should complete promptly
+ assertTrue(completionLatch.await(2, TimeUnit.SECONDS));
+// else {
+// // Reader thread should be blocking
+// assertFalse(completionLatch.await(250, TimeUnit.MILLISECONDS));
+// // Let the writer commit down
+// commitLatch.countDown();
+// assertTrue(completionLatch.await(1, TimeUnit.SECONDS));
+// }
+
+ assertThreadsRanCleanly();
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+ Object expected = isUsingInvalidation() ? null : VALUE2;
+ assertEquals("Correct node2 value", expected, remoteAccessStrategy.get(KEY, txTimestamp));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#remove(java.lang.Object)}.
+ */
+ public void testRemove() {
+ evictOrRemoveTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#removeAll()}.
+ */
+ public void testRemoveAll() {
+ evictOrRemoveAllTest(false);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evict(java.lang.Object)}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * EntityRegionAccessStrategy API.
+ */
+ public void testEvict() {
+ evictOrRemoveTest(true);
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#evictAll()}.
+ *
+ * FIXME add testing of the "immediately without regard for transaction isolation" bit in the
+ * EntityRegionAccessStrategy API.
+ */
+ public void testEvictAll() {
+ evictOrRemoveAllTest(true);
+ }
+
+ private void evictOrRemoveTest(boolean evict) {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ if (evict)
+ localAccessStrategy.evict(KEY);
+ else
+ localAccessStrategy.remove(KEY);
+
+ assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // sleep(1000);
+
+ assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ private void evictOrRemoveAllTest(boolean evict) {
+
+ final String KEY = KEY_BASE + testCount++;
+
+// Fqn regionFqn = getRegionFqn(REGION_NAME, REGION_PREFIX);
+//
+// Node regionRoot = localCache.getRoot().getChild(regionFqn);
+// assertFalse(regionRoot == null);
+ assertEquals(0, localCache.keySet().size());
+// assertTrue(regionRoot.isResident());
+
+// regionRoot = remoteCache.getRoot().getChild(regionFqn);
+// assertFalse(regionRoot == null);
+ assertEquals(0, remoteCache.keySet().size());
+// assertTrue(regionRoot.isResident());
+
+ assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Wait for async propagation
+ sleep(250);
+
+ if (evict)
+ localAccessStrategy.evictAll();
+ else
+ localAccessStrategy.removeAll();
+
+ // This should re-establish the region root node in the optimistic case
+ assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+// regionRoot = localCache.getRoot().getChild(regionFqn);
+// assertFalse(regionRoot == null);
+// assertEquals(0, getValidChildrenCount(regionRoot));
+// assertTrue(regionRoot.isValid());
+// assertTrue(regionRoot.isResident());
+ assertEquals(0, localCache.keySet().size());
+
+ // Re-establishing the region root on the local node doesn't
+ // propagate it to other nodes. Do a get on the remote node to re-establish
+ assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+// regionRoot = remoteCache.getRoot().getChild(regionFqn);
+// assertFalse(regionRoot == null);
+// assertTrue(regionRoot.isValid());
+// assertTrue(regionRoot.isResident());
+// // Not invalidation, so we didn't insert a child above
+// assertEquals(0, getValidChildrenCount(regionRoot));
+ assertEquals(0, remoteCache.keySet().size());
+
+ // Test whether the get above messes up the optimistic version
+ remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+ assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ // Revalidate the region root
+// regionRoot = remoteCache.getRoot().getChild(regionFqn);
+// assertFalse(regionRoot == null);
+// assertTrue(regionRoot.isValid());
+// assertTrue(regionRoot.isResident());
+// // Region root should have 1 child -- the one we added above
+// assertEquals(1, getValidChildrenCount(regionRoot));
+ assertEquals(1, remoteCache.keySet().size());
+
+ // Wait for async propagation
+ sleep(250);
+
+ assertEquals("local is correct", (isUsingInvalidation() ? null : VALUE1), localAccessStrategy
+ .get(KEY, System.currentTimeMillis()));
+ assertEquals("remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System
+ .currentTimeMillis()));
+ }
+
+ protected void rollback() {
+ try {
+ BatchModeTransactionManager.getInstance().rollback();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
+ private static class AccessStrategyTestSetup extends TestSetup {
+
+ private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
+ private final String configName;
+ private String preferIPv4Stack;
+
+ public AccessStrategyTestSetup(Test test, String configName) {
+ super(test);
+ this.configName = configName;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ try {
+ super.tearDown();
+ } finally {
+ if (preferIPv4Stack == null)
+ System.clearProperty(PREFER_IPV4STACK);
+ else
+ System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
+ }
+
+ // Try to ensure we use IPv4; otherwise cluster formation is very slow
+ preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
+ System.setProperty(PREFER_IPV4STACK, "true");
+
+ localCfg = createConfiguration(configName);
+ localRegionFactory = CacheTestUtil.startRegionFactory(localCfg);
+// localCache = localRegionFactory.getCacheManager().getCache("entity");
+
+ remoteCfg = createConfiguration(configName);
+ remoteRegionFactory = CacheTestUtil.startRegionFactory(remoteCfg);
+// remoteCache = remoteRegionFactory.getCacheManager().getCache("entity");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ if (localRegionFactory != null)
+ localRegionFactory.stop();
+
+ if (remoteRegionFactory != null)
+ remoteRegionFactory.stop();
+ }
+
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractReadOnlyAccessTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractReadOnlyAccessTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractReadOnlyAccessTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,93 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.entity;
+
+import org.hibernate.cache.access.AccessType;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractReadOnlyAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
+
+ /**
+ * Create a new AbstractTransactionalAccessTestCase.
+ *
+ */
+ public AbstractReadOnlyAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+ @Override
+ public void testPutFromLoad() throws Exception {
+ putFromLoadTest(false);
+ }
+
+ @Override
+ public void testPutFromLoadMinimal() throws Exception {
+ putFromLoadTest(true);
+ }
+
+ private void putFromLoadTest(boolean minimal) throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+ assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ if (minimal)
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
+ else
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+
+ sleep(250);
+ Object expected = isUsingInvalidation() ? null : VALUE1;
+ assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+
+ BatchModeTransactionManager.getInstance().commit();
+ assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
+ assertEquals(expected, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
+ }
+
+ @Override
+ public void testUpdate() throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ try {
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+ fail("Call to update did not throw exception");
+ }
+ catch (UnsupportedOperationException good) {}
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractTransactionalAccessTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractTransactionalAccessTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/AbstractTransactionalAccessTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,132 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.entity;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.access.AccessType;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Base class for tests of TRANSACTIONAL access.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractTransactionalAccessTestCase extends AbstractEntityRegionAccessStrategyTestCase {
+
+ public AbstractTransactionalAccessTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ public void testContestedPutFromLoad() throws Exception {
+
+ final String KEY = KEY_BASE + testCount++;
+
+ localAccessStrategy.get(KEY, System.currentTimeMillis());
+ localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
+
+ final CountDownLatch pferLatch = new CountDownLatch(1);
+ final CountDownLatch pferCompletionLatch = new CountDownLatch(1);
+ final CountDownLatch commitLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+
+ Thread blocker = new Thread("Blocker") {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ assertEquals("Correct initial value", VALUE1, localAccessStrategy.get(KEY,
+ txTimestamp));
+
+ localAccessStrategy.update(KEY, VALUE2, new Integer(2), new Integer(1));
+
+ pferLatch.countDown();
+ commitLatch.await();
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ Thread putter = new Thread("Putter") {
+
+ public void run() {
+
+ try {
+ long txTimestamp = System.currentTimeMillis();
+ BatchModeTransactionManager.getInstance().begin();
+
+ localAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
+
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ log.error("node1 caught exception", e);
+ node1Exception = e;
+ rollback();
+ } catch (AssertionFailedError e) {
+ node1Failure = e;
+ rollback();
+ } finally {
+ pferCompletionLatch.countDown();
+ }
+ }
+ };
+
+ blocker.start();
+ assertTrue("Active tx has done an update", pferLatch.await(1, TimeUnit.SECONDS));
+ putter.start();
+ assertTrue("putFromLoadreturns promtly", pferCompletionLatch.await(10, TimeUnit.MILLISECONDS));
+
+ commitLatch.countDown();
+
+ assertTrue("Threads completed", completionLatch.await(1, TimeUnit.SECONDS));
+
+ assertThreadsRanCleanly();
+
+ long txTimestamp = System.currentTimeMillis();
+ assertEquals("Correct node1 value", VALUE2, localAccessStrategy.get(KEY, txTimestamp));
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/EntityRegionImplTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/EntityRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/EntityRegionImplTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,101 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.entity;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.test.cache.infinispan.AbstractEntityCollectionRegionTestCase;
+import org.infinispan.Cache;
+
+/**
+ * Tests of EntityRegionImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class EntityRegionImplTestCase extends AbstractEntityCollectionRegionTestCase {
+
+ public EntityRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected void supportedAccessTypeTest(RegionFactory regionFactory, Properties properties) {
+
+ EntityRegion region = regionFactory.buildEntityRegion("test", properties, null);
+
+ assertNull("Got TRANSACTIONAL", region.buildAccessStrategy(AccessType.TRANSACTIONAL).lockRegion());
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.READ_ONLY).lockRegion();
+ fail("Did not get READ_ONLY");
+ }
+ catch (UnsupportedOperationException good) {}
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.NONSTRICT_READ_WRITE);
+ fail("Incorrectly got NONSTRICT_READ_WRITE");
+ }
+ catch (CacheException good) {}
+
+ try
+ {
+ region.buildAccessStrategy(AccessType.READ_WRITE);
+ fail("Incorrectly got READ_WRITE");
+ }
+ catch (CacheException good) {}
+
+ }
+
+ @Override
+ protected void putInRegion(Region region, Object key, Object value) {
+ ((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).insert(key, value, new Integer(1));
+ }
+
+ @Override
+ protected void removeFromRegion(Region region, Object key) {
+ ((EntityRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL).remove(key);
+ }
+
+ @Override
+ protected Region createRegion(InfinispanRegionFactory regionFactory, String regionName,
+ Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildEntityRegion(regionName, properties, cdd);
+ }
+
+ @Override
+ protected Cache getInfinispanCache(InfinispanRegionFactory regionFactory) {
+ return regionFactory.getCacheManager().getCache("entity");
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/InvalidatedTransactionalTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/InvalidatedTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/InvalidatedTransactionalTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.entity;
+
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * InvalidatedTransactionalTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class InvalidatedTransactionalTestCase extends AbstractTransactionalAccessTestCase {
+
+ public InvalidatedTransactionalTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ assertTrue("Synchronous mode", isSynchronous());
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = CacheTestUtil.createFailureExpectedSuite(InvalidatedTransactionalTestCase.class);
+ return getTestSetup(suite, "entity");
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyExtraAPITestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyExtraAPITestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,95 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.entity;
+
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy;
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the Infinispan integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class ReadOnlyExtraAPITestCase extends TransactionalExtraAPITestCase {
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ public ReadOnlyExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected AccessType getAccessType() {
+ return AccessType.READ_ONLY;
+ }
+
+ @Override
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ @Override
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ @Override
+ public void testLockItem() {
+ try {
+ getEntityAccessStrategy().lockItem(KEY, new Integer(1));
+ fail("Call to lockItem did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ @Override
+ public void testLockRegion() {
+ try {
+ getEntityAccessStrategy().lockRegion();
+ fail("Call to lockRegion did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ @Override
+ public void testAfterUpdate() {
+ try {
+ getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock());
+ fail("Call to afterUpdate did not throw exception");
+ }
+ catch (UnsupportedOperationException expected) {}
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/ReadOnlyTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,62 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.entity;
+
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Tests READ_ONLY access when pessimistic locking and invalidation are used.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class ReadOnlyTestCase extends AbstractReadOnlyAccessTestCase {
+
+ /**
+ * Create a new PessimisticTransactionalAccessTestCase.
+ *
+ * @param name
+ */
+ public ReadOnlyTestCase(String name) {
+ super(name);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = CacheTestUtil.createFailureExpectedSuite(ReadOnlyTestCase.class);
+ return getTestSetup(suite, "entity");
+ }
+
+ // Known failures
+
+ // Overrides
+
+ @Override
+ public void testCacheConfiguration() {
+ assertTrue("Using Invalidation", isUsingInvalidation());
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/entity/TransactionalExtraAPITestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,147 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.entity;
+
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.hibernate.cache.access.SoftLock;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.AbstractNonFunctionalTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+
+/**
+ * Tests for the "extra API" in EntityRegionAccessStrategy;.
+ * <p>
+ * By "extra API" we mean those methods that are superfluous to the
+ * function of the JBC integration, where the impl is a no-op or a static
+ * false return value, UnsupportedOperationException, etc.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class TransactionalExtraAPITestCase extends AbstractNonFunctionalTestCase {
+
+ public TransactionalExtraAPITestCase(String name) {
+ super(name);
+ }
+
+ public static final String REGION_NAME = "test/com.foo.test";
+ public static final String KEY = "KEY";
+ public static final String VALUE1 = "VALUE1";
+ public static final String VALUE2 = "VALUE2";
+
+ private static EntityRegionAccessStrategy localAccessStrategy;
+
+ private static boolean optimistic;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ if (getEntityAccessStrategy() == null) {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory rf = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ EntityRegion localEntityRegion = rf.buildEntityRegion(REGION_NAME, cfg.getProperties(), null);
+ setEntityRegionAccessStrategy(localEntityRegion.buildAccessStrategy(getAccessType()));
+ }
+ }
+
+ protected void tearDown() throws Exception {
+
+ super.tearDown();
+ }
+
+ protected Configuration createConfiguration() {
+ Configuration cfg = CacheTestUtil.buildConfiguration(REGION_PREFIX, InfinispanRegionFactory.class, true, false);
+ cfg.setProperty(InfinispanRegionFactory.ENTITY_CACHE_RESOURCE_PROP, getCacheConfigName());
+ return cfg;
+ }
+
+ protected String getCacheConfigName() {
+ return "entity";
+ }
+
+ protected AccessType getAccessType() {
+ return AccessType.TRANSACTIONAL;
+ }
+
+ protected EntityRegionAccessStrategy getEntityAccessStrategy() {
+ return localAccessStrategy;
+ }
+
+ protected void setEntityRegionAccessStrategy(EntityRegionAccessStrategy strategy) {
+ localAccessStrategy = strategy;
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockItem(java.lang.Object, java.lang.Object)}.
+ */
+ public void testLockItem() {
+ assertNull(getEntityAccessStrategy().lockItem(KEY, new Integer(1)));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#lockRegion()}.
+ */
+ public void testLockRegion() {
+ assertNull(getEntityAccessStrategy().lockRegion());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockItem(java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockItem() {
+ getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#unlockRegion(org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testUnlockRegion() {
+ getEntityAccessStrategy().unlockItem(KEY, new MockSoftLock());
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)}.
+ */
+ public void testAfterInsert() {
+ assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterInsert(KEY, VALUE1, new Integer(1)));
+ }
+
+ /**
+ * Test method for {@link TransactionalAccess#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, org.hibernate.cache.access.SoftLock)}.
+ */
+ public void testAfterUpdate() {
+ assertFalse("afterInsert always returns false", getEntityAccessStrategy().afterUpdate(KEY, VALUE2, new Integer(1), new Integer(2), new MockSoftLock()));
+ }
+
+ public static class MockSoftLock implements SoftLock {
+
+ }
+
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/AbstractFunctionalTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,39 @@
+package org.hibernate.test.cache.infinispan.functional;
+
+import java.util.Map;
+
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.stat.Statistics;
+
+/**
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractFunctionalTestCase extends FunctionalTestCase {
+ private final String cacheConcurrencyStrategy;
+
+ public AbstractFunctionalTestCase(String string, String cacheConcurrencyStrategy) {
+ super(string);
+ this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
+ }
+
+ public String[] getMappings() {
+ return new String[] { "cache/infinispan/functional/Item.hbm.xml" };
+ }
+
+ @Override
+ public String getCacheConcurrencyStrategy() {
+ return cacheConcurrencyStrategy;
+ }
+
+ public void testEmptySecondLevelCacheEntry() throws Exception {
+// getSessions().evictEntity(Item.class.getName());
+ getSessions().getCache().evictEntityRegion(Item.class.getName());
+ Statistics stats = getSessions().getStatistics();
+ stats.clear();
+ SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+ Map cacheEntries = statistics.getEntries();
+ assertEquals(0, cacheEntries.size());
+ }
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicReadOnlyTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,13 @@
+package org.hibernate.test.cache.infinispan.functional;
+
+/**
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class BasicReadOnlyTestCase extends AbstractFunctionalTestCase {
+
+ public BasicReadOnlyTestCase(String string) {
+ super(string, "read-only");
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/BasicTransactionalTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,188 @@
+package org.hibernate.test.cache.infinispan.functional;
+
+import java.io.Serializable;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.cache.entry.CacheEntry;
+import org.hibernate.stat.SecondLevelCacheStatistics;
+import org.hibernate.stat.Statistics;
+
+/**
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class BasicTransactionalTestCase extends AbstractFunctionalTestCase {
+
+ public BasicTransactionalTestCase(String string) {
+ super(string, "transactional");
+ }
+
+ public void testEntityCache() {
+ Item item = new Item("chris", "Chris's Item");
+
+ Session s = openSession();
+ Statistics stats = s.getSessionFactory().getStatistics();
+ s.getTransaction().begin();
+ s.persist(item);
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ Item found = (Item) s.load(Item.class, item.getId());
+ System.out.println(stats);
+ assertEquals(item.getDescription(), found.getDescription());
+ assertEquals(0, stats.getSecondLevelCacheMissCount());
+ assertEquals(1, stats.getSecondLevelCacheHitCount());
+ s.delete(found);
+ s.close();
+ }
+
+ public void testCollectionCache() {
+ Item item = new Item("chris", "Chris's Item");
+ Item another = new Item("another", "Owned Item");
+ item.addItem(another);
+
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist(item);
+ s.persist(another);
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ Statistics stats = s.getSessionFactory().getStatistics();
+ Item loaded = (Item) s.load(Item.class, item.getId());
+ assertEquals(1, loaded.getItems().size());
+ s.close();
+
+ s = openSession();
+ SecondLevelCacheStatistics cStats = stats.getSecondLevelCacheStatistics(Item.class.getName() + ".items");
+ Item loadedWithCachedCollection = (Item) s.load(Item.class, item.getId());
+ stats.logSummary();
+ assertEquals(item.getName(), loadedWithCachedCollection.getName());
+ assertEquals(item.getItems().size(), loadedWithCachedCollection.getItems().size());
+ assertEquals(1, cStats.getHitCount());
+ s.close();
+ }
+
+ public void testStaleWritesLeaveCacheConsistent() {
+ Session s = openSession();
+ Transaction txn = s.beginTransaction();
+ VersionedItem item = new VersionedItem();
+ item.setName("steve");
+ item.setDescription("steve's item");
+ s.save(item);
+ txn.commit();
+ s.close();
+
+ Long initialVersion = item.getVersion();
+
+ // manually revert the version property
+ item.setVersion(new Long(item.getVersion().longValue() - 1));
+
+ try {
+ s = openSession();
+ txn = s.beginTransaction();
+ s.update(item);
+ txn.commit();
+ s.close();
+ fail("expected stale write to fail");
+ } catch (Throwable expected) {
+ // expected behavior here
+ if (txn != null) {
+ try {
+ txn.rollback();
+ } catch (Throwable ignore) {
+ }
+ }
+ } finally {
+ if (s != null && s.isOpen()) {
+ try {
+ s.close();
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+
+ // check the version value in the cache...
+ SecondLevelCacheStatistics slcs = sfi().getStatistics().getSecondLevelCacheStatistics(VersionedItem.class.getName());
+
+ Object entry = slcs.getEntries().get(item.getId());
+ Long cachedVersionValue;
+ cachedVersionValue = (Long) ((CacheEntry) entry).getVersion();
+ assertEquals(initialVersion.longValue(), cachedVersionValue.longValue());
+
+ // cleanup
+ s = openSession();
+ txn = s.beginTransaction();
+ item = (VersionedItem) s.load(VersionedItem.class, item.getId());
+ s.delete(item);
+ txn.commit();
+ s.close();
+ }
+
+ public void testQueryCacheInvalidation() {
+ Session s = openSession();
+ Transaction t = s.beginTransaction();
+ Item i = new Item();
+ i.setName("widget");
+ i.setDescription("A really top-quality, full-featured widget.");
+ s.persist(i);
+ t.commit();
+ s.close();
+
+ SecondLevelCacheStatistics slcs = s.getSessionFactory().getStatistics().getSecondLevelCacheStatistics(Item.class.getName());
+
+ assertEquals(slcs.getPutCount(), 1);
+ assertEquals(slcs.getElementCountInMemory(), 1);
+ assertEquals(slcs.getEntries().size(), 1);
+
+ s = openSession();
+ t = s.beginTransaction();
+ i = (Item) s.get(Item.class, i.getId());
+
+ assertEquals(slcs.getHitCount(), 1);
+ assertEquals(slcs.getMissCount(), 0);
+
+ i.setDescription("A bog standard item");
+
+ t.commit();
+ s.close();
+
+ assertEquals(slcs.getPutCount(), 2);
+
+ CacheEntry entry = (CacheEntry) slcs.getEntries().get(i.getId());
+ Serializable[] ser = entry.getDisassembledState();
+ assertTrue(ser[0].equals("widget"));
+ assertTrue(ser[1].equals("A bog standard item"));
+
+ // cleanup
+ s = openSession();
+ t = s.beginTransaction();
+ s.delete(i);
+ t.commit();
+ s.close();
+ }
+
+ public void testQueryCache() {
+ Item item = new Item("chris", "Chris's Item");
+
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist(item);
+ s.getTransaction().commit();
+ s.close();
+
+ s = openSession();
+ s.createQuery("from Item").setCacheable(true).list();
+ s.close();
+
+ s = openSession();
+ Statistics stats = s.getSessionFactory().getStatistics();
+ s.createQuery("from Item").setCacheable(true).list();
+ assertEquals(1, stats.getQueryCacheHitCount());
+ s.createQuery("delete from Item").executeUpdate();
+ s.close();
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Contact.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Contact.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Contact.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,91 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional;
+
+import java.io.Serializable;
+
+/**
+ * Entity that has a many-to-one relationship to a Customer
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class Contact implements Serializable {
+ Integer id;
+ String name;
+ String tlf;
+ Customer customer;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTlf() {
+ return tlf;
+ }
+
+ public void setTlf(String tlf) {
+ this.tlf = tlf;
+ }
+
+ public Customer getCustomer() {
+ return customer;
+ }
+
+ public void setCustomer(Customer customer) {
+ this.customer = customer;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof Contact))
+ return false;
+ Contact c = (Contact) o;
+ return c.id.equals(id) && c.name.equals(name) && c.tlf.equals(tlf);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + (id == null ? 0 : id.hashCode());
+ result = 31 * result + name.hashCode();
+ result = 31 * result + tlf.hashCode();
+ return result;
+ }
+
+}
Property changes on: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Contact.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Customer.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Customer.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Customer.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,67 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional;
+
+import java.io.Serializable;
+import java.util.Set;
+
+/**
+ * Company customer
+ *
+ * @author Emmanuel Bernard
+ * @author Kabir Khan
+ */
+public class Customer implements Serializable {
+ Integer id;
+ String name;
+
+ private transient Set<Contact> contacts;
+
+ public Customer() {
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String string) {
+ name = string;
+ }
+
+ public Set<Contact> getContacts() {
+ return contacts;
+ }
+
+ public void setContacts(Set<Contact> contacts) {
+ this.contacts = contacts;
+ }
+}
Property changes on: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Customer.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Item.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Item.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Item.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,90 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Gavin King
+ */
+public class Item {
+ private Long id;
+ private String name;
+ private String description;
+ private Item owner;
+ private Set<Item> items = new HashSet<Item>();
+
+ public Item() {}
+
+ public Item( String name, String description ) {
+ this.name = name;
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Item getOwner() {
+ return owner;
+ }
+
+ public void setOwner( Item owner ) {
+ this.owner = owner;
+ }
+
+ public Set<Item> getItems() {
+ return items;
+ }
+
+ public void setItems( Set<Item> items ) {
+ this.items = items;
+ }
+
+ public void addItem( Item item ) {
+ item.setOwner( this );
+ getItems().add( item );
+ }
+}
Property changes on: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/Item.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/VersionedItem.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/VersionedItem.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/VersionedItem.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,39 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional;
+
+/**
+ * @author Steve Ebersole
+ */
+public class VersionedItem extends Item {
+ private Long version;
+
+ public Long getVersion() {
+ return version;
+ }
+
+ public void setVersion(Long version) {
+ this.version = version;
+ }
+}
Property changes on: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/VersionedItem.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/bulk/BulkOperationsTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,321 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.bulk;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.FlushMode;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.classic.Session;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.test.cache.infinispan.functional.Contact;
+import org.hibernate.test.cache.infinispan.functional.Customer;
+import org.hibernate.transaction.CMTTransactionFactory;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * BulkOperationsTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class BulkOperationsTestCase extends FunctionalTestCase {
+
+ private static final Logger log = LoggerFactory.getLogger(BulkOperationsTestCase.class);
+
+ private TransactionManager tm;
+
+ public BulkOperationsTestCase(String string) {
+ super(string);
+ }
+
+ public String[] getMappings() {
+ return new String[] { "cache/infinispan/functional/Contact.hbm.xml", "cache/infinispan/functional/Customer.hbm.xml" };
+ }
+
+ @Override
+ public String getCacheConcurrencyStrategy() {
+ return "transactional";
+ }
+
+ protected Class getTransactionFactoryClass() {
+ return CMTTransactionFactory.class;
+ }
+
+ protected Class getConnectionProviderClass() {
+// return org.hibernate.test.tm.ConnectionProviderImpl.class;
+ return org.hibernate.test.cache.infinispan.tm.XaConnectionProvider.class;
+ }
+
+ protected Class<? extends TransactionManagerLookup> getTransactionManagerLookupClass() {
+ return org.hibernate.test.cache.infinispan.tm.XaTransactionManagerLookup.class;
+// return org.hibernate.test.tm.TransactionManagerLookupImpl.class;
+ }
+
+ public void configure(Configuration cfg) {
+ super.configure(cfg);
+
+ cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
+ cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
+ cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
+
+ Class transactionFactory = getTransactionFactoryClass();
+ cfg.setProperty( Environment.TRANSACTION_STRATEGY, transactionFactory.getName());
+ }
+
+ public void testBulkOperations() throws Throwable {
+ System.out.println("*** testBulkOperations()");
+ boolean cleanedUp = false;
+ try {
+ tm = getTransactionManagerLookupClass().newInstance().getTransactionManager(null);
+
+ createContacts();
+
+ List<Integer> rhContacts = getContactsByCustomer("Red Hat");
+ assertNotNull("Red Hat contacts exist", rhContacts);
+ assertEquals("Created expected number of Red Hat contacts", 10, rhContacts.size());
+
+ assertEquals("Deleted all Red Hat contacts", 10, deleteContacts());
+
+ List<Integer> jbContacts = getContactsByCustomer("JBoss");
+ assertNotNull("JBoss contacts exist", jbContacts);
+ assertEquals("JBoss contacts remain", 10, jbContacts.size());
+
+ for (Integer id : rhContacts) {
+ assertNull("Red Hat contact " + id + " cannot be retrieved", getContact(id));
+ }
+ rhContacts = getContactsByCustomer("Red Hat");
+ if (rhContacts != null) {
+ assertEquals("No Red Hat contacts remain", 0, rhContacts.size());
+ }
+
+ updateContacts("Kabir", "Updated");
+ for (Integer id : jbContacts) {
+ Contact contact = getContact(id);
+ assertNotNull("JBoss contact " + id + " exists", contact);
+ String expected = ("Kabir".equals(contact.getName())) ? "Updated" : "2222";
+ assertEquals("JBoss contact " + id + " has correct TLF", expected, contact.getTlf());
+ }
+
+ List<Integer> updated = getContactsByTLF("Updated");
+ assertNotNull("Got updated contacts", updated);
+ assertEquals("Updated contacts", 5, updated.size());
+ } catch(Throwable t) {
+ cleanedUp = true;
+ log.debug("Exceptional cleanup");
+ cleanup(true);
+ throw t;
+ } finally {
+ // cleanup the db so we can run this test multiple times w/o restarting the cluster
+ if (!cleanedUp) {
+ log.debug("Non exceptional cleanup");
+ cleanup(false);
+ }
+ }
+ }
+
+ public void createContacts() throws Exception {
+ log.debug("Create 10 contacts");
+ tm.begin();
+ try {
+ for (int i = 0; i < 10; i++)
+ createCustomer(i);
+ tm.commit();
+ } catch (Exception e) {
+ log.error("Unable to create customer", e);
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public int deleteContacts() throws Exception {
+ String deleteHQL = "delete Contact where customer in ";
+ deleteHQL += " (select customer FROM Customer as customer ";
+ deleteHQL += " where customer.name = :cName)";
+
+ tm.begin();
+ try {
+
+ Session session = getSessions().getCurrentSession();
+ int rowsAffected = session.createQuery(deleteHQL).setFlushMode(FlushMode.AUTO)
+ .setParameter("cName", "Red Hat").executeUpdate();
+ tm.commit();
+ return rowsAffected;
+ } catch (Exception e) {
+ try {
+ tm.rollback();
+ } catch (Exception ee) {
+ // ignored
+ }
+ throw e;
+ }
+ }
+
+ public List<Integer> getContactsByCustomer(String customerName) throws Exception {
+ String selectHQL = "select contact.id from Contact contact";
+ selectHQL += " where contact.customer.name = :cName";
+
+ log.debug("Get contacts for customer " + customerName);
+ tm.begin();
+ try {
+
+ Session session = getSessions().getCurrentSession();
+ List results = session.createQuery(selectHQL).setFlushMode(FlushMode.AUTO).setParameter("cName", customerName)
+ .list();
+ tm.commit();
+ return results;
+ } catch (Exception e) {
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public List<Integer> getContactsByTLF(String tlf) throws Exception {
+ String selectHQL = "select contact.id from Contact contact";
+ selectHQL += " where contact.tlf = :cTLF";
+
+ tm.begin();
+ try {
+
+ Session session = getSessions().getCurrentSession();
+ List results = session.createQuery(selectHQL).setFlushMode(FlushMode.AUTO).setParameter("cTLF", tlf).list();
+ tm.commit();
+ return results;
+ } catch (Exception e) {
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public int updateContacts(String name, String newTLF) throws Exception {
+ String updateHQL = "update Contact set tlf = :cNewTLF where name = :cName";
+
+ tm.begin();
+ try {
+
+ Session session = getSessions().getCurrentSession();
+ int rowsAffected = session.createQuery(updateHQL).setFlushMode(FlushMode.AUTO).setParameter("cNewTLF", newTLF)
+ .setParameter("cName", name).executeUpdate();
+ tm.commit();
+ return rowsAffected;
+ } catch (Exception e) {
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public Contact getContact(Integer id) throws Exception {
+ tm.begin();
+ try {
+
+ Session session = getSessions().getCurrentSession();
+ Contact contact = (Contact) session.get(Contact.class, id);
+ tm.commit();
+ return contact;
+ } catch (Exception e) {
+ tm.rollback();
+ throw e;
+ }
+ }
+
+// public void cleanup() throws Exception {
+// String deleteContactHQL = "delete from Contact";
+// String deleteCustomerHQL = "delete from Customer";
+// tm.begin();
+// try {
+// Session session = getSessions().getCurrentSession();
+// session.createQuery(deleteContactHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
+// session.createQuery(deleteCustomerHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
+// tm.commit();
+// } catch (Exception e) {
+// try {
+// tm.rollback();
+// } catch (Exception ee) {
+// // ignored
+// }
+// throw e;
+// }
+// }
+
+ public void cleanup(boolean ignore) throws Exception {
+ String deleteContactHQL = "delete from Contact";
+ String deleteCustomerHQL = "delete from Customer";
+ tm.begin();
+ try {
+ Session session = getSessions().getCurrentSession();
+ session.createQuery(deleteContactHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
+ session.createQuery(deleteCustomerHQL).setFlushMode(FlushMode.AUTO).executeUpdate();
+ tm.commit();
+ } catch (Exception e) {
+ if (!ignore) {
+ try {
+ tm.rollback();
+ } catch (Exception ee) {
+ // ignored
+ }
+ throw e;
+ }
+ }
+ }
+
+ private Customer createCustomer(int id) throws Exception {
+ System.out.println("CREATE CUSTOMER " + id);
+ try {
+ Customer customer = new Customer();
+ customer.setName((id % 2 == 0) ? "JBoss" : "Red Hat");
+ Set<Contact> contacts = new HashSet<Contact>();
+
+ Contact kabir = new Contact();
+ kabir.setCustomer(customer);
+ kabir.setName("Kabir");
+ kabir.setTlf("1111");
+ contacts.add(kabir);
+
+ Contact bill = new Contact();
+ bill.setCustomer(customer);
+ bill.setName("Bill");
+ bill.setTlf("2222");
+ contacts.add(bill);
+
+ customer.setContacts(contacts);
+
+ Session s = openSession();
+ s.getTransaction().begin();
+ s.persist(customer);
+ s.getTransaction().commit();
+ s.close();
+
+ return customer;
+ } finally {
+ System.out.println("CREATE CUSTOMER " + id + " - END");
+ }
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/Account.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/Account.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/Account.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,122 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.classloader;
+
+import java.io.Serializable;
+
+/**
+ * Comment
+ *
+ * @author Brian Stansberry
+ */
+public class Account implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private Integer id;
+ private AccountHolder accountHolder;
+ private Integer balance;
+ private String branch;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public AccountHolder getAccountHolder() {
+ return accountHolder;
+ }
+
+ public void setAccountHolder(AccountHolder accountHolder) {
+ this.accountHolder = accountHolder;
+ }
+
+ public Integer getBalance() {
+ return balance;
+ }
+
+ public void setBalance(Integer balance) {
+ this.balance = balance;
+ }
+
+ public String getBranch() {
+ return branch;
+ }
+
+ public void setBranch(String branch) {
+ this.branch = branch;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (!(obj instanceof Account))
+ return false;
+ Account acct = (Account) obj;
+ if (!safeEquals(id, acct.id))
+ return false;
+ if (!safeEquals(branch, acct.branch))
+ return false;
+ if (!safeEquals(balance, acct.balance))
+ return false;
+ if (!safeEquals(accountHolder, acct.accountHolder))
+ return false;
+ return true;
+ }
+
+ public int hashCode() {
+ int result = 17;
+ result = result * 31 + safeHashCode(id);
+ result = result * 31 + safeHashCode(branch);
+ result = result * 31 + safeHashCode(balance);
+ result = result * 31 + safeHashCode(accountHolder);
+ return result;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer(getClass().getName());
+ sb.append("[id=");
+ sb.append(id);
+ sb.append(",branch=");
+ sb.append(branch);
+ sb.append(",balance=");
+ sb.append(balance);
+ sb.append(",accountHolder=");
+ sb.append(accountHolder);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private static int safeHashCode(Object obj) {
+ return obj == null ? 0 : obj.hashCode();
+ }
+
+ private static boolean safeEquals(Object a, Object b) {
+ return (a == b || (a != null && a.equals(b)));
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/AccountHolder.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/AccountHolder.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/AccountHolder.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,96 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.classloader;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+/**
+ * Comment
+ *
+ * @author Brian Stansberry
+ */
+public class AccountHolder implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ private String lastName;
+ private String ssn;
+ private transient boolean deserialized;
+
+ public AccountHolder( ) {
+ this("Stansberry", "123-456-7890");
+ }
+
+ public AccountHolder(String lastName, String ssn)
+ {
+ this.lastName = lastName;
+ this.ssn = ssn;
+ }
+
+ public String getLastName( ) { return this.lastName; }
+ public void setLastName(String lastName) { this.lastName = lastName; }
+
+ public String getSsn( ) { return ssn; }
+ public void setSsn(String ssn) { this.ssn = ssn; }
+
+ public boolean equals(Object obj)
+ {
+ if (obj == this) return true;
+ if (!(obj instanceof AccountHolder)) return false;
+ AccountHolder pk = (AccountHolder)obj;
+ if (!lastName.equals(pk.lastName)) return false;
+ if (!ssn.equals(pk.ssn)) return false;
+ return true;
+ }
+
+ public int hashCode( )
+ {
+ int result = 17;
+ result = result * 31 + lastName.hashCode();
+ result = result * 31 + ssn.hashCode();
+ return result;
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer(getClass().getName());
+ sb.append("[lastName=");
+ sb.append(lastName);
+ sb.append(",ssn=");
+ sb.append(ssn);
+ sb.append(",deserialized=");
+ sb.append(deserialized);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException
+ {
+ ois.defaultReadObject();
+ deserialized = true;
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/CacheAccessListener.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/CacheAccessListener.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/CacheAccessListener.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,105 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.classloader;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
+
+@Listener
+public class CacheAccessListener {
+// HashSet<Fqn<String>> modified = new HashSet<Fqn<String>>();
+// HashSet<Fqn<String>> accessed = new HashSet<Fqn<String>>();
+ HashSet modified = new HashSet();
+ HashSet accessed = new HashSet();
+
+ public void clear() {
+ modified.clear();
+ accessed.clear();
+ }
+
+ @CacheEntryModified
+ public void nodeModified(CacheEntryModifiedEvent event) {
+ if (!event.isPre()) {
+ Object key = event.getKey();
+ System.out.println("MyListener - Modified node " + key);
+ modified.add(key);
+ }
+ }
+
+ @CacheEntryCreated
+ public void nodeCreated(CacheEntryCreatedEvent event) {
+ if (!event.isPre()) {
+ Object key = event.getKey();
+ System.out.println("MyListener - Created node " + key);
+ modified.add(key);
+ }
+ }
+
+ @CacheEntryVisited
+ public void nodeVisited(CacheEntryVisitedEvent event) {
+ if (!event.isPre()) {
+ Object key = event.getKey();
+ System.out.println("MyListener - Visited node " + key);
+ accessed.add(key);
+ }
+ }
+
+ public boolean getSawRegionModification(Object key) {
+ return getSawRegion(key, modified);
+ }
+
+ public boolean getSawRegionAccess(Object key) {
+ return getSawRegion(key, accessed);
+ }
+
+ private boolean getSawRegion(Object key, Set sawEvents) {
+ if (sawEvents.contains(key)) {
+ sawEvents.remove(key);
+ return true;
+ }
+ return false;
+// boolean saw = false;
+// for (Object key : sawEvents) {
+//
+// }
+// Fqn<String> fqn = Fqn.fromString(regionName);
+// for (Iterator<Fqn<String>> it = sawEvent.iterator(); it.hasNext();) {
+// Fqn<String> modified = (Fqn<String>) it.next();
+// if (modified.isChildOf(fqn)) {
+// it.remove();
+// saw = true;
+// }
+// }
+// return saw;
+ }
+
+}
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/ClassLoaderTestDAO.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,295 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.classloader;
+
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Comment
+ *
+ * @author Brian Stansberry
+ */
+public class ClassLoaderTestDAO {
+ private static final Logger log = LoggerFactory.getLogger(ClassLoaderTestDAO.class);
+
+ private SessionFactory sessionFactory;
+ private TransactionManager tm;
+
+ private Class acctClass;
+ private Class holderClass;
+ private Method setId;
+ private Method setBalance;
+ private Method setBranch;
+ private Method setHolder;
+ private Object smith;
+ private Object jones;
+ private Object barney;
+ private Method setName;
+ private Method setSsn;
+
+ public ClassLoaderTestDAO(SessionFactory factory, TransactionManager tm) throws Exception {
+ this.sessionFactory = factory;
+ this.tm = tm;
+
+ acctClass = Thread.currentThread().getContextClassLoader().loadClass(
+ getClass().getPackage().getName() + ".Account");
+ holderClass = Thread.currentThread().getContextClassLoader().loadClass(
+ getClass().getPackage().getName() + ".AccountHolder");
+ setId = acctClass.getMethod("setId", Integer.class);
+ setBalance = acctClass.getMethod("setBalance", Integer.class);
+ setBranch = acctClass.getMethod("setBranch", String.class);
+ setHolder = acctClass.getMethod("setAccountHolder", holderClass);
+
+ setName = holderClass.getMethod("setLastName", String.class);
+ setSsn = holderClass.getMethod("setSsn", String.class);
+
+ smith = holderClass.newInstance();
+ setName.invoke(smith, "Smith");
+ setSsn.invoke(smith, "1000");
+
+ jones = holderClass.newInstance();
+ setName.invoke(jones, "Jones");
+ setSsn.invoke(jones, "2000");
+
+ barney = holderClass.newInstance();
+ setName.invoke(barney, "Barney");
+ setSsn.invoke(barney, "3000");
+ }
+
+ public Object getSmith() {
+ return smith;
+ }
+
+ public Object getJones() {
+ return jones;
+ }
+
+ public Object getBarney() {
+ return barney;
+ }
+
+ public void updateAccountBranch(Integer id, String branch) throws Exception {
+ log.debug("Updating account " + id + " to branch " + branch);
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Object account = session.get(acctClass, id);
+ log.debug("Set branch " + branch);
+ setBranch.invoke(account, branch);
+ session.update(account);
+ tm.commit();
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+ log.debug("Updated account " + id + " to branch " + branch);
+ }
+
+ public int getCountForBranch(String branch, boolean useRegion) throws Exception {
+ tm.begin();
+ try {
+ Query query = sessionFactory.getCurrentSession().createQuery(
+ "select account from Account as account where account.branch = :branch");
+ query.setString("branch", branch);
+ if (useRegion) {
+ query.setCacheRegion("AccountRegion");
+ }
+ query.setCacheable(true);
+ int result = query.list().size();
+ tm.commit();
+ return result;
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+
+ }
+
+ public void createAccount(Object holder, Integer id, Integer openingBalance, String branch) throws Exception {
+ log.debug("Creating account " + id);
+ tm.begin();
+ try {
+ Object account = acctClass.newInstance();
+ setId.invoke(account, id);
+ setHolder.invoke(account, holder);
+ setBalance.invoke(account, openingBalance);
+ log.debug("Set branch " + branch);
+ setBranch.invoke(account, branch);
+ sessionFactory.getCurrentSession().persist(account);
+ tm.commit();
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+
+ log.debug("Created account " + id);
+ }
+
+ public Account getAccount(Integer id) throws Exception {
+ log.debug("Getting account " + id);
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Account acct = (Account) session.get(acctClass, id);
+ tm.commit();
+ return acct;
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public Account getAccountWithRefresh(Integer id) throws Exception {
+ log.debug("Getting account " + id + " with refresh");
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Account acct = (Account) session.get(acctClass, id);
+ session.refresh(acct);
+ acct = (Account) session.get(acctClass, id);
+ tm.commit();
+ return acct;
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public void updateAccountBalance(Integer id, Integer newBalance) throws Exception {
+ log.debug("Updating account " + id + " to balance " + newBalance);
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Object account = session.get(acctClass, id);
+ setBalance.invoke(account, newBalance);
+ session.update(account);
+ tm.commit();
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+ log.debug("Updated account " + id + " to balance " + newBalance);
+ }
+
+ public String getBranch(Object holder, boolean useRegion) throws Exception {
+ tm.begin();
+ try {
+ Query query = sessionFactory.getCurrentSession().createQuery(
+ "select account.branch from Account as account where account.accountHolder = ?");
+ query.setParameter(0, holder);
+ if (useRegion) {
+ query.setCacheRegion("AccountRegion");
+ }
+ query.setCacheable(true);
+ String result = (String) query.list().get(0);
+ tm.commit();
+ return result;
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+ }
+
+ public int getTotalBalance(Object holder, boolean useRegion) throws Exception {
+ List results = null;
+ tm.begin();
+ try {
+ Query query = sessionFactory.getCurrentSession().createQuery(
+ "select account.balance from Account as account where account.accountHolder = ?");
+ query.setParameter(0, holder);
+ if (useRegion) {
+ query.setCacheRegion("AccountRegion");
+ }
+ query.setCacheable(true);
+ results = query.list();
+ tm.commit();
+ } catch (Exception e) {
+ log.error("rolling back", e);
+ tm.rollback();
+ throw e;
+ }
+
+ int total = 0;
+ if (results != null) {
+ for (Iterator it = results.iterator(); it.hasNext();) {
+ total += ((Integer) it.next()).intValue();
+ System.out.println("Total = " + total);
+ }
+ }
+ return total;
+ }
+
+ public void cleanup() throws Exception {
+ internalCleanup();
+ }
+
+ private void internalCleanup() throws Exception {
+ if (sessionFactory != null) {
+ tm.begin();
+ try {
+
+ Session session = sessionFactory.getCurrentSession();
+ Query query = session.createQuery("select account from Account as account");
+ List accts = query.list();
+ if (accts != null) {
+ for (Iterator it = accts.iterator(); it.hasNext();) {
+ try {
+ Object acct = it.next();
+ log.info("Removing " + acct);
+ session.delete(acct);
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ tm.commit();
+ } catch (Exception e) {
+ tm.rollback();
+ throw e;
+ }
+ }
+ }
+
+ public void remove() {
+ try {
+ internalCleanup();
+ } catch (Exception e) {
+ log.error("Caught exception in remove", e);
+ }
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedCacheTestSetup.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedCacheTestSetup.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedCacheTestSetup.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.infinispan.functional.classloader;
+
+import org.hibernate.test.cache.infinispan.functional.cluster.ClusterAwareRegionFactory;
+import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl;
+
+import junit.framework.Test;
+
+/**
+ * A TestSetup that uses SelectedClassnameClassLoader to ensure that certain classes are not visible
+ * to JBoss Cache or JGroups' classloader.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ */
+public class IsolatedCacheTestSetup extends SelectedClassnameClassLoaderTestSetup {
+
+ private String[] isolatedClasses;
+ private String cacheConfig;
+
+ /**
+ * Create a new IsolatedCacheTestSetup.
+ */
+ public IsolatedCacheTestSetup(Test test, String[] isolatedClasses, String cacheConfig) {
+ super(test, null, null, isolatedClasses);
+ this.isolatedClasses = isolatedClasses;
+ this.cacheConfig = cacheConfig;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+// // At this point the TCCL cannot see the isolatedClasses
+// // We want the caches to use this CL as their default classloader
+
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+
+// org.jgroups.ChannelFactory cf = new org.jgroups.JChannelFactory();
+// cf.setMultiplexerConfig(DEF_JGROUPS_RESOURCE);
+//
+// // Use a CacheManager that will inject the desired defaultClassLoader into our caches
+// CustomClassLoaderCacheManager cm = new CustomClassLoaderCacheManager(DEF_CACHE_FACTORY_RESOURCE, cf, tccl);
+// cm.start();
+// TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.LOCAL, cm);
+//
+// cm.getCache(cacheConfig, true);
+//
+// // Repeat for the "remote" cache
+//
+// cf = new org.jgroups.JChannelFactory();
+// cf.setMultiplexerConfig(DEF_JGROUPS_RESOURCE);
+//
+// cm = new CustomClassLoaderCacheManager(DEF_CACHE_FACTORY_RESOURCE, cf, tccl);
+// cm.start();
+// TestCacheInstanceManager.addTestCacheManager(DualNodeTestUtil.REMOTE, cm);
+//
+// cm.getCache(cacheConfig, true);
+
+ // Now make the isolatedClasses visible to the test driver itself
+ SelectedClassnameClassLoader visible = new SelectedClassnameClassLoader(isolatedClasses, null, null, tccl);
+ Thread.currentThread().setContextClassLoader(visible);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ super.tearDown();
+ } finally {
+ ClusterAwareRegionFactory.clearCacheManagers();
+ DualNodeJtaTransactionManagerImpl.cleanupTransactions();
+ DualNodeJtaTransactionManagerImpl.cleanupTransactionManagers();
+ }
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedClassLoaderTest.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedClassLoaderTest.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/IsolatedClassLoaderTest.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,331 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.classloader;
+
+import javax.transaction.TransactionManager;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.cache.StandardQueryCache;
+import org.hibernate.test.cache.infinispan.functional.cluster.AbstractDualNodeTestCase;
+import org.hibernate.test.cache.infinispan.functional.cluster.ClusterAwareRegionFactory;
+import org.hibernate.test.cache.infinispan.functional.cluster.DualNodeJtaTransactionManagerImpl;
+import org.infinispan.Cache;
+import org.infinispan.manager.CacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tests entity and query caching when class of objects being cached are not visible to Infinispan's
+ * classloader. Also serves as a general integration test.
+ * <p/>
+ * This test stores an object (AccountHolder) that isn't visible to the Infinispan classloader in
+ * the cache in two places:
+ *
+ * 1) As part of the value tuple in an Account entity 2) As part of the FQN in a query cache entry
+ * (see query in ClassLoaderTestDAO.getBranch())
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class IsolatedClassLoaderTest extends AbstractDualNodeTestCase {
+
+ public static final String OUR_PACKAGE = IsolatedClassLoaderTest.class.getPackage().getName();
+
+ private static final String CACHE_CONFIG = "replicated-query";
+
+ protected static final long SLEEP_TIME = 300L;
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ static int test = 0;
+
+ private Cache localQueryCache ;
+ private CacheAccessListener localQueryListener;
+
+ private Cache remoteQueryCache;
+ private CacheAccessListener remoteQueryListener;
+
+ public IsolatedClassLoaderTest(String string) {
+ super(string);
+ }
+
+ public static Test suite() throws Exception {
+ TestSuite suite = new TestSuite(IsolatedClassLoaderTest.class);
+ String[] acctClasses = { OUR_PACKAGE + ".Account", OUR_PACKAGE + ".AccountHolder" };
+ return new IsolatedCacheTestSetup(suite, acctClasses, CACHE_CONFIG);
+ }
+
+ @Override
+ public String[] getMappings() {
+ return new String[] { "cache/infinispan/functional/classloader/Account.hbm.xml" };
+ }
+
+ @Override
+ protected void cleanupTransactionManagement() {
+ // Don't clean up the managers, just the transactions
+ // Managers are still needed by the long-lived caches
+ DualNodeJtaTransactionManagerImpl.cleanupTransactions();
+ }
+
+ @Override
+ protected void cleanupTest() throws Exception {
+ try {
+ if (localQueryCache != null && localQueryListener != null)
+ localQueryCache.removeListener(localQueryListener);
+ if (remoteQueryCache != null && remoteQueryListener != null)
+ remoteQueryCache.removeListener(remoteQueryListener);
+ } finally {
+ super.cleanupTest();
+ }
+ }
+
+ /**
+ * Simply confirms that the test fixture's classloader isolation setup is functioning as
+ * expected.
+ *
+ * @throws Exception
+ */
+ public void testIsolatedSetup() throws Exception {
+ // Bind a listener to the "local" cache
+ // Our region factory makes its CacheManager available to us
+ CacheManager localManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.LOCAL);
+ Cache localAccountCache = localManager.getCache(Account.class.getName());
+ Cache localAccountHolderCache = localManager.getCache(AccountHolder.class.getName());
+
+ // Bind a listener to the "remote" cache
+ CacheManager remoteManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.REMOTE);
+ Cache remoteAccountCache = remoteManager.getCache(Account.class.getName());
+ Cache remoteAccountHolderCache = remoteManager.getCache(AccountHolder.class.getName());
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ log.info("TCCL is " + cl);
+ Thread.currentThread().setContextClassLoader(cl.getParent());
+
+ // org.jboss.cache.Fqn fqn = org.jboss.cache.Fqn.fromString("/isolated1");
+ // org.jboss.cache.Region r = localCache.getRegion(fqn, true);
+ // r.registerContextClassLoader(cl.getParent());
+ // r.activate();
+ //
+ // r = remoteCache.getRegion(fqn, true);
+ // r.registerContextClassLoader(cl.getParent());
+ // r.activate();
+ // Thread.currentThread().setContextClassLoader(cl);
+ Account acct = new Account();
+ acct.setAccountHolder(new AccountHolder());
+
+ try {
+ localAccountCache.put("isolated1", acct);
+ fail("Should not have succeeded in putting acct -- classloader not isolated");
+ } catch (Exception e) {
+ log.info("Caught exception as desired", e);
+ }
+
+ // localCache.getRegion(fqn,
+ // false).registerContextClassLoader(Thread.currentThread().getContextClassLoader());
+ // remoteCache.getRegion(fqn,
+ // false).registerContextClassLoader(Thread.currentThread().getContextClassLoader());
+
+ Thread.currentThread().setContextClassLoader(cl);
+ localAccountCache.put("isolated1", acct);
+ assertEquals(acct.getClass().getName(), remoteAccountCache.get("isolated1").getClass().getName());
+ }
+
+ public void testClassLoaderHandlingNamedQueryRegion() throws Exception {
+ queryTest(true);
+ }
+
+ public void testClassLoaderHandlingStandardQueryCache() throws Exception {
+ queryTest(false);
+ }
+
+ protected void queryTest(boolean useNamedRegion) throws Exception {
+ // Bind a listener to the "local" cache
+ // Our region factory makes its CacheManager available to us
+ CacheManager localManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.LOCAL);
+ localQueryCache = localManager.getCache("local-query");
+ localQueryListener = new CacheAccessListener();
+ localQueryCache.addListener(localQueryListener);
+
+ TransactionManager localTM = DualNodeJtaTransactionManagerImpl.getInstance(AbstractDualNodeTestCase.LOCAL);
+
+ // Bind a listener to the "remote" cache
+ CacheManager remoteManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.REMOTE);
+ remoteQueryCache = remoteManager.getCache("local-query");
+ remoteQueryListener = new CacheAccessListener();
+ remoteQueryCache.addListener(remoteQueryListener);
+
+ TransactionManager remoteTM = DualNodeJtaTransactionManagerImpl.getInstance(AbstractDualNodeTestCase.REMOTE);
+
+ SessionFactory localFactory = getEnvironment().getSessionFactory();
+ SessionFactory remoteFactory = getSecondNodeEnvironment().getSessionFactory();
+
+ ClassLoaderTestDAO dao0 = new ClassLoaderTestDAO(localFactory, localTM);
+ ClassLoaderTestDAO dao1 = new ClassLoaderTestDAO(remoteFactory, remoteTM);
+
+// // Determine whether our query region is already there (in which case it
+// // will receive remote messages immediately) or is yet to be created on
+// // first use (in which case it will initially discard remote messages)
+// String regionName = createRegionName(useNamedRegion ? "AccountRegion" : StandardQueryCache.class.getName());
+// Region queryRegion = remoteCache.getRegion(Fqn.fromString(regionName), false);
+// boolean queryRegionExists = queryRegion != null && queryRegion.isActive();
+
+ // Initial ops on node 0
+ setupEntities(dao0);
+
+ // Query on post code count
+ assertEquals("63088 has correct # of accounts", 6, dao0.getCountForBranch("63088", useNamedRegion));
+
+ assertTrue("Query cache used ", localQueryListener.getSawRegionModification("???"));
+ // Clear the access state
+ localQueryListener.getSawRegionAccess("???");
+
+ log.info("First query on node0 done");
+
+ // Sleep a bit to allow async repl to happen
+ sleep(SLEEP_TIME);
+
+// // If region isn't activated yet, should not have been modified
+// if (!queryRegionExists) {
+ assertFalse("Query cache remotely modified", remoteQueryListener.getSawRegionModification("???"));
+ // Clear the access state
+ remoteQueryListener.getSawRegionAccess("???");
+// } else {
+ assertTrue("Query cache remotely modified ", remoteQueryListener.getSawRegionModification("???"));
+ // Clear the access state
+ remoteQueryListener.getSawRegionAccess("???");
+// }
+
+ // Do query again from node 1
+ assertEquals("63088 has correct # of accounts", 6, dao1.getCountForBranch("63088", useNamedRegion));
+
+// if (!queryRegionExists) {
+// // Query should have activated the region and then been inserted
+ assertTrue("Query cache modified ", remoteQueryListener.getSawRegionModification("???"));
+ // Clear the access state
+ remoteQueryListener.getSawRegionAccess("???");
+// }
+
+ log.info("First query on node 1 done");
+
+ // We now have the query cache region activated on both nodes.
+
+ // Sleep a bit to allow async repl to happen
+ sleep(SLEEP_TIME);
+
+ // Do some more queries on node 0
+
+ assertEquals("Correct branch for Smith", "94536", dao0.getBranch(dao0.getSmith(), useNamedRegion));
+
+ assertEquals("Correct high balances for Jones", 40, dao0.getTotalBalance(dao0.getJones(), useNamedRegion));
+
+ assertTrue("Query cache used ", localQueryListener.getSawRegionModification("???"));
+ // Clear the access state
+ localQueryListener.getSawRegionAccess("???");
+
+ log.info("Second set of queries on node0 done");
+
+ // Sleep a bit to allow async repl to happen
+ sleep(SLEEP_TIME);
+
+ // Check if the previous queries replicated
+ assertTrue("Query cache remotely modified ", remoteQueryListener.getSawRegionModification("???"));
+ // Clear the access state
+ remoteQueryListener.getSawRegionAccess("???");
+
+ // Do queries again from node 1
+ assertEquals("Correct branch for Smith", "94536", dao1.getBranch(dao1.getSmith(), useNamedRegion));
+
+ assertEquals("Correct high balances for Jones", 40, dao1.getTotalBalance(dao1.getJones(), useNamedRegion));
+
+ // Should be no change; query was already there
+ assertFalse("Query cache modified ", remoteQueryListener.getSawRegionModification("???"));
+ assertTrue("Query cache accessed ", remoteQueryListener.getSawRegionAccess("???"));
+
+ log.info("Second set of queries on node1 done");
+
+ // allow async to propagate
+ sleep(SLEEP_TIME);
+
+ // Modify underlying data on node 1
+ modifyEntities(dao1);
+
+ // allow async timestamp change to propagate
+ sleep(SLEEP_TIME);
+
+ // Confirm query results are correct on node 0
+
+ assertEquals("63088 has correct # of accounts", 7, dao0.getCountForBranch("63088", useNamedRegion));
+
+ assertEquals("Correct branch for Smith", "63088", dao0.getBranch(dao0.getSmith(), useNamedRegion));
+
+ assertEquals("Correct high balances for Jones", 50, dao0.getTotalBalance(dao0.getJones(), useNamedRegion));
+
+ log.info("Third set of queries on node0 done");
+ }
+
+ protected void setupEntities(ClassLoaderTestDAO dao) throws Exception {
+ dao.cleanup();
+
+ dao.createAccount(dao.getSmith(), new Integer(1001), new Integer(5), "94536");
+ dao.createAccount(dao.getSmith(), new Integer(1002), new Integer(15), "94536");
+ dao.createAccount(dao.getSmith(), new Integer(1003), new Integer(20), "94536");
+
+ dao.createAccount(dao.getJones(), new Integer(2001), new Integer(5), "63088");
+ dao.createAccount(dao.getJones(), new Integer(2002), new Integer(15), "63088");
+ dao.createAccount(dao.getJones(), new Integer(2003), new Integer(20), "63088");
+
+ dao.createAccount(dao.getBarney(), new Integer(3001), new Integer(5), "63088");
+ dao.createAccount(dao.getBarney(), new Integer(3002), new Integer(15), "63088");
+ dao.createAccount(dao.getBarney(), new Integer(3003), new Integer(20), "63088");
+
+ log.info("Standard entities created");
+ }
+
+ protected void resetRegionUsageState(CacheAccessListener localListener, CacheAccessListener remoteListener) {
+ String stdName = StandardQueryCache.class.getName();
+ String acctName = Account.class.getName();
+
+ localListener.getSawRegionModification(stdName);
+ localListener.getSawRegionModification(acctName);
+
+ localListener.getSawRegionAccess(stdName);
+ localListener.getSawRegionAccess(acctName);
+
+ remoteListener.getSawRegionModification(stdName);
+ remoteListener.getSawRegionModification(acctName);
+
+ remoteListener.getSawRegionAccess(stdName);
+ remoteListener.getSawRegionAccess(acctName);
+
+ log.info("Region usage state cleared");
+ }
+
+ protected void modifyEntities(ClassLoaderTestDAO dao) throws Exception {
+ dao.updateAccountBranch(1001, "63088");
+ dao.updateAccountBalance(2001, 15);
+
+ log.info("Entities modified");
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoader.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoader.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoader.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,288 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.classloader;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A ClassLoader that loads classes whose classname begins with one of a
+ * given set of strings, without attempting first to delegate to its
+ * parent loader.
+ * <p>
+ * This class is intended to allow emulation of 2 different types of common J2EE
+ * classloading situations.
+ * <ul>
+ * <li>Servlet-style child-first classloading, where this class is the
+ * child loader.</li>
+ * <li>Parent-first classloading where the parent does not have access to
+ * certain classes</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This class can also be configured to raise a ClassNotFoundException if
+ * asked to load certain classes, thus allowing classes on the classpath
+ * to be hidden from a test environment.
+ * </p>
+ *
+ * @author Brian Stansberry
+ */
+public class SelectedClassnameClassLoader extends ClassLoader
+{
+ private Logger log = LoggerFactory.getLogger(SelectedClassnameClassLoader.class);
+
+ private String[] includedClasses = null;
+ private String[] excludedClasses = null;
+ private String[] notFoundClasses = null;
+
+ private Map<String, Class> classes = new java.util.HashMap<String, Class>();
+
+ /**
+ * Creates a new classloader that loads the given classes.
+ *
+ * @param includedClasses array of class or package names that should be
+ * directly loaded by this loader. Classes
+ * whose name starts with any of the strings
+ * in this array will be loaded by this class,
+ * unless their name appears in
+ * <code>excludedClasses</code>.
+ * Can be <code>null</code>
+ * @param excludedClasses array of class or package names that should NOT
+ * be directly loaded by this loader. Loading of
+ * classes whose name starts with any of the
+ * strings in this array will be delegated to
+ * <code>parent</code>, even if the classes
+ * package or classname appears in
+ * <code>includedClasses</code>. Typically this
+ * parameter is used to exclude loading one or
+ * more classes in a package whose other classes
+ * are loaded by this object.
+ * @param parent ClassLoader to which loading of classes should
+ * be delegated if necessary
+ */
+ public SelectedClassnameClassLoader(String[] includedClasses,
+ String[] excludedClasses,
+ ClassLoader parent)
+ {
+ this(includedClasses, excludedClasses, null, parent);
+ }
+
+ /**
+ * Creates a new classloader that loads the given classes.
+ *
+ * @param includedClasses array of class or package names that should be
+ * directly loaded by this loader. Classes
+ * whose name starts with any of the strings
+ * in this array will be loaded by this class,
+ * unless their name appears in
+ * <code>excludedClasses</code>.
+ * Can be <code>null</code>
+ * @param excludedClasses array of class or package names that should NOT
+ * be directly loaded by this loader. Loading of
+ * classes whose name starts with any of the
+ * strings in this array will be delegated to
+ * <code>parent</code>, even if the classes
+ * package or classname appears in
+ * <code>includedClasses</code>. Typically this
+ * parameter is used to exclude loading one or
+ * more classes in a package whose other classes
+ * are loaded by this object.
+ * @param notFoundClasses array of class or package names for which this
+ * should raise a ClassNotFoundException
+ * @param parent ClassLoader to which loading of classes should
+ * be delegated if necessary
+ */
+ public SelectedClassnameClassLoader(String[] includedClasses,
+ String[] excludedClasses,
+ String[] notFoundClasses,
+ ClassLoader parent)
+ {
+ super(parent);
+ this.includedClasses = includedClasses;
+ this.excludedClasses = excludedClasses;
+ this.notFoundClasses = notFoundClasses;
+
+ log.debug("created " + this);
+ }
+
+ protected synchronized Class<?> loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ log.trace("loadClass(" + name + "," + resolve + ")");
+ if (isIncluded(name) && (isExcluded(name) == false))
+ {
+ Class c = findClass(name);
+
+ if (resolve)
+ {
+ resolveClass(c);
+ }
+ return c;
+ }
+ else if (isNotFound(name))
+ {
+ throw new ClassNotFoundException(name + " is discarded");
+ }
+ else
+ {
+ return super.loadClass(name, resolve);
+ }
+ }
+
+ protected Class<?> findClass(String name) throws ClassNotFoundException
+ {
+ log.trace("findClass(" + name + ")");
+ Class result = classes.get(name);
+ if (result != null)
+ {
+ return result;
+ }
+
+ if (isIncluded(name) && (isExcluded(name) == false))
+ {
+ result = createClass(name);
+ }
+ else if (isNotFound(name))
+ {
+ throw new ClassNotFoundException(name + " is discarded");
+ }
+ else
+ {
+ result = super.findClass(name);
+ }
+
+ classes.put(name, result);
+
+ return result;
+ }
+
+ protected Class createClass(String name) throws ClassFormatError, ClassNotFoundException
+ {
+ log.info("createClass(" + name + ")");
+ try
+ {
+ InputStream is = getResourceAsStream(name.replace('.', '/').concat(".class"));
+ byte[] bytes = new byte[1024];
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+ int read;
+ while ((read = is.read(bytes)) > -1)
+ {
+ baos.write(bytes, 0, read);
+ }
+ bytes = baos.toByteArray();
+ return this.defineClass(name, bytes, 0, bytes.length);
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new ClassNotFoundException("cannot find " + name, e);
+ }
+ catch (IOException e)
+ {
+ throw new ClassNotFoundException("cannot read " + name, e);
+ }
+ }
+
+ protected boolean isIncluded(String className)
+ {
+
+ if (includedClasses != null)
+ {
+ for (int i = 0; i < includedClasses.length; i++)
+ {
+ if (className.startsWith(includedClasses[i]))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean isExcluded(String className)
+ {
+
+ if (excludedClasses != null)
+ {
+ for (int i = 0; i < excludedClasses.length; i++)
+ {
+ if (className.startsWith(excludedClasses[i]))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean isNotFound(String className)
+ {
+
+ if (notFoundClasses != null)
+ {
+ for (int i = 0; i < notFoundClasses.length; i++)
+ {
+ if (className.startsWith(notFoundClasses[i]))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public String toString() {
+ String s = getClass().getName();
+ s += "[includedClasses=";
+ s += listClasses(includedClasses);
+ s += ";excludedClasses=";
+ s += listClasses(excludedClasses);
+ s += ";notFoundClasses=";
+ s += listClasses(notFoundClasses);
+ s += ";parent=";
+ s += getParent();
+ s += "]";
+ return s;
+ }
+
+ private static String listClasses(String[] classes) {
+ if (classes == null) return null;
+ String s = "";
+ for (int i = 0; i < classes.length; i++) {
+ if (i > 0)
+ s += ",";
+ s += classes[i];
+ }
+ return s;
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoaderTestSetup.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoaderTestSetup.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/classloader/SelectedClassnameClassLoaderTestSetup.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates. All rights reserved.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, v. 2.1. This program is distributed in the
+ * hope that it will be useful, but WITHOUT A 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, v.2.1 along with this
+ * distribution; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Red Hat Author(s): Brian Stansberry
+ */
+
+package org.hibernate.test.cache.infinispan.functional.classloader;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+
+/**
+ * A TestSetup that makes SelectedClassnameClassLoader the thread
+ * context classloader for the duration of the test.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 1 $
+ */
+public class SelectedClassnameClassLoaderTestSetup extends TestSetup
+{
+ private ClassLoader originalTCCL;
+ private String[] includedClasses;
+ private String[] excludedClasses;
+ private String[] notFoundClasses;
+
+
+ /**
+ * Create a new SelectedClassnameClassLoaderTestSetup.
+ *
+ * @param test
+ */
+ public SelectedClassnameClassLoaderTestSetup(Test test,
+ String[] includedClasses,
+ String[] excludedClasses,
+ String[] notFoundClasses)
+ {
+ super(test);
+ this.includedClasses = includedClasses;
+ this.excludedClasses = excludedClasses;
+ this.notFoundClasses = notFoundClasses;
+ }
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+
+ originalTCCL = Thread.currentThread().getContextClassLoader();
+ ClassLoader parent = originalTCCL == null ? getClass().getClassLoader() : originalTCCL;
+ ClassLoader selectedTCCL = new SelectedClassnameClassLoader(includedClasses, excludedClasses, notFoundClasses, parent);
+ Thread.currentThread().setContextClassLoader(selectedTCCL);
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ Thread.currentThread().setContextClassLoader(originalTCCL);
+ super.tearDown();
+ }
+
+
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/AbstractDualNodeTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/AbstractDualNodeTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/AbstractDualNodeTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,238 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.cluster;
+
+import org.hibernate.Session;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Mappings;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.junit.functional.ExecutionEnvironment;
+import org.hibernate.junit.functional.FunctionalTestCase;
+import org.hibernate.transaction.CMTTransactionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * AbstractDualNodeTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public abstract class AbstractDualNodeTestCase extends FunctionalTestCase {
+
+ private static final Logger log = LoggerFactory.getLogger(AbstractDualNodeTestCase.class);
+ public static final String NODE_ID_PROP = "hibernate.test.cluster.node.id";
+ public static final String LOCAL = "local";
+ public static final String REMOTE = "remote";
+ private ExecutionEnvironment secondNodeEnvironment;
+ private Session secondNodeSession;
+
+ public AbstractDualNodeTestCase(String string) {
+ super(string);
+ }
+
+ public String[] getMappings() {
+ return new String[] { "cache/infinispan/functional/Contact.hbm.xml", "cache/infinispan/functional/Customer.hbm.xml" };
+ }
+
+ @Override
+ public String getCacheConcurrencyStrategy() {
+ return "transactional";
+ }
+
+ protected Class getCacheRegionFactory() {
+ return ClusterAwareRegionFactory.class;
+ }
+
+ @Override
+ public void configure(Configuration cfg) {
+ standardConfigure(cfg);
+ configureFirstNode(cfg);
+ }
+
+ @Override
+ protected void prepareTest() throws Exception {
+ log.info("Building second node locally managed execution env");
+ secondNodeEnvironment = new ExecutionEnvironment(new SecondNodeSettings());
+ secondNodeEnvironment.initialize();
+ super.prepareTest();
+ }
+
+ @Override
+ protected void runTest() throws Throwable {
+ try {
+ super.runTest();
+ } finally {
+ if ( secondNodeSession != null && secondNodeSession.isOpen() ) {
+ if ( secondNodeSession.isConnected() ) {
+ secondNodeSession.connection().rollback();
+ }
+ secondNodeSession.close();
+ secondNodeSession = null;
+ fail( "unclosed session" );
+ } else {
+ secondNodeSession = null;
+ }
+
+ }
+ }
+
+ @Override
+ protected void cleanupTest() throws Exception {
+ try {
+ super.cleanupTest();
+
+ log.info( "Destroying second node locally managed execution env" );
+ secondNodeEnvironment.complete();
+ secondNodeEnvironment = null;
+ } finally {
+ cleanupTransactionManagement();
+ }
+ }
+
+ protected void cleanupTransactionManagement() {
+ DualNodeJtaTransactionManagerImpl.cleanupTransactions();
+ DualNodeJtaTransactionManagerImpl.cleanupTransactionManagers();
+ }
+
+ public ExecutionEnvironment getSecondNodeEnvironment() {
+ return secondNodeEnvironment;
+ }
+
+ protected Class getConnectionProviderClass() {
+ return DualNodeConnectionProviderImpl.class;
+ }
+
+ protected Class getTransactionManagerLookupClass() {
+ return DualNodeTransactionManagerLookup.class;
+ }
+
+ protected Class getTransactionFactoryClass() {
+ return CMTTransactionFactory.class;
+ }
+
+ /**
+ * Apply any node-specific configurations to our first node.
+ *
+ * @param the
+ * Configuration to update.
+ */
+ protected void configureFirstNode(Configuration cfg) {
+ cfg.setProperty(NODE_ID_PROP, LOCAL);
+ }
+
+ /**
+ * Apply any node-specific configurations to our second node.
+ *
+ * @param the
+ * Configuration to update.
+ */
+ protected void configureSecondNode(Configuration cfg) {
+ cfg.setProperty(NODE_ID_PROP, REMOTE);
+ }
+
+ protected void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ }
+ catch (InterruptedException e) {
+ log.warn("Interrupted during sleep", e);
+ }
+ }
+
+ private void standardConfigure(Configuration cfg) {
+ super.configure(cfg);
+
+ cfg.setProperty(Environment.CONNECTION_PROVIDER, getConnectionProviderClass().getName());
+ cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, getTransactionManagerLookupClass().getName());
+ cfg.setProperty(Environment.TRANSACTION_STRATEGY, getTransactionFactoryClass().getName());
+ cfg.setProperty(Environment.CACHE_REGION_FACTORY, getCacheRegionFactory().getName());
+ }
+
+ /**
+ * Settings impl that delegates most calls to the DualNodeTestCase itself, but overrides the
+ * configure method to allow separate cache settings for the second node.
+ */
+ public class SecondNodeSettings implements ExecutionEnvironment.Settings {
+ private final AbstractDualNodeTestCase delegate;
+
+ public SecondNodeSettings() {
+ this.delegate = AbstractDualNodeTestCase.this;
+ }
+
+ /**
+ * This is the important one -- we extend the delegate's work by adding second-node specific
+ * settings
+ */
+ public void configure(Configuration arg0) {
+ delegate.standardConfigure(arg0);
+ configureSecondNode(arg0);
+ }
+
+ /**
+ * Disable creating of schemas; we let the primary session factory do that to our shared
+ * database.
+ */
+ public boolean createSchema() {
+ return false;
+ }
+
+ /**
+ * Disable creating of schemas; we let the primary session factory do that to our shared
+ * database.
+ */
+ public boolean recreateSchemaAfterFailure() {
+ return false;
+ }
+
+ public void afterConfigurationBuilt(Mappings arg0, Dialect arg1) {
+ delegate.afterConfigurationBuilt(arg0, arg1);
+ }
+
+ public void afterSessionFactoryBuilt(SessionFactoryImplementor arg0) {
+ delegate.afterSessionFactoryBuilt(arg0);
+ }
+
+ public boolean appliesTo(Dialect arg0) {
+ return delegate.appliesTo(arg0);
+ }
+
+ public String getBaseForMappings() {
+ return delegate.getBaseForMappings();
+ }
+
+ public String getCacheConcurrencyStrategy() {
+ return delegate.getCacheConcurrencyStrategy();
+ }
+
+ public String[] getMappings() {
+ return delegate.getMappings();
+ }
+
+ public boolean overrideCacheStrategy() {
+ return delegate.overrideCacheStrategy();
+ }
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/ClusterAwareRegionFactory.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.cluster;
+
+import java.util.Hashtable;
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.RegionFactory;
+import org.hibernate.cache.TimestampsRegion;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Settings;
+import org.infinispan.manager.CacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ClusterAwareRegionFactory.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class ClusterAwareRegionFactory implements RegionFactory {
+
+ private static final Logger log = LoggerFactory.getLogger(ClusterAwareRegionFactory.class);
+ private static final Hashtable<String, CacheManager> cacheManagers = new Hashtable<String, CacheManager>();
+
+ private final InfinispanRegionFactory delegate = new InfinispanRegionFactory();
+ private String cacheManagerName;
+ private boolean locallyAdded;
+
+ public ClusterAwareRegionFactory(Properties props) {
+ }
+
+ public static CacheManager getCacheManager(String name) {
+ return cacheManagers.get(name);
+ }
+
+ public static void addCacheManager(String name, CacheManager manager) {
+ cacheManagers.put(name, manager);
+ }
+
+ public static void clearCacheManagers() {
+ for (CacheManager manager : cacheManagers.values()) {
+ try {
+ manager.stop();
+ } catch (Exception e) {
+ log.error("Exception cleaning up CacheManager " + manager, e);
+ }
+ }
+ cacheManagers.clear();
+ }
+
+ public void start(Settings settings, Properties properties) throws CacheException {
+ cacheManagerName = properties.getProperty(AbstractDualNodeTestCase.NODE_ID_PROP);
+
+ CacheManager existing = getCacheManager(cacheManagerName);
+ locallyAdded = (existing == null);
+
+ if (locallyAdded) {
+ delegate.start(settings, properties);
+ cacheManagers.put(cacheManagerName, delegate.getCacheManager());
+ } else {
+ delegate.setCacheManager(existing);
+ }
+ }
+
+ public void stop() {
+ if (locallyAdded) cacheManagers.remove(cacheManagerName);
+ delegate.stop();
+ }
+
+ public CollectionRegion buildCollectionRegion(String regionName, Properties properties,
+ CacheDataDescription metadata) throws CacheException {
+ return delegate.buildCollectionRegion(regionName, properties, metadata);
+ }
+
+ public EntityRegion buildEntityRegion(String regionName, Properties properties,
+ CacheDataDescription metadata) throws CacheException {
+ return delegate.buildEntityRegion(regionName, properties, metadata);
+ }
+
+ public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties)
+ throws CacheException {
+ return delegate.buildQueryResultsRegion(regionName, properties);
+ }
+
+ public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties)
+ throws CacheException {
+ return delegate.buildTimestampsRegion(regionName, properties);
+ }
+
+ public boolean isMinimalPutsEnabledByDefault() {
+ return delegate.isMinimalPutsEnabledByDefault();
+ }
+
+ public long nextTimestamp() {
+ return delegate.nextTimestamp();
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeConnectionProviderImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeConnectionProviderImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeConnectionProviderImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,85 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.cluster;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * A {@link ConnectionProvider} implementation adding JTA-style transactionality around the returned
+ * connections using the {@link DualNodeJtaTransactionManagerImpl}.
+ *
+ * @author Brian Stansberry
+ */
+public class DualNodeConnectionProviderImpl implements ConnectionProvider {
+ private static ConnectionProvider actualConnectionProvider = ConnectionProviderFactory.newConnectionProvider();
+ private String nodeId;
+ private boolean isTransactional;
+
+ public static ConnectionProvider getActualConnectionProvider() {
+ return actualConnectionProvider;
+ }
+
+ public void configure(Properties props) throws HibernateException {
+ nodeId = props.getProperty(AbstractDualNodeTestCase.NODE_ID_PROP);
+ if (nodeId == null)
+ throw new HibernateException(AbstractDualNodeTestCase.NODE_ID_PROP + " not configured");
+ }
+
+ public Connection getConnection() throws SQLException {
+ DualNodeJtaTransactionImpl currentTransaction = DualNodeJtaTransactionManagerImpl
+ .getInstance(nodeId).getCurrentTransaction();
+ if (currentTransaction == null) {
+ isTransactional = false;
+ return actualConnectionProvider.getConnection();
+ } else {
+ isTransactional = true;
+ Connection connection = currentTransaction.getEnlistedConnection();
+ if (connection == null) {
+ connection = actualConnectionProvider.getConnection();
+ currentTransaction.enlistConnection(connection);
+ }
+ return connection;
+ }
+ }
+
+ public void closeConnection(Connection conn) throws SQLException {
+ if (!isTransactional) {
+ conn.close();
+ }
+ }
+
+ public void close() throws HibernateException {
+ actualConnectionProvider.close();
+ }
+
+ public boolean supportsAggressiveRelease() {
+ return true;
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,253 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.cluster;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SimpleJtaTransactionImpl variant that works with DualNodeTransactionManagerImpl.
+ *
+ * @author Brian Stansberry
+ */
+public class DualNodeJtaTransactionImpl implements Transaction {
+ private static final Logger log = LoggerFactory.getLogger(DualNodeJtaTransactionImpl.class);
+
+ private int status;
+ private LinkedList synchronizations;
+ private Connection connection; // the only resource we care about is jdbc connection
+ private final DualNodeJtaTransactionManagerImpl jtaTransactionManager;
+ private List<XAResource> enlistedResources = new ArrayList<XAResource>();
+ private Xid xid = new DualNodeJtaTransactionXid();
+
+ public DualNodeJtaTransactionImpl(DualNodeJtaTransactionManagerImpl jtaTransactionManager) {
+ this.jtaTransactionManager = jtaTransactionManager;
+ this.status = Status.STATUS_ACTIVE;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException,
+ HeuristicRollbackException, IllegalStateException, SystemException {
+
+ if (status == Status.STATUS_MARKED_ROLLBACK) {
+ log.trace("on commit, status was marked for rollback-only");
+ rollback();
+ } else {
+ status = Status.STATUS_PREPARING;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.beforeCompletion();
+ }
+
+ if (!runXaResourcePrepare()) {
+ status = Status.STATUS_ROLLING_BACK;
+ } else {
+ status = Status.STATUS_PREPARED;
+ }
+
+ status = Status.STATUS_COMMITTING;
+
+ if (connection != null) {
+ try {
+ connection.commit();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+ }
+
+
+ runXaResourceCommitTx();
+
+ status = Status.STATUS_COMMITTED;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ jtaTransactionManager.endCurrent(this);
+ }
+ }
+
+ public void rollback() throws IllegalStateException, SystemException {
+ status = Status.STATUS_ROLLING_BACK;
+ runXaResourceRollback();
+ status = Status.STATUS_ROLLEDBACK;
+
+ if (connection != null) {
+ try {
+ connection.rollback();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+ }
+
+ if (synchronizations != null) {
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ jtaTransactionManager.endCurrent(this);
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ status = Status.STATUS_MARKED_ROLLBACK;
+ }
+
+ public void registerSynchronization(Synchronization synchronization) throws RollbackException,
+ IllegalStateException, SystemException {
+ // todo : find the spec-allowable statuses during which synch can be registered...
+ if (synchronizations == null) {
+ synchronizations = new LinkedList();
+ }
+ synchronizations.add(synchronization);
+ }
+
+ public void enlistConnection(Connection connection) {
+ if (this.connection != null) {
+ throw new IllegalStateException("Connection already registered");
+ }
+ this.connection = connection;
+ }
+
+ public Connection getEnlistedConnection() {
+ return connection;
+ }
+
+ public boolean enlistResource(XAResource xaResource) throws RollbackException,
+ IllegalStateException, SystemException {
+ enlistedResources.add(xaResource);
+ try {
+ xaResource.start(xid, 0);
+ } catch (XAException e) {
+ log.error("Got an exception", e);
+ throw new SystemException(e.getMessage());
+ }
+ return true;
+ }
+
+ public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException,
+ SystemException {
+ throw new SystemException("not supported");
+ }
+
+ public Collection<XAResource> getEnlistedResources() {
+ return enlistedResources;
+ }
+
+ private boolean runXaResourcePrepare() throws SystemException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.prepare(xid);
+ } catch (XAException e) {
+ log.trace("The resource wants to rollback!", e);
+ return false;
+ } catch (Throwable th) {
+ log.error("Unexpected error from resource manager!", th);
+ throw new SystemException(th.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private void runXaResourceRollback() {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.rollback(xid);
+ } catch (XAException e) {
+ log.warn("Error while rolling back",e);
+ }
+ }
+ }
+
+ private boolean runXaResourceCommitTx() throws HeuristicMixedException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.commit(xid, false);//todo we only support one phase commit for now, change this!!!
+ } catch (XAException e) {
+ log.warn("exception while committing",e);
+ throw new HeuristicMixedException(e.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private static class DualNodeJtaTransactionXid implements Xid {
+ private static AtomicInteger txIdCounter = new AtomicInteger(0);
+ private int id = txIdCounter.incrementAndGet();
+
+ public int getFormatId() {
+ return id;
+ }
+
+ public byte[] getGlobalTransactionId() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ public byte[] getBranchQualifier() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" +
+ "id=" + id +
+ '}';
+ }
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeJtaTransactionManagerImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,158 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.cluster;
+
+import java.util.Hashtable;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Variant of SimpleJtaTransactionManagerImpl that doesn't use a VM-singleton, but rather a set of
+ * impls keyed by a node id.
+ *
+ * @author Brian Stansberry
+ */
+public class DualNodeJtaTransactionManagerImpl implements TransactionManager {
+
+ private static final Logger log = LoggerFactory.getLogger(DualNodeJtaTransactionManagerImpl.class);
+
+ private static final Hashtable INSTANCES = new Hashtable();
+
+ private ThreadLocal currentTransaction = new ThreadLocal();
+ private String nodeId;
+
+ public synchronized static DualNodeJtaTransactionManagerImpl getInstance(String nodeId) {
+ DualNodeJtaTransactionManagerImpl tm = (DualNodeJtaTransactionManagerImpl) INSTANCES
+ .get(nodeId);
+ if (tm == null) {
+ tm = new DualNodeJtaTransactionManagerImpl(nodeId);
+ INSTANCES.put(nodeId, tm);
+ }
+ return tm;
+ }
+
+ public synchronized static void cleanupTransactions() {
+ for (java.util.Iterator it = INSTANCES.values().iterator(); it.hasNext();) {
+ TransactionManager tm = (TransactionManager) it.next();
+ try {
+ tm.suspend();
+ } catch (Exception e) {
+ log.error("Exception cleaning up TransactionManager " + tm);
+ }
+ }
+ }
+
+ public synchronized static void cleanupTransactionManagers() {
+ INSTANCES.clear();
+ }
+
+ private DualNodeJtaTransactionManagerImpl(String nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ public int getStatus() throws SystemException {
+ Transaction tx = getCurrentTransaction();
+ return tx == null ? Status.STATUS_NO_TRANSACTION : tx.getStatus();
+ }
+
+ public Transaction getTransaction() throws SystemException {
+ return (Transaction) currentTransaction.get();
+ }
+
+ public DualNodeJtaTransactionImpl getCurrentTransaction() {
+ return (DualNodeJtaTransactionImpl) currentTransaction.get();
+ }
+
+ public void begin() throws NotSupportedException, SystemException {
+ currentTransaction.set(new DualNodeJtaTransactionImpl(this));
+ }
+
+ public Transaction suspend() throws SystemException {
+ DualNodeJtaTransactionImpl suspended = getCurrentTransaction();
+ log.trace(nodeId + ": Suspending " + suspended + " for thread "
+ + Thread.currentThread().getName());
+ currentTransaction.set(null);
+ return suspended;
+ }
+
+ public void resume(Transaction transaction) throws InvalidTransactionException,
+ IllegalStateException, SystemException {
+ currentTransaction.set((DualNodeJtaTransactionImpl) transaction);
+ log.trace(nodeId + ": Resumed " + transaction + " for thread "
+ + Thread.currentThread().getName());
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException,
+ HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
+ Transaction tx = getCurrentTransaction();
+ if (tx == null) {
+ throw new IllegalStateException("no current transaction to commit");
+ }
+ tx.commit();
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException, SystemException {
+ Transaction tx = getCurrentTransaction();
+ if (tx == null) {
+ throw new IllegalStateException("no current transaction");
+ }
+ tx.rollback();
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ Transaction tx = getCurrentTransaction();
+ if (tx == null) {
+ throw new IllegalStateException("no current transaction");
+ }
+ tx.setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int i) throws SystemException {
+ }
+
+ void endCurrent(DualNodeJtaTransactionImpl transaction) {
+ if (transaction == currentTransaction.get()) {
+ currentTransaction.set(null);
+ }
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer(getClass().getName());
+ sb.append("[nodeId=");
+ sb.append(nodeId);
+ sb.append("]");
+ return sb.toString();
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTransactionManagerLookup.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/DualNodeTransactionManagerLookup.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,55 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.functional.cluster;
+
+import java.util.Properties;
+import javax.transaction.TransactionManager;
+import javax.transaction.Transaction;
+
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.hibernate.HibernateException;
+
+/**
+ * SimpleJtaTransactionManagerLookupImpl subclass that finds a different DualNodeTransactionManager
+ * based on the value of property {@link DualNodeTestUtil#NODE_ID_PROP}.
+ *
+ * @author Brian Stansberry
+ */
+public class DualNodeTransactionManagerLookup implements TransactionManagerLookup {
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ String nodeId = props.getProperty(AbstractDualNodeTestCase.NODE_ID_PROP);
+ if (nodeId == null)
+ throw new HibernateException(AbstractDualNodeTestCase.NODE_ID_PROP + " not configured");
+ return DualNodeJtaTransactionManagerImpl.getInstance(nodeId);
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException("jndi currently not implemented for these tests");
+ }
+
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/EntityCollectionInvalidationTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,387 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.cluster;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cache.CacheKey;
+import org.hibernate.test.cache.infinispan.functional.Contact;
+import org.hibernate.test.cache.infinispan.functional.Customer;
+import org.infinispan.Cache;
+import org.infinispan.manager.CacheManager;
+import org.infinispan.marshall.MarshalledValue;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
+import org.jboss.util.collection.ConcurrentSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * EntityCollectionInvalidationTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class EntityCollectionInvalidationTestCase extends AbstractDualNodeTestCase {
+ private static final Logger log = LoggerFactory.getLogger(EntityCollectionInvalidationTestCase.class);
+ private static final long SLEEP_TIME = 50l;
+ private static final Integer CUSTOMER_ID = new Integer(1);
+ static int test = 0;
+
+ public EntityCollectionInvalidationTestCase(String string) {
+ super(string);
+ }
+
+ protected String getEntityCacheConfigName() {
+ return "entity";
+ }
+
+ public void testAll() throws Exception {
+ log.info("*** testAll()");
+
+ // Bind a listener to the "local" cache
+ // Our region factory makes its CacheManager available to us
+ CacheManager localManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.LOCAL);
+ // Cache localCache = localManager.getCache("entity");
+ Cache localCustomerCache = localManager.getCache(Customer.class.getName());
+ Cache localContactCache = localManager.getCache(Contact.class.getName());
+ Cache localCollectionCache = localManager.getCache(Customer.class.getName() + ".contacts");
+ MyListener localListener = new MyListener("local");
+ localCustomerCache.addListener(localListener);
+ localContactCache.addListener(localListener);
+ localCollectionCache.addListener(localListener);
+ TransactionManager localTM = DualNodeJtaTransactionManagerImpl.getInstance(AbstractDualNodeTestCase.LOCAL);
+
+ // Bind a listener to the "remote" cache
+ CacheManager remoteManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.REMOTE);
+ Cache remoteCustomerCache = remoteManager.getCache(Customer.class.getName());
+ Cache remoteContactCache = remoteManager.getCache(Contact.class.getName());
+ Cache remoteCollectionCache = remoteManager.getCache(Customer.class.getName() + ".contacts");
+ MyListener remoteListener = new MyListener("remote");
+ remoteCustomerCache.addListener(remoteListener);
+ remoteContactCache.addListener(remoteListener);
+ remoteCollectionCache.addListener(remoteListener);
+ TransactionManager remoteTM = DualNodeJtaTransactionManagerImpl.getInstance(AbstractDualNodeTestCase.REMOTE);
+
+ SessionFactory localFactory = getEnvironment().getSessionFactory();
+ SessionFactory remoteFactory = getSecondNodeEnvironment().getSessionFactory();
+
+ try {
+ assertTrue(remoteListener.isEmpty());
+ assertTrue(localListener.isEmpty());
+
+ log.debug("Create node 0");
+ IdContainer ids = createCustomer(localFactory, localTM);
+
+ assertTrue(remoteListener.isEmpty());
+ assertTrue(localListener.isEmpty());
+
+ // Sleep a bit to let async commit propagate. Really just to
+ // help keep the logs organized for debugging any issues
+ sleep(SLEEP_TIME);
+
+ log.debug("Find node 0");
+ // This actually brings the collection into the cache
+ getCustomer(ids.customerId, localFactory, localTM);
+
+ sleep(SLEEP_TIME);
+
+ // Now the collection is in the cache so, the 2nd "get"
+ // should read everything from the cache
+ log.debug("Find(2) node 0");
+ localListener.clear();
+ getCustomer(ids.customerId, localFactory, localTM);
+
+ // Check the read came from the cache
+ log.debug("Check cache 0");
+ assertLoadedFromCache(localListener, ids.customerId, ids.contactIds);
+
+ log.debug("Find node 1");
+ // This actually brings the collection into the cache since invalidation is in use
+ getCustomer(ids.customerId, remoteFactory, remoteTM);
+
+ // Now the collection is in the cache so, the 2nd "get"
+ // should read everything from the cache
+ log.debug("Find(2) node 1");
+ remoteListener.clear();
+ getCustomer(ids.customerId, remoteFactory, remoteTM);
+
+ // Check the read came from the cache
+ log.debug("Check cache 1");
+ assertLoadedFromCache(remoteListener, ids.customerId, ids.contactIds);
+
+ // Modify customer in remote
+ remoteListener.clear();
+ ids = modifyCustomer(ids.customerId, remoteFactory, remoteTM);
+ sleep(250);
+ assertLoadedFromCache(remoteListener, ids.customerId, ids.contactIds);
+
+ // After modification, local cache should have been invalidated and hence should be empty
+ assertTrue(localCollectionCache.isEmpty());
+ assertTrue(localCustomerCache.isEmpty());
+ } catch (Exception e) {
+ log.error("Error", e);
+ throw e;
+ } finally {
+ // cleanup the db
+ log.debug("Cleaning up");
+ cleanup(localFactory, localTM);
+ }
+ }
+
+ private IdContainer createCustomer(SessionFactory sessionFactory, TransactionManager tm)
+ throws Exception {
+ log.debug("CREATE CUSTOMER");
+
+ tm.begin();
+
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Customer customer = new Customer();
+ customer.setName("JBoss");
+ Set<Contact> contacts = new HashSet<Contact>();
+
+ Contact kabir = new Contact();
+ kabir.setCustomer(customer);
+ kabir.setName("Kabir");
+ kabir.setTlf("1111");
+ contacts.add(kabir);
+
+ Contact bill = new Contact();
+ bill.setCustomer(customer);
+ bill.setName("Bill");
+ bill.setTlf("2222");
+ contacts.add(bill);
+
+ customer.setContacts(contacts);
+
+ session.save(customer);
+ tm.commit();
+
+ IdContainer ids = new IdContainer();
+ ids.customerId = customer.getId();
+ Set contactIds = new HashSet();
+ contactIds.add(kabir.getId());
+ contactIds.add(bill.getId());
+ ids.contactIds = contactIds;
+
+ return ids;
+ } catch (Exception e) {
+ log.error("Caught exception creating customer", e);
+ try {
+ tm.rollback();
+ } catch (Exception e1) {
+ log.error("Exception rolling back txn", e1);
+ }
+ throw e;
+ } finally {
+ log.debug("CREATE CUSTOMER - END");
+ }
+ }
+
+ private Customer getCustomer(Integer id, SessionFactory sessionFactory, TransactionManager tm) throws Exception {
+ log.debug("Find customer with id=" + id);
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Customer customer = doGetCustomer(id, session, tm);
+ tm.commit();
+ return customer;
+ } catch (Exception e) {
+ try {
+ tm.rollback();
+ } catch (Exception e1) {
+ log.error("Exception rolling back txn", e1);
+ }
+ throw e;
+ } finally {
+ log.debug("Find customer ended.");
+ }
+ }
+
+ private Customer doGetCustomer(Integer id, Session session, TransactionManager tm) throws Exception {
+ Customer customer = (Customer) session.get(Customer.class, id);
+ // Access all the contacts
+ for (Iterator it = customer.getContacts().iterator(); it.hasNext();) {
+ ((Contact) it.next()).getName();
+ }
+ return customer;
+ }
+
+ private IdContainer modifyCustomer(Integer id, SessionFactory sessionFactory, TransactionManager tm) throws Exception {
+ log.debug("Modify customer with id=" + id);
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ IdContainer ids = new IdContainer();
+ Set contactIds = new HashSet();
+ Customer customer = doGetCustomer(id, session, tm);
+ customer.setName("NewJBoss");
+ ids.customerId = customer.getId();
+
+// Set<Contact> contacts = customer.getContacts();
+// for (Contact c : contacts) {
+// if (c.getName().equals("Kabir")) {
+// contacts.remove(c);
+// } else {
+// contactIds.add(c.getId());
+// }
+// }
+// ids.contactIds = contactIds;
+// customer.setContacts(contacts);
+ Set<Contact> contacts = customer.getContacts();
+ for (Contact c : contacts) {
+ contactIds.add(c.getId());
+ }
+ Contact contact = contacts.iterator().next();
+ contacts.remove(contact);
+ contactIds.remove(contact.getId());
+ ids.contactIds = contactIds;
+ contact.setCustomer(null);
+
+ session.save(customer);
+ tm.commit();
+ return ids;
+ } catch (Exception e) {
+ try {
+ tm.rollback();
+ } catch (Exception e1) {
+ log.error("Exception rolling back txn", e1);
+ }
+ throw e;
+ } finally {
+ log.debug("Find customer ended.");
+ }
+ }
+
+ private void cleanup(SessionFactory sessionFactory, TransactionManager tm) throws Exception {
+ tm.begin();
+ try {
+ Session session = sessionFactory.getCurrentSession();
+ Customer c = (Customer) session.get(Customer.class, CUSTOMER_ID);
+ if (c != null) {
+ Set contacts = c.getContacts();
+ for (Iterator it = contacts.iterator(); it.hasNext();)
+ session.delete(it.next());
+ c.setContacts(null);
+ session.delete(c);
+ }
+
+ tm.commit();
+ } catch (Exception e) {
+ try {
+ tm.rollback();
+ } catch (Exception e1) {
+ log.error("Exception rolling back txn", e1);
+ }
+ log.error("Caught exception in cleanup", e);
+ }
+ }
+
+ private void assertLoadedFromCache(MyListener listener, Integer custId, Set contactIds) {
+ assertTrue("Customer#" + custId + " was in cache", listener.visited.contains("Customer#"
+ + custId));
+ for (Iterator it = contactIds.iterator(); it.hasNext();) {
+ Integer contactId = (Integer) it.next();
+ assertTrue("Contact#" + contactId + " was in cache", listener.visited.contains("Contact#"
+ + contactId));
+ assertTrue("Contact#" + contactId + " was in cache", listener.visited.contains("Contact#"
+ + contactId));
+ }
+ assertTrue("Customer.contacts" + custId + " was in cache", listener.visited
+ .contains("Customer.contacts#" + custId));
+ }
+
+ @Listener
+ public static class MyListener {
+ private static final Logger log = LoggerFactory.getLogger(MyListener.class);
+ private Set<String> visited = new ConcurrentSet<String>();
+ private final String name;
+
+ public MyListener(String name) {
+ this.name = name;
+ }
+
+ public void clear() {
+ visited.clear();
+ }
+
+ public boolean isEmpty() {
+ return visited.isEmpty();
+ }
+
+ @CacheEntryVisited
+ public void nodeVisited(CacheEntryVisitedEvent event) {
+ log.debug(event.toString());
+ if (!event.isPre()) {
+ MarshalledValue mv = (MarshalledValue) event.getKey();
+ CacheKey cacheKey = (CacheKey) mv.get();
+ Integer primKey = (Integer) cacheKey.getKey();
+ String key = (String) cacheKey.getEntityOrRoleName() + '#' + primKey;
+ log.debug("MyListener[" + name +"] - Visiting key " + key);
+ // String name = fqn.toString();
+ String token = ".functional.";
+ int index = key.indexOf(token);
+ if (index > -1) {
+ index += token.length();
+ key = key.substring(index);
+ log.debug("MyListener[" + name +"] - recording visit to " + key);
+ visited.add(key);
+ }
+ }
+ }
+
+// @CacheEntryModified
+// public void nodeModified(CacheEntryModifiedEvent event) {
+// log.debug(event.toString());
+// if (!event.isPre()) {
+// MarshalledValue mv = (MarshalledValue) event.getKey();
+// CacheKey cacheKey = (CacheKey) mv.get();
+// Integer primKey = (Integer) cacheKey.getKey();
+// String key = (String) cacheKey.getEntityOrRoleName() + '#' + primKey;
+// log.debug("MyListener[" + name +"] - Modified key " + key);
+// // String name = fqn.toString();
+// String token = ".functional.";
+// int index = key.indexOf(token);
+// if (index > -1) {
+// index += token.length();
+// key = key.substring(index);
+// log.debug("MyListener[" + name +"] - recording modification of " + key);
+// visited.add(key);
+// }
+// }
+// }
+ }
+
+ private class IdContainer {
+ Integer customerId;
+ Set<Integer> contactIds;
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/SessionRefreshTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/SessionRefreshTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/functional/cluster/SessionRefreshTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,131 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.functional.cluster;
+
+import javax.transaction.TransactionManager;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.test.cache.infinispan.functional.classloader.Account;
+import org.hibernate.test.cache.infinispan.functional.classloader.ClassLoaderTestDAO;
+import org.infinispan.Cache;
+import org.infinispan.manager.CacheManager;
+import org.infinispan.test.TestingUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * SessionRefreshTestCase.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class SessionRefreshTestCase extends AbstractDualNodeTestCase {
+
+ public static final String OUR_PACKAGE = SessionRefreshTestCase.class.getPackage().getName();
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ static int test = 0;
+
+ private Cache localCache;
+
+ public SessionRefreshTestCase(String string) {
+ super(string);
+ }
+
+ protected String getEntityCacheConfigName() {
+ return "entity";
+ }
+
+ /**
+ * Disables use of the second level cache for this session factory.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ protected void configureSecondNode(Configuration cfg) {
+ super.configureSecondNode(cfg);
+ cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "false");
+ }
+
+ @Override
+ public String[] getMappings() {
+ return new String[] { "cache/infinispan/functional/classloader/Account.hbm.xml" };
+ }
+
+ @Override
+ protected void cleanupTransactionManagement() {
+ // Don't clean up the managers, just the transactions
+ // Managers are still needed by the long-lived caches
+ DualNodeJtaTransactionManagerImpl.cleanupTransactions();
+ }
+
+ public void testRefreshAfterExternalChange() throws Exception {
+ // First session factory uses a cache
+ CacheManager localManager = ClusterAwareRegionFactory.getCacheManager(AbstractDualNodeTestCase.LOCAL);
+ localCache = localManager.getCache(Account.class.getName());
+ TransactionManager localTM = DualNodeJtaTransactionManagerImpl.getInstance(AbstractDualNodeTestCase.LOCAL);
+ SessionFactory localFactory = getEnvironment().getSessionFactory();
+
+ // Second session factory doesn't; just needs a transaction manager
+ TransactionManager remoteTM = DualNodeJtaTransactionManagerImpl.getInstance(AbstractDualNodeTestCase.REMOTE);
+ SessionFactory remoteFactory = getSecondNodeEnvironment().getSessionFactory();
+
+ ClassLoaderTestDAO dao0 = new ClassLoaderTestDAO(localFactory, localTM);
+ ClassLoaderTestDAO dao1 = new ClassLoaderTestDAO(remoteFactory, remoteTM);
+
+ Integer id = new Integer(1);
+ dao0.createAccount(dao0.getSmith(), id, new Integer(5), AbstractDualNodeTestCase.LOCAL);
+
+ // Basic sanity check
+ Account acct1 = dao1.getAccount(id);
+ assertNotNull(acct1);
+ assertEquals(AbstractDualNodeTestCase.LOCAL, acct1.getBranch());
+
+ // This dao's session factory isn't caching, so cache won't see this change
+ dao1.updateAccountBranch(id, AbstractDualNodeTestCase.REMOTE);
+
+ // dao1's session doesn't touch the cache,
+ // so reading from dao0 should show a stale value from the cache
+ // (we check to confirm the cache is used)
+ Account acct0 = dao0.getAccount(id);
+ assertNotNull(acct0);
+ assertEquals(AbstractDualNodeTestCase.LOCAL, acct0.getBranch());
+ log.debug("Contents when re-reading from local: " + TestingUtil.printCache(localCache));
+
+ // Now call session.refresh and confirm we get the correct value
+ acct0 = dao0.getAccountWithRefresh(id);
+ assertNotNull(acct0);
+ assertEquals(AbstractDualNodeTestCase.REMOTE, acct0.getBranch());
+ log.debug("Contents after refreshing in remote: " + TestingUtil.printCache(localCache));
+
+ // Double check with a brand new session, in case the other session
+ // for some reason bypassed the 2nd level cache
+ ClassLoaderTestDAO dao0A = new ClassLoaderTestDAO(localFactory, localTM);
+ Account acct0A = dao0A.getAccount(id);
+ assertNotNull(acct0A);
+ assertEquals(AbstractDualNodeTestCase.REMOTE, acct0A.getBranch());
+ log.debug("Contents after creating a new session: " + TestingUtil.printCache(localCache));
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/query/QueryRegionImplTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,303 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.query;
+
+import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.StandardQueryCache;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
+import org.hibernate.test.cache.infinispan.util.CacheTestUtil;
+import org.infinispan.Cache;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
+import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+import org.infinispan.util.concurrent.IsolationLevel;
+
+/**
+ * Tests of QueryResultRegionImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class QueryRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
+
+ // protected static final String REGION_NAME = "test/" + StandardQueryCache.class.getName();
+
+ /**
+ * Create a new EntityRegionImplTestCase.
+ *
+ * @param name
+ */
+ public QueryRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildQueryResultsRegion(regionName, properties);
+ }
+
+ @Override
+ protected String getStandardRegionName(String regionPrefix) {
+ return regionPrefix + "/" + StandardQueryCache.class.getName();
+ }
+
+ @Override
+ protected Cache getInfinispanCache(InfinispanRegionFactory regionFactory) {
+ return regionFactory.getCacheManager().getCache("local-query");
+ }
+
+ @Override
+ protected Configuration createConfiguration() {
+ return CacheTestUtil.buildCustomQueryCacheConfiguration("test", "replicated-query");
+ }
+
+ public void testPutDoesNotBlockGet() throws Exception {
+ putDoesNotBlockGetTest();
+ }
+
+ private void putDoesNotBlockGetTest() throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), cfg
+ .getProperties());
+
+ region.put(KEY, VALUE1);
+ assertEquals(VALUE1, region.get(KEY));
+
+ final CountDownLatch readerLatch = new CountDownLatch(1);
+ final CountDownLatch writerLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ final ExceptionHolder holder = new ExceptionHolder();
+
+ Thread reader = new Thread() {
+ public void run() {
+ try {
+ BatchModeTransactionManager.getInstance().begin();
+ log.debug("Transaction began, get value for key");
+ assertTrue(VALUE2.equals(region.get(KEY)) == false);
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (AssertionFailedError e) {
+ holder.a1 = e;
+ rollback();
+ } catch (Exception e) {
+ holder.e1 = e;
+ rollback();
+ } finally {
+ readerLatch.countDown();
+ }
+ }
+ };
+
+ Thread writer = new Thread() {
+ public void run() {
+ try {
+ BatchModeTransactionManager.getInstance().begin();
+ log.debug("Put value2");
+ region.put(KEY, VALUE2);
+ log.debug("Put finished for value2, await writer latch");
+ writerLatch.await();
+ log.debug("Writer latch finished");
+ BatchModeTransactionManager.getInstance().commit();
+ log.debug("Transaction committed");
+ } catch (Exception e) {
+ holder.e2 = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ reader.setDaemon(true);
+ writer.setDaemon(true);
+
+ writer.start();
+ assertFalse("Writer is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ // Start the reader
+ reader.start();
+ assertTrue("Reader finished promptly", readerLatch.await(1000000000, TimeUnit.MILLISECONDS));
+
+ writerLatch.countDown();
+ assertTrue("Reader finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ assertEquals(VALUE2, region.get(KEY));
+
+ if (holder.a1 != null)
+ throw holder.a1;
+ else if (holder.a2 != null)
+ throw holder.a2;
+
+ assertEquals("writer saw no exceptions", null, holder.e1);
+ assertEquals("reader saw no exceptions", null, holder.e2);
+ }
+
+ public void testGetDoesNotBlockPut() throws Exception {
+ getDoesNotBlockPutTest();
+ }
+
+ // public void testGetDoesNotBlockPutPessimisticRepeatableRead() throws Exception {
+ // getDoesNotBlockPutTest();
+ // }
+
+ private void getDoesNotBlockPutTest() throws Exception {
+ Configuration cfg = createConfiguration();
+ InfinispanRegionFactory regionFactory = CacheTestUtil.startRegionFactory(cfg, getCacheTestSupport());
+
+ // Sleep a bit to avoid concurrent FLUSH problem
+ avoidConcurrentFlush();
+
+ final QueryResultsRegion region = regionFactory.buildQueryResultsRegion(getStandardRegionName(REGION_PREFIX), cfg
+ .getProperties());
+
+ region.put(KEY, VALUE1);
+ assertEquals(VALUE1, region.get(KEY));
+
+ // final Fqn rootFqn = getRegionFqn(getStandardRegionName(REGION_PREFIX), REGION_PREFIX);
+ final Cache jbc = getInfinispanCache(regionFactory);
+
+ final CountDownLatch blockerLatch = new CountDownLatch(1);
+ final CountDownLatch writerLatch = new CountDownLatch(1);
+ final CountDownLatch completionLatch = new CountDownLatch(1);
+ final ExceptionHolder holder = new ExceptionHolder();
+
+ Thread blocker = new Thread() {
+
+ public void run() {
+ // Fqn toBlock = new Fqn(rootFqn, KEY);
+ GetBlocker blocker = new GetBlocker(blockerLatch, KEY);
+ try {
+ jbc.addListener(blocker);
+
+ BatchModeTransactionManager.getInstance().begin();
+ region.get(KEY);
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ holder.e1 = e;
+ rollback();
+ } finally {
+ jbc.removeListener(blocker);
+ }
+ }
+ };
+
+ Thread writer = new Thread() {
+
+ public void run() {
+ try {
+ writerLatch.await();
+
+ BatchModeTransactionManager.getInstance().begin();
+ region.put(KEY, VALUE2);
+ BatchModeTransactionManager.getInstance().commit();
+ } catch (Exception e) {
+ holder.e2 = e;
+ rollback();
+ } finally {
+ completionLatch.countDown();
+ }
+ }
+ };
+
+ blocker.setDaemon(true);
+ writer.setDaemon(true);
+
+ boolean unblocked = false;
+ try {
+ blocker.start();
+ writer.start();
+
+ assertFalse("Blocker is blocking", completionLatch.await(100, TimeUnit.MILLISECONDS));
+ // Start the writer
+ writerLatch.countDown();
+ assertTrue("Writer finished promptly", completionLatch.await(100, TimeUnit.MILLISECONDS));
+
+ blockerLatch.countDown();
+ unblocked = true;
+
+ if (IsolationLevel.REPEATABLE_READ.equals(jbc.getConfiguration().getIsolationLevel())) {
+ assertEquals(VALUE1, region.get(KEY));
+ } else {
+ assertEquals(VALUE2, region.get(KEY));
+ }
+
+ if (holder.a1 != null)
+ throw holder.a1;
+ else if (holder.a2 != null)
+ throw holder.a2;
+
+ assertEquals("blocker saw no exceptions", null, holder.e1);
+ assertEquals("writer saw no exceptions", null, holder.e2);
+ } finally {
+ if (!unblocked)
+ blockerLatch.countDown();
+ }
+ }
+
+ @Listener
+ public class GetBlocker {
+
+ private CountDownLatch latch;
+ // private Fqn fqn;
+ private Object key;
+
+ GetBlocker(CountDownLatch latch, Object key) {
+ this.latch = latch;
+ this.key = key;
+ }
+
+ @CacheEntryVisited
+ public void nodeVisisted(CacheEntryVisitedEvent event) {
+ if (event.isPre() && event.getKey().equals(key)) {
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ log.error("Interrupted waiting for latch", e);
+ }
+ }
+ }
+ }
+
+ private class ExceptionHolder {
+ Exception e1;
+ Exception e2;
+ AssertionFailedError a1;
+ AssertionFailedError a2;
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/timestamp/TimestampsRegionImplTestCase.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,62 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.timestamp;
+
+import java.util.Properties;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.Region;
+import org.hibernate.cache.UpdateTimestampsCache;
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.test.cache.infinispan.AbstractGeneralDataRegionTestCase;
+import org.infinispan.Cache;
+
+/**
+ * Tests of TimestampsRegionImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class TimestampsRegionImplTestCase extends AbstractGeneralDataRegionTestCase {
+
+ public TimestampsRegionImplTestCase(String name) {
+ super(name);
+ }
+
+ @Override
+ protected String getStandardRegionName(String regionPrefix) {
+ return regionPrefix + "/" + UpdateTimestampsCache.class.getName();
+ }
+
+ @Override
+ protected Region createRegion(InfinispanRegionFactory regionFactory, String regionName, Properties properties, CacheDataDescription cdd) {
+ return regionFactory.buildTimestampsRegion(regionName, properties);
+ }
+
+ @Override
+ protected Cache getInfinispanCache(InfinispanRegionFactory regionFactory) {
+ return regionFactory.getCacheManager().getCache("timestamps");
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaConnectionProvider.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.connection.ConnectionProvider;
+import org.hibernate.connection.ConnectionProviderFactory;
+
+/**
+ * XaConnectionProvider.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class XaConnectionProvider implements ConnectionProvider {
+ private static ConnectionProvider actualConnectionProvider = ConnectionProviderFactory.newConnectionProvider();
+ private boolean isTransactional;
+
+ public static ConnectionProvider getActualConnectionProvider() {
+ return actualConnectionProvider;
+ }
+
+ public void configure(Properties props) throws HibernateException {
+ }
+
+ public Connection getConnection() throws SQLException {
+ XaTransactionImpl currentTransaction = XaTransactionManagerImpl.getInstance().getCurrentTransaction();
+ if (currentTransaction == null) {
+ isTransactional = false;
+ return actualConnectionProvider.getConnection();
+ } else {
+ isTransactional = true;
+ Connection connection = currentTransaction.getEnlistedConnection();
+ if (connection == null) {
+ connection = actualConnectionProvider.getConnection();
+ currentTransaction.enlistConnection(connection);
+ }
+ return connection;
+ }
+ }
+
+ public void closeConnection(Connection conn) throws SQLException {
+ if (!isTransactional) {
+ conn.close();
+ }
+ }
+
+ public void close() throws HibernateException {
+ actualConnectionProvider.close();
+ }
+
+ public boolean supportsAggressiveRelease() {
+ return true;
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,247 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.tm;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * XaResourceCapableTransactionImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class XaTransactionImpl implements Transaction {
+ private static final Logger log = LoggerFactory.getLogger(XaTransactionImpl.class);
+ private int status;
+ private LinkedList synchronizations;
+ private Connection connection; // the only resource we care about is jdbc connection
+ private final XaTransactionManagerImpl jtaTransactionManager;
+ private List<XAResource> enlistedResources = new ArrayList<XAResource>();
+ private Xid xid = new XaResourceCapableTransactionXid();
+
+ public XaTransactionImpl(XaTransactionManagerImpl jtaTransactionManager) {
+ this.jtaTransactionManager = jtaTransactionManager;
+ this.status = Status.STATUS_ACTIVE;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+ IllegalStateException, SystemException {
+
+ if (status == Status.STATUS_MARKED_ROLLBACK) {
+ log.trace("on commit, status was marked for rollback-only");
+ rollback();
+ } else {
+ status = Status.STATUS_PREPARING;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.beforeCompletion();
+ }
+
+// if (!runXaResourcePrepare()) {
+// status = Status.STATUS_ROLLING_BACK;
+// } else {
+// status = Status.STATUS_PREPARED;
+// }
+
+ status = Status.STATUS_COMMITTING;
+
+ if (connection != null) {
+ try {
+ connection.commit();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+ }
+
+// runXaResourceCommitTx();
+
+ status = Status.STATUS_COMMITTED;
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ jtaTransactionManager.endCurrent(this);
+ }
+ }
+
+ public void rollback() throws IllegalStateException, SystemException {
+// status = Status.STATUS_ROLLING_BACK;
+// runXaResourceRollback();
+ status = Status.STATUS_ROLLEDBACK;
+
+ if (connection != null) {
+ try {
+ connection.rollback();
+ connection.close();
+ } catch (SQLException sqle) {
+ status = Status.STATUS_UNKNOWN;
+ throw new SystemException();
+ }
+ }
+
+ for (int i = 0; i < synchronizations.size(); i++) {
+ Synchronization s = (Synchronization) synchronizations.get(i);
+ s.afterCompletion(status);
+ }
+
+ // status = Status.STATUS_NO_TRANSACTION;
+ jtaTransactionManager.endCurrent(this);
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ status = Status.STATUS_MARKED_ROLLBACK;
+ }
+
+ public void registerSynchronization(Synchronization synchronization) throws RollbackException,
+ IllegalStateException, SystemException {
+ // todo : find the spec-allowable statuses during which synch can be registered...
+ if (synchronizations == null) {
+ synchronizations = new LinkedList();
+ }
+ synchronizations.add(synchronization);
+ }
+
+ public void enlistConnection(Connection connection) {
+ if (this.connection != null) {
+ throw new IllegalStateException("Connection already registered");
+ }
+ this.connection = connection;
+ }
+
+ public Connection getEnlistedConnection() {
+ return connection;
+ }
+
+ public boolean enlistResource(XAResource xaResource) throws RollbackException, IllegalStateException,
+ SystemException {
+ enlistedResources.add(xaResource);
+ try {
+ xaResource.start(xid, 0);
+ } catch (XAException e) {
+ log.error("Got an exception", e);
+ throw new SystemException(e.getMessage());
+ }
+ return true;
+ }
+
+ public boolean delistResource(XAResource xaResource, int i) throws IllegalStateException, SystemException {
+ throw new SystemException("not supported");
+ }
+
+ public Collection<XAResource> getEnlistedResources() {
+ return enlistedResources;
+ }
+
+ private boolean runXaResourcePrepare() throws SystemException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.prepare(xid);
+ } catch (XAException e) {
+ log.trace("The resource wants to rollback!", e);
+ return false;
+ } catch (Throwable th) {
+ log.error("Unexpected error from resource manager!", th);
+ throw new SystemException(th.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private void runXaResourceRollback() {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.rollback(xid);
+ } catch (XAException e) {
+ log.warn("Error while rolling back",e);
+ }
+ }
+ }
+
+ private boolean runXaResourceCommitTx() throws HeuristicMixedException {
+ Collection<XAResource> resources = getEnlistedResources();
+ for (XAResource res : resources) {
+ try {
+ res.commit(xid, false);//todo we only support one phase commit for now, change this!!!
+ } catch (XAException e) {
+ log.warn("exception while committing",e);
+ throw new HeuristicMixedException(e.getMessage());
+ }
+ }
+ return true;
+ }
+
+ private static class XaResourceCapableTransactionXid implements Xid {
+ private static AtomicInteger txIdCounter = new AtomicInteger(0);
+ private int id = txIdCounter.incrementAndGet();
+
+ public int getFormatId() {
+ return id;
+ }
+
+ public byte[] getGlobalTransactionId() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ public byte[] getBranchQualifier() {
+ throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" +
+ "id=" + id +
+ '}';
+ }
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerImpl.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,105 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.tm;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * XaResourceCapableTransactionManagerImpl.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class XaTransactionManagerImpl implements TransactionManager {
+ private static final XaTransactionManagerImpl INSTANCE = new XaTransactionManagerImpl();
+ private XaTransactionImpl currentTransaction;
+
+ public static XaTransactionManagerImpl getInstance() {
+ return INSTANCE;
+ }
+
+ public int getStatus() throws SystemException {
+ return currentTransaction == null ? Status.STATUS_NO_TRANSACTION : currentTransaction.getStatus();
+ }
+
+ public Transaction getTransaction() throws SystemException {
+ return currentTransaction;
+ }
+
+ public XaTransactionImpl getCurrentTransaction() {
+ return currentTransaction;
+ }
+
+ public void begin() throws NotSupportedException, SystemException {
+ currentTransaction = new XaTransactionImpl(this);
+ }
+
+ public Transaction suspend() throws SystemException {
+ Transaction suspended = currentTransaction;
+ currentTransaction = null;
+ return suspended;
+ }
+
+ public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException,
+ SystemException {
+ currentTransaction = (XaTransactionImpl) transaction;
+ }
+
+ public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+ SecurityException, IllegalStateException, SystemException {
+ if (currentTransaction == null) {
+ throw new IllegalStateException("no current transaction to commit");
+ }
+ currentTransaction.commit();
+ }
+
+ public void rollback() throws IllegalStateException, SecurityException, SystemException {
+ if (currentTransaction == null) {
+ throw new IllegalStateException("no current transaction");
+ }
+ currentTransaction.rollback();
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ if (currentTransaction == null) {
+ throw new IllegalStateException("no current transaction");
+ }
+ currentTransaction.setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int i) throws SystemException {
+ }
+
+ void endCurrent(Transaction transaction) {
+ if (transaction == currentTransaction) {
+ currentTransaction = null;
+ }
+ }
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/XaTransactionManagerLookup.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or it's affiliates, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.hibernate.test.cache.infinispan.tm;
+
+import java.util.Properties;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * XaResourceCapableTransactionManagerLookup.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class XaTransactionManagerLookup implements TransactionManagerLookup {
+
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ return XaTransactionManagerImpl.getInstance();
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException( "jndi currently not implemented for these tests" );
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,61 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.util;
+
+import java.util.Properties;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.Transaction;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+import org.infinispan.transaction.tm.BatchModeTransactionManager;
+
+/**
+ * Uses the JBoss Cache BatchModeTransactionManager. Should not be used in
+ * any tests that simulate usage of database connections.
+ *
+ * @author Brian Stansberry
+ */
+public class BatchModeTransactionManagerLookup
+ implements TransactionManagerLookup {
+
+ public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+ try {
+ return BatchModeTransactionManager.getInstance();
+ }
+ catch (Exception e) {
+ throw new HibernateException("Failed getting BatchModeTransactionManager", e);
+ }
+ }
+
+ public String getUserTransactionName() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Object getTransactionIdentifier(Transaction transaction) {
+ return transaction;
+ }
+
+}
Property changes on: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/BatchModeTransactionManagerLookup.java
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestSupport.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,151 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.util;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.slf4j.Logger;
+
+import org.hibernate.cache.RegionFactory;
+import org.infinispan.Cache;
+
+/**
+ * Support class for tracking and cleaning up objects used in tests.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ */
+public class CacheTestSupport {
+
+ private static final String PREFER_IPV4STACK = "java.net.preferIPv4Stack";
+
+ private Logger log;
+
+ private Set<Cache> caches = new HashSet();
+ private Set<RegionFactory> factories = new HashSet();
+ private Exception exception;
+ private String preferIPv4Stack;
+
+ public CacheTestSupport(Logger log) {
+ this.log = log;
+ }
+
+ public void registerCache(Cache cache) {
+ caches.add(cache);
+ }
+
+ public void registerFactory(RegionFactory factory) {
+ factories.add(factory);
+ }
+
+ public void unregisterCache(Cache cache) {
+ caches.remove(cache);
+ }
+
+ public void unregisterFactory(RegionFactory factory) {
+ factories.remove(factory);
+ }
+
+ public void setUp() throws Exception {
+
+ // Try to ensure we use IPv4; otherwise cluster formation is very slow
+ preferIPv4Stack = System.getProperty(PREFER_IPV4STACK);
+ System.setProperty(PREFER_IPV4STACK, "true");
+
+ cleanUp();
+ throwStoredException();
+ }
+
+ public void tearDown() throws Exception {
+
+ if (preferIPv4Stack == null)
+ System.clearProperty(PREFER_IPV4STACK);
+ else
+ System.setProperty(PREFER_IPV4STACK, preferIPv4Stack);
+
+ cleanUp();
+ throwStoredException();
+ }
+
+ public void avoidConcurrentFlush() {
+ // JG 2.6.1 has a problem where calling flush more than once too quickly
+ // can result in several second delays
+ sleep(100);
+ }
+
+ private void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ }
+ catch (InterruptedException e) {
+ log.warn("Interrupted during sleep", e);
+ }
+ }
+
+ private void cleanUp() {
+ for (Iterator it = factories.iterator(); it.hasNext(); ) {
+ try {
+ ((RegionFactory) it.next()).stop();
+ }
+ catch (Exception e) {
+ storeException(e);
+ }
+ finally {
+ it.remove();
+ }
+ }
+ factories.clear();
+
+ for (Iterator it = caches.iterator(); it.hasNext(); ) {
+ try {
+ Cache cache = (Cache) it.next();
+ cache.stop();
+ }
+ catch (Exception e) {
+ storeException(e);
+ }
+ finally {
+ it.remove();
+ }
+ avoidConcurrentFlush();
+ }
+ caches.clear();
+ }
+
+ private void storeException(Exception e) {
+ if (this.exception == null) {
+ this.exception = e;
+ }
+ }
+
+ private void throwStoredException() throws Exception {
+ if (exception != null) {
+ Exception toThrow = exception;
+ exception = null;
+ throw toThrow;
+ }
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/util/CacheTestUtil.java 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,145 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat, Inc. and/or it's affiliates.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * 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 Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.cache.infinispan.util;
+
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.cache.infinispan.InfinispanRegionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.cfg.Settings;
+
+/**
+ * Utilities for cache testing.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ */
+public class CacheTestUtil {
+
+ public static Configuration buildConfiguration(String regionPrefix, Class regionFactory, boolean use2ndLevel, boolean useQueries) {
+ Configuration cfg = new Configuration();
+ cfg.setProperty(Environment.GENERATE_STATISTICS, "true");
+ cfg.setProperty(Environment.USE_STRUCTURED_CACHE, "true");
+ cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, BatchModeTransactionManagerLookup.class.getName());
+
+ cfg.setProperty(Environment.CACHE_REGION_FACTORY, regionFactory.getName());
+ cfg.setProperty(Environment.CACHE_REGION_PREFIX, regionPrefix);
+ cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, String.valueOf(use2ndLevel));
+ cfg.setProperty(Environment.USE_QUERY_CACHE, String.valueOf(useQueries));
+
+ return cfg;
+ }
+
+ public static Configuration buildLocalOnlyConfiguration(String regionPrefix, boolean use2ndLevel, boolean useQueries) {
+ Configuration cfg = buildConfiguration(regionPrefix, InfinispanRegionFactory.class, use2ndLevel, useQueries);
+ cfg.setProperty(InfinispanRegionFactory.INFINISPAN_CONFIG_RESOURCE_PROP,
+ InfinispanRegionFactory.DEF_INFINISPAN_CONFIG_RESOURCE);
+ return cfg;
+ }
+
+ public static Configuration buildCustomQueryCacheConfiguration(String regionPrefix, String queryCacheName) {
+ Configuration cfg = buildConfiguration(regionPrefix, InfinispanRegionFactory.class, true, true);
+ cfg.setProperty(InfinispanRegionFactory.QUERY_CACHE_RESOURCE_PROP, queryCacheName);
+ return cfg;
+ }
+
+ public static InfinispanRegionFactory startRegionFactory(Configuration cfg) throws ClassNotFoundException,
+ InstantiationException, IllegalAccessException {
+
+ Settings settings = cfg.buildSettings();
+ Properties properties = cfg.getProperties();
+
+ String factoryType = cfg.getProperty(Environment.CACHE_REGION_FACTORY);
+ Class factoryClass = Thread.currentThread().getContextClassLoader().loadClass(factoryType);
+ InfinispanRegionFactory regionFactory = (InfinispanRegionFactory) factoryClass.newInstance();
+
+ regionFactory.start(settings, properties);
+
+ return regionFactory;
+ }
+
+ public static InfinispanRegionFactory startRegionFactory(Configuration cfg, CacheTestSupport testSupport)
+ throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+ InfinispanRegionFactory factory = startRegionFactory(cfg);
+ testSupport.registerFactory(factory);
+ return factory;
+ }
+
+ public static void stopRegionFactory(InfinispanRegionFactory factory, CacheTestSupport testSupport) {
+ factory.stop();
+ testSupport.unregisterFactory(factory);
+ }
+
+ /**
+ * Supports easy creation of a TestSuite where a subclass' "FailureExpected" version of a base
+ * test is included in the suite, while the base test is excluded. E.g. test class FooTestCase
+ * includes method testBar(), while test class SubFooTestCase extends FooTestCase includes method
+ * testBarFailureExcluded(). Passing SubFooTestCase.class to this method will return a suite that
+ * does not include testBar().
+ *
+ * FIXME Move this to UnitTestCase
+ */
+ public static TestSuite createFailureExpectedSuite(Class testClass) {
+
+ TestSuite allTests = new TestSuite(testClass);
+ Set failureExpected = new HashSet();
+ Enumeration tests = allTests.tests();
+ while (tests.hasMoreElements()) {
+ Test t = (Test) tests.nextElement();
+ if (t instanceof TestCase) {
+ String name = ((TestCase) t).getName();
+ if (name.endsWith("FailureExpected"))
+ failureExpected.add(name);
+ }
+ }
+
+ TestSuite result = new TestSuite();
+ tests = allTests.tests();
+ while (tests.hasMoreElements()) {
+ Test t = (Test) tests.nextElement();
+ if (t instanceof TestCase) {
+ String name = ((TestCase) t).getName();
+ if (!failureExpected.contains(name + "FailureExpected")) {
+ result.addTest(t);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Prevent instantiation.
+ */
+ private CacheTestUtil() {
+ }
+
+}
Added: core/trunk/cache-infinispan/src/test/resources/hibernate.properties
===================================================================
--- core/trunk/cache-infinispan/src/test/resources/hibernate.properties (rev 0)
+++ core/trunk/cache-infinispan/src/test/resources/hibernate.properties 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,40 @@
+################################################################################
+# Hibernate, Relational Persistence for Idiomatic Java #
+# #
+# Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as #
+# indicated by the @author tags or express copyright attribution #
+# statements applied by the authors. All third-party contributions are #
+# distributed under license by Red Hat, Inc. and/or it's affiliates. #
+# #
+# This copyrighted material is made available to anyone wishing to use, modify,#
+# copy, or redistribute it subject to the terms and conditions of the GNU #
+# Lesser General Public License, as published by the Free Software Foundation. #
+# #
+# 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 Lesser General Public License
+# for more details. #
+# #
+# You should have received a copy of the GNU Lesser General Public License #
+# along with this distribution; if not, write to: #
+# Free Software Foundation, Inc. #
+# 51 Franklin Street, Fifth Floor #
+# Boston, MA 02110-1301 USA #
+################################################################################
+hibernate.dialect org.hibernate.dialect.HSQLDialect
+hibernate.connection.driver_class org.hsqldb.jdbcDriver
+hibernate.connection.url jdbc:hsqldb:mem:/test
+hibernate.connection.username sa
+hibernate.connection.password
+
+hibernate.connection.pool_size 5
+
+hibernate.format_sql true
+
+hibernate.max_fetch_depth 5
+
+hibernate.generate_statistics true
+
+hibernate.cache.use_second_level_cache true
+hibernate.cache.use_query_cache true
+hibernate.cache.region.factory_class org.hibernate.cache.infinispan.InfinispanRegionFactory
\ No newline at end of file
Property changes on: core/trunk/cache-infinispan/src/test/resources/hibernate.properties
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/resources/log4j.properties
===================================================================
--- core/trunk/cache-infinispan/src/test/resources/log4j.properties (rev 0)
+++ core/trunk/cache-infinispan/src/test/resources/log4j.properties 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,37 @@
+################################################################################
+# Hibernate, Relational Persistence for Idiomatic Java #
+# #
+# Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as #
+# indicated by the @author tags or express copyright attribution #
+# statements applied by the authors. All third-party contributions are #
+# distributed under license by Red Hat, Inc. and/or it's affiliates. #
+# #
+# This copyrighted material is made available to anyone wishing to use, modify,#
+# copy, or redistribute it subject to the terms and conditions of the GNU #
+# Lesser General Public License, as published by the Free Software Foundation. #
+# #
+# 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 Lesser General Public License
+# for more details. #
+# #
+# You should have received a copy of the GNU Lesser General Public License #
+# along with this distribution; if not, write to: #
+# Free Software Foundation, Inc. #
+# 51 Franklin Street, Fifth Floor #
+# Boston, MA 02110-1301 USA #
+################################################################################
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p [%t] %c{1}:%L - %m%n
+
+
+log4j.rootLogger=info, stdout
+
+#log4j.logger.org.hibernate.test=info
+log4j.logger.org.hibernate.test=trace
+log4j.logger.org.hibernate.cache=trace
+log4j.logger.org.hibernate.SQL=debug
+#log4j.logger.org.jgroups=info
+#log4j.logger.org.infinispan=trace
\ No newline at end of file
Property changes on: core/trunk/cache-infinispan/src/test/resources/log4j.properties
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Contact.hbm.xml
===================================================================
--- core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Contact.hbm.xml (rev 0)
+++ core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Contact.hbm.xml 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+ <!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java ~ ~
+ Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party
+ contributors as ~ indicated by the @author tags or express
+ copyright attribution ~ statements applied by the authors. All
+ third-party contributions are ~ distributed under license by Red
+ Hat Middleware LLC. ~ ~ This copyrighted material is made
+ available to anyone wishing to use, modify, ~ copy, or
+ redistribute it subject to the terms and conditions of the GNU ~
+ Lesser General Public License, as published by the Free Software
+ Foundation. ~ ~ 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 Lesser General Public License ~ for more
+ details. ~ ~ You should have received a copy of the GNU Lesser
+ General Public License ~ along with this distribution; if not,
+ write to: ~ Free Software Foundation, Inc. ~ 51 Franklin Street,
+ Fifth Floor ~ Boston, MA 02110-1301 USA
+ -->
+<hibernate-mapping
+ package="org.hibernate.test.cache.infinispan.functional">
+
+ <class name="Contact" table="Contacts">
+ <id name="id">
+ <generator class="increment" />
+ </id>
+ <property name="name" not-null="true" />
+ <property name="tlf" not-null="true" />
+ <many-to-one name="customer" column="cust_id" class="Customer" />
+ </class>
+
+</hibernate-mapping>
\ No newline at end of file
Property changes on: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Contact.hbm.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Customer.hbm.xml
===================================================================
--- core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Customer.hbm.xml (rev 0)
+++ core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Customer.hbm.xml 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+ <!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java ~ ~
+ Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party
+ contributors as ~ indicated by the @author tags or express
+ copyright attribution ~ statements applied by the authors. All
+ third-party contributions are ~ distributed under license by Red
+ Hat Middleware LLC. ~ ~ This copyrighted material is made
+ available to anyone wishing to use, modify, ~ copy, or
+ redistribute it subject to the terms and conditions of the GNU ~
+ Lesser General Public License, as published by the Free Software
+ Foundation. ~ ~ 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 Lesser General Public License ~ for more
+ details. ~ ~ You should have received a copy of the GNU Lesser
+ General Public License ~ along with this distribution; if not,
+ write to: ~ Free Software Foundation, Inc. ~ 51 Franklin Street,
+ Fifth Floor ~ Boston, MA 02110-1301 USA
+ -->
+<hibernate-mapping
+ package="org.hibernate.test.cache.infinispan.functional">
+
+ <class name="Customer" table="Customers">
+ <id name="id">
+ <generator class="increment" />
+ </id>
+ <property name="name" not-null="true" />
+ <set name="contacts" inverse="true" cascade="save-update">
+ <key column="cust_id" />
+ <one-to-many class="Contact" />
+ </set>
+
+ </class>
+
+</hibernate-mapping>
\ No newline at end of file
Added: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Item.hbm.xml
===================================================================
--- core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Item.hbm.xml (rev 0)
+++ core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Item.hbm.xml 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+ <!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java ~ ~
+ Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party
+ contributors as ~ indicated by the @author tags or express
+ copyright attribution ~ statements applied by the authors. All
+ third-party contributions are ~ distributed under license by Red
+ Hat Middleware LLC. ~ ~ This copyrighted material is made
+ available to anyone wishing to use, modify, ~ copy, or
+ redistribute it subject to the terms and conditions of the GNU ~
+ Lesser General Public License, as published by the Free Software
+ Foundation. ~ ~ 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 Lesser General Public License ~ for more
+ details. ~ ~ You should have received a copy of the GNU Lesser
+ General Public License ~ along with this distribution; if not,
+ write to: ~ Free Software Foundation, Inc. ~ 51 Franklin Street,
+ Fifth Floor ~ Boston, MA 02110-1301 USA
+ -->
+<hibernate-mapping package="org.hibernate.test.cache.infinispan.functional">
+
+ <class name="Item" table="Items">
+ <id name="id">
+ <generator class="increment" />
+ </id>
+ <property name="name" not-null="true" />
+ <property name="description" not-null="true" />
+ <many-to-one name="owner" column="owner_id" class="Item" />
+ <set name="items" inverse="true">
+ <key column="owner_id" />
+ <one-to-many class="Item" />
+ </set>
+ </class>
+
+ <class name="VersionedItem" table="VersionedItems">
+ <id name="id">
+ <generator class="increment" />
+ </id>
+ <version name="version" type="long" />
+ <property name="name" not-null="true" />
+ <property name="description" not-null="true" />
+ </class>
+
+</hibernate-mapping>
\ No newline at end of file
Property changes on: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/Item.hbm.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/classloader/Account.hbm.xml
===================================================================
--- core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/classloader/Account.hbm.xml (rev 0)
+++ core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/classloader/Account.hbm.xml 2009-08-21 08:39:33 UTC (rev 17386)
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<!--
+ ~ Hibernate, Relational Persistence for Idiomatic Java
+ ~
+ ~ Copyright (c) 2008, Red Hat, Inc. and/or it's affiliates or third-party contributors as
+ ~ indicated by the @author tags or express copyright attribution
+ ~ statements applied by the authors. All third-party contributions are
+ ~ distributed under license by Red Hat, Inc. and/or it's affiliates.
+ ~
+ ~ This copyrighted material is made available to anyone wishing to use, modify,
+ ~ copy, or redistribute it subject to the terms and conditions of the GNU
+ ~ Lesser General Public License, as published by the Free Software Foundation.
+ ~
+ ~ 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 Lesser General Public License
+ ~ for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public License
+ ~ along with this distribution; if not, write to:
+ ~ Free Software Foundation, Inc.
+ ~ 51 Franklin Street, Fifth Floor
+ ~ Boston, MA 02110-1301 USA
+ -->
+<hibernate-mapping
+ package="org.hibernate.test.cache.infinispan.functional.classloader">
+
+ <class name="Account" table="Accounts">
+
+ <cache usage="transactional"/>
+
+ <id name="id">
+ <generator class="assigned"/>
+ </id>
+
+ <property name="branch" not-null="true"/>
+ <property name="balance" not-null="true"/>
+ <property name="accountHolder" type="serializable" not-null="true"/>
+
+ </class>
+
+</hibernate-mapping>
Property changes on: core/trunk/cache-infinispan/src/test/resources/org/hibernate/test/cache/infinispan/functional/classloader/Account.hbm.xml
___________________________________________________________________
Name: svn:executable
+ *
14 years, 9 months