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