| 
 1 | 
  
 |  | 
| 
 2 | 
  
 |  | 
| 
 3 | 
  
 |  | 
| 
 4 | 
  
 |  | 
| 
 5 | 
  
 |  | 
| 
 6 | 
  
 |  | 
| 
 7 | 
  
 |  | 
| 
 8 | 
  
 |  | 
| 
 9 | 
  
 |  | 
| 
 10 | 
  
 |  | 
| 
 11 | 
  
 |  | 
| 
 12 | 
  
 |  | 
| 
 13 | 
  
 |  | 
| 
 14 | 
  
 |  | 
| 
 15 | 
  
 | package org.apache.hivemind.lib.chain; | 
| 
 16 | 
  
 |  | 
| 
 17 | 
  
 | import java.lang.reflect.Modifier; | 
| 
 18 | 
  
 | import java.util.HashMap; | 
| 
 19 | 
  
 | import java.util.List; | 
| 
 20 | 
  
 | import java.util.Map; | 
| 
 21 | 
  
 |  | 
| 
 22 | 
  
 | import org.apache.hivemind.ClassResolver; | 
| 
 23 | 
  
 | import org.apache.hivemind.service.BodyBuilder; | 
| 
 24 | 
  
 | import org.apache.hivemind.service.ClassFab; | 
| 
 25 | 
  
 | import org.apache.hivemind.service.ClassFabUtils; | 
| 
 26 | 
  
 | import org.apache.hivemind.service.ClassFactory; | 
| 
 27 | 
  
 | import org.apache.hivemind.service.MethodIterator; | 
| 
 28 | 
  
 | import org.apache.hivemind.service.MethodSignature; | 
| 
 29 | 
  
 | import org.apache.hivemind.util.ConstructorUtils; | 
| 
 30 | 
  
 | import org.apache.hivemind.util.Defense; | 
| 
 31 | 
  
 |  | 
| 
 32 | 
  
 |  | 
| 
 33 | 
  
 |  | 
| 
 34 | 
  
 |  | 
| 
 35 | 
  
 |  | 
| 
 36 | 
  
 |  | 
| 
 37 | 
  
 |  | 
| 
 38 | 
  
 | public class ChainBuilderImpl implements ChainBuilder | 
