diff options
Diffstat (limited to 'server/src')
30 files changed, 498 insertions, 145 deletions
diff --git a/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java b/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java index b1bf58199a..9c2e4b2f83 100644 --- a/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java +++ b/server/src/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactory.java @@ -36,10 +36,26 @@ import com.vaadin.ui.RichTextArea; import com.vaadin.ui.Table; import com.vaadin.ui.TextField; +/** + * This class contains a basic implementation for {@link FieldGroupFieldFactory} + * .The class is singleton, use {@link #get()} method to get reference to the + * instance. + * + * @author Vaadin Ltd + */ public class DefaultFieldGroupFieldFactory implements FieldGroupFieldFactory { + private static final DefaultFieldGroupFieldFactory INSTANCE = new DefaultFieldGroupFieldFactory(); + public static final Object CAPTION_PROPERTY_ID = "Caption"; + protected DefaultFieldGroupFieldFactory() { + } + + public static DefaultFieldGroupFieldFactory get() { + return INSTANCE; + } + @Override public <T extends Field> T createField(Class<?> type, Class<T> fieldType) { if (Enum.class.isAssignableFrom(type)) { diff --git a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java index e647bdbf6d..c5aab5a053 100644 --- a/server/src/com/vaadin/data/fieldgroup/FieldGroup.java +++ b/server/src/com/vaadin/data/fieldgroup/FieldGroup.java @@ -28,6 +28,7 @@ import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.Validator.InvalidValueException; import com.vaadin.data.util.TransactionalPropertyWrapper; +import com.vaadin.ui.AbstractField; import com.vaadin.ui.DefaultFieldFactory; import com.vaadin.ui.Field; import com.vaadin.ui.Form; @@ -67,7 +68,8 @@ public class FieldGroup implements Serializable { /** * The field factory used by builder methods. */ - private FieldGroupFieldFactory fieldFactory = new DefaultFieldGroupFieldFactory(); + private FieldGroupFieldFactory fieldFactory = DefaultFieldGroupFieldFactory + .get(); /** * Constructs a field binder. Use {@link #setItemDataSource(Item)} to set a @@ -435,8 +437,14 @@ public class FieldGroup implements Serializable { return; } for (Field<?> f : fieldToPropertyId.keySet()) { - ((Property.Transactional<?>) f.getPropertyDataSource()) - .startTransaction(); + Property.Transactional<?> property = (Property.Transactional<?>) f + .getPropertyDataSource(); + if (property == null) { + throw new CommitException("Property \"" + + fieldToPropertyId.get(f) + + "\" not bound to datasource."); + } + property.startTransaction(); } try { firePreCommitEvent(); @@ -1095,4 +1103,18 @@ public class FieldGroup implements Serializable { } return memberFieldInOrder; } + + /** + * Clears the value of all fields. + * + * @since + */ + public void clear() { + for (Field<?> f : getFields()) { + if (f instanceof AbstractField) { + ((AbstractField) f).clear(); + } + } + + } } diff --git a/server/src/com/vaadin/data/util/BeanItem.java b/server/src/com/vaadin/data/util/BeanItem.java index ac3ef86434..12d9b23d0a 100644 --- a/server/src/com/vaadin/data/util/BeanItem.java +++ b/server/src/com/vaadin/data/util/BeanItem.java @@ -214,13 +214,75 @@ public class BeanItem<BT> extends PropertysetItem { } BeanInfo info = Introspector.getBeanInfo(beanClass); - propertyDescriptors.addAll(Arrays.asList(info - .getPropertyDescriptors())); + propertyDescriptors.addAll(getPropertyDescriptors(info)); return propertyDescriptors; } else { BeanInfo info = Introspector.getBeanInfo(beanClass); - return Arrays.asList(info.getPropertyDescriptors()); + return getPropertyDescriptors(info); + } + } + + // Workaround for Java6 bug JDK-6788525. Do nothing for JDK7+. + private static List<PropertyDescriptor> getPropertyDescriptors( + BeanInfo beanInfo) { + PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors(); + List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>( + descriptors.length); + for (PropertyDescriptor descriptor : descriptors) { + try { + Method readMethod = getMethodFromBridge(descriptor + .getReadMethod()); + if (readMethod != null) { + Method writeMethod = getMethodFromBridge( + descriptor.getWriteMethod(), + readMethod.getReturnType()); + if (writeMethod == null) { + writeMethod = descriptor.getWriteMethod(); + } + PropertyDescriptor descr = new PropertyDescriptor( + descriptor.getName(), readMethod, writeMethod); + result.add(descr); + } else { + result.add(descriptor); + } + } catch (SecurityException ignore) { + // handle next descriptor + } catch (IntrospectionException e) { + result.add(descriptor); + } + } + return result; + } + + /** + * Return not bridged method for bridge {@code bridgeMethod} method. If + * method {@code bridgeMethod} is not bridge method then return null. + */ + private static Method getMethodFromBridge(Method bridgeMethod) + throws SecurityException { + if (bridgeMethod == null) { + return null; + } + return getMethodFromBridge(bridgeMethod, + bridgeMethod.getParameterTypes()); + } + + /** + * Return not bridged method for bridge {@code bridgeMethod} method and + * declared {@code paramTypes}. If method {@code bridgeMethod} is not bridge + * method then return null. + */ + private static Method getMethodFromBridge(Method bridgeMethod, + Class<?>... paramTypes) throws SecurityException { + if (bridgeMethod == null || !bridgeMethod.isBridge()) { + return null; + } + try { + return bridgeMethod.getDeclaringClass().getMethod( + bridgeMethod.getName(), paramTypes); + } catch (NoSuchMethodException e) { + return null; } } diff --git a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java index fdf858a528..26613c5d02 100644 --- a/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java +++ b/server/src/com/vaadin/data/util/converter/DefaultConverterFactory.java @@ -110,6 +110,8 @@ public class DefaultConverterFactory implements ConverterFactory { return new StringToBooleanConverter(); } else if (Date.class.isAssignableFrom(sourceType)) { return new StringToDateConverter(); + } else if (Enum.class.isAssignableFrom(sourceType)) { + return new StringToEnumConverter(); } else { return null; } diff --git a/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java new file mode 100644 index 0000000000..a1328d831c --- /dev/null +++ b/server/src/com/vaadin/data/util/converter/StringToEnumConverter.java @@ -0,0 +1,97 @@ +/* + * 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.data.util.converter; + +import java.util.EnumSet; +import java.util.Locale; + +/** + * A converter that converts from {@link String} to an {@link Enum} and back. + * <p> + * Designed to provide nice human readable strings for {@link Enum} classes + * where the constants are named SOME_UPPERCASE_WORDS. Will not necessarily work + * correctly for other cases. + * </p> + * + * @author Vaadin Ltd + * @since + */ +public class StringToEnumConverter implements Converter<String, Enum> { + + @Override + public Enum convertToModel(String value, Class<? extends Enum> targetType, + Locale locale) throws ConversionException { + if (value == null) { + return null; + } + if (locale == null) { + locale = Locale.getDefault(); + } + + // Foo -> FOO + // Foo bar -> FOO_BAR + String result = value.replace(" ", "_").toUpperCase(locale); + try { + return Enum.valueOf(targetType, result); + } catch (IllegalArgumentException 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; + } + } + + // Fallback did not work either, re-throw original exception so user + // knows what went wrong + throw new ConversionException(ee); + } + } + + @Override + public String convertToPresentation(Enum value, + Class<? extends String> targetType, Locale locale) + throws ConversionException { + if (value == null) { + return null; + } + if (locale == null) { + locale = Locale.getDefault(); + } + + String enumString = value.toString(); + // FOO -> Foo + // FOO_BAR -> Foo bar + // _FOO -> _foo + String result = enumString.substring(0, 1).toUpperCase(locale); + result += enumString.substring(1).toLowerCase(locale).replace('_', ' '); + + return result; + } + + @Override + public Class<Enum> getModelType() { + return Enum.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } + +} diff --git a/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java new file mode 100644 index 0000000000..43d4570d90 --- /dev/null +++ b/server/src/com/vaadin/server/AbstractDeploymentConfiguration.java @@ -0,0 +1,54 @@ +/* + * 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; + +/** + * An abstract base class for DeploymentConfiguration implementations. This + * class provides default implementation for common config properties. + * + * @author Vaadin Ltd + */ +public abstract class AbstractDeploymentConfiguration implements + DeploymentConfiguration { + + @Override + public String getUIClassName() { + return getApplicationOrSystemProperty(VaadinSession.UI_PARAMETER, null); + } + + @Override + public String getUIProviderClassName() { + return getApplicationOrSystemProperty( + Constants.SERVLET_PARAMETER_UI_PROVIDER, null); + } + + @Override + public String getWidgetset(String defaultValue) { + return getApplicationOrSystemProperty(Constants.PARAMETER_WIDGETSET, + defaultValue); + } + + @Override + public String getResourcesPath() { + return getApplicationOrSystemProperty( + Constants.PARAMETER_VAADIN_RESOURCES, null); + } + + @Override + public String getClassLoaderName() { + return getApplicationOrSystemProperty("ClassLoader", null); + } +} diff --git a/server/src/com/vaadin/server/BootstrapHandler.java b/server/src/com/vaadin/server/BootstrapHandler.java index 0605d6a2b8..f0666f63fc 100644 --- a/server/src/com/vaadin/server/BootstrapHandler.java +++ b/server/src/com/vaadin/server/BootstrapHandler.java @@ -350,7 +350,6 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { /*- Add classnames; * .v-app * .v-app-loading - * .v-app-<simpleName for app class> *- Additionally added from javascript: * <themeName, remove non-alphanum> */ @@ -362,6 +361,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { mainDiv.attr("id", context.getAppId()); mainDiv.addClass("v-app"); mainDiv.addClass(context.getThemeName()); + mainDiv.addClass(context.getUIClass().getSimpleName() + .toLowerCase(Locale.ENGLISH)); if (style != null && style.length() != 0) { mainDiv.attr("style", style); } @@ -401,7 +402,7 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { builder.append("//<![CDATA[\n"); builder.append("if (!window.vaadin) alert(" + JsonUtil.quote("Failed to load the bootstrap javascript: " - + bootstrapLocation) + ");\n"); + + bootstrapLocation) + ");\n"); appendMainScriptTagContents(context, builder); @@ -501,7 +502,8 @@ public abstract class BootstrapHandler extends SynchronizedRequestHandler { if (systemMessages.getAuthenticationErrorURL() == null) { authErrMsg.put("url", Json.createNull()); } else { - authErrMsg.put("url", systemMessages.getAuthenticationErrorURL()); + authErrMsg.put("url", + systemMessages.getAuthenticationErrorURL()); } appConfig.put("authErrMsg", authErrMsg); diff --git a/server/src/com/vaadin/server/BrowserWindowOpener.java b/server/src/com/vaadin/server/BrowserWindowOpener.java index 44679fbfbb..8cc1faa728 100644 --- a/server/src/com/vaadin/server/BrowserWindowOpener.java +++ b/server/src/com/vaadin/server/BrowserWindowOpener.java @@ -126,6 +126,55 @@ public class BrowserWindowOpener extends AbstractExtension { } /** + * Sets the provided URL {@code url} for this instance. The {@code url} will + * be opened in a new browser window/tab when the extended component is + * clicked. + * + * @param url + * URL to open + */ + public void setUrl(String url) { + setResource(new ExternalResource(url)); + } + + /** + * Sets the provided {@code resource} for this instance. The + * {@code resource} will be opened in a new browser window/tab when the + * extended component is clicked. + * + * @param resource + * resource to open + */ + public void setResource(Resource resource) { + setResource(BrowserWindowOpenerState.locationResource, resource); + } + + /** + * Returns the resource for this instance. + * + * @return resource to open browser window + */ + public Resource getResource() { + return getResource(BrowserWindowOpenerState.locationResource); + } + + /** + * Returns the URL for this BrowserWindowOpener instance. Returns + * {@code null} if this instance is not URL resource based (a non URL based + * resource has been set for it). + * + * @return URL to open in the new browser window/tab when the extended + * component is clicked + */ + public String getUrl() { + Resource resource = getResource(); + if (resource instanceof ExternalResource) { + return ((ExternalResource) resource).getURL(); + } + return null; + } + + /** * Sets the target window name that will be used. If a window has already * been opened with the same name, the contents of that window will be * replaced instead of opening a new window. If the name is diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 2b868c12a6..fc0bf7381a 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -162,4 +162,6 @@ public interface Constants { static final String PORTAL_PARAMETER_VAADIN_WIDGETSET = "vaadin.widgetset"; static final String PORTAL_PARAMETER_VAADIN_RESOURCE_PATH = "vaadin.resources.path"; static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme"; + + static final String PORTLET_CONTEXT = "PORTLET_CONTEXT"; } diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java index fd14c3cd3f..22d5210eaa 100644 --- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java @@ -29,7 +29,8 @@ import com.vaadin.shared.communication.PushMode; * @author Vaadin Ltd * @since 7.0.0 */ -public class DefaultDeploymentConfiguration implements DeploymentConfiguration { +public class DefaultDeploymentConfiguration extends + AbstractDeploymentConfiguration { /** * Default value for {@link #getResourceCacheTime()} = {@value} . */ diff --git a/server/src/com/vaadin/server/DefaultUIProvider.java b/server/src/com/vaadin/server/DefaultUIProvider.java index 2a1a59dbe6..38525fc020 100644 --- a/server/src/com/vaadin/server/DefaultUIProvider.java +++ b/server/src/com/vaadin/server/DefaultUIProvider.java @@ -24,15 +24,9 @@ public class DefaultUIProvider extends UIProvider { public Class<? extends UI> getUIClass(UIClassSelectionEvent event) { VaadinRequest request = event.getRequest(); - Object uiClassNameObj = request - .getService() - .getDeploymentConfiguration() - .getApplicationOrSystemProperty(VaadinSession.UI_PARAMETER, - null); - - if (uiClassNameObj instanceof String) { - String uiClassName = uiClassNameObj.toString(); - + String uiClassName = request.getService().getDeploymentConfiguration() + .getUIClassName(); + if (uiClassName != null) { ClassLoader classLoader = request.getService().getClassLoader(); try { Class<? extends UI> uiClass = Class.forName(uiClassName, true, diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java index fcfeecc31f..3124729773 100644 --- a/server/src/com/vaadin/server/DeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DeploymentConfiguration.java @@ -163,6 +163,38 @@ public interface DeploymentConfiguration extends Serializable { String defaultValue); /** + * Gets UI class configuration option value. + * + * @return UI class name + */ + public String getUIClassName(); + + /** + * Gets UI provider class configuration option value. + * + * @return UI class name + */ + public String getUIProviderClassName(); + + /** + * Gets Widgetset configuration option value. {@code defaultValue} is + * returned if widgetset parameter is not configured. + * + * @return UI class name + */ + public String getWidgetset(String defaultValue); + + /** + * Gets resources path configuration option value. + */ + public String getResourcesPath(); + + /** + * Gets class loader configuration option value. + */ + public String getClassLoaderName(); + + /** * Returns to legacy Property.toString() mode used. See * {@link AbstractProperty#isLegacyToStringEnabled()} for more information. * diff --git a/server/src/com/vaadin/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java index c21f27de97..c0c3eebca3 100644 --- a/server/src/com/vaadin/server/DragAndDropService.java +++ b/server/src/com/vaadin/server/DragAndDropService.java @@ -38,6 +38,7 @@ import com.vaadin.shared.communication.SharedState; import com.vaadin.shared.ui.dd.DragEventType; import com.vaadin.ui.Component; import com.vaadin.ui.UI; + import elemental.json.JsonObject; public class DragAndDropService implements VariableOwner, ClientConnector { @@ -64,7 +65,7 @@ public class DragAndDropService implements VariableOwner, ClientConnector { final Component sourceComponent = (Component) variables .get("component"); - if (sourceComponent != null && !sourceComponent.isEnabled()) { + if (sourceComponent != null && !sourceComponent.isConnectorEnabled()) { // source component not supposed to be enabled getLogger().warning( "Client dropped from " + sourceComponent @@ -83,7 +84,7 @@ public class DragAndDropService implements VariableOwner, ClientConnector { DropTarget dropTarget = (DropTarget) owner; - if (!dropTarget.isEnabled()) { + if (!dropTarget.isConnectorEnabled()) { getLogger() .warning( "Client dropped on " + owner diff --git a/server/src/com/vaadin/server/Page.java b/server/src/com/vaadin/server/Page.java index 3acea97c0f..3ddf4862b2 100644 --- a/server/src/com/vaadin/server/Page.java +++ b/server/src/com/vaadin/server/Page.java @@ -485,14 +485,14 @@ public class Page implements Serializable { } private void addListener(Class<?> eventType, Object target, Method method) { - if (eventRouter == null) { + if (!hasEventRouter()) { eventRouter = new EventRouter(); } eventRouter.addListener(eventType, target, method); } private void removeListener(Class<?> eventType, Object target, Method method) { - if (eventRouter != null) { + if (hasEventRouter()) { eventRouter.removeListener(eventType, target, method); } } @@ -599,7 +599,7 @@ public class Page implements Serializable { } private void fireEvent(EventObject event) { - if (eventRouter != null) { + if (hasEventRouter()) { eventRouter.fireEvent(event); } } @@ -776,8 +776,8 @@ public class Page implements Serializable { BrowserWindowResizeListener resizeListener) { removeListener(BrowserWindowResizeEvent.class, resizeListener, BROWSER_RESIZE_METHOD); - getState(true).hasResizeListeners = eventRouter - .hasListeners(BrowserWindowResizeEvent.class); + getState(true).hasResizeListeners = hasEventRouter() + && eventRouter.hasListeners(BrowserWindowResizeEvent.class); } /** @@ -1242,4 +1242,7 @@ public class Page implements Serializable { return state; } + private boolean hasEventRouter() { + return eventRouter != null; + } } diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java index 2ec747ba3a..197d9fe416 100644 --- a/server/src/com/vaadin/server/ServletPortletHelper.java +++ b/server/src/com/vaadin/server/ServletPortletHelper.java @@ -130,8 +130,7 @@ public class ServletPortletHelper implements Serializable { public static void initDefaultUIProvider(VaadinSession session, VaadinService vaadinService) throws ServiceException { String uiProperty = vaadinService.getDeploymentConfiguration() - .getApplicationOrSystemProperty(VaadinSession.UI_PARAMETER, - null); + .getUIClassName(); // Add provider for UI parameter first to give it lower priority // (providers are FILO) @@ -141,8 +140,7 @@ public class ServletPortletHelper implements Serializable { } String uiProviderProperty = vaadinService.getDeploymentConfiguration() - .getApplicationOrSystemProperty( - Constants.SERVLET_PARAMETER_UI_PROVIDER, null); + .getUIProviderClassName(); // Then add custom UI provider if defined if (uiProviderProperty != null) { UIProvider uiProvider = getUIProvider(uiProviderProperty, diff --git a/server/src/com/vaadin/server/VaadinPortletService.java b/server/src/com/vaadin/server/VaadinPortletService.java index 2b290b4cc4..cff024672c 100644 --- a/server/src/com/vaadin/server/VaadinPortletService.java +++ b/server/src/com/vaadin/server/VaadinPortletService.java @@ -124,9 +124,7 @@ public class VaadinPortletService extends VaadinService { @Override public String getConfiguredWidgetset(VaadinRequest request) { - String widgetset = getDeploymentConfiguration() - .getApplicationOrSystemProperty( - VaadinPortlet.PARAMETER_WIDGETSET, null); + String widgetset = getDeploymentConfiguration().getWidgetset(null); if (widgetset == null) { widgetset = getParameter(request, @@ -162,7 +160,11 @@ public class VaadinPortletService extends VaadinService { String staticFileLocation = getParameter(request, Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH, "/html"); - return trimTrailingSlashes(staticFileLocation); + if (Constants.PORTLET_CONTEXT.equals(staticFileLocation)) { + return request.getContextPath(); + } else{ + return trimTrailingSlashes(staticFileLocation); + } } private PortletContext getPortletContext() { diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index 8fd6da8dee..4d8e7e9bc9 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -155,7 +155,7 @@ public abstract class VaadinService implements Serializable { this.deploymentConfiguration = deploymentConfiguration; final String classLoaderName = getDeploymentConfiguration() - .getApplicationOrSystemProperty("ClassLoader", null); + .getClassLoaderName(); if (classLoaderName != null) { try { final Class<?> classLoaderClass = getClass().getClassLoader() @@ -448,7 +448,7 @@ public abstract class VaadinService implements Serializable { */ public void fireSessionDestroy(VaadinSession vaadinSession) { final VaadinSession session = vaadinSession; - session.accessSynchronously(new Runnable() { + session.access(new Runnable() { @Override public void run() { if (session.getState() == State.CLOSED) { diff --git a/server/src/com/vaadin/server/VaadinServletService.java b/server/src/com/vaadin/server/VaadinServletService.java index a4ff3943c9..8946ac4fae 100644 --- a/server/src/com/vaadin/server/VaadinServletService.java +++ b/server/src/com/vaadin/server/VaadinServletService.java @@ -118,9 +118,7 @@ public class VaadinServletService extends VaadinService { VaadinServletRequest servletRequest = (VaadinServletRequest) request; String staticFileLocation; // if property is defined in configurations, use that - staticFileLocation = getDeploymentConfiguration() - .getApplicationOrSystemProperty( - VaadinServlet.PARAMETER_VAADIN_RESOURCES, null); + staticFileLocation = getDeploymentConfiguration().getResourcesPath(); if (staticFileLocation != null) { return staticFileLocation; } @@ -159,8 +157,7 @@ public class VaadinServletService extends VaadinService { @Override public String getConfiguredWidgetset(VaadinRequest request) { - return getDeploymentConfiguration().getApplicationOrSystemProperty( - VaadinServlet.PARAMETER_WIDGETSET, + return getDeploymentConfiguration().getWidgetset( VaadinServlet.DEFAULT_WIDGETSET); } diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java index f93cb8e070..e5d63a6961 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -721,6 +721,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * {@link InheritableThreadLocal}). In other cases, (e.g. from background * threads started in some other way), the current session is not * automatically defined. + * <p> + * The session is stored using a weak reference to avoid leaking memory in + * case it is not explicitly cleared. * * @return the current session instance if available, otherwise * <code>null</code> @@ -741,9 +744,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * The application developer can also use this method to define the current * session outside the normal request handling and treads started from * request handling threads, e.g. when initiating custom background threads. - * </p> + * <p> + * The session is stored using a weak reference to avoid leaking memory in + * case it is not explicitly cleared. * * @param session + * the session to set as current * * @see #getCurrent() * @see ThreadLocal diff --git a/server/src/com/vaadin/server/WebBrowser.java b/server/src/com/vaadin/server/WebBrowser.java index 5ec4e6b19c..cb5979d612 100644 --- a/server/src/com/vaadin/server/WebBrowser.java +++ b/server/src/com/vaadin/server/WebBrowser.java @@ -264,6 +264,7 @@ public class WebBrowser implements Serializable { * @return true if the user is using Windows Phone, false if the user is not * using Windows Phone or if no information on the browser is * present + * @since 7.3.2 */ public boolean isWindowsPhone() { return browserDetails.isWindowsPhone(); @@ -290,6 +291,26 @@ public class WebBrowser implements Serializable { } /** + * Tests if the browser is run on IPhone. + * + * @return true if run on IPhone false if the user is not using IPhone or if + * no information on the browser is present + */ + public boolean isIPhone() { + return browserDetails.isIPhone(); + } + + /** + * Tests if the browser is run on IPad. + * + * @return true if run on IPad false if the user is not using IPad or if no + * information on the browser is present + */ + public boolean isIPad() { + return browserDetails.isIPad(); + } + + /** * Returns the browser-reported TimeZone offset in milliseconds from GMT. * This includes possible daylight saving adjustments, to figure out which * TimeZone the user actually might be in, see diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java index f8ef360eda..a274fbbb9b 100644 --- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java +++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java @@ -269,6 +269,7 @@ public class AtmospherePushConnection implements PushConnection { // the resource is already resumed; this is a bit hacky and should // be implemented in a better way in 7.2. resource = null; + state = State.DISCONNECTED; return; } diff --git a/server/src/com/vaadin/ui/AbstractField.java b/server/src/com/vaadin/ui/AbstractField.java index 47ac953319..369ad1253c 100644 --- a/server/src/com/vaadin/ui/AbstractField.java +++ b/server/src/com/vaadin/ui/AbstractField.java @@ -1402,7 +1402,8 @@ public abstract class AbstractField<T> extends AbstractComponent implements valueLocale); T newinternalValue = convertFromModel(convertedValue); if (!SharedUtil.equals(getInternalValue(), newinternalValue)) { - setConvertedValue(convertedValue); + setInternalValue(newinternalValue); + fireValueChange(false); } } } @@ -1512,6 +1513,19 @@ public abstract class AbstractField<T> extends AbstractComponent implements } /** + * 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 + */ + public void clear() { + setValue(null); + } + + /** * Is automatic, visible validation enabled? * * If automatic validation is enabled, any validators connected to this diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 76b82aa034..e58ad7bee5 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -359,7 +359,7 @@ public class Button extends AbstractComponent implements * No action is taken is the button is disabled. */ public void click() { - if (isEnabled() && !isReadOnly()) { + if (isConnectorEnabled() && !isReadOnly()) { fireClick(); } } diff --git a/server/src/com/vaadin/ui/Calendar.java b/server/src/com/vaadin/ui/Calendar.java index 59dfceec9b..63ac9fe35c 100644 --- a/server/src/com/vaadin/ui/Calendar.java +++ b/server/src/com/vaadin/ui/Calendar.java @@ -890,17 +890,21 @@ public class Calendar extends AbstractComponent implements * @see #isEventClickAllowed() */ protected boolean isClientChangeAllowed() { - return !isReadOnly() && isEnabled(); + return !isReadOnly(); } /** - * Is the user allowed to trigger click events + * Is the user allowed to trigger click events. Returns {@code true} by + * default. Subclass can override this method to disallow firing event + * clicks got from the client side. * * @return true if the client is allowed to click events * @see #isClientChangeAllowed() + * @deprecated Override {@link #fireEventClick(Integer)} instead. */ + @Deprecated protected boolean isEventClickAllowed() { - return isEnabled(); + return true; } /** diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java index 7f1aa1ce46..f4fe7fa66c 100644 --- a/server/src/com/vaadin/ui/CustomLayout.java +++ b/server/src/com/vaadin/ui/CustomLayout.java @@ -16,6 +16,7 @@ package com.vaadin.ui; +import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -101,22 +102,20 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent { protected void initTemplateContentsFromInputStream( InputStream templateStream) throws IOException { - InputStreamReader reader = new InputStreamReader(templateStream, - "UTF-8"); - StringBuilder b = new StringBuilder(BUFFER_SIZE); - - char[] cbuf = new char[BUFFER_SIZE]; - int offset = 0; - - while (true) { - int nrRead = reader.read(cbuf, offset, BUFFER_SIZE); - b.append(cbuf, 0, nrRead); - if (nrRead < BUFFER_SIZE) { - break; + BufferedReader reader = new BufferedReader(new InputStreamReader( + templateStream, "UTF-8")); + StringBuilder builder = new StringBuilder(BUFFER_SIZE); + try { + char[] cbuf = new char[BUFFER_SIZE]; + int nRead; + while ((nRead = reader.read(cbuf, 0, BUFFER_SIZE)) > 0) { + builder.append(cbuf, 0, nRead); } + } finally { + reader.close(); } - setTemplateContents(b.toString()); + setTemplateContents(builder.toString()); } @Override diff --git a/server/src/com/vaadin/ui/DateField.java b/server/src/com/vaadin/ui/DateField.java index e88d767bc9..030bd5f6c2 100644 --- a/server/src/com/vaadin/ui/DateField.java +++ b/server/src/com/vaadin/ui/DateField.java @@ -815,17 +815,15 @@ public class DateField extends AbstractField<Date> implements // Clone the instance final Calendar newCal = (Calendar) calendar.clone(); - // Assigns the current time tom calendar. - final Date currentDate = getValue(); - if (currentDate != null) { - newCal.setTime(currentDate); - } - final TimeZone currentTimeZone = getTimeZone(); if (currentTimeZone != null) { newCal.setTimeZone(currentTimeZone); } + final Date currentDate = getValue(); + if (currentDate != null) { + newCal.setTime(currentDate); + } return newCal; } diff --git a/server/src/com/vaadin/ui/Form.java b/server/src/com/vaadin/ui/Form.java index 391ee45536..48239b09e3 100644 --- a/server/src/com/vaadin/ui/Form.java +++ b/server/src/com/vaadin/ui/Form.java @@ -1064,7 +1064,7 @@ public class Form extends AbstractField<Object> implements Item.Editor, for (Object id : itemPropertyIds) { if (id != null) { Field<?> field = getField(id); - if (field.isEnabled() && !field.isReadOnly()) { + if (field.isConnectorEnabled() && !field.isReadOnly()) { return field; } } @@ -1202,6 +1202,21 @@ public class Form extends AbstractField<Object> implements Item.Editor, return true; } + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractField#clear() + */ + @Override + public void clear() { + for (Iterator<Field<?>> i = fields.values().iterator(); i.hasNext();) { + Field<?> f = i.next(); + if (f instanceof AbstractField) { + ((AbstractField<?>) f).clear(); + } + } + } + /** * Adding validators directly to form is not supported. * diff --git a/server/src/com/vaadin/ui/Table.java b/server/src/com/vaadin/ui/Table.java index 3a1ab82be5..34d48a9b18 100644 --- a/server/src/com/vaadin/ui/Table.java +++ b/server/src/com/vaadin/ui/Table.java @@ -422,61 +422,11 @@ public class Table extends AbstractSelect implements Action.Container, private Object currentPageFirstItemId = null; /* - * This class stores the hashcode and scroll position of the previous - * container so that the scroll position can be restored if the same - * container is removed and then re-added. This resolves #14581. + * If all rows get removed then scroll position of the previous container + * can be restored after re-adding/replacing rows via addAll(). This + * resolves #14581. */ - protected static class ScrollPositionRepairOnReAddAllRowsData implements - Serializable { - - private static final long serialVersionUID = 1L; - // current page first item index (to repair scroll position) - private int itemIndex; - /* - * hashCode() of container before it was cleared via - * container.removeAllItems(); - */ - private int containerHashCode; - - public ScrollPositionRepairOnReAddAllRowsData() { - itemIndex = -1; - containerHashCode = -1; - } - - public int getItemId() { - return itemIndex; - } - - public void setItemId(int itemId) { - itemIndex = itemId; - } - - public void resetItemId() { - itemIndex = -1; - } - - public void setContainerData(Container container) { - if (container != null) { - containerHashCode = container.hashCode(); - } else { - containerHashCode = -1; - } - } - - public boolean needRepairScrollPosition(Container newContainer) { - return (itemIndex != -1) && isTheSameContainer(newContainer); - } - - private boolean isTheSameContainer(Container newContainer) { - boolean theSame = false; - if (newContainer != null) { - theSame = (newContainer.hashCode() == containerHashCode); - } - return theSame; - } - } - - private final ScrollPositionRepairOnReAddAllRowsData scrollRepairOnReAdding = new ScrollPositionRepairOnReAddAllRowsData(); + private int repairOnReAddAllRowsDataScrollPositionItemIndex = -1; /** * Index of the first item on the current page. @@ -2734,10 +2684,6 @@ public class Table extends AbstractSelect implements Action.Container, newDataSource = new IndexedContainer(); } - if (scrollRepairOnReAdding != null) { - // this is important if container is set for table after filling - scrollRepairOnReAdding.setContainerData(newDataSource); - } Collection<Object> generated; if (columnGenerators != null) { generated = columnGenerators.keySet(); @@ -4571,14 +4517,22 @@ public class Table extends AbstractSelect implements Action.Container, int currentFirstItemIndex = getCurrentPageFirstItemIndex(); if (event.getContainer().size() == 0) { - scrollRepairOnReAdding.setItemId(getCurrentPageFirstItemIndex()); + repairOnReAddAllRowsDataScrollPositionItemIndex = getCurrentPageFirstItemIndex(); } else { - if (scrollRepairOnReAdding.needRepairScrollPosition(event - .getContainer())) { - currentFirstItemIndex = scrollRepairOnReAdding.getItemId(); + if (repairOnReAddAllRowsDataScrollPositionItemIndex != -1) { + currentFirstItemIndex = repairOnReAddAllRowsDataScrollPositionItemIndex; + /* + * Reset repairOnReAddAllRowsDataScrollPositionItemIndex. + * + * Next string should be commented (removed) if we want to have + * possibility to restore scroll position during adding items to + * container one by one via add() but not only addAll(). The + * problem in this case: we cannot track what happened between + * add() and add()... So it is ambiguous where to stop restore + * scroll position. + */ + repairOnReAddAllRowsDataScrollPositionItemIndex = -1; } - scrollRepairOnReAdding.resetItemId(); - scrollRepairOnReAdding.setContainerData(event.getContainer()); } // ensure that page still has first item in page, ignore buffer refresh diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index d67e08828a..438b086ec2 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -719,9 +719,11 @@ public abstract class UI extends AbstractSingleComponentContainer implements * The application developer can also use this method to define the current * UI outside the normal request handling, e.g. when initiating custom * background threads. - * </p> + * <p> + * The UI is stored using a weak reference to avoid leaking memory in case + * it is not explicitly cleared. * - * @param uI + * @param ui * the UI to register as the current UI * * @see #getCurrent() @@ -735,6 +737,9 @@ public abstract class UI extends AbstractSingleComponentContainer implements * Gets the currently used UI. The current UI is automatically defined when * processing requests to the server. In other cases, (e.g. from background * threads), the current UI is not automatically defined. + * <p> + * The UI is stored using a weak reference to avoid leaking memory in case + * it is not explicitly cleared. * * @return the current UI instance if available, otherwise <code>null</code> * diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java index 1c953779e4..693bd74dbf 100644 --- a/server/src/com/vaadin/ui/Upload.java +++ b/server/src/com/vaadin/ui/Upload.java @@ -1150,23 +1150,25 @@ public class Upload extends AbstractComponent implements Component.Focusable, fireUploadSuccess(event.getFileName(), event.getMimeType(), event.getContentLength()); endUpload(); - markAsDirty(); } @Override public void streamingFailed(StreamingErrorEvent event) { - Exception exception = event.getException(); - if (exception instanceof NoInputStreamException) { - fireNoInputStream(event.getFileName(), - event.getMimeType(), 0); - } else if (exception instanceof NoOutputStreamException) { - fireNoOutputStream(event.getFileName(), - event.getMimeType(), 0); - } else { - fireUploadInterrupted(event.getFileName(), - event.getMimeType(), 0, exception); + try { + Exception exception = event.getException(); + if (exception instanceof NoInputStreamException) { + fireNoInputStream(event.getFileName(), + event.getMimeType(), 0); + } else if (exception instanceof NoOutputStreamException) { + fireNoOutputStream(event.getFileName(), + event.getMimeType(), 0); + } else { + fireUploadInterrupted(event.getFileName(), + event.getMimeType(), 0, exception); + } + } finally { + endUpload(); } - endUpload(); } }; } |