java Desktop支持

package org.liufei.jweb.util;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 桌面启动器工兄1�7
 * 
 * @author 刘飞
 * 
 */
public class DesktopUtil {
	private static final Logger log = Logger.getLogger(DesktopUtil.class
			.getName());

	private static final String OS_MACOS = "Mac OS";
	private static final String OS_WINDOWS = "Windows";

	private static final String[] UNIX_BROWSE_CMDS = { "www-browser",
			"firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape",
			"w3m", "lynx" };

	private static final String[] UNIX_OPEN_CMDS = { "run-mailcap", "pager",
			"less", "more" };

	private DesktopUtil() {
	}

	/**
	 * 使用系统默认浏览器启动指定URL指向的地坄1�7〄1�7
	 * 
	 * @param url
	 *            the URL to open
	 * @throws IOException
	 *             if a browser couldn't be found or if the URL failed to launch
	 */
	public static void browse(final URL url) throws IOException {
		// Try Java 1.6 Desktop class if supported
		if (browseDesktop(url))
			return;

		final String osName = System.getProperty("os.name");
		log.finer("Launching " + url + " for OS " + osName);

		if (osName.startsWith(OS_MACOS)) {
			browseMac(url);
		} else if (osName.startsWith(OS_WINDOWS)) {
			browseWindows(url);
		} else {
			// assume Unix or Linux
			browseUnix(url);
		}
	}

