Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractBrokerSerializationTest.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractBrokerSerializationTest.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractBrokerSerializationTest.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractBrokerSerializationTest.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,446 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import javax.persistence.EntityManager; + +import org.apache.openjpa.event.AbstractLifecycleListener; +import org.apache.openjpa.event.AbstractTransactionListener; +import org.apache.openjpa.event.LifecycleEvent; +import org.apache.openjpa.event.TransactionEvent; +import org.apache.openjpa.persistence.InvalidStateException; +import org.apache.openjpa.persistence.JPAFacadeHelper; +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory; +import org.apache.openjpa.persistence.jdbc.JDBCFetchPlan; +import org.apache.openjpa.persistence.jdbc.JoinSyntax; +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +/* + * To test: + * - managed transactions + * - converting non-enhanced classes to enhanced subclasses + * (maybe an ugly ThreadLocal, maybe through PCData?) + */ +public abstract class AbstractBrokerSerializationTest<T> + extends SingleEMFTestCase { + + private static LifeListener deserializedLifeListener; + private static int testGlobalRefreshCount = 0; + + private static TxListener deserializedTxListener; + private static int testGlobalBeginCount = 0; + + + private Object id; + + public void setUp() { + testGlobalRefreshCount = 0; + deserializedLifeListener = null; + testGlobalBeginCount = 0; + deserializedTxListener = null; + + setUp(getManagedType(), getSecondaryType(), CLEAR_TABLES, + "openjpa.EntityManagerFactoryPool", "true"); + + T e = newManagedInstance(); + OpenJPAEntityManager em = emf.createEntityManager(); + em.getTransaction().begin(); + em.persist(e); + em.getTransaction().commit(); + id = em.getObjectId(e); + em.close(); + } + + @Override + public void tearDown() throws Exception { + super.tearDown(); + testGlobalRefreshCount = 0; + deserializedLifeListener = null; + testGlobalBeginCount = 0; + deserializedTxListener = null; + } + + public void testEmptyBrokerSerialization() { + OpenJPAEntityManager em = emf.createEntityManager(); + OpenJPAEntityManager em2 = deserializeEM(serialize(em)); + + assertTrue(em != em2); + assertTrue( + JPAFacadeHelper.toBroker(em) != JPAFacadeHelper.toBroker(em2)); + assertSame(em.getEntityManagerFactory(), em2.getEntityManagerFactory()); + + assertSame(em2, JPAFacadeHelper.toBroker(em2) + .getUserObject(JPAFacadeHelper.EM_KEY)); + + em.close(); + assertTrue(em2.isOpen()); + em2.close(); + } + + public void testNontransactionalBrokerSerialization() { + OpenJPAEntityManager em = emf.createEntityManager(); + T e = em.find(getManagedType(), id); + OpenJPAEntityManager em2 = deserializeEM(serialize(em)); + + assertFalse(em2.getTransaction().isActive()); + + assertFalse(em2.contains(e)); + assertEquals(1*graphSize(), em2.getManagedObjects().size()); + T e2 = em2.find(getManagedType(), id); + assertEquals(em.getObjectId(e), em2.getObjectId(e2)); + + em.close(); + em2.close(); + } + + public void testUnflushedOptimisticTxBrokerSerialization() { + OpenJPAEntityManager em = emf.createEntityManager(); + T e = em.find(getManagedType(), id); + OpenJPAEntityManager em2 = null; + OpenJPAEntityManager em3 = null; + try { + em.getTransaction().begin(); + modifyInstance(e); + T newe = newManagedInstance(); + em.persist(newe); + em2 = deserializeEM(serialize(em)); + + assertTrue(em2.getTransaction().isActive()); + + assertFalse(em2.contains(e)); + T e2 = em2.find(getManagedType(), id); + assertEquals(em.getObjectId(e), em2.getObjectId(e2)); + + assertEquals("modified", getModifiedValue(e2)); + + em.getTransaction().rollback(); + assertTrue(em2.getTransaction().isActive()); + em2.getTransaction().commit(); + + em3 = emf.createEntityManager(); + T e3 = em3.find(getManagedType(), id); + assertEquals(getModifiedValue(e2), getModifiedValue(e3)); + assertTrue(1 < ((Number) em3.createQuery("select count(o) from " + + getManagedType().getName() + " o").getSingleResult()) + .intValue()); + } finally { + close(em); + close(em2); + close(em3); + } + } + + public void testFlushedOptimisticTxBrokerSerialization() { + OpenJPAEntityManager em = emf.createEntityManager(); + T e = em.find(getManagedType(), id); + em.getTransaction().begin(); + modifyInstance(e); + em.flush(); + try { + serialize(em); + } catch (InvalidStateException ise) { + // expected + assertTrue(ise.getMessage().contains("flushed")); + } finally { + em.getTransaction().rollback(); + em.close(); + } + } + + public void testConnectedOptimisticTxBrokerSerialization() { + Map m = new HashMap(); + m.put("openjpa.ConnectionRetainMode", "always"); + OpenJPAEntityManager em = emf.createEntityManager(m); + try { + serialize(em); + } catch (InvalidStateException ise) { + // expected + assertTrue(ise.getMessage().contains("connected")); + } finally { + em.close(); + } + } + + public void testEmptyPessimisticTxBrokerSerialization() { + Map m = new HashMap(); + m.put("openjpa.Optimistic", "false"); + OpenJPAEntityManager em = emf.createEntityManager(m); + em.getTransaction().begin(); + try { + serialize(em); + fail("should not be able to serialize"); + } catch (InvalidStateException ise) { + // expected + assertTrue(ise.getMessage().contains("datastore (pessimistic)")); + } finally { + em.getTransaction().rollback(); + em.close(); + } + } + + public void testNonEmptyPessimisticTxBrokerSerialization() { + Map m = new HashMap(); + m.put("openjpa.Optimistic", "false"); + OpenJPAEntityManager em = emf.createEntityManager(m); + T e = em.find(getManagedType(), id); + em.getTransaction().begin(); + try { + serialize(em); + fail("should not be able to serialize"); + } catch (InvalidStateException ise) { + // expected + assertTrue(ise.getMessage().contains("datastore (pessimistic)")); + } finally { + em.getTransaction().rollback(); + em.close(); + } + } + + public void testFetchConfigurationMutations() { + OpenJPAEntityManager em = emf.createEntityManager(); + JDBCFetchPlan plan = (JDBCFetchPlan) em.getFetchPlan(); + + assertNotEquals(17, plan.getLockTimeout()); + assertNotEquals(JoinSyntax.TRADITIONAL, plan.getJoinSyntax()); + + plan.setLockTimeout(17); + plan.setJoinSyntax(JoinSyntax.TRADITIONAL); + + OpenJPAEntityManager em2 = deserializeEM(serialize(em)); + JDBCFetchPlan plan2 = (JDBCFetchPlan) em2.getFetchPlan(); + assertEquals(17, plan2.getLockTimeout()); + assertEquals(JoinSyntax.TRADITIONAL, plan2.getJoinSyntax()); + } + + public void testInMemorySavepointsWithNewInstances() { + emf.close(); + OpenJPAEntityManagerFactory emf = createEMF( + getManagedType(), getSecondaryType(), + "openjpa.EntityManagerFactoryPool", "true", + "openjpa.SavepointManager", "in-mem"); + OpenJPAEntityManager em = emf.createEntityManager(); + OpenJPAEntityManager em2 = null; + try { + em.getTransaction().begin(); + T t = newManagedInstance(); + Object orig = getModifiedValue(t); + em.persist(t); + Object id = em.getObjectId(t); + em.setSavepoint("foo"); + modifyInstance(t); + assertNotEquals(orig, getModifiedValue(t)); + + em2 = deserializeEM(serialize(em)); + T t2 = em2.find(getManagedType(), id); + assertNotEquals(orig, getModifiedValue(t2)); + + em.rollbackToSavepoint("foo"); + assertEquals(orig, getModifiedValue(t)); + + em2.rollbackToSavepoint("foo"); + assertEquals(orig, getModifiedValue(t2)); + } finally { + close(em); + close(em2); + } + } + + public void testInMemorySavepointsWithModifiedInstances() { + emf.close(); + OpenJPAEntityManagerFactory emf = createEMF( + getManagedType(), getSecondaryType(), + "openjpa.EntityManagerFactoryPool", "true", + "openjpa.SavepointManager", "in-mem"); + OpenJPAEntityManager em = emf.createEntityManager(); + OpenJPAEntityManager em2 = null; + try { + em.getTransaction().begin(); + T t = em.find(getManagedType(), id); + Object orig = getModifiedValue(t); + em.setSavepoint("foo"); + modifyInstance(t); + assertNotEquals(orig, getModifiedValue(t)); + + em2 = deserializeEM(serialize(em)); + T t2 = em2.find(getManagedType(), id); + assertNotEquals(orig, getModifiedValue(t2)); + + em.rollbackToSavepoint("foo"); + assertEquals(orig, getModifiedValue(t)); + + em2.rollbackToSavepoint("foo"); + assertEquals(orig, getModifiedValue(t2)); + } finally { + close(em); + close(em2); + } + } + + public void testEventManagers() { + TxListener txListener = new TxListener(); + emf.addTransactionListener(txListener); + LifeListener lifeListener = new LifeListener(); + emf.addLifecycleListener(lifeListener, null); + + OpenJPAEntityManager em = emf.createEntityManager(); + T t = em.find(getManagedType(), id); + assertEquals(0, lifeListener.refreshCount); + em.refresh(t); + assertEquals(1*graphSize(), lifeListener.refreshCount); + em.getTransaction().begin(); + em.getTransaction().commit(); + em.getTransaction().begin(); + em.getTransaction().commit(); + assertEquals(2, txListener.beginCount); + + OpenJPAEntityManager em2 = deserializeEM(serialize(em)); + assertNotNull(deserializedLifeListener); + assertEquals(1* graphSize(), + deserializedLifeListener.refreshCount); + assertNotSame(lifeListener, deserializedLifeListener); + T t2 = em2.find(getManagedType(), id); + em2.refresh(t2); + assertEquals(2* graphSize(), + deserializedLifeListener.refreshCount); + + // if this is 3*refreshMultiplier(), that means that there are + // extra registered listeners + assertEquals(2* graphSize(), testGlobalRefreshCount); + + + assertNotNull(deserializedTxListener); + assertEquals(2, deserializedTxListener.beginCount); + assertNotSame(txListener, deserializedTxListener); + em2.getTransaction().begin(); + em2.getTransaction().rollback(); + assertEquals(3, deserializedTxListener.beginCount); + + // if this is 4, that means that there are extra registered listeners + assertEquals(3, testGlobalBeginCount); + } + + byte[] serialize(Object o) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(o); + oos.flush(); + return baos.toByteArray(); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + + OpenJPAEntityManager deserializeEM(byte[] bytes) { + return (OpenJPAEntityManager) deserialize(bytes); + } + + private Object deserialize(byte[] bytes) { + try { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais); + return ois.readObject(); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + void close(EntityManager em) { + if (em != null && em.isOpen() && em.getTransaction().isActive()) + em.getTransaction().rollback(); + if (em != null && em.isOpen()) + em.close(); + } + + protected abstract Class<T> getManagedType(); + + protected abstract T newManagedInstance(); + + protected abstract void modifyInstance(T t); + + protected abstract Object getModifiedValue(T t); + + /** + * The number of instances in the graph created + * by [EMAIL PROTECTED] #newManagedInstance()} of type T. + */ + protected int graphSize() { + return 1; + } + + /** + * An additional type that must be available in this PC. May be null. + */ + protected Class getSecondaryType() { + return null; + } + + private static class TxListener + extends AbstractTransactionListener + implements Serializable { + + private int beginCount = 0; + + public TxListener() { + + } + + @Override + public void afterBegin(TransactionEvent event) { + beginCount++; + testGlobalBeginCount++; + } + + private void readObject(ObjectInputStream in) + throws ClassNotFoundException, IOException { + in.defaultReadObject(); + deserializedTxListener = this; + } + } + + private static class LifeListener + extends AbstractLifecycleListener + implements Serializable { + + private int refreshCount = 0; + + @Override + public void afterRefresh(LifecycleEvent event) { + refreshCount++; + testGlobalRefreshCount++; + } + + private void readObject(ObjectInputStream in) + throws ClassNotFoundException, IOException { + in.defaultReadObject(); + deserializedLifeListener = this; + } + } +} \ No newline at end of file
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractUnenhancedRelationBrokerSerializationTest.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractUnenhancedRelationBrokerSerializationTest.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractUnenhancedRelationBrokerSerializationTest.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/AbstractUnenhancedRelationBrokerSerializationTest.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.enhance.PersistenceCapable; +import org.apache.openjpa.enhance.UnenhancedSubtype; +import org.apache.openjpa.persistence.OpenJPAEntityManager; +import org.apache.openjpa.util.ImplHelper; + +public abstract class AbstractUnenhancedRelationBrokerSerializationTest<T> + extends AbstractBrokerSerializationTest<T> { + + public void testNewUnenhancedSMsRegisteredGlobally() { + OpenJPAEntityManager em = emf.createEntityManager(); + OpenJPAEntityManager em2 = null; + try { + em.getTransaction().begin(); + UnenhancedSubtype newe = (UnenhancedSubtype) newManagedInstance(); + em.persist(newe); + em2 = deserializeEM(serialize(em)); + + for (Object o : em2.getManagedObjects()) { + assertFalse(o instanceof PersistenceCapable); + assertNotNull(ImplHelper.toPersistenceCapable(o, + emf.getConfiguration())); + if (o instanceof UnenhancedSubtype) + assertNotNull(ImplHelper.toPersistenceCapable( + ((UnenhancedSubtype) o).getRelated(), + emf.getConfiguration())); + } + } finally { + close(em); + close(em2); + } + } +} Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEnhancedInstanceBrokerSerialization.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEnhancedInstanceBrokerSerialization.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEnhancedInstanceBrokerSerialization.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEnhancedInstanceBrokerSerialization.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.enhance.PersistenceCapable; +import org.apache.openjpa.persistence.query.SimpleEntity; + +public class TestEnhancedInstanceBrokerSerialization + extends AbstractBrokerSerializationTest<SimpleEntity> { + + @Override + public void setUp() { + assertTrue( + PersistenceCapable.class.isAssignableFrom(SimpleEntity.class)); + super.setUp(); + } + + protected Class<SimpleEntity> getManagedType() { + return SimpleEntity.class; + } + + protected SimpleEntity newManagedInstance() { + SimpleEntity e = new SimpleEntity(); + e.setName("foo"); + e.setValue("bar"); + return e; + } + + protected void modifyInstance(SimpleEntity e) { + e.setValue("modified"); + } + + protected Object getModifiedValue(SimpleEntity e) { + return e.getValue(); + } +} \ No newline at end of file Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEntityManagerFactoryPool.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEntityManagerFactoryPool.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEntityManagerFactoryPool.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestEntityManagerFactoryPool.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import java.util.HashMap; +import java.util.Map; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; + +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +public class TestEntityManagerFactoryPool + extends SingleEMFTestCase { + + public void setUp() { + setUp("openjpa.EntityManagerFactoryPool", Boolean.TRUE); + + emf.createEntityManager().close(); + } + + public void testBrokerFactoryPoolHit() { + Map m = new HashMap(); + // also tests string values for the property + m.put("openjpa.EntityManagerFactoryPool", "True"); + EntityManagerFactory emf = Persistence.createEntityManagerFactory( + "test", m); + assertSame(this.emf, emf); + } + + public void testBrokerFactoryPoolMiss() { + Map m = new HashMap(); + m.put("openjpa.EntityManagerFactoryPool", Boolean.TRUE); + EntityManagerFactory emf = Persistence.createEntityManagerFactory( + "second-persistence-unit", m); + assertNotSame(this.emf, emf); + } +} \ No newline at end of file Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestInstanceGraphBrokerSerialization.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestInstanceGraphBrokerSerialization.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestInstanceGraphBrokerSerialization.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestInstanceGraphBrokerSerialization.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.persistence.query.ManyOneEntity; + +public class TestInstanceGraphBrokerSerialization + extends AbstractBrokerSerializationTest<ManyOneEntity> { + + protected Class<ManyOneEntity> getManagedType() { + return ManyOneEntity.class; + } + + protected ManyOneEntity newManagedInstance() { + ManyOneEntity e = new ManyOneEntity(); + e.setName("foo"); + ManyOneEntity rel = new ManyOneEntity(); + rel.setName("bar"); + e.setRel(rel); + return e; + } + + protected void modifyInstance(ManyOneEntity e) { + e.getRel().setName("modified"); + } + + protected Object getModifiedValue(ManyOneEntity e) { + return e.getRel().getName(); + } + + @Override + protected int graphSize() { + return 2; + } +} \ No newline at end of file Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessInstanceBrokerSerialization.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessInstanceBrokerSerialization.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessInstanceBrokerSerialization.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessInstanceBrokerSerialization.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.enhance.UnenhancedFieldAccess; + +public class TestUnenhancedFieldAccessInstanceBrokerSerialization + extends AbstractBrokerSerializationTest<UnenhancedFieldAccess> { + + protected Class<UnenhancedFieldAccess> getManagedType() { + return UnenhancedFieldAccess.class; + } + + protected UnenhancedFieldAccess newManagedInstance() { + UnenhancedFieldAccess e = new UnenhancedFieldAccess(); + e.setStringField("foo"); + return e; + } + + protected void modifyInstance(UnenhancedFieldAccess e) { + e.setStringField("modified"); + } + + protected Object getModifiedValue(UnenhancedFieldAccess e) { + return e.getStringField(); + } +} \ No newline at end of file Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessWithRelationInstanceBrokerSerialization.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessWithRelationInstanceBrokerSerialization.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessWithRelationInstanceBrokerSerialization.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedFieldAccessWithRelationInstanceBrokerSerialization.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.enhance.UnenhancedFieldAccess; +import org.apache.openjpa.enhance.UnenhancedFieldAccessSubclass; + +public class TestUnenhancedFieldAccessWithRelationInstanceBrokerSerialization + extends AbstractUnenhancedRelationBrokerSerializationTest + <UnenhancedFieldAccessSubclass> { + + protected Class getSecondaryType() { + return UnenhancedFieldAccess.class; + } + + protected Class<UnenhancedFieldAccessSubclass> getManagedType() { + return UnenhancedFieldAccessSubclass.class; + } + + protected UnenhancedFieldAccessSubclass newManagedInstance() { + UnenhancedFieldAccessSubclass e = new UnenhancedFieldAccessSubclass(); + e.setStringField("foo"); + UnenhancedFieldAccess related = new UnenhancedFieldAccess(); + related.setStringField("bar"); + e.setRelated(related); + return e; + } + + protected void modifyInstance(UnenhancedFieldAccessSubclass e) { + e.getRelated().setStringField("modified"); + } + + protected Object getModifiedValue(UnenhancedFieldAccessSubclass e) { + return e.getRelated().getStringField(); + } + + @Override + protected int graphSize() { + return 2; + } +} \ No newline at end of file Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessInstanceBrokerSerialization.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessInstanceBrokerSerialization.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessInstanceBrokerSerialization.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessInstanceBrokerSerialization.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.enhance.UnenhancedPropertyAccess; + +public class TestUnenhancedPropertyAccessInstanceBrokerSerialization + extends AbstractBrokerSerializationTest<UnenhancedPropertyAccess> { + + protected Class<UnenhancedPropertyAccess> getManagedType() { + return UnenhancedPropertyAccess.class; + } + + protected UnenhancedPropertyAccess newManagedInstance() { + UnenhancedPropertyAccess e = new UnenhancedPropertyAccess(); + e.setStringField("foo"); + return e; + } + + protected void modifyInstance(UnenhancedPropertyAccess e) { + e.setStringField("modified"); + } + + protected Object getModifiedValue(UnenhancedPropertyAccess e) { + return e.getStringField(); + } +} \ No newline at end of file Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessWithRelationInstanceBrokerSerialization.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessWithRelationInstanceBrokerSerialization.java?rev=597155&view=auto ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessWithRelationInstanceBrokerSerialization.java (added) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestUnenhancedPropertyAccessWithRelationInstanceBrokerSerialization.java Wed Nov 21 09:40:54 2007 @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openjpa.kernel; + +import org.apache.openjpa.enhance.UnenhancedPropertyAccess; +import org.apache.openjpa.enhance.UnenhancedPropertyAccessSubclass; + +public class TestUnenhancedPropertyAccessWithRelationInstanceBrokerSerialization + extends AbstractUnenhancedRelationBrokerSerializationTest + <UnenhancedPropertyAccessSubclass> { + + protected Class getSecondaryType() { + return UnenhancedPropertyAccess.class; + } + + protected Class<UnenhancedPropertyAccessSubclass> getManagedType() { + return UnenhancedPropertyAccessSubclass.class; + } + + protected UnenhancedPropertyAccessSubclass newManagedInstance() { + UnenhancedPropertyAccessSubclass e = + new UnenhancedPropertyAccessSubclass(); + e.setStringField("foo"); + UnenhancedPropertyAccess related = new UnenhancedPropertyAccess(); + related.setStringField("bar"); + e.setRelated(related); + return e; + } + + protected void modifyInstance(UnenhancedPropertyAccessSubclass e) { + e.getRelated().setStringField("modified"); + } + + protected Object getModifiedValue(UnenhancedPropertyAccessSubclass e) { + return e.getRelated().getStringField(); + } + + @Override + protected int graphSize() { + return 2; + } +} \ No newline at end of file Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/ManyOneEntity.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/ManyOneEntity.java?rev=597155&r1=597154&r2=597155&view=diff ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/ManyOneEntity.java (original) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/ManyOneEntity.java Wed Nov 21 09:40:54 2007 @@ -18,6 +18,7 @@ */ package org.apache.openjpa.persistence.query; +import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -29,7 +30,7 @@ @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) -public class ManyOneEntity { +public class ManyOneEntity implements Serializable { @Id @GeneratedValue Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java?rev=597155&r1=597154&r2=597155&view=diff ============================================================================== --- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java (original) +++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/SimpleEntity.java Wed Nov 21 09:40:54 2007 @@ -18,6 +18,7 @@ */ package org.apache.openjpa.persistence.query; +import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; @@ -43,7 +44,7 @@ @FieldResult(name = "value", column = "VALUE") })) @Entity(name = "simple") @Table(name = "SIMPLE_ENTITY") -public class SimpleEntity { +public class SimpleEntity implements Serializable { @Id @GeneratedValue Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=597155&r1=597154&r2=597155&view=diff ============================================================================== --- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original) +++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Wed Nov 21 09:40:54 2007 @@ -18,6 +18,15 @@ */ package org.apache.openjpa.persistence; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Collection; @@ -30,6 +39,9 @@ import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.ee.ManagedRuntime; +import org.apache.openjpa.enhance.PCEnhancer; +import org.apache.openjpa.enhance.PCRegistry; +import org.apache.openjpa.kernel.AbstractBrokerFactory; import org.apache.openjpa.kernel.Broker; import org.apache.openjpa.kernel.DelegatingBroker; import org.apache.openjpa.kernel.FindCallbacks; @@ -40,8 +52,8 @@ import org.apache.openjpa.kernel.QueryLanguages; import org.apache.openjpa.kernel.Seq; import org.apache.openjpa.kernel.jpql.JPQLParser; -import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Closeable; +import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.FieldMetaData; import org.apache.openjpa.meta.QueryMetaData; @@ -59,30 +71,36 @@ * @nojavadoc */ public class EntityManagerImpl - implements OpenJPAEntityManagerSPI, + implements OpenJPAEntityManagerSPI, Externalizable, FindCallbacks, OpCallbacks, Closeable, OpenJPAEntityTransaction { private static final Localizer _loc = Localizer.forPackage (EntityManagerImpl.class); + private static final Object[] EMPTY_OBJECTS = new Object[0]; - private final DelegatingBroker _broker; - private final EntityManagerFactoryImpl _emf; + private DelegatingBroker _broker; + private EntityManagerFactoryImpl _emf; private FetchPlan _fetch = null; - private static final Object[] EMPTY_OBJECTS = new Object[0]; private RuntimeExceptionTranslator ret = PersistenceExceptions.getRollbackTranslator(this); + public EntityManagerImpl() { + // for Externalizable + } + /** * Constructor; supply factory and delegate. */ public EntityManagerImpl(EntityManagerFactoryImpl factory, Broker broker) { + initialize(factory, broker); + } + + private void initialize(EntityManagerFactoryImpl factory, Broker broker) { _emf = factory; - RuntimeExceptionTranslator translator = - PersistenceExceptions.getRollbackTranslator(this); - _broker = new DelegatingBroker(broker, translator); - _broker.setImplicitBehavior(this, translator); + _broker = new DelegatingBroker(broker, ret); + _broker.setImplicitBehavior(this, ret); } /** @@ -1179,5 +1197,145 @@ if (!(other instanceof EntityManagerImpl)) return false; return _broker.equals(((EntityManagerImpl) other)._broker); + } + + public void readExternal(ObjectInput in) + throws IOException, ClassNotFoundException { + try { + ret = PersistenceExceptions.getRollbackTranslator(this); + + // this assumes that serialized Brokers are from something + // that extends AbstractBrokerFactory. + Object factoryKey = in.readObject(); + AbstractBrokerFactory factory = + AbstractBrokerFactory.getPooledFactoryForKey(factoryKey); + byte[] brokerBytes = (byte[]) in.readObject(); + ObjectInputStream innerIn = new BrokerBytesInputStream(brokerBytes, + factory.getConfiguration()); + + Broker broker = (Broker) innerIn.readObject(); + EntityManagerFactoryImpl emf = (EntityManagerFactoryImpl) + JPAFacadeHelper.toEntityManagerFactory( + broker.getBrokerFactory()); + broker.putUserObject(JPAFacadeHelper.EM_KEY, this); + initialize(emf, broker); + } catch (RuntimeException re) { + try { + re = ret.translate(re); + } catch (Exception e) { + // ignore + } + throw re; + } + } + + public void writeExternal(ObjectOutput out) throws IOException { + try { + // this requires that only AbstractBrokerFactory-sourced + // brokers can be serialized + Object factoryKey = ((AbstractBrokerFactory) _broker + .getBrokerFactory()).getPoolKey(); + out.writeObject(factoryKey); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream innerOut = new ObjectOutputStream(baos); + innerOut.writeObject(_broker.getDelegate()); + innerOut.flush(); + out.writeObject(baos.toByteArray()); + } catch (RuntimeException re) { + try { + re = ret.translate(re); + } catch (Exception e) { + // ignore + } + throw re; + } + } + + private static class BrokerBytesInputStream extends ObjectInputStream { + + private OpenJPAConfiguration conf; + + BrokerBytesInputStream(byte[] bytes, OpenJPAConfiguration conf) + throws IOException { + super(new ByteArrayInputStream(bytes)); + if (conf == null) + throw new IllegalArgumentException( + "Illegal null argument to ObjectInputStreamWithLoader"); + this.conf = conf; + } + + /** + * Make a primitive array class + */ + private Class primitiveType(char type) { + switch (type) { + case 'B': return byte.class; + case 'C': return char.class; + case 'D': return double.class; + case 'F': return float.class; + case 'I': return int.class; + case 'J': return long.class; + case 'S': return short.class; + case 'Z': return boolean.class; + default: return null; + } + } + + protected Class resolveClass(ObjectStreamClass classDesc) + throws IOException, ClassNotFoundException { + + String cname = classDesc.getName(); + if (cname.startsWith("[")) { + // An array + Class component; // component class + int dcount; // dimension + for (dcount=1; cname.charAt(dcount)=='['; dcount++) ; + if (cname.charAt(dcount) == 'L') { + component = lookupClass(cname.substring(dcount+1, + cname.length()-1)); + } else { + if (cname.length() != dcount+1) { + throw new ClassNotFoundException(cname);// malformed + } + component = primitiveType(cname.charAt(dcount)); + } + int dim[] = new int[dcount]; + for (int i=0; i<dcount; i++) { + dim[i]=0; + } + return Array.newInstance(component, dim).getClass(); + } else { + return lookupClass(cname); + } + } + + /** + * If this is a generated subclass, look up the corresponding Class + * object via metadata. + */ + private Class lookupClass(String className) + throws ClassNotFoundException { + try { + return Class.forName(className); + } catch (ClassNotFoundException e) { + if (PCEnhancer.isPCSubclassName(className)) { + String superName = PCEnhancer.toManagedTypeName(className); + ClassMetaData[] metas = conf.getMetaDataRepositoryInstance() + .getMetaDatas(); + for (int i = 0; i < metas.length; i++) { + if (superName.equals( + metas[i].getDescribedType().getName())) { + return PCRegistry.getPCType( + metas[i].getDescribedType()); + } + } + + // if it's not found, try to look for it anyways + return Class.forName(className); + } else { + throw e; + } + } + } } } Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java?rev=597155&r1=597154&r2=597155&view=diff ============================================================================== --- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java (original) +++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceExceptions.java Wed Nov 21 09:40:54 2007 @@ -51,8 +51,8 @@ * and [EMAIL PROTECTED] NonUniqueResultException} in accordance with * section 3.7 of the EJB 3.0 specification. */ - public static RuntimeExceptionTranslator getRollbackTranslator - (final OpenJPAEntityManager em) { + public static RuntimeExceptionTranslator getRollbackTranslator( + final OpenJPAEntityManager em) { return new RuntimeExceptionTranslator() { private boolean throwing = false; Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java?rev=597155&r1=597154&r2=597155&view=diff ============================================================================== --- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java (original) +++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProviderImpl.java Wed Nov 21 09:40:54 2007 @@ -22,6 +22,8 @@ import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import javax.persistence.EntityManager; import javax.persistence.spi.ClassTransformer; import javax.persistence.spi.PersistenceProvider; @@ -54,6 +56,7 @@ implements PersistenceProvider { static final String CLASS_TRANSFORMER_OPTIONS = "ClassTransformerOptions"; + private static final String EMF_POOL = "EntityManagerFactoryPool"; private static final Localizer _loc = Localizer.forPackage( PersistenceProviderImpl.class); @@ -72,17 +75,37 @@ String resource, Map m) { PersistenceProductDerivation pd = new PersistenceProductDerivation(); try { + Object poolValue = Configurations.removeProperty(EMF_POOL, m); ConfigurationProvider cp = pd.load(resource, name, m); if (cp == null) return null; - BrokerFactory factory = Bootstrap.newBrokerFactory(cp, null); + BrokerFactory factory = getBrokerFactory(cp, poolValue, null); return JPAFacadeHelper.toEntityManagerFactory(factory); } catch (Exception e) { throw PersistenceExceptions.toPersistenceException(e); } } + private BrokerFactory getBrokerFactory(ConfigurationProvider cp, + Object poolValue, ClassLoader loader) { + // handle "true" and "false" + if (poolValue instanceof String + && ("true".equalsIgnoreCase((String) poolValue) + || "false".equalsIgnoreCase((String) poolValue))) + poolValue = Boolean.valueOf((String) poolValue); + + if (poolValue != null && !(poolValue instanceof Boolean)) { + // we only support boolean settings for this option currently. + throw new IllegalArgumentException(poolValue.toString()); + } + + if (poolValue == null || !((Boolean) poolValue).booleanValue()) + return Bootstrap.newBrokerFactory(cp, loader); + else + return Bootstrap.getBrokerFactory(cp, loader); + } + public OpenJPAEntityManagerFactory createEntityManagerFactory(String name, Map m) { return createEntityManagerFactory(name, null, m); @@ -92,6 +115,7 @@ PersistenceUnitInfo pui, Map m) { PersistenceProductDerivation pd = new PersistenceProductDerivation(); try { + Object poolValue = Configurations.removeProperty(EMF_POOL, m); ConfigurationProvider cp = pd.load(pui, m); if (cp == null) return null; @@ -117,7 +141,7 @@ BrokerValue.NON_FINALIZING_ALIAS); } - BrokerFactory factory = Bootstrap.newBrokerFactory(cp, + BrokerFactory factory = getBrokerFactory(cp, poolValue, pui.getClassLoader()); if (transformerException != null) { Log log = factory.getConfiguration().getLog(
