Package org.knopflerfish.bundle.desktop.swing

Source Code of org.knopflerfish.bundle.desktop.swing.Util

/*
* Copyright (c) 2003-2010, 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 org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.startlevel.*;
import org.osgi.service.packageadmin.*;


import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.RenderingHints;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.*;
import javax.swing.*;

import org.knopflerfish.util.Text;

public class Util {

  public static String shortLocation(String s) {
    int ix = s.lastIndexOf("/");

    // handle eclipse extended location directory syntax
    if(s.endsWith("/")) {
      ix = s.lastIndexOf("/", ix - 1);
    }

    if(ix == -1) {
      ix = s.lastIndexOf("\\");
    }
    if(ix != -1) {
      return s.substring(ix + 1);
    }
    return s;
  }

  public static final String URL_BUNDLE_PREFIX = "http://desktop/bid/";
  public static final String URL_SERVICE_PREFIX = "http://desktop/sid/";
  public static final String URL_RESOURCE_PREFIX = "http://desktop/resource/";

  public static void bundleLink(StringBuffer sb, Bundle b) {
    sb.append("<a href=\"" + URL_BUNDLE_PREFIX + b.getBundleId() + "\">");
    sb.append(Util.getBundleName(b));
    sb.append("</a>");
  }

  public static void serviceLink(StringBuffer sb,
                                 ServiceReference sr,
                                 String txt) {
    sb.append("<a href=\"" + URL_SERVICE_PREFIX +
              sr.getProperty(Constants.SERVICE_ID) + "\">");
    sb.append(txt);
    sb.append("</a>");
  }

  public static void resourceLink(StringBuffer sb,
                                  String path) {
    sb.append("<a href=\"" + URL_RESOURCE_PREFIX + path + "\">");
    sb.append(path);
    sb.append("</a>");
  }

  public static boolean isBundleLink(URL url) {
    return url.toString().startsWith(URL_BUNDLE_PREFIX);
  }

  public static boolean isServiceLink(URL url) {
    return url.toString().startsWith(URL_SERVICE_PREFIX);
  }

  public static boolean isResourceLink(URL url) {
    return url.toString().startsWith(URL_RESOURCE_PREFIX);
  }

  public static String resourcePathFromURL(URL url) {
    if(!isResourceLink(url)) {
      throw new RuntimeException("URL '" + url + "' does not start with " +
                                 URL_RESOURCE_PREFIX);
    }
    return url.toString().substring(URL_RESOURCE_PREFIX.length());
  }

  public static long bidFromURL(URL url) {
    if(!isBundleLink(url)) {
      throw new RuntimeException("URL '" + url + "' does not start with " +
                                 URL_BUNDLE_PREFIX);
    }
    return Long.parseLong(url.toString().substring(URL_BUNDLE_PREFIX.length()));
  }

  public static long sidFromURL(URL url) {
    if(!isServiceLink(url)) {
      throw new RuntimeException("URL '" + url + "' does not start with " +
                                 URL_SERVICE_PREFIX);
    }
    return Long.parseLong(url.toString().substring(URL_SERVICE_PREFIX.length()));
  }

  public static String serviceEventName(int type) {
    switch(type) {
    case ServiceEvent.REGISTERED:    return "registered";
    case ServiceEvent.UNREGISTERING: return "unregistering";
    case ServiceEvent.MODIFIED:      return "modified";
    default:                      return "<" + type + ">";
    }
  }

  public static String bundleEventName(int type) {
    switch(type) {
    case BundleEvent.INSTALLED:   return "installed";
    case BundleEvent.STARTED:     return "started";
    case BundleEvent.STOPPED:     return "stopped";
    case BundleEvent.UNINSTALLED: return "uninstalled";
    case BundleEvent.UPDATED:     return "updated";
    case BundleEvent.RESOLVED:    return "resolved";
    case BundleEvent.UNRESOLVED:  return "unresolved";
    case BundleEvent.STARTING:    return "starting";
    case BundleEvent.STOPPING:    return "stopping";
    case BundleEvent.LAZY_ACTIVATION: return "lazyActivation";
    default:                      return "<" + type + ">";
    }
  }

  public static Object getProp(ServiceReference sr,
                               String key,
                               Object def) {
    Object obj = sr.getProperty(key);
    return obj != null ? obj : def;
  }

  public static String getStringProp(ServiceReference sr,
                                     String key,
                                     String def) {
    return (String)getProp(sr, key, def);
  }

  public static boolean getBooleanProp(ServiceReference sr,
                                       String key,
                                       boolean def) {
    return ((Boolean)getProp(sr, key, def ? Boolean.TRUE : Boolean.FALSE))
      .booleanValue();
  }

  public static String stateName(int state) {
    switch(state) {
    case Bundle.ACTIVE:
      return "active";
    case Bundle.INSTALLED:
      return "installed";
    case Bundle.UNINSTALLED:
      return "uninstalled";
    case Bundle.RESOLVED:
      return "resolved";
    case Bundle.STARTING:
      return "starting";
    case Bundle.STOPPING:
      return "stopping";
    default:
      return "unknown " + state;
    }
  }

  public static String getHeader(Bundle b, String name) {
    return getHeader(b, name, null);
  }

  public static String getHeader(Bundle b, String name, String def) {
    String s = b != null
      ? (String)b.getHeaders().get(name)
      : def;

    return s;
  }

  public static String getBundleName(Bundle b) {
    if(b == null) {
      return "null";
    }
    String s = getHeader(b, "Bundle-Name", "");
    if(s == null || "".equals(s) || s.startsWith("%")) {
      String loc = b.getLocation();
      if (loc != null) {
        s = shortLocation(b.getLocation());
      }
    }

    return s;
  }

  public static Bundle findBundleByHeader(BundleContext bc, String headerName, String headerValue) {
    if(headerName == null) {
      throw new NullPointerException("headerName cannot be null");
    }
    if(headerValue == null) {
      throw new NullPointerException("headerValue cannot be null");
    }
    Bundle[] bl = bc.getBundles();
    for(int i = 0; bl != null && i < bl.length; i++) {
      String v = getHeader(bl[i], headerName);
      if(headerValue.equals(v)) {
        return bl[i];
      }
    }
    return null;
  }

  public static boolean doAutostart() {
    return "true".equals(Util.getProperty("org.knopflerfish.desktop.autostart", "false"));
  }

  public static boolean canBeStarted(Bundle b) {
    return hasActivator(b) || hasMainClass(b) || hasComponent(b);
  }

  public static boolean hasActivator(Bundle b) {
    return null != getHeader(b, "Bundle-Activator");
  }

  public static boolean hasFragment(Bundle b) {
    return null != getHeader(b, "Fragment-Host");
  }

  public static boolean hasComponent(Bundle b) {
    return null != getHeader(b, "Service-Component");
  }

  public static boolean hasMainClass(Bundle b) {
    return null != getHeader(b, "Main-class");
  }

  static public String bundleInfo(Bundle b) {
    final StringBuffer sb = new StringBuffer();

    sb.append("<html>");
    sb.append(" Id: "       + b.getBundleId() + "<br>");
    sb.append(" Name: "     + Util.getBundleName(b) + "<br>");
    sb.append(" State: "    + Util.stateName(b.getState()) + "<br>");

    final StartLevel sls = (StartLevel) Activator.getStartLevelService();
    if(sls != null) {
      sb.append(" Start level: ");
      try {
        sb.append(sls.getBundleStartLevel(b));
      } catch (IllegalArgumentException e) {
        sb.append("not managed");
      }
      sb.append("<br>");
    }

    sb.append("</html>");
    return sb.toString();
  }

  // Bundle -> Icon
  static Map iconMap = new HashMap();

  // This constant should be in org.osgi.framework.Contants but is not...
  final static String BUNDLE_ICON = "Bundle-Icon";


  // Clear the bundle icon after an update of the bundle.
  public static void clearBundleIcon(Bundle b) {
    synchronized(iconMap) {
      iconMap.remove(b);
    }
  }

  // Get the bundle icon for a bundle. Icons are cached.
  public static Icon getBundleIcon(Bundle b) {
    synchronized(iconMap) {
      Class clazz = Util.class;
      Icon icon = (Icon)iconMap.get(b);
      if(icon != null) {
        return icon;
      }

      URL appURL = getBundleIconURL(b);
      if (null==appURL) {
        appURL = getApplicationIconURL(b);
      }

      try {
        if (appURL!=null) {
          icon = new BundleImageIcon(b, appURL);
        } else if(Util.hasMainClass(b)) {
          icon = new BundleImageIcon(b, clazz.getResource("/jarexec.png"));
        } else if(Util.hasFragment(b)) {
          icon = new BundleImageIcon(b, clazz.getResource("/frag.png"));
        } else if(Util.hasComponent(b)) {
          icon = new BundleImageIcon(b, clazz.getResource("/component.png"));
        } else if(Util.hasActivator(b)) {
          icon = new BundleImageIcon(b, clazz.getResource("/bundle.png"));
        } else {
          icon = new BundleImageIcon(b, clazz.getResource("/lib.png"));
        }
      } catch (Exception e) {
        Activator.log.error("Failed to load icon, appURL=" + appURL);
        icon = new BundleImageIcon(b, clazz.getResource("/bundle.png"));
      }
      iconMap.put(b, icon);
      return icon;
    }
  }

  // Get the bundle icon URL for icon with size 32 from the manifest
  // header "Bundle-Icon".
  private static URL getBundleIconURL(final Bundle b)
  {
    URL res = null;

    final String bih = (String) b.getHeaders().get(BUNDLE_ICON);
    if (null!=bih && 0<bih.length()) {
      // Re-uses the manifest entry parser from the KF-framework
      try {
        final Iterator it = org.knopflerfish.framework.Util
          .parseEntries(BUNDLE_ICON, bih, false, true, false);
        String iconName = null;
        int iconSize = -1;
        // We prefer a 32x32 size icon.
        while (it.hasNext()) {
          final Map entry = (Map) it.next();
          final List icns = (List) entry.get("$keys");
          final String sizeS = (String) entry.get("size");

          if (null==sizeS) {
            // Icon with unspecifeid size; use it if no other icon
            // has been found.
            if (null==iconName) {
              iconName= (String) icns.get(0);
            }
          } else {
            int size = -1;
            try {
              size = Integer.parseInt(sizeS);
            } catch (NumberFormatException nfe) {
            }
            if (-1<size) {
              if (-1==iconSize) {
                // First icon with a valid size; start with it.
                iconName= (String) icns.get(0);
                iconSize = size;
              } else if (Math.abs(size-32) < Math.abs(iconSize-32)) {
                // Icon is closer in size 32 than old icon; use it
                iconName= (String) icns.get(0);
                iconSize = size;
              }
            }
          }
        }
        if (null!=iconName) {
          try {
            try {
              res = new URL(iconName);
            } catch (MalformedURLException mfe) {
              // iconName is not a valid URL; assume it is a resource path
              res = b.getResource(iconName);
              if (null==res) {
                Activator.log.warn("Failed to load icon with name '"
                                    +iconName +"' from bundle #"
                                    +b.getBundleId() +" (" +getBundleName(b)
                                    +"): No such resource.");
              }
            }
          } catch (Exception e) {
            Activator.log.error("Failed to load icon with name '"
                                +iconName +"' from bundle #"
                                +b.getBundleId() +" (" +getBundleName(b)
                                +"): " +e.getMessage(), e);
          }
        }
      } catch (IllegalArgumentException iae) {
        Activator.log.error("Failed to parse Bundle-Icon header for #"
                            +b.getBundleId() +" (" +getBundleName(b)
                            +"): " +iae.getMessage(), iae);
      }
    }
    return res;
  }

  // Get the bundle icon URL for icon with size 32 from the
  // Knopflerfish defined manifest header "Application-Icon".
  private static URL getApplicationIconURL(final Bundle b)
  {
    URL res = null;

    String iconName = (String) b.getHeaders().get("Application-Icon");
    if(iconName != null) {
      iconName = iconName.trim();
    }

    if(iconName != null && 0<iconName.length()) {
      try {
        res = b.getResource(iconName);
        if (null==res) {
          Activator.log.warn("Failed to load icon with name '"
                             +iconName +"' from bundle #"
                             +b.getBundleId() +" (" +getBundleName(b)
                             +"): No such resource.");
        }
      } catch (Exception e) {
        Activator.log.error("Failed to load icon with name '"
                            +iconName +"' from bundle #"
                            +b.getBundleId() +" (" +getBundleName(b)
                            +"): " +e.getMessage(), e);
      }
    }
    return res;
  }


  public static Comparator bundleIdComparator = new BundleIdComparator();

  public static class BundleIdComparator implements Comparator {
    public int compare(Object o1, Object o2) {
      Bundle b1 = (Bundle)o1;
      Bundle b2 = (Bundle)o2;

      return (int)(b1.getBundleId() - b2.getBundleId());
    }

    public boolean equals(Object obj) {
      return obj.getClass().equals(BundleIdComparator.class);
    }
  }


// StringBuffer (red.green.blue) -> Color
  static Hashtable colors = new Hashtable();

  static int maxK = 256;

  public static Color rgbInterpolate(Color c1, Color c2, double k) {
    int K = (int)(maxK * k);

    if(c1 == null || c2 == null) {
      return Color.gray;
    }

    if(k <= 0.0) return c1;
    if(k >= 1.0) return c2;

    int r1 = c1.getRed();
    int g1 = c1.getGreen();
    int b1 = c1.getBlue();
    int r2 = c2.getRed();
    int g2 = c2.getGreen();
    int b2 = c2.getBlue();

    int r = (int)(r1 + (double)K * (r2 - r1) / maxK);
    int g = (int)(g1 + (double)K * (g2 - g1) / maxK);
    int b = (int)(b1 + (double)K * (b2 - b1) / maxK);

    Integer key = new Integer((r << 16) | (g << 8) | g);

    Color c = (Color)colors.get(key);
    if(c == null) {
      c = new Color(r, g, b);
      colors.put(key, c);
    }
    return c;
  }

  static Color rgbInterpolate2(Color c1, Color c2, double k) {

    if(c1 == null || c2 == null) {
      return Color.gray;
    }

    if(k == 0.0) return c1;
    if(k == 1.0) return c2;

    int r1 = c1.getRed();
    int g1 = c1.getGreen();
    int b1 = c1.getBlue();
    int r2 = c2.getRed();
    int g2 = c2.getGreen();
    int b2 = c2.getBlue();

    int r = (int)(r1 + (double)(r2 - r1));
    int g = (int)(g1 + (double)(g2 - g1));
    int b = (int)(b1 + (double)(b2 - b1));

    Color c = new Color(r, g, b);
    return c;
  }

    public static byte[] readStream(InputStream is) throws IOException {
      try {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        BufferedInputStream   bin = new BufferedInputStream(is);
        byte[] buf = new byte[1024 * 10];
        int len;
        while(-1 != (len = bin.read(buf))) {
          out.write(buf, 0, len);
        }
        return out.toByteArray();
      } finally {
        try { is.close(); } catch (Exception ignored) { }
      }
    }


    /**
     * Get transitive closure of a target bundle
     * by searching for all exporters to the target.
     *
     * @param pm      Package mananger
     * @param target  Target bundle to calculate closure for
     * @param handled Set of already scanned bundles. Should be
     *                null or empty set on top level call
     * @return        Set of <tt>Bundle</tt>
     */
    static public Set getPackageClosure(PackageManager pm,
                                        Bundle       target,
                                        Set          handled)
    {
      if(handled == null) {
        handled = new HashSet();
      }

      Set closure = new TreeSet(Util.bundleIdComparator);

      Collection importedPkgs = pm.getImportedPackages(target);

      for(Iterator it = importedPkgs.iterator(); it.hasNext();) {
        ExportedPackage pkg = (ExportedPackage)it.next();

        Bundle exporter = pkg.getExportingBundle();
        if (null==exporter) continue;

        closure.add(exporter);

        // Then, get closure from the exporter, if not already
        // handled. Add that closure set to the target closure.
        if(!handled.contains(exporter)) {
          handled.add(exporter);

          // call recursivly with exporter as target
          Set trans = getPackageClosure(pm, exporter, handled);
          closure.addAll(trans);
        }
      }
      /*
      // This is O(n2) at least, possibly O(n3). Should be improved
      for(int i = 0; i < allBundles.length; i++) {
        ExportedPackage[] pkgs = pkgAdmin.getExportedPackages(allBundles[i]);

        for(int j = 0; pkgs != null && j < pkgs.length; j++) {
          Bundle[] bl2 = pkgs[j].getImportingBundles();

          for(int k = 0; bl2 != null && k < bl2.length;  k++) {
            if(bl2[k].getBundleId() == target.getBundleId()) {

              // found an exporter to target - add it to closure
              closure.add(allBundles[i]);

              // Then, get closure from the exporter, if not already
              // handled. Add that closure set to the target closure.
              if(!handled.contains(allBundles[i])) {
                handled.add(allBundles[i]);

                // call recursivley with exporter as target
                Set trans =
                  getPackageClosure(pkgAdmin, allBundles, allBundles[i], handled);
                closure.addAll(trans);
              }
            }
          }
        }
      }
      */
      return closure;
    }

    /**
     * Get transitive closure of bundles a target bundle depends
     * on via services.
     *
     * @param target target bundle to get closure for
     * @param handles set of already handled bundles. Should be null or
     *                empty set on top level call.
     * @return        Set of <tt>Bundle</tt>
     */
    static public Set getServiceClosure(Bundle       target,
                                        Set          handled) {

      if(handled == null) {
        handled = new HashSet();
      }

      Set closure = new TreeSet(Util.bundleIdComparator);

      ServiceReference[] srl = target.getServicesInUse();

      for(int i = 0; srl != null && i < srl.length; i++) {
        Bundle b = srl[i].getBundle();
        if (null==b) continue; // Unregistered service.

        closure.add(b);

        if(!handled.contains(b)) {
          handled.add(b);

          Set trans = getServiceClosure(b, handled);
          closure.addAll(trans);
        }
      }

      return closure;
    }

  static String[] STD_PROPS = {
    "org.knopflerfish.verbosity=0",
    "org.knopflerfish.gosg.jars",
    "org.knopflerfish.framework.debug.packages=false",
    "org.knopflerfish.framework.debug.errors=false",
    "org.knopflerfish.framework.debug.classloader=false",
    "org.knopflerfish.framework.debug.startlevel=false",
    "org.knopflerfish.framework.debug.ldap=false",
    "org.osgi.framework.system.packages=",
    "org.knopflerfish.http.dnslookup=false",
    "org.knopflerfish.startlevel.use=true",
    "org.knopflerfish.log.out=false",
    "org.knopflerfish.log.level=info",
  };

  public static StringBuffer getXARGS(Bundle target,
                                      Set pkgClosure,
                                      Set serviceClosure) {

    StringBuffer sb = new StringBuffer();

    String jarBase = Util.getProperty("org.knopflerfish.gosg.jars", "");

    Set all = new TreeSet(Util.bundleIdComparator);
    all.addAll(pkgClosure);
    all.addAll(serviceClosure);

    all.remove(Activator.getTargetBC_getBundle(0));
    if(target != null) {
      all.add(target);
    }
    for(int i = 0; i < STD_PROPS.length; i++) {
      String[] w = Text.splitwords(STD_PROPS[i], "=", '\"');
      String def = null;
      if(w.length == 2) {
        def = w[1];
      }
      String val = Util.getProperty(w[0],null);
      if(null != val && !val.equals(def)) {
        sb.append("-D" + w[0] + "=" + val);
        sb.append("\n");
      }
    }

    StartLevel sl = (StartLevel)Activator.desktop.slTracker.getService();

    int levelMax = -1;

    int n = 0;
    int lastLevel = -1;
    for(Iterator it = all.iterator(); it.hasNext(); ) {
      Bundle b = (Bundle)it.next();
      int level = -1;
      try {
        level = sl.getBundleStartLevel(b);
      } catch (Exception ignored) {
      }

      levelMax = Math.max(level, levelMax);
      if(level != -1 && level != lastLevel) {
        sb.append("-initlevel " + level + "\n");

        lastLevel = level;
      }
      sb.append("-install " +
                Text.replace(b.getLocation(), jarBase, "") +
                "\n");

      n++;
    }

    sb.append("-launch\n");

    n = 0;
    for(Iterator it = all.iterator(); it.hasNext(); ) {
      Bundle b = (Bundle)it.next();
      n++;
      if(b.getState() == Bundle.ACTIVE) {
        sb.append("-start " + n + "\n");
      }
    }

    if(levelMax != -1) {
      sb.append("-startlevel " + levelMax);
    }

    return sb;
  }

  public static final String[] FWPROPS = new String[] {
    Constants.FRAMEWORK_VENDOR,
    Constants.FRAMEWORK_VERSION,
    Constants.FRAMEWORK_LANGUAGE,
    Constants.FRAMEWORK_OS_NAME,
    Constants.FRAMEWORK_OS_VERSION,
    Constants.FRAMEWORK_PROCESSOR,
    Constants.FRAMEWORK_EXECUTIONENVIRONMENT,
    Constants.FRAMEWORK_BOOTDELEGATION,
    Constants.FRAMEWORK_STORAGE,
    Constants.FRAMEWORK_STORAGE_CLEAN,
    Constants.FRAMEWORK_TRUST_REPOSITORIES,
    Constants.FRAMEWORK_EXECPERMISSION,
    Constants.FRAMEWORK_LIBRARY_EXTENSIONS,
    Constants.FRAMEWORK_BEGINNING_STARTLEVEL,
    Constants.FRAMEWORK_BUNDLE_PARENT,
    Constants.FRAMEWORK_WINDOWSYSTEM,
    Constants.FRAMEWORK_SECURITY,
    Constants.SUPPORTS_FRAMEWORK_EXTENSION,
    Constants.SUPPORTS_FRAMEWORK_FRAGMENT,
    Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE,
  };

  static public String getSystemInfo() {
    final StringBuffer sb = new StringBuffer();

    try {
      final Map props = new TreeMap(Activator.getSystemProperties());

      sb.append("<table>\n");

      sb.append(" <tr><td colspan=2 bgcolor=\"#eeeeee\">");
      sb.append(fontify("OSGi specified Framework properties", -1));

      String spid = Activator.getBC().getProperty("org.osgi.provisioning.spid");
      if(spid != null && !"".equals(spid)) {
        sb.append(fontify(" (" + spid + ")", -1));
      }

      sb.append("</td>\n");
      sb.append(" </tr>\n");


      for(int i = 0; i < FWPROPS.length; i++) {
        sb.append(" <tr>\n");
        sb.append("  <td valign=\"top\">");
        sb.append(fontify(FWPROPS[i]));
        sb.append("</td>\n");
        sb.append("  <td valign=\"top\">");
        final String pValue = Activator.getTargetBC_getProperty(FWPROPS[i]);
        sb.append(null!=pValue ? fontify(pValue) : "");
        sb.append("</td>\n");
        sb.append(" </tr>\n");
      }

      sb.append("<tr><td colspan=2 bgcolor=\"#eeeeee\">");
      sb.append(fontify("All Framework and System properties", -1));
      sb.append("</td>\n");
      sb.append("</tr>\n");


      for(Iterator it = props.keySet().iterator(); it.hasNext();) {
        String key = (String)it.next();
        String val = (String)props.get(key);
        sb.append(" <tr>\n");
        sb.append("  <td valign=\"top\">");
        sb.append(fontify(key));
        sb.append("</td>\n");
        sb.append("  <td valign=\"top\">");
        sb.append(fontify(val));
        sb.append("</td>\n");
        sb.append("</tr>\n");
      }

    } catch (Exception e) {
      sb.append("<tr><td colspan=2>" +
                fontify("Failed to get system props: " + e) +
                "</td></tr>");

    }
    sb.append("</table>");

    return sb.toString();
  }

  static public String fontify(Object o) {
    return fontify(o, -2);
  }

  public static String fontify(Object o, int size) {
    return "<font size=\"" + size + "\" face=\"Verdana, Arial, Helvetica, sans-serif\">" + o + "</font>";
  }


  static public void printObject(PrintWriter out, Object val) throws IOException {
    if(val == null) {
      out.println("null");
    } else if(val.getClass().isArray()) {
      printArray(out, val);
    } else if(val instanceof Vector) {
      printVector(out, (Vector)val);
    } else if(val instanceof Map) {
      printMap(out, (Map)val);
    } else if(val instanceof Set) {
      printSet(out, (Set)val);
    } else if(val instanceof Dictionary) {
      printDictionary(out, (Dictionary)val);
    } else {
      out.print(Util.fontify(val));
      //      out.print(" (" + val.getClass().getName() + ")");
    }
  }

  static public void printDictionary(PrintWriter out, Dictionary d) throws IOException {

    out.println("<table border=0>");
    for(Enumeration e = d.keys(); e.hasMoreElements();) {
      Object key = e.nextElement();
      Object val = d.get(key);
      out.println("<tr>");

      out.println("<td valign=top>");
      printObject(out, key);
      out.println("</td>");

      out.println("<td valign=top>");
      printObject(out, val);
      out.println("</td>");

      out.println("</tr>");
    }
    out.println("</table>");
  }

  static public void printMap(PrintWriter out, Map m) throws IOException {

    out.println("<table border=0>");
    for(Iterator it = m.keySet().iterator(); it.hasNext();) {
      Object key = it.next();
      Object val = m.get(key);

      out.println("<tr>");

      out.println("<td valign=top>");
      printObject(out, key);
      out.println("</td>");

      out.println("<td valign=top>");
      printObject(out, val);
      out.println("</td>");

      out.println("</tr>");
    }
    out.println("</table>");
  }

  static public void printArray(PrintWriter out, Object a) throws IOException {
    int length = Array.getLength(a);
    for(int i = 0; i < length; i++) {
      printObject(out, Array.get(a,i));
      if(i < length - 1) {
        out.println("<br>");
      }
    }
  }

  static public void printSet(PrintWriter out, Set a) throws IOException {
    for(Iterator it = a.iterator(); it.hasNext();) {
      printObject(out, it.next());
      if(it.hasNext()) {
        out.println("<br>");
      }
    }
  }

  static public void printVector(PrintWriter out, Vector a) throws IOException {
    for(int i = 0; i < a.size(); i++) {
      printObject(out, a.elementAt(i));
      if(i < a.size() - 1) {
        out.println("<br>");
      }
    }
  }


  static public void openExternalURL(URL url) throws IOException {
    if(Util.isWindows()) {
      // Yes, this only works on windows
      String systemBrowser = "explorer.exe";
      Runtime rt = Runtime.getRuntime();
      Process proc = rt.exec(new String[] {
        systemBrowser,
        "\"" + url.toString() + "\"",
      });
      new StreamGobbler(proc.getErrorStream());
      new StreamGobbler(proc.getInputStream());
    } else if (OSXAdapter.isMacOSX()) {
      // Yes, this only works on Mac OS X
      Runtime rt = Runtime.getRuntime();
      Process proc = rt.exec(new String[] {
        "/usr/bin/open",
        url.toString(),
      });
      new StreamGobbler(proc.getErrorStream());
      new StreamGobbler(proc.getInputStream());
    } else {
      throw new IOException
        ("Only windows and Mac OS X browsers are yet supported");
    }
  }

  public static boolean isWindows() {
    String os = Util.getProperty("os.name", null);
    if(os != null) {
      return -1 != os.toLowerCase().indexOf("win");
    }
    return false;
  }

  /** A thread that empties an input stream without complaining.*/
  static class StreamGobbler extends Thread
  {
    InputStream is;
    StreamGobbler(InputStream is)
    {
      this.is = is;
      start();
    }

    public void run()
    {
      BufferedReader br = new BufferedReader(new InputStreamReader(is));
      String line = "";
      try {
        while (null!=line) {
          line = br.readLine();
        }
      } catch (IOException _ioe) {
      }
    }
  }

  public static String getProperty(String key, String def)
  {
    String sValue = Activator.getBC().getProperty(key);
    if (null!=sValue && 0<sValue.length()) {
      return sValue;
    }
    return def;
  }

  public static int getIntProperty(String key, int def)
  {
    String sValue = Activator.getBC().getProperty(key);
    if (null!=sValue && 0<sValue.length()) {
      try {
        return Integer.parseInt(sValue);
      } catch (Exception _e) {
      }
    }
    return def;
  }


  public static boolean getBooleanProperty(String key, boolean def)
  {
    String sValue = Activator.getBC().getProperty(key);
    if (null!=sValue && 0<sValue.length()) {
      return "true".equals(sValue);
    }
    return def;
  }


  /**
   * Try to get the BundleContext from a Bundle instance using
   * various known backdoors (we don't really rely on R4.1 yet)
   */
  public static BundleContext getBundleContext(Bundle b) {
    Class clazz = b.getClass();
    try {
      // getBundleContext() is an R4.1 method, but try to grab it
      // using reflection and punch a hole in the method modifiers.
      // Should work on recent KF and recent Felix.
      Method m =  clazz.getMethod("getBundleContext", new Class[] { });

      m.setAccessible(true);
      return (BundleContext)m.invoke(b, new Object[] { });
    } catch (Exception e) {
      Activator.log.debug("Failed to call Bundle.getBundleContext()", e);

      // Try some known private fields.
      String[] fieldNames = new String[] {
        "bundleContext", // available in KF
        "context",       // available in Equinox and Concierge
      };
      for(int i = 0; i < fieldNames.length; i++) {
        try {
          Activator.log.debug("Try field " + clazz.getName() + "." + fieldNames[i]);

          Field field = clazz.getDeclaredField(fieldNames[i]);
          field.setAccessible(true);
          return (BundleContext)field.get(b);
        } catch (Exception e2) {
          Activator.log.info("Failed: field " + clazz.getName() + "." + fieldNames[i], e2);
        }
      }
    }
    Activator.log.warn("Failed to get BundleContext from " + clazz.getName());
    return null;
  }

  public static String getServiceInfo(ServiceReference sr) {
    StringBuffer sb = new StringBuffer();

    sb.append(sr.getProperty("service.id") + ": " + getClassNames(sr));
    sb.append("\n");
    sb.append("from #" + sr.getBundle().getBundleId());
    sb.append(" " + Util.getBundleName(sr.getBundle()));



    Bundle[] bl = sr.getUsingBundles();
    if(bl != null) {
      sb.append("\nto ");
      for(int i = 0; i < bl.length; i++) {
        sb.append("#" + bl[i].getBundleId());
        sb.append(" " + Util.getBundleName(bl[i]));
        if(i < bl.length -1) {
          sb.append("\n");
        }
      }
    }
    return sb.toString();
  }


  public static String getClassNames(ServiceReference sr) {
    return getClassNames(sr, "\n");
  }

  public static String getClassNames(ServiceReference sr, String sep) {

    StringBuffer sb = new StringBuffer();
    String sa[] = (String[])sr.getProperty("objectClass");
    for(int j = 0; j < sa.length; j++) {
      sb.append(sa[j]);
      if(j < sa.length - 1) {
        sb.append(sep);
      }
    }
    return sb.toString();
  }

  static public void setAntialias(Graphics g, boolean b) {
    Graphics2D g2 = (Graphics2D)g;
    if(b) {
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_ON);
    } else {
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_OFF);
    }
  }

}
TOP

Related Classes of org.knopflerfish.bundle.desktop.swing.Util

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.