001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by Paul Hammant * 009 *****************************************************************************/ 010 011 package org.picocontainer.gems.monitors; 012 013 import java.lang.reflect.Constructor; 014 import java.util.ArrayList; 015 import java.util.Collections; 016 import java.util.HashSet; 017 import java.util.List; 018 import java.util.Set; 019 020 import org.picocontainer.ComponentAdapter; 021 import org.picocontainer.ComponentMonitor; 022 import org.picocontainer.PicoContainer; 023 import org.picocontainer.monitors.AbstractComponentMonitor; 024 025 @SuppressWarnings("serial") 026 public final class DotDependencyGraphComponentMonitor extends AbstractComponentMonitor implements ComponentMonitor { 027 028 029 final List<Instantiation> allInstantiated = new ArrayList<Instantiation>(); 030 031 public DotDependencyGraphComponentMonitor(final ComponentMonitor delegate) { 032 super(delegate); 033 } 034 035 public DotDependencyGraphComponentMonitor() { 036 } 037 038 @Override 039 public <T> void instantiated(final PicoContainer container, final ComponentAdapter<T> componentAdapter, 040 final Constructor<T> constructor, 041 final Object instantiated, 042 final Object[] injected, 043 final long duration) { 044 045 this.allInstantiated.add(new Instantiation(constructor, instantiated, injected, duration)); 046 047 super.instantiated(container, componentAdapter, constructor, instantiated, injected, duration); 048 } 049 050 051 public String getClassDependencyGraph() { 052 053 Set<String> lines = new HashSet<String>(); 054 055 for (Object anAllInstantiated : allInstantiated) { 056 Instantiation instantiation = (Instantiation)anAllInstantiated; 057 for (int j = 0; j < instantiation.getInjected().length; j++) { 058 Object instantiated = instantiation.getInstantiated(); 059 Object injected = instantiation.getInjected()[j]; 060 lines.add( 061 " '" + instantiated.getClass().getName() + "' -> '" + injected.getClass().getName() + "';\n"); 062 } 063 } 064 065 return sortLines(lines); 066 } 067 068 private String sortLines(final Set<String> lines) { 069 List<String> list = new ArrayList<String>(lines); 070 Collections.sort(list); 071 072 String dependencies = ""; 073 for (Object aList : list) { 074 String dep = (String)aList; 075 dependencies = dependencies + dep; 076 } 077 return dependencies.replaceAll("'","\""); 078 } 079 080 public String getInterfaceDependencyGraph() { 081 Set<String> lines = new HashSet<String>(); 082 083 for (Object anAllInstantiated : allInstantiated) { 084 Instantiation instantiation = (Instantiation)anAllInstantiated; 085 for (int j = 0; j < instantiation.getInjected().length; j++) { 086 Object injected = instantiation.getInjected()[j]; 087 Class<?> injectedType = instantiation.getConstructor().getParameterTypes()[j]; 088 Object instantiated = instantiation.getInstantiated(); 089 if (injected.getClass() != injectedType) { 090 lines.add(" '" + instantiated.getClass().getName() + "' -> '" + injectedType.getName() + 091 "' [style=dotted,label='needs'];\n"); 092 lines.add(" '" + injected.getClass().getName() + "' -> '" + injectedType.getName() + 093 "' [style=dotted, color=red,label='isA'];\n"); 094 lines.add(" '" + injectedType.getName() + "' [shape=box, label=" + printClassName(injectedType) + 095 "];\n"); 096 } else { 097 lines.add(" '" + instantiated.getClass().getName() + "' -> '" + injected.getClass().getName() + 098 "' [label='needs'];\n"); 099 } 100 lines.add(" '" + instantiated.getClass().getName() + "' [label=" + 101 printClassName(instantiated.getClass()) + "];\n"); 102 103 } 104 } 105 106 return sortLines(lines); 107 } 108 109 private String printClassName(final Class<?> clazz) { 110 String className = clazz.getName(); 111 return "'" + className.substring(className.lastIndexOf(".")+1) + "\\n" + clazz.getPackage().getName() + "'"; 112 113 } 114 115 private static final class Instantiation { 116 final Constructor<?> constructor; 117 final Object instantiated; 118 final Object[] injected; 119 final long duration; 120 121 public Instantiation(final Constructor<?> constructor, final Object instantiated, final Object[] injected, final long duration) { 122 this.constructor = constructor; 123 this.instantiated = instantiated; 124 this.injected = injected; 125 this.duration = duration; 126 } 127 128 public Constructor<?> getConstructor() { 129 return constructor; 130 } 131 132 public Object getInstantiated() { 133 return instantiated; 134 } 135 public Object[] getInjected() { 136 return injected; 137 } 138 } 139 }