Package com.salas.bb.utils.osx

Source Code of com.salas.bb.utils.osx.OSXSupport

// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: OSXSupport.java,v 1.21 2007/10/01 17:03:27 spyromus Exp $
//

package com.salas.bb.utils.osx;

import com.jgoodies.uif.osx.OSXApplicationMenu;
import com.jgoodies.uif.util.ResourceUtils;
import com.jgoodies.uif.util.SystemUtils;
import com.salas.bb.utils.apple.AppleApplication;
import com.salas.bb.utils.apple.IAppleApplicationListener;
import com.salas.bb.utils.i18n.Strings;
import com.salas.bb.utils.ipc.IPC;
import com.salas.bb.utils.uif.laf.MacLookAndFeel;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Interface layer to Mac OSX. Contains both local functionality and interfaces to JGoodies OSX
* Support. Utility.
*/
public final class OSXSupport
{
    private static final Logger LOG = Logger.getLogger(OSXSupport.class.getName());

    /**
     * Width of splitter pane.
     */
    public static final int SPLITPANE_WIDTH = 8;
    private static ClassLoader cocoaClassLoader;

    /**
     * Hidden constructor of utility class.
     */
    private OSXSupport()
    {
    }

    /**
     * Set the name of the Application Menu.
     *
     * @param aString - Application menu
     */
    public static void setAboutMenuName(String aString)
    {
        if (SystemUtils.IS_OS_MAC) OSXApplicationMenu.setAboutName(aString);
    }

    /**
     * Tell OSX that you want the main window to be Metal. N.B. It is crucial that this method is
     * called before any Swing related code is run. This includes even 'new'ing a class derived from
     * JFrame. If it looks like this method isn't doing anything, it's probably because it has been
     * called too late.
     */
    public static void setMetalOSXLook()
    {
        System.setProperty("apple.awt.brushMetalLook", "true");
    }

    /**
     * Declare the ActionListeners to be invoked when the indicated commands picked off the
     * Application menu of OSX. Note: noop if we are not on a mac.
     *
     * @param about About action
     * @param prefs Show Preferences action
     * @param exit  Quit Application action
     */
    public static void setApplicationMenu(ActionListener about, ActionListener prefs,
                                          ActionListener exit)
    {
        if (SystemUtils.IS_OS_MAC) OSXApplicationMenu.register(about, prefs, exit);
    }

    /**
     * Initializes Mac-specific LAF.
     */
    public static void setupLAF()
    {
        if (!SystemUtils.IS_OS_MAC) return;

        try
        {
            UIManager.setLookAndFeel(new MacLookAndFeel());
        } catch (Exception e)
        {
            LOG.log(Level.SEVERE, Strings.error("unhandled.exception"), e);
        }
    }

    /**
     * Returns Cocoa class by name.
     *
     * @param name name of the class (i.e. <code>com.apple.cocoa.application.NSImage</code>).
     *
     * @return class.
     *
     * @throws ClassNotFoundException if class not found.
     */
    public static Class getCocoaClass(String name)
        throws ClassNotFoundException
    {
        if (!SystemUtils.IS_OS_MAC) return null;
        return getCocoaClassLoader().loadClass(name);
    }

    /**
     * Returns classloader for Cocoa classes.
     *
     * @return class loader.
     */
    public static synchronized ClassLoader getCocoaClassLoader()
    {
        if (!SystemUtils.IS_OS_MAC) return null;
        if (cocoaClassLoader == null)
        {
            // Setup Cocoa Class Loader plus Growl delegate which should be on the
            // same class loader with the rest of Cocoa tools
            ClassLoader currentCL = OSXSupport.class.getClassLoader();
            URL urlCocoa = null;
            try
            {
                urlCocoa = new URL("file:///System/Library/Java/");
            } catch (MalformedURLException e)
            {
                // Impossible
            }
            ClassLoader cl = new AllPermissionsURLClassLoader(new URL[] { urlCocoa }, currentCL);
            cocoaClassLoader = new ResourceClassLoader("resources/growl", cl);
        }

        return cocoaClassLoader;
    }

    /**
     * Loads resource into the array of bytes.
     *
     * @param resource resource to load.
     *
     * @return array of bytes or <code>NULL</code> if not found.
     */
    public static byte[] loadResourceBytes(String resource)
    {
        byte[] buffer = null;

        InputStream stream = OSXSupport.class.getClassLoader().getResourceAsStream(resource);
        if (stream != null)
        {
            BufferedInputStream bis = new BufferedInputStream(stream);
            try
            {
                buffer = new byte[bis.available()];
                bis.read(buffer);
            } catch (IOException e)
            {
                buffer = null;
                LOG.log(Level.SEVERE, Strings.error("notify.failed.to.load.resource"), e);
            } finally
            {
                try { bis.close(); } catch (IOException e) { }
            }
        } else LOG.log(Level.SEVERE, MessageFormat.format(Strings.error("resource.not.found"), new Object[] { resource }));

        return buffer;
    }

    /**
     * Sets the application icon.
     */
    public static void setApplicationIcon()
    {
        if (!SystemUtils.IS_OS_MAC) return;
        Image image = ResourceUtils.readImage("blogbridge.icns");
        DockIcon.setApplicationIcon(image);
    }

