Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.beans.property.adapter;
027
028import com.sun.javafx.property.adapter.ReadOnlyPropertyDescriptor;
029import javafx.beans.property.ReadOnlyObjectPropertyBase;
030
031import java.lang.reflect.InvocationTargetException;
032import java.lang.reflect.UndeclaredThrowableException;
033import sun.misc.Cleaner;
034
035import java.security.AccessController;
036import java.security.AccessControlContext;
037import java.security.PrivilegedAction;
038
039import sun.reflect.misc.MethodUtil;
040
041/**
042 * A {@code ReadOnlyJavaBeanObjectProperty} provides an adapter between a regular
043 * read only Java Bean property of {@code T} and a JavaFX 
044 * {@code ReadOnlyObjectProperty}. It cannot be created directly, but a 
045 * {@link ReadOnlyJavaBeanObjectPropertyBuilder} has to be used.
046 * <p>
047 * As a minimum, the Java Bean must implement a getter for the
048 * property. If the getter of an instance of this class is called, the property of 
049 * the Java Bean is returned. If the Java Bean property is bound (i.e. it supports
050 * PropertyChangeListeners), this {@code ReadOnlyJavaBeanObjectProperty} will be 
051 * aware of changes in the Java Bean. Otherwise it can be notified about
052 * changes by calling {@link #fireValueChangedEvent()}.
053 * 
054 * @see javafx.beans.property.ReadOnlyObjectProperty
055 * @see ReadOnlyJavaBeanObjectPropertyBuilder
056 * 
057 * @param T the type of the wrapped {@code Object}
058 */
059public final class ReadOnlyJavaBeanObjectProperty<T> extends ReadOnlyObjectPropertyBase<T> implements ReadOnlyJavaBeanProperty<T> {
060
061    private final ReadOnlyPropertyDescriptor descriptor;
062    private final ReadOnlyPropertyDescriptor.ReadOnlyListener<T> listener;
063
064    private final AccessControlContext acc = AccessController.getContext();
065
066    ReadOnlyJavaBeanObjectProperty(ReadOnlyPropertyDescriptor descriptor, Object bean) {
067        this.descriptor = descriptor;
068        this.listener = descriptor.new ReadOnlyListener<T>(bean, this);
069        descriptor.addListener(listener);
070        Cleaner.create(this, new Runnable() {
071            @Override
072            public void run() {
073                ReadOnlyJavaBeanObjectProperty.this.descriptor.removeListener(listener);
074            }
075        });
076    }
077
078    /**
079     * {@inheritDoc}
080     * 
081     * @throws UndeclaredThrowableException if calling the getter of the Java Bean
082     * property throws an {@code IllegalAccessException} or an 
083     * {@code InvocationTargetException}.
084     */
085    @Override
086    public T get() {
087        return AccessController.doPrivileged(new PrivilegedAction<T>() {
088            public T run() {
089                try {
090                    return (T)MethodUtil.invoke(descriptor.getGetter(), getBean(), (Object[])null);
091                } catch (IllegalAccessException e) {
092                    throw new UndeclaredThrowableException(e);
093                } catch (InvocationTargetException e) {
094                    throw new UndeclaredThrowableException(e);
095                }
096            }
097        }, acc);
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    @Override
104    public Object getBean() {
105        return listener.getBean();
106    }
107
108    /**
109     * {@inheritDoc}
110     */
111    @Override
112    public String getName() {
113        return descriptor.getName();
114    }
115
116    /**
117     * {@inheritDoc}
118     */
119    @Override
120    public void fireValueChangedEvent() {
121        super.fireValueChangedEvent();
122    }
123
124    /**
125     * {@inheritDoc}
126     */
127    @Override
128    public void dispose() {
129        descriptor.removeListener(listener);
130
131    }
132}