aboutsummaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2014-12-12 10:32:29 +0200
committerArtur Signell <artur@vaadin.com>2014-12-12 10:32:29 +0200
commit6fdc3320fec5801a73f51d3e3a3584d23d942c6c (patch)
treebca21a044acc56530bb403eb1cd3652c01c71928 /server/src
parentb3e6edc9634f444ccece00e200cb51eee7994d75 (diff)
parent10fa4e4236ed049ef6eac337d23701bc381763ce (diff)
downloadvaadin-framework-6fdc3320fec5801a73f51d3e3a3584d23d942c6c.tar.gz
vaadin-framework-6fdc3320fec5801a73f51d3e3a3584d23d942c6c.zip
Merge remote-tracking branch 'origin/master' into grid
Conflicts: server/tests/src/com/vaadin/data/util/BeanItemContainerTest.java Change-Id: I04938bd8c5b4f01c3ca801c9f7adbb20d279523c
Diffstat (limited to 'server/src')
-rw-r--r--server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java14
-rw-r--r--server/src/com/vaadin/data/fieldgroup/FieldGroup.java89
-rw-r--r--server/src/com/vaadin/data/util/AbstractBeanContainer.java10
-rw-r--r--server/src/com/vaadin/data/util/BeanItem.java25
-rw-r--r--server/src/com/vaadin/data/util/MethodProperty.java10
-rw-r--r--server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java1
-rw-r--r--server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java7
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java11
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToByteConverter.java2
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToEnumConverter.java20
-rw-r--r--server/src/com/vaadin/data/util/converter/StringToShortConverter.java2
-rw-r--r--server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java27
-rw-r--r--server/src/com/vaadin/server/BootstrapHandler.java2
-rw-r--r--server/src/com/vaadin/server/FileResource.java3
-rw-r--r--server/src/com/vaadin/server/VaadinServlet.java28
-rw-r--r--server/src/com/vaadin/server/communication/UIInitHandler.java21
-rw-r--r--server/src/com/vaadin/ui/AbsoluteLayout.java2
-rw-r--r--server/src/com/vaadin/ui/AbstractComponentContainer.java2
-rw-r--r--server/src/com/vaadin/ui/AbstractField.java19
-rw-r--r--server/src/com/vaadin/ui/AbstractSelect.java2
-rw-r--r--server/src/com/vaadin/ui/AbstractSplitPanel.java2
-rw-r--r--server/src/com/vaadin/ui/AbstractTextField.java2
-rw-r--r--server/src/com/vaadin/ui/CssLayout.java4
-rw-r--r--server/src/com/vaadin/ui/CustomLayout.java4
-rw-r--r--server/src/com/vaadin/ui/DateField.java14
-rw-r--r--server/src/com/vaadin/ui/Field.java22
-rw-r--r--server/src/com/vaadin/ui/Form.java9
-rw-r--r--server/src/com/vaadin/ui/GridLayout.java3
-rw-r--r--server/src/com/vaadin/ui/RichTextArea.java2
-rw-r--r--server/src/com/vaadin/ui/TabSheet.java11
-rw-r--r--server/src/com/vaadin/ui/TextField.java12
-rw-r--r--server/src/com/vaadin/ui/UI.java8
-rw-r--r--server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java74
33 files changed, 271 insertions, 193 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java
index e5d53b759d..257a958f3a 100644
--- a/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/BeanFieldGroup.java
@@ -125,21 +125,29 @@ public class BeanFieldGroup<T> extends FieldGroup {
* Helper method for setting the data source directly using a bean. This
* method wraps the bean in a {@link BeanItem} and calls
* {@link #setItemDataSource(Item)}.
+ * <p>
+ * For null values, a null item is passed to
+ * {@link #setItemDataSource(Item)} to be properly clear fields.
*
* @param bean
* The bean to use as data source.
*/
public void setItemDataSource(T bean) {
- setItemDataSource(new BeanItem(bean));
+ if (bean == null) {
+ setItemDataSource((Item) null);
+ } else {
+ setItemDataSource(new BeanItem<T>(bean, beanType));
+ }
}
@Override
public void setItemDataSource(Item item) {
- if (!(item instanceof BeanItem)) {
+ if (item == null || (item instanceof BeanItem)) {
+ super.setItemDataSource(item);
+ } else {
throw new RuntimeException(getClass().getSimpleName()
+ " only supports BeanItems as item data source");
}
- super.setItemDataSource(item);
}
@Override
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
index 5a4e877554..c89b94ace9 100644
--- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
+++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java
@@ -255,6 +255,9 @@ public class FieldGroup implements Serializable {
fieldToPropertyId.put(field, propertyId);
propertyIdToField.put(propertyId, field);
if (itemDataSource == null) {
+ // Clear any possible existing binding to clear the field
+ field.setPropertyDataSource(null);
+ field.clear();
// Will be bound when data source is set
return;
}
@@ -452,6 +455,56 @@ public class FieldGroup implements Serializable {
// Not using buffered mode, nothing to do
return;
}
+
+ startTransactions();
+
+ try {
+ firePreCommitEvent();
+
+ List<InvalidValueException> invalidValueExceptions = commitFields();
+
+ if (invalidValueExceptions.isEmpty()) {
+ firePostCommitEvent();
+ commitTransactions();
+ } else {
+ throwInvalidValueException(invalidValueExceptions);
+ }
+ } catch (Exception e) {
+ rollbackTransactions();
+
+ throw new CommitException("Commit failed", e);
+ }
+
+ }
+
+ private List<InvalidValueException> commitFields() {
+ List<InvalidValueException> invalidValueExceptions = new ArrayList<InvalidValueException>();
+
+ for (Field<?> f : fieldToPropertyId.keySet()) {
+ try {
+ f.commit();
+ } catch (InvalidValueException e) {
+ invalidValueExceptions.add(e);
+ }
+ }
+
+ return invalidValueExceptions;
+ }
+
+ private void throwInvalidValueException(
+ List<InvalidValueException> invalidValueExceptions) {
+ if (invalidValueExceptions.size() == 1) {
+ throw invalidValueExceptions.get(0);
+ } else {
+ InvalidValueException[] causes = invalidValueExceptions
+ .toArray(new InvalidValueException[invalidValueExceptions
+ .size()]);
+
+ throw new InvalidValueException(null, causes);
+ }
+ }
+
+ private void startTransactions() throws CommitException {
for (Field<?> f : fieldToPropertyId.keySet()) {
Property.Transactional<?> property = (Property.Transactional<?>) f
.getPropertyDataSource();
@@ -462,33 +515,23 @@ public class FieldGroup implements Serializable {
}
property.startTransaction();
}
- try {
- firePreCommitEvent();
- // Commit the field values to the properties
- for (Field<?> f : fieldToPropertyId.keySet()) {
- f.commit();
- }
- firePostCommitEvent();
+ }
- // Commit the properties
- for (Field<?> f : fieldToPropertyId.keySet()) {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .commit();
- }
+ private void commitTransactions() {
+ for (Field<?> f : fieldToPropertyId.keySet()) {
+ ((Property.Transactional<?>) f.getPropertyDataSource()).commit();
+ }
+ }
- } catch (Exception e) {
- for (Field<?> f : fieldToPropertyId.keySet()) {
- try {
- ((Property.Transactional<?>) f.getPropertyDataSource())
- .rollback();
- } catch (Exception rollbackException) {
- // FIXME: What to do ?
- }
+ private void rollbackTransactions() {
+ for (Field<?> f : fieldToPropertyId.keySet()) {
+ try {
+ ((Property.Transactional<?>) f.getPropertyDataSource())
+ .rollback();
+ } catch (Exception rollbackException) {
+ // FIXME: What to do ?
}
-
- throw new CommitException("Commit failed", e);
}
-
}
/**
diff --git a/server/src/com/vaadin/data/util/AbstractBeanContainer.java b/server/src/com/vaadin/data/util/AbstractBeanContainer.java
index 0559585e14..6dcfbb2b84 100644
--- a/server/src/com/vaadin/data/util/AbstractBeanContainer.java
+++ b/server/src/com/vaadin/data/util/AbstractBeanContainer.java
@@ -152,7 +152,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends
* A description of the properties found in beans of type {@link #type}.
* Determines the property ids that are present in the container.
*/
- private LinkedHashMap<String, VaadinPropertyDescriptor<BEANTYPE>> model;
+ private final LinkedHashMap<String, VaadinPropertyDescriptor<BEANTYPE>> model;
/**
* Constructs a {@code AbstractBeanContainer} for beans of the given type.
@@ -178,7 +178,11 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends
*/
@Override
public Class<?> getType(Object propertyId) {
- return model.get(propertyId).getPropertyType();
+ VaadinPropertyDescriptor<BEANTYPE> descriptor = model.get(propertyId);
+ if (descriptor == null) {
+ return null;
+ }
+ return descriptor.getPropertyType();
}
/**
@@ -888,7 +892,7 @@ public abstract class AbstractBeanContainer<IDTYPE, BEANTYPE> extends
model.put(qualifiedPropertyId, pd);
model.remove(propertyId);
for (BeanItem<BEANTYPE> item : itemIdToItem.values()) {
- item.addItemProperty(propertyId,
+ item.addItemProperty(qualifiedPropertyId,
pd.createProperty(item.getBean()));
item.removeItemProperty(propertyId);
}
diff --git a/server/src/com/vaadin/data/util/BeanItem.java b/server/src/com/vaadin/data/util/BeanItem.java
index 12d9b23d0a..64f30261c2 100644
--- a/server/src/com/vaadin/data/util/BeanItem.java
+++ b/server/src/com/vaadin/data/util/BeanItem.java
@@ -62,7 +62,30 @@ public class BeanItem<BT> extends PropertysetItem {
*
*/
public BeanItem(BT bean) {
- this(bean, getPropertyDescriptors((Class<BT>) bean.getClass()));
+ this(bean, (Class<BT>) bean.getClass());
+ }
+
+ /**
+ * <p>
+ * Creates a new instance of <code>BeanItem</code> and adds all properties
+ * of a Java Bean to it. The properties are identified by their respective
+ * bean names.
+ * </p>
+ *
+ * <p>
+ * Note : This version only supports introspectable bean properties and
+ * their getter and setter methods. Stand-alone <code>is</code> and
+ * <code>are</code> methods are not supported.
+ * </p>
+ *
+ * @param bean
+ * the Java Bean to copy properties from.
+ * @param beanClass
+ * class of the {@code bean}
+ *
+ */
+ public BeanItem(BT bean, Class<BT> beanClass) {
+ this(bean, getPropertyDescriptors(beanClass));
}
/**
diff --git a/server/src/com/vaadin/data/util/MethodProperty.java b/server/src/com/vaadin/data/util/MethodProperty.java
index 5e6b731571..853f68b711 100644
--- a/server/src/com/vaadin/data/util/MethodProperty.java
+++ b/server/src/com/vaadin/data/util/MethodProperty.java
@@ -132,7 +132,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
setArguments(getArgs, setArgs, setArgumentIndex);
String name = (String) in.readObject();
Class<?>[] paramTypes = SerializerHelper.readClassArray(in);
- if (name != null) {
+ if (instance != null && name != null) {
setMethod = instance.getClass().getMethod(name, paramTypes);
} else {
setMethod = null;
@@ -140,7 +140,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
name = (String) in.readObject();
paramTypes = SerializerHelper.readClassArray(in);
- if (name != null) {
+ if (instance != null && name != null) {
getMethod = instance.getClass().getMethod(name, paramTypes);
} else {
getMethod = null;
@@ -589,7 +589,11 @@ public class MethodProperty<T> extends AbstractProperty<T> {
@Override
public T getValue() {
try {
- return (T) getMethod.invoke(instance, getArgs);
+ if (instance == null) {
+ return null;
+ } else {
+ return (T) getMethod.invoke(instance, getArgs);
+ }
} catch (final Throwable e) {
throw new MethodException(this, e);
}
diff --git a/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java b/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java
index 9054f258c7..81f1a85f89 100644
--- a/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java
+++ b/server/src/com/vaadin/data/util/converter/AbstractStringToNumberConverter.java
@@ -88,6 +88,7 @@ public abstract class AbstractStringToNumberConverter<T> implements
// Convert "" to null
return null;
}
+
return parsedValue;
}
diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
index 26613c5d02..3a1f1a4252 100644
--- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
+++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java
@@ -17,6 +17,7 @@
package com.vaadin.data.util.converter;
import java.math.BigDecimal;
+import java.math.BigInteger;
import java.util.Date;
import java.util.logging.Logger;
@@ -112,6 +113,12 @@ public class DefaultConverterFactory implements ConverterFactory {
return new StringToDateConverter();
} else if (Enum.class.isAssignableFrom(sourceType)) {
return new StringToEnumConverter();
+ } else if (BigInteger.class.isAssignableFrom(sourceType)) {
+ return new StringToBigIntegerConverter();
+ } else if (Short.class.isAssignableFrom(sourceType)) {
+ return new StringToShortConverter();
+ } else if (Byte.class.isAssignableFrom(sourceType)) {
+ return new StringToByteConverter();
} else {
return null;
}
diff --git a/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java b/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java
index 1e830c1fd2..d176ac2e0d 100644
--- a/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java
+++ b/server/src/com/vaadin/data/util/converter/StringToBigIntegerConverter.java
@@ -15,6 +15,7 @@
*/
package com.vaadin.data.util.converter;
+import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
@@ -32,7 +33,7 @@ import java.util.Locale;
* </p>
*
* @author Vaadin Ltd
- * @since 7.3.1
+ * @since
*/
public class StringToBigIntegerConverter extends
AbstractStringToNumberConverter<BigInteger> {
@@ -41,7 +42,7 @@ public class StringToBigIntegerConverter extends
protected NumberFormat getFormat(Locale locale) {
NumberFormat numberFormat = super.getFormat(locale);
if (numberFormat instanceof DecimalFormat) {
- ((DecimalFormat) numberFormat).setParseIntegerOnly(true);
+ ((DecimalFormat) numberFormat).setParseBigDecimal(true);
}
return numberFormat;
@@ -51,7 +52,11 @@ public class StringToBigIntegerConverter extends
public BigInteger convertToModel(String value,
Class<? extends BigInteger> targetType, Locale locale)
throws com.vaadin.data.util.converter.Converter.ConversionException {
- return (BigInteger) convertToNumber(value, BigInteger.class, locale);
+
+ BigDecimal bigDecimalValue = (BigDecimal) convertToNumber(value,
+ BigDecimal.class, locale);
+
+ return (bigDecimalValue != null) ? bigDecimalValue.toBigInteger() : null;
}
@Override
diff --git a/server/src/com/vaadin/data/util/converter/StringToByteConverter.java b/server/src/com/vaadin/data/util/converter/StringToByteConverter.java
index b14182dc3f..26f52d108a 100644
--- a/server/src/com/vaadin/data/util/converter/StringToByteConverter.java
+++ b/server/src/com/vaadin/data/util/converter/StringToByteConverter.java
@@ -28,7 +28,7 @@ import java.util.Locale;
* </p>
*
* @author Vaadin Ltd
- * @since 7.3.1
+ * @since
*/
public class StringToByteConverter extends
AbstractStringToNumberConverter<Byte> {
diff --git a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java
index a1328d831c..29bf8fc400 100644
--- a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java
+++ b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java
@@ -34,7 +34,7 @@ public class StringToEnumConverter implements Converter<String, Enum> {
@Override
public Enum convertToModel(String value, Class<? extends Enum> targetType,
Locale locale) throws ConversionException {
- if (value == null) {
+ if (value == null || value.trim().equals("")) {
return null;
}
if (locale == null) {
@@ -46,19 +46,21 @@ public class StringToEnumConverter implements Converter<String, Enum> {
String result = value.replace(" ", "_").toUpperCase(locale);
try {
return Enum.valueOf(targetType, result);
- } catch (IllegalArgumentException ee) {
+ } catch (Exception ee) {
// There was no match. Try to compare the available values to see if
// the constant is using something else than all upper case
-
- EnumSet<?> set = EnumSet.allOf(targetType);
- for (Enum e : set) {
- if (e.name().toUpperCase(locale).equals(result)) {
- return e;
+ try {
+ EnumSet<?> set = EnumSet.allOf(targetType);
+ for (Enum e : set) {
+ if (e.name().toUpperCase(locale).equals(result)) {
+ return e;
+ }
}
+ } catch (Exception e) {
}
- // Fallback did not work either, re-throw original exception so user
- // knows what went wrong
+ // Fallback did not work either, re-throw original exception so
+ // user knows what went wrong
throw new ConversionException(ee);
}
}
diff --git a/server/src/com/vaadin/data/util/converter/StringToShortConverter.java b/server/src/com/vaadin/data/util/converter/StringToShortConverter.java
index 3761d11227..4ee085286f 100644
--- a/server/src/com/vaadin/data/util/converter/StringToShortConverter.java
+++ b/server/src/com/vaadin/data/util/converter/StringToShortConverter.java
@@ -28,7 +28,7 @@ import java.util.Locale;
* </p>
*
* @author Vaadin Ltd
- * @since 7.3.1
+ * @since
*/
public class StringToShortConverter extends
AbstractStringToNumberConverter<Short> {
diff --git a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
index 683140d279..c0c660c084 100644
--- a/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
+++ b/server/src/com/vaadin/data/util/sqlcontainer/SQLContainer.java
@@ -652,7 +652,6 @@ public class SQLContainer implements Container, Container.Filterable,
if (cachedItems.isEmpty()) {
getPage();
}
- int size = size();
// this protects against infinite looping
int counter = 0;
int oldIndex;
@@ -1020,18 +1019,20 @@ public class SQLContainer implements Container, Container.Filterable,
}
/* Perform buffered modifications */
for (RowItem item : modifiedItems) {
- if (queryDelegate.storeRow(item) > 0) {
- /*
- * Also reset the modified state in the item in case it is
- * reused e.g. in a form.
- */
- item.commit();
- } else {
- queryDelegate.rollback();
- refresh();
- throw new ConcurrentModificationException(
- "Item with the ID '" + item.getId()
- + "' has been externally modified.");
+ if (!removedItems.containsKey(item.getId())) {
+ if (queryDelegate.storeRow(item) > 0) {
+ /*
+ * Also reset the modified state in the item in case it
+ * is reused e.g. in a form.
+ */
+ item.commit();
+ } else {
+ queryDelegate.rollback();
+ refresh();
+ throw new ConcurrentModificationException(
+ "Item with the ID '" + item.getId()
+ + "' has been externally modified.");
+ }
}
}
/* Perform buffered additions */
diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java
index f0666f63fc..c34e986fce 100644
--- a/server/src/com/vaadin/server/BootstrapHandler.java
+++ b/server/src/com/vaadin/server/BootstrapHandler.java
@@ -469,6 +469,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler {
JsonObject versionInfo = Json.createObject();
versionInfo.put("vaadinVersion", Version.getFullVersion());
+ versionInfo.put("atmosphereVersion",
+ org.atmosphere.util.Version.getRawVersion());
appConfig.put("versionInfo", versionInfo);
appConfig.put("widgetset", context.getWidgetsetName());
diff --git a/server/src/com/vaadin/server/FileResource.java b/server/src/com/vaadin/server/FileResource.java
index de14e2f0f2..b32905f972 100644
--- a/server/src/com/vaadin/server/FileResource.java
+++ b/server/src/com/vaadin/server/FileResource.java
@@ -57,6 +57,9 @@ public class FileResource implements ConnectorResource {
* the file that should be served.
*/
public FileResource(File sourceFile) {
+ if (sourceFile == null) {
+ throw new IllegalArgumentException("File cannot be null");
+ }
setSourceFile(sourceFile);
}
diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java
index 4656f9a672..d1242676da 100644
--- a/server/src/com/vaadin/server/VaadinServlet.java
+++ b/server/src/com/vaadin/server/VaadinServlet.java
@@ -573,8 +573,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
/**
* A helper method to strip away characters that might somehow be used for
- * XSS attacs. Leaves at least alphanumeric characters intact. Also removes
- * eg. ( and ), so values should be safe in javascript too.
+ * XSS attacks. Leaves at least alphanumeric characters intact. Also removes
+ * e.g. '(' and ')', so values should be safe in javascript too.
*
* @param themeName
* @return
@@ -583,7 +583,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
* version
*/
@Deprecated
- protected static String stripSpecialChars(String themeName) {
+ public static String stripSpecialChars(String themeName) {
StringBuilder sb = new StringBuilder();
char[] charArray = themeName.toCharArray();
for (int i = 0; i < charArray.length; i++) {
@@ -704,6 +704,15 @@ public class VaadinServlet extends HttpServlet implements Constants {
return;
}
+ String cacheControl = "public, max-age=0, must-revalidate";
+ int resourceCacheTime = getCacheTime(filename);
+ if (resourceCacheTime > 0) {
+ cacheControl = "max-age=" + String.valueOf(resourceCacheTime);
+ }
+ response.setHeader("Cache-Control", cacheControl);
+ response.setDateHeader("Expires", System.currentTimeMillis()
+ + (resourceCacheTime * 1000));
+
// Find the modification timestamp
long lastModifiedTime = 0;
URLConnection connection = null;
@@ -714,6 +723,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
// are not returned by the browser in the "If-Modified-Since"
// header).
lastModifiedTime = lastModifiedTime - lastModifiedTime % 1000;
+ response.setDateHeader("Last-Modified", lastModifiedTime);
if (browserHasNewestVersion(request, lastModifiedTime)) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
@@ -748,18 +758,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
response.setContentType(mimetype);
}
- // Provide modification timestamp to the browser if it is known.
- if (lastModifiedTime > 0) {
- response.setDateHeader("Last-Modified", lastModifiedTime);
-
- String cacheControl = "public, max-age=0, must-revalidate";
- int resourceCacheTime = getCacheTime(filename);
- if (resourceCacheTime > 0) {
- cacheControl = "max-age=" + String.valueOf(resourceCacheTime);
- }
- response.setHeader("Cache-Control", cacheControl);
- }
-
writeStaticResourceResponse(request, response, resourceUrl);
}
diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java
index 8e61370d85..1216d2b689 100644
--- a/server/src/com/vaadin/server/communication/UIInitHandler.java
+++ b/server/src/com/vaadin/server/communication/UIInitHandler.java
@@ -17,7 +17,7 @@
package com.vaadin.server.communication;
import java.io.IOException;
-import java.io.OutputStreamWriter;
+import java.io.OutputStream;
import java.io.StringWriter;
import java.util.List;
import java.util.logging.Level;
@@ -110,18 +110,13 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler {
// iOS 6 Safari requires this (#9732)
response.setHeader("Cache-Control", "no-cache");
- // NOTE! GateIn requires, for some weird reason, getOutputStream
- // to be used instead of getWriter() (it seems to interpret
- // application/json as a binary content type)
- OutputStreamWriter outputWriter = new OutputStreamWriter(
- response.getOutputStream(), "UTF-8");
- try {
- outputWriter.write(json);
- // NOTE GateIn requires the buffers to be flushed to work
- outputWriter.flush();
- } finally {
- outputWriter.close();
- }
+ byte[] b = json.getBytes("UTF-8");
+ response.setHeader("Content-Length", String.valueOf(b.length));
+
+ OutputStream outputStream = response.getOutputStream();
+ outputStream.write(b);
+ // NOTE GateIn requires the buffers to be flushed to work
+ outputStream.flush();
return true;
}
diff --git a/server/src/com/vaadin/ui/AbsoluteLayout.java b/server/src/com/vaadin/ui/AbsoluteLayout.java
index afc73f5ecc..af47981db6 100644
--- a/server/src/com/vaadin/ui/AbsoluteLayout.java
+++ b/server/src/com/vaadin/ui/AbsoluteLayout.java
@@ -153,7 +153,6 @@ public class AbsoluteLayout extends AbstractLayout implements
internalRemoveComponent(c);
throw e;
}
- markAsDirty();
}
/**
@@ -197,7 +196,6 @@ public class AbsoluteLayout extends AbstractLayout implements
public void removeComponent(Component c) {
internalRemoveComponent(c);
super.removeComponent(c);
- markAsDirty();
}
/**
diff --git a/server/src/com/vaadin/ui/AbstractComponentContainer.java b/server/src/com/vaadin/ui/AbstractComponentContainer.java
index e70b0fa0ce..1095331602 100644
--- a/server/src/com/vaadin/ui/AbstractComponentContainer.java
+++ b/server/src/com/vaadin/ui/AbstractComponentContainer.java
@@ -209,6 +209,7 @@ public abstract class AbstractComponentContainer extends AbstractComponent
c.setParent(this);
fireComponentAttachEvent(c);
+ markAsDirty();
}
/**
@@ -223,6 +224,7 @@ public abstract class AbstractComponentContainer extends AbstractComponent
if (equals(c.getParent())) {
c.setParent(null);
fireComponentDetachEvent(c);
+ markAsDirty();
}
}
diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java
index 369ad1253c..df7bbb68a2 100644
--- a/server/src/com/vaadin/ui/AbstractField.java
+++ b/server/src/com/vaadin/ui/AbstractField.java
@@ -1502,25 +1502,12 @@ public abstract class AbstractField<T> extends AbstractComponent implements
markAsDirty();
}
- /**
- * Is the field empty?
- *
- * In general, "empty" state is same as null. As an exception, TextField
- * also treats empty string as "empty".
- */
- protected boolean isEmpty() {
+ @Override
+ public boolean isEmpty() {
return (getFieldValue() == null);
}
- /**
- * Clear the value of the field.
- * <p>
- * The field value is typically reset to the initial value of the field but
- * this is not mandatory. Calling {@link #isEmpty()} on a cleared field must
- * always returns true.
- *
- * @since
- */
+ @Override
public void clear() {
setValue(null);
}
diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java
index 2c4dd5be5d..70f08c95d8 100644
--- a/server/src/com/vaadin/ui/AbstractSelect.java
+++ b/server/src/com/vaadin/ui/AbstractSelect.java
@@ -1782,7 +1782,7 @@ public abstract class AbstractSelect extends AbstractField<Object> implements
* @see AbstractField#isEmpty().
*/
@Override
- protected boolean isEmpty() {
+ public boolean isEmpty() {
if (!multiSelect) {
return super.isEmpty();
} else {
diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java
index e9b37f8cff..a78f192fa2 100644
--- a/server/src/com/vaadin/ui/AbstractSplitPanel.java
+++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java
@@ -214,7 +214,6 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
} else if (c == getSecondComponent()) {
getState().secondChild = null;
}
- markAsDirty();
}
/*
@@ -256,7 +255,6 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer {
} else if (oldComponent == getSecondComponent()) {
setSecondComponent(newComponent);
}
- markAsDirty();
}
/**
diff --git a/server/src/com/vaadin/ui/AbstractTextField.java b/server/src/com/vaadin/ui/AbstractTextField.java
index 9293d38119..ea0372bc8c 100644
--- a/server/src/com/vaadin/ui/AbstractTextField.java
+++ b/server/src/com/vaadin/ui/AbstractTextField.java
@@ -317,7 +317,7 @@ public abstract class AbstractTextField extends AbstractField<String> implements
}
@Override
- protected boolean isEmpty() {
+ public boolean isEmpty() {
return super.isEmpty() || getValue().length() == 0;
}
diff --git a/server/src/com/vaadin/ui/CssLayout.java b/server/src/com/vaadin/ui/CssLayout.java
index e7b63cc87a..350423576f 100644
--- a/server/src/com/vaadin/ui/CssLayout.java
+++ b/server/src/com/vaadin/ui/CssLayout.java
@@ -118,7 +118,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier {
components.add(c);
try {
super.addComponent(c);
- markAsDirty();
} catch (IllegalArgumentException e) {
components.remove(c);
throw e;
@@ -141,7 +140,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier {
components.addFirst(c);
try {
super.addComponent(c);
- markAsDirty();
} catch (IllegalArgumentException e) {
components.remove(c);
throw e;
@@ -170,7 +168,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier {
components.add(index, c);
try {
super.addComponent(c);
- markAsDirty();
} catch (IllegalArgumentException e) {
components.remove(c);
throw e;
@@ -187,7 +184,6 @@ public class CssLayout extends AbstractLayout implements LayoutClickNotifier {
public void removeComponent(Component c) {
components.remove(c);
super.removeComponent(c);
- markAsDirty();
}
/**
diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java
index f4fe7fa66c..a9c266b0b9 100644
--- a/server/src/com/vaadin/ui/CustomLayout.java
+++ b/server/src/com/vaadin/ui/CustomLayout.java
@@ -144,8 +144,8 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent {
}
slots.put(location, c);
getState().childLocations.put(c, location);
- c.setParent(this);
- fireComponentAttachEvent(c);
+
+ super.addComponent(c);
}
/**
diff --git a/server/src/com/vaadin/ui/DateField.java b/server/src/com/vaadin/ui/DateField.java
index 030bd5f6c2..d5700c4b65 100644
--- a/server/src/com/vaadin/ui/DateField.java
+++ b/server/src/com/vaadin/ui/DateField.java
@@ -316,10 +316,10 @@ public class DateField extends AbstractField<Date> implements
throw new IllegalStateException(
"startDate cannot be later than endDate");
}
- getState().rangeStart = startDate;
- // rangeStart = startDate;
- // This has to be done to correct for the resolution
- // updateRangeState();
+
+ // Create a defensive copy against issues when using java.sql.Date (and
+ // also against mutable Date).
+ getState().rangeStart = new Date(startDate.getTime());
updateRangeValidator();
}
@@ -436,8 +436,10 @@ public class DateField extends AbstractField<Date> implements
throw new IllegalStateException(
"endDate cannot be earlier than startDate");
}
- // rangeEnd = endDate;
- getState().rangeEnd = endDate;
+
+ // Create a defensive copy against issues when using java.sql.Date (and
+ // also against mutable Date).
+ getState().rangeEnd = new Date(endDate.getTime());
updateRangeValidator();
}
diff --git a/server/src/com/vaadin/ui/Field.java b/server/src/com/vaadin/ui/Field.java
index f191e1bdd7..6dee4de6cb 100644
--- a/server/src/com/vaadin/ui/Field.java
+++ b/server/src/com/vaadin/ui/Field.java
@@ -113,4 +113,26 @@ public interface Field<T> extends Component, BufferedValidatable, Property<T>,
return (Property) getSource();
}
}
+
+ /**
+ * Is the field empty?
+ *
+ * In general, "empty" state is same as null. As an exception, TextField
+ * also treats empty string as "empty".
+ *
+ * @since
+ * @return true if the field is empty, false otherwise
+ */
+ public boolean isEmpty();
+
+ /**
+ * Clears the value of the field.
+ * <p>
+ * The field value is typically reset to the initial value of the field.
+ * Calling {@link #isEmpty()} on a cleared field must always returns true.
+ *
+ * @since
+ */
+ public void clear();
+
}
diff --git a/server/src/com/vaadin/ui/Form.java b/server/src/com/vaadin/ui/Form.java
index 48239b09e3..45532756e5 100644
--- a/server/src/com/vaadin/ui/Form.java
+++ b/server/src/com/vaadin/ui/Form.java
@@ -1186,9 +1186,14 @@ public class Form extends AbstractField<Object> implements Item.Editor,
}
}
- /** Form is empty if all of its fields are empty. */
+ /**
+ * {@inheritDoc}
+ * <p>
+ * A Form is empty if all of its fields are empty.
+ *
+ */
@Override
- protected boolean isEmpty() {
+ public boolean isEmpty() {
for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) {
Field<?> f = i.next();
diff --git a/server/src/com/vaadin/ui/GridLayout.java b/server/src/com/vaadin/ui/GridLayout.java
index 0dd16a03e7..96854c5b1b 100644
--- a/server/src/com/vaadin/ui/GridLayout.java
+++ b/server/src/com/vaadin/ui/GridLayout.java
@@ -255,8 +255,6 @@ public class GridLayout extends AbstractLayout implements
cursorY = row1;
}
}
-
- markAsDirty();
}
/**
@@ -390,7 +388,6 @@ public class GridLayout extends AbstractLayout implements
getState().childData.remove(component);
components.remove(component);
-
super.removeComponent(component);
}
diff --git a/server/src/com/vaadin/ui/RichTextArea.java b/server/src/com/vaadin/ui/RichTextArea.java
index 9d05181541..31327b3a6f 100644
--- a/server/src/com/vaadin/ui/RichTextArea.java
+++ b/server/src/com/vaadin/ui/RichTextArea.java
@@ -285,7 +285,7 @@ public class RichTextArea extends AbstractField<String> implements
}
@Override
- protected boolean isEmpty() {
+ public boolean isEmpty() {
return super.isEmpty() || getValue().length() == 0;
}
diff --git a/server/src/com/vaadin/ui/TabSheet.java b/server/src/com/vaadin/ui/TabSheet.java
index d3410464a2..88002104b1 100644
--- a/server/src/com/vaadin/ui/TabSheet.java
+++ b/server/src/com/vaadin/ui/TabSheet.java
@@ -195,7 +195,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
if (component != null && components.contains(component)) {
int componentIndex = components.indexOf(component);
-
super.removeComponent(component);
keyMapper.remove(component);
components.remove(component);
@@ -232,7 +231,6 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
fireSelectedTabChange();
}
}
- markAsDirty();
}
}
@@ -394,8 +392,9 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
setSelected(tabComponent);
fireSelectedTabChange();
}
+
super.addComponent(tabComponent);
- markAsDirty();
+
return tab;
}
}
@@ -967,16 +966,16 @@ public class TabSheet extends AbstractComponentContainer implements Focusable,
/**
* Gets the icon alt text for the tab.
- *
+ *
* @since 7.2
*/
public String getIconAlternateText();
/**
* Sets the icon alt text for the tab.
- *
+ *
* @since 7.2
- *
+ *
* @param iconAltText
* the icon to set
*/
diff --git a/server/src/com/vaadin/ui/TextField.java b/server/src/com/vaadin/ui/TextField.java
index fb1e4284a2..1fc10c6ced 100644
--- a/server/src/com/vaadin/ui/TextField.java
+++ b/server/src/com/vaadin/ui/TextField.java
@@ -43,7 +43,7 @@ public class TextField extends AbstractTextField {
* Constructs an empty <code>TextField</code> with no caption.
*/
public TextField() {
- setValue("");
+ clear();
}
/**
@@ -99,4 +99,14 @@ public class TextField extends AbstractTextField {
setCaption(caption);
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractField#clear()
+ */
+ @Override
+ public void clear() {
+ setValue("");
+ }
+
}
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index 78cb5488e8..4bd4b67259 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -633,7 +633,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
this.embedId = embedId;
// Actual theme - used for finding CustomLayout templates
- getState().theme = request.getParameter("theme");
+ setTheme(request.getParameter("theme"));
getPage().init(request);
@@ -1164,7 +1164,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements
* The new theme name
*/
public void setTheme(String theme) {
- getState().theme = theme;
+ if(theme == null) {
+ getState().theme = null;
+ } else {
+ getState().theme = VaadinServlet.stripSpecialChars(theme);
+ }
}
/**
diff --git a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java
index fcaabcc079..2f51b21f7c 100644
--- a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java
+++ b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java
@@ -249,71 +249,33 @@ public class ContainerEventProvider implements CalendarEditableEventProvider,
@Override
public List<CalendarEvent> getEvents(Date startDate, Date endDate) {
eventCache.clear();
-
- int[] rangeIndexes = getFirstAndLastEventIndex(startDate, endDate);
- for (int i = rangeIndexes[0]; i <= rangeIndexes[1]
- && i < container.size(); i++) {
- eventCache.add(getEvent(i));
- }
- return Collections.unmodifiableList(eventCache);
- }
-
- /**
- * Get the first event for a date
- *
- * @param date
- * The date to search for, NUll returns first event in container
- * @return Returns an array where the first item is the start index and the
- * second item is the end item
- */
- private int[] getFirstAndLastEventIndex(Date start, Date end) {
- int startIndex = 0;
int size = container.size();
assert size >= 0;
- int endIndex = size - 1;
- if (start != null) {
- /*
- * Iterating from the start of the container, if range is in the end
- * of the container then this will be slow TODO This could be
- * improved by using some sort of divide and conquer algorithm
- */
- while (startIndex < size) {
- Object id = container.getIdByIndex(startIndex);
- Item item = container.getItem(id);
- Date d = (Date) item.getItemProperty(startDateProperty)
+ for (int i = 0; i < size; i++) {
+ Object id = container.getIdByIndex(i);
+ Item item = container.getItem(id);
+ boolean add = true;
+ if (startDate != null) {
+ Date eventEnd = (Date) item.getItemProperty(endDateProperty)
.getValue();
- if (d.compareTo(start) >= 0) {
- break;
+ if (eventEnd.compareTo(startDate) < 0) {
+ add = false;
}
- startIndex++;
}
- }
-
- if (end != null) {
- /*
- * Iterate from the start index until range ends
- */
- endIndex = startIndex;
- while (endIndex < size - 1) {
- Object id = container.getIdByIndex(endIndex);
- Item item = container.getItem(id);
- Date d = (Date) item.getItemProperty(endDateProperty)
- .getValue();
- if (d == null) {
- // No end date present, use start date
- d = (Date) item.getItemProperty(startDateProperty)
- .getValue();
+ if (add && endDate != null) {
+ Date eventStart = (Date) item
+ .getItemProperty(startDateProperty).getValue();
+ if (eventStart.compareTo(endDate) >= 0) {
+ break; // because container is sorted, all further events
+ // will be even later
}
- if (d.compareTo(end) >= 0) {
- endIndex--;
- break;
- }
- endIndex++;
+ }
+ if (add) {
+ eventCache.add(getEvent(i));
}
}
-
- return new int[] { startIndex, endIndex };
+ return Collections.unmodifiableList(eventCache);
}
/*