1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.swing.text.html; 26 27 import java.util.Enumeration; 28 import java.awt.*; 29 import javax.swing.*; 30 import javax.swing.text.*; 31 import java.beans.*; 32 import java.lang.reflect.*; 33 34 import sun.reflect.misc.MethodUtil; 35 import sun.reflect.misc.ReflectUtil; 36 37 /** 38 * Component decorator that implements the view interface 39 * for <object> elements. 40 * <p> 41 * This view will try to load the class specified by the 42 * <code>classid</code> attribute. If possible, the Classloader 43 * used to load the associated Document is used. 44 * This would typically be the same as the ClassLoader 45 * used to load the EditorKit. If the document's 46 * ClassLoader is null, <code>Class.forName</code> is used. 47 * <p> 48 * If the class can successfully be loaded, an attempt will 49 * be made to create an instance of it by calling 50 * <code>Class.newInstance</code>. An attempt will be made 51 * to narrow the instance to type <code>java.awt.Component</code> 52 * to display the object. 53 * <p> 54 * This view can also manage a set of parameters with limitations. 55 * The parameters to the <object> element are expected to 56 * be present on the associated elements attribute set as simple 57 * strings. Each bean property will be queried as a key on 58 * the AttributeSet, with the expectation that a non-null value 59 * (of type String) will be present if there was a parameter 60 * specification for the property. Reflection is used to 61 * set the parameter. Currently, this is limited to a very 62 * simple single parameter of type String. 63 * <p> 64 * A simple example HTML invocation is: 65 * <pre> 66 * <object classid="javax.swing.JLabel"> 67 * <param name="text" value="sample text"> 68 * </object> 69 * </pre> 70 * 71 * @author Timothy Prinzing 72 */ 73 public class ObjectView extends ComponentView { 74 75 /** 76 * Creates a new ObjectView object. 77 * 78 * @param elem the element to decorate 79 */ 80 public ObjectView(Element elem) { 81 super(elem); 82 } 83 84 /** 85 * Create the component. The classid is used 86 * as a specification of the classname, which 87 * we try to load. 88 */ 89 protected Component createComponent() { 90 AttributeSet attr = getElement().getAttributes(); 91 String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID); 92 try { 93 ReflectUtil.checkPackageAccess(classname); 94 Class c = Class.forName(classname, true,Thread.currentThread(). 95 getContextClassLoader()); 96 Object o = c.newInstance(); 97 if (o instanceof Component) { 98 Component comp = (Component) o; 99 setParameters(comp, attr); 100 return comp; 101 } 102 } catch (Throwable e) { 103 // couldn't create a component... fall through to the 104 // couldn't load representation. 105 } 106 107 return getUnloadableRepresentation(); 108 } 109 110 /** 111 * Fetch a component that can be used to represent the 112 * object if it can't be created. 113 */ 114 Component getUnloadableRepresentation() { 115 // PENDING(prinz) get some artwork and return something 116 // interesting here. 117 Component comp = new JLabel("??"); 118 comp.setForeground(Color.red); 119 return comp; 120 } 121 122 /** 123 * Initialize this component according the KEY/VALUEs passed in 124 * via the <param> elements in the corresponding 125 * <object> element. 126 */ 127 private void setParameters(Component comp, AttributeSet attr) { 128 Class k = comp.getClass(); 129 BeanInfo bi; 130 try { 131 bi = Introspector.getBeanInfo(k); 132 } catch (IntrospectionException ex) { 133 System.err.println("introspector failed, ex: "+ex); 134 return; // quit for now 135 } 136 PropertyDescriptor props[] = bi.getPropertyDescriptors(); 137 for (int i=0; i < props.length; i++) { 138 // System.err.println("checking on props[i]: "+props[i].getName()); 139 Object v = attr.getAttribute(props[i].getName()); 140 if (v instanceof String) { 141 // found a property parameter 142 String value = (String) v; 143 Method writer = props[i].getWriteMethod(); 144 if (writer == null) { 145 // read-only property. ignore 146 return; // for now 147 } 148 Class[] params = writer.getParameterTypes(); 149 if (params.length != 1) { 150 // zero or more than one argument, ignore 151 return; // for now 152 } 153 Object [] args = { value }; 154 try { 155 MethodUtil.invoke(writer, comp, args); 156 } catch (Exception ex) { 157 System.err.println("Invocation failed"); 158 // invocation code 159 } 160 } 161 } 162 } 163 164 }