summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorDenis Anisimov <denis@vaadin.com>2016-11-28 10:10:21 +0300
committerVaadin Code Review <review@vaadin.com>2016-11-29 10:35:59 +0000
commitb8e84da2e2dc4bcaed40d169c40a97f3d11e0648 (patch)
tree80e5a8e7a7856b67048319958ef88b5466d3e4bc /server
parent0d57c15577f5d5e15453024ce90144120948eae9 (diff)
downloadvaadin-framework-b8e84da2e2dc4bcaed40d169c40a97f3d11e0648.tar.gz
vaadin-framework-b8e84da2e2dc4bcaed40d169c40a97f3d11e0648.zip
Correct all tests that introspect classpath for Vaadin classes.
Fixes vaadin/framework8-issues#399 RemoveListenersDeprecatedTest test is fixed. Corrections are made to make the test above passes. Change-Id: I209a4693d241a1488b69b4742f48549dbf4bf0ac
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/event/MethodEventSource.java6
-rw-r--r--server/src/main/java/com/vaadin/event/SortEvent.java7
-rw-r--r--server/src/main/java/com/vaadin/navigator/Navigator.java10
-rw-r--r--server/src/main/java/com/vaadin/server/AbstractClientConnector.java6
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinPortletSession.java20
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinService.java12
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinSession.java14
-rw-r--r--server/src/main/java/com/vaadin/ui/LoginForm.java6
-rw-r--r--server/src/main/java/com/vaadin/ui/Slider.java2
-rw-r--r--server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java4
-rw-r--r--server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java40
-rw-r--r--server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java30
-rw-r--r--server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java13
-rw-r--r--server/src/main/java/com/vaadin/ui/declarative/DesignContext.java9
-rw-r--r--server/src/test/java/com/vaadin/server/RemoveListenersDeprecatedTest.java78
-rw-r--r--server/src/test/java/com/vaadin/tests/VaadinClasses.java193
-rw-r--r--server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java137
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/FinalMethodTest.java21
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java77
-rw-r--r--server/src/test/java/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java23
20 files changed, 474 insertions, 234 deletions
diff --git a/server/src/main/java/com/vaadin/event/MethodEventSource.java b/server/src/main/java/com/vaadin/event/MethodEventSource.java
index 2ba5586eb1..e59ccfd4d4 100644
--- a/server/src/main/java/com/vaadin/event/MethodEventSource.java
+++ b/server/src/main/java/com/vaadin/event/MethodEventSource.java
@@ -141,7 +141,10 @@ public interface MethodEventSource extends Serializable {
* @param method
* the method owned by the target that's registered to listen to
* events of type eventType.
+ * @deprecated use a {@link Registration} returned by
+ * {@link #addListener(Class, Object, Method)}
*/
+ @Deprecated
public void removeListener(Class<?> eventType, Object target,
Method method);
@@ -172,7 +175,10 @@ public interface MethodEventSource extends Serializable {
* @param methodName
* the name of the method owned by <code>target</code> that's
* registered to listen to events of type <code>eventType</code>.
+ * @deprecated use a {@link Registration} returned by
+ * {@link #addListener(Class, Object, String)}
*/
+ @Deprecated
public void removeListener(Class<?> eventType, Object target,
String methodName);
}
diff --git a/server/src/main/java/com/vaadin/event/SortEvent.java b/server/src/main/java/com/vaadin/event/SortEvent.java
index e9dd4c75ae..0bc6d4b2cf 100644
--- a/server/src/main/java/com/vaadin/event/SortEvent.java
+++ b/server/src/main/java/com/vaadin/event/SortEvent.java
@@ -19,6 +19,7 @@ import java.io.Serializable;
import java.util.List;
import com.vaadin.data.sort.SortOrder;
+import com.vaadin.shared.Registration;
import com.vaadin.ui.Component;
/**
@@ -95,8 +96,9 @@ public class SortEvent extends Component.Event {
*
* @param listener
* the sort order change listener to add
+ * @return a registration object for removing the listener
*/
- public void addSortListener(SortListener listener);
+ public Registration addSortListener(SortListener listener);
/**
* Removes a sort order change listener previously added using
@@ -104,7 +106,10 @@ public class SortEvent extends Component.Event {
*
* @param listener
* the sort order change listener to remove
+ * @deprecated use a {@link Registration} returned by
+ * {@link #addSortListener(SortListener)}
*/
+ @Deprecated
public void removeSortListener(SortListener listener);
}
}
diff --git a/server/src/main/java/com/vaadin/navigator/Navigator.java b/server/src/main/java/com/vaadin/navigator/Navigator.java
index 07d7c5c085..163db74feb 100644
--- a/server/src/main/java/com/vaadin/navigator/Navigator.java
+++ b/server/src/main/java/com/vaadin/navigator/Navigator.java
@@ -41,6 +41,7 @@ import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
import com.vaadin.server.Page;
import com.vaadin.server.Page.UriFragmentChangedEvent;
import com.vaadin.server.Page.UriFragmentChangedListener;
+import com.vaadin.shared.Registration;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
@@ -345,7 +346,7 @@ public class Navigator implements Serializable {
throw new RuntimeException(e);
}
// TODO error handling
-
+
}
return null;
}
@@ -975,8 +976,9 @@ public class Navigator implements Serializable {
* @param listener
* Listener to invoke during a view change.
*/
- public void addViewChangeListener(ViewChangeListener listener) {
+ public Registration addViewChangeListener(ViewChangeListener listener) {
listeners.add(listener);
+ return () -> listeners.remove(listener);
}
/**
@@ -984,7 +986,11 @@ public class Navigator implements Serializable {
*
* @param listener
* Listener to remove.
+ * @deprecated use a {@link Registration} object returned by
+ * {@link #addViewChangeListener(ViewChangeListener)} to remove
+ * a listener
*/
+ @Deprecated
public void removeViewChangeListener(ViewChangeListener listener) {
listeners.remove(listener);
}
diff --git a/server/src/main/java/com/vaadin/server/AbstractClientConnector.java b/server/src/main/java/com/vaadin/server/AbstractClientConnector.java
index 32f62edb8e..5c905e2f84 100644
--- a/server/src/main/java/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/main/java/com/vaadin/server/AbstractClientConnector.java
@@ -103,6 +103,7 @@ public abstract class AbstractClientConnector
}
@Override
+ @Deprecated
public void removeAttachListener(AttachListener listener) {
removeListener(AttachEvent.ATTACH_EVENT_IDENTIFIER, AttachEvent.class,
listener);
@@ -115,6 +116,7 @@ public abstract class AbstractClientConnector
}
@Override
+ @Deprecated
public void removeDetachListener(DetachListener listener) {
removeListener(DetachEvent.DETACH_EVENT_IDENTIFIER, DetachEvent.class,
listener);
@@ -940,8 +942,12 @@ public abstract class AbstractClientConnector
* @param method
* the method owned by <code>target</code> that's registered to
* listen to events of type <code>eventType</code>.
+ * @deprecated use a {@link Registration} from
+ * {@link #addListener(Class, Object, Method)} to remove a
+ * listener
*/
@Override
+ @Deprecated
public void removeListener(Class<?> eventType, Object target,
Method method) {
if (eventRouter != null) {
diff --git a/server/src/main/java/com/vaadin/server/VaadinPortletSession.java b/server/src/main/java/com/vaadin/server/VaadinPortletSession.java
index f1b32efabe..68a1470e05 100644
--- a/server/src/main/java/com/vaadin/server/VaadinPortletSession.java
+++ b/server/src/main/java/com/vaadin/server/VaadinPortletSession.java
@@ -42,6 +42,7 @@ import javax.servlet.http.HttpSessionBindingListener;
import javax.xml.namespace.QName;
import com.vaadin.server.communication.PortletListenerNotifier;
+import com.vaadin.shared.Registration;
import com.vaadin.ui.UI;
import com.vaadin.util.CurrentInstance;
@@ -123,8 +124,9 @@ public class VaadinPortletSession extends VaadinSession {
* @param listener
* to add
*/
- public void addPortletListener(PortletListener listener) {
+ public Registration addPortletListener(PortletListener listener) {
portletListeners.add(listener);
+ return () -> portletListeners.remove(listener);
}
/**
@@ -133,7 +135,11 @@ public class VaadinPortletSession extends VaadinSession {
*
* @param listener
* to remove
+ * @deprecated Use a {@link Registration} object returned by
+ * {@link #addPortletListener(PortletListener)} to remove a
+ * listener
*/
+ @Deprecated
public void removePortletListener(PortletListener listener) {
portletListeners.remove(listener);
}
@@ -143,8 +149,7 @@ public class VaadinPortletSession extends VaadinSession {
*/
public void firePortletRenderRequest(UI uI, RenderRequest request,
RenderResponse response) {
- for (PortletListener l : new ArrayList<>(
- portletListeners)) {
+ for (PortletListener l : new ArrayList<>(portletListeners)) {
l.handleRenderRequest(request,
new RestrictedRenderResponse(response), uI);
}
@@ -172,8 +177,7 @@ public class VaadinPortletSession extends VaadinSession {
sharedParameterActionValueMap.remove(key);
} else {
// normal action request, notify listeners
- for (PortletListener l : new ArrayList<>(
- portletListeners)) {
+ for (PortletListener l : new ArrayList<>(portletListeners)) {
l.handleActionRequest(request, response, uI);
}
}
@@ -184,8 +188,7 @@ public class VaadinPortletSession extends VaadinSession {
*/
public void firePortletEventRequest(UI uI, EventRequest request,
EventResponse response) {
- for (PortletListener l : new ArrayList<>(
- portletListeners)) {
+ for (PortletListener l : new ArrayList<>(portletListeners)) {
l.handleEventRequest(request, response, uI);
}
}
@@ -195,8 +198,7 @@ public class VaadinPortletSession extends VaadinSession {
*/
public void firePortletResourceRequest(UI uI, ResourceRequest request,
ResourceResponse response) {
- for (PortletListener l : new ArrayList<>(
- portletListeners)) {
+ for (PortletListener l : new ArrayList<>(portletListeners)) {
l.handleResourceRequest(request, response, uI);
}
}
diff --git a/server/src/main/java/com/vaadin/server/VaadinService.java b/server/src/main/java/com/vaadin/server/VaadinService.java
index 62d9d75edb..70a60a4f1f 100644
--- a/server/src/main/java/com/vaadin/server/VaadinService.java
+++ b/server/src/main/java/com/vaadin/server/VaadinService.java
@@ -415,10 +415,8 @@ public abstract class VaadinService implements Serializable {
* @return a registration object for removing the listener
*/
public Registration addSessionInitListener(SessionInitListener listener) {
- eventRouter.addListener(SessionInitEvent.class, listener,
+ return eventRouter.addListener(SessionInitEvent.class, listener,
SESSION_INIT_METHOD);
- return () -> eventRouter.removeListener(SessionInitEvent.class,
- listener, SESSION_INIT_METHOD);
}
/**
@@ -454,10 +452,8 @@ public abstract class VaadinService implements Serializable {
*/
public Registration addSessionDestroyListener(
SessionDestroyListener listener) {
- eventRouter.addListener(SessionDestroyEvent.class, listener,
+ return eventRouter.addListener(SessionDestroyEvent.class, listener,
SESSION_DESTROY_METHOD);
- return () -> eventRouter.removeListener(SessionInitEvent.class,
- listener, SESSION_DESTROY_METHOD);
}
/**
@@ -1877,10 +1873,8 @@ public abstract class VaadinService implements Serializable {
*/
public Registration addServiceDestroyListener(
ServiceDestroyListener listener) {
- eventRouter.addListener(ServiceDestroyEvent.class, listener,
+ return eventRouter.addListener(ServiceDestroyEvent.class, listener,
SERVICE_DESTROY_METHOD);
- return () -> eventRouter.removeListener(ServiceDestroyEvent.class,
- listener, SERVICE_DESTROY_METHOD);
}
/**
diff --git a/server/src/main/java/com/vaadin/server/VaadinSession.java b/server/src/main/java/com/vaadin/server/VaadinSession.java
index ebda81b9c7..3e3202ee1b 100644
--- a/server/src/main/java/com/vaadin/server/VaadinSession.java
+++ b/server/src/main/java/com/vaadin/server/VaadinSession.java
@@ -48,6 +48,7 @@ import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import com.vaadin.event.EventRouter;
+import com.vaadin.shared.Registration;
import com.vaadin.shared.communication.PushMode;
import com.vaadin.ui.UI;
import com.vaadin.util.CurrentInstance;
@@ -822,13 +823,20 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
*
* @param listener
* the bootstrap listener to add
+ * @return a registration object for removing the listener
*/
- public void addBootstrapListener(BootstrapListener listener) {
+ public Registration addBootstrapListener(BootstrapListener listener) {
assert hasLock();
eventRouter.addListener(BootstrapFragmentResponse.class, listener,
BOOTSTRAP_FRAGMENT_METHOD);
eventRouter.addListener(BootstrapPageResponse.class, listener,
BOOTSTRAP_PAGE_METHOD);
+ return () -> {
+ eventRouter.removeListener(BootstrapFragmentResponse.class,
+ listener, BOOTSTRAP_FRAGMENT_METHOD);
+ eventRouter.removeListener(BootstrapPageResponse.class, listener,
+ BOOTSTRAP_PAGE_METHOD);
+ };
}
/**
@@ -838,7 +846,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
*
* @param listener
* the bootstrap listener to remove
+ * @deprecated Use a {@link Registration} object returned by
+ * {@link #addBootstrapListener(BootstrapListener)} to remove a
+ * listener
*/
+ @Deprecated
public void removeBootstrapListener(BootstrapListener listener) {
assert hasLock();
eventRouter.removeListener(BootstrapFragmentResponse.class, listener,
diff --git a/server/src/main/java/com/vaadin/ui/LoginForm.java b/server/src/main/java/com/vaadin/ui/LoginForm.java
index 6b6bfec5bc..abef0c1276 100644
--- a/server/src/main/java/com/vaadin/ui/LoginForm.java
+++ b/server/src/main/java/com/vaadin/ui/LoginForm.java
@@ -326,17 +326,17 @@ public class LoginForm extends AbstractSingleComponentContainer {
private TextField getUsernameField() {
assert initialized;
- return (TextField) getState().userNameFieldConnector;
+ return (TextField) getState(false).userNameFieldConnector;
}
private PasswordField getPasswordField() {
assert initialized;
- return (PasswordField) getState().passwordFieldConnector;
+ return (PasswordField) getState(false).passwordFieldConnector;
}
private Button getLoginButton() {
assert initialized;
- return (Button) getState().loginButtonConnector;
+ return (Button) getState(false).loginButtonConnector;
}
/**
diff --git a/server/src/main/java/com/vaadin/ui/Slider.java b/server/src/main/java/com/vaadin/ui/Slider.java
index 16c287d92c..58964d1378 100644
--- a/server/src/main/java/com/vaadin/ui/Slider.java
+++ b/server/src/main/java/com/vaadin/ui/Slider.java
@@ -304,7 +304,7 @@ public class Slider extends AbstractField<Double> {
@Override
public Double getValue() {
- return getState().value;
+ return getState(false).value;
}
@Override
diff --git a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java
index ae1c304fd2..101a4b642a 100644
--- a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java
+++ b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerHistory.java
@@ -50,8 +50,8 @@ public class ColorPickerHistory extends CustomField<Color> {
ColorPickerGrid grid = new ColorPickerGrid(ROWS, COLUMNS);
grid.setWidth("100%");
grid.setPosition(0, 0);
- grid.addValueChangeListener(event -> fireEvent(new ValueChangeEvent<>(this,
- event.isUserOriginated())));
+ grid.addValueChangeListener(event -> fireEvent(
+ new ValueChangeEvent<>(this, event.isUserOriginated())));
return grid;
}
diff --git a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java
index 15fc1bcb45..9d88b03fa5 100644
--- a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java
+++ b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPopup.java
@@ -18,6 +18,7 @@ package com.vaadin.ui.components.colorpicker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -33,6 +34,7 @@ import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
+import com.vaadin.ui.HasComponents;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Slider;
@@ -119,6 +121,10 @@ public class ColorPickerPopup extends Window implements HasValue<Color> {
/** The selectors. */
private final Set<HasValue<Color>> selectors = new HashSet<>();
+ private boolean readOnly;
+
+ private boolean required;
+
/**
* Set true while the slider values are updated after colorChange. When
* true, valueChange reactions from the sliders are disabled, because
@@ -175,6 +181,7 @@ public class ColorPickerPopup extends Window implements HasValue<Color> {
selPreview = new ColorPickerPreview(selectedColor);
selPreview.setWidth("100%");
selPreview.setHeight("20px");
+ selPreview.setRequiredIndicatorVisible(required);
selPreview.addValueChangeListener(this::colorChanged);
selectors.add(selPreview);
@@ -711,12 +718,15 @@ public class ColorPickerPopup extends Window implements HasValue<Color> {
@Override
public void setRequiredIndicatorVisible(boolean visible) {
- super.setRequiredIndicatorVisible(visible);
+ required = visible;
+ if (selPreview != null) {
+ selPreview.setRequiredIndicatorVisible(required);
+ }
}
@Override
public boolean isRequiredIndicatorVisible() {
- return super.isRequiredIndicatorVisible();
+ return required;
}
private static Logger getLogger() {
@@ -725,11 +735,33 @@ public class ColorPickerPopup extends Window implements HasValue<Color> {
@Override
public void setReadOnly(boolean readOnly) {
- super.setReadOnly(readOnly);
+ this.readOnly = readOnly;
+ updateColorComponents();
}
@Override
public boolean isReadOnly() {
- return super.isReadOnly();
+ return readOnly;
+ }
+
+ private void updateColorComponents() {
+ if (getContent() != null) {
+ updateColorComponents(getContent());
+ }
+ }
+
+ private void updateColorComponents(Component component) {
+ if (component instanceof HasValue<?>) {
+ ((HasValue<?>) component).setReadOnly(isReadOnly());
+ ((HasValue<?>) component)
+ .setRequiredIndicatorVisible(isRequiredIndicatorVisible());
+ }
+ if (component instanceof HasComponents) {
+ Iterator<Component> iterator = ((HasComponents) component)
+ .iterator();
+ while (iterator.hasNext()) {
+ updateColorComponents(iterator.next());
+ }
+ }
}
}
diff --git a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
index 9c4ee78069..0c99779658 100644
--- a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
+++ b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.ui.components.colorpicker;
+import java.util.Iterator;
import java.util.Objects;
import com.vaadin.data.HasValue;
@@ -22,6 +23,7 @@ import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
+import com.vaadin.ui.HasComponents;
import com.vaadin.ui.TextField;
/**
@@ -44,6 +46,8 @@ public class ColorPickerPreview extends CssLayout implements HasValue<Color> {
private String oldValue;
private Registration valueChangeListenerRegistration = null;
+ private boolean readOnly;
+
private ColorPickerPreview() {
setStyleName("v-colorpicker-preview");
field = new TextField();
@@ -187,21 +191,39 @@ public class ColorPickerPreview extends CssLayout implements HasValue<Color> {
@Override
public void setRequiredIndicatorVisible(boolean visible) {
- super.setRequiredIndicatorVisible(visible);
+ field.setRequiredIndicatorVisible(visible);
}
@Override
public boolean isRequiredIndicatorVisible() {
- return super.isRequiredIndicatorVisible();
+ return field.isRequiredIndicatorVisible();
}
@Override
public void setReadOnly(boolean readOnly) {
- super.setReadOnly(readOnly);
+ this.readOnly = readOnly;
+ updateColorComponents();
}
@Override
public boolean isReadOnly() {
- return super.isReadOnly();
+ return readOnly;
+ }
+
+ private void updateColorComponents() {
+ iterator().forEachRemaining(this::updateColorComponents);
+ }
+
+ private void updateColorComponents(Component component) {
+ if (component instanceof HasValue<?>) {
+ ((HasValue<?>) component).setReadOnly(isReadOnly());
+ }
+ if (component instanceof HasComponents) {
+ Iterator<Component> iterator = ((HasComponents) component)
+ .iterator();
+ while (iterator.hasNext()) {
+ updateColorComponents(iterator.next());
+ }
+ }
}
}
diff --git a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java
index f762aae827..9ee87dc0c8 100644
--- a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java
+++ b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerSelect.java
@@ -182,8 +182,21 @@ public class ColorPickerSelect extends CustomField<Color> {
}
}
+ /**
+ * Returns the selected value.
+ * <p>
+ * Value can be {@code null} if component is not yet initialized via
+ * {@link #initContent()}
+ *
+ * @see ColorPickerSelect#initContent()
+ *
+ * @return the selected color, may be {@code null}
+ */
@Override
public Color getValue() {
+ if (grid == null) {
+ return null;
+ }
return grid.getValue();
}
diff --git a/server/src/main/java/com/vaadin/ui/declarative/DesignContext.java b/server/src/main/java/com/vaadin/ui/declarative/DesignContext.java
index b72edc4c1a..28004104cb 100644
--- a/server/src/main/java/com/vaadin/ui/declarative/DesignContext.java
+++ b/server/src/main/java/com/vaadin/ui/declarative/DesignContext.java
@@ -33,6 +33,7 @@ import com.vaadin.annotations.DesignRoot;
import com.vaadin.server.Constants;
import com.vaadin.server.DeploymentConfiguration;
import com.vaadin.server.VaadinService;
+import com.vaadin.shared.Registration;
import com.vaadin.ui.Component;
import com.vaadin.ui.HasComponents;
import com.vaadin.ui.declarative.Design.ComponentFactory;
@@ -628,10 +629,12 @@ public class DesignContext implements Serializable {
*
* @param listener
* the component creation listener to be added
+ * @return a registration object for removing the listener
*/
- public void addComponentCreationListener(
+ public Registration addComponentCreationListener(
ComponentCreationListener listener) {
listeners.add(listener);
+ return () -> listeners.remove(listener);
}
/**
@@ -639,7 +642,11 @@ public class DesignContext implements Serializable {
*
* @param listener
* the component creation listener to be removed
+ * @deprecated Use a {@link Registration} object returned by
+ * {@link #addComponentCreationListener(ComponentCreationListener)}
+ * a listener
*/
+ @Deprecated
public void removeComponentCreationListener(
ComponentCreationListener listener) {
listeners.remove(listener);
diff --git a/server/src/test/java/com/vaadin/server/RemoveListenersDeprecatedTest.java b/server/src/test/java/com/vaadin/server/RemoveListenersDeprecatedTest.java
index 3ca5092ac5..e9c97d1b80 100644
--- a/server/src/test/java/com/vaadin/server/RemoveListenersDeprecatedTest.java
+++ b/server/src/test/java/com/vaadin/server/RemoveListenersDeprecatedTest.java
@@ -1,29 +1,97 @@
package com.vaadin.server;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
import java.util.regex.Pattern;
import org.junit.Assert;
import org.junit.Test;
+import com.vaadin.event.EventRouter;
+import com.vaadin.event.MethodEventSource;
+import com.vaadin.server.data.AbstractDataProvider;
+import com.vaadin.shared.Registration;
import com.vaadin.tests.VaadinClasses;
public class RemoveListenersDeprecatedTest {
+ private static final List<Predicate<Method>> ALLOW_REMOVE_LISTENER = new ArrayList<>();
+
+ static {
+ ALLOW_REMOVE_LISTENER.add(
+ RemoveListenersDeprecatedTest::acceptAbstarctClientConnectorRemoveMethods);
+ ALLOW_REMOVE_LISTENER
+ .add(RemoveListenersDeprecatedTest::acceptAbstractDataProvider);
+ ALLOW_REMOVE_LISTENER
+ .add(RemoveListenersDeprecatedTest::acceptMethodEventSource);
+ }
+
@Test
public void allRemoveListenerMethodsMarkedAsDeprecated() {
- Pattern methodPattern = Pattern.compile("remove.*Listener");
+ Pattern removePattern = Pattern.compile("remove.*Listener");
+ Pattern addPattern = Pattern.compile("add.*Listener");
+ int count = 0;
for (Class<? extends Object> serverClass : VaadinClasses
- .getComponents()) {
- for (Method method : serverClass.getMethods()) {
- if (methodPattern.matcher(method.getName()).matches()) {
+ .getAllServerSideClasses()) {
+ count++;
+ if (serverClass.equals(EventRouter.class)) {
+ continue;
+ }
+ for (Method method : serverClass.getDeclaredMethods()) {
+ if (Modifier.isPrivate(method.getModifiers())) {
+ continue;
+ }
+ if (addPattern.matcher(method.getName()).matches()
+ && method.getAnnotation(Deprecated.class) == null) {
+ Class<?> returnType = method.getReturnType();
+ Assert.assertEquals(
+ "Method " + method.getName()
+ + " is not deprectated in class "
+ + serverClass.getName()
+ + " and doesn't return a Registration object",
+ Registration.class, returnType);
+ }
+ if (ALLOW_REMOVE_LISTENER.stream()
+ .anyMatch(predicate -> predicate.test(method))) {
+ continue;
+ }
+
+ if (removePattern.matcher(method.getName()).matches()) {
Assert.assertNotNull(
"Method " + method.getName() + " in class "
- + serverClass.getSimpleName()
+ + serverClass.getName()
+ " has not been marked as deprecated.",
method.getAnnotation(Deprecated.class));
}
}
}
+ Assert.assertTrue(count > 0);
+ }
+
+ private static boolean acceptMethodEventSource(Method method) {
+ return method.getDeclaringClass().equals(MethodEventSource.class)
+ && method.getParameterCount() == 2;
+ }
+
+ private static boolean acceptAbstarctClientConnectorRemoveMethods(
+ Method method) {
+ if (method.getDeclaringClass().equals(AbstractClientConnector.class)) {
+ if (method.getParameterCount() == 2) {
+ return true;
+ } else if (method.getParameterCount() == 0) {
+ return false;
+ } else {
+ return method.getParameterTypes()[0].equals(String.class);
+ }
+ }
+ return false;
+ }
+
+ private static boolean acceptAbstractDataProvider(Method method) {
+ return method.getDeclaringClass().equals(AbstractDataProvider.class)
+ && method.getParameterCount() == 2;
}
}
diff --git a/server/src/test/java/com/vaadin/tests/VaadinClasses.java b/server/src/test/java/com/vaadin/tests/VaadinClasses.java
index 3e3c641de8..287222be48 100644
--- a/server/src/test/java/com/vaadin/tests/VaadinClasses.java
+++ b/server/src/test/java/com/vaadin/tests/VaadinClasses.java
@@ -1,23 +1,13 @@
package com.vaadin.tests;
import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.net.JarURLConnection;
import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
import java.util.List;
-import java.util.jar.JarEntry;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
-import org.junit.Test;
-
-import com.vaadin.server.VaadinSession;
+import com.vaadin.tests.server.ClasspathHelper;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CustomComponent;
@@ -53,40 +43,26 @@ public class VaadinClasses {
}
public static List<Class<? extends Component>> getComponents() {
- try {
- return findClasses(Component.class, "com.vaadin.ui");
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
+ return getServerClasses(Component.class::isAssignableFrom)
+ .map(VaadinClasses::castComponentClass)
+ .collect(Collectors.toList());
}
public static List<Class<? extends Object>> getThemeClasses() {
- try {
- return findClasses(Object.class, "com.vaadin.ui.themes");
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
+ return getServerClasses(clazz -> clazz.getPackage().getName()
+ .equals("com.vaadin.ui.themes")).collect(Collectors.toList());
}
public static List<Class<? extends Object>> getAllServerSideClasses() {
- try {
- return findClassesNoTests(Object.class, "com.vaadin",
- new String[] { "com.vaadin.tests", "com.vaadin.client" });
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
+ return getServerClasses(clazz -> true).collect(Collectors.toList());
}
public static List<Class<? extends ComponentContainer>> getComponentContainers() {
- try {
- return findClasses(ComponentContainer.class, "com.vaadin.ui");
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- }
+ return getServerClasses(ComponentContainer.class::isAssignableFrom)
+ .filter(clazz -> clazz.getPackage().getName()
+ .startsWith("com.vaadin.ui"))
+ .map(VaadinClasses::castContainerClass)
+ .collect(Collectors.toList());
}
public static List<Class<? extends ComponentContainer>> getComponentContainersSupportingAddRemoveComponent() {
@@ -110,133 +86,28 @@ public class VaadinClasses {
return classes;
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static List<Class<?>> getBasicComponentTests() {
+ public static Stream<Class<?>> getServerClasses(
+ Predicate<? super Class<?>> predicate) {
try {
- // Given as name to avoid dependencies on testbench source folder
- return (List) findClasses(
- Class.forName(
- "com.vaadin.tests.components.AbstractComponentTest"),
- "com.vaadin.tests.components");
- } catch (Exception e) {
- e.printStackTrace();
- return null;
+ File testRoot = new File(
+ VaadinClasses.class.getResource("/").toURI());
+ ClasspathHelper helper = new ClasspathHelper();
+ return helper
+ .getVaadinClassesFromClasspath(
+ entry -> !testRoot.equals(new File(entry)))
+ .filter(predicate);
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
}
-
- }
-
- public static <T> List<Class<? extends T>> findClasses(Class<T> baseClass,
- String basePackage) throws IOException {
- return findClasses(baseClass, basePackage, new String[] {});
}
- private static <T> List<Class<? extends T>> findClasses(Class<T> baseClass,
- String basePackage, String[] ignoredPackages) throws IOException {
- List<Class<? extends T>> classes = new ArrayList<>();
- String basePackageDirName = "/" + basePackage.replace('.', '/');
- URL location = VaadinSession.class.getResource(basePackageDirName);
- if (location.getProtocol().equals("file")) {
- try {
- File f = new File(location.toURI());
- if (!f.exists()) {
- throw new IOException(
- "Directory " + f.toString() + " does not exist");
- }
- findPackages(f, basePackage, baseClass, classes,
- ignoredPackages);
- } catch (URISyntaxException e) {
- throw new IOException(e.getMessage());
- }
- } else if (location.getProtocol().equals("jar")) {
- JarURLConnection juc = (JarURLConnection) location.openConnection();
- findPackages(juc, basePackage, baseClass, classes);
- }
-
- Collections.sort(classes, (Class<? extends T> o1, Class<? extends T> o2) -> o1.getName().compareTo(o2.getName()));
- return classes;
+ private static Class<? extends Component> castComponentClass(
+ Class<?> clazz) {
+ return (Class<? extends Component>) clazz;
}
- private static <T> List<Class<? extends T>> findClassesNoTests(
- Class<T> baseClass, String basePackage, String[] ignoredPackages)
- throws IOException {
- List<Class<? extends T>> classes = findClasses(baseClass, basePackage,
- ignoredPackages);
- List<Class<? extends T>> classesNoTests = new ArrayList<>();
- for (Class<? extends T> clazz : classes) {
- if (!clazz.getName().contains("Test")) {
- boolean testPresent = false;
- for (Method method : clazz.getMethods()) {
- if (method.isAnnotationPresent(Test.class)) {
- testPresent = true;
- break;
- }
- }
- if (!testPresent) {
- classesNoTests.add(clazz);
- }
- }
- }
- return classesNoTests;
- }
-
- private static <T> void findPackages(JarURLConnection juc,
- String javaPackage, Class<T> baseClass,
- Collection<Class<? extends T>> result) throws IOException {
- String prefix = "com/vaadin/ui";
- Enumeration<JarEntry> ent = juc.getJarFile().entries();
- while (ent.hasMoreElements()) {
- JarEntry e = ent.nextElement();
- if (e.getName().endsWith(".class")
- && e.getName().startsWith(prefix)) {
- String fullyQualifiedClassName = e.getName().replace('/', '.')
- .replace(".class", "");
- addClassIfMatches(result, fullyQualifiedClassName, baseClass);
- }
- }
- }
-
- private static <T> void findPackages(File parent, String javaPackage,
- Class<T> baseClass, Collection<Class<? extends T>> result,
- String[] ignoredPackages) {
- for (String ignoredPackage : ignoredPackages) {
- if (javaPackage.equals(ignoredPackage)) {
- return;
- }
- }
-
- for (File file : parent.listFiles()) {
- if (file.isDirectory()) {
- findPackages(file, javaPackage + "." + file.getName(),
- baseClass, result, ignoredPackages);
- } else if (file.getName().endsWith(".class")) {
- String fullyQualifiedClassName = javaPackage + "."
- + file.getName().replace(".class", "");
- addClassIfMatches(result, fullyQualifiedClassName, baseClass);
- }
- }
-
- }
-
- @SuppressWarnings("unchecked")
- private static <T> void addClassIfMatches(
- Collection<Class<? extends T>> result,
- String fullyQualifiedClassName, Class<T> baseClass) {
- try {
- // Try to load the class
-
- Class<?> c = Class.forName(fullyQualifiedClassName);
- if (baseClass.isAssignableFrom(c)
- && !Modifier.isAbstract(c.getModifiers())
- && !c.isAnonymousClass() && !c.isMemberClass()
- && !c.isLocalClass()) {
- result.add((Class<? extends T>) c);
- }
- } catch (Exception e) {
- // Could ignore that class cannot be loaded
- e.printStackTrace();
- } catch (LinkageError e) {
- // Ignore. Client side classes will at least throw LinkageErrors
- }
-
+ private static Class<? extends ComponentContainer> castContainerClass(
+ Class<?> clazz) {
+ return (Class<? extends ComponentContainer>) clazz;
}
}
diff --git a/server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java b/server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java
new file mode 100644
index 0000000000..8dfe96d1c3
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/ClasspathHelper.java
@@ -0,0 +1,137 @@
+package com.vaadin.tests.server;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Modifier;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Allows to get classes from the current classpath using classes FQN filter.
+ * <p>
+ * The methods in the class return all real (not anonymous and not private)
+ * classes from the filtered classpath.
+ *
+ * @author Vaadin Ltd
+ *
+ */
+public class ClasspathHelper {
+
+ public static final String COM_VAADIN_FILE_PREFIX = "com"
+ + File.separatorChar + "vaadin" + File.separatorChar;
+ private final Predicate<String> skipClassesFilter;
+
+ public ClasspathHelper(Predicate<String> skipClassesFilter) {
+ this.skipClassesFilter = skipClassesFilter;
+ }
+
+ public ClasspathHelper() {
+ this(fqn -> false);
+ }
+
+ public Stream<Class<?>> getVaadinClassesFromClasspath(
+ Predicate<String> classpathFilter,
+ Predicate<Class<?>> classFilter) {
+ return getRawClasspathEntries().stream().filter(classpathFilter)
+ .map(File::new).map(file -> getVaadinClassesFromFile(file))
+ .flatMap(List::stream).filter(classFilter)
+ .filter(cls -> !cls.isSynthetic() && !cls.isAnonymousClass()
+ && !Modifier.isPrivate(cls.getModifiers()));
+
+ }
+
+ public Stream<Class<?>> getVaadinClassesFromClasspath(
+ Predicate<String> classpathFilter) {
+ return getVaadinClassesFromClasspath(classpathFilter, cls -> true);
+ }
+
+ private List<Class<?>> getVaadinClassesFromFile(File classesRoot) {
+ try {
+ if (classesRoot.isDirectory()) {
+ return Files.walk(classesRoot.toPath())
+ .filter(Files::isRegularFile)
+ .filter(path -> path.toFile().getName()
+ .endsWith(".class"))
+ .filter(path -> classesRoot.toPath().relativize(path)
+ .toString().contains(COM_VAADIN_FILE_PREFIX))
+ .map(path -> getClassFromFile(path,
+ classesRoot.toPath()))
+ .filter(Objects::nonNull).collect(Collectors.toList());
+ } else if (classesRoot.getName().toLowerCase(Locale.ENGLISH)
+ .endsWith(".jar")) {
+ URI uri = URI.create("jar:file:" + classesRoot.getPath());
+ FileSystem fileSystem;
+ try {
+ fileSystem = FileSystems.getFileSystem(uri);
+ } catch (FileSystemNotFoundException e) {
+ fileSystem = null;
+ }
+ if (fileSystem == null) {
+ fileSystem = FileSystems.newFileSystem(uri,
+ Collections.emptyMap());
+ }
+ Path root = fileSystem.getPath(File.separator);
+ return Files.walk(root).filter(Files::isRegularFile)
+ .filter(path -> path.toUri().getSchemeSpecificPart()
+ .endsWith(".class"))
+ .filter(path -> root.relativize(path).toString()
+ .contains(COM_VAADIN_FILE_PREFIX))
+ .map(path -> getClassFromFile(path, root))
+ .filter(Objects::nonNull).collect(Collectors.toList());
+ }
+ return null;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private Class<?> getClassFromFile(Path path, Path root) {
+ Path relative = root.relativize(path);
+ String name = relative.toString();
+ name = name.substring(0, name.length() - ".class".length());
+ name = name.replace(File.separatorChar, '.');
+ if (skipClassesFilter.test(name)) {
+ return null;
+ }
+ try {
+ return Class.forName(name, false, getClass().getClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private final static List<String> getRawClasspathEntries() {
+ List<String> locations = new ArrayList<>();
+
+ String pathSep = System.getProperty("path.separator");
+ String classpath = System.getProperty("java.class.path");
+
+ if (classpath.startsWith("\"")) {
+ classpath = classpath.substring(1);
+ }
+ if (classpath.endsWith("\"")) {
+ classpath = classpath.substring(0, classpath.length() - 1);
+ }
+
+ String[] split = classpath.split(pathSep);
+ for (int i = 0; i < split.length; i++) {
+ String classpathEntry = split[i];
+ locations.add(classpathEntry);
+ }
+
+ return locations;
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/FinalMethodTest.java b/server/src/test/java/com/vaadin/tests/server/component/FinalMethodTest.java
index 5519163012..71d423808e 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/FinalMethodTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/FinalMethodTest.java
@@ -4,6 +4,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
+import org.junit.Assert;
import org.junit.Test;
import com.vaadin.tests.VaadinClasses;
@@ -23,35 +24,39 @@ public class FinalMethodTest {
@Test
public void testThatComponentsHaveNoFinalMethods() {
HashSet<Class<?>> tested = new HashSet<>();
+ int count = 0;
for (Class<? extends Component> c : VaadinClasses.getComponents()) {
ensureNoFinalMethods(c, tested);
+ count++;
}
+ Assert.assertTrue(count > 0);
}
- private void ensureNoFinalMethods(Class<?> c, HashSet<Class<?>> tested) {
- if (tested.contains(c)) {
+ private void ensureNoFinalMethods(Class<?> clazz,
+ HashSet<Class<?>> tested) {
+ if (tested.contains(clazz)) {
return;
}
- tested.add(c);
+ tested.add(clazz);
- if (c == Object.class) {
+ if (clazz == null || clazz.equals(Object.class)) {
return;
}
- System.out.println("Checking " + c.getName());
- for (Method m : c.getDeclaredMethods()) {
+ System.out.println("Checking " + clazz.getName());
+ for (Method m : clazz.getDeclaredMethods()) {
if (isPrivate(m)) {
continue;
}
if (isFinal(m)) {
- String error = "Class " + c.getName() + " contains a "
+ String error = "Class " + clazz.getName() + " contains a "
+ (isPublic(m) ? "public" : "non-public")
+ " final method: " + m.getName();
// System.err.println(error);
throw new RuntimeException(error);
}
}
- ensureNoFinalMethods(c.getSuperclass(), tested);
+ ensureNoFinalMethods(clazz.getSuperclass(), tested);
}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java b/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java
index b6392f0910..87986c1b5c 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/StateGetDoesNotMarkDirtyTest.java
@@ -1,16 +1,20 @@
package com.vaadin.tests.server.component;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import com.vaadin.server.VaadinSession;
import com.vaadin.tests.VaadinClasses;
import com.vaadin.ui.Component;
import com.vaadin.ui.ConnectorTracker;
@@ -25,17 +29,27 @@ public class StateGetDoesNotMarkDirtyTest {
public void setUp() {
excludedMethods.add(Label.class.getName() + "getDataProviderValue");
excludedMethods.add("getConnectorId");
+ excludedMethods.add("getContent");
}
@Test
public void testGetDoesntMarkStateDirty() throws Exception {
- for (Class<? extends Component> c : VaadinClasses.getComponents()) {
- Component newInstance = construct(c);
+ int count = 0;
+ for (Class<? extends Component> clazz : VaadinClasses.getComponents()) {
+ if (clazz.isInterface()
+ || Modifier.isAbstract(clazz.getModifiers())) {
+ continue;
+ }
+ Component newInstance = construct(clazz);
+ if (newInstance == null) {
+ continue;
+ }
+ count++;
prepareMockUI(newInstance);
Set<Method> methods = new HashSet<>();
- methods.addAll(Arrays.asList(c.getMethods()));
- methods.addAll(Arrays.asList(c.getDeclaredMethods()));
+ methods.addAll(Arrays.asList(clazz.getMethods()));
+ methods.addAll(Arrays.asList(clazz.getDeclaredMethods()));
for (Method method : methods) {
try {
if (method.getName().startsWith("is")
@@ -49,7 +63,7 @@ public class StateGetDoesNotMarkDirtyTest {
continue;
}
if (excludedMethods
- .contains(c.getName() + method.getName())) {
+ .contains(clazz.getName() + method.getName())) {
// blacklisted method for specific classes
continue;
}
@@ -62,40 +76,63 @@ public class StateGetDoesNotMarkDirtyTest {
method.invoke(newInstance);
}
} catch (Exception e) {
- System.err.println("problem with method " + c.getName()
+ System.err.println("problem with method " + clazz.getName()
+ "# " + method.getName());
e.printStackTrace();
throw e;
}
}
}
-
+ Assert.assertTrue(count > 0);
}
private void prepareMockUI(Component newInstance) {
+ UI ui = mockUI();
+ ConnectorTracker connectorTracker = ui.getConnectorTracker();
+ Mockito.doThrow(new RuntimeException("getState(true) called in getter"))
+ .when(connectorTracker).markDirty(newInstance);
+ newInstance.setParent(null);
+ newInstance.setParent(ui);
+ }
+
+ private UI mockUI() {
UI ui = Mockito.mock(UI.class);
Mockito.when(ui.getLocale()).thenReturn(Locale.ENGLISH);
ConnectorTracker connectorTracker = Mockito
.mock(ConnectorTracker.class);
Mockito.when(ui.getConnectorTracker()).thenReturn(connectorTracker);
- Mockito.doThrow(new RuntimeException("getState(true) called in getter"))
- .when(connectorTracker).markDirty(newInstance);
-
- newInstance.setParent(ui);
+ return ui;
}
- private Component construct(Class<? extends Component> c) {
+ private Component construct(Class<? extends Component> clazz) {
try {
- try {
- Constructor<? extends Component> declaredConstructor = c
- .getDeclaredConstructor();
- declaredConstructor.setAccessible(true);
- return declaredConstructor.newInstance();
- } catch (NoSuchMethodException e) {
- return c.newInstance();
+ Constructor<? extends Component> declaredConstructor = clazz
+ .getDeclaredConstructor();
+ declaredConstructor.setAccessible(true);
+ Component component = declaredConstructor.newInstance();
+
+ if (component instanceof UI) {
+ return component;
}
- } catch (Exception e) {
+ emulateAttach(component);
+ return component;
+ } catch (NoSuchMethodException e) {
+ // no default CTOR, skip
+ return null;
+ } catch (InstantiationException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
+
+ private void emulateAttach(Component component) {
+ UI ui = mockUI();
+ VaadinSession session = Mockito.mock(VaadinSession.class);
+ Mockito.when(session.hasLock()).thenReturn(true);
+ Mockito.when(ui.getSession()).thenReturn(session);
+ component.setParent(ui);
+
+ component.attach();
+ }
+
}
diff --git a/server/src/test/java/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java b/server/src/test/java/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java
index 4662f6f84b..e5537992c0 100644
--- a/server/src/test/java/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/componentcontainer/AddRemoveComponentTest.java
@@ -1,5 +1,8 @@
package com.vaadin.tests.server.componentcontainer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.util.List;
import org.junit.Assert;
@@ -15,16 +18,30 @@ public class AddRemoveComponentTest {
@Test
public void testRemoveComponentFromWrongContainer()
- throws InstantiationException, IllegalAccessException {
+ throws InstantiationException, IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException {
List<Class<? extends ComponentContainer>> containerClasses = VaadinClasses
.getComponentContainersSupportingAddRemoveComponent();
+ Assert.assertTrue(containerClasses.size() > 0);
+
// No default constructor, special case
containerClasses.remove(CustomLayout.class);
testRemoveComponentFromWrongContainer(new CustomLayout("dummy"));
- for (Class<? extends ComponentContainer> c : containerClasses) {
- testRemoveComponentFromWrongContainer(c.newInstance());
+ for (Class<? extends ComponentContainer> clazz : containerClasses) {
+ if (Modifier.isAbstract(clazz.getModifiers())) {
+ continue;
+ }
+ try {
+ Constructor<? extends ComponentContainer> constructor = clazz
+ .getConstructor();
+ constructor.setAccessible(true);
+ testRemoveComponentFromWrongContainer(
+ constructor.newInstance());
+ } catch (NoSuchMethodException ignore) {
+ // if there is no default CTOR, just ignore
+ }
}
}