| 
 39 | 
  
 | { | 
| 
 40 | 
  
 |     private ClassResolver _classResolver; | 
| 
 41 | 
  
 |  | 
| 
 42 | 
  
 |     private ClassFactory _classFactory; | 
| 
 43 | 
  
 |  | 
| 
 44 | 
  
 |      | 
| 
 45 | 
  
 |  | 
| 
 46 | 
  
 |  | 
| 
 47 | 
  
 |  | 
| 
 48 | 
  
 |     private Map _implementations = new HashMap(); | 
| 
 49 | 
  
 |  | 
| 
 50 | 
 4
 |     public Object buildImplementation(Class commandInterface, List commands, String toString)
 | 
| 
 51 | 
  
 |     { | 
| 
 52 | 
 4
 |         Defense.notNull(commandInterface, "commandInterface");
 | 
| 
 53 | 
 4
 |         Defense.notNull(commands, "commands");
 | 
| 
 54 | 
 4
 |         Defense.notNull(toString, "toString");
 | 
| 
 55 | 
  
 |  | 
| 
 56 | 
 4
 |         Class instanceClass = findImplementationClass(commandInterface);
 | 
| 
 57 | 
  
 |  | 
| 
 58 | 
 4
 |         return createInstance(instanceClass, commands, toString);
 | 
| 
 59 | 
  
 |     } | 
| 
 60 | 
  
 |  | 
| 
 61 | 
 4
 |     private synchronized Class findImplementationClass(Class commandInterface)
 | 
| 
 62 | 
  
 |     { | 
| 
 63 | 
 4
 |         Class result = (Class) _implementations.get(commandInterface);
 | 
| 
 64 | 
  
 |  | 
| 
 65 | 
 4
 |         if (result == null)
 | 
| 
 66 | 
  
 |         { | 
| 
 67 | 
 3
 |             result = constructImplementationClass(commandInterface);
 | 
| 
 68 | 
  
 |  | 
| 
 69 | 
 3
 |             _implementations.put(commandInterface, result);
 | 
| 
 70 | 
  
 |         } | 
| 
 71 | 
  
 |  | 
| 
 72 | 
 4
 |         return result;
 | 
| 
 73 | 
  
 |     } | 
| 
 74 | 
  
 |  | 
| 
 75 | 
 3
 |     private Class constructImplementationClass(Class commandInterface)
 | 
| 
 76 | 
  
 |     { | 
| 
 77 | 
 3
 |         String name = ClassFabUtils.generateClassName(commandInterface);
 | 
| 
 78 | 
  
 |  | 
| 
 79 | 
 3
 |         ClassFab cf = _classFactory.newClass(name, Object.class);
 | 
| 
 80 | 
  
 |  | 
| 
 81 | 
 3
 |         addInfrastructure(cf, commandInterface);
 | 
| 
 82 | 
  
 |  | 
| 
 83 | 
 3
 |         addMethods(cf, commandInterface);
 | 
| 
 84 | 
  
 |  | 
| 
 85 | 
 3
 |         return cf.createClass();
 | 
| 
 86 | 
  
 |     } | 
| 
 87 | 
  
 |  | 
| 
 88 | 
 3
 |     void addInfrastructure(ClassFab cf, Class commandInterface)
 | 
| 
 89 | 
  
 |     { | 
| 
 90 | 
 3
 |         Class array = _classResolver.findClass(commandInterface.getName() + "[]");
 | 
| 
 91 | 
  
 |  | 
| 
 92 | 
 3
 |         cf.addInterface(commandInterface);
 | 
| 
 93 | 
 3
 |         cf.addField("_commands", array);
 | 
| 
 94 | 
 3
 |         cf.addField("_toString", String.class);
 | 
| 
 95 | 
  
 |  | 
| 
 96 | 
 3
 |         BodyBuilder builder = new BodyBuilder();
 | 
| 
 97 | 
  
 |  | 
| 
 98 | 
 3
 |         builder.begin();
 | 
| 
 99 | 
 3
 |         builder.addln("_commands = ({0}[]) $1.toArray(new {0}[0]);", commandInterface.getName());
 | 
| 
 100 | 
 3
 |         builder.addln("_toString = $2;");
 | 
| 
 101 | 
 3
 |         builder.end();
 | 
| 
 102 | 
  
 |  | 
| 
 103 | 
 3
 |         cf.addConstructor(new Class[]
 | 
| 
 104 | 
  
 |         { List.class, String.class }, null, builder.toString()); | 
| 
 105 | 
  
 |     } | 
| 
 106 | 
  
 |  | 
| 
 107 | 
 4
 |     private Object createInstance(Class instanceClass, List commands, String toString)
 | 
| 
 108 | 
  
 |     { | 
| 
 109 | 
 4
 |         return ConstructorUtils.invokeConstructor(instanceClass, new Object[]
 | 
| 
 110 | 
  
 |         { commands, toString }); | 
| 
 111 | 
  
 |     } | 
| 
 112 | 
  
 |  | 
| 
 113 | 
 3
 |     void addMethods(ClassFab cf, Class commandInterface)
 | 
| 
 114 | 
  
 |     { | 
| 
 115 | 
 3
 |         MethodIterator mi = new MethodIterator(commandInterface);
 | 
| 
 116 | 
  
 |  | 
| 
 117 | 
 3
 |         while (mi.hasNext())
 | 
| 
 118 | 
  
 |         { | 
| 
 119 | 
 3
 |             MethodSignature sig = mi.next();
 | 
| 
 120 | 
  
 |  | 
| 
 121 | 
 3
 |             addMethod(cf, commandInterface, sig);
 | 
| 
 122 | 
  
 |         } | 
| 
 123 | 
  
 |  | 
| 
 124 | 
 3
 |         if (!mi.getToString())
 | 
| 
 125 | 
 3
 |             addToString(cf);
 | 
| 
 126 | 
  
 |     } | 
| 
 127 | 
  
 |  | 
| 
 128 | 
 5
 |     void addMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
 | 
| 
 129 | 
  
 |     { | 
| 
 130 | 
 5
 |         Class returnType = sig.getReturnType();
 | 
| 
 131 | 
  
 |  | 
| 
 132 | 
 5
 |         if (returnType.equals(void.class))
 | 
| 
 133 | 
  
 |         { | 
| 
 134 | 
 1
 |             addVoidMethod(cf, commandInterface, sig);
 | 
| 
 135 | 
 1
 |             return;
 | 
| 
 136 | 
  
 |         } | 
| 
 137 | 
  
 |  | 
| 
 138 | 
 4
 |         String defaultValue = defaultForReturnType(returnType);
 | 
| 
 139 | 
  
 |  | 
| 
 140 | 
 4
 |         BodyBuilder builder = new BodyBuilder();
 | 
| 
 141 | 
 4
 |         builder.begin();
 | 
| 
 142 | 
  
 |  | 
| 
 143 | 
 4
 |         builder
 | 
| 
 144 | 
  
 |                 .addln( | 
| 
 145 | 
  
 |                         "{0} result = {1};", | 
| 
 146 | 
  
 |                         ClassFabUtils.getJavaClassName(returnType), | 
| 
 147 | 
  
 |                         defaultValue); | 
| 
 148 | 
 4
 |         builder.addln("for (int i = 0; i < _commands.length; i++)");
 | 
| 
 149 | 
  
 |  | 
| 
 150 | 
 4
 |         builder.begin();
 | 
| 
 151 | 
 4
 |         builder.addln("result = _commands[i].{0}($$);", sig.getName());
 | 
| 
 152 | 
  
 |  | 
| 
 153 | 
 4
 |         builder.addln("if (result != {0}) break;", defaultValue);
 | 
| 
 154 | 
  
 |  | 
| 
 155 | 
 4
 |         builder.end();
 | 
| 
 156 | 
  
 |  | 
| 
 157 | 
 4
 |         builder.addln("return result;");
 | 
| 
 158 | 
 4
 |         builder.end();
 | 
| 
 159 | 
  
 |  | 
| 
 160 | 
 4
 |         cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
 | 
| 
 161 | 
  
 |     } | 
| 
 162 | 
  
 |  | 
| 
 163 | 
 10
 |     String defaultForReturnType(Class returnType)
 | 
| 
 164 | 
  
 |     { | 
| 
 165 | 
  
 |          | 
| 
 166 | 
  
 |  | 
| 
 167 | 
 10
 |         if (!returnType.isPrimitive())
 | 
| 
 168 | 
 4
 |             return "null";
 | 
| 
 169 | 
  
 |  | 
| 
 170 | 
 6
 |         if (returnType.equals(boolean.class))
 | 
| 
 171 | 
 5
 |             return "false";
 | 
| 
 172 | 
  
 |  | 
| 
 173 | 
  
 |          | 
| 
 174 | 
  
 |          | 
| 
 175 | 
  
 |  | 
| 
 176 | 
 1
 |         return "0";
 | 
| 
 177 | 
  
 |     } | 
| 
 178 | 
  
 |  | 
| 
 179 | 
 1
 |     private void addVoidMethod(ClassFab cf, Class commandInterface, MethodSignature sig)
 | 
| 
 180 | 
  
 |     { | 
| 
 181 | 
 1
 |         BodyBuilder builder = new BodyBuilder();
 | 
| 
 182 | 
  
 |  | 
| 
 183 | 
 1
 |         builder.begin();
 | 
| 
 184 | 
  
 |  | 
| 
 185 | 
 1
 |         builder.addln("for (int i = 0; i < _commands.length; i++)");
 | 
| 
 186 | 
 1
 |         builder.addln("_commands[i].{0}($$);", sig.getName());
 | 
| 
 187 | 
  
 |  | 
| 
 188 | 
 1
 |         builder.end();
 | 
| 
 189 | 
  
 |  | 
| 
 190 | 
 1
 |         cf.addMethod(Modifier.PUBLIC, sig, builder.toString());
 | 
| 
 191 | 
  
 |     } | 
| 
 192 | 
  
 |  | 
| 
 193 | 
 3
 |     void addToString(ClassFab cf)
 | 
| 
 194 | 
  
 |     { | 
| 
 195 | 
 3
 |         MethodSignature sig = new MethodSignature(String.class, "toString", null, null);
 | 
| 
 196 | 
  
 |  | 
| 
 197 | 
 3
 |         cf.addMethod(Modifier.PUBLIC, sig, "return _toString;");
 | 
| 
 198 | 
  
 |     } | 
| 
 199 | 
  
 |  | 
| 
 200 | 
 3
 |     public void setClassFactory(ClassFactory classFactory)
 | 
| 
 201 | 
  
 |     { | 
| 
 202 | 
 3
 |         _classFactory = classFactory;
 | 
| 
 203 | 
  
 |     } | 
| 
 204 | 
  
 |  | 
| 
 205 | 
 3
 |     public void setClassResolver(ClassResolver classResolver)
 | 
| 
 206 | 
  
 |     { | 
| 
 207 | 
 3
 |         _classResolver = classResolver;
 | 
| 
 208 | 
  
 |     } | 
| 
 209 | 
  
 | } |