diff options
Diffstat (limited to 'server/src/com/vaadin')
15 files changed, 205 insertions, 34 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index c5aab5a053..5a4e877554 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -211,7 +211,8 @@ public class FieldGroup implements Serializable { public void setReadOnly(boolean fieldsReadOnly) { readOnly = fieldsReadOnly; for (Field<?> field : getFields()) { - if (!field.getPropertyDataSource().isReadOnly()) { + if (field.getPropertyDataSource() == null + || !field.getPropertyDataSource().isReadOnly()) { field.setReadOnly(fieldsReadOnly); } else { field.setReadOnly(true); @@ -244,15 +245,13 @@ public class FieldGroup implements Serializable { * @param propertyId * The propertyId to bind to the field * @throws BindException - * If the property id is already bound to another field by this - * field binder + * If the field is null or the property id is already bound to + * another field by this field binder */ public void bind(Field<?> field, Object propertyId) throws BindException { - if (propertyIdToField.containsKey(propertyId) - && propertyIdToField.get(propertyId) != field) { - throw new BindException("Property id " + propertyId - + " is already bound to another field"); - } + throwIfFieldIsNull(field, propertyId); + throwIfPropertyIdAlreadyBound(field, propertyId); + fieldToPropertyId.put(field, propertyId); propertyIdToField.put(propertyId, field); if (itemDataSource == null) { @@ -264,6 +263,23 @@ public class FieldGroup implements Serializable { configureField(field); } + private void throwIfFieldIsNull(Field<?> field, Object propertyId) { + if (field == null) { + throw new BindException( + String.format( + "Cannot bind property id '%s' to a null field.", + propertyId)); + } + } + + private void throwIfPropertyIdAlreadyBound(Field<?> field, Object propertyId) { + if (propertyIdToField.containsKey(propertyId) + && propertyIdToField.get(propertyId) != field) { + throw new BindException("Property id " + propertyId + + " is already bound to another field"); + } + } + private <T> Property.Transactional<T> wrapInTransactionalProperty( Property<T> itemProperty) { return new TransactionalPropertyWrapper<T>(itemProperty); diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index fc0bf7381a..5841bfac4d 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -67,7 +67,7 @@ public interface Constants { // Keep the version number in sync with push/build.xml and other locations // listed in that file - static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin5"; + static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin6"; static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n" + "=================================================================\n" @@ -115,6 +115,15 @@ public interface Constants { + Constants.SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING + ". Supported values are 'false','warning','true'"; + static final String CANNOT_ACQUIRE_CLASSLOADER_SEVERE = "\n" + + "=================================================================\n" + + "Vaadin was unable to acquire class loader from servlet container\n" + + "to load your application classes. Setup appropriate security\n" + + "policy to allow invoking Thread.getContextClassLoader() from\n" + + "VaadinService if you're not using custom class loader.\n" + + "NullPointerExceptions will be thrown later." + + "================================================================="; + static final String URL_PARAMETER_THEME = "theme"; static final String SERVLET_PARAMETER_PRODUCTION_MODE = "productionMode"; @@ -164,4 +173,5 @@ public interface Constants { static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme"; static final String PORTLET_CONTEXT = "PORTLET_CONTEXT"; + } diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java index cff024672c..878b8964b6 100644 --- a/server/src/com/vaadin/server/VaadinPortletService.java +++ b/server/src/com/vaadin/server/VaadinPortletService.java @@ -46,16 +46,6 @@ public class VaadinPortletService extends VaadinService { throws ServiceException { super(deploymentConfiguration); this.portlet = portlet; - - // Set default class loader if not already set - if (getClassLoader() == null) { - /* - * The portlet is most likely to be loaded with a class loader - * specific to the application instead of some generic system class - * loader that loads the Vaadin classes. - */ - setClassLoader(portlet.getClass().getClassLoader()); - } } @Override @@ -162,7 +152,7 @@ public class VaadinPortletService extends VaadinService { if (Constants.PORTLET_CONTEXT.equals(staticFileLocation)) { return request.getContextPath(); - } else{ + } else { return trimTrailingSlashes(staticFileLocation); } } diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index 4d8e7e9bc9..fb93a44d37 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -170,6 +170,10 @@ public abstract class VaadinService implements Serializable { + classLoaderName, e); } } + + if (getClassLoader() == null) { + setDefaultClassLoader(); + } } /** @@ -1861,4 +1865,25 @@ public abstract class VaadinService implements Serializable { eventRouter.fireEvent(new ServiceDestroyEvent(this)); } + /** + * Tries to acquire default class loader and sets it as a class loader for + * this {@link VaadinService} if found. If current security policy disallows + * acquiring class loader instance it will log a message and re-throw + * {@link SecurityException} + * + * @throws SecurityException + * If current security policy forbids acquiring class loader + * + * @since 7.3.5 + */ + protected void setDefaultClassLoader() { + try { + setClassLoader(VaadinServiceClassLoaderUtil + .findDefaultClassLoader()); + } catch (SecurityException e) { + getLogger().log(Level.SEVERE, + Constants.CANNOT_ACQUIRE_CLASSLOADER_SEVERE, e); + throw e; + } + } } diff --git a/server/src/com/vaadin/server/VaadinServiceClassLoaderUtil.java b/server/src/com/vaadin/server/VaadinServiceClassLoaderUtil.java new file mode 100644 index 0000000000..c9e73e2a29 --- /dev/null +++ b/server/src/com/vaadin/server/VaadinServiceClassLoaderUtil.java @@ -0,0 +1,57 @@ +/* + * 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.security.AccessController; +import java.security.PrivilegedAction; + +/** + * Utility class used by {@link VaadinService#setDefaultClassLoader()}. + * + * @since + * @author Vaadin Ltd + */ +class VaadinServiceClassLoaderUtil { + + private static class GetClassLoaderPrivilegedAction implements + PrivilegedAction<ClassLoader> { + @Override + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + } + + /** + * Called by {@link VaadinService#setDefaultClassLoader()} to acquire + * appropriate class loader to load application's classes (e.g. UI). Calls + * should be guarded by try/catch block to catch SecurityException and log + * appropriate message. The code for this method is modeled after + * recommendations laid out by JEE 5 specification sections EE.6.2.4.7 and + * EE.8.2.5 + * + * @return Instance of {@link ClassLoader} that should be used by this + * instance of {@link VaadinService} + * @throws SecurityException + * if current security policy doesn't allow acquiring current + * thread's context class loader + */ + static protected ClassLoader findDefaultClassLoader() + throws SecurityException { + return AccessController + .doPrivileged(new VaadinServiceClassLoaderUtil.GetClassLoaderPrivilegedAction()); + } + +} diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java index 8946ac4fae..6832da236a 100644 --- a/server/src/com/vaadin/server/VaadinServletService.java +++ b/server/src/com/vaadin/server/VaadinServletService.java @@ -51,16 +51,6 @@ public class VaadinServletService extends VaadinService { throws ServiceException { super(deploymentConfiguration); this.servlet = servlet; - - // Set default class loader if not already set - if (getClassLoader() == null) { - /* - * The servlet is most likely to be loaded with a class loader - * specific to the application instead of some generic system class - * loader that loads the Vaadin classes. - */ - setClassLoader(servlet.getClass().getClassLoader()); - } } private static boolean checkAtmosphereSupport() { diff --git a/server/src/com/vaadin/server/WebBrowser.java b/server/src/com/vaadin/server/WebBrowser.java index cb5979d612..66018b02f2 100644 --- a/server/src/com/vaadin/server/WebBrowser.java +++ b/server/src/com/vaadin/server/WebBrowser.java @@ -295,6 +295,7 @@ public class WebBrowser implements Serializable { * * @return true if run on IPhone false if the user is not using IPhone or if * no information on the browser is present + * @since 7.3.3 */ public boolean isIPhone() { return browserDetails.isIPhone(); @@ -305,6 +306,7 @@ public class WebBrowser implements Serializable { * * @return true if run on IPad false if the user is not using IPad or if no * information on the browser is present + * @since 7.3.3 */ public boolean isIPad() { return browserDetails.isIPad(); diff --git a/server/src/com/vaadin/server/communication/FileUploadHandler.java b/server/src/com/vaadin/server/communication/FileUploadHandler.java index 22c6a76106..576cbd8411 100644 --- a/server/src/com/vaadin/server/communication/FileUploadHandler.java +++ b/server/src/com/vaadin/server/communication/FileUploadHandler.java @@ -216,7 +216,10 @@ public class FileUploadHandler implements RequestHandler { } } - private static final int LF = "\n".getBytes()[0]; + /** + * as per RFC 2045, line delimiters in headers are always CRLF, i.e. 13 10 + */ + private static final int LF = 10; private static final String CRLF = "\r\n"; @@ -295,6 +298,9 @@ public class FileUploadHandler implements RequestHandler { ByteArrayOutputStream bout = new ByteArrayOutputStream(); int readByte = stream.read(); while (readByte != LF) { + if (readByte == -1) { + throw new IOException("The multipart stream ended unexpectedly"); + } bout.write(readByte); readByte = stream.read(); } diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java index b083db3183..2c4dd5be5d 100644 --- a/server/src/com/vaadin/ui/AbstractSelect.java +++ b/server/src/com/vaadin/ui/AbstractSelect.java @@ -1675,6 +1675,8 @@ public abstract class AbstractSelect extends AbstractField<Object> implements // Clears the item id mapping table itemIdMapper.removeAll(); + adjustSelection(); + // Notify all listeners fireItemSetChange(); } @@ -1713,6 +1715,23 @@ public abstract class AbstractSelect extends AbstractField<Object> implements } /** + * Removes orphaned ids from selection. + */ + protected void adjustSelection() { + Object value = getValue(); + if (isMultiSelect() && (value instanceof Collection)) { + Collection<?> collection = (Collection<?>) value; + for (Object id : collection) { + if (!containsId(id)) { + unselect(id); + } + } + } else if (!containsId(value)) { + unselect(value); + } + } + + /** * Implementation of item set change event. */ private static class ItemSetChangeEvent extends EventObject implements diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index 63ac9fe35c..72ff6eb0e0 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -516,7 +516,8 @@ public class Calendar extends AbstractComponent implements day.date = df_date.format(date); day.localizedDateFormat = weeklyCaptionFormatter.format(date); day.dayOfWeek = getDowByLocale(currentCalendar); - day.week = currentCalendar.get(java.util.Calendar.WEEK_OF_YEAR); + day.week = getWeek(currentCalendar); + day.yearOfWeek = getYearOfWeek(currentCalendar); days.add(day); @@ -560,6 +561,23 @@ public class Calendar extends AbstractComponent implements state.actions = createActionsList(actionMap); } + private int getWeek(java.util.Calendar calendar) { + return calendar.get(java.util.Calendar.WEEK_OF_YEAR); + } + + private int getYearOfWeek(java.util.Calendar calendar) { + // Would use calendar.getWeekYear() but it's only available since 1.7. + int week = getWeek(calendar); + int month = calendar.get(java.util.Calendar.MONTH); + int year = calendar.get(java.util.Calendar.YEAR); + + if (week == 1 && month == java.util.Calendar.DECEMBER) { + return year + 1; + } + + return year; + } + private void setActionsForEachHalfHour( Map<CalendarDateRange, Set<Action>> actionMap, Date start, Date end, Action.Handler actionHandler) { @@ -1772,7 +1790,7 @@ public class Calendar extends AbstractComponent implements String[] splitted = event.split("w"); if (splitted.length == 2) { try { - int yr = 1900 + Integer.parseInt(splitted[0]); + int yr = Integer.parseInt(splitted[0]); int week = Integer.parseInt(splitted[1]); fireWeekClick(week, yr); } catch (NumberFormatException e) { diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index 34d48a9b18..9da25d3e48 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -1029,7 +1029,7 @@ public class Table extends AbstractSelect implements Action.Container, * </p> * * <p> - * If Table has width set ({@link #setWidth(float, int)} ) the client side + * If Table has height set ({@link #setHeight(float, int)} ) the client side * may update the page length automatically the correct value. * </p> * diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 438b086ec2..78cb5488e8 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -499,6 +499,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements private void attachWindow(Window w) { windows.add(w); w.setParent(this); + fireComponentAttachEvent(w); markAsDirty(); } @@ -523,6 +524,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements window.setParent(null); markAsDirty(); window.fireClose(); + fireComponentDetachEvent(window); return true; } diff --git a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java index 8dff224627..fcaabcc079 100644 --- a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java +++ b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java @@ -442,6 +442,8 @@ public class ContainerEventProvider implements CalendarEditableEventProvider, /** * Set the all day property for the event + * + * @since 7.3.4 */ public void setAllDayProperty(Object allDayProperty) { this.allDayProperty = allDayProperty; @@ -449,6 +451,8 @@ public class ContainerEventProvider implements CalendarEditableEventProvider, /** * Get the all day property for the event + * + * @since 7.3.4 */ public Object getAllDayProperty() { return allDayProperty; diff --git a/server/src/com/vaadin/ui/components/calendar/handler/BasicBackwardHandler.java b/server/src/com/vaadin/ui/components/calendar/handler/BasicBackwardHandler.java index f4d47f89d4..0e99b26856 100644 --- a/server/src/com/vaadin/ui/components/calendar/handler/BasicBackwardHandler.java +++ b/server/src/com/vaadin/ui/components/calendar/handler/BasicBackwardHandler.java @@ -47,6 +47,7 @@ public class BasicBackwardHandler implements BackwardHandler { // calculate amount to move back int durationInDays = (int) (((end.getTime()) - start.getTime()) / DateConstants.DAYINMILLIS); durationInDays++; + // for week view durationInDays = -7, for day view durationInDays = -1 durationInDays = -durationInDays; // set new start and end times @@ -59,6 +60,21 @@ public class BasicBackwardHandler implements BackwardHandler { javaCalendar.add(java.util.Calendar.DATE, durationInDays); Date newEnd = javaCalendar.getTime(); + if (start.equals(end)) { // day view + int firstDay = event.getComponent().getFirstVisibleDayOfWeek(); + int lastDay = event.getComponent().getLastVisibleDayOfWeek(); + int dayOfWeek = javaCalendar.get(Calendar.DAY_OF_WEEK); + + // we suppose that 7 >= lastDay >= firstDay >= 1 + while (!(firstDay <= dayOfWeek && dayOfWeek <= lastDay)) { + javaCalendar.add(java.util.Calendar.DATE, -1); + dayOfWeek = javaCalendar.get(Calendar.DAY_OF_WEEK); + } + + newStart = javaCalendar.getTime(); + newEnd = javaCalendar.getTime(); + } + setDates(event, newStart, newEnd); } diff --git a/server/src/com/vaadin/ui/components/calendar/handler/BasicForwardHandler.java b/server/src/com/vaadin/ui/components/calendar/handler/BasicForwardHandler.java index 96c3c097dc..45b44cb673 100644 --- a/server/src/com/vaadin/ui/components/calendar/handler/BasicForwardHandler.java +++ b/server/src/com/vaadin/ui/components/calendar/handler/BasicForwardHandler.java @@ -45,6 +45,7 @@ public class BasicForwardHandler implements ForwardHandler { // calculate amount to move forward int durationInDays = (int) (((end.getTime()) - start.getTime()) / DateConstants.DAYINMILLIS); + // for week view durationInDays = 7, for day view durationInDays = 1 durationInDays++; // set new start and end times @@ -57,6 +58,21 @@ public class BasicForwardHandler implements ForwardHandler { javaCalendar.add(java.util.Calendar.DATE, durationInDays); Date newEnd = javaCalendar.getTime(); + if (start.equals(end)) { // day view + int firstDay = event.getComponent().getFirstVisibleDayOfWeek(); + int lastDay = event.getComponent().getLastVisibleDayOfWeek(); + int dayOfWeek = javaCalendar.get(Calendar.DAY_OF_WEEK); + + // we suppose that 7 >= lastDay >= firstDay >= 1 + while (!(firstDay <= dayOfWeek && dayOfWeek <= lastDay)) { + javaCalendar.add(java.util.Calendar.DATE, 1); + dayOfWeek = javaCalendar.get(Calendar.DAY_OF_WEEK); + } + + newStart = javaCalendar.getTime(); + newEnd = javaCalendar.getTime(); + } + setDates(event, newStart, newEnd); } |