summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java2
-rw-r--r--server/src/main/java/com/vaadin/annotations/Push.java2
-rw-r--r--server/src/main/java/com/vaadin/annotations/Theme.java2
-rw-r--r--server/src/main/java/com/vaadin/annotations/Title.java2
-rw-r--r--server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java2
-rw-r--r--server/src/main/java/com/vaadin/annotations/Widgetset.java2
-rw-r--r--server/src/main/java/com/vaadin/server/UIProvider.java34
-rw-r--r--server/src/main/java/com/vaadin/server/VaadinPortlet.java27
-rw-r--r--server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java98
-rw-r--r--server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java13
-rw-r--r--server/src/main/java/com/vaadin/server/communication/UidlWriter.java9
-rw-r--r--server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java38
-rw-r--r--server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java11
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java19
-rw-r--r--server/src/main/java/com/vaadin/ui/AbstractSelect.java15
-rw-r--r--server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java10
-rw-r--r--server/src/main/java/com/vaadin/ui/FormLayout.java2
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java9
-rw-r--r--server/src/main/java/com/vaadin/ui/GridLayout.java20
-rw-r--r--server/src/main/java/com/vaadin/ui/Window.java4
-rw-r--r--server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java53
-rw-r--r--server/src/test/java/com/vaadin/server/UIProviderTest.java113
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java42
23 files changed, 415 insertions, 114 deletions
diff --git a/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java b/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java
index 7f4ef3ffe5..86723b97fc 100644
--- a/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java
+++ b/server/src/main/java/com/vaadin/annotations/PreserveOnRefresh.java
@@ -17,6 +17,7 @@
package com.vaadin.annotations;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -45,6 +46,7 @@ import com.vaadin.ui.UI;
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
+@Inherited
public @interface PreserveOnRefresh {
// Empty marker annotation
}
diff --git a/server/src/main/java/com/vaadin/annotations/Push.java b/server/src/main/java/com/vaadin/annotations/Push.java
index b6a28c1560..736bc4488b 100644
--- a/server/src/main/java/com/vaadin/annotations/Push.java
+++ b/server/src/main/java/com/vaadin/annotations/Push.java
@@ -17,6 +17,7 @@
package com.vaadin.annotations;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -38,6 +39,7 @@ import com.vaadin.ui.UI;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
+@Inherited
public @interface Push {
/**
* Returns the {@link PushMode} to use for the annotated UI. The default
diff --git a/server/src/main/java/com/vaadin/annotations/Theme.java b/server/src/main/java/com/vaadin/annotations/Theme.java
index 61c47389ad..03fa1179bc 100644
--- a/server/src/main/java/com/vaadin/annotations/Theme.java
+++ b/server/src/main/java/com/vaadin/annotations/Theme.java
@@ -17,6 +17,7 @@
package com.vaadin.annotations;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -28,6 +29,7 @@ import com.vaadin.ui.UI;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
+@Inherited
public @interface Theme {
/**
* @return simple name of the theme
diff --git a/server/src/main/java/com/vaadin/annotations/Title.java b/server/src/main/java/com/vaadin/annotations/Title.java
index 38a3d75f17..07eaf17e33 100644
--- a/server/src/main/java/com/vaadin/annotations/Title.java
+++ b/server/src/main/java/com/vaadin/annotations/Title.java
@@ -17,6 +17,7 @@
package com.vaadin.annotations;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -28,6 +29,7 @@ import com.vaadin.ui.UI;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
+@Inherited
public @interface Title {
/**
* Gets the HTML title that should be used if the UI is used on it's own.
diff --git a/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java b/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java
index 00af38ecc1..907f2c3a0c 100644
--- a/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java
+++ b/server/src/main/java/com/vaadin/annotations/VaadinServletConfiguration.java
@@ -18,6 +18,7 @@ package com.vaadin.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -44,6 +45,7 @@ import com.vaadin.ui.UI;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
+@Inherited
public @interface VaadinServletConfiguration {
/**
* Defines the init parameter name for methods in
diff --git a/server/src/main/java/com/vaadin/annotations/Widgetset.java b/server/src/main/java/com/vaadin/annotations/Widgetset.java
index c6ef6a7194..2dcf93af13 100644
--- a/server/src/main/java/com/vaadin/annotations/Widgetset.java
+++ b/server/src/main/java/com/vaadin/annotations/Widgetset.java
@@ -17,6 +17,7 @@
package com.vaadin.annotations;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -28,6 +29,7 @@ import com.vaadin.ui.UI;
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
+@Inherited
public @interface Widgetset {
/**
* @return name of the widgetset
diff --git a/server/src/main/java/com/vaadin/server/UIProvider.java b/server/src/main/java/com/vaadin/server/UIProvider.java
index d3d834cad7..4ed86b9c31 100644
--- a/server/src/main/java/com/vaadin/server/UIProvider.java
+++ b/server/src/main/java/com/vaadin/server/UIProvider.java
@@ -18,6 +18,7 @@ package com.vaadin.server;
import java.io.Serializable;
import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.annotations.Push;
@@ -43,8 +44,15 @@ public abstract class UIProvider implements Serializable {
/**
* Helper to get an annotation for a class. If the annotation is not present
- * on the target class, its super classes and implemented interfaces are
- * also searched for the annotation.
+ * on the target class, its super classes and directly implemented
+ * interfaces are also searched for the annotation. Interfaces implemented
+ * by superclasses are not taken into account.
+ * <p>
+ * Note that searching implemented interfaces for {@code @Inherited}
+ * annotations and searching for superclasses for non-inherited annotations
+ * do not follow the standard semantics and are supported for backwards
+ * compatibility. Future versions of the framework might only support the
+ * standard semantics of {@code @Inherited}.
*
* @param clazz
* the class from which the annotation should be found
@@ -55,18 +63,26 @@ public abstract class UIProvider implements Serializable {
*/
protected static <T extends Annotation> T getAnnotationFor(Class<?> clazz,
Class<T> annotationType) {
- // Find from the class hierarchy
- Class<?> currentType = clazz;
- while (currentType != Object.class) {
- T annotation = currentType.getAnnotation(annotationType);
+ // Don't discover hierarchy if annotation is inherited
+ if (annotationType.getAnnotation(Inherited.class) != null) {
+ T annotation = clazz.getAnnotation(annotationType);
if (annotation != null) {
return annotation;
- } else {
- currentType = currentType.getSuperclass();
+ }
+ } else {
+ // Find from the class hierarchy
+ Class<?> currentType = clazz;
+ while (currentType != Object.class) {
+ T annotation = currentType.getAnnotation(annotationType);
+ if (annotation != null) {
+ return annotation;
+ } else {
+ currentType = currentType.getSuperclass();
+ }
}
}
- // Find from an implemented interface
+ // Find from a directly implemented interface
for (Class<?> iface : clazz.getInterfaces()) {
T annotation = iface.getAnnotation(annotationType);
if (annotation != null) {
diff --git a/server/src/main/java/com/vaadin/server/VaadinPortlet.java b/server/src/main/java/com/vaadin/server/VaadinPortlet.java
index 043f95fd7b..5c91b6669c 100644
--- a/server/src/main/java/com/vaadin/server/VaadinPortlet.java
+++ b/server/src/main/java/com/vaadin/server/VaadinPortlet.java
@@ -180,6 +180,14 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
*/
public static class VaadinLiferayRequest extends
VaadinHttpAndPortletRequest {
+ /**
+ * The PortalUtil class to use. Set to either
+ * {@link #LIFERAY_6_PORTAL_UTIL} or {@link #LIFERAY_7_PORTAL_UTIL} the
+ * first time it is needed.
+ */
+ private static String portalUtilClass = null;
+ private static final String LIFERAY_6_PORTAL_UTIL = "com.liferay.portal.util.PortalUtil";
+ private static final String LIFERAY_7_PORTAL_UTIL = "com.liferay.portal.kernel.util.PortalUtil";
public VaadinLiferayRequest(PortletRequest request,
VaadinPortletService vaadinService) {
@@ -247,19 +255,28 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
@Override
protected HttpServletRequest getServletRequest(PortletRequest request) {
+ if (portalUtilClass == null) {
+ try {
+ invokeStaticLiferayMethod(LIFERAY_7_PORTAL_UTIL,
+ "getHttpServletRequest", request,
+ "javax.portlet.PortletRequest");
+ portalUtilClass = LIFERAY_7_PORTAL_UTIL;
+ } catch (Exception e) {
+ // Liferay 6 or older
+ portalUtilClass = LIFERAY_6_PORTAL_UTIL;
+ }
+ }
try {
// httpRequest = PortalUtil.getHttpServletRequest(request);
HttpServletRequest httpRequest = (HttpServletRequest) invokeStaticLiferayMethod(
- "com.liferay.portal.util.PortalUtil",
- "getHttpServletRequest", request,
+ portalUtilClass, "getHttpServletRequest", request,
"javax.portlet.PortletRequest");
// httpRequest =
// PortalUtil.getOriginalServletRequest(httpRequest);
httpRequest = (HttpServletRequest) invokeStaticLiferayMethod(
- "com.liferay.portal.util.PortalUtil",
- "getOriginalServletRequest", httpRequest,
- "javax.servlet.http.HttpServletRequest");
+ portalUtilClass, "getOriginalServletRequest",
+ httpRequest, "javax.servlet.http.HttpServletRequest");
return httpRequest;
} catch (Exception e) {
throw new IllegalStateException("Liferay request not detected",
diff --git a/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java
index 593b1f544f..3503a2d8b1 100644
--- a/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/main/java/com/vaadin/server/communication/ServerRpcHandler.java
@@ -316,7 +316,7 @@ public class ServerRpcHandler implements Serializable {
* 6 semantics for components and add-ons that do not use Vaadin 7 RPC
* directly.
*
- * @param uI
+ * @param ui
* the UI receiving the invocations data
* @param lastSyncIdSeenByClient
* the most recent sync id the client has seen at the time the
@@ -324,20 +324,21 @@ public class ServerRpcHandler implements Serializable {
* @param invocationsData
* JSON containing all information needed to execute all
* requested RPC calls.
+ * @since
*/
- private void handleInvocations(UI uI, int lastSyncIdSeenByClient,
+ protected void handleInvocations(UI ui, int lastSyncIdSeenByClient,
JsonArray invocationsData) {
// TODO PUSH Refactor so that this is not needed
- LegacyCommunicationManager manager = uI.getSession()
+ LegacyCommunicationManager manager = ui.getSession()
.getCommunicationManager();
try {
- ConnectorTracker connectorTracker = uI.getConnectorTracker();
+ ConnectorTracker connectorTracker = ui.getConnectorTracker();
Set<Connector> enabledConnectors = new HashSet<Connector>();
List<MethodInvocation> invocations = parseInvocations(
- uI.getConnectorTracker(), invocationsData,
+ ui.getConnectorTracker(), invocationsData,
lastSyncIdSeenByClient);
for (MethodInvocation invocation : invocations) {
final ClientConnector connector = connectorTracker
@@ -404,35 +405,11 @@ public class ServerRpcHandler implements Serializable {
}
if (invocation instanceof ServerRpcMethodInvocation) {
- try {
- ServerRpcManager.applyInvocation(connector,
- (ServerRpcMethodInvocation) invocation);
- } catch (RpcInvocationException e) {
- manager.handleConnectorRelatedException(connector, e);
- }
+ handleInvocation(ui, connector,
+ (ServerRpcMethodInvocation) invocation);
} else {
-
- // All code below is for legacy variable changes
LegacyChangeVariablesInvocation legacyInvocation = (LegacyChangeVariablesInvocation) invocation;
- Map<String, Object> changes = legacyInvocation
- .getVariableChanges();
- try {
- if (connector instanceof VariableOwner) {
- // The source parameter is never used anywhere
- changeVariables(null, (VariableOwner) connector,
- changes);
- } else {
- throw new IllegalStateException(
- "Received legacy variable change for "
- + connector.getClass().getName()
- + " ("
- + connector.getConnectorId()
- + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: "
- + changes.keySet());
- }
- } catch (Exception e) {
- manager.handleConnectorRelatedException(connector, e);
- }
+ handleInvocation(ui, connector, legacyInvocation);
}
}
} catch (JsonException e) {
@@ -444,6 +421,63 @@ public class ServerRpcHandler implements Serializable {
}
/**
+ * Handles the given RPC method invocation for the given connector
+ *
+ * @since
+ * @param ui
+ * the UI containing the connector
+ * @param connector
+ * the connector the RPC is targeted to
+ * @param invocation
+ * information about the rpc to invoke
+ */
+ protected void handleInvocation(UI ui, ClientConnector connector,
+ ServerRpcMethodInvocation invocation) {
+ try {
+ ServerRpcManager.applyInvocation(connector, invocation);
+ } catch (RpcInvocationException e) {
+ ui.getSession().getCommunicationManager()
+ .handleConnectorRelatedException(connector, e);
+ }
+
+ }
+
+ /**
+ * Handles the given Legacy variable change RPC method invocation for the
+ * given connector
+ *
+ * @since
+ * @param ui
+ * the UI containing the connector
+ * @param connector
+ * the connector the RPC is targeted to
+ * @param invocation
+ * information about the rpc to invoke
+ */
+ protected void handleInvocation(UI ui, ClientConnector connector,
+ LegacyChangeVariablesInvocation legacyInvocation) {
+ Map<String, Object> changes = legacyInvocation.getVariableChanges();
+ try {
+ if (connector instanceof VariableOwner) {
+ // The source parameter is never used anywhere
+ changeVariables(null, (VariableOwner) connector, changes);
+ } else {
+ throw new IllegalStateException(
+ "Received legacy variable change for "
+ + connector.getClass().getName()
+ + " ("
+ + connector.getConnectorId()
+ + ") which is not a VariableOwner. The client-side connector sent these legacy varaibles: "
+ + changes.keySet());
+ }
+ } catch (Exception e) {
+ ui.getSession().getCommunicationManager()
+ .handleConnectorRelatedException(connector, e);
+ }
+
+ }
+
+ /**
* Parse JSON from the client into a list of MethodInvocation instances.
*
* @param connectorTracker
diff --git a/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java
index dda3d81453..db18bb9e1e 100644
--- a/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java
+++ b/server/src/main/java/com/vaadin/server/communication/UidlRequestHandler.java
@@ -51,9 +51,20 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements
public static final String UIDL_PATH = "UIDL/";
- private ServerRpcHandler rpcHandler = new ServerRpcHandler();
+ private ServerRpcHandler rpcHandler;
public UidlRequestHandler() {
+ rpcHandler = createRpcHandler();
+ }
+
+ /**
+ * Creates the ServerRpcHandler to use
+ *
+ * @since
+ * @return the ServerRpcHandler to use
+ */
+ protected ServerRpcHandler createRpcHandler() {
+ return new ServerRpcHandler();
}
@Override
diff --git a/server/src/main/java/com/vaadin/server/communication/UidlWriter.java b/server/src/main/java/com/vaadin/server/communication/UidlWriter.java
index b117cb4b4d..8a4e62fb24 100644
--- a/server/src/main/java/com/vaadin/server/communication/UidlWriter.java
+++ b/server/src/main/java/com/vaadin/server/communication/UidlWriter.java
@@ -352,9 +352,12 @@ public class UidlWriter implements Serializable {
* @throws IOException
*/
private void writePerformanceData(UI ui, Writer writer) throws IOException {
- writer.write(String.format(", \"timings\":[%d, %d]", ui.getSession()
- .getCumulativeRequestDuration(), ui.getSession()
- .getLastRequestDuration()));
+ if (!ui.getSession().getService().getDeploymentConfiguration()
+ .isProductionMode()) {
+ writer.write(String.format(", \"timings\":[%d, %d]", ui
+ .getSession().getCumulativeRequestDuration(), ui
+ .getSession().getLastRequestDuration()));
+ }
}
private static final Logger getLogger() {
diff --git a/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java b/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java
index 063f4f5346..255f34d936 100644
--- a/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java
+++ b/server/src/main/java/com/vaadin/server/widgetsetutils/ClassPathExplorer.java
@@ -495,7 +495,24 @@ public class ClassPathExplorer {
* @return URL
*/
public static URL getDefaultSourceDirectory() {
+ return getWidgetsetSourceDirectory(null);
+ }
+ /**
+ * Find and return the source directory which contains the given widgetset
+ * file.
+ *
+ * If not applicable or widgetsetFileName is null, return the first
+ * directory (not a JAR file etc.) on the classpath.
+ *
+ * TODO this could be done better...
+ *
+ * @param widgetsetFileName
+ * relative path for the widgetset
+ *
+ * @return URL
+ */
+ public static URL getWidgetsetSourceDirectory(String widgetsetFileName) {
if (debug) {
debug("classpathLocations values:");
ArrayList<String> locations = new ArrayList<String>(
@@ -505,6 +522,7 @@ public class ClassPathExplorer {
}
}
+ URL firstDirectory = null;
Iterator<String> it = rawClasspathEntries.iterator();
while (it.hasNext()) {
String entry = it.next();
@@ -513,13 +531,18 @@ public class ClassPathExplorer {
if (directory.exists() && !directory.isHidden()
&& directory.isDirectory()) {
try {
- return new URL("file://" + directory.getCanonicalPath());
- } catch (MalformedURLException e) {
- // ignore: continue to the next classpath entry
- if (debug) {
- e.printStackTrace();
+ URL directoryUrl = directory.toURI().toURL();
+
+ // Store the first directory encountered.
+ if (firstDirectory == null) {
+ firstDirectory = directoryUrl;
}
- } catch (IOException e) {
+
+ if (widgetsetFileName == null
+ || new File(directory, widgetsetFileName).exists()) {
+ return directoryUrl;
+ }
+ } catch (MalformedURLException e) {
// ignore: continue to the next classpath entry
if (debug) {
e.printStackTrace();
@@ -527,7 +550,8 @@ public class ClassPathExplorer {
}
}
}
- return null;
+
+ return firstDirectory;
}
/**
diff --git a/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java b/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
index f810a63a38..b0d8cdd004 100644
--- a/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
+++ b/server/src/main/java/com/vaadin/server/widgetsetutils/WidgetSetBuilder.java
@@ -61,16 +61,17 @@ public class WidgetSetBuilder {
Map<String, URL> availableWidgetSets = ClassPathExplorer
.getAvailableWidgetSets();
+ String widgetsetFileName = widgetset.replace(".", "/") + ".gwt.xml";
URL sourceUrl = availableWidgetSets.get(widgetset);
if (sourceUrl == null) {
// find first/default source directory
- sourceUrl = ClassPathExplorer.getDefaultSourceDirectory();
+ sourceUrl = ClassPathExplorer
+ .getWidgetsetSourceDirectory(widgetsetFileName);
}
- String widgetsetfilename = sourceUrl.getFile() + "/"
- + widgetset.replace(".", "/") + ".gwt.xml";
+ String wsFullPath = sourceUrl.getFile() + "/" + widgetsetFileName;
- File widgetsetFile = new File(widgetsetfilename);
+ File widgetsetFile = new File(wsFullPath);
if (!widgetsetFile.exists()) {
// create empty gwt module file
File parent = widgetsetFile.getParentFile();
@@ -137,7 +138,7 @@ public class WidgetSetBuilder {
changed = changed || !content.equals(originalContent);
if (changed) {
- commitChanges(widgetsetfilename, content);
+ commitChanges(wsFullPath, content);
}
} else {
System.out
diff --git a/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java
index e0dbcb004b..f517ab0af5 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractOrderedLayout.java
@@ -31,7 +31,6 @@ import com.vaadin.server.Sizeable;
import com.vaadin.shared.Connector;
import com.vaadin.shared.EventId;
import com.vaadin.shared.MouseEventDetails;
-import com.vaadin.shared.ui.AlignmentInfo;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutServerRpc;
import com.vaadin.shared.ui.orderedlayout.AbstractOrderedLayoutState;
@@ -486,22 +485,8 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
Component newChild = designContext.readDesign(childComponent);
addComponent(newChild);
// handle alignment
- int bitMask = 0;
- if (attr.hasKey(":middle")) {
- bitMask += AlignmentInfo.Bits.ALIGNMENT_VERTICAL_CENTER;
- } else if (attr.hasKey(":bottom")) {
- bitMask += AlignmentInfo.Bits.ALIGNMENT_BOTTOM;
- } else {
- bitMask += AlignmentInfo.Bits.ALIGNMENT_TOP;
- }
- if (attr.hasKey(":center")) {
- bitMask += AlignmentInfo.Bits.ALIGNMENT_HORIZONTAL_CENTER;
- } else if (attr.hasKey(":right")) {
- bitMask += AlignmentInfo.Bits.ALIGNMENT_RIGHT;
- } else {
- bitMask += AlignmentInfo.Bits.ALIGNMENT_LEFT;
- }
- setComponentAlignment(newChild, new Alignment(bitMask));
+ setComponentAlignment(newChild,
+ DesignAttributeHandler.readAlignment(attr));
// handle expand ratio
if (attr.hasKey(":expand")) {
String value = attr.get(":expand");
diff --git a/server/src/main/java/com/vaadin/ui/AbstractSelect.java b/server/src/main/java/com/vaadin/ui/AbstractSelect.java
index 9babf7e876..2714e0cbf5 100644
--- a/server/src/main/java/com/vaadin/ui/AbstractSelect.java
+++ b/server/src/main/java/com/vaadin/ui/AbstractSelect.java
@@ -532,13 +532,16 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
} else {
final Object id = itemIdMapper
.get(clientSideSelectedKeys[0]);
- if (!isNullSelectionAllowed() && id == null) {
- markAsDirty();
- } else if (id != null
- && id.equals(getNullSelectionItemId())) {
- setValue(null, true);
+
+ if (id != null) {
+ if (isNullSelectionAllowed()
+ && id.equals(getNullSelectionItemId())) {
+ setValue(null, true);
+ } else {
+ setValue(id, true);
+ }
} else {
- setValue(id, true);
+ markAsDirty();
}
}
}
diff --git a/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java b/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java
index 90b3b56ef6..29179ddca7 100644
--- a/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java
+++ b/server/src/main/java/com/vaadin/ui/DragAndDropWrapper.java
@@ -40,6 +40,7 @@ import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.ui.dd.HorizontalDropLocation;
import com.vaadin.shared.ui.dd.VerticalDropLocation;
import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperConstants;
+import com.vaadin.shared.ui.draganddropwrapper.DragAndDropWrapperServerRpc;
import com.vaadin.ui.declarative.DesignContext;
@SuppressWarnings("serial")
@@ -111,6 +112,14 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
}
+ private final DragAndDropWrapperServerRpc rpc = new DragAndDropWrapperServerRpc() {
+
+ @Override
+ public void poll() {
+ // #19616 RPC to poll the server for changes
+ }
+ };
+
private Map<String, ProxyReceiver> receivers = new HashMap<String, ProxyReceiver>();
public class WrapperTargetDetails extends TargetDetailsImpl {
@@ -197,6 +206,7 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
@Deprecated
public DragAndDropWrapper() {
super();
+ registerRpc(rpc);
}
/**
diff --git a/server/src/main/java/com/vaadin/ui/FormLayout.java b/server/src/main/java/com/vaadin/ui/FormLayout.java
index f6f711d658..c817300e53 100644
--- a/server/src/main/java/com/vaadin/ui/FormLayout.java
+++ b/server/src/main/java/com/vaadin/ui/FormLayout.java
@@ -36,7 +36,7 @@ public class FormLayout extends AbstractOrderedLayout {
public FormLayout() {
super();
setSpacing(true);
- setMargin(new MarginInfo(true, false, true, false));
+ setMargin(new MarginInfo(true, false));
setWidth(100, UNITS_PERCENTAGE);
}
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java
index 4074672675..036fe8b756 100644
--- a/server/src/main/java/com/vaadin/ui/Grid.java
+++ b/server/src/main/java/com/vaadin/ui/Grid.java
@@ -4855,8 +4855,13 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
- * Sets the grid data source.
- *
+ * Sets the grid data source.<p>
+ *
+ * <strong>Note</strong> Grid columns are based on properties and try to detect a correct converter for
+ * the data type. The columns are not reinitialized automatically if the container is changed, and if the same
+ * properties are present after container change, the columns are reused.
+ * Properties with same names, but different data types will lead to unpredictable behaviour.
+ *
* @param container
* The container data source. Cannot be null.
* @throws IllegalArgumentException
diff --git a/server/src/main/java/com/vaadin/ui/GridLayout.java b/server/src/main/java/com/vaadin/ui/GridLayout.java
index 8517962e91..148fd85fff 100644
--- a/server/src/main/java/com/vaadin/ui/GridLayout.java
+++ b/server/src/main/java/com/vaadin/ui/GridLayout.java
@@ -1330,7 +1330,7 @@ public class GridLayout extends AbstractLayout implements
}
}
setRows(Math.max(rows.size(), 1));
-
+ Map<Component, Alignment> alignments = new HashMap<Component, Alignment>();
List<Integer> columnExpandRatios = new ArrayList<Integer>();
for (int row = 0; row < rowElements.size(); ++row) {
Element rowElement = rowElements.get(row);
@@ -1357,7 +1357,10 @@ public class GridLayout extends AbstractLayout implements
Component child = null;
if (col.children().size() > 0) {
- child = designContext.readDesign(col.child(0));
+ Element childElement = col.child(0);
+ child = designContext.readDesign(childElement);
+ alignments.put(child, DesignAttributeHandler
+ .readAlignment(childElement.attributes()));
// TODO: Currently ignoring any extra children.
// Needs Error handling?
} // Else: Empty placeholder. No child component.
@@ -1441,6 +1444,7 @@ public class GridLayout extends AbstractLayout implements
// Add component with area
addComponent(child, j, i, j + colspan, i + rowspan);
+ setComponentAlignment(child, alignments.get(child));
}
}
// Set cursor position explicitly
@@ -1511,16 +1515,8 @@ public class GridLayout extends AbstractLayout implements
ChildComponentData coords = childData.get(child);
Alignment alignment = getComponentAlignment(child);
- if (alignment.isMiddle()) {
- childElement.attr(":middle", true);
- } else if (alignment.isBottom()) {
- childElement.attr(":bottom", true);
- }
- if (alignment.isCenter()) {
- childElement.attr(":center", true);
- } else if (alignment.isRight()) {
- childElement.attr(":right", true);
- }
+ DesignAttributeHandler.writeAlignment(childElement,
+ alignment);
col.appendChild(childElement);
if (coords.row1 != coords.row2) {
diff --git a/server/src/main/java/com/vaadin/ui/Window.java b/server/src/main/java/com/vaadin/ui/Window.java
index b5cd384f53..70399ae566 100644
--- a/server/src/main/java/com/vaadin/ui/Window.java
+++ b/server/src/main/java/com/vaadin/ui/Window.java
@@ -1051,7 +1051,9 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
@Override
public void handleAction(Object sender, Object target) {
- window.close();
+ if (window.isClosable()) {
+ window.close();
+ }
}
public boolean equals(int keyCode, int... modifiers) {
diff --git a/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java b/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java
index cee2ebe381..bbfd90b2cc 100644
--- a/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java
+++ b/server/src/main/java/com/vaadin/ui/declarative/DesignAttributeHandler.java
@@ -37,7 +37,9 @@ import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import com.vaadin.data.util.converter.Converter;
+import com.vaadin.shared.ui.AlignmentInfo;
import com.vaadin.shared.util.SharedUtil;
+import com.vaadin.ui.Alignment;
/**
* Default attribute handler implementation used when parsing designs to
@@ -452,4 +454,55 @@ public class DesignAttributeHandler implements Serializable {
return (methods != null && methods.length > 1) ? methods[1] : null;
}
}
+
+ /**
+ * Read the alignment from the given child component attributes.
+ *
+ * @since 7.6.4
+ * @param attr
+ * the child component attributes
+ * @return the component alignment
+ */
+ public static Alignment readAlignment(Attributes attr) {
+ int bitMask = 0;
+ if (attr.hasKey(":middle")) {
+ bitMask += AlignmentInfo.Bits.ALIGNMENT_VERTICAL_CENTER;
+ } else if (attr.hasKey(":bottom")) {
+ bitMask += AlignmentInfo.Bits.ALIGNMENT_BOTTOM;
+ } else {
+ bitMask += AlignmentInfo.Bits.ALIGNMENT_TOP;
+ }
+ if (attr.hasKey(":center")) {
+ bitMask += AlignmentInfo.Bits.ALIGNMENT_HORIZONTAL_CENTER;
+ } else if (attr.hasKey(":right")) {
+ bitMask += AlignmentInfo.Bits.ALIGNMENT_RIGHT;
+ } else {
+ bitMask += AlignmentInfo.Bits.ALIGNMENT_LEFT;
+ }
+
+ return new Alignment(bitMask);
+ }
+
+ /**
+ * Writes the alignment to the given child element attributes.
+ *
+ * @since 7.6.4
+ * @param childElement
+ * the child element
+ * @param alignment
+ * the component alignment
+ */
+ public static void writeAlignment(Element childElement, Alignment alignment) {
+ if (alignment.isMiddle()) {
+ childElement.attr(":middle", true);
+ } else if (alignment.isBottom()) {
+ childElement.attr(":bottom", true);
+ }
+ if (alignment.isCenter()) {
+ childElement.attr(":center", true);
+ } else if (alignment.isRight()) {
+ childElement.attr(":right", true);
+ }
+ }
+
}
diff --git a/server/src/test/java/com/vaadin/server/UIProviderTest.java b/server/src/test/java/com/vaadin/server/UIProviderTest.java
new file mode 100644
index 0000000000..579a3f1858
--- /dev/null
+++ b/server/src/test/java/com/vaadin/server/UIProviderTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.server;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.annotations.Widgetset;
+
+/**
+ * Tests for {@link UIProvider} class.
+ *
+ * @author Vaadin Ltd
+ */
+public class UIProviderTest {
+
+ @Test
+ public void getAnnotationFor_widgetsetAnnotationForSubclass_annotationFound() {
+ Assert.assertNotNull("Widgetset annotation is not found for subclass",
+ UIProvider.getAnnotationFor(TestClass.class, Widgetset.class));
+ }
+
+ @Test
+ public void getAnnotationFor_themeAnnotationForSubclass_annotationFound() {
+ Assert.assertNotNull("Theme annotation is not found for subclass",
+ UIProvider.getAnnotationFor(TestClass.class, Theme.class));
+ }
+
+ @Test
+ public void getAnnotationFor_themeAnnotationForSubclass_annotationOverridden() {
+ Assert.assertEquals(
+ "Theme annotation is not overridden correctly in subclass",
+ "c", UIProvider.getAnnotationFor(TestClass.class, Theme.class)
+ .value());
+ }
+
+ @Test
+ public void getAnnotationFor_notInheritedAnnotationForSubclass_annotationFound() {
+ Assert.assertNotNull(
+ "TestAnnotation annotation is not found for subclass",
+ UIProvider.getAnnotationFor(TestClass.class,
+ TestAnnotation.class));
+ }
+
+ @Test
+ public void getAnnotationFor_directAnnotationForSubclass_annotationFound() {
+ Assert.assertNotNull(
+ "TestAnnotation1 annotation is not found for subclass",
+ UIProvider.getAnnotationFor(TestClass.class,
+ TestAnnotation1.class));
+ }
+
+ @Test
+ public void getAnnotationFor_annotationInheritedFromInterface_annotationFound() {
+ Assert.assertNotNull(
+ "Theme annotation is not inherited from interface", UIProvider
+ .getAnnotationFor(ClassImplementingInterface.class,
+ Theme.class));
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface TestAnnotation {
+
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ public @interface TestAnnotation1 {
+
+ }
+
+ @Widgetset("a")
+ @Theme("b")
+ @TestAnnotation
+ public static class TestSuperClass {
+
+ }
+
+ @TestAnnotation1
+ @Theme("c")
+ public static class TestClass extends TestSuperClass {
+
+ }
+
+ @Theme("d")
+ public interface InterfaceWithAnnotation {
+ }
+
+ public static class ClassImplementingInterface implements
+ InterfaceWithAnnotation {
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java
index 0e4293481e..e3975e41a8 100644
--- a/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/component/gridlayout/GridLayoutDeclarativeTest.java
@@ -70,7 +70,7 @@ public class GridLayoutDeclarativeTest extends
@Test
public void testOneBigComponentGridLayout() {
- Button b1 = new Button("Button 0,0 -> 1,1");
+ Button b1 = new Button("Button 0,0 -&gt; 1,1");
b1.setCaptionAsHtml(true);
String design = "<vaadin-grid-layout><row>" //
+ "<column colspan=2 rowspan=2>" + writeChild(b1) + "</column>" //
@@ -86,19 +86,19 @@ public class GridLayoutDeclarativeTest extends
@Test
public void testMultipleSpannedComponentsGridLayout() {
GridLayout gl = new GridLayout(5, 5);
- Button b1 = new Button("Button 0,0 -> 0,2");
+ Button b1 = new Button("Button 0,0 -&gt; 0,2");
b1.setCaptionAsHtml(true);
gl.addComponent(b1, 0, 0, 2, 0);
- Button b2 = new Button("Button 0,3 -> 3,3");
+ Button b2 = new Button("Button 0,3 -&gt; 3,3");
b2.setCaptionAsHtml(true);
gl.addComponent(b2, 3, 0, 3, 3);
- Button b3 = new Button("Button 0,4 -> 1,4");
+ Button b3 = new Button("Button 0,4 -&gt; 1,4");
b3.setCaptionAsHtml(true);
gl.addComponent(b3, 4, 0, 4, 1);
- Button b4 = new Button("Button 1,0 -> 3,1");
+ Button b4 = new Button("Button 1,0 -&gt; 3,1");
b4.setCaptionAsHtml(true);
gl.addComponent(b4, 0, 1, 1, 3);
@@ -106,11 +106,11 @@ public class GridLayoutDeclarativeTest extends
b5.setCaptionAsHtml(true);
gl.addComponent(b5, 2, 2);
- Button b6 = new Button("Button 3,4 -> 4,4");
+ Button b6 = new Button("Button 3,4 -&gt; 4,4");
b6.setCaptionAsHtml(true);
gl.addComponent(b6, 4, 3, 4, 4);
- Button b7 = new Button("Button 4,1 -> 4,2");
+ Button b7 = new Button("Button 4,1 -&gt; 4,2");
b7.setCaptionAsHtml(true);
gl.addComponent(b7, 2, 4, 3, 4);
@@ -146,7 +146,7 @@ public class GridLayoutDeclarativeTest extends
@Test
public void testManyExtraGridLayoutSlots() {
GridLayout gl = new GridLayout(5, 5);
- Button b1 = new Button("Button 0,4 -> 4,4");
+ Button b1 = new Button("Button 0,4 -&gt; 4,4");
b1.setCaptionAsHtml(true);
gl.addComponent(b1, 4, 0, 4, 4);
gl.setColumnExpandRatio(2, 2.0f);
@@ -166,7 +166,7 @@ public class GridLayoutDeclarativeTest extends
@Test
public void testManyEmptyColumnsWithOneExpand() {
GridLayout gl = new GridLayout(5, 5);
- Button b1 = new Button("Button 0,4 -> 4,4");
+ Button b1 = new Button("Button 0,4 -&gt; 4,4");
b1.setCaptionAsHtml(true);
gl.addComponent(b1, 0, 0, 0, 4);
gl.setColumnExpandRatio(4, 2.0f);
@@ -202,13 +202,29 @@ public class GridLayoutDeclarativeTest extends
GridLayout result = super.testRead(design, expected);
for (int row = 0; row < expected.getRows(); ++row) {
- Assert.assertTrue(Math.abs(expected.getRowExpandRatio(row)
- - result.getRowExpandRatio(row)) < 0.00001);
+ Assert.assertEquals(expected.getRowExpandRatio(row),
+ result.getRowExpandRatio(row), 0.00001);
}
for (int col = 0; col < expected.getColumns(); ++col) {
- Assert.assertTrue(Math.abs(expected.getColumnExpandRatio(col)
- - result.getColumnExpandRatio(col)) < 0.00001);
+ Assert.assertEquals(expected.getColumnExpandRatio(col),
+ result.getColumnExpandRatio(col), 0.00001);
}
+ for (int row = 0; row < expected.getRows(); ++row) {
+ for (int col = 0; col < expected.getColumns(); ++col) {
+ Component eC = expected.getComponent(col, row);
+ Component rC = result.getComponent(col, row);
+
+ assertEquals(eC, rC);
+ if (eC == null) {
+ continue;
+ }
+
+ Assert.assertEquals(expected.getComponentAlignment(eC),
+ result.getComponentAlignment(rC));
+
+ }
+ }
+
return result;
}