KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > yan > FactoryComponent


1 /*****************************************************************************
2  * Copyright (C) Zephyr Business Solution. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  *****************************************************************************/

8
9 /*
10  * Created on Apr 15, 2005
11  *
12  * Author Ben Yu
13  * ZBS
14  */

15 package jfun.yan;
16
17 import java.lang.reflect.InvocationHandler JavaDoc;
18 import java.lang.reflect.Method JavaDoc;
19 import java.lang.reflect.Proxy JavaDoc;
20
21 import jfun.yan.util.ReflectionUtil;
22
23 /**
24  * Every component is a factory.
25  * FactoryComponent adapts a Component that creates the product
26  * to a Component that creates the product factory.
27  * <p>
28  * Zephyr Business Solution
29  *
30  * @author Ben Yu
31  *
32  */

33 final class FactoryComponent<T> extends Component<T> {
34   private final Creator cc;
35   private final Class JavaDoc<T> factory_class;
36   private final ClassLoader JavaDoc loader;
37   private final String JavaDoc text;
38   private interface SerializableInvocationHandler
39   extends InvocationHandler JavaDoc, java.io.Serializable JavaDoc{}
40   FactoryComponent(final Creator cc, final Class JavaDoc<T> factory_class,
41       final ClassLoader JavaDoc loader, String JavaDoc text) {
42     this.cc = cc;
43     this.factory_class = factory_class;
44     this.loader = loader;
45     this.text = text;
46   }
47   
48   public Class JavaDoc<T> getType() {
49     return factory_class;
50   }
51   public boolean isConcrete(){
52     return true;
53   }
54   public T create(final Dependency dep){
55     final InvocationHandler JavaDoc handler = new SerializableInvocationHandler(){
56       public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc mtd, Object JavaDoc[] args)
57       throws Throwable JavaDoc{
58         if(Object JavaDoc.class.equals(mtd.getDeclaringClass())){
59           //Object method
60
try{
61             return mtd.invoke(FactoryComponent.this, args);
62           }
63           catch(java.lang.reflect.InvocationTargetException JavaDoc e){
64             throw e.getTargetException();
65           }
66         }
67         else{
68           if(args==null || args.length==0){
69             return cc.create(dep);
70           }
71           else{
72             final Creator[] cargs = new Creator[args.length];
73             for(int i=0; i<args.length; i++){
74               cargs[i] = Components.value(args[i]);
75             }
76             //these arguments should be applied to dependency,
77
//not to the component, so that it takes lower precedence
78
//than the customizations already done to the component.
79
//If the component is created using withArgument
80
//that argument will override the value passed in from the factory method.
81

82             /*
83              * 4/2005
84              * No! component functional update is stack-based. Once an update
85              * is made, it can't be overridden or undone.
86              * So, withArguments should be ok.
87              * But, since this works too and we might someday change the
88              * behavior of functional update, let's leave it as is.
89              */

90             final Dependency ndep = bindArgs(dep, cargs);
91             return cc.create(ndep);
92           }
93         }
94       }
95     };
96     return (T)Proxy.newProxyInstance(loader, new Class JavaDoc[]{factory_class},
97         handler);
98   }
99   public Class JavaDoc verify(final Dependency dep){
100     final Method JavaDoc[] mtds = factory_class.getMethods();
101     final Component wildcard = Components.value(null);
102     for(int i=0; i<mtds.length; i++){
103       final Method JavaDoc mtd = mtds[i];
104       if(Object JavaDoc.class.equals(mtd.getDeclaringClass())){
105         continue;
106       }
107       final Class JavaDoc[] ptypes = mtd.getParameterTypes();
108       final Class JavaDoc rtype = mtd.getReturnType();
109       final Dependency parametered = withParamTypes(dep, ptypes, wildcard);
110       final Class JavaDoc real_type = cc.verify(parametered);
111       if(!ReflectionUtil.isAssignableFrom(rtype, real_type)){
112         throw new ReturnTypeMismatchException(rtype, real_type, mtd);
113       }
114     }
115     return getType();
116   }
117   private static Dependency bindArgs(Dependency dep, Creator[] args){
118     return Components.bindArguments(dep, Components.getParameterBinder(args));
119   }
120   private static Dependency withParamTypes(
121       final Dependency dep, final Class JavaDoc[] ptypes, final Component wildcard){
122     if(ptypes==null || ptypes.length==0) return dep;
123     final Creator[] args = new Creator[ptypes.length];
124     for(int i=0; i<args.length; i++){
125       args[i] = wildcard.cast(ptypes[i]);
126     }
127     return bindArgs(dep, args);
128   }
129   public boolean equals(Object JavaDoc obj) {
130     if(obj instanceof FactoryComponent){
131       final FactoryComponent other = (FactoryComponent)obj;
132       return factory_class.equals(other.factory_class)
133       && cc.equals(other.cc);
134     }
135     else return false;
136   }
137   public int hashCode() {
138     return factory_class.hashCode()*31+cc.hashCode();
139   }
140   public String JavaDoc toString() {
141     //return "<"+cc + "> : " + factory_class.getName();
142
return text;
143   }
144   public boolean isSingleton(){
145     return false;
146   }
147 }
148
Popular Tags