1 /*
2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javafx.beans.property.adapter;
27
28 import com.sun.javafx.binding.ExpressionHelper;
29 import com.sun.javafx.property.adapter.Disposer;
30 import com.sun.javafx.property.adapter.PropertyDescriptor;
31 import javafx.beans.InvalidationListener;
32 import javafx.beans.property.IntegerProperty;
33 import javafx.beans.value.ChangeListener;
34 import javafx.beans.value.ObservableValue;
35
36 import java.lang.reflect.InvocationTargetException;
37 import java.lang.reflect.UndeclaredThrowableException;
38
39 import java.security.AccessControlContext;
40 import java.security.AccessController;
41 import java.security.PrivilegedAction;
42
43 import sun.reflect.misc.MethodUtil;
44
45 /**
46 * A {@code JavaBeanIntegerProperty} provides an adapter between a regular
47 * Java Bean property of type {@code int} or {@code Integer} and a JavaFX
48 * {@code IntegerProperty}. It cannot be created directly, but a
49 * {@link JavaBeanIntegerPropertyBuilder} has to be used.
50 * <p>
51 * As a minimum, the Java Bean must implement a getter and a setter for the
52 * property. If the getter of an instance of this class is called, the property of
53 * the Java Bean is returned. If the setter is called, the value will be passed
54 * to the Java Bean property. If the Java Bean property is bound (i.e. it supports
55 * PropertyChangeListeners), this {@code JavaBeanIntegerProperty} will be
56 * aware of changes in the Java Bean. Otherwise it can be notified about
57 * changes by calling {@link #fireValueChangedEvent()}. If the Java Bean property
58 * is also constrained (i.e. it supports VetoableChangeListeners), this
59 * {@code JavaBeanIntegerProperty} will reject changes, if it is bound to an
60 * {@link javafx.beans.value.ObservableValue ObservableValue<Integer>}.
61 *
62 * @see javafx.beans.property.IntegerProperty
63 * @see JavaBeanIntegerPropertyBuilder
64 * @since JavaFX 2.1
65 */
66 public final class JavaBeanIntegerProperty extends IntegerProperty implements JavaBeanProperty<Number> {
67
68 private final PropertyDescriptor descriptor;
69 private final PropertyDescriptor.Listener<Number> listener;
70
71 private ObservableValue<? extends Number> observable = null;
72 private ExpressionHelper<Number> helper = null;
73
74 private final AccessControlContext acc = AccessController.getContext();
75
76 JavaBeanIntegerProperty(PropertyDescriptor descriptor, Object bean) {
77 this.descriptor = descriptor;
78 this.listener = descriptor.new Listener<Number>(bean, this);
79 descriptor.addListener(listener);
80 Disposer.addRecord(this, new DescriptorListenerCleaner(descriptor, listener));
81 }
82
83 /**
84 * {@inheritDoc}
85 *
86 * @throws UndeclaredThrowableException if calling the getter of the Java Bean
87 * property throws an {@code IllegalAccessException} or an
88 * {@code InvocationTargetException}.
89 */
90 @Override
91 public int get() {
92 return AccessController.doPrivileged((PrivilegedAction<Integer>) () -> {
93 try {
94 return ((Number)MethodUtil.invoke(
95 descriptor.getGetter(), getBean(), (Object[])null)).intValue();
96 } catch (IllegalAccessException e) {
97 throw new UndeclaredThrowableException(e);
98 } catch (InvocationTargetException e) {
99 throw new UndeclaredThrowableException(e);
100 }
101 }, acc);
102 }
103
104 /**
105 * {@inheritDoc}
106 *
107 * @throws UndeclaredThrowableException if calling the getter of the Java Bean
108 * property throws an {@code IllegalAccessException} or an
109 * {@code InvocationTargetException}.
110 */
111 @Override
112 public void set(final int value) {
113 if (isBound()) {
114 throw new RuntimeException("A bound value cannot be set.");
115 }
116 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
117 try {
118 MethodUtil.invoke(descriptor.getSetter(), getBean(), new Object[] {value});
119 ExpressionHelper.fireValueChangedEvent(helper);
120 } catch (IllegalAccessException e) {
121 throw new UndeclaredThrowableException(e);
122 } catch (InvocationTargetException e) {
123 throw new UndeclaredThrowableException(e);
124 }
125 return null;
126 }, acc);
127 }
128
129 /**
130 * {@inheritDoc}
131 */
132 @Override
133 public void bind(ObservableValue<? extends Number> observable) {
134 if (observable == null) {
135 throw new NullPointerException("Cannot bind to null");
136 }
137
138 if (!observable.equals(this.observable)) {
|
1 /*
2 * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javafx.beans.property.adapter;
27
28 import com.sun.javafx.binding.ExpressionHelper;
29 import com.sun.javafx.property.MethodHelper;
30 import com.sun.javafx.property.adapter.Disposer;
31 import com.sun.javafx.property.adapter.PropertyDescriptor;
32 import javafx.beans.InvalidationListener;
33 import javafx.beans.property.IntegerProperty;
34 import javafx.beans.value.ChangeListener;
35 import javafx.beans.value.ObservableValue;
36
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.UndeclaredThrowableException;
39
40 import java.security.AccessControlContext;
41 import java.security.AccessController;
42 import java.security.PrivilegedAction;
43
44 /**
45 * A {@code JavaBeanIntegerProperty} provides an adapter between a regular
46 * Java Bean property of type {@code int} or {@code Integer} and a JavaFX
47 * {@code IntegerProperty}. It cannot be created directly, but a
48 * {@link JavaBeanIntegerPropertyBuilder} has to be used.
49 * <p>
50 * As a minimum, the Java Bean class must implement a getter and a setter for the
51 * property.
52 * The class, as well as the getter and a setter methods, must be declared public.
53 * If the getter of an instance of this class is called, the property of
54 * the Java Bean is returned. If the setter is called, the value will be passed
55 * to the Java Bean property. If the Java Bean property is bound (i.e. it supports
56 * PropertyChangeListeners), this {@code JavaBeanIntegerProperty} will be
57 * aware of changes in the Java Bean. Otherwise it can be notified about
58 * changes by calling {@link #fireValueChangedEvent()}. If the Java Bean property
59 * is also constrained (i.e. it supports VetoableChangeListeners), this
60 * {@code JavaBeanIntegerProperty} will reject changes, if it is bound to an
61 * {@link javafx.beans.value.ObservableValue ObservableValue<Integer>}.
62 * </p>
63 * <p><b>Deploying an Application as a Module</b></p>
64 * <p>
65 * If the Java Bean class is in a named module, then it must be reflectively
66 * accessible to the {@code javafx.base} module.
67 * A class is reflectively accessible if the module
68 * {@link Module#isOpen(String,Module) opens} the containing package to at
69 * least the {@code javafx.base} module.
70 * </p>
71 * <p>
72 * For example, if {@code com.foo.MyBeanClass} is in the {@code foo.app} module,
73 * the {@code module-info.java} might
74 * look like this:
75 * </p>
76 *
77 <pre>{@code module foo.app {
78 opens com.foo to javafx.base;
79 }}</pre>
80 *
81 * <p>
82 * Alternatively, a class is reflectively accessible if the module
83 * {@link Module#isExported(String) exports} the containing package
84 * unconditionally.
85 * </p>
86 *
87 * @see javafx.beans.property.IntegerProperty
88 * @see JavaBeanIntegerPropertyBuilder
89 * @since JavaFX 2.1
90 */
91 public final class JavaBeanIntegerProperty extends IntegerProperty implements JavaBeanProperty<Number> {
92
93 private final PropertyDescriptor descriptor;
94 private final PropertyDescriptor.Listener<Number> listener;
95
96 private ObservableValue<? extends Number> observable = null;
97 private ExpressionHelper<Number> helper = null;
98
99 private final AccessControlContext acc = AccessController.getContext();
100
101 JavaBeanIntegerProperty(PropertyDescriptor descriptor, Object bean) {
102 this.descriptor = descriptor;
103 this.listener = descriptor.new Listener<Number>(bean, this);
104 descriptor.addListener(listener);
105 Disposer.addRecord(this, new DescriptorListenerCleaner(descriptor, listener));
106 }
107
108 /**
109 * {@inheritDoc}
110 *
111 * @throws UndeclaredThrowableException if calling the getter of the Java Bean
112 * property throws an {@code IllegalAccessException} or an
113 * {@code InvocationTargetException}.
114 */
115 @Override
116 public int get() {
117 return AccessController.doPrivileged((PrivilegedAction<Integer>) () -> {
118 try {
119 return ((Number)MethodHelper.invoke(
120 descriptor.getGetter(), getBean(), (Object[])null)).intValue();
121 } catch (IllegalAccessException e) {
122 throw new UndeclaredThrowableException(e);
123 } catch (InvocationTargetException e) {
124 throw new UndeclaredThrowableException(e);
125 }
126 }, acc);
127 }
128
129 /**
130 * {@inheritDoc}
131 *
132 * @throws UndeclaredThrowableException if calling the getter of the Java Bean
133 * property throws an {@code IllegalAccessException} or an
134 * {@code InvocationTargetException}.
135 */
136 @Override
137 public void set(final int value) {
138 if (isBound()) {
139 throw new RuntimeException("A bound value cannot be set.");
140 }
141 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
142 try {
143 MethodHelper.invoke(descriptor.getSetter(), getBean(), new Object[] {value});
144 ExpressionHelper.fireValueChangedEvent(helper);
145 } catch (IllegalAccessException e) {
146 throw new UndeclaredThrowableException(e);
147 } catch (InvocationTargetException e) {
148 throw new UndeclaredThrowableException(e);
149 }
150 return null;
151 }, acc);
152 }
153
154 /**
155 * {@inheritDoc}
156 */
157 @Override
158 public void bind(ObservableValue<? extends Number> observable) {
159 if (observable == null) {
160 throw new NullPointerException("Cannot bind to null");
161 }
162
163 if (!observable.equals(this.observable)) {
|