001 /* 002 Copyright (C) 2001-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.*; 022 import org.apache.log4j.Logger; 023 import org.objectweb.jac.core.rtti.*; 024 import org.objectweb.jac.util.*; 025 026 /** 027 * @author <a href="mailto:pawlak@cnam.fr">Renaud Pawlak</a> 028 */ 029 030 /** 031 * This class manages all the aspect components that are present in 032 * the JAC system. 033 * 034 * <p>When a new aspect component is registered, it is 035 * woven regarding its weaving properties. Once woven, the aspect 036 * component manager dispatches all the events of the 037 * <code>BaseProgramListener</code> to it. 038 * 039 * @see AspectComponent 040 * @see BaseProgramListener */ 041 042 public class ACManager extends OrderedRepository 043 implements BaseProgramListener 044 { 045 static Logger logger = Logger.getLogger("jac"); 046 static Logger loggerAspects = Logger.getLogger("aspects"); 047 static Logger loggerACM = Logger.getLogger("acm"); 048 static Logger loggerWuni = Logger.getLogger("wuni"); 049 050 /** 051 * A internally-used flag to bootstrap the AC manager. */ 052 053 public boolean registering = false; 054 055 /** 056 * Get the sole instance of Aspect Component Manager for this 057 * JAC container. 058 * 059 * <p>If this instance does not exist yet, then it is created. 060 * 061 * <p>This method returns a <code>Repository</code> so that the 062 * result must be casted to used specific method of 063 * <code>ACManager</code>. 064 * 065 * @return the aspect component manager of the local container 066 * @see org.objectweb.jac.util.Repository */ 067 068 public static Repository get() { 069 if ( acManager == null ) { 070 acManager = new ACManager(); 071 } 072 return acManager; 073 } 074 075 public static ACManager getACM() { 076 return acManager; 077 } 078 079 public AspectComponent[] getAspectComponents() { 080 return (AspectComponent[])objects.values().toArray(new AspectComponent[0]); 081 } 082 083 /** Stores the sole instance of Aspect Component Manager. */ 084 protected static ACManager acManager = null; 085 086 /** Stores all the declared aspect components. */ 087 protected Hashtable declaredACs = (Hashtable) JacPropLoader.declaredACs; 088 089 static { 090 Runtime.getRuntime().addShutdownHook( 091 new Thread() { 092 public void run() { 093 if (acManager!=null) { 094 logger.info("JAC system shutdown: notifying all ACs..."); 095 acManager.onExit(); 096 } 097 logger.info("Bye bye."); 098 } 099 } 100 ); 101 //GarbageCollector.init(); 102 } 103 104 /** 105 * Declares a new aspect component. 106 * 107 * @param name the name of the aspect component 108 * @param path its path (must be accessible from the current 109 * classpath) */ 110 111 public void declareAC(String name, String path) { 112 loggerAspects.debug("declaring "+path+" as "+name); 113 declaredACs.put(name, path); 114 } 115 116 public boolean isACDeclared(String name) { 117 if (name==null) return false; 118 return (declaredACs.get(name) != null); 119 } 120 121 /** 122 * Gets a declared aspect component path from its name. 123 * 124 * @param acName the name of the AC 125 * @return the corresponding path, null if not declared */ 126 127 public String getACPathFromName(String acName) { 128 return (String)declaredACs.get(acName); 129 } 130 131 /** 132 * Gets the declared aspect components. 133 * 134 * @return the set of the declared aspect components names */ 135 136 public Set getDeclaredACs() { 137 return declaredACs.keySet(); 138 } 139 140 /** 141 * Registers a declared aspect as is (not linked to an application 142 * and with no configuration). 143 * 144 * @param name the aspect name */ 145 146 public AspectComponent registerDeclaredAC(String name) { 147 AspectComponent ac = null; 148 try { 149 if ( !acManager.isRegistered(name) ) { 150 String className = getACPathFromName(name); 151 loggerAspects.debug("registering the "+name+" ac"); 152 acManager.register( 153 name, ac = (AspectComponent) Class.forName(className).newInstance()); 154 } else { 155 loggerAspects.debug(name+" is already registered"); 156 } 157 } catch (Exception e) { 158 e.printStackTrace(); 159 } 160 return ac; 161 } 162 163 /** 164 * Called by the JAC launcher to create and declare the aspect components 165 * defined in jac.prop. */ 166 167 public static void main(String[] args) throws Throwable { 168 169 ACManager acManager = (ACManager)get(); 170 171 loggerAspects.debug("initializing the AC manager"); 172 173 try { 174 175 // Create the Composition Aspect 176 //String prop1 = JacObject.props.getProperty(compositionAspectProp); 177 AspectComponent ac = null; 178 try { 179 loggerAspects.debug("compositionAspect = "+ 180 JacPropLoader.compositionAspect); 181 loggerAspects.debug("JacPropLoader = "+ 182 Strings.hex(JacPropLoader.class)); 183 JacPropLoader.loadProps(); 184 ac = (AspectComponent) Class.forName( 185 JacPropLoader.compositionAspect ).newInstance(); 186 } catch (Exception e) { 187 e.printStackTrace(); 188 System.exit(1); 189 } 190 acManager.register("JAC_composition_aspect", ac); 191 192 /** Creating the needed aspects. */ 193 194 acManager.registerDeclaredAC("naming"); 195 acManager.registerDeclaredAC("binding"); 196 acManager.registerDeclaredAC("rtti"); 197 // acManager.registerDeclaredAC( "deployment" ); 198 199 } catch (Exception e) { 200 e.printStackTrace(); 201 } 202 203 } 204 205 /** 206 * Returns an AC of a given name for the current application. 207 * @param name aspect's name 208 */ 209 public AspectComponent getAC(String name) { 210 String appName = Collaboration.get().getCurApp(); 211 if (appName==null) { 212 loggerAspects.error("getAC("+name+") cannot work because curApp==null"); 213 } 214 return (AspectComponent)getObject(appName+"."+name); 215 } 216 217 /** 218 * Returns an AC of a given name 219 * @param fullName aspect's full name (<application_name>.<aspect_name>) 220 */ 221 public AspectComponent getACFromFullName(String fullName) { 222 return (AspectComponent)getObject(fullName); 223 } 224 225 /** 226 * The default constructor will set the acManager field to the 227 * right value and bind the JAC internal MOP to it so that it will 228 * be notified of the base program events. 229 * 230 * @see BaseProgramListener */ 231 232 public ACManager () { 233 } 234 235 /** 236 * Dispatch this event to all the registered Aspect Components. 237 * 238 * @param newInstance the remotly created instance 239 * @param name the original remote name 240 * @see AspectComponent#whenRemoteInstantiation(Wrappee,String) 241 * @see BaseProgramListener#whenRemoteInstantiation(Wrappee,String) */ 242 243 public final void whenRemoteInstantiation(Wrappee newInstance, 244 String name) { 245 System.out.println("------ REMINST "+name+"-> "+newInstance); 246 Iterator it = orderedObjects.iterator(); 247 while (it.hasNext()) { 248 AspectComponent curac = (AspectComponent)it.next(); 249 curac.whenRemoteInstantiation(newInstance, name); 250 } 251 } 252 253 /** 254 * Dispatch this event to all the registered Aspect Components that 255 * are woven. 256 * 257 * @see AspectComponent#whenUsingNewInstance(Interaction) 258 * @see BaseProgramListener#whenUsingNewInstance(Interaction) 259 */ 260 261 public final void whenUsingNewInstance(Interaction interaction) { 262 loggerWuni.debug("whenUsingNewInstance "+Strings.hex(interaction.wrappee)); 263 // Collaboration collab = Collaboration.get(); 264 // String old_ac = (String)collab.getCurAC(); 265 try { 266 ClassItem cli = interaction.getClassItem(); 267 boolean isJacClass = cli.getName().startsWith("org.objectweb.jac.core"); 268 Vector toNotify = (Vector)orderedObjects.clone(); 269 for (int i=0; i<toNotify.size(); i++) { 270 AspectComponent curac = (AspectComponent)toNotify.get(i); 271 loggerAspects.debug("curac = "+names.get(curac)); 272 // collab.setCurAC((String)names.get(curac)); 273 if ((!isJacClass) || curac.isSystemListener()) { 274 loggerWuni.debug(" wuni "+curac.getName()); 275 curac.whenUsingNewInstance(interaction); 276 } 277 } 278 } catch (Exception e) { 279 loggerWuni.error("ACManager.whenUsingNewInstance "+interaction,e); 280 281 } /* 282 finally { 283 collab.setCurAC(old_ac); 284 } 285 */ 286 } 287 288 HashSet initializedClasses = new HashSet(); 289 public final synchronized void whenUsingNewClass(ClassItem cl) { 290 if (!initializedClasses.contains(cl)) { 291 loggerAspects.debug("whenUsingNewClass "+cl); 292 try { 293 Vector toNotify = (Vector)orderedObjects.clone(); 294 for (int i=0; i<toNotify.size(); i++) { 295 AspectComponent curac = (AspectComponent)toNotify.get(i); 296 loggerAspects.debug("curac = "+names.get(curac)); 297 curac.whenUsingNewClass(cl); 298 } 299 } catch ( Exception e ) { 300 e.printStackTrace(); 301 } 302 initializedClasses.add(cl); 303 } 304 } 305 306 /** 307 * Dispatch this event to all the woven Aspect Components. 308 * 309 * <p>Note: the current collaboration contains an attribute called 310 * "orgObject" and that is a reference to the object that is 311 * currently serialized. 312 * 313 * @param finalObject the corresponding serialized structure. 314 * @see AspectComponent#whenSerialized(Wrappee,SerializedJacObject) 315 * @see BaseProgramListener#whenSerialized(Wrappee,SerializedJacObject) 316 */ 317 318 public final Wrappee whenSerialized(Wrappee orgObject, 319 SerializedJacObject finalObject) { 320 Iterator it = orderedObjects.iterator(); 321 while (it.hasNext()) { 322 AspectComponent curac = (AspectComponent)it.next(); 323 orgObject = curac.whenSerialized(orgObject,finalObject); 324 } 325 return orgObject; 326 } 327 328 /** 329 * Dispatch this event to all the woven Aspect Components. 330 * 331 * <p>Note: the current collaboration contains an attribute called 332 * "finalObject" and that is a reference to the object that is 333 * will be finally deserialized. 334 * 335 * @param orgObject the corresponding serialized structure. 336 * @see AspectComponent#whenDeserialized(SerializedJacObject,Wrappee) 337 * @see BaseProgramListener#whenDeserialized(SerializedJacObject,Wrappee) 338 */ 339 340 public final Wrappee whenDeserialized(SerializedJacObject orgObject, 341 Wrappee finalObject) { 342 Iterator it = orderedObjects.iterator(); 343 while (it.hasNext()) { 344 AspectComponent curac = (AspectComponent)it.next(); 345 finalObject = curac.whenDeserialized(orgObject,finalObject); 346 } 347 return finalObject; 348 } 349 350 /** 351 * Apply all the woven aspect components to the given wrappee. 352 * 353 * @param wrappee the wrappee that have to be treated 354 */ 355 356 public final void simulateUsingNewInstance(Wrappee wrappee) { 357 if (wrappee==null) 358 return; 359 360 Iterator it=((Vector)orderedObjects.clone()).iterator(); 361 while(it.hasNext()) { 362 AspectComponent curac = (AspectComponent)it.next(); 363 curac.simulateUsingNewInstance(wrappee); 364 } 365 } 366 367 /** 368 * Dispatch this event to all the registered Aspect Components that 369 * are woven. 370 * 371 * @param cloned the wrappee that is being cloned 372 * @param clone the new clone of cloned 373 * @see AspectComponent#whenClone(Wrappee,Wrappee) 374 * @see BaseProgramListener#whenClone(Wrappee,Wrappee) */ 375 376 public final void whenClone(Wrappee cloned, Wrappee clone) { 377 Object[] acs = orderedObjects.toArray(); 378 for ( int i=0; i<acs.length; i++) { 379 AspectComponent curac = (AspectComponent)acs[i]; 380 curac.whenClone(cloned, clone); 381 } 382 } 383 384 public final void whenDeleted(Wrappee object) { 385 Object[] acs = orderedObjects.toArray(); 386 for (int i=0; i<acs.length; i++) { 387 AspectComponent curac = (AspectComponent)acs[i]; 388 curac.whenDeleted(object); 389 } 390 } 391 392 public final void whenFree(Wrappee object) { 393 Object[] acs = orderedObjects.toArray(); 394 for (int i=0; i<acs.length; i++) { 395 AspectComponent curac = (AspectComponent)acs[i]; 396 curac.whenFree(object); 397 } 398 } 399 400 /** 401 * Dispatch this event to all the registered Aspect Components that 402 * are woven. 403 * 404 * @see AspectComponent#afterApplicationStarted() */ 405 406 public final void afterApplicationStarted() { 407 Object[] acs = orderedObjects.toArray(); 408 for ( int i = 0; i < acs.length; i++ ) { 409 AspectComponent curac = (AspectComponent)acs[i]; 410 curac.afterApplicationStarted(); 411 } 412 } 413 414 public final void onExit() { 415 Object[] acs = orderedObjects.toArray(); 416 for ( int i = 0; i < acs.length; i++ ) { 417 AspectComponent curac = (AspectComponent)acs[i]; 418 curac.onExit(); 419 } 420 } 421 422 423 /** 424 * Dispatch this event to all the registered Aspect Components that 425 * are woven. 426 * 427 * @see AspectComponent#whenTopologyChanged() */ 428 429 public final void whenTopologyChanged() { 430 Object[] acs = orderedObjects.toArray(); 431 for ( int i = 0; i < acs.length; i++ ) { 432 AspectComponent curac = (AspectComponent)acs[i]; 433 curac.whenTopologyChanged(); 434 } 435 } 436 437 /** 438 * Dispatch this event to all the registered Aspect Components that 439 * are woven. 440 * 441 * @see AspectComponent#whenCloseDisplay(Display) */ 442 443 public final void whenCloseDisplay(Display display) { 444 Object[] acs = orderedObjects.toArray(); 445 for ( int i = 0; i < acs.length; i++ ) { 446 AspectComponent curac = (AspectComponent)acs[i]; 447 curac.whenCloseDisplay(display); 448 } 449 } 450 451 /** 452 * Forward this event to the aspect component that owns the 453 * wrapper. 454 * 455 * @param wrapper the wrapper that is going to be runned 456 * @param wrappingMethod the name of the may-be runned wrapping 457 * @see AspectComponent#beforeRunningWrapper(Wrapper,String) 458 * @see BaseProgramListener#beforeRunningWrapper(Wrapper,String) */ 459 460 public final boolean beforeRunningWrapper(Wrapper wrapper, 461 String wrappingMethod) { 462 boolean ret = true; 463 AspectComponent ac = wrapper.getAspectComponent(); 464 465 if (ac != null) { 466 if (!ac.beforeRunningWrapper(wrapper,wrappingMethod)) { 467 ret = false; 468 } 469 } 470 return ret; 471 } 472 473 /** 474 * Upcall the beforeRunningWrapper method of all the aspect 475 * component that owns the wrapper. 476 * 477 * @param wrapper the wrapper that has just been runned 478 * @param wrappingMethod the name of the runned wrapping method 479 * @see AspectComponent#afterRunningWrapper(Wrapper,String) 480 * @see BaseProgramListener#afterRunningWrapper(Wrapper,String) */ 481 482 public final void afterRunningWrapper(Wrapper wrapper, 483 String wrappingMethod) { 484 AspectComponent ac = wrapper.getAspectComponent(); 485 if (ac != null) { 486 ac.afterRunningWrapper(wrapper, wrappingMethod); 487 } 488 } 489 490 /** 491 * Upcall the beforeRunningWrapper method of all the aspect 492 * component that owns the wrapper. 493 * 494 * @see AspectComponent#afterWrap(Wrappee,Wrapper,String[],String[][]) */ 495 496 public final void afterWrap(Wrappee wrappee, Wrapper wrapper, 497 String[] wrapping_methods, 498 String[][] wrapped_methods) { 499 Object[] acs = orderedObjects.toArray(); 500 for (int i=0; i<acs.length; i++) { 501 AspectComponent curac = (AspectComponent)acs[i]; 502 curac.afterWrap(wrappee, wrapper, wrapping_methods, wrapped_methods); 503 } 504 } 505 506 public void whenGetObjects(Collection objects, ClassItem cl) 507 { 508 Iterator it = orderedObjects.iterator(); 509 while (it.hasNext()) { 510 AspectComponent curac = (AspectComponent)it.next(); 511 try { 512 curac.whenGetObjects(objects,cl); 513 } catch (Exception e) { 514 loggerAspects.error("whenGetObjects failed on "+curac,e); 515 } 516 } 517 } 518 519 public String whenNameObject(Object object, String name) 520 { 521 Iterator it = orderedObjects.iterator(); 522 while (it.hasNext()) { 523 AspectComponent curac = (AspectComponent)it.next(); 524 name = curac.whenNameObject(object,name); 525 } 526 return name; 527 } 528 529 public void getNameCounters(Map counters) { 530 Iterator it = orderedObjects.iterator(); 531 while (it.hasNext()) { 532 AspectComponent curac = (AspectComponent)it.next(); 533 curac.getNameCounters(counters); 534 } 535 } 536 537 /** 538 * Update name counters 539 */ 540 public void updateNameCounters(Map counters) { 541 Iterator it = orderedObjects.iterator(); 542 while (it.hasNext()) { 543 AspectComponent curac = (AspectComponent)it.next(); 544 curac.updateNameCounters(counters); 545 } 546 } 547 548 public void whenObjectMiss(String name) 549 { 550 loggerACM.debug("whenObjectMiss("+name+")"); 551 Iterator it = orderedObjects.iterator(); 552 while (it.hasNext()) { 553 AspectComponent curac = (AspectComponent)it.next(); 554 logger.debug("whenObjectMiss("+curac+")"); 555 curac.whenObjectMiss (name); 556 } 557 } 558 559 /** 560 * Register a new aspect component. 561 * 562 * <p>When a new aspect component is registered, the 563 * <code>allWoven</code> flag is set to false. And the 564 * <code>checkWeaving</code> method will be called for each base 565 * method call until all the aspect components are woven. 566 * 567 * @param name the aspect component key for the AC manager 568 * @param aspectComponent the registered aspect component 569 * @see AspectComponent#weave() 570 */ 571 572 public final boolean register(String name, Object aspectComponent) { 573 loggerAspects.debug("registering AC "+name); 574 Object o = names.get(name); 575 if (o != null) { 576 // reject if already registered 577 return false; 578 } 579 //registering = true; 580 AspectComponent ac = (AspectComponent) aspectComponent; 581 //ac.init(); 582 583 //AspectComponent compAC = (AspectComponent) names.get( 584 // "JAC_composition_aspect" ); 585 586 boolean ret = super.register(name, ac); 587 588 loggerAspects.debug("memory objects = "+ObjectRepository.getMemoryObjects()); 589 Iterator it = ObjectRepository.getMemoryObjects().iterator(); 590 while( it.hasNext() ) { 591 Wrappee cur = (Wrappee) it.next(); 592 String className = cur.getClass().getName(); 593 if ( ! ( className.equals("org.objectweb.jac.core.NameRepository") || 594 className.equals("org.objectweb.jac.core.ACManager") || 595 className.equals("org.objectweb.jac.core.dist.Topology") ) ) { 596 if ( (! className.startsWith("org.objectweb.jac.core")) || ac.isSystemListener() ) { 597 loggerAspects.debug("simulateUsingNewInstance on "+cur.getClass()); 598 ac.simulateUsingNewInstance(cur); 599 } 600 } 601 } 602 //nonWovenACs.add ( ac ); 603 //allWoven = false; 604 //registering = false; 605 return ret; 606 } 607 608 /** 609 * A resister method that can be used by a UI. 610 * 611 * <p>This method creates a new aspect component with the name of 612 * the given class and registers it. It will be woven immediatly. 613 * 614 * @param name the aspect component key for the AC manager 615 * @param className the aspect component class name 616 * @see ACManager#register(String,Object) 617 * @see AspectComponent#weave() */ 618 619 public final boolean registerWithName(String name, String className) { 620 boolean ret = false; 621 try { 622 ret = register(name, Class.forName(className).newInstance()); 623 } catch (Exception e) { 624 e.printStackTrace(); 625 } 626 return ret; 627 } 628 629 /** 630 * Register (if not allready registered) and weaves a new Aspect 631 * Component. 632 * 633 * @param ac the aspect component to weave 634 * @see ACManager#register(String,Object) 635 * @see AspectComponent#weave() */ 636 637 public final void weave(AspectComponent ac) { 638 if (names.get(ac) == null) { 639 register(ac.toString(),ac); 640 } 641 } 642 643 /** 644 * Unregister a given aspect component (it is then unwoven). 645 * 646 * @param name the aspect component key for the AC manager 647 * @see #register(String,Object) 648 * @see AspectComponent#unweave() */ 649 650 public final void unregister(String name) { 651 AspectComponent ac = (AspectComponent)objects.get(name); 652 if (ac == null) { 653 loggerAspects.debug("'"+name+"' aspect component not found. ("+names+")"); 654 return; 655 } 656 ac.unweave(); 657 super.unregister(name); 658 } 659 660 // following methods implement the CollaborationParticipant interface 661 662 public final void attrdef( String name, Object value ) { 663 Collaboration.get().addAttribute( name, value ); 664 } 665 666 public final Object attr(String name) { 667 return Collaboration.get().getAttribute(name); 668 } 669 670 /** 671 * Reload an aspect for an application 672 * @param application the application's name 673 * @param aspect the aspect's name 674 */ 675 public void reloadAspect(String application, String aspect) { 676 String fullName = application+"."+aspect; 677 logger.info("Reloading "+fullName); 678 AspectComponent ac = getACFromFullName(fullName); 679 if (ac != null) { 680 ApplicationRepository.get().unextend(application,aspect); 681 ac.beforeReload(); 682 ApplicationRepository.get().extend(application,aspect); 683 ac.whenReload(); 684 } 685 } 686 687 /** 688 * Reload an aspect for the current application 689 * @param aspect the aspect's name 690 */ 691 public void reloadAspect(String aspect) throws Exception { 692 String application = Collaboration.get().getCurApp(); 693 if (application==null) { 694 throw new Exception("No current application in context"); 695 } 696 reloadAspect(application,aspect); 697 } 698 699 /* 700 public static Collection getWeavedAspects() { 701 String application = Collaboration.get().getCurApp(); 702 if (application==null) { 703 throw new Exception("No current application in context"); 704 } 705 AspectComponent[] aspects = getACM().getAspectComponents(); 706 Vector weavedAspects = new Vector(aspects.length); 707 for (int i=0; i<aspects.length; i++) { 708 if (application.equals(aspects[i].getApplication()) 709 && aspects[i].) 710 } 711 return weavedAspects; 712 } 713 */ 714 715 public final void beforeWrappeeInit(Wrappee wrappee) { 716 Object[] acs = orderedObjects.toArray(); 717 for (int i = 0; i < acs.length; i++) { 718 AspectComponent curac = (AspectComponent)acs[i]; 719 curac.beforeWrappeeInit(wrappee); 720 } 721 } 722 723 public final void afterWrappeeInit(Wrappee wrappee) { 724 Object[] acs = orderedObjects.toArray(); 725 for (int i = 0; i < acs.length; i++) { 726 AspectComponent curac = (AspectComponent)acs[i]; 727 curac.afterWrappeeInit(wrappee); 728 } 729 } 730 731 }