You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by br...@apache.org on 2004/07/06 14:45:44 UTC
cvs commit: db-ojb/src/test/org/apache/ojb/broker/dirty DirtyTest.java
brianm 2004/07/06 05:45:44
Added: src/java/org/apache/ojb/broker/dirty
DirtyPersistenceBrokerFactory.java Entry.java
LifeCycleListener.java StateListener.java
Tracker.java
src/test/org/apache/ojb/broker/dirty DirtyTest.java
Log:
Initial checkin of persistence broker auto-dirty system. Not optimized yet, and not fully tested, but it should work for majority of cases.
Revision Changes Path
1.1 db-ojb/src/java/org/apache/ojb/broker/dirty/DirtyPersistenceBrokerFactory.java
Index: DirtyPersistenceBrokerFactory.java
===================================================================
/* Copyright 2004-2004 The Apache Software Foundation
*
* 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.apache.ojb.broker.dirty;
import org.apache.ojb.broker.PBFactoryException;
import org.apache.ojb.broker.PBKey;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.PersistenceBrokerFactory;
import org.apache.ojb.broker.core.PersistenceBrokerFactoryFactory;
import org.apache.ojb.broker.metadata.MetadataManager;
import org.apache.ojb.broker.util.configuration.Configurator;
import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
/**
* Provides PersistenceBroker instances configured to do
* dirty checking on commit.
* <p>
* Behavior is iffy on rollback, but database will be clean
*/
public class DirtyPersistenceBrokerFactory
{
private static final PersistenceBroker wrap(PersistenceBroker broker)
{
Tracker t = new Tracker();
broker.addListener(new LifeCycleListener(t));
broker.addListener(new StateListener(t));
return broker;
}
public static PersistenceBroker defaultPersistenceBroker()
{
return wrap(PersistenceBrokerFactory.defaultPersistenceBroker());
}
/**
* Returns the {@link org.apache.ojb.broker.util.configuration.Configurator}
* object.
*
* @return the configurator
*/
public static Configurator getConfigurator()
{
return OjbConfigurator.getInstance();
}
/**
* @see org.apache.ojb.broker.core.PersistenceBrokerFactoryIF#setDefaultKey
*/
public static void setDefaultKey(PBKey key)
{
MetadataManager.getInstance().setDefaultPBKey(key);
}
/**
* @see org.apache.ojb.broker.core.PersistenceBrokerFactoryIF#getDefaultKey
*/
public static PBKey getDefaultKey()
{
return MetadataManager.getInstance().getDefaultPBKey();
}
/**
* @see org.apache.ojb.broker.core.PersistenceBrokerFactoryIF#createPersistenceBroker(java.lang.String, java.lang.String, java.lang.String)
*/
public static PersistenceBroker createPersistenceBroker(String jcdAlias,
String user, String password)
throws PBFactoryException
{
return wrap(PersistenceBrokerFactoryFactory.instance().
createPersistenceBroker(jcdAlias, user, password));
}
/**
* @see org.apache.ojb.broker.core.PersistenceBrokerFactoryIF#createPersistenceBroker(org.apache.ojb.broker.PBKey)
*/
public static PersistenceBroker createPersistenceBroker(PBKey key)
throws PBFactoryException
{
return wrap(PersistenceBrokerFactoryFactory.instance().createPersistenceBroker(key));
}
/**
* @see org.apache.ojb.broker.core.PersistenceBrokerFactoryIF#releaseAllInstances
*/
public static void releaseAllInstances()
{
PersistenceBrokerFactoryFactory.instance().releaseAllInstances();
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/dirty/Entry.java
Index: Entry.java
===================================================================
/* Copyright 2004-2004 The Apache Software Foundation
*
* 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.apache.ojb.broker.dirty;
import org.apache.ojb.otm.states.State;
import org.apache.ojb.broker.metadata.MetadataManager;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
public class Entry
{
private State state;
private Object[] fields;
public Entry(Object original, State state)
{
MetadataManager man = MetadataManager.getInstance();
ClassDescriptor cd = man.getRepository().getDescriptorFor(original.getClass());
FieldDescriptor[] fds = cd.getFieldDescriptions();
fields = new Object[fds.length];
for (int i = 0; i < fds.length; i++)
{
FieldDescriptor fd = fds[i];
PersistentField pd = fd.getPersistentField();
fields[i] = pd.get(original);
}
this.state = state;
}
public boolean changed(Object key)
{
MetadataManager man = MetadataManager.getInstance();
ClassDescriptor cd = man.getRepository().getDescriptorFor(key.getClass());
FieldDescriptor[] fds = cd.getFieldDescriptions();
for (int i = 0; i < fds.length; i++)
{
FieldDescriptor fd = fds[i];
PersistentField pd = fd.getPersistentField();
if (fields[i] == null && pd.get(key) == null) continue;
if (fields[i] == null && pd.get(key) != null) return true;
if (!fields[i].equals(pd.get(key))
&& ( this.state == State.PERSISTENT_CLEAN || this.state == State.PERSISTENT_NEW)) return true;
}
return false;
}
public void restore(Object key)
{
MetadataManager man = MetadataManager.getInstance();
ClassDescriptor cd = man.getRepository().getDescriptorFor(key.getClass());
FieldDescriptor[] fds = cd.getFieldDescriptions();
for (int i = 0; i < fds.length; i++)
{
FieldDescriptor fd = fds[i];
PersistentField pd = fd.getPersistentField();
if (fields[i] == null && pd.get(key) == null) continue;
if (fields[i] == null && pd.get(key) != null)
{
pd.set(key, null);
}
if (!fields[i].equals(pd.get(key)))
{
pd.set(key, fields[i]);
}
}
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/dirty/LifeCycleListener.java
Index: LifeCycleListener.java
===================================================================
/* Copyright 2004-2004 The Apache Software Foundation
*
* 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.apache.ojb.broker.dirty;
import org.apache.ojb.broker.PBLifeCycleListener;
import org.apache.ojb.broker.PBLifeCycleEvent;
import org.apache.ojb.broker.PersistenceBrokerException;
public class LifeCycleListener implements PBLifeCycleListener
{
private Tracker tracker;
LifeCycleListener(Tracker t)
{
tracker = t;
}
public void beforeInsert(PBLifeCycleEvent event) throws PersistenceBrokerException
{
}
public void afterInsert(PBLifeCycleEvent event) throws PersistenceBrokerException
{
tracker.inserted(event.getTarget());
}
public void beforeUpdate(PBLifeCycleEvent event) throws PersistenceBrokerException
{
}
public void afterUpdate(PBLifeCycleEvent event) throws PersistenceBrokerException
{
tracker.flushed(event.getTarget());
}
public void beforeDelete(PBLifeCycleEvent event) throws PersistenceBrokerException
{
}
public void afterDelete(PBLifeCycleEvent event) throws PersistenceBrokerException
{
tracker.deleted(event.getTarget());
}
public void afterLookup(PBLifeCycleEvent event) throws PersistenceBrokerException
{
tracker.fetched(event.getTarget());
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/dirty/StateListener.java
Index: StateListener.java
===================================================================
/* Copyright 2004-2004 The Apache Software Foundation
*
* 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.apache.ojb.broker.dirty;
import org.apache.ojb.broker.PBStateListener;
import org.apache.ojb.broker.PBStateEvent;
public class StateListener implements PBStateListener
{
private Tracker tracker;
StateListener(Tracker t)
{
tracker = t;
}
public void afterOpen(PBStateEvent event)
{
}
public void beforeBegin(PBStateEvent event)
{
}
/**
* Called after a <tt>PersistenceBroker transaction</tt> was started.
*/
public void afterBegin(PBStateEvent event)
{
tracker.begin();
}
/**
* Called before a <tt>PersistenceBroker commit</tt> was called.
*/
public void beforeCommit(PBStateEvent event)
{
tracker.commit(event.getTriggeringBroker());
}
/**
* Called after a <tt>PersistenceBroker commit</tt> was called.
*/
public void afterCommit(PBStateEvent event)
{
}
/**
* Called before a <tt>PersistenceBroker rollback</tt> was called.
*/
public void beforeRollback(PBStateEvent event)
{
}
/**
* Called after a <tt>PersistenceBroker rollback</tt> was called.
*/
public void afterRollback(PBStateEvent event)
{
}
/**
* Called before the {@link org.apache.ojb.broker.PersistenceBroker}
* instance was returned to pool.
*/
public void beforeClose(PBStateEvent event)
{
}
}
1.1 db-ojb/src/java/org/apache/ojb/broker/dirty/Tracker.java
Index: Tracker.java
===================================================================
/* Copyright 2004-2004 The Apache Software Foundation
*
* 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.apache.ojb.broker.dirty;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.core.proxy.ProxyHelper;
import org.apache.ojb.otm.states.State;
import java.util.Iterator;
import java.util.Map;
import java.util.IdentityHashMap;
public class Tracker
{
private final IdentityHashMap map = new IdentityHashMap();
private boolean flushing = false;
private boolean transactional = true;
/**
* transaction started, begin tracking changes
*/
public void begin()
{
map.clear();
flushing = false;
transactional = true;
}
public void rollback()
{
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();)
{
Map.Entry map_entry = (Map.Entry) iterator.next();
Object key = map_entry.getKey();
Entry entry = (Entry) map_entry.getValue();
entry.restore(key);
}
map.clear();
transactional = false;
}
/**
* About to commit, flush dirty objects!
*/
public void commit(PersistenceBroker broker)
{
flushing = true;
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();)
{
Map.Entry map_entry = (Map.Entry) iterator.next();
Object key = map_entry.getKey();
Entry entry = (Entry) map_entry.getValue();
if (entry.changed(key))
{
broker.store(key);
}
}
map.clear();
flushing = false;
transactional = false;
}
/**
* Called on explicit update. Set target as the
* current instance in entity map, and make it
* persistentclean
*/
public void flushed(Object target)
{
if (flushing || !transactional) return;
map.put(target, new Entry(target, State.PERSISTENT_CLEAN));
}
/**
* inserted during trasnacton, add as persistent clean
*/
public void inserted(Object source)
{
if (!transactional) return;
map.put(source, new Entry(source, State.PERSISTENT_NEW));
}
/**
* Deleted in transaction, add as persistent-deleted
*/
public void deleted(Object source)
{
if (!transactional) return;
map.put(source, new Entry(source, State.PERSISTENT_DELETED));
}
/**
* fetched during transaction, add as persistent clean
*/
public void fetched(Object source)
{
if (!transactional) return;
if (ProxyHelper.isProxy(source)) return;
map.put(source, new Entry(source, State.PERSISTENT_CLEAN));
}
}
1.1 db-ojb/src/test/org/apache/ojb/broker/dirty/DirtyTest.java
Index: DirtyTest.java
===================================================================
package org.apache.ojb.broker.dirty;
import junit.framework.TestCase;
import org.apache.ojb.broker.Article;
import org.apache.ojb.broker.Identity;
import org.apache.ojb.broker.InterfaceArticle;
import org.apache.ojb.broker.PersistenceBroker;
import org.apache.ojb.broker.Person;
import org.apache.ojb.broker.ProductGroupWithCollectionProxy;
import org.apache.ojb.broker.core.proxy.CollectionProxy;
import org.apache.ojb.broker.core.proxy.ProxyHelper;
import java.util.List;
public class DirtyTest extends TestCase
{
public void testSimpleInsert() throws Exception
{
Person p = new Person();
p.setFirstname("brian");
PersistenceBroker pb = DirtyPersistenceBrokerFactory.defaultPersistenceBroker();
pb.beginTransaction();
pb.store(p);
pb.commitTransaction();
pb.clearCache();
Identity id = new Identity(p, pb);
Person same = (Person) pb.getObjectByIdentity(id);
assertEquals("brian", same.getFirstname());
pb.close();
}
public void testSimpleUpdate() throws Exception
{
Person p = new Person();
p.setFirstname("brian");
PersistenceBroker pb = DirtyPersistenceBrokerFactory.defaultPersistenceBroker();
pb.beginTransaction();
pb.store(p);
pb.commitTransaction();
pb.clearCache();
pb.beginTransaction();
Identity id = new Identity(p, pb);
Person same = (Person) pb.getObjectByIdentity(id);
same.setFirstname("george");
pb.commitTransaction();
pb.clearCache();
same = (Person) pb.getObjectByIdentity(id);
assertEquals("george", same.getFirstname());
pb.close();
}
public void testProxyWorks() throws Exception
{
ProductGroupWithCollectionProxy pg = new ProductGroupWithCollectionProxy();
pg.setGroupName("groupName");
InterfaceArticle a = Article.createInstance();
a.setProductGroup(pg);
a.setArticleName("name");
pg.add(a);
PersistenceBroker pb = DirtyPersistenceBrokerFactory.defaultPersistenceBroker();
pb.beginTransaction();
pb.store(pg);
pb.store(a);
pb.commitTransaction();
pb.clearCache();
pb.beginTransaction();
pg = (ProductGroupWithCollectionProxy) pb.getObjectByIdentity(new Identity(pg, pb));
List articles = pg.getAllArticlesInGroup();
assertTrue(ProxyHelper.isCollectionProxy(articles));
CollectionProxy proxy = (CollectionProxy)articles;
assertFalse(proxy.isLoaded());
a = (InterfaceArticle) articles.get(0);
a.setArticleName("new name");
pb.commitTransaction();
pb.clearCache();
a = (Article) pb.getObjectByIdentity(new Identity(a, pb));
assertEquals("new name", a.getArticleName());
pb.close();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org