在OSGi环境的JavaHelp页面中嵌入Swing组件?
JavaHelp是Sun编写的一个库,它在Swing应用程序中显示HTML帮助页面。JavaHelp允许将Swing组件嵌入其HTML页面:在OSGi环境的JavaHelp页面中嵌入Swing组件?,osgi,javahelp,Osgi,Javahelp,JavaHelp是Sun编写的一个库,它在Swing应用程序中显示HTML帮助页面。JavaHelp允许将Swing组件嵌入其HTML页面: <html> <object classid="java:javax.swing.JButton"> <param name="text" value="Wow, a Swing component in HTML HTML!"> </object> </html> 这里将进一步讨论这
<html>
<object classid="java:javax.swing.JButton">
<param name="text" value="Wow, a Swing component in HTML HTML!">
</object>
</html>
这里将进一步讨论这一点:
我正在ApacheFelix中运行一个大型OSGi应用程序。如上所示,
classid
属性指的是我要嵌入的Swing组件类的FQN。我希望这是指我在自己的包中定义的Swing组件类。因为JavaHelp在自己的包中运行,所以它不能引用我的包中的类。我只是在HTML页面中看到?
,表示找不到该类。如何让JavaHelp捆绑包引用捆绑包中的类?这只能部分实现。原因如下
要解决这个问题,我们必须创建自己的HTMLEditorKit
,它拦截对象
标记,然后从对象
标记的classid
创建组件
。下面是它的样子*
public class OurHTMLEditorKit extends HTMLEditorKit {
public ViewFactory getViewFactory() {
return new HTMLEditorKit.HTMLFactory() {
public View create(Element elem) {
if (elem.getName().equalsIgnoreCase("object"))
return new InternalObjectView(elem);
else
return super.create(elem);
}
};
}
}
private static Object attemptToGetClass(final String className) {
try {
Class c = Class.forName(className);
Object o = c.newInstance();
return o;
} catch (Exception e) {
logger.error(e.getMessage());
}
return null;
}
private static class InternalObjectView extends ObjectView {
public InternalObjectView(Element elem) {
super(elem);
logger.info(elem.toString());
}
protected Component createComponent() {
AttributeSet attrs = getElement().getAttributes();
String classname = ((String) attrs.getAttribute(HTML.Attribute.CLASSID)).trim();
try {
Component comp = (Component) attemptToGetClass(classname);
setParameters(comp, attrs);
return comp;
} catch (Exception e) {
logger.warn(e.getMessage());
}
return getUnloadableRepresentation();
}
// Copied from javax.swing.text.html.ObjectView with modifications to how exceptions are reported
Component getUnloadableRepresentation() {
Component comp = new JLabel("??");
comp.setForeground(Color.red);
return comp;
}
private void setParameters(Component comp, AttributeSet attr) {
Class k = comp.getClass();
BeanInfo bi;
try {
bi = Introspector.getBeanInfo(k);
} catch (IntrospectionException ex) {
logger.warn("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) {
logger.warn("Invocation failed: " + ex.getMessage());
// invocation code
}
}
}
}
}
公共类OurHTMLEditorKit扩展HTMLEditorKit{
公共ViewFactory getViewFactory(){
返回新的HTMLEditorKit.HTMLFactory(){
公共视图创建(元素元素){
if(elem.getName().equalsIgnoreCase(“对象”))
返回新的InternalObjectView(elem);
其他的
返回super.create(elem);
}
};
}
}
私有静态对象attemptToGetClass(最终字符串类名){
试一试{
类别c=类别forName(类别名称);
对象o=c.newInstance();
返回o;
}捕获(例外e){
logger.error(例如getMessage());
}
返回null;
}
私有静态类InternalObjectView扩展了ObjectView{
公共内部对象视图(元素元素元素){
超级(elem);
logger.info(elem.toString());
}
受保护的组件createComponent(){
AttributeSet attrs=getElement().getAttributes();
String classname=((String)attrs.getAttribute(HTML.Attribute.CLASSID)).trim();
试一试{
组件comp=(组件)attemptToGetClass(类名);
设置参数(组件、属性);
返回补偿;
}捕获(例外e){
logger.warn(例如getMessage());
}
返回getUnloadableRepresentation();
}
//从javax.swing.text.html.ObjectView复制,修改了异常报告的方式
组件getUnloadableRepresentation(){
组件组件=新的JLabel(“??”);
组件设置前景(颜色为红色);
返回补偿;
}
私有void setParameters(组件组件、属性集属性){
k类=comp.getClass();
比尼福比;
试一试{
bi=内省者。getBeanInfo(k);
}捕获(内省例外){
logger.warn(“内省器失败,ex:+ex”);
return;//暂时退出
}
PropertyDescriptor props[]=bi.getPropertyDescriptors();
for(int i=0;i
但是有了JavaHelp,使用
标记[2]无法注册我们的HTMLEditorKit
。由于OSGi环境的原因,JavaHelp无法访问我们的HTMLEditorKit
**
相反,唯一可行的方法是使用我们的HTMLEditorKit
创建一个JEditorPane
,使用TOCView.parse()
创建我们自己的TOCJTree
,并在JTree
的选择更改时告诉JEditorPane
加载帮助页面
*这看起来很长,但大部分代码都是从
javax.swing.text.html.ObjectView
[1]复制的。我不得不从那里复制代码,因为getUnloadableMresentation
和setParameters
是私有的,不受保护
**这可能是由于动态ImportPackage
清单条目[3]造成的。但这需要跨越很多障碍。首先,必须更改JavaHelp清单。其次,Felix启动后,必须告诉它允许使用动态导入
命令进行动态导入
我怀疑这将是一次痛苦的经历,因为我认为JavaHelp只是做了一个Class.forName。您将不得不求助于动态导入,我不知道这是否值得。这是否需要修改JavaHelp jar以在清单中包含
Dynamic PackageImport
条目,然后在Felix中使用Dynamic Import
命令?还是有更简单的方法?我发现动态导入
会导致其他bundle神秘地停止。而且JavaHelp仍然找不到我的类。而且,事实证明真正的罪魁祸首甚至不在JavaHelp中,而是在HTMLEditorKit
的ObjectView
: