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