summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/data/fieldgroup/FieldGroup.java2
-rw-r--r--server/src/com/vaadin/server/AbstractCommunicationManager.java8
-rw-r--r--server/src/com/vaadin/server/JsonCodec.java4
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java12
-rw-r--r--server/src/com/vaadin/ui/ComboBox.java21
-rw-r--r--server/src/com/vaadin/ui/ConnectorTracker.java54
-rw-r--r--server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java6
-rw-r--r--server/src/com/vaadin/util/ReflectTools.java50
-rw-r--r--server/tests/src/com/vaadin/server/JSONSerializerTest.java27
-rw-r--r--server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java9
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java53
-rw-r--r--server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java65
-rw-r--r--server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java26
13 files changed, 302 insertions, 35 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
index 5a69cad62e..51cd3126cb 100644
--- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
@@ -830,7 +830,7 @@ public class FieldGroup implements Serializable {
try {
// Get the field from the object
field = (Field<?>) ReflectTools.getJavaFieldValue(
- objectWithMemberFields, memberField);
+ objectWithMemberFields, memberField, Field.class);
} catch (Exception e) {
// If we cannot determine the value, just skip the field and try
// the next one
diff --git a/server/src/com/vaadin/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java
index af9118547f..0e279d140b 100644
--- a/server/src/com/vaadin/server/AbstractCommunicationManager.java
+++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java
@@ -2418,11 +2418,11 @@ public abstract class AbstractCommunicationManager implements Serializable {
reinitUI(retainedUI, request);
return retainedUI;
} else {
- getLogger()
- .info("Not using retained UI in " + windowName
+ getLogger().info(
+ "Not using retained UI in " + windowName
+ " because retained UI was of type "
- + retainedUIId.getClass() + " but "
- + uiClass + " is expected for the request.");
+ + retainedUI.getClass() + " but " + uiClass
+ + " is expected for the request.");
}
}
}
diff --git a/server/src/com/vaadin/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java
index 89ef060ef0..f7cbe79fdb 100644
--- a/server/src/com/vaadin/server/JsonCodec.java
+++ b/server/src/com/vaadin/server/JsonCodec.java
@@ -185,6 +185,7 @@ public class JsonCodec implements Serializable {
registerType(HashMap.class, JsonConstants.VTYPE_MAP);
registerType(List.class, JsonConstants.VTYPE_LIST);
registerType(Set.class, JsonConstants.VTYPE_SET);
+ registerType(Void.class, JsonConstants.VTYPE_NULL);
}
private static void registerType(Class<?> type, String transportType) {
@@ -325,6 +326,9 @@ public class JsonCodec implements Serializable {
if (encodedJsonValue == JSONObject.NULL) {
return null;
+ } else if (targetType == Void.class) {
+ throw new JSONException(
+ "Something other than null was encoded for a null type");
}
// UidlValue
diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java
index 63cf19283f..49c3d75385 100644
--- a/server/src/com/vaadin/ui/AbstractComponent.java
+++ b/server/src/com/vaadin/ui/AbstractComponent.java
@@ -593,11 +593,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
* @return CSS height
*/
private String getCSSHeight() {
- if (getHeightUnits() == Unit.PIXELS) {
- return ((int) getHeight()) + getHeightUnits().getSymbol();
- } else {
- return getHeight() + getHeightUnits().getSymbol();
- }
+ return getHeight() + getHeightUnits().getSymbol();
}
/**
@@ -606,11 +602,7 @@ public abstract class AbstractComponent extends AbstractClientConnector
* @return CSS width
*/
private String getCSSWidth() {
- if (getWidthUnits() == Unit.PIXELS) {
- return ((int) getWidth()) + getWidthUnits().getSymbol();
- } else {
- return getWidth() + getWidthUnits().getSymbol();
- }
+ return getWidth() + getWidthUnits().getSymbol();
}
/**
diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java
index c35ecdb21f..3bf6ee992b 100644
--- a/server/src/com/vaadin/ui/ComboBox.java
+++ b/server/src/com/vaadin/ui/ComboBox.java
@@ -792,6 +792,27 @@ public class ComboBox extends AbstractSelect implements
}
/**
+ * Returns the page length of the suggestion popup.
+ *
+ * @return the pageLength
+ */
+ public int getPageLength() {
+ return pageLength;
+ }
+
+ /**
+ * Sets the page length for the suggestion popup. Setting the page length to
+ * 0 will disable suggestion popup paging (all items visible).
+ *
+ * @param pageLength
+ * the pageLength to set
+ */
+ public void setPageLength(int pageLength) {
+ this.pageLength = pageLength;
+ markAsDirty();
+ }
+
+ /**
* Sets whether to scroll the selected item visible (directly open the page
* on which it is) when opening the combo box popup or not. Only applies to
* single select mode.
diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java
index 91f9ac451c..d5ee43f0a0 100644
--- a/server/src/com/vaadin/ui/ConnectorTracker.java
+++ b/server/src/com/vaadin/ui/ConnectorTracker.java
@@ -62,6 +62,13 @@ public class ConnectorTracker implements Serializable {
private Set<ClientConnector> dirtyConnectors = new HashSet<ClientConnector>();
private Set<ClientConnector> uninitializedConnectors = new HashSet<ClientConnector>();
+ /**
+ * Connectors that have been unregistered and should be cleaned up the next
+ * time {@link #cleanConnectorMap()} is invoked unless they have been
+ * registered again.
+ */
+ private final Set<ClientConnector> unregisteredConnectors = new HashSet<ClientConnector>();
+
private boolean writingResponse = false;
private UI uI;
@@ -105,6 +112,8 @@ public class ConnectorTracker implements Serializable {
* The connector to register.
*/
public void registerConnector(ClientConnector connector) {
+ boolean wasUnregistered = unregisteredConnectors.remove(connector);
+
String connectorId = connector.getConnectorId();
ClientConnector previouslyRegistered = connectorIdToConnector
.get(connectorId);
@@ -117,13 +126,13 @@ public class ConnectorTracker implements Serializable {
} else if (previouslyRegistered != connector) {
throw new RuntimeException("A connector with id " + connectorId
+ " is already registered!");
- } else {
+ } else if (!wasUnregistered) {
getLogger().warning(
"An already registered connector was registered again: "
+ connector.getClass().getSimpleName() + " ("
+ connectorId + ")");
}
-
+ dirtyConnectors.add(connector);
}
/**
@@ -152,14 +161,17 @@ public class ConnectorTracker implements Serializable {
+ " is not the one that was registered for that id");
}
- getLogger().fine(
- "Unregistered " + connector.getClass().getSimpleName() + " ("
- + connectorId + ")");
-
- removeFromGlobalResourceHandler(connector);
- connectorIdToConnector.remove(connectorId);
- uninitializedConnectors.remove(connector);
- diffStates.remove(connector);
+ dirtyConnectors.remove(connector);
+ if (unregisteredConnectors.add(connector)) {
+ getLogger().fine(
+ "Unregistered " + connector.getClass().getSimpleName()
+ + " (" + connectorId + ")");
+ } else {
+ getLogger().warning(
+ "Unregistered " + connector.getClass().getSimpleName()
+ + " (" + connectorId
+ + ") that was already unregistered.");
+ }
}
private void removeFromGlobalResourceHandler(ClientConnector connector) {
@@ -221,7 +233,12 @@ public class ConnectorTracker implements Serializable {
* given id
*/
public ClientConnector getConnector(String connectorId) {
- return connectorIdToConnector.get(connectorId);
+ ClientConnector connector = connectorIdToConnector.get(connectorId);
+ // Ignore connectors that have been unregistered but not yet cleaned up
+ if (unregisteredConnectors.contains(connector)) {
+ return null;
+ }
+ return connector;
}
/**
@@ -229,6 +246,18 @@ public class ConnectorTracker implements Serializable {
* to the application. This should only be called by the framework.
*/
public void cleanConnectorMap() {
+ // Remove connectors that have been unregistered
+ for (ClientConnector connector : unregisteredConnectors) {
+ ClientConnector removedConnector = connectorIdToConnector
+ .remove(connector.getConnectorId());
+ assert removedConnector == connector;
+
+ removeFromGlobalResourceHandler(connector);
+ uninitializedConnectors.remove(connector);
+ diffStates.remove(connector);
+ }
+ unregisteredConnectors.clear();
+
// remove detached components from paintableIdMap so they
// can be GC'ed
Iterator<String> iterator = connectorIdToConnector.keySet().iterator();
@@ -423,10 +452,12 @@ public class ConnectorTracker implements Serializable {
}
public JSONObject getDiffState(ClientConnector connector) {
+ assert getConnector(connector.getConnectorId()) == connector;
return diffStates.get(connector);
}
public void setDiffState(ClientConnector connector, JSONObject diffState) {
+ assert getConnector(connector.getConnectorId()) == connector;
diffStates.put(connector, diffState);
}
@@ -537,6 +568,7 @@ public class ConnectorTracker implements Serializable {
*/
public void addStreamVariable(String connectorId, String variableName,
StreamVariable variable) {
+ assert getConnector(connectorId) != null;
if (pidToNameToStreamVariable == null) {
pidToNameToStreamVariable = new HashMap<String, Map<String, StreamVariable>>();
}
diff --git a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java
index ddd61f37b2..1bff71f0f7 100644
--- a/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java
+++ b/server/src/com/vaadin/ui/components/colorpicker/ColorPickerGradient.java
@@ -52,9 +52,6 @@ public class ColorPickerGradient extends AbstractComponent implements
/** The y-coordinate. */
private int y = 0;
- /** The background color. */
- private Color backgroundColor;
-
/**
* Instantiates a new color picker gradient.
*
@@ -65,7 +62,7 @@ public class ColorPickerGradient extends AbstractComponent implements
*/
public ColorPickerGradient(String id, Coordinates2Color converter) {
registerRpc(rpc);
- getState().id = id;
+ addStyleName(id);
// width and height must be set here instead of in theme, otherwise
// coordinate calculations fail
getState().width = "220px";
@@ -103,7 +100,6 @@ public class ColorPickerGradient extends AbstractComponent implements
* the new background color
*/
public void setBackgroundColor(Color color) {
- backgroundColor = color;
getState().bgColor = color.getCSS();
}
diff --git a/server/src/com/vaadin/util/ReflectTools.java b/server/src/com/vaadin/util/ReflectTools.java
index 285d876e1c..2b0b4ce29a 100644
--- a/server/src/com/vaadin/util/ReflectTools.java
+++ b/server/src/com/vaadin/util/ReflectTools.java
@@ -94,6 +94,56 @@ public class ReflectTools {
}
/**
+ * Returns the value of the java field that is assignable to the property
+ * type.
+ * <p>
+ * Uses getter if a getter for the correct return type is present, otherwise
+ * tries to access even private fields directly. If the java field is not
+ * assignable to the property type throws an IllegalArgumentException.
+ *
+ * @param object
+ * The object containing the field
+ * @param field
+ * The field we want to get the value for
+ * @param propertyType
+ * The type the field must be assignable to
+ * @return The value of the field in the object
+ * @throws InvocationTargetException
+ * If the value could not be retrieved
+ * @throws IllegalAccessException
+ * If the value could not be retrieved
+ * @throws IllegalArgumentException
+ * If the value could not be retrieved
+ */
+ public static Object getJavaFieldValue(Object object,
+ java.lang.reflect.Field field, Class<?> propertyType)
+ throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException {
+ PropertyDescriptor pd;
+ try {
+ pd = new PropertyDescriptor(field.getName(), object.getClass());
+ if (propertyType.isAssignableFrom(pd.getPropertyType())) {
+ Method getter = pd.getReadMethod();
+ if (getter != null) {
+ return getter.invoke(object, (Object[]) null);
+ }
+ }
+ } catch (IntrospectionException e1) {
+ // Ignore this and try to get directly using the field
+ }
+ // If the field's type cannot be casted in to the requested type
+ if (!propertyType.isAssignableFrom(field.getType())) {
+ throw new IllegalArgumentException();
+ }
+ // Try to get the value or throw an exception
+ if (!field.isAccessible()) {
+ // Try to gain access even if field is private
+ field.setAccessible(true);
+ }
+ return field.get(object);
+ }
+
+ /**
* Sets the value of a java field.
* <p>
* Uses setter if present, otherwise tries to access even private fields
diff --git a/server/tests/src/com/vaadin/server/JSONSerializerTest.java b/server/tests/src/com/vaadin/server/JSONSerializerTest.java
index fc02c13781..981f74a2a4 100644
--- a/server/tests/src/com/vaadin/server/JSONSerializerTest.java
+++ b/server/tests/src/com/vaadin/server/JSONSerializerTest.java
@@ -16,13 +16,20 @@ package com.vaadin.server;
* the License.
*/
import java.lang.reflect.Type;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import com.vaadin.server.JsonCodec.BeanProperty;
+import com.vaadin.shared.communication.UidlValue;
import com.vaadin.shared.ui.splitpanel.AbstractSplitPanelState;
/**
@@ -72,6 +79,26 @@ public class JSONSerializerTest extends TestCase {
ensureDecodedCorrectly(stateToStringMap, encodedMap, mapType);
}
+ public void testNullLegacyValue() throws JSONException {
+ JSONArray inputArray = new JSONArray(
+ Arrays.asList("n", JSONObject.NULL));
+ UidlValue decodedObject = (UidlValue) JsonCodec.decodeInternalType(
+ UidlValue.class, true, inputArray, null);
+ assertNull(decodedObject.getValue());
+ }
+
+ public void testNullTypeOtherValue() {
+ try {
+ JSONArray inputArray = new JSONArray(Arrays.asList("n", "a"));
+ UidlValue decodedObject = (UidlValue) JsonCodec.decodeInternalType(
+ UidlValue.class, true, inputArray, null);
+
+ throw new AssertionFailedError("No JSONException thrown");
+ } catch (JSONException e) {
+ // Should throw exception
+ }
+ }
+
private void ensureDecodedCorrectly(Object original, Object encoded,
Type type) throws Exception {
Object serverSideDecoded = JsonCodec.decodeInternalOrCustomType(type,
diff --git a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
index f24638e6a7..250fa3f771 100644
--- a/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
+++ b/server/tests/src/com/vaadin/tests/server/TestStreamVariableMapping.java
@@ -50,16 +50,17 @@ public class TestStreamVariableMapping extends TestCase {
public void testAddStreamVariable() {
String targetUrl = cm.getStreamVariableTargetUrl(owner, variableName,
streamVariable);
- assertTrue(targetUrl.startsWith("app://APP/UPLOAD/-1/1/myName/"));
+ assertTrue(targetUrl.startsWith("app://APP/UPLOAD/-1/"
+ + owner.getConnectorId() + "/myName/"));
- ConnectorTracker tracker = UI.getCurrent().getConnectorTracker();
+ ConnectorTracker tracker = owner.getUI().getConnectorTracker();
StreamVariable streamVariable2 = tracker.getStreamVariable(
owner.getConnectorId(), variableName);
assertSame(streamVariable, streamVariable2);
}
- public void testRemoverVariable() {
- ConnectorTracker tracker = UI.getCurrent().getConnectorTracker();
+ public void testRemoveVariable() {
+ ConnectorTracker tracker = owner.getUI().getConnectorTracker();
cm.getStreamVariableTargetUrl(owner, variableName, streamVariable);
assertNotNull(tracker.getStreamVariable(owner.getConnectorId(),
variableName));
diff --git a/server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java
new file mode 100644
index 0000000000..033f1458e8
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescription.java
@@ -0,0 +1,53 @@
+package com.vaadin.tests.server.component.fieldgroup;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.vaadin.data.fieldgroup.FieldGroup;
+import com.vaadin.data.fieldgroup.PropertyId;
+import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.data.util.PropertysetItem;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.TextField;
+
+public class FieldNamedDescription {
+
+ @Test
+ public void bindReadOnlyPropertyToFieldGroup() {
+ // Create an item
+ PropertysetItem item = new PropertysetItem();
+ item.addItemProperty("name", new ObjectProperty<String>("Zaphod"));
+ item.addItemProperty("description", new ObjectProperty<String>(
+ "This is a description"));
+
+ // Define a form as a class that extends some layout
+ class MyForm extends FormLayout {
+ // Member that will bind to the "name" property
+ TextField name = new TextField("Name");
+
+ // This member will not bind to the desctiptionProperty as the name
+ // description conflicts with something in the binding process
+ @PropertyId("description")
+ TextField description = new TextField("Description");
+
+ public MyForm() {
+
+ // Add the fields
+ addComponent(name);
+ addComponent(description);
+ }
+ }
+
+ // Create one
+ MyForm form = new MyForm();
+
+ // Now create a binder that can also creates the fields
+ // using the default field factory
+ FieldGroup binder = new FieldGroup(item);
+ binder.bindMemberFields(form);
+
+ assertTrue(form.description.getValue().equals("This is a description"));
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java b/server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java
new file mode 100644
index 0000000000..78be9b04fb
--- /dev/null
+++ b/server/tests/src/com/vaadin/util/ReflectToolsGetFieldValueByType.java
@@ -0,0 +1,65 @@
+package com.vaadin.util;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Test;
+
+public class ReflectToolsGetFieldValueByType {
+ @Test
+ public void getFieldValue() {
+ class MyClass {
+ public Integer getField() {
+ return 1;
+ }
+
+ public void setField(Integer i) {
+ }
+
+ }
+ class MySubClass extends MyClass {
+ public String field = "Hello";
+ }
+
+ MySubClass myInstance = new MySubClass();
+
+ java.lang.reflect.Field memberField;
+ Object fieldValue = new Boolean(false);
+ try {
+ memberField = myInstance.getClass().getField("field");
+ // Should get a String value. Without the third parameter (calling
+ // ReflectTools.getJavaFieldValue(Object object, Field field)) would
+ // get an Integer value
+ fieldValue = ReflectTools.getJavaFieldValue(myInstance,
+ memberField, String.class);
+ } catch (Exception e) {
+ }
+ assertTrue(fieldValue instanceof String);
+
+ }
+
+ @Test
+ public void getFieldValueViaGetter() {
+ class MyClass {
+ public Integer field = 1;
+ }
+ class MySubClass extends MyClass {
+ public String field = "Hello";
+ }
+
+ MySubClass myInstance = new MySubClass();
+
+ java.lang.reflect.Field memberField;
+ try {
+ memberField = myInstance.getClass().getField("field");
+ // Should throw an IllegalArgument exception as the mySubClass class
+ // doesn't have an Integer field.
+ ReflectTools.getJavaFieldValue(myInstance,
+ memberField, Integer.class);
+ fail("Previous method call should have thrown an exception");
+ } catch (Exception e) {
+ }
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java b/server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java
new file mode 100644
index 0000000000..df192c51f2
--- /dev/null
+++ b/server/tests/src/com/vaadin/util/ReflectToolsGetPrimitiveFieldValue.java
@@ -0,0 +1,26 @@
+package com.vaadin.util;
+
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+public class ReflectToolsGetPrimitiveFieldValue {
+ @Test
+ public void getFieldValueViaGetter() {
+ class MyClass {
+ public int field = 1;
+ }
+
+ MyClass myInstance = new MyClass();
+
+ java.lang.reflect.Field memberField;
+ Object fieldValue = new Boolean(false);
+ try {
+ memberField = myInstance.getClass().getField("field");
+ fieldValue = ReflectTools.getJavaFieldValue(myInstance,
+ memberField);
+ } catch (Exception e) {
+ }
+ assertFalse(fieldValue instanceof Boolean);
+ }
+} \ No newline at end of file