001 /* 002 Copyright (C) 2003 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 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA */ 018 019 package org.objectweb.jac.core; 020 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.Map; 024 import org.apache.log4j.Logger; 025 import org.objectweb.jac.core.ACManager; 026 027 /** 028 * This class is the root class for the composite aspect components 029 * defined by JAC aspect programmers. 030 * 031 * <p>A composite aspect is a kind of facade that factorizes and 032 * simplifies the use of a set of sub-aspects (called chidren 033 * aspects). For instance, the user and authentication aspects of JAC 034 * can be factorized in on unique aspect in order to simplify the use 035 * (factorization) and to eliminate useless dependencies. 036 * 037 * @author <a href="mailto:renaud@aopsys.com">Renaud Pawlak</a> */ 038 039 public class CompositeAspectComponent extends AspectComponent { 040 static Logger logger = Logger.getLogger("aspects.composite"); 041 042 Map childClasses=new HashMap(); 043 Map children=new HashMap(); 044 Map defaultConfigs=new HashMap(); 045 046 /** 047 * The default constructor. 048 * 049 * <p>Should be redefined be the programmer in order to declare the child aspects. 050 * 051 * @see #addChild(String,Class) */ 052 public CompositeAspectComponent () { 053 super(); 054 } 055 056 /** 057 * Invoke this method in the constructor in order to disable the 058 * application of the default configuration for a given child 059 * aspect component. 060 * 061 * <p>Note that the default configs are defined by the 062 * <code>getDefaultConfig</code> method. By default, all the 063 * children's default configs are applied. */ 064 protected void disableDefaultConfigs(String childName) { 065 defaultConfigs.put(childName,Boolean.FALSE); 066 } 067 068 /** 069 * Declares a new child for this composite (should be invoked from 070 * the constructor). 071 * 072 * @param name the child's name (can be any unique id) 073 * @param acClass the aspect component's class of the child */ 074 protected void addChild(String name,Class acClass) { 075 logger.debug("addChild("+name+ 076 ","+acClass+")"+" to composite "+getName()); 077 childClasses.put(name,acClass); 078 } 079 080 /** 081 * Removes a child for this composite (do not use unless you know 082 * what you are doing). 083 * 084 * @param name the child's name as given in the {@link 085 * #addChild(String,Class)} method */ 086 protected void removeChild(String name) { 087 logger.debug("removeChild("+name+ 088 ") from composite "+getName()+")"); 089 childClasses.remove(name); } 090 091 /** 092 * Returns a child aspect component from its name. 093 * 094 * <p>This method should be used in configuration methods of the 095 * composite to delegate the configuration to the child 096 * aspects. */ 097 protected AspectComponent getChild(String name) { 098 logger.debug("getChild("+name+ 099 ") in composite "+getName()); 100 return (AspectComponent)children.get(name); 101 } 102 103 /** 104 * Returns the internal name of a child (applicationName.name). 105 * 106 * @param name the child's name */ 107 protected String getChildActualName(String name) { 108 logger.debug("getChildActualName("+name+ 109 ") in composite "+getName()); 110 return getChild(name).getApplication()+"."+name; 111 } 112 113 /** 114 * Returns the internal name of a child, as it is registered in 115 * the JAC ACManager. 116 * 117 * <p>Note that this method will return null if the child is not 118 * yet registered in the AC manager. This is the case at 119 * configuration time. Thus, {@link #getChildActualName(String)} 120 * should be prefered. 121 * 122 * @param name the child's name */ 123 protected String getChildRegisteredName(String name) { 124 logger.debug("getChildActualName("+name+ 125 ") in composite "+getName()); 126 return ACManager.getACM().getName(getChild(name)); 127 } 128 129 /** 130 * This method is upcalled by the system when the composite aspect 131 * is about to be configured. 132 * 133 * <p>This method instantiates all the declared children (with 134 * {@link #addChild(String,Class)} method. */ 135 public void beforeConfiguration() throws Exception { 136 logger.debug("beforeConfiguration()"+ 137 " for composite "+getName()); 138 Iterator it=childClasses.entrySet().iterator(); 139 while(it.hasNext()) { 140 Map.Entry entry=(Map.Entry)it.next(); 141 Class acClass=(Class)entry.getValue(); 142 AspectComponent instance = (AspectComponent) acClass.newInstance(); 143 instance.setApplication(getApplication()); 144 children.put(entry.getKey(),instance); 145 // apply the default configurations if needed 146 String[] defaults = instance.getDefaultConfigs(); 147 for (int i=0; i<defaults.length; i++) { 148 instance.configure((String)entry.getKey(),defaults[i]); 149 } 150 } 151 152 } 153 154 /** 155 * This method is upcalled by the system when the composite aspect 156 * is actually registered in the AC manager. 157 * 158 * <p>It symply registers all the children with the right 159 * names. */ 160 public final void doRegister() { 161 logger.debug("registerChildren()"+ 162 " for composite "+getName()); 163 Iterator it=children.entrySet().iterator(); 164 while(it.hasNext()) { 165 Map.Entry entry=(Map.Entry)it.next(); 166 AspectComponent ac=(AspectComponent)entry.getValue(); 167 ACManager.get().register( ac.getApplication() + 168 "." + entry.getKey(), ac ); 169 } 170 logger.debug("end registerChildren() => ACM dump: "+ 171 ACManager.get().getPrintableString()); 172 173 } 174 175 176 /** 177 * This method is upcalled by the system when the composite aspect 178 * is actually unregistered in the AC manager. 179 * 180 * <p>It symply unregisters all the children. */ 181 public final void doUnregister() { 182 logger.debug("unregisterChildren()"+ 183 " for composite "+getName()); 184 Iterator it=children.entrySet().iterator(); 185 while(it.hasNext()) { 186 Map.Entry entry=(Map.Entry)it.next(); 187 AspectComponent ac=(AspectComponent)entry.getValue(); 188 ACManager.get().unregister( ac.getApplication() + 189 "." + entry.getKey() ); 190 } 191 } 192 193 }