1 /*
   2  * $Id$
   3  *
   4  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   5  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   6  *
   7  * This code is free software; you can redistribute it and/or modify it
   8  * under the terms of the GNU General Public License version 2 only, as
   9  * published by the Free Software Foundation.  Oracle designates this
  10  * particular file as subject to the "Classpath" exception as provided
  11  * by Oracle in the LICENSE file that accompanied this code.
  12  *
  13  * This code is distributed in the hope that it will be useful, but WITHOUT
  14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16  * version 2 for more details (a copy is included in the LICENSE file that
  17  * accompanied this code).
  18  *
  19  * You should have received a copy of the GNU General Public License version
  20  * 2 along with this work; if not, write to the Free Software Foundation,
  21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  22  *
  23  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  24  * or visit www.oracle.com if you need additional information or have any
  25  * questions.
  26  */
  27 package com.sun.javatest.tool;
  28 
  29 import com.sun.javatest.tool.jthelp.HelpBroker;
  30 import com.sun.javatest.tool.jthelp.JHelpContentViewer;
  31 
  32 import java.awt.event.MouseAdapter;
  33 import java.awt.event.MouseEvent;
  34 import java.io.BufferedReader;
  35 import java.io.InputStreamReader;
  36 import java.lang.reflect.Method;
  37 import javax.swing.SwingUtilities;
  38 
  39 /**
  40  * This link type opens in external browser if current OS supports awt.Desktop
  41  *
  42  * usage:
  43  * <object classid="java:com.sun.javatest.tool.HelpExternalLink">
  44  * <param name="text" value=...>
  45  * <param name="target" value="http://...">
  46  * </object>
  47  * note that the protocol should be specified in the URL path (e.g. value="http://www.google.com")
  48  * @see HelpLink
  49  */
  50 public class HelpExternalLink extends HelpLink {
  51 
  52     public HelpExternalLink() {
  53         super(null);
  54         this.addMouseListener(new MouseAdapter() {
  55 
  56             @Override
  57             public void mousePressed(MouseEvent e) {
  58                 if (!openUrl(getTarget())) {
  59                     JHelpContentViewer cv = (JHelpContentViewer) SwingUtilities.getAncestorOfClass(JHelpContentViewer.class, e.getComponent());
  60                     HelpBroker hb = (HelpBroker) (cv.getClientProperty(HELPBROKER_FOR_HELPLINK));
  61                     hb.displayCurrentID(getTarget());
  62                 }
  63             }
  64         });
  65     }
  66 
  67     public static boolean openUrl(String url) {
  68         String os = System.getProperty("os.name");
  69         try {
  70             if (os != null) {
  71                 if (os.startsWith("Windows")) {
  72                     // rundll32 allows to open a file in appropriate default application
  73                     Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url);
  74                 } else if (os.startsWith("Mac OS")) {
  75                     Class<?> fileMgr = Class.forName("com.apple.eio.FileManager");
  76                     Method openURL = fileMgr.getDeclaredMethod("openURL",
  77                             new Class<?>[]{String.class});
  78                     openURL.invoke(null, new Object[]{url});
  79                 } else {
  80                     String[] commands = {
  81                         // xdg-open is used on some linux systems to open files types in default applications
  82                         "xdg-open", "firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape"};
  83                     String resultCommand = null;
  84                     for (int i = 0; i < commands.length && resultCommand == null; i++) {
  85                         Process process = Runtime.getRuntime().exec(new String[]{"which", commands[i]});
  86                         // IOException is thrown if there is no "which" command in the system, false returned - cannot find browser
  87                         BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
  88 
  89                         int time = 0;
  90                         int exitValue = -1;
  91                         // don't want to catch a lock - waiting 10 seconds for result
  92                         while(true) {
  93                             try {
  94                                 exitValue = process.exitValue();
  95                                 break;
  96                             } catch(IllegalThreadStateException e) {
  97                             }
  98                             if(time >= 10000) {
  99                                 process.destroy();
 100                                 break;
 101                             }
 102                             Thread.sleep(100);
 103                             time += 100;
 104                         }
 105 
 106                         String result = in.readLine();
 107                         // can't just check exitValue - "which" command works in other way in Solaris
 108                         if(result.startsWith("/") && result.endsWith(commands[i]) && exitValue == 0)
 109                             resultCommand = commands[i];
 110                     }
 111                     if(resultCommand == null)
 112                         return false;
 113                     // starting browser
 114                     Runtime.getRuntime().exec(new String[] {resultCommand, url});
 115                 }
 116             }
 117         } catch (Exception e) {
 118             return false;
 119         }
 120         return true;
 121     }
 122 }