1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
/* * @(#)ObjectView.java 1.15 05/11/17 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package javax.swing.text.html; import java.util.Enumeration; import java.awt.*; import javax.swing.*; import javax.swing.text.*; import java.beans.*; import java.lang.reflect.*; /** * Component decorator that implements the view interface * for <object> elements. * <p> * This view will try to load the class specified by the * <code>classid</code> attribute. If possible, the Classloader * used to load the associated Document is used. * This would typically be the same as the ClassLoader * used to load the EditorKit. If the document's * ClassLoader is null, <code>Class.forName</code> is used. * <p> * If the class can successfully be loaded, an attempt will * be made to create an instance of it by calling * <code>Class.newInstance</code>. An attempt will be made * to narrow the instance to type <code>java.awt.Component</code> * to display the object. * <p> * This view can also manage a set of parameters with limitations. * The parameters to the <object> element are expected to * be present on the associated elements attribute set as simple * strings. Each bean property will be queried as a key on * the AttributeSet, with the expectation that a non-null value * (of type String) will be present if there was a parameter * specification for the property. Reflection is used to * set the parameter. Currently, this is limited to a very * simple single parameter of type String. * <p> * A simple example HTML invocation is: * <pre> * <object classid="javax.swing.JLabel"> * <param name="text" value="sample text"> * </object> * </pre> * * @author Timothy Prinzing * @version 1.15 11/17/05 */ public class ObjectView extends ComponentView { /** * Creates a new ObjectView object. * * @param elem the element to decorate */ public ObjectView(Element elem) { super(elem); } /** * Create the component. The classid is used * as a specification of the classname, which * we try to load. */ protected Component createComponent() { AttributeSet attr = getElement().getAttributes(); String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID); try { Class c = Class.forName(classname, true,Thread.currentThread(). getContextClassLoader()); Object o = c.newInstance(); if (o instanceof Component) { Component comp = (Component) o; setParameters(comp, attr); return comp; } } catch (Throwable e) { // couldn't create a component... fall through to the // couldn't load representation. } return getUnloadableRepresentation(); } /** * Fetch a component that can be used to represent the * object if it can't be created. */ Component getUnloadableRepresentation() { // PENDING(prinz) get some artwork and return something // interesting here. Component comp = new JLabel("??"); comp.setForeground(Color.red); return comp; } /** * Get a Class object to use for loading the * classid. If possible, the Classloader * used to load the associated Document is used. * This would typically be the same as the ClassLoader * used to load the EditorKit. If the documents * ClassLoader is null, * <code>Class.forName</code> is used. */ private Class getClass(String classname) throws ClassNotFoundException { Class klass; Class docClass = getDocument().getClass(); ClassLoader loader = docClass.getClassLoader(); if (loader != null) { klass = loader.loadClass(classname); } else { klass = Class.forName(classname); } return klass; } /** * Initialize this component according the KEY/VALUEs passed in * via the <param> elements in the corresponding * <object> element. */ private void setParameters(Component comp, AttributeSet attr) { Class k = comp.getClass(); BeanInfo bi; try { bi = Introspector.getBeanInfo(k); } catch (IntrospectionException ex) { System.err.println("introspector failed, ex: "+ex); return; // quit for now } PropertyDescriptor props[] = bi.getPropertyDescriptors(); for (int i=0; i < props.length; i++) { // System.err.println("checking on props[i]: "+props[i].getName()); Object v = attr.getAttribute(props[i].getName()); if (v instanceof String) { // found a property parameter String value = (String) v; Method writer = props[i].getWriteMethod(); if (writer == null) { // read-only property. ignore return; // for now } Class[] params = writer.getParameterTypes(); if (params.length != 1) { // zero or more than one argument, ignore return; // for now } Object [] args = { value }; try { writer.invoke(comp, args); } catch (Exception ex) { System.err.println("Invocation failed"); // invocation code } } } } }