alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SunClipboard.java)

This example Java source code file (SunClipboard.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

appcontext, awt, bean, clipboard_flavor_listener_key, clipboardowner, datatransfer, eventlisteneraggregate, flavorlistener, illegalstateexception, ioexception, javabean, nullpointerexception, peerevent, runnable, set, sunclipboard, sunflavorchangenotifier, transferable, util

The SunClipboard.java Java example source code

/*
 * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt.datatransfer;

import java.awt.EventQueue;

import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.FlavorTable;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;

import java.io.IOException;

import sun.awt.AppContext;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
import sun.awt.EventListenerAggregate;


/**
 * Serves as a common, helper superclass for the Win32 and X11 system
 * Clipboards.
 *
 * @author Danila Sinopalnikov
 * @author Alexander Gerasimov
 *
 * @since 1.3
 */
public abstract class SunClipboard extends Clipboard
    implements PropertyChangeListener {

    public static final FlavorTable flavorMap =
        (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();

    private AppContext contentsContext = null;

    private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;

    /**
     * A number of <code>FlavorListeners currently registered
     * on this clipboard across all <code>AppContexts.
     */
    private volatile int numberOfFlavorListeners = 0;

    /**
     * A set of <code>DataFlavors that is available on
     * this clipboard. It is used for tracking changes
     * of <code>DataFlavors available on this clipboard.
     */
    private volatile Set currentDataFlavors;


    public SunClipboard(String name) {
        super(name);
        CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
    }

    public synchronized void setContents(Transferable contents,
                                         ClipboardOwner owner) {
        // 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
        // should throw NPE
        if (contents == null) {
            throw new NullPointerException("contents");
        }

        initContext();

        final ClipboardOwner oldOwner = this.owner;
        final Transferable oldContents = this.contents;

        try {
            this.owner = owner;
            this.contents = new TransferableProxy(contents, true);

            setContentsNative(contents);
        } finally {
            if (oldOwner != null && oldOwner != owner) {
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        oldOwner.lostOwnership(SunClipboard.this, oldContents);
                    }
                });
            }
        }
    }

    private synchronized void initContext() {
        final AppContext context = AppContext.getAppContext();

        if (contentsContext != context) {
            // Need to synchronize on the AppContext to guarantee that it cannot
            // be disposed after the check, but before the listener is added.
            synchronized (context) {
                if (context.isDisposed()) {
                    throw new IllegalStateException("Can't set contents from disposed AppContext");
                }
                context.addPropertyChangeListener
                    (AppContext.DISPOSED_PROPERTY_NAME, this);
            }
            if (contentsContext != null) {
                contentsContext.removePropertyChangeListener
                    (AppContext.DISPOSED_PROPERTY_NAME, this);
            }
            contentsContext = context;
        }
    }

    public synchronized Transferable getContents(Object requestor) {
        if (contents != null) {
            return contents;
        }
        return new ClipboardTransferable(this);
    }


    /**
     * @return the contents of this clipboard if it has been set from the same
     *         AppContext as it is currently retrieved or null otherwise
     * @since 1.5
     */
    private synchronized Transferable getContextContents() {
        AppContext context = AppContext.getAppContext();
        return (context == contentsContext) ? contents : null;
    }


    /**
     * @see java.awt.Clipboard#getAvailableDataFlavors
     * @since 1.5
     */
    public DataFlavor[] getAvailableDataFlavors() {
        Transferable cntnts = getContextContents();
        if (cntnts != null) {
            return cntnts.getTransferDataFlavors();
        }

        long[] formats = getClipboardFormatsOpenClose();

        return DataTransferer.getInstance().
            getFlavorsForFormatsAsArray(formats, flavorMap);
    }

    /**
     * @see java.awt.Clipboard#isDataFlavorAvailable
     * @since 1.5
     */
    public boolean isDataFlavorAvailable(DataFlavor flavor) {
        if (flavor == null) {
            throw new NullPointerException("flavor");
        }

        Transferable cntnts = getContextContents();
        if (cntnts != null) {
            return cntnts.isDataFlavorSupported(flavor);
        }

        long[] formats = getClipboardFormatsOpenClose();

        return formatArrayAsDataFlavorSet(formats).contains(flavor);
    }

    /**
     * @see java.awt.Clipboard#getData
     * @since 1.5
     */
    public Object getData(DataFlavor flavor)
        throws UnsupportedFlavorException, IOException {
        if (flavor == null) {
            throw new NullPointerException("flavor");
        }

        Transferable cntnts = getContextContents();
        if (cntnts != null) {
            return cntnts.getTransferData(flavor);
        }

        long format = 0;
        byte[] data = null;
        Transferable localeTransferable = null;

        try {
            openClipboard(null);

            long[] formats = getClipboardFormats();
            Long lFormat = (Long)DataTransferer.getInstance().
                    getFlavorsForFormats(formats, flavorMap).get(flavor);

            if (lFormat == null) {
                throw new UnsupportedFlavorException(flavor);
            }

            format = lFormat.longValue();
            data = getClipboardData(format);

            if (DataTransferer.getInstance().isLocaleDependentTextFormat(format)) {
                localeTransferable = createLocaleTransferable(formats);
            }

        } finally {
            closeClipboard();
        }

        return DataTransferer.getInstance().
                translateBytes(data, flavor, format, localeTransferable);
    }

    /**
     * The clipboard must be opened.
     *
     * @since 1.5
     */
    protected Transferable createLocaleTransferable(long[] formats) throws IOException {
        return null;
    }

    /**
     * @throws IllegalStateException if the clipboard has not been opened
     */
    public void openClipboard(SunClipboard newOwner) {}
    public void closeClipboard() {}

    public abstract long getID();

    public void propertyChange(PropertyChangeEvent evt) {
        if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) &&
            Boolean.TRUE.equals(evt.getNewValue())) {
            final AppContext disposedContext = (AppContext)evt.getSource();
            lostOwnershipLater(disposedContext);
        }
    }

    protected void lostOwnershipImpl() {
        lostOwnershipLater(null);
    }

    /**
     * Clears the clipboard state (contents, owner and contents context) and
     * notifies the current owner that ownership is lost. Does nothing if the
     * argument is not <code>null and is not equal to the current
     * contents context.
     *
     * @param disposedContext the AppContext that is disposed or
     *        <code>null if the ownership is lost because another
     *        application acquired ownership.
     */
    protected void lostOwnershipLater(final AppContext disposedContext) {
        final AppContext context = this.contentsContext;
        if (context == null) {
            return;
        }

        final Runnable runnable = new Runnable() {
                public void run() {
                    final SunClipboard sunClipboard = SunClipboard.this;
                    ClipboardOwner owner = null;
                    Transferable contents = null;

                    synchronized (sunClipboard) {
                        final AppContext context = sunClipboard.contentsContext;

                        if (context == null) {
                            return;
                        }

                        if (disposedContext == null || context == disposedContext) {
                            owner = sunClipboard.owner;
                            contents = sunClipboard.contents;
                            sunClipboard.contentsContext = null;
                            sunClipboard.owner = null;
                            sunClipboard.contents = null;
                            sunClipboard.clearNativeContext();
                            context.removePropertyChangeListener
                                (AppContext.DISPOSED_PROPERTY_NAME, sunClipboard);
                        } else {
                            return;
                        }
                    }
                    if (owner != null) {
                        owner.lostOwnership(sunClipboard, contents);
                    }
                }
            };

        SunToolkit.postEvent(context, new PeerEvent(this, runnable,
                                                    PeerEvent.PRIORITY_EVENT));
    }

    protected abstract void clearNativeContext();

    protected abstract void setContentsNative(Transferable contents);

    /**
     * @since 1.5
     */
    protected long[] getClipboardFormatsOpenClose() {
        try {
            openClipboard(null);
            return getClipboardFormats();
        } finally {
            closeClipboard();
        }
    }

    /**
     * Returns zero-length array (not null) if the number of available formats is zero.
     *
     * @throws IllegalStateException if formats could not be retrieved
     */
    protected abstract long[] getClipboardFormats();

    protected abstract byte[] getClipboardData(long format) throws IOException;


    private static Set formatArrayAsDataFlavorSet(long[] formats) {
        return (formats == null) ? null :
                DataTransferer.getInstance().
                getFlavorsForFormatsAsSet(formats, flavorMap);
    }


    public synchronized void addFlavorListener(FlavorListener listener) {
        if (listener == null) {
            return;
        }
        AppContext appContext = AppContext.getAppContext();
        EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
                appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
        if (contextFlavorListeners == null) {
            contextFlavorListeners = new EventListenerAggregate(FlavorListener.class);
            appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, contextFlavorListeners);
        }
        contextFlavorListeners.add(listener);

        if (numberOfFlavorListeners++ == 0) {
            long[] currentFormats = null;
            try {
                openClipboard(null);
                currentFormats = getClipboardFormats();
            } catch (IllegalStateException exc) {
            } finally {
                closeClipboard();
            }
            currentDataFlavors = formatArrayAsDataFlavorSet(currentFormats);

            registerClipboardViewerChecked();
        }
    }

    public synchronized void removeFlavorListener(FlavorListener listener) {
        if (listener == null) {
            return;
        }
        AppContext appContext = AppContext.getAppContext();
        EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
                appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
        if (contextFlavorListeners == null){
            //else we throw NullPointerException, but it is forbidden
            return;
        }
        if (contextFlavorListeners.remove(listener) &&
                --numberOfFlavorListeners == 0) {
            unregisterClipboardViewerChecked();
            currentDataFlavors = null;
        }
    }

    public synchronized FlavorListener[] getFlavorListeners() {
        EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
                AppContext.getAppContext().get(CLIPBOARD_FLAVOR_LISTENER_KEY);
        return contextFlavorListeners == null ? new FlavorListener[0] :
                (FlavorListener[])contextFlavorListeners.getListenersCopy();
    }

    public boolean areFlavorListenersRegistered() {
        return (numberOfFlavorListeners > 0);
    }

    protected abstract void registerClipboardViewerChecked();

    protected abstract void unregisterClipboardViewerChecked();

    /**
     * Checks change of the <code>DataFlavors and, if necessary,
     * posts notifications on <code>FlavorEvents to the
     * AppContexts' EDTs.
     * The parameter <code>formats is null iff we have just
     * failed to get formats available on the clipboard.
     *
     * @param formats data formats that have just been retrieved from
     *        this clipboard
     */
    public void checkChange(long[] formats) {
        Set prevDataFlavors = currentDataFlavors;
        currentDataFlavors = formatArrayAsDataFlavorSet(formats);

        if ((prevDataFlavors != null) && (currentDataFlavors != null) &&
                prevDataFlavors.equals(currentDataFlavors)) {
            // we've been able to successfully get available on the clipboard
            // DataFlavors this and previous time and they are coincident;
            // don't notify
            return;
        }

        class SunFlavorChangeNotifier implements Runnable {
            private final FlavorListener flavorListener;

            SunFlavorChangeNotifier(FlavorListener flavorListener) {
                this.flavorListener = flavorListener;
            }

            public void run() {
                if (flavorListener != null) {
                    flavorListener.flavorsChanged(new FlavorEvent(SunClipboard.this));
                }
            }
        };

        for (Iterator it = AppContext.getAppContexts().iterator(); it.hasNext();) {
            AppContext appContext = (AppContext)it.next();
            if (appContext == null || appContext.isDisposed()) {
                continue;
            }
            EventListenerAggregate flavorListeners = (EventListenerAggregate)
                    appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
            if (flavorListeners != null) {
                FlavorListener[] flavorListenerArray =
                        (FlavorListener[])flavorListeners.getListenersInternal();
                for (int i = 0; i < flavorListenerArray.length; i++) {
                    SunToolkit.postEvent(appContext, new PeerEvent(this,
                            new SunFlavorChangeNotifier(flavorListenerArray[i]),
                            PeerEvent.PRIORITY_EVENT));
                }
            }
        }
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java SunClipboard.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.