/** 6-27-97 Modified by Kent L. Smotherman CSG Systems, Inc. Get rid of the silly code generation/compilation and replace it with my stuff. **/ package sun.beanbox; import java.util.*; import java.beans.*; import java.lang.reflect.*; import csgsys.java.util.*; //added 6-27-97 kls import java.lang.Class.*; public class HookupManager { static void hookup(EventSetDescriptor esd, Method listenerMethod, Object source, Object target, Method targetMethod) { try { // Here is my non-code generating solution: KLS Class cargs[] = new Class[1]; Listener listener = new Listener(target,targetMethod.getName()); cargs[0] = listener.getClass(); Object[] addArgs = new Object[1]; addArgs[0] = listener; String addName = esd.getAddListenerMethod().getName(); Method addMethod = null; try { addMethod = source.getClass().getMethod(addName,cargs); addMethod.invoke(source,addArgs); } catch (NoSuchMethodException e) { // If we were smart, we would cache and reuse hookups. We aren't. String hookupName = generateHookup(esd, listenerMethod, source, target, targetMethod); SimpleClassLoader loader = SimpleClassLoader.ourLoader; javaFiles.addElement(hookupName); Class hookupClass = loader.loadFromFile(hookupName); Object hookup = hookupClass.newInstance(); Method setTargetMethod = findMethod(hookupClass, "setTarget"); Object args[] = new Object[1]; args[0] = target; setTargetMethod.invoke(hookup, args); args[0] = hookup; esd.getAddListenerMethod().invoke(source, args); } } catch (Exception ex) { System.err.println("Hookup caught " + ex); } } static Vector getHookupFiles() { return javaFiles; } static String generateHookup(EventSetDescriptor esd, Method listenerMethod, Object source, Object target, Method targetMethod) { String id = getId(); String className = "___Hookup_" + id; String fileName = tmpDir + java.io.File.separator + className + ".java"; String targetType = target.getClass().getName(); // Create an appropriate subdirectory. java.io.File tmp = new java.io.File(tmpDir); tmp.mkdirs(); // Open the new java source file, java.io.PrintWriter out = null; try { java.io.FileWriter fout = new java.io.FileWriter(fileName); out = new java.io.PrintWriter(fout); } catch (Exception ex) { System.err.println("Couldn't open hookup file " + fileName); System.err.println(" " + ex); return (null); } out.println("// Automatically generated event hookup file."); out.println(""); out.println("package " + packageName + ";"); out.println(""); out.println("public class " + className + " implements " + esd.getListenerType().getName() + ", java.io.Serializable {"); out.println(""); out.println(" public void setTarget(" + targetType + " t) {"); out.println(" target = t;"); out.println(" }"); Method methods[] = esd.getListenerMethods(); for (int k = 0; k < methods.length; k++) { out.println(""); out.print(" public void " + methods[k].getName() + "("); Class argTypes[] = methods[k].getParameterTypes(); for (int i = 0; i < argTypes.length; i++) { if (i > 0) { out.print(", "); } out.print("" + argTypes[i].getName() + " arg" + i); } out.print(")"); /** * At the moment getExceptionTypes fails to return the * PropertyVetoException. I've hacked around the problem. */ /* * Class[] exceptionTypes = methods[k].getExceptionTypes(); * if (exceptionTypes.length > 0) { * out.print("\n throws"); * for (int i = 0; i < exceptionTypes.length; i++) * out.print(((i != 0) ? ", " : " ") + exceptionTypes[i].getName()); * out.print(" "); * } */ if ("vetoableChange".equals(methods[k].getName())) { out.print(" throws java.beans.PropertyVetoException"); } out.println(" {"); if (listenerMethod.getName() == methods[k].getName()) { out.print(" target." + targetMethod.getName() + "("); // Either the targetMethod must take zero args, or the // same args as the listenerMethod. if (targetMethod.getParameterTypes().length != 0) { for (int i = 0; i < argTypes.length; i++) { if (i > 0) { out.print(", "); } out.print("arg" + i); } } out.println(");"); } out.println(" }"); } out.println(""); out.println(" private " + targetType + " target;"); out.println("}"); out.close(); compile(fileName); String fullClassName = packageName+"."+className; String pathToFile = tmpDir+java.io.File.separatorChar+className+".class"; return (pathToFile); } /** * A classpath corresponding to all the JAR files that have been * loaded so far. */ static String loadedJarFiles() { String path = System.getProperty("java.class.path"); String sep = System.getProperty("path.separator"); Vector allJI = BeanBoxFrame.getToolBox().getLoadedJarInfo(); StringBuffer allJars = new StringBuffer(path); Enumeration e = allJI.elements(); JarInfo prev = null; // REMIND!! clean this up while (e.hasMoreElements()) { JarInfo ji = (JarInfo) e.nextElement(); if (ji == null) { // the built-in BeanBox container continue; } if (ji == prev) { // we already dealt with this one continue; } prev = ji; allJars.append(sep); allJars.append(ji.getJarName()); } return allJars.toString(); } static void compile(String fileName) { // Run the javac compiler inside the current address space. String args[] = new String[4]; args[0] = "-classpath"; args[1] = loadedJarFiles(); args[2] = "-nowarn"; args[3] = fileName; sun.tools.javac.Main compiler = new sun.tools.javac.Main(System.err, "javac"); boolean ok = compiler.compile(args); if (!ok) { System.err.println("Compile failed"); } } static String getId() { java.util.Date now = new java.util.Date(); long id = now.getTime()/10; return (Long.toHexString(id)); } private static Method findMethod(Class cls, String methodName) { try { Method methods[] = cls.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(methodName)) { return method; } } throw new Error("method " + methodName + " not found"); } catch (Exception ex) { throw new Error("findMethod caught : " + ex); } } static String shortPackageName = "sun.beanbox"; static String shortTmpDir = BeanBoxFrame.getTmpDir(); static String packageName; static String tmpDir; static Vector javaFiles = new Vector(); static { packageName = shortTmpDir.replace(java.io.File.separatorChar, '.')+"."+shortPackageName; tmpDir = packageName.replace('.', java.io.File.separatorChar); } }