001    /*
002      Copyright (C) 2002 Julien van Malderen, 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.Iterator;
021    import java.util.Vector;
022    import org.aopalliance.intercept.ConstructorInvocation;
023    import org.aopalliance.intercept.MethodInvocation;
024    import org.apache.log4j.Logger;
025    import org.objectweb.jac.core.AspectComponent;
026    import org.objectweb.jac.core.Interaction;
027    import org.objectweb.jac.core.Wrapper;
028    import org.objectweb.jac.core.rtti.ClassItem;
029    import org.objectweb.jac.core.rtti.ClassRepository;
030    import org.objectweb.jac.core.rtti.FieldItem;
031    import org.objectweb.jac.core.rtti.MethodItem;
032    
033    /**
034     * This wrapper provides a constraints scheme to limit fields
035     * modifications.
036     */
037    
038    public class ConstraintWrapper extends Wrapper {
039        static final Logger logger = Logger.getLogger("integrity.conditions");
040    
041            public ConstraintWrapper(AspectComponent ac) {
042                    super(ac);
043            }
044    
045            private void invokeTest(
046                    MethodItem method,
047                    FieldItem field,
048                    Object[] args,
049                    String errorMsg)
050                    throws Exception 
051        {
052                    Boolean result = (Boolean) method.invoke(null, args);
053    
054                    if (result == null)
055                            throw new Exception("The constraint " + method + " does not exist");
056    
057                    if (!result.booleanValue()) {
058                            if ((errorMsg == null) || errorMsg.length() == 0)
059                                    throw new Exception(
060                                            "The constraint "
061                                                    + method
062                                                    + " has not been validated for "
063                                                    + field);
064                            throw new Exception(field + ": " + errorMsg);
065                    }
066            }
067    
068            /**
069             * This wrapping method checks if pre and post conditions are
070             * validated for modified fields.
071             */
072    
073            public Object testConditions(Interaction interaction) throws Exception {
074                    logger.debug(
075                            "entering test conditions for " + interaction.method);
076    
077                    IntegrityAC ac = (IntegrityAC) getAspectComponent();
078                    String fieldName =
079                            ((MethodItem) interaction.method).getWrittenFields()[0].getName();
080                    ClassItem curClass =
081                            ClassRepository.get().getClass(interaction.wrappee);
082                    FieldItem field = null;
083                    Vector preList = null;
084    
085                    // get the pre list from the superclasses if not defined here
086                    while (preList == null && curClass != null) {
087                            field = curClass.getField(fieldName);
088                            preList = (Vector) ac.preConditionsFields.get(field);
089                            logger.debug(
090                                    field.getClassItem() + "." + field + " => " + preList);
091                            curClass = curClass.getSuperclass();
092                    }
093    
094                    Vector postList = null;
095                    curClass = ClassRepository.get().getClass(interaction.wrappee);
096    
097                    // get the post list from the superclasses if not defined here
098                    while (postList == null && curClass != null) {
099                            field = curClass.getField(fieldName);
100                            postList = (Vector) ac.postConditionsFields.get(field);
101                            logger.debug(
102                                    field.getClassItem() + "." + field + " => " + preList);
103                            curClass = curClass.getSuperclass();
104                    }
105    
106                    if (preList != null) {
107                            Iterator i = preList.iterator();
108                Object currentFieldValue = 
109                    field.getThroughAccessor(interaction.wrappee);
110                            while (i.hasNext()) {
111                                    ConstraintDescriptor conditionToTest =
112                                            (ConstraintDescriptor) i.next();
113                                    logger.debug(
114                                            "testing pre " + conditionToTest.getConstraint());
115                                    invokeTest(
116                                            conditionToTest.getConstraint(),
117                                            field,
118                                            new Object[] {
119                                                    interaction.wrappee,
120                                                    field,
121                                                    currentFieldValue,
122                                                    conditionToTest.getParams()},
123                                            conditionToTest.getErrorMsg());
124                            }
125                    }
126    
127                    if (postList != null) {
128                            Iterator i = postList.iterator();
129                            while (i.hasNext()) {
130                                    ConstraintDescriptor conditionToTest =
131                                            (ConstraintDescriptor) i.next();
132                                    logger.debug(
133                                            "testing post " + conditionToTest.getConstraint());
134                                    invokeTest(
135                                            conditionToTest.getConstraint(),
136                                            field,
137                                            new Object[] {
138                                                    interaction.wrappee,
139                                                    field,
140                                                    interaction.args[0],
141                                                    conditionToTest.getParams()},
142                                            conditionToTest.getErrorMsg());
143                            }
144                    }
145    
146                    return proceed(interaction);
147            }
148    
149            public Object invoke(MethodInvocation invocation) throws Throwable {
150                    return testConditions((Interaction) invocation);
151            }
152    }