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 * 009 *****************************************************************************/ 010 package org.picocontainer.adapters; 011 012 import org.picocontainer.ComponentMonitor; 013 import org.picocontainer.PicoVisitor; 014 import org.picocontainer.ComponentAdapter; 015 import org.picocontainer.ComponentMonitorStrategy; 016 import org.picocontainer.PicoContainer; 017 import org.picocontainer.PicoCompositionException; 018 import org.picocontainer.injectors.ProviderAdapter; 019 import org.picocontainer.injectors.Provider; 020 import org.picocontainer.monitors.AbstractComponentMonitor; 021 import org.picocontainer.monitors.NullComponentMonitor; 022 023 import java.io.Serializable; 024 025 /** 026 * Base class for a ComponentAdapter with general functionality. 027 * This implementation provides basic checks for a healthy implementation of a ComponentAdapter. 028 * It does not allow to use <code>null</code> for the component key or the implementation, 029 * ensures that the implementation is a concrete class and that the key is assignable from the 030 * implementation if the key represents a type. 031 * 032 * @author Paul Hammant 033 * @author Aslak Hellesøy 034 * @author Jon Tirsén 035 */ 036 public abstract class AbstractAdapter<T> implements ComponentAdapter<T>, ComponentMonitorStrategy, Serializable { 037 private Object componentKey; 038 private Class<T> componentImplementation; 039 private ComponentMonitor componentMonitor; 040 041 /** 042 * Constructs a new ComponentAdapter for the given key and implementation. 043 * @param componentKey the search key for this implementation 044 * @param componentImplementation the concrete implementation 045 */ 046 public AbstractAdapter(Object componentKey, Class componentImplementation) { 047 this(componentKey, componentImplementation, new AbstractComponentMonitor()); 048 this.componentMonitor = new NullComponentMonitor(); 049 } 050 051 /** 052 * Constructs a new ComponentAdapter for the given key and implementation. 053 * @param componentKey the search key for this implementation 054 * @param componentImplementation the concrete implementation 055 * @param monitor the component monitor used by this ComponentAdapter 056 */ 057 public AbstractAdapter(Object componentKey, Class componentImplementation, ComponentMonitor monitor) { 058 if (monitor == null) { 059 throw new NullPointerException("ComponentMonitor==null"); 060 } 061 this.componentMonitor = monitor; 062 if (componentImplementation == null) { 063 throw new NullPointerException("componentImplementation"); 064 } 065 this.componentKey = componentKey; 066 this.componentImplementation = componentImplementation; 067 checkTypeCompatibility(); 068 } 069 070 /** 071 * {@inheritDoc} 072 * @see org.picocontainer.ComponentAdapter#getComponentKey() 073 */ 074 public Object getComponentKey() { 075 if (componentKey == null) { 076 throw new NullPointerException("componentKey"); 077 } 078 return componentKey; 079 } 080 081 /** 082 * {@inheritDoc} 083 * @see org.picocontainer.ComponentAdapter#getComponentImplementation() 084 */ 085 public Class<T> getComponentImplementation() { 086 return componentImplementation; 087 } 088 089 protected void checkTypeCompatibility() { 090 if (componentKey instanceof Class) { 091 Class<?> componentType = (Class) componentKey; 092 if (Provider.class.isAssignableFrom(componentImplementation)) { 093 if (!componentType.isAssignableFrom(ProviderAdapter.getProvideMethod(componentImplementation).getReturnType())) { 094 throw newCCE(componentType); 095 } 096 } else { 097 if (!componentType.isAssignableFrom(componentImplementation)) { 098 throw newCCE(componentType); 099 } 100 } 101 } 102 } 103 104 private ClassCastException newCCE(Class<?> componentType) { 105 return new ClassCastException(componentImplementation.getName() + " is not a " + componentType.getName()); 106 } 107 108 public T getComponentInstance(PicoContainer container) throws PicoCompositionException { 109 return getComponentInstance(container, null); 110 } 111 112 /** 113 * @return Returns the ComponentAdapter's class name and the component's key. 114 * @see java.lang.Object#toString() 115 */ 116 public String toString() { 117 return getDescriptor() + getComponentKey(); 118 } 119 120 public void accept(PicoVisitor visitor) { 121 visitor.visitComponentAdapter(this); 122 } 123 124 public void changeMonitor(ComponentMonitor monitor) { 125 this.componentMonitor = monitor; 126 } 127 128 /** 129 * Returns the monitor currently used 130 * @return The ComponentMonitor currently used 131 */ 132 public ComponentMonitor currentMonitor(){ 133 return componentMonitor; 134 } 135 136 public final ComponentAdapter<T> getDelegate() { 137 return null; 138 } 139 140 public final <U extends ComponentAdapter> U findAdapterOfType(Class<U> adapterType) { 141 if (adapterType.isAssignableFrom(this.getClass())) { 142 return (U) this; 143 } else if (getDelegate() != null) { 144 return getDelegate().findAdapterOfType(adapterType); 145 } 146 return null; 147 } 148 149 150 }