	/**
	 * 使用系统默认浏览器启动指定URL指向的地坄1�7, 错误时给出提示对话框〄1�7
	 * 
	 * @param url
	 *            the URL to open
	 * @param parentComponent
	 *            The parent Component over which the error dialog should be
	 *            shown
	 */
	public static void browseAndWarn(final URL url,
			final Component parentComponent) {
		try {
			browse(url);
		} catch (final IOException e) {
			log.log(Level.SEVERE, "Unable to browse to " + url, e);
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					JOptionPane.showMessageDialog(parentComponent,
							"Couldn't open a web browser:\n"
									+ e.getLocalizedMessage(),
							"Unable to launch web browser",
							JOptionPane.ERROR_MESSAGE);
				}
			});
		}
	}

	/**
	 * 使用系统默认浏览器启动指定URL指向的地坄1�7, 错误时给出提示对话框〄1�7
	 * 
	 * @param url
	 *            the URL to open
	 * @param parentComponent
	 *            The parent Component over which the error dialog should be
	 *            shown
	 */
	public static void browseAndWarn(final String url,
			final Component parentComponent) {
		try {
			browse(new URL(url));
		} catch (final IOException e) {
			log.log(Level.SEVERE, "Unable to browse to " + url, e);
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					JOptionPane.showMessageDialog(parentComponent,
							"Couldn't open a web browser:\n"
									+ e.getLocalizedMessage(),
							"Unable to launch web browser",
							JOptionPane.ERROR_MESSAGE);
				}
			});
		}
	}

	/**
	 * 使用系统默认程序启动指定文件〄1�7
	 * 
	 * @param file
	 *            the File to open
	 * @throws IOException
	 *             if an application couldn't be found or if the File failed to
	 *             launch
	 */
	public static void open(final File file) throws IOException {
		// Try Java 1.6 Desktop class if supported
		if (openDesktop(file))
			return;

		final String osName = System.getProperty("os.name");
		log.finer("Opening " + file + " for OS " + osName);

		if (osName.startsWith(OS_MACOS)) {
			openMac(file);
		} else if (osName.startsWith(OS_WINDOWS)) {
			openWindows(file);
		} else {
			// assume Unix or Linux
			openUnix(file);
		}
	}

	/**
	 * 打开指定文件, 失败时在parentComponent指定的AWT组件前面弹出消息对话框�1�7�1�7
	 * 
	 * @param file
	 *            the File to open
	 * @param parentComponent
	 *            The parent Component over which the error dialog should be
	 *            shown
	 */
	public static void openAndWarn(final File file,
			final Component parentComponent) {
		try {
			open(file);
		} catch (final IOException e) {
			log.log(Level.SEVERE, "Unable to open " + file, e);
			SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					JOptionPane.showMessageDialog(parentComponent, "不能打开文件 "
							+ file + ":\n" + e.getLocalizedMessage(), "不能打开文件",
							JOptionPane.ERROR_MESSAGE);
				}
			});
		}
	}

	/**
	 * 不直接调用java.awt.Desktop籄1�7,
	 * 而是使用反射去加载java.awt.Desktop类,这样当jre版本小于1.6时就不会执行, true表示执行成功,
	 * false表示执行不成劄1�7, 即jre版本小于1.6
	 * 
	 * @param url
	 *            the URL to launch
	 * @return true if launch successful, false if we should fall back to other
	 *         methods
	 * @throws IOException
	 *             if Desktop was found, but the browse() call failed.
	 */
	private static boolean browseDesktop(final URL url) throws IOException {
		final Class<?> desktopClass = getDesktopClass();
		if (desktopClass == null)
			return false;

		final Object desktopInstance = getDesktopInstance(desktopClass);
		if (desktopInstance == null)
			return false;

		log.finer("Launching " + url + " using Desktop.browse()");

		try {
			final Method browseMethod = desktopClass.getDeclaredMethod(
					"browse", URI.class);
			browseMethod.invoke(desktopInstance, new URI(url.toExternalForm()));
			return true;
		} catch (InvocationTargetException e) {
			if (e.getCause() instanceof IOException) {
				throw (IOException) e.getCause();
			} else {
				log.log(Level.FINE, "Exception in Desktop operation", e);
				return false;
			}
		} catch (Exception e) {
			log.log(Level.FINE, "Exception in Desktop operation", e);
			return false;
		}
	}

	/**
	 * 在windows操作系统下使用url.dll打开指定URL地址〄1�7
	 * 
	 * @param url
	 *            the URL to launch
	 * @throws IOException
	 *             if the launch failed
	 */
	private static void browseWindows(final URL url) throws IOException {
		log.finer("Windows invoking rundll32");
		Runtime.getRuntime().exec(
				new String[] { "rundll32", "url.dll,FileProtocolHandler",
						url.toString() });
	}

	/**
	 * 在Unix系统下打弄1�7指定URL地址〄1�7
	 * 
	 * @param url
	 *            the URL to launch
	 * @throws IOException
	 *             if the launch failed
	 */
	private static void browseUnix(final URL url) throws IOException {
		for (final String cmd : UNIX_BROWSE_CMDS) {
			log.finest("Unix looking for " + cmd);
			if (unixCommandExists(cmd)) {
				log.finer("Unix found " + cmd);
				Runtime.getRuntime().exec(new String[] { cmd, url.toString() });
				return;
			}
		}
		throw new IOException("Could not find a suitable web browser");
	}

	/**
	 * 
	 * 通过反射使用com.apple.eio.FileManager籄1�7
	 * 
	 * @param url
	 *            the URL to launch
	 * @throws IOException
	 *             if the launch failed
	 */
	private static void browseMac(final URL url) throws IOException {
		try {
			final Class<?> fileMgr = getAppleFileManagerClass();
			final Method openURL = fileMgr.getDeclaredMethod("openURL",
					String.class);

			log.finer("Mac invoking");
			openURL.invoke(null, url.toString());
		} catch (Exception e) {
			log.log(Level.WARNING, "Couldn't launch Mac URL", e);
			throw new IOException("Could not launch Mac URL: "
					+ e.getLocalizedMessage());
		}
	}

	/**
	 * 不直接调用java.awt.Desktop籄1�7,
	 * 而是使用反射去加载java.awt.Desktop类,这样当jre版本小于1.6时就不会执行, true表示执行成功,
	 * false表示执行不成劄1�7, 即jre版本小于1.6
	 * 
	 * @param file
	 *            the File to open
	 * @return true if open successful, false if we should fall back to other
	 *         methods
	 * @throws IOException
	 *             if Desktop was found, but the open() call failed.
	 */
	private static boolean openDesktop(final File file) throws IOException {
		final Class<?> desktopClass = getDesktopClass();
		if (desktopClass == null)
			return false;

		final Object desktopInstance = getDesktopInstance(desktopClass);
		if (desktopInstance == null)
			return false;

		log.finer("Opening " + file + " using Desktop.open()");

		try {
			final Method browseMethod = desktopClass.getDeclaredMethod("open",
					File.class);
			browseMethod.invoke(desktopInstance, file);
			return true;
		} catch (InvocationTargetException e) {
			if (e.getCause() instanceof IOException) {
				throw (IOException) e.getCause();
			} else if (e.getCause() instanceof IllegalArgumentException) {
				throw new FileNotFoundException(e.getCause()
						.getLocalizedMessage());
			} else {
				log.log(Level.FINE, "Exception in Desktop operation", e);
				return false;
			}
		} catch (Exception e) {
			log.log(Level.FINE, "Exception in Desktop operation", e);
			return false;
		}
	}

	/**
	 * 在windows操作系统下使用shell32.dll打开指定文件〄1�7
	 * 
	 * @param file
	 *            the File to open
	 * @throws IOException
	 *             if the open failed
	 */
	private static void openWindows(final File file) throws IOException {
		log.finer("Windows invoking rundll32");
		Runtime.getRuntime().exec(
				new String[] { "rundll32", "shell32.dll,ShellExec_RunDLL",
						file.getAbsolutePath() });
	}

	/**
	 * 通过反射使用com.apple.eio.FileManager籄1�7
	 * 
	 * @param file
	 *            the File to open
	 * @throws IOException
	 *             if the open failed
	 */
	@SuppressWarnings("deprecation")
	private static void openMac(final File file) throws IOException {
		// we use openURL() on the file's URL form since openURL supports
		// file:// protocol
		browseMac(file.getAbsoluteFile().toURL());
	}

	/**
	 * 在Unix系统下打弄1�7指定文件〄1�7
	 * 
	 * @param file
	 *            the File to open
	 * @throws IOException
	 *             if the open failed
	 */
	private static void openUnix(final File file) throws IOException {
		for (final String cmd : UNIX_OPEN_CMDS) {
			log.finest("Unix looking for " + cmd);
			if (unixCommandExists(cmd)) {
				log.finer("Unix found " + cmd);
				Runtime.getRuntime().exec(
						new String[] { cmd, file.getAbsolutePath() });
				return;
			}
		}
		throw new IOException("Could not find a suitable viewer");
	}

	/**
	 * 判断当前系统的JRE是否有java.awt.Desktop类库, 即是否是jre1.6或其以上版本〄1�7
	 * 
	 * @return the Desktop class object, or null if it could not be found
	 */
	private static Class<?> getDesktopClass() {
		// NB The following String is intentionally not inlined to prevent
		// ProGuard trying to locate the unknown class.
		final String desktopClassName = "java.awt.Desktop";
		try {
			return Class.forName(desktopClassName);
		} catch (ClassNotFoundException e) {
			log.fine("Desktop class not found");
			return null;
		}
	}

	/**
	 * 
	 * 获取java.awt.Desktop类的实例,如果支持�1�7�我们检查isDesktopSupported()
	 *  但为了方便,我们也懒得去棄1�7查isSupported(方法),�1�7�是
	 * 调用者处理任何UnsupportedOperationExceptions
	 * 
	 * @param desktopClass
	 *            the Desktop Class object
	 * @return the Desktop instance, or null if it is not supported
	 */
	private static Object getDesktopInstance(final Class<?> desktopClass) {
		try {
			final Method isDesktopSupportedMethod = desktopClass
					.getDeclaredMethod("isDesktopSupported");
			log.finest("invoking isDesktopSupported");
			final boolean isDesktopSupported = (Boolean) isDesktopSupportedMethod
					.invoke(null);

			if (!isDesktopSupported) {
				log.finer("isDesktopSupported: no");
				return null;
			}

			final Method getDesktopMethod = desktopClass
					.getDeclaredMethod("getDesktop");
			return getDesktopMethod.invoke(null);
		} catch (Exception e) {
			log.log(Level.FINE, "Exception in Desktop operation", e);
			return null;
		}
	}

	/**
	 * 在MAC系统下找到com.apple.eio.FileManager籄1�7
	 * 
	 * @return the FileManager instance
	 * @throws ClassNotFoundException
	 *             if FileManager was not found
	 */
	private static Class<?> getAppleFileManagerClass()
			throws ClassNotFoundException {
		log.finest("Mac looking for com.apple.eio.FileManager");

		// NB The following String is intentionally not inlined to prevent
		// ProGuard trying to locate the unknown class.
		final String appleClass = "com.apple.eio.FileManager";
		return Class.forName(appleClass);
	}

	/**
	 * 棄1�7查是否存在一个给定的可执行文件,通过"which"指命令�1�7�1�7
	 * 
	 * @param cmd
	 *            the executable to locate
	 * @return true if the executable was found
	 * @throws IOException
	 *             if Runtime.exec() throws an IOException
	 */
	private static boolean unixCommandExists(final String cmd)
			throws IOException {
		final Process whichProcess = Runtime.getRuntime().exec(
				new String[] { "which", cmd });

		boolean finished = false;
		do {
			try {
				whichProcess.waitFor();
				finished = true;
			} catch (InterruptedException e) {
				log.log(Level.WARNING,
						"Interrupted waiting for which to complete", e);
			}
		} while (!finished);

		return whichProcess.exitValue() == 0;
	}
}

你可能感兴趣的:(Desktop)