    /**
     * Configures Mac-specific IPC.
     *
     * @param ipc IPC module.
     */
    public static void setupIPC(final IPC ipc)
    {
        AppleApplication.addApplicationListener(new IAppleApplicationListener()
        {
            /**
             * Invoked when Finder gives the command to open some file.
             *
             * @param filename file name.
             *
             * @return <code>TRUE</code> if the action was performed.
             */
            public boolean handleOpenFile(String filename)
            {
                if (filename == null) return false;

                URL u = null;

                // Check if it's URL
                try
                {
                    u = new URL(filename);
                } catch (MalformedURLException e)
                {
                    // Not URL
                }

                // Check if it's filename
                if (u == null)
                {
                    File f = new File(filename);
                    try
                    {
                        u = f.toURL();
                    } catch (MalformedURLException e)
                    {
                        // Not filename
                    }
                }

                if (u != null) ipc.fireSubscribe(u);

                return u == null;
            }
        });
    }

    /**
     * The class loader which is taking classes from the resources.
     */
    private static class ResourceClassLoader extends ClassLoader
    {
        private final Map classes = new HashMap();
        private final String root;

        /**
         * Creates a new class loader.
         *
         * @param root offset from the resources root to start loading classes from.
         * @param parent parent class loader.
         */
        public ResourceClassLoader(String root, ClassLoader parent)
        {
            super(parent);
            this.root = root;
        }

        /**
         * Loads the class with the specified name.  This method searches for
         * classes in the same manner as the {@link #loadClass(String, boolean)}
         * method.  It is invoked by the Java virtual machine to resolveURI class
         * references.  Invoking this method is equivalent to invoking {@link
         * #loadClass(String, boolean) <tt>loadClass(name, false)</tt>}.  </p>
         *
         * @param name The name of the class
         * @return The resulting <tt>Class</tt> object
         * @throws ClassNotFoundException If the class was not found
         */
        public Class loadClass(String name) throws ClassNotFoundException
        {
            return loadClass(name, true);
        }

        /**
         * Loads the class with the specified name.  The default implementation
         * of this method searches for classes in the following order:
         * <p/>
         * <p><ol>
         * <p/>
         * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
         * has already been loaded.  </p></li>
         * <p/>
         * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
         * on the parent class loader.  If the parent is <tt>null</tt> the class
         * loader built-in to the virtual machine is used, instead.  </p></li>
         * <p/>
         * <li><p> Invoke the {@link #findClass(String)} method to find the
         * class.  </p></li>
         * <p/>
         * </ol>
         * <p/>
         * <p> If the class was found using the above steps, and the
         * <tt>resolveURI</tt> flag is true, this method will then invoke the {@link
         * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
         * <p/>
         * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
         * #findClass(String)}, rather than this method.  </p>
         *
         * @param name    The name of the class
         * @param resolve If <tt>true</tt> then resolveURI the class
         * @return The resulting <tt>Class</tt> object
         * @throws ClassNotFoundException If the class could not be found
         */
        protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException
        {
            Class result;

            result = (Class)classes.get(name);
            if (result == null)
            {
                try
                {
                    result = super.loadClass(name, resolve);
                } catch (ClassNotFoundException e)
                {
                    // Not a parent class-loader class
                }

                if (result == null)
                {
                    byte[] classBytes = loadClassBytes(name);
                    if (classBytes != null)
                    {
                        ProtectionDomain protectionDomain = ResourceClassLoader.class.getProtectionDomain();
                        result = defineClass(name, classBytes, 0, classBytes.length, protectionDomain);
                        if (result == null) throw new ClassFormatError(name);

                        // Put class in cache
                        classes.put(name, result);
                    }
                }
            }

            return result;
        }

        /**
         * Loads class bytes.
         *
         * @param name  name of the class.
         *
         * @return bytes.
         *
         * @throws ClassNotFoundException if class couldn't be found.
         */
        private byte[] loadClassBytes(String name) throws ClassNotFoundException
        {
            String resource = root + "/" + name.replace('.', '/') + ".class";

            byte[] buffer = loadResourceBytes(resource);
            if (buffer == null || buffer.length == 0) throw new ClassNotFoundException(name);

            return buffer;
        }
    }

    /**
     * URL class loader setting all permissions to the classes it loads.
     */
    private static class AllPermissionsURLClassLoader extends URLClassLoader
    {
        private PermissionCollection pc;

        /**
         * Creates loader.
         *
         * @param urls the list of URLs to treat as roots.
         * @param parent parent class loader.
         */
        public AllPermissionsURLClassLoader(URL[] urls, ClassLoader parent)
        {
            super(urls, parent);

            AllPermission ap = new AllPermission();
            pc = ap.newPermissionCollection();
            pc.add(ap);
        }

        /**
         * Returns the permissions for the code source.
         *
         * @param codesource code source.
         *
         * @return permissions.
         */
        protected PermissionCollection getPermissions(CodeSource codesource)
        {
            return pc;
        }
    }
}
TOP

Related Classes of com.salas.bb.utils.osx.OSXSupport

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.