diff options
Diffstat (limited to 'server')
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 |