/*
* Copyright (c) 2003, KNOPFLERFISH project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* - Neither the name of the KNOPFLERFISH project nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.knopflerfish.bundle.desktop.swing;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
/**
* Utiliy swing component which display bundle info as
* HTML.
*
*
* Intended to be used as base class. Subclasses should override
* the valueChanged method and retur an HTML string.
*
*
*
* If the Util.bundleLink method is used to create
* text for bundles, these will become selection links for
* the bundle.
*
*/
public abstract class JHTMLBundle extends JPanel {
JPanel panel;
JTextPane html;
JScrollPane scroll;
DefaultSwingBundleDisplayer displayer;
ArrayList historyBack = new ArrayList();
ArrayList historyFwd = new ArrayList();
JButton backButton = null;
JButton fwdButton = null;
private long currentBid = -1;
JHTMLBundle(DefaultSwingBundleDisplayer _displayer) {
setLayout(new BorderLayout());
this.displayer = _displayer;
html = new JTextPane();
html.setText(Strings.get("bundleinfo_startup"));
html.setContentType("text/html");
html.setEditable(false);
html.addHyperlinkListener(new HyperlinkListener()
{
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
URL url = e.getURL();
if(Util.isBundleLink(url)) {
long bid = Util.bidFromURL(url);
if(getCurrentBID() != -1) {
historyBack.add(new Long(getCurrentBID()));
backButton.setEnabled(!historyBack.isEmpty());
}
displayer.getBundleSelectionModel().clearSelection();
displayer.getBundleSelectionModel().setSelected(bid, true);
} else if(Util.isServiceLink(url)) {
long sid = Util.sidFromURL(url);
if(getCurrentBID() != -1) {
historyBack.add(new Long(getCurrentBID()));
backButton.setEnabled(!historyBack.isEmpty());
}
setServiceHTML(sid);
} else {
try {
Util.openExternalURL(url);
} catch (Exception e2) {
Activator.log.error("Failed to open url " + url, e2);
}
}
}
}
}
);
scroll =
new JScrollPane(html,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
html.setPreferredSize(new Dimension(300, 300));
JToolBar cmds = new JToolBar() {
{
add(backButton = new JButton(Activator.desktop.prevIcon) {
{
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
if(!historyBack.isEmpty()) {
Long bid = (Long)historyBack.get(historyBack.size()-1);
historyBack.remove(historyBack.size()-1);
if(getCurrentBID() != -1) {
historyFwd.add(new Long(getCurrentBID()));
}
// System.out.println("back to " + bid);
gotoBid(bid.longValue());
}
backButton.setEnabled(historyBack.size() > 0);
fwdButton.setEnabled(historyFwd.size() > 0);
}
});
setToolTipText(Strings.get("tt_html_back"));
}
});
add(fwdButton = new JButton(Activator.desktop.nextIcon) {
{
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
if(historyFwd.size() > 0) {
Long bid = (Long)historyFwd.get(historyFwd.size()-1);
historyFwd.remove(historyFwd.size()-1);
if(getCurrentBID() != -1) {
historyBack.add(new Long(getCurrentBID()));
}
// System.out.println("fwd to " + bid);
gotoBid(bid.longValue());
}
backButton.setEnabled(historyBack.size() > 0);
fwdButton.setEnabled(historyFwd.size() > 0);
}
});
setToolTipText(Strings.get("tt_html_back"));
}
});
backButton.setEnabled(historyBack.size() > 0);
fwdButton.setEnabled(historyFwd.size() > 0);
}
};
cmds.setFloatable(false);
add(scroll, BorderLayout.CENTER);
add(cmds, BorderLayout.SOUTH);
valueChanged(null);
}
void gotoBid(long bid) {
displayer.getBundleSelectionModel().clearSelection();
displayer.getBundleSelectionModel().setSelected(bid, true);
}
void setServiceHTML(long sid) {
StringBuffer sb = new StringBuffer();
try {
ServiceReference[] srl =
Activator.getTargetBC().getServiceReferences(null,
"(" + Constants.SERVICE_ID + "=" + sid + ")");
if(srl != null && srl.length == 1) {
sb.append("");
sb.append("");
sb.append("| ");
startFont(sb, "-1");
sb.append("Service #" + sid);
sb.append(", ");
Util.bundleLink(sb, srl[0].getBundle());
sb.append("\n");
sb.append(" | \n");
sb.append("
\n");
sb.append("
");
startFont(sb);
sb.append("Properties");
sb.append("");
sb.append("");
String[] keys = srl[0].getPropertyKeys();
for(int i = 0; keys != null && i < keys.length; i++) {
StringWriter sw = new StringWriter();
PrintWriter pr = new PrintWriter(sw);
Util.printObject(pr, srl[0].getProperty(keys[i]));
sb.append("");
sb.append("| ");
startFont(sb);
sb.append(keys[i]);
stopFont(sb);
sb.append(" | ");
sb.append("");
sb.append(sw.toString());
sb.append(" | ");
sb.append("
");
}
sb.append("
");
try {
sb.append(formatServiceObject(srl[0]).toString());
} catch (Exception e) {
sb.append("Failed to format service object: " + e);
}
sb.append("");
} else {
sb.append("No service with sid=" + sid);
}
} catch (Exception e2) {
e2.printStackTrace();
}
setHTML(sb.toString());
}
StringBuffer formatServiceObject(ServiceReference sr) {
String[] names = (String[]) sr.getProperty(Constants.OBJECTCLASS);
StringBuffer sb = new StringBuffer();
startFont(sb);
sb.append("Implemented interfaces");
sb.append("
");
for(int i = 0; i < names.length; i++) {
sb.append(names[i]);
if(i < names.length -1) {
sb.append(", ");
}
}
sb.append("");
sb.append("
");
startFont(sb);
sb.append("Methods");
sb.append("");
for (int i=0; i| ");
startFont(sb);
sb.append("Class not found: ").append(names[i]);
sb.append(" | ");
}
}
sb.append("
");
return sb;
}
StringBuffer formatClass(Class clazz) {
Method[] methods = clazz.getDeclaredMethods();
StringBuffer sb = new StringBuffer();
sb.append("");
sb.append("| ");
startFont(sb);
sb.append(clazz.getName());
sb.append(" |
");
for(int i = 0; i < methods.length; i++) {
if(!Modifier.isPublic(methods[i].getModifiers())) {
continue;
}
Class[] params = methods[i].getParameterTypes();
sb.append("");
sb.append("| ");
startFont(sb);
sb.append(className(methods[i].getReturnType().getName()));
sb.append(" ");
sb.append(methods[i].getName());
sb.append("(");
for(int j = 0; j < params.length; j++) {
sb.append(className(params[j].getName()));
if(j < params.length - 1) {
sb.append(", ");
}
}
sb.append("); ");
sb.append("");
sb.append(" | ");
sb.append("
");
}
return sb;
}
String className(String name) {
if(name.startsWith("[L") && name.endsWith(";")) {
name = name.substring(2, name.length() - 1) + "[]";
}
if(name.startsWith("java.lang.")) {
name = name.substring(10);
}
return name;
}
/**
* Override this to provide special bundle info in HTML
* format.
*/
public abstract StringBuffer bundleInfo(Bundle b);
/**
* Get header text for no selected bundle page.
*/
public String getNoBundleSelectedHeader() {
return "No bundle selected";
}
/**
* Get main text for no selected bundle page.
*/
public String getNoBundleSelectedText() {
return
"Select one or more bundles in the main view to " +
"view detail information";
}
/**
* Get header text for selected bundle page.
*/
public String getBundleSelectedHeader(Bundle b) {
return
"#" + b.getBundleId() + " " + Util.getBundleName(b);
}
public void valueChanged(Bundle[] bl) {
StringBuffer sb = new StringBuffer("\n");
// System.out.println("valueChanged bl=" + (bl != null ? ("#" + bl.length) : "null"));
if(bl == null || bl.length == 0) {
sb.append("\n");
sb.append("\n");
sb.append("| ");
startFont(sb, "-1");
sb.append(getNoBundleSelectedHeader());
sb.append("\n");
sb.append(" | \n");
sb.append("
\n");
sb.append("
\n");
startFont(sb);
sb.append(getNoBundleSelectedText());
sb.append("\n" +
"\n" +
"");
} else {
if(bl.length == 1) {
if(bl[0].getBundleId() == getCurrentBID()) {
// System.out.println("skip already set bid=" + getCurrentBID());
// return;
}
}
// System.out.println("new bundle " + bl[0].getBundleId());
setCurrentBID(bl[0].getBundleId());
for(int i = 0; i < bl.length; i++) {
sb.append("\n");
sb.append("| ");
startFont(sb, "-1");
sb.append(getBundleSelectedHeader(bl[i]));
sb.append("\n");
sb.append(" | \n");
sb.append("
\n");
sb.append("| ");
sb.append(bundleInfo(bl[i]).toString());
sb.append(" | \n");
sb.append("
\n");
sb.append("
\n");
}
}
sb.append("\n");
setHTML(sb.toString());
}
protected void setCurrentBID(long bid) {
this.currentBid = bid;
}
public long getCurrentBID() {
return currentBid;
}
void setHTML(String s) {
html.setText(s);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
JViewport vp = scroll.getViewport();
if(vp != null) {
vp.setViewPosition(new Point(0,0));
scroll.setViewport(vp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
void appendRow(StringBuffer sb, String c1, String c2) {
sb.append("" +
" | ");
startFont(sb);
sb.append(c1);
sb.append("");
sb.append(" | \n");
sb.append(" ");
startFont(sb);
sb.append(c2);
sb.append(" | \n" +
"
\n");
}
void startFont(StringBuffer sb) {
startFont(sb, "-2");
}
void stopFont(StringBuffer sb) {
sb.append("");
}
void startFont(StringBuffer sb, String size) {
sb.append("");
}
}