diff options
Diffstat (limited to 'server/src/com')
19 files changed, 598 insertions, 505 deletions
diff --git a/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java b/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java index eafd3573bc..0bfec33957 100644 --- a/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java +++ b/server/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java @@ -701,7 +701,9 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical, */ @Override public int size() { - return container.size(); + int size = container.size(); + assert size >= 0; + return size; } /* diff --git a/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java b/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java index 483753da88..4bb4e4c1b2 100644 --- a/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java +++ b/server/src/com/vaadin/data/util/ContainerOrderedWrapper.java @@ -494,6 +494,7 @@ public class ContainerOrderedWrapper implements Container.Ordered, @Override public int size() { int newSize = container.size(); + assert newSize >= 0; if (lastKnownSize != -1 && newSize != lastKnownSize && !(container instanceof Container.ItemSetChangeNotifier)) { // Update the internal cache when the size of the container changes diff --git a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java index acf6a870c6..410eea3c01 100644 --- a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java +++ b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java @@ -103,6 +103,8 @@ import com.vaadin.ui.JavaScriptFunction; * <li>The primitive Java boolean and the boxed Boolean are represented by * JavaScript booleans.</li> * <li>Java Strings are represented by JavaScript strings.</li> + * <li>Java Dates are represented by JavaScript numbers containing the timestamp + * </li> * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li> * <li>Map<String, ?> in Java is represented by JavaScript object with fields * corresponding to the map keys.</li> diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 34c9b5b767..08b5b70f50 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.vaadin2"; + static final String REQUIRED_ATMOSPHERE_RUNTIME_VERSION = "2.1.2.vaadin3"; static final String INVALID_ATMOSPHERE_VERSION_WARNING = "\n" + "=================================================================\n" diff --git a/server/src/com/vaadin/server/JsonCodec.java b/server/src/com/vaadin/server/JsonCodec.java index 93074abcdb..34b05f73bf 100644 --- a/server/src/com/vaadin/server/JsonCodec.java +++ b/server/src/com/vaadin/server/JsonCodec.java @@ -1,12 +1,12 @@ /* * 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 @@ -56,7 +56,7 @@ import com.vaadin.ui.ConnectorTracker; /** * Decoder for converting RPC parameters and other values from JSON in transfer * between the client and the server and vice versa. - * + * * @since 7.0 */ public class JsonCodec implements Serializable { @@ -119,9 +119,9 @@ public class JsonCodec implements Serializable { public static Collection<FieldProperty> find(Class<?> type) throws IntrospectionException { - Collection<FieldProperty> properties = new ArrayList<FieldProperty>(); - Field[] fields = type.getFields(); + Collection<FieldProperty> properties = new ArrayList<FieldProperty>( + fields.length); for (Field field : fields) { if (!Modifier.isStatic(field.getModifiers())) { properties.add(new FieldProperty(field)); @@ -341,7 +341,7 @@ public class JsonCodec implements Serializable { * using the declared type. Otherwise only internal types are allowed in * collections. * </p> - * + * * @param targetType * The type that should be returned by this method * @param valueAndType @@ -471,13 +471,13 @@ public class JsonCodec implements Serializable { private static Map<Object, Object> decodeObjectMap(Type keyType, Type valueType, JSONArray jsonMap, ConnectorTracker connectorTracker) throws JSONException { - Map<Object, Object> map = new HashMap<Object, Object>(); JSONArray keys = jsonMap.getJSONArray(0); JSONArray values = jsonMap.getJSONArray(1); assert (keys.length() == values.length()); + Map<Object, Object> map = new HashMap<Object, Object>(keys.length() * 2); for (int i = 0; i < keys.length(); i++) { Object key = decodeInternalOrCustomType(keyType, keys.get(i), connectorTracker); @@ -580,8 +580,9 @@ public class JsonCodec implements Serializable { private static List<Object> decodeList(Type targetType, boolean restrictToInternalTypes, JSONArray jsonArray, ConnectorTracker connectorTracker) throws JSONException { - List<Object> list = new ArrayList<Object>(); - for (int i = 0; i < jsonArray.length(); ++i) { + int arrayLength = jsonArray.length(); + List<Object> list = new ArrayList<Object>(arrayLength); + for (int i = 0; i < arrayLength; ++i) { // each entry always has two elements: type and value Object encodedValue = jsonArray.get(i); Object decodedChild = decodeParametrizedType(targetType, @@ -754,7 +755,7 @@ public class JsonCodec implements Serializable { /** * Compares the value with the reference. If they match, returns true. - * + * * @param fieldValue * @param referenceValue * @return diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index e8cdcd7055..8d44ff74ed 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -1,12 +1,12 @@ /* * 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 @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; @@ -69,9 +70,9 @@ import com.vaadin.util.ReflectTools; /** * Provide deployment specific settings that are required outside terminal * specific code. - * + * * @author Vaadin Ltd. - * + * * @since 7.0 */ public abstract class VaadinService implements Serializable { @@ -144,7 +145,7 @@ public abstract class VaadinService implements Serializable { /** * Creates a new vaadin service based on a deployment configuration - * + * * @param deploymentConfiguration * the deployment configuration for the service */ @@ -172,7 +173,7 @@ public abstract class VaadinService implements Serializable { /** * Initializes this service. The service should be initialized before it is * used. - * + * * @since 7.1 * @throws ServiceException * if a problem occurs when creating the service @@ -191,7 +192,7 @@ public abstract class VaadinService implements Serializable { * called first. This enables overriding this method and using add on the * returned list to add a custom request handler which overrides any * predefined handler. - * + * * @return The list of request handlers used by this service. * @throws ServiceException * if a problem occurs when creating the request handlers @@ -214,13 +215,13 @@ public abstract class VaadinService implements Serializable { * Return the URL from where static files, e.g. the widgetset and the theme, * are served. In a standard configuration the VAADIN folder inside the * returned folder is what is used for widgetsets and themes. - * + * * The returned folder is usually the same as the context path and * independent of e.g. the servlet mapping. - * + * * @param request * the request for which the location should be determined - * + * * @return The location of static resources (should contain the VAADIN * directory). Never ends with a slash (/). */ @@ -229,7 +230,7 @@ public abstract class VaadinService implements Serializable { /** * Gets the widgetset that is configured for this deployment, e.g. from a * parameter in web.xml. - * + * * @param request * the request for which a widgetset is required * @return the name of the widgetset @@ -239,7 +240,7 @@ public abstract class VaadinService implements Serializable { /** * Gets the theme that is configured for this deployment, e.g. from a portal * parameter or just some sensible default value. - * + * * @param request * the request for which a theme is required * @return the name of the theme @@ -251,7 +252,7 @@ public abstract class VaadinService implements Serializable { * whether it will be included into some other context. A standalone UI may * do things that might interfere with other parts of a page, e.g. changing * the page title and requesting focus upon loading. - * + * * @param request * the request for which the UI is loaded * @return a boolean indicating whether the UI should be standalone @@ -262,9 +263,9 @@ public abstract class VaadinService implements Serializable { * Gets the class loader to use for loading classes loaded by name, e.g. * custom UI classes. This is by default the class loader that was used to * load the Servlet or Portlet class to which this service belongs. - * + * * @return the class loader to use, or <code>null</code> - * + * * @see #setClassLoader(ClassLoader) */ public ClassLoader getClassLoader() { @@ -277,10 +278,10 @@ public abstract class VaadinService implements Serializable { * any existing class loader hierarchy, e.g. by ensuring that a class loader * set for this service delegates to the previously set class loader if the * class is not found. - * + * * @param classLoader * the new class loader to set, not <code>null</code>. - * + * * @see #getClassLoader() */ public void setClassLoader(ClassLoader classLoader) { @@ -296,11 +297,11 @@ public abstract class VaadinService implements Serializable { * not known. The MIME type is determined by the configuration of the * container, and may be specified in a deployment descriptor. Common MIME * types are "text/html" and "image/gif". - * + * * @param resourceName * a String specifying the name of a file * @return a String specifying the file's MIME type - * + * * @see ServletContext#getMimeType(String) * @see PortletContext#getMimeType(String) */ @@ -308,7 +309,7 @@ public abstract class VaadinService implements Serializable { /** * Gets the deployment configuration. - * + * * @return the deployment configuration */ public DeploymentConfiguration getDeploymentConfiguration() { @@ -318,9 +319,9 @@ public abstract class VaadinService implements Serializable { /** * Sets the system messages provider to use for getting system messages to * display to users of this service. - * + * * @see #getSystemMessagesProvider() - * + * * @param systemMessagesProvider * the system messages provider; <code>null</code> is not * allowed. @@ -340,11 +341,11 @@ public abstract class VaadinService implements Serializable { * By default, the {@link DefaultSystemMessagesProvider} which always * provides the built-in default {@link SystemMessages} is used. * </p> - * + * * @see #setSystemMessagesProvider(SystemMessagesProvider) * @see SystemMessagesProvider * @see SystemMessages - * + * * @return the system messages provider; not <code>null</code> */ public SystemMessagesProvider getSystemMessagesProvider() { @@ -356,7 +357,7 @@ public abstract class VaadinService implements Serializable { * also be implemented to use information from current instances of various * objects, which means that this method might return different values for * the same locale under different circumstances. - * + * * @param locale * the desired locale for the system messages * @param request @@ -373,13 +374,13 @@ public abstract class VaadinService implements Serializable { /** * Returns the context base directory. - * + * * Typically an application is deployed in a such way that is has an * application directory. For web applications this directory is the root * directory of the web applications. In some cases applications might not * have an application directory (for example web applications running * inside a war). - * + * * @return The application base directory or null if the application has no * base directory. */ @@ -393,10 +394,10 @@ public abstract class VaadinService implements Serializable { * the listener is not necessarily notified immediately when the session is * created but only when the first request for that session is handled by * this service. - * + * * @see #removeSessionInitListener(SessionInitListener) * @see SessionInitListener - * + * * @param listener * the Vaadin service session initialization listener */ @@ -408,9 +409,9 @@ public abstract class VaadinService implements Serializable { /** * Removes a Vaadin service session initialization listener from this * service. - * + * * @see #addSessionInitListener(SessionInitListener) - * + * * @param listener * the Vaadin service session initialization listener to remove. */ @@ -425,9 +426,9 @@ public abstract class VaadinService implements Serializable { * <p> * The session being destroyed is locked and its UIs have been removed when * the listeners are called. - * + * * @see #addSessionInitListener(SessionInitListener) - * + * * @param listener * the vaadin service session destroy listener */ @@ -439,7 +440,7 @@ public abstract class VaadinService implements Serializable { /** * Handles destruction of the given session. Internally ensures proper * locking is done. - * + * * @param vaadinSession * The session to destroy */ @@ -485,9 +486,9 @@ public abstract class VaadinService implements Serializable { /** * Removes a Vaadin service session destroy listener from this service. - * + * * @see #addSessionDestroyListener(SessionDestroyListener) - * + * * @param listener * the vaadin service session destroy listener */ @@ -502,12 +503,12 @@ public abstract class VaadinService implements Serializable { * Handles locking of the session internally to avoid creation of duplicate * sessions by two threads simultaneously. * </p> - * + * * @param request * the request to get a vaadin service session for. - * + * * @see VaadinSession - * + * * @return the vaadin service session for the request, or <code>null</code> * if no session is found and this is a request for which a new * session shouldn't be created. @@ -529,7 +530,7 @@ public abstract class VaadinService implements Serializable { * Associates the given lock with this service and the given wrapped * session. This method should not be called more than once when the lock is * initialized for the session. - * + * * @see #getSessionLock(WrappedSession) * @param wrappedSession * The wrapped session the lock is associated with @@ -550,7 +551,7 @@ public abstract class VaadinService implements Serializable { /** * Returns the name used to store the lock in the HTTP session. - * + * * @return The attribute name for the lock */ private String getLockAttributeName() { @@ -564,7 +565,7 @@ public abstract class VaadinService implements Serializable { * This method uses the wrapped session instead of VaadinSession to be able * to lock even before the VaadinSession has been initialized. * </p> - * + * * @param wrappedSession * The wrapped session * @return A lock instance used for locking access to the wrapped session @@ -588,10 +589,10 @@ public abstract class VaadinService implements Serializable { /** * Locks the given session for this service instance. Typically you want to * call {@link VaadinSession#lock()} instead of this method. - * + * * @param wrappedSession * The session to lock - * + * * @throws IllegalStateException * if the session is invalidated before it can be locked */ @@ -631,7 +632,7 @@ public abstract class VaadinService implements Serializable { * Releases the lock for the given session for this service instance. * Typically you want to call {@link VaadinSession#unlock()} instead of this * method. - * + * * @param wrappedSession * The session to unlock */ @@ -666,7 +667,7 @@ public abstract class VaadinService implements Serializable { * Finds or creates a Vaadin session. Assumes necessary synchronization has * been done by the caller to ensure this is not called simultaneously by * several threads. - * + * * @param request * @param requestCanCreateSession * @return @@ -733,8 +734,8 @@ public abstract class VaadinService implements Serializable { /** * Creates and registers a new VaadinSession for this service. Assumes * proper locking has been taken care of by the caller. - * - * + * + * * @param request * The request which triggered session creation. * @return A new VaadinSession instance @@ -771,11 +772,11 @@ public abstract class VaadinService implements Serializable { * service. * <p> * This is only used to support legacy cases. - * + * * @param request * @return * @throws MalformedURLException - * + * * @deprecated As of 7.0. Only used to support {@link LegacyApplication}. */ @Deprecated @@ -786,12 +787,12 @@ public abstract class VaadinService implements Serializable { /** * Creates a new Vaadin session for this service and request - * + * * @param request * The request for which to create a VaadinSession * @return A new VaadinSession * @throws ServiceException - * + * */ protected VaadinSession createVaadinSession(VaadinRequest request) throws ServiceException { @@ -839,7 +840,7 @@ public abstract class VaadinService implements Serializable { /** * Retrieves the wrapped session for the request. - * + * * @param request * The request for which to retrieve a session * @param requestCanCreateSession @@ -862,7 +863,7 @@ public abstract class VaadinService implements Serializable { /** * Checks whether it's valid to create a new service session as a result of * the given request. - * + * * @param request * the request * @return <code>true</code> if it's valid to create a new service session @@ -877,10 +878,10 @@ public abstract class VaadinService implements Serializable { * {@link InheritableThreadLocal}). In other cases, (e.g. from background * threads started in some other way), the current service is not * automatically defined. - * + * * @return the current Vaadin service instance if available, otherwise * <code>null</code> - * + * * @see #setCurrentInstances(VaadinRequest, VaadinResponse) */ public static VaadinService getCurrent() { @@ -898,14 +899,14 @@ public abstract class VaadinService implements Serializable { * instances outside the normal request handling, e.g. when initiating * custom background threads. * </p> - * + * * @param request * the Vaadin request to set as the current request, or * <code>null</code> if no request should be set. * @param response * the Vaadin response to set as the current response, or * <code>null</code> if no response should be set. - * + * * @see #getCurrent() * @see #getCurrentRequest() * @see #getCurrentResponse() @@ -919,7 +920,7 @@ public abstract class VaadinService implements Serializable { /** * Sets the given Vaadin service as the current service. - * + * * @param service */ public static void setCurrent(VaadinService service) { @@ -931,10 +932,10 @@ public abstract class VaadinService implements Serializable { * automatically defined when the request is started. The current request * can not be used in e.g. background threads because of the way server * implementations reuse request instances. - * + * * @return the current Vaadin request instance if available, otherwise * <code>null</code> - * + * * @see #setCurrentInstances(VaadinRequest, VaadinResponse) */ public static VaadinRequest getCurrentRequest() { @@ -946,10 +947,10 @@ public abstract class VaadinService implements Serializable { * automatically defined when the request is started. The current response * can not be used in e.g. background threads because of the way server * implementations reuse response instances. - * + * * @return the current Vaadin response instance if available, otherwise * <code>null</code> - * + * * @see #setCurrentInstances(VaadinRequest, VaadinResponse) */ public static VaadinResponse getCurrentResponse() { @@ -961,7 +962,7 @@ public abstract class VaadinService implements Serializable { * different services of the same type but the same for corresponding * instances running in different JVMs in a cluster. This is typically based * on e.g. the configured servlet's or portlet's name. - * + * * @return the unique name of this service instance. */ public abstract String getServiceName(); @@ -972,11 +973,11 @@ public abstract class VaadinService implements Serializable { * related to any particular UI or have the UI information encoded in a * non-standard way. The returned UI is also set as the current UI ( * {@link UI#setCurrent(UI)}). - * + * * @param request * the request for which a UI is desired * @return the UI belonging to the request or null if no UI is found - * + * */ public UI findUI(VaadinRequest request) { // getForSession asserts that the lock is held @@ -1002,12 +1003,12 @@ public abstract class VaadinService implements Serializable { * typically checks the @{@link PreserveOnRefresh} annotation but UI * providers and ultimately VaadinService implementations may choose to * override the defaults. - * + * * @param provider * the UI provider responsible for the UI * @param event * the UI create event with details about the UI - * + * * @return <code>true</code> if the UI should be preserved on refresh; * <code>false</code> if a new UI instance should be initialized on * refreshed. @@ -1024,7 +1025,7 @@ public abstract class VaadinService implements Serializable { * Please note that this method makes certain assumptions about how data is * stored in the underlying session and may thus not be compatible with some * environments. - * + * * @param request * The Vaadin request for which the session should be * reinitialized @@ -1034,8 +1035,10 @@ public abstract class VaadinService implements Serializable { // Stores all attributes (security key, reference to this context // instance) so they can be added to the new session - HashMap<String, Object> attrs = new HashMap<String, Object>(); - for (String name : oldSession.getAttributeNames()) { + Set<String> attributeNames = oldSession.getAttributeNames(); + HashMap<String, Object> attrs = new HashMap<String, Object>( + attributeNames.size() * 2); + for (String name : attributeNames) { Object value = oldSession.getAttribute(name); if (value instanceof VaadinSession) { // set flag to avoid cleanup @@ -1076,9 +1079,9 @@ public abstract class VaadinService implements Serializable { /** * TODO PUSH Document - * + * * TODO Pass UI or VaadinSession? - * + * * @param uI * @param themeName * @param resource @@ -1090,14 +1093,14 @@ public abstract class VaadinService implements Serializable { /** * Creates and returns a unique ID for the DIV where the UI is to be * rendered. - * + * * @param session * The service session to which the bootstrapped UI will belong. * @param request * The request for which a div id is needed * @param uiClass * The class of the UI that will be bootstrapped - * + * * @return the id to use in the DOM */ public abstract String getMainDivId(VaadinSession session, @@ -1115,9 +1118,9 @@ public abstract class VaadinService implements Serializable { * To avoid causing out of sync errors, you should typically redirect to * some other page using {@link Page#setLocation(String)} to make the * browser unload the invalidated UI. - * + * * @see SystemMessages#getSessionExpiredCaption() - * + * * @param session * the session to close */ @@ -1129,7 +1132,7 @@ public abstract class VaadinService implements Serializable { * Called at the end of a request, after sending the response. Closes * inactive UIs in the given session, removes closed UIs from the session, * and closes the session if it is itself inactive. - * + * * @param session */ void cleanupSession(VaadinSession session) { @@ -1164,29 +1167,29 @@ public abstract class VaadinService implements Serializable { /** * Removes those UIs from the given session for which {@link UI#isClosing() * isClosing} yields true. - * + * * @param session */ private void removeClosedUIs(final VaadinSession session) { ArrayList<UI> uis = new ArrayList<UI>(session.getUIs()); for (final UI ui : uis) { - ui.accessSynchronously(new Runnable() { - @Override - public void run() { - if (ui.isClosing()) { + if (ui.isClosing()) { + ui.accessSynchronously(new Runnable() { + @Override + public void run() { getLogger().log(Level.FINER, "Removing closed UI {0}", ui.getUIId()); session.removeUI(ui); } - } - }); + }); + } } } /** * Closes those UIs in the given session for which {@link #isUIActive} * yields false. - * + * * @since 7.0.0 */ private void closeInactiveUIs(VaadinSession session) { @@ -1212,11 +1215,11 @@ public abstract class VaadinService implements Serializable { * session. This is a lower bound; it might take longer to close an inactive * UI. Returns a negative number if heartbeat is disabled and timeout never * occurs. - * + * * @see DeploymentConfiguration#getHeartbeatInterval() - * + * * @since 7.0.0 - * + * * @return The heartbeat timeout in seconds or a negative number if timeout * never occurs. */ @@ -1235,12 +1238,12 @@ public abstract class VaadinService implements Serializable { * requests suffice to keep the session alive, but it will still eventually * expire in the regular manner if there are no requests at all (see * {@link WrappedSession#getMaxInactiveInterval()}). - * + * * @see DeploymentConfiguration#isCloseIdleSessions() * @see #getHeartbeatTimeout() - * + * * @since 7.0.0 - * + * * @return The UIDL request timeout in seconds, or a negative number if * timeout never occurs. */ @@ -1257,12 +1260,12 @@ public abstract class VaadinService implements Serializable { * A UI is active if and only if its {@link UI#isClosing() isClosing} * returns false and {@link #getHeartbeatTimeout() getHeartbeatTimeout} is * negative or has not yet expired. - * + * * @since 7.0.0 - * + * * @param ui * The UI whose status to check - * + * * @return true if the UI is active, false if it could be removed. */ private boolean isUIActive(UI ui) { @@ -1282,10 +1285,10 @@ public abstract class VaadinService implements Serializable { * A session is active if and only if its {@link #isClosing} returns false * and {@link #getUidlRequestTimeout(VaadinSession) getUidlRequestTimeout} * is negative or has not yet expired. - * + * * @param session * The session whose status to check - * + * * @return true if the session is active, false if it could be closed. */ private boolean isSessionActive(VaadinSession session) { @@ -1305,7 +1308,7 @@ public abstract class VaadinService implements Serializable { /** * Called before the framework starts handling a request - * + * * @param request * The request * @param response @@ -1323,7 +1326,7 @@ public abstract class VaadinService implements Serializable { /** * Called after the framework has handled a request and the response has * been written. - * + * * @param request * The request object * @param response @@ -1335,23 +1338,16 @@ public abstract class VaadinService implements Serializable { public void requestEnd(VaadinRequest request, VaadinResponse response, VaadinSession session) { if (session != null) { - final VaadinSession finalSession = session; - - session.accessSynchronously(new Runnable() { - @Override - public void run() { - cleanupSession(finalSession); - } - }); - - final long duration = (System.nanoTime() - (Long) request - .getAttribute(REQUEST_START_TIME_ATTRIBUTE)) / 1000000; - session.accessSynchronously(new Runnable() { - @Override - public void run() { - finalSession.setLastRequestDuration(duration); - } - }); + assert VaadinSession.getCurrent() == session; + session.lock(); + try { + cleanupSession(session); + final long duration = (System.nanoTime() - (Long) request + .getAttribute(REQUEST_START_TIME_ATTRIBUTE)) / 1000000; + session.setLastRequestDuration(duration); + } finally { + session.unlock(); + } } CurrentInstance.clearAll(); } @@ -1360,11 +1356,11 @@ public abstract class VaadinService implements Serializable { * Returns the request handlers that are registered with this service. The * iteration order of the returned collection is the same as the order in * which the request handlers will be invoked when a request is handled. - * + * * @return a collection of request handlers in the order they are invoked - * + * * @see #createRequestHandlers() - * + * * @since 7.1 */ public Iterable<RequestHandler> getRequestHandlers() { @@ -1381,7 +1377,7 @@ public abstract class VaadinService implements Serializable { * request handler handles session expiration a default expiration message * will be written. * </p> - * + * * @param request * The incoming request * @param response @@ -1473,7 +1469,7 @@ public abstract class VaadinService implements Serializable { /** * Writes the given string as a response using the given content type. - * + * * @param response * The response reference * @param contentType @@ -1498,7 +1494,7 @@ public abstract class VaadinService implements Serializable { /** * Called when the session has expired and the request handling is therefore * aborted. - * + * * @param request * The request * @param response @@ -1553,7 +1549,7 @@ public abstract class VaadinService implements Serializable { /** * Creates a JSON message which, when sent to client as-is, will cause a * critical error to be shown with the given details. - * + * * @param caption * The caption of the error or null to omit * @param message @@ -1616,10 +1612,10 @@ public abstract class VaadinService implements Serializable { /** * Enables push if push support is available and push has not yet been * enabled. - * + * * If push support is not available, a warning explaining the situation will * be logged at least the first time this method is invoked. - * + * * @return <code>true</code> if push can be used; <code>false</code> if push * is not available. */ @@ -1638,7 +1634,7 @@ public abstract class VaadinService implements Serializable { * internally used by {@link VaadinSession#accessSynchronously(Runnable)} * and {@link UI#accessSynchronously(Runnable)} to help avoid causing * deadlocks. - * + * * @since 7.1 * @param session * the session that is being locked @@ -1657,7 +1653,7 @@ public abstract class VaadinService implements Serializable { * provided one for which the current thread holds a lock. This method might * not detect all cases where some other session is locked, but it should * cover the most typical situations. - * + * * @since 7.2 * @param session * the session that is expected to be locked @@ -1681,11 +1677,11 @@ public abstract class VaadinService implements Serializable { * to allow a certain type of testing. For these cases, the check can be * disabled by setting the init parameter * <code>disable-xsrf-protection</code> to <code>true</code>. - * + * * @see DeploymentConfiguration#isXsrfProtectionEnabled() - * + * * @since 7.1 - * + * * @param session * the vaadin session for which the check should be done * @param requestToken @@ -1712,15 +1708,15 @@ public abstract class VaadinService implements Serializable { * Implementation for {@link VaadinSession#access(Runnable)}. This method is * implemented here instead of in {@link VaadinSession} to enable overriding * the implementation without using a custom subclass of VaadinSession. - * + * * @since 7.1 * @see VaadinSession#access(Runnable) - * + * * @param session * the vaadin session to access * @param runnable * the runnable to run with the session locked - * + * * @return a future that can be used to check for task completion and to * cancel the task */ @@ -1739,7 +1735,7 @@ public abstract class VaadinService implements Serializable { * thread, the queue will be purged when the session is unlocked. If the * lock is not held by any thread, it is acquired and the queue is purged * right away. - * + * * @since 7.1.2 * @param session * the session for which the access queue should be purged @@ -1775,7 +1771,7 @@ public abstract class VaadinService implements Serializable { * <p> * This method is automatically run by the framework at appropriate * situations and is not intended to be used by application developers. - * + * * @param session * the vaadin session to purge the queue for * @since 7.1 @@ -1817,11 +1813,11 @@ public abstract class VaadinService implements Serializable { /** * Adds a service destroy listener that gets notified when this service is * destroyed. - * + * * @since 7.2 * @param listener * the service destroy listener to add - * + * * @see #destroy() * @see #removeServiceDestroyListener(ServiceDestroyListener) * @see ServiceDestroyListener @@ -1834,7 +1830,7 @@ public abstract class VaadinService implements Serializable { /** * Removes a service destroy listener that was previously added with * {@link #addServiceDestroyListener(ServiceDestroyListener)}. - * + * * @since 7.2 * @param listener * the service destroy listener to remove @@ -1848,11 +1844,11 @@ public abstract class VaadinService implements Serializable { * Called when the servlet, portlet or similar for this service is being * destroyed. After this method has been called, no more requests will be * handled by this service. - * + * * @see #addServiceDestroyListener(ServiceDestroyListener) * @see Servlet#destroy() * @see Portlet#destroy() - * + * * @since 7.2 */ public void destroy() { diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java index 12e7c28cd8..09b8a22a46 100644 --- a/server/src/com/vaadin/server/VaadinServlet.java +++ b/server/src/com/vaadin/server/VaadinServlet.java @@ -16,12 +16,14 @@ package com.vaadin.server; import java.io.BufferedWriter; +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; +import java.io.Serializable; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; @@ -29,7 +31,10 @@ import java.net.URLConnection; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; @@ -51,6 +56,59 @@ import com.vaadin.util.CurrentInstance; @SuppressWarnings("serial") public class VaadinServlet extends HttpServlet implements Constants { + private static class ScssCacheEntry implements Serializable { + + private final String css; + private final List<String> sourceUris; + private final long timestamp; + + public ScssCacheEntry(String css, List<String> sourceUris) { + this.css = css; + this.sourceUris = sourceUris; + + timestamp = getLastModified(); + } + + public String getCss() { + return css; + } + + private long getLastModified() { + long newest = 0; + for (String uri : sourceUris) { + File file = new File(uri); + if (!file.exists()) { + return -1; + } else { + newest = Math.max(newest, file.lastModified()); + } + } + + return newest; + } + + public boolean isStillValid() { + if (timestamp == -1) { + /* + * Don't ever bother checking anything if files used during the + * compilation were gone before the cache entry was created. + */ + return false; + } else if (timestamp != getLastModified()) { + /* + * Would in theory still be valid if the last modification is + * before the recorded timestamp, but that would still mean that + * something has changed since we last checked, so let's + * invalidate in that case as well to be on the safe side. + */ + return false; + } else { + return true; + } + } + + } + private VaadinServletService servletService; /** @@ -535,10 +593,18 @@ public class VaadinServlet extends HttpServlet implements Constants { * Mutex for preventing to scss compilations to take place simultaneously. * This is a workaround needed as the scss compiler currently is not thread * safe (#10292). + * <p> + * In addition, this is also used to protect the cached compilation results. */ private static final Object SCSS_MUTEX = new Object(); /** + * Global cache of scss compilation results. This map is protected from + * concurrent access by {@link #SCSS_MUTEX}. + */ + private static final Map<String, ScssCacheEntry> scssCache = new HashMap<String, ScssCacheEntry>(); + + /** * Returns the default theme. Must never return null. * * @return @@ -824,46 +890,62 @@ public class VaadinServlet extends HttpServlet implements Constants { } synchronized (SCSS_MUTEX) { - String realFilename = sc.getRealPath(scssFilename); - ScssStylesheet scss = ScssStylesheet.get(realFilename); - if (scss == null) { - // Not a file in the file system (WebContent directory). Use the - // identifier directly (VAADIN/themes/.../styles.css) so - // ScssStylesheet will try using the class loader. - if (scssFilename.startsWith("/")) { - scssFilename = scssFilename.substring(1); - } + ScssCacheEntry cacheEntry = scssCache.get(scssFilename); - scss = ScssStylesheet.get(scssFilename); + if (cacheEntry == null || !cacheEntry.isStillValid()) { + cacheEntry = compileScssOnTheFly(filename, scssFilename, sc); + scssCache.put(scssFilename, cacheEntry); } - if (scss == null) { - getLogger() - .log(Level.WARNING, - "Scss file {0} exists but ScssStylesheet was not able to find it", - scssFilename); - return false; - } - try { - getLogger().log(Level.FINE, "Compiling {0} for request to {1}", - new Object[] { realFilename, filename }); - scss.compile(); - } catch (Exception e) { - getLogger().log(Level.WARNING, "Scss compilation failed", e); + if (cacheEntry == null) { + // compilation did not produce any result, but logged a message return false; } // This is for development mode only so instruct the browser to - // never - // cache it + // never cache it response.setHeader("Cache-Control", "no-cache"); final String mimetype = getService().getMimeType(filename); - writeResponse(response, mimetype, scss.printState()); + writeResponse(response, mimetype, cacheEntry.getCss()); return true; } } + private ScssCacheEntry compileScssOnTheFly(String filename, + String scssFilename, ServletContext sc) throws IOException { + String realFilename = sc.getRealPath(scssFilename); + ScssStylesheet scss = ScssStylesheet.get(realFilename); + if (scss == null) { + // Not a file in the file system (WebContent directory). Use the + // identifier directly (VAADIN/themes/.../styles.css) so + // ScssStylesheet will try using the class loader. + if (scssFilename.startsWith("/")) { + scssFilename = scssFilename.substring(1); + } + + scss = ScssStylesheet.get(scssFilename); + } + + if (scss == null) { + getLogger() + .log(Level.WARNING, + "Scss file {0} exists but ScssStylesheet was not able to find it", + scssFilename); + return null; + } + try { + getLogger().log(Level.FINE, "Compiling {0} for request to {1}", + new Object[] { realFilename, filename }); + scss.compile(); + } catch (Exception e) { + getLogger().log(Level.WARNING, "Scss compilation failed", e); + return null; + } + + return new ScssCacheEntry(scss.printState(), scss.getSourceUris()); + } + /** * Check whether a URL obtained from a classloader refers to a valid static * resource in the directory VAADIN. diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java index bbabd881f8..2ab8c52dad 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -1,12 +1,12 @@ /* * 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 @@ -65,7 +65,7 @@ import com.vaadin.util.ReflectTools; * Everything inside a {@link VaadinSession} should be serializable to ensure * compatibility with schemes using serialization for persisting the session * data. - * + * * @author Vaadin Ltd * @since 7.0.0 */ @@ -77,7 +77,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * {@link VaadinSession#access(Runnable)}. This class is used internally by * the framework and is not intended to be directly used by application * developers. - * + * * @since 7.1 * @author Vaadin Ltd */ @@ -93,10 +93,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Creates an instance for the given runnable - * + * * @param session * the session to which the task belongs - * + * * @param runnable * the runnable to run when this task is purged from the * queue @@ -114,7 +114,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * deadlocks unless implemented very carefully. get(long, TimeUnit) * does not have the same detection since a sensible timeout should * avoid completely locking up the application. - * + * * Even though no deadlock could occur after the runnable has been * run, the check is always done as the deterministic behavior makes * it easier to detect potential problems. @@ -126,9 +126,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the current instance values that should be used when running * this task. - * + * * @see CurrentInstance#restoreInstances(Map) - * + * * @return a map of current instances. */ public Map<Class<?>, CurrentInstance> getCurrentInstances() { @@ -137,7 +137,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Handles exceptions thrown during the execution of this task. - * + * * @since 7.1.8 * @param exception * the thrown exception. @@ -168,7 +168,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * The lifecycle state of a VaadinSession. - * + * * @since 7.2 */ public enum State { @@ -273,7 +273,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Creates a new VaadinSession tied to a VaadinService. - * + * * @param service * the Vaadin service for the new session */ @@ -327,9 +327,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Get the web browser associated with this session. - * + * * @return the web browser object - * + * * @deprecated As of 7.0, use {@link Page#getWebBrowser()} instead. */ @Deprecated @@ -350,7 +350,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Sets the time spent servicing the last request in the session and updates * the total time spent servicing requests in this session. - * + * * @param time * The time spent in the last request, in milliseconds. */ @@ -371,11 +371,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Sets the time when the last UIDL request was serviced in this session. - * + * * @param timestamp * The time when the last request was handled, in milliseconds * since the epoch. - * + * */ public void setLastRequestTimestamp(long timestamp) { assert hasLock(); @@ -384,7 +384,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Returns the time when the last request was serviced in this session. - * + * * @return The time when the last request was handled, in milliseconds since * the epoch. */ @@ -396,7 +396,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the underlying session to which this service session is currently * associated. - * + * * @return the wrapped session for this context */ public WrappedSession getSession() { @@ -410,7 +410,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * @return - * + * * @deprecated As of 7.0. Will likely change or be removed in a future * version */ @@ -430,7 +430,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Loads the VaadinSession for the given service and WrappedSession from the * HTTP session. - * + * * @param service * The service the VaadinSession is associated with * @param underlyingSession @@ -460,7 +460,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Retrieves all {@link VaadinSession}s which are stored in the given HTTP * session - * + * * @since 7.2 * @param httpSession * the HTTP session @@ -485,7 +485,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Removes this VaadinSession from the HTTP session. - * + * * @param service * The service this session is associated with * @deprecated As of 7.0. Should be moved to a separate session storage @@ -500,7 +500,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Retrieves the name of the attribute used for storing a VaadinSession for * the given service. - * + * * @param service * The service associated with the sessio * @return The attribute name used for storing the session @@ -511,7 +511,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Stores this VaadinSession in the HTTP session. - * + * * @param service * The service this session is associated with * @param session @@ -564,7 +564,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the configuration for this session - * + * * @return the deployment configuration */ public DeploymentConfiguration getConfiguration() { @@ -574,10 +574,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the default locale for this session. - * + * * By default this is the preferred locale of the user using the session. In * most cases it is read from the browser defaults. - * + * * @return the locale of this session. */ public Locale getLocale() { @@ -590,13 +590,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Sets the default locale for this session. - * + * * By default this is the preferred locale of the user using the * application. In most cases it is read from the browser defaults. - * + * * @param locale * the Locale object. - * + * */ public void setLocale(Locale locale) { assert hasLock(); @@ -605,7 +605,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the session's error handler. - * + * * @return the current error handler */ public ErrorHandler getErrorHandler() { @@ -615,7 +615,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Sets the session error handler. - * + * * @param errorHandler */ public void setErrorHandler(ErrorHandler errorHandler) { @@ -626,9 +626,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the {@link ConverterFactory} used to locate a suitable * {@link Converter} for fields in the session. - * + * * See {@link #setConverterFactory(ConverterFactory)} for more details - * + * * @return The converter factory used in the session */ public ConverterFactory getConverterFactory() { @@ -653,7 +653,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * </p> * <p> * The converter factory must never be set to null. - * + * * @param converterFactory * The converter factory used in the session */ @@ -670,12 +670,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * Handlers are called in reverse order of addition, so the most recently * added handler will be called first. * </p> - * + * * @param handler * the request handler to add - * + * * @see #removeRequestHandler(RequestHandler) - * + * * @since 7.0 */ public void addRequestHandler(RequestHandler handler) { @@ -685,10 +685,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Removes a request handler from the session. - * + * * @param handler * the request handler to remove - * + * * @since 7.0 */ public void removeRequestHandler(RequestHandler handler) { @@ -700,13 +700,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * Gets the request handlers that are registered to the session. The * iteration order of the returned collection is the same as the order in * which the request handlers will be invoked when a request is handled. - * + * * @return a collection of request handlers, with the iteration order * according to the order they would be invoked - * + * * @see #addRequestHandler(RequestHandler) * @see #removeRequestHandler(RequestHandler) - * + * * @since 7.0 */ public Collection<RequestHandler> getRequestHandlers() { @@ -721,12 +721,12 @@ 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. - * + * * @return the current session instance if available, otherwise * <code>null</code> - * + * * @see #setCurrent(VaadinSession) - * + * * @since 7.0 */ public static VaadinSession getCurrent() { @@ -742,12 +742,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * session outside the normal request handling and treads started from * request handling threads, e.g. when initiating custom background threads. * </p> - * + * * @param session - * + * * @see #getCurrent() * @see ThreadLocal - * + * * @since 7.0 */ public static void setCurrent(VaadinSession session) { @@ -758,9 +758,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * Gets all the UIs of this session. This includes UIs that have been * requested but not yet initialized. UIs that receive no heartbeat requests * from the client are eventually removed from the session. - * + * * @return a collection of UIs belonging to this application - * + * * @since 7.0 */ public Collection<UI> getUIs() { @@ -775,11 +775,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Generate an id for the given Connector. Connectors must not call this * method more than once, the first time they need an id. - * + * * @param connector * A connector that has not yet been assigned an id. * @return A new id for the connector - * + * * @deprecated As of 7.0. Will likely change or be removed in a future * version */ @@ -794,7 +794,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * <p> * This is meant for framework internal use. * </p> - * + * * @param uiId * The UI id * @return The UI with the given id or null if not found @@ -806,7 +806,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Checks if the current thread has exclusive access to this VaadinSession - * + * * @return true if the thread has exclusive access, false otherwise */ public boolean hasLock() { @@ -817,7 +817,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Checks if the current thread has exclusive access to the given * WrappedSession. - * + * * @return true if this thread has exclusive access, false otherwise */ private static boolean hasLock(VaadinService service, WrappedSession session) { @@ -830,10 +830,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * be generated. This can be used to modify the contents of the HTML that * loads the Vaadin application in the browser and the HTTP headers that are * included in the response serving the HTML. - * + * * @see BootstrapListener#modifyBootstrapFragment(BootstrapFragmentResponse) * @see BootstrapListener#modifyBootstrapPage(BootstrapPageResponse) - * + * * @param listener * the bootstrap listener to add */ @@ -847,9 +847,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Remove a bootstrap listener that was previously added. - * + * * @see #addBootstrapListener(BootstrapListener) - * + * * @param listener * the bootstrap listener to remove */ @@ -865,11 +865,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * Fires a bootstrap event to all registered listeners. There are currently * two supported events, both inheriting from {@link BootstrapResponse}: * {@link BootstrapFragmentResponse} and {@link BootstrapPageResponse}. - * + * * @param response * the bootstrap response event for which listeners should be * fired - * + * * @deprecated As of 7.0. Will likely change or be removed in a future * version */ @@ -882,12 +882,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Called by the framework to remove an UI instance from the session because * it has been closed. - * + * * @param ui * the UI to remove */ public void removeUI(UI ui) { assert hasLock(); + assert UI.getCurrent() == ui; Integer id = Integer.valueOf(ui.getUIId()); ui.setSession(null); uIs.remove(id); @@ -902,7 +903,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * connector resources that are not served by any single connector because * e.g. because they are served with strong caching or because of legacy * reasons. - * + * * @param createOnDemand * <code>true</code> if a resource handler should be initialized * if there is no handler associated with this application. @@ -911,7 +912,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * @return this session's global resource handler, or <code>null</code> if * there is no handler and the createOnDemand parameter is * <code>false</code>. - * + * * @since 7.0.0 */ public GlobalResourceHandler getGlobalResourceHandler(boolean createOnDemand) { @@ -933,10 +934,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * instance is not guaranteed to support any other features of the * <code>Lock</code> interface than {@link Lock#lock()} and * {@link Lock#unlock()}. - * + * * @return the <code>Lock</code> that is used for synchronization, never * <code>null</code> - * + * * @see #lock() * @see Lock */ @@ -951,7 +952,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * is done correctly is to wrap your code using {@link UI#access(Runnable)} * (or {@link VaadinSession#access(Runnable)} if you are only touching the * session and not any UI), e.g.: - * + * * <pre> * myUI.access(new Runnable() { * @Override @@ -962,10 +963,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * } * }); * </pre> - * + * * If you for whatever reason want to do locking manually, you should do it * like: - * + * * <pre> * session.lock(); * try { @@ -974,12 +975,12 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * session.unlock(); * } * </pre> - * + * * This method will block until the lock can be retrieved. * <p> * {@link #getLockInstance()} can be used if more control over the locking * is required. - * + * * @see #unlock() * @see #getLockInstance() * @see #hasLock() @@ -995,7 +996,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * For UIs in this session that have its push mode set to * {@link PushMode#AUTOMATIC automatic}, pending changes will be pushed to * their respective clients. - * + * * @see #lock() * @see UI#push() */ @@ -1045,9 +1046,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * data with the current user so that it can be retrieved at a later point * from some other part of the application. Setting the value to * <code>null</code> clears the stored value. - * + * * @see #getAttribute(String) - * + * * @param name * the name to associate the value with, can not be * <code>null</code> @@ -1077,10 +1078,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * value. The outcome of calling this method is thus the same as if calling<br /> * <br /> * <code>setAttribute(type.getName(), value);</code> - * + * * @see #getAttribute(Class) * @see #setAttribute(String, Object) - * + * * @param type * the type that the stored value represents, can not be null * @param value @@ -1104,9 +1105,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * Gets a stored attribute value. If a value has been stored for the * session, that value is returned. If no value is stored for the name, * <code>null</code> is returned. - * + * * @see #setAttribute(String, Object) - * + * * @param name * the name of the value to get, can not be <code>null</code>. * @return the value, or <code>null</code> if no value has been stored or if @@ -1129,10 +1130,10 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * value. The outcome of calling this method is thus the same as if calling<br /> * <br /> * <code>getAttribute(type.getName());</code> - * + * * @see #setAttribute(Class, Object) * @see #getAttribute(String) - * + * * @param type * the type of the value to get, can not be <code>null</code>. * @return the value, or <code>null</code> if no value has been stored or if @@ -1153,7 +1154,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Creates a new unique id for a UI. - * + * * @return a unique UI id */ public int getNextUIid() { @@ -1163,7 +1164,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Adds an initialized UI to this session. - * + * * @param ui * the initialized UI to add. */ @@ -1197,7 +1198,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Adds a UI provider to this session. - * + * * @param uiProvider * the UI provider that should be added */ @@ -1208,7 +1209,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Removes a UI provider association from this session. - * + * * @param uiProvider * the UI provider that should be removed */ @@ -1219,7 +1220,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the UI providers configured for this session. - * + * * @return an unmodifiable list of UI providers */ public List<UIProvider> getUIProviders() { @@ -1243,9 +1244,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * To avoid causing out of sync errors, you should typically redirect to * some other page using {@link Page#setLocation(String)} to make the * browser unload the invalidated UI. - * + * * @see SystemMessages#getSessionExpiredCaption() - * + * */ public void close() { assert hasLock(); @@ -1255,13 +1256,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Returns whether this session is marked to be closed. Note that this * method also returns true if the session is actually already closed. - * + * * @see #close() - * + * * @deprecated As of 7.2, use * <code>{@link #getState() getState() != State.OPEN}</code> * instead. - * + * * @return true if this session is marked to be closed, false otherwise */ @Deprecated @@ -1272,7 +1273,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Returns the lifecycle state of this session. - * + * * @since 7.2 * @return the current state */ @@ -1284,7 +1285,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Sets the lifecycle state of this session. The allowed transitions are * OPEN to CLOSING and CLOSING to CLOSED. - * + * * @since 7.2 * @param state * the new state @@ -1323,15 +1324,15 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * later point in time.</li> * </ul> * </p> - * + * * @param runnable * the runnable which accesses the session - * + * * @throws IllegalStateException * if the current thread holds the lock for another session - * + * * @since 7.1 - * + * * @see #lock() * @see #getCurrent() * @see #access(Runnable) @@ -1385,14 +1386,14 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * an exception if it is detected that the current thread holds the lock for * some other session. * </p> - * + * * @see #lock() * @see #getCurrent() * @see #accessSynchronously(Runnable) * @see UI#access(Runnable) - * + * * @since 7.1 - * + * * @param runnable * the runnable which accesses the session * @return a future that can be used to check for task completion and to @@ -1406,9 +1407,9 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { * Gets the queue of tasks submitted using {@link #access(Runnable)}. It is * safe to call this method and access the returned queue without holding * the {@link #lock() session lock}. - * + * * @since 7.1 - * + * * @return the queue of pending access tasks */ public Queue<FutureAccess> getPendingAccessQueue() { @@ -1418,7 +1419,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Gets the CSRF token (aka double submit cookie) that is used to protect * against Cross Site Request Forgery attacks. - * + * * @since 7.1 * @return the csrf token string */ @@ -1439,13 +1440,13 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { /** * Finds the UI with the corresponding embed id. - * + * * @since 7.2 * @param embedId * the embed id * @return the UI with the corresponding embed id, or <code>null</code> if * no UI is found - * + * * @see UI#getEmbedId() */ public UI getUIByEmbedId(String embedId) { diff --git a/server/src/com/vaadin/server/communication/LegacyUidlWriter.java b/server/src/com/vaadin/server/communication/LegacyUidlWriter.java index 43ea1aca67..3f70a25c5b 100644 --- a/server/src/com/vaadin/server/communication/LegacyUidlWriter.java +++ b/server/src/com/vaadin/server/communication/LegacyUidlWriter.java @@ -1,12 +1,12 @@ /* * 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 @@ -35,7 +35,7 @@ import com.vaadin.ui.UI; /** * Serializes legacy UIDL changes to JSON. - * + * * @author Vaadin Ltd * @since 7.1 */ @@ -44,7 +44,7 @@ public class LegacyUidlWriter implements Serializable { /** * Writes a JSON array containing the changes of all dirty * {@link LegacyComponent}s in the given UI. - * + * * @param ui * The {@link UI} whose legacy changes to write * @param writer @@ -60,7 +60,8 @@ public class LegacyUidlWriter implements Serializable { Collection<ClientConnector> dirtyVisibleConnectors = ui .getConnectorTracker().getDirtyVisibleConnectors(); - List<Component> legacyComponents = new ArrayList<Component>(); + List<Component> legacyComponents = new ArrayList<Component>( + dirtyVisibleConnectors.size()); for (ClientConnector connector : dirtyVisibleConnectors) { // All Components that want to use paintContent must implement // LegacyComponent diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java index 983ada3279..5a7ae5b3e8 100644 --- a/server/src/com/vaadin/server/communication/PushHandler.java +++ b/server/src/com/vaadin/server/communication/PushHandler.java @@ -1,12 +1,12 @@ /* * 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 @@ -48,7 +48,7 @@ import com.vaadin.ui.UI; /** * Establishes bidirectional ("push") communication channels - * + * * @author Vaadin Ltd * @since 7.1 */ @@ -194,7 +194,7 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter { /** * Find the UI for the atmosphere resource, lock it and invoke the callback. - * + * * @param resource * the atmosphere resource for the current request * @param callback @@ -211,6 +211,8 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter { try { try { session = service.findVaadinSession(vaadinRequest); + assert VaadinSession.getCurrent() == session; + } catch (ServiceException e) { getLogger().log(Level.SEVERE, "Could not get session. This should never happen", e); @@ -231,9 +233,9 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter { UI ui = null; session.lock(); try { - VaadinSession.setCurrent(session); - // Sets UI.currentInstance ui = service.findUI(vaadinRequest); + assert UI.getCurrent() == ui; + if (ui == null) { sendNotificationAndDisconnect(resource, UidlRequestHandler.getUINotFoundErrorJSON(service, @@ -417,10 +419,10 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter { * two push connections which try to use the same UI. Using the * AtmosphereResource directly guarantees the message goes to the correct * recipient. - * + * * @param resource * The atmosphere resource to send refresh to - * + * */ private static void sendRefreshAndDisconnect(AtmosphereResource resource) throws IOException { diff --git a/server/src/com/vaadin/server/communication/PushRequestHandler.java b/server/src/com/vaadin/server/communication/PushRequestHandler.java index db14e73c1a..308f94686f 100644 --- a/server/src/com/vaadin/server/communication/PushRequestHandler.java +++ b/server/src/com/vaadin/server/communication/PushRequestHandler.java @@ -1,12 +1,12 @@ /* * 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 @@ -47,7 +47,7 @@ import com.vaadin.shared.communication.PushConstants; * Handles requests to open a push (bidirectional) communication channel between * the client and the server. After the initial request, communication through * the push channel is managed by {@link PushHandler}. - * + * * @author Vaadin Ltd * @since 7.1 */ @@ -66,7 +66,8 @@ public class PushRequestHandler implements RequestHandler, public PushRequestHandler(VaadinServletService service) throws ServiceException { - final ServletConfig config = service.getServlet().getServletConfig(); + final ServletConfig vaadinServletConfig = service.getServlet() + .getServletConfig(); atmosphere = new AtmosphereFramework() { @Override @@ -77,7 +78,7 @@ public class PushRequestHandler implements RequestHandler, @Override public AtmosphereFramework addInitParameter(String name, String value) { - if (config.getInitParameter(name) == null) { + if (vaadinServletConfig.getInitParameter(name) == null) { super.addInitParameter(name, value); } return this; @@ -117,7 +118,7 @@ public class PushRequestHandler implements RequestHandler, "org.atmosphere.cpr.showSupportMessage", "false"); try { - atmosphere.init(config); + atmosphere.init(vaadinServletConfig); // Ensure the client-side knows how to split the message stream // into individual messages when using certain transports diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index 36bfc8bcc6..9107a4e049 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -1,12 +1,12 @@ /* * 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 @@ -55,7 +55,7 @@ import com.vaadin.ui.UI; /** * Handles a client-to-server message containing serialized {@link ServerRpc * server RPC} invocations. - * + * * @author Vaadin Ltd * @since 7.1 */ @@ -64,7 +64,7 @@ public class ServerRpcHandler implements Serializable { /** * A data transfer object representing an RPC request sent by the client * side. - * + * * @since 7.2 * @author Vaadin Ltd */ @@ -78,7 +78,13 @@ public class ServerRpcHandler implements Serializable { public RpcRequest(String jsonString, VaadinRequest request) throws JSONException { json = new JSONObject(jsonString); - csrfToken = json.getString(ApplicationConstants.CSRF_TOKEN); + + String csrfToken = json.optString(ApplicationConstants.CSRF_TOKEN); + if (csrfToken.equals("")) { + csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; + } + this.csrfToken = csrfToken; + if (request.getService().getDeploymentConfiguration() .isSyncIdCheckEnabled()) { syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID); @@ -91,7 +97,7 @@ public class ServerRpcHandler implements Serializable { /** * Gets the CSRF security token (double submit cookie) for this request. - * + * * @return the CSRF security token for this current change request */ public String getCsrfToken() { @@ -100,7 +106,7 @@ public class ServerRpcHandler implements Serializable { /** * Gets the data to recreate the RPC as requested by the client side. - * + * * @return the data describing which RPC should be made, and all their * data */ @@ -110,7 +116,7 @@ public class ServerRpcHandler implements Serializable { /** * Gets the sync id last seen by the client. - * + * * @return the last sync id given by the server, according to the * client's request */ @@ -124,9 +130,9 @@ public class ServerRpcHandler implements Serializable { * <p> * <em>Note:</em> This is a shared reference - any modifications made * will be shared. - * + * * @return the raw JSON object that was received from the client - * + * */ public JSONObject getRawJson() { return json; @@ -138,7 +144,7 @@ public class ServerRpcHandler implements Serializable { /** * Reads JSON containing zero or more serialized RPC calls (including legacy * variable changes) and executes the calls. - * + * * @param ui * The {@link UI} receiving the calls. Cannot be null. * @param reader @@ -188,7 +194,7 @@ public class ServerRpcHandler implements Serializable { * changeVariables() is only called once for them. This preserves the Vaadin * 6 semantics for components and add-ons that do not use Vaadin 7 RPC * directly. - * + * * @param uI * the UI receiving the invocations data * @param lastSyncIdSeenByClient @@ -318,7 +324,7 @@ public class ServerRpcHandler implements Serializable { /** * Parse JSON from the client into a list of MethodInvocation instances. - * + * * @param connectorTracker * The ConnectorTracker used to lookup connectors * @param invocationsJson @@ -333,11 +339,13 @@ public class ServerRpcHandler implements Serializable { private List<MethodInvocation> parseInvocations( ConnectorTracker connectorTracker, JSONArray invocationsJson, int lastSyncIdSeenByClient) throws JSONException { - ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>(); + int invocationCount = invocationsJson.length(); + ArrayList<MethodInvocation> invocations = new ArrayList<MethodInvocation>( + invocationCount); MethodInvocation previousInvocation = null; // parse JSON to MethodInvocations - for (int i = 0; i < invocationsJson.length(); ++i) { + for (int i = 0; i < invocationCount; ++i) { JSONArray invocationJson = invocationsJson.getJSONArray(i); @@ -500,7 +508,7 @@ public class ServerRpcHandler implements Serializable { /** * Generates an error message when the client is trying to to something * ('what') with a connector which is disabled or invisible. - * + * * @since 7.1.8 * @param connector * the connector which is disabled (or invisible) diff --git a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java index d6e232035b..f3cbf47b62 100644 --- a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java +++ b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java @@ -116,6 +116,8 @@ import com.vaadin.shared.ui.JavaScriptComponentState; * <li>The primitive Java boolean and the boxed Boolean are represented by * JavaScript booleans.</li> * <li>Java Strings are represented by JavaScript strings.</li> + * <li>Java Dates are represented by JavaScript numbers containing the timestamp + * </li> * <li>List, Set and all arrays in Java are represented by JavaScript arrays.</li> * <li>Map<String, ?> in Java is represented by JavaScript object with fields * corresponding to the map keys.</li> diff --git a/server/src/com/vaadin/ui/AbstractSelect.java b/server/src/com/vaadin/ui/AbstractSelect.java index b8db329906..b083db3183 100644 --- a/server/src/com/vaadin/ui/AbstractSelect.java +++ b/server/src/com/vaadin/ui/AbstractSelect.java @@ -759,7 +759,9 @@ public abstract class AbstractSelect extends AbstractField<Object> implements */ @Override public int size() { - return items.size(); + int size = items.size(); + assert size >= 0; + return size; } /** diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java index 048726dc84..5367505c56 100644 --- a/server/src/com/vaadin/ui/ComboBox.java +++ b/server/src/com/vaadin/ui/ComboBox.java @@ -354,6 +354,7 @@ public class ComboBox extends AbstractSelect implements if (pageLength == 0) { // no paging: return all items filteredSize = container.size(); + assert filteredSize >= 0; return new ArrayList<Object>(container.getItemIds()); } @@ -391,6 +392,7 @@ public class ComboBox extends AbstractSelect implements } filteredSize = container.size(); + assert filteredSize >= 0; currentPage = adjustCurrentPage(currentPage, needNullSelectOption, indexToEnsureInView, filteredSize); int first = getFirstItemIndexOnCurrentPage(needNullSelectOption, diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index b5a0227d99..9b8729f779 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -1,12 +1,12 @@ /* * 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 @@ -55,10 +55,10 @@ import com.vaadin.server.StreamVariable; * operation new information needs to be sent to its * {@link com.vaadin.client.ServerConnector}. * </p> - * + * * @author Vaadin Ltd * @since 7.0.0 - * + * */ public class ConnectorTracker implements Serializable { @@ -87,7 +87,7 @@ public class ConnectorTracker implements Serializable { /** * Map to track on which syncId each connector was removed. - * + * * @see #getCurrentSyncId() * @see #cleanConcurrentlyRemovedConnectorIds(long) */ @@ -95,9 +95,9 @@ public class ConnectorTracker implements Serializable { /** * Gets a logger for this class - * + * * @return A logger instance for logging within this class - * + * */ public static Logger getLogger() { return Logger.getLogger(ConnectorTracker.class.getName()); @@ -107,7 +107,7 @@ public class ConnectorTracker implements Serializable { * Creates a new ConnectorTracker for the given uI. A tracker is always * attached to a uI and the uI cannot be changed during the lifetime of a * {@link ConnectorTracker}. - * + * * @param uI * The uI to attach to. Cannot be null. */ @@ -121,7 +121,7 @@ public class ConnectorTracker implements Serializable { * The lookup method {@link #getConnector(String)} only returns registered * connectors. * </p> - * + * * @param connector * The connector to register. */ @@ -157,12 +157,12 @@ public class ConnectorTracker implements Serializable { /** * Unregister the given connector. - * + * * <p> * The lookup method {@link #getConnector(String)} only returns registered * connectors. * </p> - * + * * @param connector * The connector to unregister */ @@ -213,7 +213,7 @@ public class ConnectorTracker implements Serializable { * Checks whether the given connector has already been initialized in the * browser. The given connector should be registered with this connector * tracker. - * + * * @param connector * the client connector to check * @return <code>true</code> if the initial state has previously been sent @@ -228,9 +228,9 @@ public class ConnectorTracker implements Serializable { /** * Marks the given connector as initialized, meaning that the client-side * state has been initialized for the connector. - * + * * @see #isClientSideInitialized(ClientConnector) - * + * * @param connector * the connector that should be marked as initialized */ @@ -242,7 +242,7 @@ public class ConnectorTracker implements Serializable { * Marks all currently registered connectors as uninitialized. This should * be done when the client-side has been reset but the server-side state is * retained. - * + * * @see #isClientSideInitialized(ClientConnector) */ public void markAllClientSidesUninitialized() { @@ -252,7 +252,7 @@ public class ConnectorTracker implements Serializable { /** * Gets a connector by its id. - * + * * @param connectorId * The connector id to look for * @return The connector with the given id or null if no connector has the @@ -400,10 +400,10 @@ public class ConnectorTracker implements Serializable { /** * Mark the connector as dirty. This should not be done while the response * is being written. - * + * * @see #getDirtyConnectors() * @see #isWritingResponse() - * + * * @param connector * The connector that should be marked clean. */ @@ -425,7 +425,7 @@ public class ConnectorTracker implements Serializable { /** * Mark the connector as clean. - * + * * @param connector * The connector that should be marked clean. */ @@ -443,7 +443,7 @@ public class ConnectorTracker implements Serializable { /** * Returns {@link #getConnectorString(ClientConnector)} for the connector * and its parent (if it has a parent). - * + * * @param connector * The connector * @return A string describing the connector and its parent @@ -460,7 +460,7 @@ public class ConnectorTracker implements Serializable { /** * Returns a string with the connector name and id. Useful mostly for * debugging and logging. - * + * * @param connector * The connector * @return A string that describes the connector @@ -500,7 +500,7 @@ public class ConnectorTracker implements Serializable { /** * Marks all visible connectors dirty, starting from the given connector and * going downwards in the hierarchy. - * + * * @param c * The component to start iterating downwards from */ @@ -521,7 +521,7 @@ public class ConnectorTracker implements Serializable { * The state and pending RPC calls for dirty connectors are sent to the * client in the following request. * </p> - * + * * @return A collection of all dirty connectors for this uI. This list may * contain invisible connectors. */ @@ -531,7 +531,7 @@ public class ConnectorTracker implements Serializable { /** * Checks if there a dirty connectors. - * + * * @return true if there are dirty connectors, false otherwise */ public boolean hasDirtyConnectors() { @@ -541,17 +541,19 @@ public class ConnectorTracker implements Serializable { /** * Returns a collection of those {@link #getDirtyConnectors() dirty * connectors} that are actually visible to the client. - * + * * @return A list of dirty and visible connectors. */ public ArrayList<ClientConnector> getDirtyVisibleConnectors() { - ArrayList<ClientConnector> dirtyConnectors = new ArrayList<ClientConnector>(); - for (ClientConnector c : getDirtyConnectors()) { + Collection<ClientConnector> dirtyConnectors = getDirtyConnectors(); + ArrayList<ClientConnector> dirtyVisibleConnectors = new ArrayList<ClientConnector>( + dirtyConnectors.size()); + for (ClientConnector c : dirtyConnectors) { if (LegacyCommunicationManager.isConnectorVisibleToClient(c)) { - dirtyConnectors.add(c); + dirtyVisibleConnectors.add(c); } } - return dirtyConnectors; + return dirtyVisibleConnectors; } public JSONObject getDiffState(ClientConnector connector) { @@ -571,10 +573,10 @@ public class ConnectorTracker implements Serializable { /** * Checks whether the response is currently being written. Connectors can * not be marked as dirty when a response is being written. - * + * * @see #setWritingResponse(boolean) * @see #markDirty(ClientConnector) - * + * * @return <code>true</code> if the response is currently being written, * <code>false</code> if outside the response writing phase. */ @@ -590,14 +592,14 @@ public class ConnectorTracker implements Serializable { * {@link #getCurrentSyncId()}), if {@link #isWritingResponse()} returns * <code>false</code> and <code>writingResponse</code> is set to * <code>true</code>. - * + * * @param writingResponse * the new response status. - * + * * @see #markDirty(ClientConnector) * @see #isWritingResponse() * @see #getCurrentSyncId() - * + * * @throws IllegalArgumentException * if the new response status is the same as the previous value. * This is done to help detecting problems caused by missed @@ -625,7 +627,7 @@ public class ConnectorTracker implements Serializable { // Convert JSONObjects in diff state to String representation as // JSONObject is not serializable HashMap<ClientConnector, String> stringDiffStates = new HashMap<ClientConnector, String>( - diffStates.size()); + diffStates.size() * 2); for (ClientConnector key : diffStates.keySet()) { stringDiffStates.put(key, diffStates.get(key).toString()); } @@ -643,7 +645,8 @@ public class ConnectorTracker implements Serializable { @SuppressWarnings("unchecked") HashMap<ClientConnector, String> stringDiffStates = (HashMap<ClientConnector, String>) in .readObject(); - diffStates = new HashMap<ClientConnector, JSONObject>(); + diffStates = new HashMap<ClientConnector, JSONObject>( + stringDiffStates.size() * 2); for (ClientConnector key : stringDiffStates.keySet()) { try { diffStates.put(key, new JSONObject(stringDiffStates.get(key))); @@ -657,7 +660,7 @@ public class ConnectorTracker implements Serializable { /** * Checks if the indicated connector has a StreamVariable of the given name * and returns the variable if one is found. - * + * * @param connectorId * @param variableName * @return variable if a matching one exists, otherwise null @@ -678,7 +681,7 @@ public class ConnectorTracker implements Serializable { /** * Adds a StreamVariable of the given name to the indicated connector. - * + * * @param connectorId * @param variableName * @param variable @@ -734,7 +737,7 @@ public class ConnectorTracker implements Serializable { /** * Removes any StreamVariable of the given name from the indicated * connector. - * + * * @param connectorId * @param variableName */ @@ -752,7 +755,7 @@ public class ConnectorTracker implements Serializable { /** * Returns the security key associated with the given StreamVariable. - * + * * @param variable * @return matching security key if one exists, null otherwise */ @@ -767,7 +770,7 @@ public class ConnectorTracker implements Serializable { * Check whether a connector was present on the client when the it was * creating this request, but was removed server-side before the request * arrived. - * + * * @since 7.2 * @param connectorId * The connector id to check for whether it was removed @@ -827,7 +830,7 @@ public class ConnectorTracker implements Serializable { * <p> * The sync id value <code>-1</code> is ignored to facilitate testing with * pre-recorded requests. - * + * * @see #setWritingResponse(boolean) * @see #connectorWasPresentAsRequestWasSent(String, long) * @since 7.2 @@ -853,7 +856,7 @@ public class ConnectorTracker implements Serializable { * <p> * The sync id value <code>-1</code> is ignored to facilitate testing with * pre-recorded requests. - * + * * @see #connectorWasPresentAsRequestWasSent(String, long) * @since 7.2 * @param lastSyncIdSeenByClient diff --git a/server/src/com/vaadin/ui/Upload.java b/server/src/com/vaadin/ui/Upload.java index 869c32751a..4c248d68ae 100644 --- a/server/src/com/vaadin/ui/Upload.java +++ b/server/src/com/vaadin/ui/Upload.java @@ -1,12 +1,12 @@ /* * 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 @@ -35,16 +35,16 @@ import com.vaadin.util.ReflectTools; /** * Component for uploading files from client to server. - * + * * <p> * The visible component consists of a file name input box and a browse button * and an upload submit button to start uploading. - * + * * <p> * The Upload component needs a java.io.OutputStream to write the uploaded data. * You need to implement the Upload.Receiver interface and return the output * stream in the receiveUpload() method. - * + * * <p> * You can get an event regarding starting (StartedEvent), progress * (ProgressEvent), and finishing (FinishedEvent) of upload by implementing @@ -52,22 +52,22 @@ import com.vaadin.util.ReflectTools; * FinishedListener is called for both failed and succeeded uploads. If you wish * to separate between these two cases, you can use SucceededListener * (SucceededEvenet) and FailedListener (FailedEvent). - * + * * <p> * The upload component does not itself show upload progress, but you can use * the ProgressIndicator for providing progress feedback by implementing * ProgressListener and updating the indicator in updateProgress(). - * + * * <p> * Setting upload component immediate initiates the upload as soon as a file is * selected, instead of the common pattern of file selection field and upload * button. - * + * * <p> * Note! Because of browser dependent implementations of <input type="file"> * element, setting size for Upload component is not supported. For some * browsers setting size may work to some extend. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -112,7 +112,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Creates a new instance of Upload. - * + * * The receiver must be set before performing an upload. */ public Upload() { @@ -132,7 +132,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Invoked when the value of a variable has changed. - * + * * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object, * java.util.Map) */ @@ -150,7 +150,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Paints the content of this component. - * + * * @param target * Target to paint the content on. * @throws PaintException @@ -189,7 +189,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Interface that must be implemented by the upload receivers to provide the * Upload component an output stream to write the uploaded data. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -197,7 +197,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Invoked when a new upload arrives. - * + * * @param filename * the desired filename of the upload, usually as specified * by the client. @@ -242,7 +242,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, * of whether the reception was successful or failed. If you wish to * distinguish between the two cases, use either SucceededEvent or * FailedEvent, which are both subclasses of the FinishedEvent. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -264,7 +264,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, private final String filename; /** - * + * * @param source * the source of the file. * @param filename @@ -284,7 +284,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Uploads where the event occurred. - * + * * @return the Source of the event. */ public Upload getUpload() { @@ -293,7 +293,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the file name. - * + * * @return the filename. */ public String getFilename() { @@ -302,7 +302,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the MIME Type of the file. - * + * * @return the MIME type. */ public String getMIMEType() { @@ -311,7 +311,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the length of the file. - * + * * @return the length. */ public long getLength() { @@ -323,7 +323,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload.FailedEvent event is sent when the upload is received, but the * reception is interrupted for some reason. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -332,7 +332,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, private Exception reason = null; /** - * + * * @param source * @param filename * @param MIMEType @@ -346,7 +346,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, } /** - * + * * @param source * @param filename * @param MIMEType @@ -360,7 +360,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the exception that caused the failure. - * + * * @return the exception that caused the failure, null if n/a */ public Exception getReason() { @@ -375,7 +375,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, public static class NoOutputStreamEvent extends FailedEvent { /** - * + * * @param source * @param filename * @param MIMEType @@ -393,7 +393,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, public static class NoInputStreamEvent extends FailedEvent { /** - * + * * @param source * @param filename * @param MIMEType @@ -409,14 +409,14 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload.SucceededEvent event is sent when the upload is received * successfully. - * + * * @author Vaadin Ltd. * @since 3.0 */ public static class SucceededEvent extends FinishedEvent { /** - * + * * @param source * @param filename * @param MIMEType @@ -431,7 +431,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload.StartedEvent event is sent when the upload is started to received. - * + * * @author Vaadin Ltd. * @since 5.0 */ @@ -445,7 +445,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, private final long length; /** - * + * * @param source * @param filename * @param MIMEType @@ -461,7 +461,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Uploads where the event occurred. - * + * * @return the Source of the event. */ public Upload getUpload() { @@ -470,7 +470,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the file name. - * + * * @return the filename. */ public String getFilename() { @@ -479,7 +479,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the MIME Type of the file. - * + * * @return the MIME type. */ public String getMIMEType() { @@ -498,7 +498,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload.ChangeEvent event is sent when the value (filename) of the upload * changes. - * + * * @since 7.2 */ public static class ChangeEvent extends Component.Event { @@ -512,7 +512,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Uploads where the event occurred. - * + * * @return the Source of the event. */ @Override @@ -522,7 +522,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the file name. - * + * * @return the filename. */ public String getFilename() { @@ -533,7 +533,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Receives the events when the upload starts. - * + * * @author Vaadin Ltd. * @since 5.0 */ @@ -541,7 +541,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload has started. - * + * * @param event * the Upload started event. */ @@ -550,7 +550,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Receives the events when the uploads are ready. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -558,7 +558,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload has finished. - * + * * @param event * the Upload finished event. */ @@ -567,7 +567,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Receives events when the uploads are finished, but unsuccessful. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -575,7 +575,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload has finished unsuccessfully. - * + * * @param event * the Upload failed event. */ @@ -584,7 +584,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Receives events when the uploads are successfully finished. - * + * * @author Vaadin Ltd. * @since 3.0 */ @@ -592,7 +592,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Upload successfull.. - * + * * @param event * the Upload successfull event. */ @@ -601,7 +601,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Listener for {@link ChangeEvent} - * + * * @since 7.2 */ public interface ChangeListener extends Serializable { @@ -611,7 +611,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * A file has been selected but upload has not yet started. - * + * * @param event * the change event */ @@ -620,7 +620,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Adds the upload started event listener. - * + * * @param listener * the Listener to be added. */ @@ -639,7 +639,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Removes the upload started event listener. - * + * * @param listener * the Listener to be removed. */ @@ -658,7 +658,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Adds the upload received event listener. - * + * * @param listener * the Listener to be added. */ @@ -677,7 +677,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Removes the upload received event listener. - * + * * @param listener * the Listener to be removed. */ @@ -696,7 +696,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Adds the upload interrupted event listener. - * + * * @param listener * the Listener to be added. */ @@ -715,7 +715,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Removes the upload interrupted event listener. - * + * * @param listener * the Listener to be removed. */ @@ -734,7 +734,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Adds the upload success event listener. - * + * * @param listener * the Listener to be added. */ @@ -753,7 +753,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Removes the upload success event listener. - * + * * @param listener * the Listener to be removed. */ @@ -771,10 +771,10 @@ public class Upload extends AbstractComponent implements Component.Focusable, } /** - * Adds the upload success event listener. - * + * Adds the upload progress event listener. + * * @param listener - * the Listener to be added. + * the progress listener to be added */ public void addProgressListener(ProgressListener listener) { if (progressListeners == null) { @@ -793,10 +793,10 @@ public class Upload extends AbstractComponent implements Component.Focusable, } /** - * Removes the upload success event listener. - * + * Removes the upload progress event listener. + * * @param listener - * the Listener to be removed. + * the progress listener to be removed */ public void removeProgressListener(ProgressListener listener) { if (progressListeners != null) { @@ -806,7 +806,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Adds a filename change event listener - * + * * @param listener * the Listener to add */ @@ -817,7 +817,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Removes a filename change event listener - * + * * @param listener * the listener to be removed */ @@ -836,7 +836,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Emit upload received event. - * + * * @param filename * @param MIMEType * @param length @@ -848,7 +848,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Emits the upload failed event. - * + * * @param filename * @param MIMEType * @param length @@ -877,11 +877,11 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Emits the upload success event. - * + * * @param filename * @param MIMEType * @param length - * + * */ protected void fireUploadSuccess(String filename, String MIMEType, long length) { @@ -890,12 +890,12 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Emits the progress event. - * + * * @param totalBytes * bytes received so far * @param contentLength * actual size of the file being uploaded, if known - * + * */ protected void fireUpdateProgress(long totalBytes, long contentLength) { // this is implemented differently than other listeners to maintain @@ -911,7 +911,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Returns the current receiver. - * + * * @return the StreamVariable. */ public Receiver getReceiver() { @@ -920,7 +920,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Sets the receiver. - * + * * @param receiver * the receiver to set. */ @@ -938,7 +938,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets the Tabulator index of this Focusable component. - * + * * @see com.vaadin.ui.Component.Focusable#getTabIndex() */ @Override @@ -948,7 +948,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Sets the Tabulator index of this Focusable component. - * + * * @see com.vaadin.ui.Component.Focusable#setTabIndex(int) */ @Override @@ -959,7 +959,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Go into upload state. This is to prevent double uploading on same * component. - * + * * Warning: this is an internal method used by the framework and should not * be used by user of the Upload component. Using it results in the Upload * component going in wrong state and not working. It is currently public @@ -986,7 +986,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Go into state where new uploading can begin. - * + * * Warning: this is an internal method used by the framework and should not * be used by user of the Upload component. */ @@ -1003,7 +1003,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Gets read bytes of the file currently being uploaded. - * + * * @return bytes */ public long getBytesRead() { @@ -1013,7 +1013,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, /** * Returns size of file currently being uploaded. Value sane only during * upload. - * + * * @return size in bytes */ public long getUploadSize() { @@ -1026,7 +1026,7 @@ public class Upload extends AbstractComponent implements Component.Focusable, public interface ProgressListener extends Serializable { /** * Updates progress to listener - * + * * @param readBytes * bytes transferred * @param contentLength @@ -1055,12 +1055,12 @@ public class Upload extends AbstractComponent implements Component.Focusable, * {@link #setImmediate(boolean)}, the file choose (html input with type * "file") is hidden and only the button with this text is shown. * <p> - * + * * <p> * <strong>Note</strong> the string given is set as is to the button. HTML * formatting is not stripped. Be sure to properly validate your value * according to your needs. - * + * * @param buttonCaption * text for upload components button. */ diff --git a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java index 7c19395df2..a8804caedb 100644 --- a/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java +++ b/server/src/com/vaadin/ui/components/calendar/ContainerEventProvider.java @@ -262,6 +262,7 @@ public class ContainerEventProvider implements CalendarEditableEventProvider, private int[] getFirstAndLastEventIndex(Date start, Date end) { int startIndex = 0; int size = container.size(); + assert size >= 0; int endIndex = size - 1; if (start != null) { diff --git a/server/src/com/vaadin/util/CurrentInstance.java b/server/src/com/vaadin/util/CurrentInstance.java index 00d2e7346d..6f2c0a2eca 100644 --- a/server/src/com/vaadin/util/CurrentInstance.java +++ b/server/src/com/vaadin/util/CurrentInstance.java @@ -1,12 +1,12 @@ /* * 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 @@ -52,12 +52,14 @@ import com.vaadin.ui.UI; * <p> * Non-inheritable: {@link VaadinRequest}, {@link VaadinResponse}. * </p> - * + * * @author Vaadin Ltd * @since 7.0.0 */ public class CurrentInstance implements Serializable { private static final Object NULL_OBJECT = new Object(); + private static final CurrentInstance CURRENT_INSTANCE_NULL = new CurrentInstance( + NULL_OBJECT, true); private final WeakReference<Object> instance; private final boolean inheritable; @@ -90,7 +92,7 @@ public class CurrentInstance implements Serializable { /** * Gets the current instance of a specific type if available. - * + * * @param type * the class to get an instance of * @return the current instance or the provided type, or <code>null</code> @@ -110,7 +112,7 @@ public class CurrentInstance implements Serializable { * ThreadLocal should only outlive the referenced object on * threads that are not doing anything related to Vaadin, which * should thus never invoke CurrentInstance.get(). - * + * * At this point, there might also be other values that have * been collected, so we'll scan the entire map and remove stale * CurrentInstance objects. Using a ReferenceQueue could make @@ -148,10 +150,10 @@ public class CurrentInstance implements Serializable { /** * Sets the current instance of the given type. - * + * * @see #setInheritable(Class, Object) * @see ThreadLocal - * + * * @param type * the class that should be used when getting the current * instance back @@ -167,10 +169,10 @@ public class CurrentInstance implements Serializable { * instance that is inheritable will be available for child threads and in * code run by {@link VaadinSession#access(Runnable)} and * {@link UI#access(Runnable)}. - * + * * @see #set(Class, Object) * @see InheritableThreadLocal - * + * * @param type * the class that should be used when getting the current * instance back @@ -181,17 +183,18 @@ public class CurrentInstance implements Serializable { set(type, instance, true); } - private static <T> void set(Class<T> type, T instance, boolean inheritable) { + private static <T> CurrentInstance set(Class<T> type, T instance, + boolean inheritable) { Map<Class<?>, CurrentInstance> map = instances.get(); + CurrentInstance previousInstance = null; if (instance == null) { // remove the instance - if (map == null) { - return; - } - map.remove(type); - if (map.isEmpty()) { - instances.remove(); - map = null; + if (map != null) { + previousInstance = map.remove(type); + if (map.isEmpty()) { + instances.remove(); + map = null; + } } } else { assert type.isInstance(instance) : "Invald instance type"; @@ -200,8 +203,8 @@ public class CurrentInstance implements Serializable { instances.set(map); } - CurrentInstance previousInstance = map.put(type, - new CurrentInstance(instance, inheritable)); + previousInstance = map.put(type, new CurrentInstance(instance, + inheritable)); if (previousInstance != null) { assert previousInstance.inheritable == inheritable : "Inheritable status mismatch for " + type @@ -211,6 +214,10 @@ public class CurrentInstance implements Serializable { + inheritable + ")"; } } + if (previousInstance == null) { + previousInstance = CURRENT_INSTANCE_NULL; + } + return previousInstance; } /** @@ -223,9 +230,9 @@ public class CurrentInstance implements Serializable { /** * Restores the given instances to the given values. Note that this should * only be used internally to restore Vaadin classes. - * + * * @since 7.1 - * + * * @param old * A Class -> CurrentInstance map to set as current instances */ @@ -243,7 +250,7 @@ public class CurrentInstance implements Serializable { * CurrentInstance. Without this a reference to an already * collected instance may be left in the CurrentInstance when it * really should be restored to null. - * + * * One example case that this fixes: * VaadinService.runPendingAccessTasks() clears all current * instances and then sets everything but the UI. This makes @@ -267,9 +274,9 @@ public class CurrentInstance implements Serializable { /** * Gets the currently set instances so that they can later be restored using * {@link #restoreInstances(Map)}. - * + * * @since 7.1 - * + * * @param onlyInheritable * <code>true</code> if only the inheritable instances should be * included; <code>false</code> to get all instances. @@ -305,20 +312,17 @@ public class CurrentInstance implements Serializable { * Sets current instances for the UI and all related classes. The previously * defined values can be restored by passing the returned map to * {@link #restoreInstances(Map)}. - * + * * @since 7.1 - * + * * @param ui * The UI * @return A map containing the old values of the instances that this method * updated. */ public static Map<Class<?>, CurrentInstance> setCurrent(UI ui) { - Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>(); - old.put(UI.class, - new CurrentInstance(getSameOrNullObject(UI.getCurrent()), true)); - UI.setCurrent(ui); - old.putAll(setCurrent(ui.getSession())); + Map<Class<?>, CurrentInstance> old = setCurrent(ui.getSession()); + old.put(UI.class, set(UI.class, ui, true)); return old; } @@ -326,9 +330,9 @@ public class CurrentInstance implements Serializable { * Sets current instances for the {@link VaadinSession} and all related * classes. The previously defined values can be restored by passing the * returned map to {@link #restoreInstances(Map)}. - * + * * @since 7.1 - * + * * @param session * The VaadinSession * @return A map containing the old values of the instances this method @@ -337,33 +341,15 @@ public class CurrentInstance implements Serializable { public static Map<Class<?>, CurrentInstance> setCurrent( VaadinSession session) { Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>(); - old.put(VaadinSession.class, new CurrentInstance( - getSameOrNullObject(VaadinSession.getCurrent()), true)); - old.put(VaadinService.class, new CurrentInstance( - getSameOrNullObject(VaadinService.getCurrent()), true)); + old.put(VaadinSession.class, set(VaadinSession.class, session, true)); VaadinService service = null; if (session != null) { service = session.getService(); } - - VaadinSession.setCurrent(session); - VaadinService.setCurrent(service); - + old.put(VaadinService.class, set(VaadinService.class, service, true)); return old; } - /** - * Returns {@code object} unless it is null, in which case #NULL_OBJECT is - * returned. - * - * @param object - * The instance to return if non-null. - * @return {@code object} or #NULL_OBJECT if {@code object} is null. - */ - private static Object getSameOrNullObject(Object object) { - return object == null ? NULL_OBJECT : object; - } - private static Logger getLogger() { return Logger.getLogger(CurrentInstance.class.getName()); } |