Index: topia/src/java/org/codelutin/topia/AbstractTopiaPersistenceService.java diff -u topia/src/java/org/codelutin/topia/AbstractTopiaPersistenceService.java:1.10 topia/src/java/org/codelutin/topia/AbstractTopiaPersistenceService.java:1.11 --- topia/src/java/org/codelutin/topia/AbstractTopiaPersistenceService.java:1.10 Fri Jul 22 16:57:57 2005 +++ topia/src/java/org/codelutin/topia/AbstractTopiaPersistenceService.java Thu Aug 4 20:59:31 2005 @@ -23,10 +23,10 @@ * * @author Benjamin Poussin * Copyright Code Lutin - * @version $Revision: 1.10 $ + * @version $Revision: 1.11 $ * - * Mise a jour: $Date: 2005/07/22 16:57:57 $ - * par : $Author: thimel $ + * Mise a jour: $Date: 2005/08/04 20:59:31 $ + * par : $Author: bpoussin $ */ package org.codelutin.topia; @@ -46,7 +46,8 @@ * subscribers list. */ public void addTopiaEntityListener(TopiaEntityListener l) { - getContext().getListeners().add(this, l); + getContext().getListeners().addCategory(getContext().getClass(), getEntityClass()); + getContext().getListeners().add(getEntityClass(), l); } /** @@ -55,7 +56,7 @@ * subscribers. */ public void removeTopiaEntityListener(TopiaEntityListener l) { - getContext().getListeners().remove(this, l); + getContext().getListeners().remove(getEntityClass(), l); } /** @@ -67,7 +68,7 @@ Entity result = null; result = (Entity)getContext().getPersistenceHelper().create(getEntityClass()); try { - getContext().getListeners().fire(this, "entityAdded", new TopiaEntityEvent(this, result)); + getContext().getListeners().fire(this.getClass(), "entityAdded", new TopiaEntityEvent(this, result)); } catch (Exception eee) { log.log(Level.FINE, "Erreur durant l'envoie de l'event de creation d'entity", eee); } @@ -76,13 +77,18 @@ public Entity makePersistent(Entity topiaEntity)throws TopiaException{ Entity result = (Entity)getContext().getPersistenceHelper().makePersistent(topiaEntity); + try { + getContext().getListeners().fire(this.getClass(), "entityAdded", new TopiaEntityEvent(this, result)); + } catch (Exception eee) { + log.log(Level.FINE, "Erreur durant l'envoie de l'event de creation d'entity", eee); + } return result; } public Entity update(Entity topiaEntity) throws TopiaException{ Entity result = (Entity)getContext().getPersistenceHelper().update(topiaEntity); try { - getContext().getListeners().fire(this, "entityModified", new TopiaEntityEvent(this, result)); + getContext().getListeners().fire(this.getClass(), "entityModified", new TopiaEntityEvent(this, result)); } catch (Exception eee) { log.log(Level.FINE, "Erreur durant l'envoie de l'event de modification d'entity", eee); } @@ -92,7 +98,7 @@ public void delete(Entity topiaEntity) throws TopiaException{ getContext().getPersistenceHelper().delete(topiaEntity); try { - getContext().getListeners().fire(this, "entityRemoved", new TopiaEntityEvent(this, topiaEntity)); + getContext().getListeners().fire(this.getClass(), "entityRemoved", new TopiaEntityEvent(this, topiaEntity)); } catch (Exception eee) { log.log(Level.FINE, "Erreur durant l'envoie de l'event de suppression d'entity", eee); } @@ -112,7 +118,7 @@ */ public Entity findBy_TopiaId_(String topiaId) throws TopiaException { // TODO Arno : Tester le topiaId avant de faire le find !!! (doit etre du type de ) - return (Entity)getContext().getPersistenceHelper().findByTopiaId(topiaId); + return (Entity)getContext().getPersistenceHelper().findByTopiaId(topiaId); } Index: topia/src/java/org/codelutin/topia/TopiaContext.java diff -u topia/src/java/org/codelutin/topia/TopiaContext.java:1.44 topia/src/java/org/codelutin/topia/TopiaContext.java:1.45 --- topia/src/java/org/codelutin/topia/TopiaContext.java:1.44 Wed Aug 3 16:17:10 2005 +++ topia/src/java/org/codelutin/topia/TopiaContext.java Thu Aug 4 20:59:31 2005 @@ -23,38 +23,40 @@ * * @author Benjamin Poussin * Copyright Code Lutin -* @version $Revision: 1.44 $ +* @version $Revision: 1.45 $ * -* Mise a jour: $Date: 2005/08/03 16:17:10 $ -* par : $Author: thimel $ +* Mise a jour: $Date: 2005/08/04 20:59:31 $ +* par : $Author: bpoussin $ */ package org.codelutin.topia; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.Map; import java.util.Properties; - +import java.util.Set; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; - import org.codelutin.topia.distribution.DistributionHelper; import org.codelutin.topia.hook.HookHelper; import org.codelutin.topia.persistence.PersistenceHelper; -import org.codelutin.topia.security.TopiaSecurityHelper; -// import org.codelutin.topia.security.TopiaGroupPrincipal; -// import org.codelutin.topia.security.TopiaPermission; -// import org.codelutin.topia.security.TopiaPermissionEvent; -// import org.codelutin.topia.security.TopiaPermissionListener; -// import org.codelutin.topia.security.TopiaSecurityException; -// import org.codelutin.topia.security.TopiaUserPrincipal; -import org.codelutin.topia.persistence.TransactionHelper; import org.codelutin.topia.persistence.TopiaTransaction; +import org.codelutin.topia.persistence.TransactionHelper; +import org.codelutin.topia.security.TopiaGroupPrincipal; +import org.codelutin.topia.security.TopiaPermission; +import org.codelutin.topia.security.TopiaPermissionEvent; +import org.codelutin.topia.security.TopiaPermissionListener; +import org.codelutin.topia.security.TopiaSecurityException; +import org.codelutin.topia.security.TopiaSecurityHelper; +import org.codelutin.topia.security.TopiaUserPrincipal; import org.codelutin.util.CategorisedListenerSet; -public abstract class TopiaContext { // TopiaContext +public abstract class TopiaContext implements TopiaEntityListener { // TopiaContext /** to use log facility, just put in your code: log.info(\"...\"); */ static private Logger log = Logger.getLogger("org.codelutin.topia.TopiaContext"); @@ -76,7 +78,7 @@ protected TransactionHelper transactionHelper = null; protected TopiaTransaction transaction = null; - + protected TopiaAssociationManager associationManager = null; protected CategorisedListenerSet listeners = new CategorisedListenerSet( @@ -87,6 +89,13 @@ protected HashMap cacheService = new HashMap(); + /** les entities ajoutées durant la transaction */ + protected HashMap> addedTopiaEntity = new HashMap>(); + /** les entities modifiées durant la transaction */ + protected HashMap> modifiedTopiaEntity = new HashMap>(); + /** les entities supprimées durant la transaction */ + protected HashMap> removedTopiaEntity = new HashMap>(); + public abstract String getContextName(); /** @@ -124,11 +133,69 @@ } /** + * Permet de recuperer la liste qui contient les entites pour un certain type + * si la liste n'existait pas, elle est creer et ajoutee + */ + protected Set getEventEntityList(HashMap> map, Class clazz){ + Set result = map.get(clazz); + if(result == null){ + map.put(clazz, result = new HashSet()); + } + return result; + } + + /** + * Appelé lorsqu'une ou plusieurs entités ont été créées + */ + public void entityAdded(TopiaEntityEvent event){ + for(TopiaEntity e:event.getTopiaEntities()){ + Class clazz = e.getClass(); + Set added = getEventEntityList(addedTopiaEntity, clazz); + added.add(e); + // il a ete ajoute ou remis s'il existait precedement + // il faut l'enlever de removed + Set removed = getEventEntityList(removedTopiaEntity, clazz); + removed.remove(added); + } + } + /** + * Appelé lorsqu'une ou plusieurs entités ont été modifiées + */ + public void entityModified(TopiaEntityEvent event){ + for(TopiaEntity e:event.getTopiaEntities()){ + Class clazz = e.getClass(); + Set added = getEventEntityList(modifiedTopiaEntity, clazz); + // on ne l'ajoute dans modifier que s'il n'est pas deja dans added + if(!added.contains(e)){ + Set modified = getEventEntityList(modifiedTopiaEntity, clazz); + modified.add(e); + } + } + } + + /** + * Appelé lorsqu'une ou plusieurs entités ont été supprimées + */ + public void entityRemoved(TopiaEntityEvent event){ + for(TopiaEntity e:event.getTopiaEntities()){ + Class clazz = e.getClass(); + Set removed = getEventEntityList(removedTopiaEntity, clazz); + removed.add(e); + // il a ete supprimé il faut l'enlever des autres + Set added = getEventEntityList(modifiedTopiaEntity, clazz); + Set modified = getEventEntityList(modifiedTopiaEntity, clazz); + added.remove(e); + modified.remove(e); + } + } + + + /** * Adds a new TopiaEntityListener to the subscribers list. * @param topiaEntityListener - the TopiaEntityListener to add to the subscribers list. */ public void addTopiaEntityListener(TopiaEntityListener l) { - getListeners().add(this, l); + getListeners().add(this.getClass(), l); } /** @@ -136,7 +203,7 @@ * @param topiaEntityListener - the TopiaEntityListener to remove from the subscribers. */ public void removeTopiaEntityListener(TopiaEntityListener l) { - getListeners().remove(this, l); + getListeners().remove(this.getClass(), l); } abstract protected TopiaContextChild createChild(); @@ -158,7 +225,57 @@ if(getTransaction() == null){ throw new TopiaException("No transaction found"); } + // il faut commencer par commiter toutes les sous-transaction + // pour que la mise a jour des longdates se fasse bien, ainsi + // que la synchro des cache entre parent et enfant + for(TopiaTransaction tt: getTransaction().getChilds()){ + TopiaContext context = TopiaContextFactory.getContext(tt); + context.commitTransaction(); + } + getPersistenceHelper().commitTransaction(); + + // il faut prevenir les listeners du contextParent de tous les + // changements + TopiaContext parent = getParentContext(); + if(parent != null){ + for(Map.Entry> set:addedTopiaEntity.entrySet()){ + Class clazz = set.getKey(); + Set entities = set.getValue(); + if(entities.size() > 0){ + // on previent les listeners du bon persistence service (clazz) + try{ + getListeners().fire(clazz, "entityAdded", new TopiaEntityEvent(this, entities)); + }catch(Exception eee){ + log.log(Level.WARNING, "Probleme lors de la propagation d'un event", eee); + } + } + } + for(Map.Entry> set:modifiedTopiaEntity.entrySet()){ + Class clazz = set.getKey(); + Set entities = set.getValue(); + if(entities.size() > 0){ + // on previent les listeners du bon persistence service (clazz) + try{ + getListeners().fire(clazz, "entityModified", new TopiaEntityEvent(this, entities)); + }catch(Exception eee){ + log.log(Level.WARNING, "Probleme lors de la propagation d'un event", eee); + } + } + } + for(Map.Entry> set:removedTopiaEntity.entrySet()){ + Class clazz = set.getKey(); + Set entities = set.getValue(); + if(entities.size() > 0){ + // on previent les listeners du bon persistence service (clazz) + try{ + getListeners().fire(clazz, "entityRemoved", new TopiaEntityEvent(this, entities)); + }catch(Exception eee){ + log.log(Level.WARNING, "Probleme lors de la propagation d'un event", eee); + } + } + } + } } public void rollbackTransaction() throws TopiaException { @@ -166,6 +283,38 @@ throw new TopiaException("No transaction found"); } getPersistenceHelper().rollbackTransaction(); + // il faut aussi rollbacker toutes les sous-transaction + for(TopiaTransaction tt: getTransaction().getChilds()){ + TopiaContext context = TopiaContextFactory.getContext(tt); + context.rollbackTransaction(); + } + + // il faut abondonner tous les events conservé + for(Set set:addedTopiaEntity.values()){ + set.clear(); + } + for(Set set:modifiedTopiaEntity.values()){ + set.clear(); + } + for(Set set:removedTopiaEntity.values()){ + set.clear(); + } + } + + /** + * Recupere le context parent + * @return le context pere ou null + */ + public TopiaContextChild getParentContext(){ + TopiaContextChild result = null; + TopiaTransaction tt = getTransaction(); + if(tt != null){ + tt = tt.getParent(); + if(tt != null){ + result = (TopiaContextChild)TopiaContextFactory.getContext(tt); + } + } + return result; } public TopiaTransaction getTransaction(){ @@ -174,6 +323,8 @@ public void setTransaction(TopiaTransaction transaction){ this.transaction = transaction; + // une transaction n'appartient qu'a un Context et un seul + TopiaContextFactory.setContext(transaction, this); } /** @@ -196,8 +347,14 @@ throws TopiaException { String className = entityClass.getName() + "PersistenceService"; Class interfacez = Util.getClazz(className); - Object result = getService(interfacez, true); - return (TopiaPersistenceService) result; + TopiaPersistenceService result = + (TopiaPersistenceService)getService(interfacez, true); + + // on s'enregistre comme listener sur tout les persistences services + // pour que lors du commit on puisse rejouer les modifications sur le + // context pere + result.addTopiaEntityListener(this); + return result; } /** @@ -253,7 +410,7 @@ } /** - * Retourne l'objet gérant les associations entre les entités + * Retourne l'objet gérant les associations entre les entités */ public TopiaAssociationManager getAssociationManager() { if (associationManager == null) Index: topia/src/java/org/codelutin/topia/TopiaContextFactory.java diff -u topia/src/java/org/codelutin/topia/TopiaContextFactory.java:1.9 topia/src/java/org/codelutin/topia/TopiaContextFactory.java:1.10 --- topia/src/java/org/codelutin/topia/TopiaContextFactory.java:1.9 Fri Jul 29 17:18:45 2005 +++ topia/src/java/org/codelutin/topia/TopiaContextFactory.java Thu Aug 4 20:59:31 2005 @@ -23,23 +23,24 @@ * * @author Benjamin Poussin * Copyright Code Lutin - * @version $Revision: 1.9 $ + * @version $Revision: 1.10 $ * - * Mise a jour: $Date: 2005/07/29 17:18:45 $ - * par : $Author: thimel $ + * Mise a jour: $Date: 2005/08/04 20:59:31 $ + * par : $Author: bpoussin $ */ package org.codelutin.topia; -import java.util.Properties; -import java.util.HashMap; import java.lang.reflect.Constructor; import java.net.URL; -import java.util.logging.Logger; +import java.util.HashMap; import java.util.logging.Level; - +import java.util.logging.Logger; +import java.util.Properties; +import java.util.WeakHashMap; import org.codelutin.util.RecursiveProperties; import org.codelutin.util.Resource; +import org.codelutin.topia.persistence.TopiaTransaction; /** * Class permettant de récupérer le context de l'application. Pour un fichier de @@ -47,8 +48,28 @@ */ public class TopiaContextFactory { // TopiaContextFactory + protected static WeakHashMap ttcontexts= new WeakHashMap(); + /** Static context */ protected static HashMap contexts = new HashMap(); + + /** + * Methode du framework permettant de retrouver le context associé a une + * transaction + */ + static public TopiaContext getContext(TopiaTransaction tt){ + return ttcontexts.get(tt); + } + + /** + * Methode du framework qui permet de changer le context associe a une + * transaction. Normalement tout changement de transaction se fait au + * travers de la methode TopiaContext.setTransaction, cette methode + * appelle donc celle-ci + */ + static public TopiaContext setContext(TopiaTransaction tt, TopiaContext context){ + return ttcontexts.put(tt, context); + } /** * Donne le context par defaut, c'est a dire que le fichier de propriété Index: topia/src/java/org/codelutin/topia/TopiaEntityEvent.java diff -u topia/src/java/org/codelutin/topia/TopiaEntityEvent.java:1.3 topia/src/java/org/codelutin/topia/TopiaEntityEvent.java:1.4 --- topia/src/java/org/codelutin/topia/TopiaEntityEvent.java:1.3 Wed Jul 20 12:49:52 2005 +++ topia/src/java/org/codelutin/topia/TopiaEntityEvent.java Thu Aug 4 20:59:31 2005 @@ -23,9 +23,9 @@ * * @author Benjamin Poussin * Copyright Code Lutin - * @version $Revision: 1.3 $ + * @version $Revision: 1.4 $ * - * Mise a jour: $Date: 2005/07/20 12:49:52 $ + * Mise a jour: $Date: 2005/08/04 20:59:31 $ * par : $Author: bpoussin $ */ @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Collection; import java.util.Date; import java.util.EventObject; import java.util.List; @@ -40,7 +41,7 @@ public class TopiaEntityEvent extends EventObject { // TopiaEntityEvent protected long date = 0; - protected List entities = null; + protected Collection entities = null; /** * @param source l'objet d'ou provient l'event @@ -49,7 +50,7 @@ public TopiaEntityEvent(Object source, TopiaEntity entity){ super(source); date = System.currentTimeMillis(); - List entities = new ArrayList(); + ArrayList entities = new ArrayList(); entities.add(entity); this.entities = Collections.unmodifiableList(entities); } @@ -58,17 +59,17 @@ * @param source l'objet d'ou provient l'event * @param entities la liste des entitées sur lequel porte l'event */ - public TopiaEntityEvent(Object source, List entities){ + public TopiaEntityEvent(Object source, Collection entities){ super(source); date = System.currentTimeMillis(); - this.entities = Collections.unmodifiableList(entities); + this.entities = Collections.unmodifiableCollection(entities); } /** * Retourne la liste des entitées sur lequel porte l'event * @return une liste non modifiable d'entité */ - public List getTopiaEntities(){ + public Collection getTopiaEntities(){ return entities; }