aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur.signell@itmill.com>2010-04-19 13:42:28 +0000
committerArtur Signell <artur.signell@itmill.com>2010-04-19 13:42:28 +0000
commit15bac5d7815a2fd4eec7155e5c119ba8dab58fc7 (patch)
tree41a7bb97fe543c0e6ea876343a14dfcb2a874796
parentfa9c9283c25d2407af4554d6d1b3663b165edf85 (diff)
downloadvaadin-framework-15bac5d7815a2fd4eec7155e5c119ba8dab58fc7.tar.gz
vaadin-framework-15bac5d7815a2fd4eec7155e5c119ba8dab58fc7.zip
Merged fixes from 6.3:
* Build updates * Fixes for #4418,#4562,#4514,#4536,#4533 * Test case updates * DevelopmentServerLauncher fix svn changeset:12649/svn branch:6.4
-rw-r--r--build/build.xml1
-rw-r--r--src/com/vaadin/data/Container.java17
-rw-r--r--src/com/vaadin/data/util/BeanItemContainer.java3
-rw-r--r--src/com/vaadin/data/util/ListSet.java84
-rw-r--r--src/com/vaadin/event/DataBoundTransferable.java9
-rw-r--r--src/com/vaadin/event/dd/DropHandler.java5
-rw-r--r--src/com/vaadin/event/dd/DropTarget.java5
-rw-r--r--src/com/vaadin/event/dd/TargetDetails.java4
-rw-r--r--src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java8
-rw-r--r--src/com/vaadin/launcher/DevelopmentServerLauncher.java6
-rw-r--r--src/com/vaadin/launcher/jetty-webdefault.xml402
-rw-r--r--src/com/vaadin/terminal/gwt/client/VBrowserDetails.java78
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java6
-rw-r--r--tests/src/com/vaadin/tests/components/select/MultiSelect.java31
-rw-r--r--tests/src/com/vaadin/tests/components/select/NativeSelects.html177
-rw-r--r--tests/src/com/vaadin/tests/components/select/NativeSelects.java153
-rw-r--r--tests/src/com/vaadin/tests/components/table/TableSorting.java67
-rw-r--r--tests/src/com/vaadin/tests/server/BrowserUserAgentParser.java18
-rw-r--r--tests/src/com/vaadin/tests/server/container/BeanItemContainerSortTest.java35
19 files changed, 1040 insertions, 69 deletions
diff --git a/build/build.xml b/build/build.xml
index 71f32c3ee5..d3b8f02370 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -676,6 +676,7 @@
<arg value="${widgetset}" />
<jvmarg value="-Xss8M"/>
+ <jvmarg value="-XX:MaxPermSize=256M"/>
<jvmarg value="-Djava.awt.headless=true"/>
</java>
<antcall target="remove-widgetset-gwt-tmp"/>
diff --git a/src/com/vaadin/data/Container.java b/src/com/vaadin/data/Container.java
index 6dbcfe779f..874b683eb4 100644
--- a/src/com/vaadin/data/Container.java
+++ b/src/com/vaadin/data/Container.java
@@ -573,10 +573,9 @@ public interface Container extends Serializable {
* visible in the container.
* </p>
* <p>
- * When an {@link com.vaadin.data.Ordered} or
- * {@link com.vaadin.data.Indexed} container is filtered, all operations of
- * these interfaces should only use the filtered contents and the filtered
- * indices to the container.
+ * When an {@link Ordered} or {@link Indexed} container is filtered, all
+ * operations of these interfaces should only use the filtered contents and
+ * the filtered indices to the container.
* </p>
* <p>
* How filtering is performed when a {@link Hierarchical} container
@@ -584,11 +583,11 @@ public interface Container extends Serializable {
* documented in the implementing class.
* </p>
* <p>
- * Adding items (if supported) to a filtered {@link com.vaadin.data.Ordered}
- * or {@link com.vaadin.data.Indexed} container should insert them
- * immediately after the indicated visible item. The unfiltered position of
- * items added at index 0, at index {@link com.vaadin.data.Container#size()}
- * or at an undefined position is up to the implementation.
+ * Adding items (if supported) to a filtered {@link Ordered} or
+ * {@link Indexed} container should insert them immediately after the
+ * indicated visible item. The unfiltered position of items added at index
+ * 0, at index {@link com.vaadin.data.Container#size()} or at an undefined
+ * position is up to the implementation.
* </p>
*
* @since 5.0
diff --git a/src/com/vaadin/data/util/BeanItemContainer.java b/src/com/vaadin/data/util/BeanItemContainer.java
index 3e3c4a5538..e99f219dbb 100644
--- a/src/com/vaadin/data/util/BeanItemContainer.java
+++ b/src/com/vaadin/data/util/BeanItemContainer.java
@@ -444,7 +444,8 @@ public class BeanItemContainer<BT> implements Indexed, Sortable, Filterable,
LinkedList<Object> sortables = new LinkedList<Object>();
for (Object propertyId : getContainerPropertyIds()) {
Class<?> propertyType = getType(propertyId);
- if (Comparable.class.isAssignableFrom(propertyType)) {
+ if (Comparable.class.isAssignableFrom(propertyType)
+ || propertyType.isPrimitive()) {
sortables.add(propertyId);
}
}
diff --git a/src/com/vaadin/data/util/ListSet.java b/src/com/vaadin/data/util/ListSet.java
index 0a3d954a3e..4c689ec361 100644
--- a/src/com/vaadin/data/util/ListSet.java
+++ b/src/com/vaadin/data/util/ListSet.java
@@ -5,20 +5,30 @@ package com.vaadin.data.util;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
/**
* ListSet is an internal Vaadin class which implements a combination of a List
- * and a Set. The main purpose of this class is to provide a fast
+ * and a Set. The main purpose of this class is to provide a list with a fast
* {@link #contains(Object)} method. Each inserted object must by unique (as
- * specified by {@link #equals(Object)}).
+ * specified by {@link #equals(Object)}). The {@link #set(int, Object)} method
+ * allows duplicates because of the way {@link Collections#sort(java.util.List)}
+ * works.
*
* This class is subject to change and should not be used outside Vaadin core.
*/
public class ListSet<E> extends ArrayList<E> {
private HashSet<E> itemSet = null;
+ /**
+ * Contains a map from an element to the number of duplicates it has. Used
+ * to temporarily allow duplicates in the list.
+ */
+ private HashMap<E, Integer> duplicates = new HashMap<E, Integer>();
+
public ListSet() {
super();
itemSet = new HashSet<E>();
@@ -35,7 +45,7 @@ public class ListSet<E> extends ArrayList<E> {
itemSet = new HashSet<E>(initialCapacity);
}
- // Delegate contains operations to the set
+ // Delegate contains operations to the set
@Override
public boolean contains(Object o) {
return itemSet.contains(o);
@@ -46,11 +56,11 @@ public class ListSet<E> extends ArrayList<E> {
return itemSet.containsAll(c);
}
- // Methods for updating the set when the list is updated.
+ // Methods for updating the set when the list is updated.
@Override
public boolean add(E e) {
if (contains(e)) {
- // Duplicates are not allowed
+ // Duplicates are not allowed
return false;
}
@@ -69,7 +79,7 @@ public class ListSet<E> extends ArrayList<E> {
@Override
public void add(int index, E element) {
if (contains(element)) {
- // Duplicates are not allowed
+ // Duplicates are not allowed
return;
}
@@ -173,20 +183,76 @@ public class ListSet<E> extends ArrayList<E> {
@Override
public E set(int index, E element) {
if (contains(element)) {
- // Element already exist in the list
+ // Element already exist in the list
if (get(index) == element) {
- // At the same position, nothing to be done
+ // At the same position, nothing to be done
return element;
+ } else {
+ // Adding at another position. We assume this is a sort
+ // operation and temporarily allow it.
+
+ // We could just remove (null) the old element and keep the list
+ // unique. This would require finding the index of the old
+ // element (indexOf(element)) which is not a fast operation in a
+ // list. So we instead allow duplicates temporarily.
+ addDuplicate(element);
}
}
E old = super.set(index, element);
- itemSet.remove(old);
+ removeFromSet(old);
itemSet.add(element);
return old;
}
+ /**
+ * Removes "e" from the set if it no longer exists in the list.
+ *
+ * @param e
+ */
+ private void removeFromSet(E e) {
+ Integer dupl = duplicates.get(e);
+ if (dupl != null) {
+ // A duplicate was present so we only decrement the duplicate count
+ // and continue
+ if (dupl == 1) {
+ // This is what always should happen. A sort sets the items one
+ // by one, temporarily breaking the uniqueness requirement.
+ duplicates.remove(e);
+ } else {
+ duplicates.put(e, dupl - 1);
+ }
+ } else {
+ // The "old" value is no longer in the list.
+ itemSet.remove(e);
+ }
+
+ }
+
+ /**
+ * Marks the "element" can be found more than once from the list. Allowed in
+ * {@link #set(int, Object)} to make sorting work.
+ *
+ * @param element
+ */
+ private void addDuplicate(E element) {
+ Integer nr = duplicates.get(element);
+ if (nr == null) {
+ nr = 1;
+ } else {
+ nr++;
+ }
+
+ /*
+ * Store the number of duplicates of this element so we know later on if
+ * we should remove an element from the set or if it was a duplicate (in
+ * removeFromSet)
+ */
+ duplicates.put(element, nr);
+
+ }
+
@SuppressWarnings("unchecked")
@Override
public Object clone() {
diff --git a/src/com/vaadin/event/DataBoundTransferable.java b/src/com/vaadin/event/DataBoundTransferable.java
index edef4c4427..8fb3143e7a 100644
--- a/src/com/vaadin/event/DataBoundTransferable.java
+++ b/src/com/vaadin/event/DataBoundTransferable.java
@@ -14,7 +14,8 @@ import com.vaadin.ui.Component;
* (identified by its Id) and optionally also a property identifier (e.g. a
* table column identifier when transferring a single table cell).
*
- * The component must implement the interface {@link Container.Viewer}.
+ * The component must implement the interface
+ * {@link com.vaadin.data.Container.Viewer}.
*
* In most cases, receivers of data transfers should depend on this class
* instead of its concrete subclasses.
@@ -47,13 +48,13 @@ public abstract class DataBoundTransferable extends TransferableImpl {
/**
* Returns the container data source from which the transfer occurs.
*
- * {@link Container.Viewer#getContainerDataSource()} is used to obtain the
- * underlying container of the source component.
+ * {@link com.vaadin.data.Container.Viewer#getContainerDataSource()} is used
+ * to obtain the underlying container of the source component.
*
* @return Container
*/
public Container getSourceContainer() {
- Component sourceComponent = getSourceComponent();
+ Component sourceComponent = getSourceComponent();
if (sourceComponent instanceof Container.Viewer) {
return ((Container.Viewer) sourceComponent)
.getContainerDataSource();
diff --git a/src/com/vaadin/event/dd/DropHandler.java b/src/com/vaadin/event/dd/DropHandler.java
index c9a28b5343..c0176207ed 100644
--- a/src/com/vaadin/event/dd/DropHandler.java
+++ b/src/com/vaadin/event/dd/DropHandler.java
@@ -14,8 +14,9 @@ import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
* DropHandlers contain the actual business logic for drag and drop operations.
* <p>
* The {@link #drop(DragAndDropEvent)} method is used to receive the transferred
- * data and the #getAcceptCriterion()} method contains the (possibly client side
- * verifiable) criterion whether the dragged data will be handled at all.
+ * data and the {@link #getAcceptCriterion()} method contains the (possibly
+ * client side verifiable) criterion whether the dragged data will be handled at
+ * all.
*
* @since 6.3
*
diff --git a/src/com/vaadin/event/dd/DropTarget.java b/src/com/vaadin/event/dd/DropTarget.java
index 31c6754f6f..fcb9670f6f 100644
--- a/src/com/vaadin/event/dd/DropTarget.java
+++ b/src/com/vaadin/event/dd/DropTarget.java
@@ -27,12 +27,11 @@ public interface DropTarget extends Component {
* {@link DropHandler}. Implementation may for exmaple translate the drop
* target details provided by the client side (drop target) to meaningful
* server side values. If null is returned the terminal implementation will
- * automatically create a {@link TargetDetails} with raw client side
- * data.
+ * automatically create a {@link TargetDetails} with raw client side data.
*
* @see DragSource#getTransferable(Map)
*
- * @param rawVariables
+ * @param clientVariables
* data passed from the DropTargets client side counterpart.
* @return A DropTargetDetails object with the translated data or null to
* use a default implementation.
diff --git a/src/com/vaadin/event/dd/TargetDetails.java b/src/com/vaadin/event/dd/TargetDetails.java
index f83edf84d1..bd2e41c63c 100644
--- a/src/com/vaadin/event/dd/TargetDetails.java
+++ b/src/com/vaadin/event/dd/TargetDetails.java
@@ -22,10 +22,10 @@ import com.vaadin.ui.Tree.TreeTargetDetails;
public interface TargetDetails extends Serializable {
/**
- * Gets target data associated to given string key
+ * Gets target data associated with the given string key
*
* @param key
- * @return
+ * @return The data associated with the key
*/
public Object getData(String key);
diff --git a/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java b/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java
index a2b631de56..6370ddad01 100644
--- a/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java
+++ b/src/com/vaadin/event/dd/acceptcriteria/AcceptCriterion.java
@@ -62,11 +62,11 @@ public interface AcceptCriterion extends Serializable {
public void paintResponse(PaintTarget target) throws PaintException;
/**
- * Validates the data in event to be appropriate for
- * {@link DropHandler#drop(com.vaadin.event.dd.DropEvent)} method.
+ * Validates the data in event to be appropriate for the
+ * {@link DropHandler#drop(DragAndDropEvent)} method.
* <p>
- * Note that even if your criterion is matched on client side, it is a very
- * good manner to validate the data on server side too.
+ * Note that even if your criterion is validated on client side, you should
+ * always validate the data on server side too.
*
* @param dragEvent
* @return
diff --git a/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/src/com/vaadin/launcher/DevelopmentServerLauncher.java
index bf17002436..ef02f8817f 100644
--- a/src/com/vaadin/launcher/DevelopmentServerLauncher.java
+++ b/src/com/vaadin/launcher/DevelopmentServerLauncher.java
@@ -4,6 +4,7 @@
package com.vaadin.launcher;
+import java.io.File;
import java.util.HashMap;
import java.util.Map;
@@ -82,9 +83,12 @@ public class DevelopmentServerLauncher {
server.setConnectors(new Connector[] { connector });
final WebAppContext webappcontext = new WebAppContext();
+ String path = DevelopmentServerLauncher.class.getPackage()
+ .getName().replace(".", File.separator);
+ webappcontext.setDefaultsDescriptor(path + File.separator
+ + "jetty-webdefault.xml");
webappcontext.setContextPath(serverArgs.get("context"));
webappcontext.setWar(serverArgs.get("webroot"));
-
server.setHandler(webappcontext);
server.start();
diff --git a/src/com/vaadin/launcher/jetty-webdefault.xml b/src/com/vaadin/launcher/jetty-webdefault.xml
new file mode 100644
index 0000000000..e5b7ececae
--- /dev/null
+++ b/src/com/vaadin/launcher/jetty-webdefault.xml
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!-- ===================================================================== -->
+<!-- This file contains the default descriptor for web applications. -->
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- The intent of this descriptor is to include jetty specific or common -->
+<!-- configuration for all webapps. If a context has a webdefault.xml -->
+<!-- descriptor, it is applied before the contexts own web.xml file -->
+<!-- -->
+<!-- A context may be assigned a default descriptor by: -->
+<!-- + Calling WebApplicationContext.setDefaultsDescriptor -->
+<!-- + Passed an arg to addWebApplications -->
+<!-- -->
+<!-- This file is used both as the resource within the jetty.jar (which is -->
+<!-- used as the default if no explicit defaults descriptor is set) and it -->
+<!-- is copied to the etc directory of the Jetty distro and explicitly -->
+<!-- by the jetty.xml file. -->
+<!-- -->
+<!-- ===================================================================== -->
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ metadata-complete="true"
+ version="2.5">
+
+ <description>
+ Default web.xml file.
+ This file is applied to a Web application before it's own WEB_INF/web.xml file
+ </description>
+
+
+ <!-- ==================================================================== -->
+ <!-- Context params to control Session Cookies -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- UNCOMMENT TO ACTIVATE
+ <context-param>
+ <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
+ <param-value>127.0.0.1</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
+ <param-value>/</param-value>
+ </context-param>
+
+ <context-param>
+ <param-name>org.mortbay.jetty.servlet.MaxAge</param-name>
+ <param-value>-1</param-value>
+ </context-param>
+ -->
+
+ <context-param>
+ <param-name>org.mortbay.jetty.webapp.NoTLDJarPattern</param-name>
+ <param-value>start.jar|ant-.*\.jar|dojo-.*\.jar|jetty-.*\.jar|jsp-api-.*\.jar|junit-.*\.jar|servlet-api-.*\.jar|dnsns\.jar|rt\.jar|jsse\.jar|tools\.jar|sunpkcs11\.jar|sunjce_provider\.jar|xerces.*\.jar</param-value>
+ </context-param>
+
+
+
+ <!-- ==================================================================== -->
+ <!-- The default servlet. -->
+ <!-- This servlet, normally mapped to /, provides the handling for static -->
+ <!-- content, OPTIONS and TRACE methods for the context. -->
+ <!-- The following initParameters are supported: -->
+ <!-- -->
+ <!-- acceptRanges If true, range requests and responses are -->
+ <!-- supported -->
+ <!-- -->
+ <!-- dirAllowed If true, directory listings are returned if no -->
+ <!-- welcome file is found. Else 403 Forbidden. -->
+ <!-- -->
+ <!-- redirectWelcome If true, redirect welcome file requests -->
+ <!-- else use request dispatcher forwards -->
+ <!-- -->
+ <!-- gzip If set to true, then static content will be served-->
+ <!-- as gzip content encoded if a matching resource is -->
+ <!-- found ending with ".gz" -->
+ <!-- -->
+ <!-- resoureBase Can be set to replace the context resource base -->
+ <!-- -->
+ <!-- relativeResourceBase -->
+ <!-- Set with a pathname relative to the base of the -->
+ <!-- servlet context root. Useful for only serving -->
+ <!-- static content from only specific subdirectories. -->
+ <!-- -->
+ <!-- useFileMappedBuffer -->
+ <!-- If set to true (the default), a memory mapped -->
+ <!-- file buffer will be used to serve static content -->
+ <!-- when using an NIO connector. Setting this value -->
+ <!-- to false means that a direct buffer will be used -->
+ <!-- instead. If you are having trouble with Windows -->
+ <!-- file locking, set this to false. -->
+ <!-- -->
+ <!-- cacheControl If set, all static content will have this value -->
+ <!-- set as the cache-control header. -->
+ <!-- -->
+ <!-- maxCacheSize Maximum size of the static resource cache -->
+ <!-- -->
+ <!-- maxCachedFileSize Maximum size of any single file in the cache -->
+ <!-- -->
+ <!-- maxCachedFiles Maximum number of files in the cache -->
+ <!-- -->
+ <!-- cacheType "nio", "bio" or "both" to determine the type(s) -->
+ <!-- of resource cache. A bio cached buffer may be used-->
+ <!-- by nio but is not as efficient as a nio buffer. -->
+ <!-- An nio cached buffer may not be used by bio. -->
+ <!-- -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <servlet>
+ <servlet-name>default</servlet-name>
+ <servlet-class>org.mortbay.jetty.servlet.DefaultServlet</servlet-class>
+ <init-param>
+ <param-name>acceptRanges</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>dirAllowed</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>redirectWelcome</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>maxCacheSize</param-name>
+ <param-value>256000000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>maxCachedFileSize</param-name>
+ <param-value>10000000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>maxCachedFiles</param-name>
+ <param-value>1000</param-value>
+ </init-param>
+ <init-param>
+ <param-name>cacheType</param-name>
+ <param-value>both</param-value>
+ </init-param>
+ <init-param>
+ <param-name>gzip</param-name>
+ <param-value>true</param-value>
+ </init-param>
+ <init-param>
+ <param-name>useFileMappedBuffer</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <!--
+ <init-param>
+ <param-name>cacheControl</param-name>
+ <param-value>max-age=3600,public</param-value>
+ </init-param>
+ -->
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
+
+
+ <!-- ==================================================================== -->
+ <!-- JSP Servlet -->
+ <!-- This is the jasper JSP servlet from the jakarta project -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- The JSP page compiler and execution servlet, which is the mechanism -->
+ <!-- used by Glassfish to support JSP pages. Traditionally, this servlet -->
+ <!-- is mapped to URL patterh "*.jsp". This servlet supports the -->
+ <!-- following initialization parameters (default values are in square -->
+ <!-- brackets): -->
+ <!-- -->
+ <!-- checkInterval If development is false and reloading is true, -->
+ <!-- background compiles are enabled. checkInterval -->
+ <!-- is the time in seconds between checks to see -->
+ <!-- if a JSP page needs to be recompiled. [300] -->
+ <!-- -->
+ <!-- compiler Which compiler Ant should use to compile JSP -->
+ <!-- pages. See the Ant documenation for more -->
+ <!-- information. [javac] -->
+ <!-- -->
+ <!-- classdebuginfo Should the class file be compiled with -->
+ <!-- debugging information? [true] -->
+ <!-- -->
+ <!-- classpath What class path should I use while compiling -->
+ <!-- generated servlets? [Created dynamically -->
+ <!-- based on the current web application] -->
+ <!-- Set to ? to make the container explicitly set -->
+ <!-- this parameter. -->
+ <!-- -->
+ <!-- development Is Jasper used in development mode (will check -->
+ <!-- for JSP modification on every access)? [true] -->
+ <!-- -->
+ <!-- enablePooling Determines whether tag handler pooling is -->
+ <!-- enabled [true] -->
+ <!-- -->
+ <!-- fork Tell Ant to fork compiles of JSP pages so that -->
+ <!-- a separate JVM is used for JSP page compiles -->
+ <!-- from the one Tomcat is running in. [true] -->
+ <!-- -->
+ <!-- ieClassId The class-id value to be sent to Internet -->
+ <!-- Explorer when using <jsp:plugin> tags. -->
+ <!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] -->
+ <!-- -->
+ <!-- javaEncoding Java file encoding to use for generating java -->
+ <!-- source files. [UTF-8] -->
+ <!-- -->
+ <!-- keepgenerated Should we keep the generated Java source code -->
+ <!-- for each page instead of deleting it? [true] -->
+ <!-- -->
+ <!-- logVerbosityLevel The level of detailed messages to be produced -->
+ <!-- by this servlet. Increasing levels cause the -->
+ <!-- generation of more messages. Valid values are -->
+ <!-- FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->
+ <!-- [WARNING] -->
+ <!-- -->
+ <!-- mappedfile Should we generate static content with one -->
+ <!-- print statement per input line, to ease -->
+ <!-- debugging? [false] -->
+ <!-- -->
+ <!-- -->
+ <!-- reloading Should Jasper check for modified JSPs? [true] -->
+ <!-- -->
+ <!-- suppressSmap Should the generation of SMAP info for JSR45 -->
+ <!-- debugging be suppressed? [false] -->
+ <!-- -->
+ <!-- dumpSmap Should the SMAP info for JSR45 debugging be -->
+ <!-- dumped to a file? [false] -->
+ <!-- False if suppressSmap is true -->
+ <!-- -->
+ <!-- scratchdir What scratch directory should we use when -->
+ <!-- compiling JSP pages? [default work directory -->
+ <!-- for the current web application] -->
+ <!-- -->
+ <!-- tagpoolMaxSize The maximum tag handler pool size [5] -->
+ <!-- -->
+ <!-- xpoweredBy Determines whether X-Powered-By response -->
+ <!-- header is added by generated servlet [false] -->
+ <!-- -->
+ <!-- If you wish to use Jikes to compile JSP pages: -->
+ <!-- Set the init parameter "compiler" to "jikes". Define -->
+ <!-- the property "-Dbuild.compiler.emacs=true" when starting Jetty -->
+ <!-- to cause Jikes to emit error messages in a format compatible with -->
+ <!-- Jasper. -->
+ <!-- If you get an error reporting that jikes can't use UTF-8 encoding, -->
+ <!-- try setting the init parameter "javaEncoding" to "ISO-8859-1". -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <servlet id="jsp">
+ <servlet-name>jsp</servlet-name>
+ <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
+ <init-param>
+ <param-name>logVerbosityLevel</param-name>
+ <param-value>DEBUG</param-value>
+ </init-param>
+ <init-param>
+ <param-name>fork</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>xpoweredBy</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <!--
+ <init-param>
+ <param-name>classpath</param-name>
+ <param-value>?</param-value>
+ </init-param>
+ -->
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>jsp</servlet-name>
+ <url-pattern>*.jsp</url-pattern>
+ <url-pattern>*.jspf</url-pattern>
+ <url-pattern>*.jspx</url-pattern>
+ <url-pattern>*.xsp</url-pattern>
+ <url-pattern>*.JSP</url-pattern>
+ <url-pattern>*.JSPF</url-pattern>
+ <url-pattern>*.JSPX</url-pattern>
+ <url-pattern>*.XSP</url-pattern>
+ </servlet-mapping>
+
+ <!-- ==================================================================== -->
+ <!-- Dynamic Servlet Invoker. -->
+ <!-- This servlet invokes anonymous servlets that have not been defined -->
+ <!-- in the web.xml or by other means. The first element of the pathInfo -->
+ <!-- of a request passed to the envoker is treated as a servlet name for -->
+ <!-- an existing servlet, or as a class name of a new servlet. -->
+ <!-- This servlet is normally mapped to /servlet/* -->
+ <!-- This servlet support the following initParams: -->
+ <!-- -->
+ <!-- nonContextServlets If false, the invoker can only load -->
+ <!-- servlets from the contexts classloader. -->
+ <!-- This is false by default and setting this -->
+ <!-- to true may have security implications. -->
+ <!-- -->
+ <!-- verbose If true, log dynamic loads -->
+ <!-- -->
+ <!-- * All other parameters are copied to the -->
+ <!-- each dynamic servlet as init parameters -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- Uncomment for dynamic invocation
+ <servlet>
+ <servlet-name>invoker</servlet-name>
+ <servlet-class>org.mortbay.jetty.servlet.Invoker</servlet-class>
+ <init-param>
+ <param-name>verbose</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>nonContextServlets</param-name>
+ <param-value>false</param-value>
+ </init-param>
+ <init-param>
+ <param-name>dynamicParam</param-name>
+ <param-value>anyValue</param-value>
+ </init-param>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>
+ -->
+
+
+
+ <!-- ==================================================================== -->
+ <session-config>
+ <session-timeout>30</session-timeout>
+ </session-config>
+
+ <!-- ==================================================================== -->
+ <!-- Default MIME mappings -->
+ <!-- The default MIME mappings are provided by the mime.properties -->
+ <!-- resource in the org.mortbay.jetty.jar file. Additional or modified -->
+ <!-- mappings may be specified here -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- UNCOMMENT TO ACTIVATE
+ <mime-mapping>
+ <extension>mysuffix</extension>
+ <mime-type>mymime/type</mime-type>
+ </mime-mapping>
+ -->
+
+ <!-- ==================================================================== -->
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ <welcome-file>index.htm</welcome-file>
+ <welcome-file>index.jsp</welcome-file>
+ </welcome-file-list>
+
+ <!-- ==================================================================== -->
+ <locale-encoding-mapping-list>
+ <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>
+ <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>
+ </locale-encoding-mapping-list>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Disable TRACE</web-resource-name>
+ <url-pattern>/</url-pattern>
+ <http-method>TRACE</http-method>
+ </web-resource-collection>
+ <auth-constraint/>
+ </security-constraint>
+
+</web-app>
+
diff --git a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
index d9f585e44f..92b3dedf1f 100644
--- a/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
+++ b/src/com/vaadin/terminal/gwt/client/VBrowserDetails.java
@@ -57,41 +57,57 @@ public class VBrowserDetails implements Serializable {
isFirefox = userAgent.indexOf(" firefox/") != -1;
// Rendering engine version
- if (isGecko) {
- String tmp = userAgent.substring(userAgent.indexOf("rv:") + 3);
- tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
- } else if (isWebKit) {
- String tmp = userAgent.substring(userAgent.indexOf("webkit/") + 7);
- tmp = tmp.replaceFirst("([0-9]+)[^0-9].+", "$1");
- browserEngineVersion = Float.parseFloat(tmp);
+ try {
+ if (isGecko) {
+ int rvPos = userAgent.indexOf("rv:");
+ if (rvPos >= 0) {
+ String tmp = userAgent.substring(rvPos + 3);
+ tmp = tmp.replaceFirst("(\\.[0-9]+).+", "$1");
+ browserEngineVersion = Float.parseFloat(tmp);
+ }
+ } else if (isWebKit) {
+ String tmp = userAgent
+ .substring(userAgent.indexOf("webkit/") + 7);
+ tmp = tmp.replaceFirst("([0-9]+)[^0-9].+", "$1");
+ browserEngineVersion = Float.parseFloat(tmp);
+ }
+ } catch (Exception e) {
+ // Browser engine version parsing failed
+ System.err.println("Browser engine version parsing failed for: "
+ + userAgent);
}
// Browser version
- if (isIE) {
- String ieVersionString = userAgent.substring(userAgent
- .indexOf("msie ") + 5);
- ieVersionString = safeSubstring(ieVersionString, 0, ieVersionString
- .indexOf(";"));
- parseVersionString(ieVersionString);
- } else if (isFirefox) {
- int i = userAgent.indexOf(" firefox/") + 9;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isChrome) {
- int i = userAgent.indexOf(" chrome/") + 8;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isSafari) {
- int i = userAgent.indexOf(" version/") + 9;
- parseVersionString(safeSubstring(userAgent, i, i + 5));
- } else if (isOpera) {
- int i = userAgent.indexOf(" version/");
- if (i != -1) {
- // Version present in Opera 10 and newer
- i += 9; // " version/".length
- } else {
- i = userAgent.indexOf("opera/") + 6;
+ try {
+ if (isIE) {
+ String ieVersionString = userAgent.substring(userAgent
+ .indexOf("msie ") + 5);
+ ieVersionString = safeSubstring(ieVersionString, 0,
+ ieVersionString.indexOf(";"));
+ parseVersionString(ieVersionString);
+ } else if (isFirefox) {
+ int i = userAgent.indexOf(" firefox/") + 9;
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isChrome) {
+ int i = userAgent.indexOf(" chrome/") + 8;
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isSafari) {
+ int i = userAgent.indexOf(" version/") + 9;
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } else if (isOpera) {
+ int i = userAgent.indexOf(" version/");
+ if (i != -1) {
+ // Version present in Opera 10 and newer
+ i += 9; // " version/".length
+ } else {
+ i = userAgent.indexOf("opera/") + 6;
+ }
+ parseVersionString(safeSubstring(userAgent, i, i + 5));
}
- parseVersionString(safeSubstring(userAgent, i, i + 5));
+ } catch (Exception e) {
+ // Browser version parsing failed
+ System.err.println("Browser version parsing failed for: "
+ + userAgent);
}
// Operating system
diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
index f326846c68..98b95b2a7c 100644
--- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
+++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
@@ -1672,6 +1672,12 @@ public abstract class AbstractCommunicationManager implements
i.remove();
} else {
Window componentsRoot = component.getWindow();
+ if (componentsRoot == null) {
+ // This should not happen unless somebody has overriden
+ // getApplication or getWindow in an illegal way.
+ throw new IllegalStateException(
+ "component.getWindow() returned null for a component attached to the application");
+ }
if (componentsRoot.getParent() != null) {
// this is a subwindow
componentsRoot = (Window) componentsRoot.getParent();
diff --git a/tests/src/com/vaadin/tests/components/select/MultiSelect.java b/tests/src/com/vaadin/tests/components/select/MultiSelect.java
new file mode 100644
index 0000000000..66ca41d829
--- /dev/null
+++ b/tests/src/com/vaadin/tests/components/select/MultiSelect.java
@@ -0,0 +1,31 @@
+package com.vaadin.tests.components.select;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Select;
+
+public class MultiSelect extends TestBase {
+
+ @Override
+ protected void setup() {
+ Select selectComponent = new Select();
+ selectComponent.setMultiSelect(true);
+
+ String[] selection = { "One", "Hund", "Three" };
+ for (String word : selection) {
+ selectComponent.addItem(word);
+ }
+
+ addComponent(selectComponent);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "The select is in multi select mode and should be rendered as such";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 4553;
+ }
+
+}
diff --git a/tests/src/com/vaadin/tests/components/select/NativeSelects.html b/tests/src/com/vaadin/tests/components/select/NativeSelects.html
new file mode 100644
index 0000000000..caff14b5b4
--- /dev/null
+++ b/tests/src/com/vaadin/tests/components/select/NativeSelects.html
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/com.vaadin.tests.components.select.NativeSelects?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>select</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[3]/VNativeSelect[0]/domChild[0]</td>
+ <td>label=The second item</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>select</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VNativeSelect[0]/domChild[0]</td>
+ <td>label=an item 1</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>select</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[7]/VNativeSelect[0]/domChild[0]</td>
+ <td>label=The second item</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>select</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[8]/VNativeSelect[0]/domChild[0]</td>
+ <td>label=an item 1</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>enabled-readwrite-noerror</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VCheckBox[0]/domChild[0]</td>
+ <td>7,6</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>enabled-readonly-noerror</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VCheckBox[0]/domChild[0]</td>
+ <td>31,6</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>enabled-readonly-error</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VCheckBox[0]/domChild[0]</td>
+ <td>3,9</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>enabled-readwrite-error</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[2]/VCheckBox[0]/domChild[0]</td>
+ <td>32,6</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>disabled-readwrite-error</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VCheckBox[0]/domChild[0]</td>
+ <td>47,6</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>disabled-readwrite-noerror</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[1]/VCheckBox[0]/domChild[0]</td>
+ <td>31,11</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>disabled-readonly-noerror</td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runcomvaadintestscomponentsselectNativeSelects::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VHorizontalLayout[0]/ChildComponentContainer[0]/VCheckBox[0]/domChild[0]</td>
+ <td>42,4</td>
+</tr>
+<tr>
+ <td>waitForVaadin</td>
+ <td></td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>disabled-readonly-error</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/src/com/vaadin/tests/components/select/NativeSelects.java b/tests/src/com/vaadin/tests/components/select/NativeSelects.java
new file mode 100644
index 0000000000..46b5267e28
--- /dev/null
+++ b/tests/src/com/vaadin/tests/components/select/NativeSelects.java
@@ -0,0 +1,153 @@
+package com.vaadin.tests.components.select;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.tests.components.ComponentTestCase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.NativeSelect;
+import com.vaadin.ui.Button.ClickEvent;
+
+public class NativeSelects extends ComponentTestCase {
+
+ private static final Object CAPTION = "caption";
+ NativeSelect label[] = new NativeSelect[20];
+
+ @Override
+ protected void setup() {
+ super.setup();
+
+ NativeSelect s;
+
+ s = createNativeSelect(null);
+ s.setWidth(null);
+ addTestComponent(s);
+
+ s = createNativeSelect("Undefined wide, empty select");
+ s.setWidth(null);
+ addTestComponent(s);
+
+ s = createNativeSelect("Undefined wide select with 5 items");
+ s.setWidth(null);
+ addItem(s, "The first item");
+ addItem(s, "The second item");
+ addItem(s, "The third item");
+ addItem(s, "The fourth item");
+ addItem(s, "The fifth item");
+ addTestComponent(s);
+
+ s = createNativeSelect("Undefined wide select with 50 items");
+ s.setWidth(null);
+ populate(s, 50);
+ addTestComponent(s);
+
+ s = createNativeSelect(null);
+ s.setWidth("100px");
+ addTestComponent(s);
+
+ s = createNativeSelect("100px wide, empty select");
+ s.setWidth("100px");
+ addTestComponent(s);
+
+ s = createNativeSelect("150px wide select with 5 items");
+ s.setWidth("150px");
+ addItem(s, "The first item");
+ addItem(s, "The second item");
+ addItem(s, "The third item");
+ addItem(s, "The fourth item");
+ addItem(s, "The fifth item");
+ addTestComponent(s);
+
+ s = createNativeSelect("200px wide select with 50 items");
+ s.setWidth("200px");
+ populate(s, 50);
+ addTestComponent(s);
+
+ }
+
+ private void populate(NativeSelect s, int nr) {
+ String text = " an item ";
+
+ String caption = "";
+ for (int i = 0; i < nr; i++) {
+ if (i % 2 == 0) {
+ caption += text;
+ } else {
+ caption += i;
+ }
+
+ addItem(s, caption);
+ }
+
+ }
+
+ private void addItem(NativeSelect s, String string) {
+ Object id = s.addItem();
+ s.getItem(id).getItemProperty(CAPTION).setValue(string);
+
+ }
+
+ private NativeSelect createNativeSelect(String caption) {
+ NativeSelect s = new NativeSelect();
+
+ s.addContainerProperty(CAPTION, String.class, "");
+ s.setItemCaptionPropertyId(CAPTION);
+ s.setCaption(caption);
+
+ return s;
+ }
+
+ @Override
+ protected String getDescription() {
+ return "A generic test for Labels in different configurations";
+ }
+
+ @Override
+ protected List<Component> createActions() {
+ ArrayList<Component> actions = new ArrayList<Component>();
+
+ CheckBox errorIndicators = new CheckBox("Error indicators",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ Button b = event.getButton();
+ boolean enabled = (Boolean) b.getValue();
+ setErrorIndicators(enabled);
+
+ }
+ });
+
+ CheckBox enabled = new CheckBox("Enabled", new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ Button b = event.getButton();
+ boolean enabled = (Boolean) b.getValue();
+ setEnabled(enabled);
+ }
+ });
+
+ CheckBox readonly = new CheckBox("Readonly",
+ new Button.ClickListener() {
+ public void buttonClick(ClickEvent event) {
+ Button b = event.getButton();
+ boolean enabled = (Boolean) b.getValue();
+ setReadOnly(enabled);
+ }
+ });
+
+ errorIndicators.setValue(new Boolean(false));
+ readonly.setValue(new Boolean(false));
+ enabled.setValue(new Boolean(true));
+
+ errorIndicators.setImmediate(true);
+ readonly.setImmediate(true);
+ enabled.setImmediate(true);
+
+ actions.add(errorIndicators);
+ actions.add(readonly);
+ actions.add(enabled);
+
+ return actions;
+ }
+
+}
diff --git a/tests/src/com/vaadin/tests/components/table/TableSorting.java b/tests/src/com/vaadin/tests/components/table/TableSorting.java
new file mode 100644
index 0000000000..4cbb1934e4
--- /dev/null
+++ b/tests/src/com/vaadin/tests/components/table/TableSorting.java
@@ -0,0 +1,67 @@
+package com.vaadin.tests.components.table;
+
+import java.io.Serializable;
+
+import com.vaadin.data.Property;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.util.BeanItemContainer;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Table;
+
+public class TableSorting extends TestBase {
+
+ @Override
+ public void setup() {
+ final Label showID = new Label("");
+ final Table testTable = new Table();
+
+ BeanItemContainer<TestItem> cont = new BeanItemContainer<TestItem>(
+ TestItem.class);
+
+ for (int i = 0; i < 20; i++) {
+ TestItem ti = new TestItem();
+ ti.setTestName("Name_" + i);
+ cont.addBean(ti);
+ }
+ testTable.setContainerDataSource(cont);
+ testTable.setImmediate(true);
+ testTable.setSelectable(true);
+ testTable.setMultiSelect(false);
+ testTable.setVisibleColumns(new Object[] { "testName" });
+
+ // Handle selection change.
+ testTable.addListener(new Property.ValueChangeListener() {
+ public void valueChange(ValueChangeEvent event) {
+ System.out.println("ValueChanged: "
+ + testTable.getValue().toString());
+ showID.setCaption("ID: " + testTable.getValue().toString());
+ }
+ });
+ addComponent(testTable);
+ addComponent(showID);
+ }
+
+ public class TestItem implements Serializable {
+ private static final long serialVersionUID = -745849615488792221L;
+ private String testName;
+
+ public String getTestName() {
+ return testName;
+ }
+
+ public void setTestName(String testName) {
+ this.testName = testName;
+ }
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Click the header to sort the table, then click on \"Name_10\". This should show ID: com.vaadin.tests.components.table.TableSorting$TestItem@<hex id> below the table";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 4537;
+ }
+} \ No newline at end of file
diff --git a/tests/src/com/vaadin/tests/server/BrowserUserAgentParser.java b/tests/src/com/vaadin/tests/server/BrowserUserAgentParser.java
index 168b99a19b..c1fa4e82f6 100644
--- a/tests/src/com/vaadin/tests/server/BrowserUserAgentParser.java
+++ b/tests/src/com/vaadin/tests/server/BrowserUserAgentParser.java
@@ -11,6 +11,8 @@ public class BrowserUserAgentParser extends TestCase {
private static final String FIREFOX35_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 (.NET CLR 3.5.30729) FirePHP/0.4";
private static final String FIREFOX36_WINDOWS = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (.NET CLR 3.5.30729)";
private static final String FIREFOX36B_MAC = "UAString mozilla/5.0 (macintosh; u; intel mac os x 10.6; en-us; rv:1.9.2) gecko/20100115 firefox/3.6";
+ private static final String FIREFOX_30B5_MAC = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9b5) Gecko/2008032619 Firefox/3.0b5";
+ private static final String KONQUEROR_LINUX = "Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Exabot-Thumbnails)";
private static final String IE6_WINDOWS = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)";
private static final String IE7_WINDOWS = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)";
@@ -106,6 +108,22 @@ public class BrowserUserAgentParser extends TestCase {
assertWindows(bd);
}
+ public void testFirefox30b5() {
+ VBrowserDetails bd = new VBrowserDetails(FIREFOX_30B5_MAC);
+ assertGecko(bd);
+ assertFirefox(bd);
+ assertBrowserMajorVersion(bd, 3);
+ assertBrowserMinorVersion(bd, 0);
+ assertEngineVersion(bd, 1.9f);
+ assertMacOSX(bd);
+ }
+
+ public void testKonquerorLinux() {
+ // Just ensure detection does not crash
+ VBrowserDetails bd = new VBrowserDetails(KONQUEROR_LINUX);
+ assertLinux(bd);
+ }
+
public void testFirefox36b() {
VBrowserDetails bd = new VBrowserDetails(FIREFOX36B_MAC);
assertGecko(bd);
diff --git a/tests/src/com/vaadin/tests/server/container/BeanItemContainerSortTest.java b/tests/src/com/vaadin/tests/server/container/BeanItemContainerSortTest.java
index eb46da776f..1320d57653 100644
--- a/tests/src/com/vaadin/tests/server/container/BeanItemContainerSortTest.java
+++ b/tests/src/com/vaadin/tests/server/container/BeanItemContainerSortTest.java
@@ -14,6 +14,16 @@ public class BeanItemContainerSortTest {
public class Person {
private String name;
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ private int age;
+
public void setName(String name) {
this.name = name;
}
@@ -23,14 +33,19 @@ public class BeanItemContainerSortTest {
}
}
- String[] names = new String[] { "Antti", "Ville", "Sirkka", "Jaakko" };
+ String[] names = new String[] { "Antti", "Ville", "Sirkka", "Jaakko",
+ "Pekka", "John" };
+ int[] ages = new int[] { 10, 20, 50, 12, 64, 67 };
+ String[] sortedByAge = new String[] { names[0], names[3], names[1],
+ names[2], names[4], names[5] };
public BeanItemContainer<Person> getContainer() {
BeanItemContainer<Person> bc = new BeanItemContainer<Person>(
Person.class);
- for (String name : names) {
+ for (int i = 0; i < names.length; i++) {
Person p = new Person();
- p.setName(name);
+ p.setName(names[i]);
+ p.setAge(ages[i]);
bc.addBean(p);
}
return bc;
@@ -55,6 +70,7 @@ public class BeanItemContainerSortTest {
int i = 0;
for (String string : asList) {
Person idByIndex = container.getIdByIndex(i++);
+ Assert.assertTrue(container.containsId(idByIndex));
Assert.assertEquals(string, idByIndex.getName());
}
}
@@ -64,4 +80,17 @@ public class BeanItemContainerSortTest {
testSort(false);
}
+ @Test
+ public void primitiveSorting() {
+ BeanItemContainer<Person> container = getContainer();
+ container.sort(new Object[] { "age" }, new boolean[] { true });
+
+ int i = 0;
+ for (String string : sortedByAge) {
+ Person idByIndex = container.getIdByIndex(i++);
+ Assert.assertTrue(container.containsId(idByIndex));
+ Assert.assertEquals(string, idByIndex.getName());
+ }
+
+ }
}