001 /* 002 Copyright (C) 2002 Renaud Pawlak <renaud@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.aspects.integrity; 019 020 import java.util.Collection; 021 import java.util.Iterator; 022 import java.util.List; 023 import org.aopalliance.intercept.ConstructorInvocation; 024 import org.aopalliance.intercept.MethodInvocation; 025 import org.apache.log4j.Logger; 026 import org.objectweb.jac.core.AspectComponent; 027 import org.objectweb.jac.core.Collaboration; 028 import org.objectweb.jac.core.Interaction; 029 import org.objectweb.jac.core.NameRepository; 030 import org.objectweb.jac.core.ObjectRepository; 031 import org.objectweb.jac.core.Wrapper; 032 import org.objectweb.jac.core.rtti.ClassItem; 033 import org.objectweb.jac.core.rtti.CollectionItem; 034 import org.objectweb.jac.core.rtti.FieldItem; 035 036 /** 037 * This wrapper manages repository collections. 038 */ 039 040 public class RepositoryWrapper extends Wrapper { 041 static final Logger logger = Logger.getLogger("integrity.repository"); 042 043 public static final int ADDER = 0; 044 public static final int REMOVER = 1; 045 046 Object repository; 047 String repositoryName; 048 CollectionItem collection; 049 FieldItem field; 050 int type = ADDER; 051 052 public RepositoryWrapper( 053 AspectComponent ac, 054 String repositoryName, 055 CollectionItem collection, 056 FieldItem field, 057 int type) 058 { 059 super(ac); 060 this.repositoryName = repositoryName; 061 this.collection = collection; 062 this.field = field; 063 this.type=type; 064 } 065 066 /** 067 * Adds the object added to field to the repository 068 */ 069 public Object addToRepository(Interaction interaction) { 070 Object ret = doAddToRepository(interaction); 071 if (IntegrityAC.isAddToRepositoryEnabled(collection)) { 072 logger.debug("checking for repository on " + interaction.method); 073 if (repository == null) 074 repository = NameRepository.get().getObject(repositoryName); 075 Object toAdd = interaction.args[0]; 076 077 if (toAdd != null 078 && repository != null 079 && !collection.getActualCollection(repository).contains(toAdd)) { 080 logger.debug("addToRepository(" + repositoryName + ")"); 081 collection.addThroughAdder(repository, toAdd); 082 } 083 } else { 084 logger.debug(collection + " disabled"); 085 } 086 return ret; 087 } 088 089 /** 090 * Disables addToRepository 091 */ 092 public Object doAddToRepository(Interaction interaction) { 093 IntegrityAC.disableAddToRepository(collection); 094 logger.debug("doAddToRepository " + collection); 095 try { 096 return proceed(interaction); 097 } finally { 098 IntegrityAC.enableAddToRepository(collection); 099 } 100 } 101 102 public Object removeFromRepository(Interaction interaction) { 103 logger.debug("removeFromRepository(" + repositoryName + ")"); 104 Object toRemove = interaction.args[0]; 105 FieldItem target = collection != null ? collection : field; 106 List constraints = (List) target.getAttribute(IntegrityAC.CONSTRAINTS); 107 if (constraints == null) 108 return proceed(interaction); 109 Iterator it = constraints.iterator(); 110 while (it.hasNext()) { 111 Constraint constraint = (Constraint) it.next(); 112 Collection objects = 113 ObjectRepository.getObjectsWhere( 114 constraint.relation.getClassItem(), 115 constraint.relation, 116 toRemove); 117 logger.debug(" " + constraint + " => " + objects); 118 switch (constraint.constraint) { 119 case Constraint.DELETE_CASCADE : 120 break; 121 case Constraint.SET_NULL : 122 Iterator it2 = objects.iterator(); 123 while (it2.hasNext()) { 124 Object substance = it2.next(); 125 logger.debug( 126 " SET_NULL " 127 + substance + "." + constraint.relation); 128 try { 129 if (constraint.relation 130 instanceof CollectionItem) { 131 ((CollectionItem) constraint.relation) 132 .removeThroughRemover( 133 substance, 134 toRemove); 135 } else { 136 constraint.relation.setThroughWriter( 137 substance, 138 null); 139 } 140 } catch (Exception e) { 141 logger.error( 142 "Failed to enforce SET_NULL constraint for " 143 + constraint.relation + " on " + substance,e); 144 } 145 } 146 break; 147 case Constraint.FORBIDDEN : 148 if (objects.size() > 0) 149 throw new RuntimeException( 150 "Cannot delete " 151 + toRemove + " from " + target.getLongName() 152 + " because of constraint " + constraint); 153 break; 154 default : 155 logger.warn( 156 "Unknown constraint type " + constraint.constraint); 157 } 158 } 159 160 return proceed(interaction); 161 } 162 163 public Object invoke(MethodInvocation invocation) throws Throwable { 164 Interaction interaction = (Interaction) invocation; 165 switch (type) { 166 case ADDER: 167 return addToRepository(interaction); 168 case REMOVER: 169 return removeFromRepository(interaction); 170 default: 171 throw new Exception("Unknown RepositoryWrapper type: "+type); 172 } 173 } 174 } 175