aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/main/java/com/vaadin/util
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2016-03-10 22:40:51 +0200
committerTeemu Suo-Anttila <teemusa@vaadin.com>2016-03-14 07:59:12 +0200
commita6653d3fe49e6a97468ac09f7f2f4d621bea1078 (patch)
tree96c82e20ca6551ee4c14c8877f0258b25c63cddf /server/src/main/java/com/vaadin/util
parentf7e57d77ce621ee39167369c31d989edc5633266 (diff)
downloadvaadin-framework-a6653d3fe49e6a97468ac09f7f2f4d621bea1078.tar.gz
vaadin-framework-a6653d3fe49e6a97468ac09f7f2f4d621bea1078.zip
Migrate vaadin-server build to maven
Change-Id: I5c740f4e9cb28103bab199f9a552153d82277e7e
Diffstat (limited to 'server/src/main/java/com/vaadin/util')
-rw-r--r--server/src/main/java/com/vaadin/util/ConnectorHelper.java101
-rw-r--r--server/src/main/java/com/vaadin/util/CurrentInstance.java355
-rw-r--r--server/src/main/java/com/vaadin/util/FileTypeResolver.java395
-rw-r--r--server/src/main/java/com/vaadin/util/ReflectTools.java216
-rw-r--r--server/src/main/java/com/vaadin/util/SerializerHelper.java157
5 files changed, 1224 insertions, 0 deletions
diff --git a/server/src/main/java/com/vaadin/util/ConnectorHelper.java b/server/src/main/java/com/vaadin/util/ConnectorHelper.java
new file mode 100644
index 0000000000..b3457068c3
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/ConnectorHelper.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.util;
+
+import java.util.LinkedList;
+
+import com.vaadin.server.ClientConnector;
+import com.vaadin.ui.Component;
+
+/**
+ * Provides various helper methods for connectors. Meant for internal use.
+ *
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class ConnectorHelper {
+
+ /**
+ * Creates a string containing debug info for the connector
+ *
+ * @since 7.1
+ * @param connector
+ * The connector to print debug info about
+ * @return A string with debug information
+ */
+ public static String getDebugInformation(ClientConnector connector) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("*** Debug details of a connector: *** \n");
+ sb.append("Type: ");
+ sb.append(connector.getClass().getName());
+ sb.append("\nId:");
+ sb.append(connector.getConnectorId());
+ if (connector instanceof Component) {
+ Component component = (Component) connector;
+ if (component.getCaption() != null) {
+ sb.append("\nCaption:");
+ sb.append(component.getCaption());
+ }
+ }
+ writeHierarchyInformation(connector, sb);
+ return sb.toString();
+ }
+
+ /**
+ * Creates a string containing hierarchy information for the connector
+ *
+ * @since 7.1
+ * @param connector
+ * The connector to get hierarchy information for
+ * @param builder
+ * The StringBuilder where the information should be written
+ */
+ public static void writeHierarchyInformation(ClientConnector connector,
+ StringBuilder builder) {
+ LinkedList<ClientConnector> h = new LinkedList<ClientConnector>();
+ h.add(connector);
+ ClientConnector parent = connector.getParent();
+ while (parent != null) {
+ h.addFirst(parent);
+ parent = parent.getParent();
+ }
+
+ builder.append("\nConnector hierarchy:\n");
+
+ int l = 0;
+ for (ClientConnector connector2 : h) {
+ if (l != 0) {
+ builder.append("\n");
+ for (int i = 0; i < l; i++) {
+ builder.append(" ");
+ }
+ }
+ l++;
+ Class<? extends ClientConnector> connectorClass = connector2
+ .getClass();
+ Class<?> topClass = connectorClass;
+ while (topClass.getEnclosingClass() != null) {
+ topClass = topClass.getEnclosingClass();
+ }
+ builder.append(connectorClass.getName());
+ builder.append("(");
+ builder.append(topClass.getSimpleName());
+ builder.append(".java:1)");
+ }
+ }
+
+}
diff --git a/server/src/main/java/com/vaadin/util/CurrentInstance.java b/server/src/main/java/com/vaadin/util/CurrentInstance.java
new file mode 100644
index 0000000000..e6b58ec65c
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/CurrentInstance.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.util;
+
+import java.io.Serializable;
+import java.lang.ref.WeakReference;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinResponse;
+import com.vaadin.server.VaadinService;
+import com.vaadin.server.VaadinSession;
+import com.vaadin.ui.UI;
+
+/**
+ * Keeps track of various current instances for the current thread. All the
+ * instances are automatically cleared after handling a request from the client
+ * to avoid leaking memory. The inheritable values are also maintained when
+ * execution is moved to another thread, both when a new thread is created and
+ * when {@link VaadinSession#access(Runnable)} or {@link UI#access(Runnable)} is
+ * used.
+ * <p>
+ * Please note that the instances are stored using {@link WeakReference}. This
+ * means that the a current instance value may suddenly disappear if there a no
+ * other references to the object.
+ * <p>
+ * Currently the framework uses the following instances:
+ * </p>
+ * <p>
+ * Inheritable: {@link UI}, {@link VaadinService}, {@link VaadinSession}.
+ * </p>
+ * <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;
+
+ private static InheritableThreadLocal<Map<Class<?>, CurrentInstance>> instances = new InheritableThreadLocal<Map<Class<?>, CurrentInstance>>() {
+ @Override
+ protected Map<Class<?>, CurrentInstance> childValue(
+ Map<Class<?>, CurrentInstance> parentValue) {
+ if (parentValue == null) {
+ return null;
+ }
+
+ Map<Class<?>, CurrentInstance> value = new HashMap<Class<?>, CurrentInstance>();
+
+ // Copy all inheritable values to child map
+ for (Entry<Class<?>, CurrentInstance> e : parentValue.entrySet()) {
+ if (e.getValue().inheritable) {
+ value.put(e.getKey(), e.getValue());
+ }
+ }
+
+ return value;
+ }
+ };
+
+ private CurrentInstance(Object instance, boolean inheritable) {
+ this.instance = new WeakReference<Object>(instance);
+ this.inheritable = inheritable;
+ }
+
+ /**
+ * 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>
+ * if there is no current instance.
+ */
+ public static <T> T get(Class<T> type) {
+ Map<Class<?>, CurrentInstance> map = instances.get();
+ if (map == null) {
+ return null;
+ }
+ CurrentInstance currentInstance = map.get(type);
+ if (currentInstance != null) {
+ Object value = currentInstance.instance.get();
+ if (value == null) {
+ /*
+ * This is believed to never actually happen since the
+ * 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
+ * this assumingly rare case slightly more efficient, but would
+ * significantly increase the complexity of the code for
+ * maintaining a separate ReferenceQueue for each Thread.
+ */
+ removeStaleInstances(map);
+
+ if (map.isEmpty()) {
+ instances.remove();
+ }
+
+ return null;
+ }
+ return type.cast(value);
+ } else {
+ return null;
+ }
+ }
+
+ private static void removeStaleInstances(Map<Class<?>, CurrentInstance> map) {
+ for (Iterator<Entry<Class<?>, CurrentInstance>> iterator = map
+ .entrySet().iterator(); iterator.hasNext();) {
+ Entry<Class<?>, CurrentInstance> entry = iterator.next();
+ Object instance = entry.getValue().instance.get();
+ if (instance == null) {
+ iterator.remove();
+ getLogger().log(Level.FINE,
+ "CurrentInstance for {0} has been garbage collected.",
+ entry.getKey());
+ }
+ }
+ }
+
+ /**
+ * 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
+ * @param instance
+ * the actual instance
+ */
+ public static <T> void set(Class<T> type, T instance) {
+ set(type, instance, false);
+ }
+
+ /**
+ * Sets the current inheritable instance of the given type. A current
+ * 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
+ * @param instance
+ * the actual instance
+ */
+ public static <T> void setInheritable(Class<T> type, T instance) {
+ set(type, instance, true);
+ }
+
+ 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) {
+ previousInstance = map.remove(type);
+ if (map.isEmpty()) {
+ instances.remove();
+ map = null;
+ }
+ }
+ } else {
+ assert type.isInstance(instance) : "Invald instance type";
+ if (map == null) {
+ map = new HashMap<Class<?>, CurrentInstance>();
+ instances.set(map);
+ }
+
+ previousInstance = map.put(type, new CurrentInstance(instance,
+ inheritable));
+ if (previousInstance != null) {
+ assert previousInstance.inheritable == inheritable : "Inheritable status mismatch for "
+ + type
+ + " (previous was "
+ + previousInstance.inheritable
+ + ", new is "
+ + inheritable + ")";
+ }
+ }
+ if (previousInstance == null) {
+ previousInstance = CURRENT_INSTANCE_NULL;
+ }
+ return previousInstance;
+ }
+
+ /**
+ * Clears all current instances.
+ */
+ public static void clearAll() {
+ instances.remove();
+ }
+
+ /**
+ * 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
+ */
+ public static void restoreInstances(Map<Class<?>, CurrentInstance> old) {
+ boolean removeStale = false;
+ for (Class c : old.keySet()) {
+ CurrentInstance ci = old.get(c);
+ Object v = ci.instance.get();
+ if (v == null) {
+ removeStale = true;
+ } else if (v == NULL_OBJECT) {
+ /*
+ * NULL_OBJECT is used to identify objects that are null when
+ * #setCurrent(UI) or #setCurrent(VaadinSession) are called on a
+ * 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
+ * UI.accessSynchronously() save these values before calling
+ * setCurrent(UI), which stores UI=null in the map it returns.
+ * This map will be restored after UI.accessSync(), which,
+ * unless it respects null values, will just leave the wrong UI
+ * instance registered.
+ */
+ v = null;
+ }
+ set(c, v, ci.inheritable);
+ }
+
+ if (removeStale) {
+ removeStaleInstances(old);
+ }
+ }
+
+ /**
+ * 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.
+ * @return a map containing the current instances
+ */
+ public static Map<Class<?>, CurrentInstance> getInstances(
+ boolean onlyInheritable) {
+ Map<Class<?>, CurrentInstance> map = instances.get();
+ if (map == null) {
+ return Collections.emptyMap();
+ } else {
+ Map<Class<?>, CurrentInstance> copy = new HashMap<Class<?>, CurrentInstance>();
+ boolean removeStale = false;
+ for (Class<?> c : map.keySet()) {
+ CurrentInstance ci = map.get(c);
+ if (ci.instance.get() == null) {
+ removeStale = true;
+ } else if (ci.inheritable || !onlyInheritable) {
+ copy.put(c, ci);
+ }
+ }
+ if (removeStale) {
+ removeStaleInstances(map);
+ if (map.isEmpty()) {
+ instances.remove();
+ }
+ }
+ return copy;
+ }
+ }
+
+ /**
+ * 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 = setCurrent(ui.getSession());
+ old.put(UI.class, set(UI.class, ui, true));
+ return old;
+ }
+
+ /**
+ * 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
+ * updated.
+ */
+ public static Map<Class<?>, CurrentInstance> setCurrent(
+ VaadinSession session) {
+ Map<Class<?>, CurrentInstance> old = new HashMap<Class<?>, CurrentInstance>();
+ old.put(VaadinSession.class, set(VaadinSession.class, session, true));
+ VaadinService service = null;
+ if (session != null) {
+ service = session.getService();
+ }
+ old.put(VaadinService.class, set(VaadinService.class, service, true));
+ return old;
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(CurrentInstance.class.getName());
+ }
+}
diff --git a/server/src/main/java/com/vaadin/util/FileTypeResolver.java b/server/src/main/java/com/vaadin/util/FileTypeResolver.java
new file mode 100644
index 0000000000..a49a0e2d01
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/FileTypeResolver.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.vaadin.util;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import com.vaadin.server.Resource;
+import com.vaadin.server.ThemeResource;
+
+/**
+ * Utility class that can figure out mime-types and icons related to files.
+ * <p>
+ * Note : The icons are associated purely to mime-types, so a file may not have
+ * a custom icon accessible with this class.
+ * </p>
+ *
+ * @author Vaadin Ltd.
+ * @since 3.0
+ */
+@SuppressWarnings("serial")
+public class FileTypeResolver implements Serializable {
+
+ /**
+ * Default icon given if no icon is specified for a mime-type.
+ */
+ static public Resource DEFAULT_ICON = new ThemeResource(
+ "../runo/icons/16/document.png");
+
+ /**
+ * Default mime-type.
+ */
+ static public String DEFAULT_MIME_TYPE = "application/octet-stream";
+
+ /**
+ * Initial file extension to mime-type mapping.
+ */
+ static private String initialExtToMIMEMap = "application/cu-seeme csm cu,"
+ + "application/dsptype tsp,"
+ + "application/futuresplash spl,"
+ + "application/mac-binhex40 hqx,"
+ + "application/msaccess mdb,"
+ + "application/msword doc dot,"
+ + "application/octet-stream bin,"
+ + "application/oda oda,"
+ + "application/pdf pdf,"
+ + "application/pgp-signature pgp,"
+ + "application/postscript ps ai eps,"
+ + "application/rtf rtf,"
+ + "application/vnd.ms-excel xls xlb,"
+ + "application/vnd.ms-powerpoint ppt pps pot,"
+ + "application/vnd.wap.wmlc wmlc,"
+ + "application/vnd.wap.wmlscriptc wmlsc,"
+ + "application/wordperfect5.1 wp5,"
+ + "application/zip zip,"
+ + "application/x-123 wk,"
+ + "application/x-bcpio bcpio,"
+ + "application/x-chess-pgn pgn,"
+ + "application/x-cpio cpio,"
+ + "application/x-debian-package deb,"
+ + "application/x-director dcr dir dxr,"
+ + "application/x-dms dms,"
+ + "application/x-dvi dvi,"
+ + "application/x-xfig fig,"
+ + "application/x-font pfa pfb gsf pcf pcf.Z,"
+ + "application/x-gnumeric gnumeric,"
+ + "application/x-gtar gtar tgz taz,"
+ + "application/x-hdf hdf,"
+ + "application/x-httpd-php phtml pht php,"
+ + "application/x-httpd-php3 php3,"
+ + "application/x-httpd-php3-source phps,"
+ + "application/x-httpd-php3-preprocessed php3p,"
+ + "application/x-httpd-php4 php4,"
+ + "application/x-ica ica,"
+ + "application/x-java-archive jar,"
+ + "application/x-java-serialized-object ser,"
+ + "application/x-java-vm class,"
+ + "application/x-javascript js,"
+ + "application/x-kchart chrt,"
+ + "application/x-killustrator kil,"
+ + "application/x-kpresenter kpr kpt,"
+ + "application/x-kspread ksp,"
+ + "application/x-kword kwd kwt,"
+ + "application/x-latex latex,"
+ + "application/x-lha lha,"
+ + "application/x-lzh lzh,"
+ + "application/x-lzx lzx,"
+ + "application/x-maker frm maker frame fm fb book fbdoc,"
+ + "application/x-mif mif,"
+ + "application/x-msdos-program com exe bat dll,"
+ + "application/x-msi msi,"
+ + "application/x-netcdf nc cdf,"
+ + "application/x-ns-proxy-autoconfig pac,"
+ + "application/x-object o,"
+ + "application/x-ogg ogg,"
+ + "application/x-oz-application oza,"
+ + "application/x-perl pl pm,"
+ + "application/x-pkcs7-crl crl,"
+ + "application/x-redhat-package-manager rpm,"
+ + "application/x-shar shar,"
+ + "application/x-shockwave-flash swf swfl,"
+ + "application/x-star-office sdd sda,"
+ + "application/x-stuffit sit,"
+ + "application/x-sv4cpio sv4cpio,"
+ + "application/x-sv4crc sv4crc,"
+ + "application/x-tar tar,"
+ + "application/x-tex-gf gf,"
+ + "application/x-tex-pk pk PK,"
+ + "application/x-texinfo texinfo texi,"
+ + "application/x-trash ~ % bak old sik,"
+ + "application/x-troff t tr roff,"
+ + "application/x-troff-man man,"
+ + "application/x-troff-me me,"
+ + "application/x-troff-ms ms,"
+ + "application/x-ustar ustar,"
+ + "application/x-wais-source src,"
+ + "application/x-wingz wz,"
+ + "application/x-x509-ca-cert crt,"
+ + "audio/basic au snd,"
+ + "audio/midi mid midi,"
+ + "audio/mpeg mpga mpega mp2 mp3,"
+ + "audio/mpegurl m3u,"
+ + "audio/prs.sid sid,"
+ + "audio/x-aiff aif aiff aifc,"
+ + "audio/x-gsm gsm,"
+ + "audio/x-pn-realaudio ra rm ram,"
+ + "audio/x-scpls pls,"
+ + "audio/x-wav wav,"
+ + "audio/ogg ogg,"
+ + "audio/mp4 m4a,"
+ + "audio/x-aac aac,"
+ + "image/bitmap bmp,"
+ + "image/gif gif,"
+ + "image/ief ief,"
+ + "image/jpeg jpeg jpg jpe,"
+ + "image/pcx pcx,"
+ + "image/png png,"
+ + "image/svg+xml svg svgz,"
+ + "image/tiff tiff tif,"
+ + "image/vnd.wap.wbmp wbmp,"
+ + "image/x-cmu-raster ras,"
+ + "image/x-coreldraw cdr,"
+ + "image/x-coreldrawpattern pat,"
+ + "image/x-coreldrawtemplate cdt,"
+ + "image/x-corelphotopaint cpt,"
+ + "image/x-jng jng,"
+ + "image/x-portable-anymap pnm,"
+ + "image/x-portable-bitmap pbm,"
+ + "image/x-portable-graymap pgm,"
+ + "image/x-portable-pixmap ppm,"
+ + "image/x-rgb rgb,"
+ + "image/x-xbitmap xbm,"
+ + "image/x-xpixmap xpm,"
+ + "image/x-xwindowdump xwd,"
+ + "text/comma-separated-values csv,"
+ + "text/css css,"
+ + "text/html htm html xhtml,"
+ + "text/mathml mml,"
+ + "text/plain txt text diff,"
+ + "text/richtext rtx,"
+ + "text/tab-separated-values tsv,"
+ + "text/vnd.wap.wml wml,"
+ + "text/vnd.wap.wmlscript wmls,"
+ + "text/xml xml,"
+ + "text/x-c++hdr h++ hpp hxx hh,"
+ + "text/x-c++src c++ cpp cxx cc,"
+ + "text/x-chdr h,"
+ + "text/x-csh csh,"
+ + "text/x-csrc c,"
+ + "text/x-java java,"
+ + "text/x-moc moc,"
+ + "text/x-pascal p pas,"
+ + "text/x-setext etx,"
+ + "text/x-sh sh,"
+ + "text/x-tcl tcl tk,"
+ + "text/x-tex tex ltx sty cls,"
+ + "text/x-vcalendar vcs,"
+ + "text/x-vcard vcf,"
+ + "video/dl dl,"
+ + "video/fli fli,"
+ + "video/gl gl,"
+ + "video/mpeg mpeg mpg mpe,"
+ + "video/quicktime qt mov,"
+ + "video/x-mng mng,"
+ + "video/x-ms-asf asf asx,"
+ + "video/x-msvideo avi,"
+ + "video/x-sgi-movie movie,"
+ + "video/ogg ogv,"
+ + "video/mp4 mp4,"
+ + "x-world/x-vrml vrm vrml wrl";
+
+ /**
+ * File extension to MIME type mapping. All extensions are in lower case.
+ */
+ static private Hashtable<String, String> extToMIMEMap = new Hashtable<String, String>();
+
+ /**
+ * MIME type to Icon mapping.
+ */
+ static private Hashtable<String, Resource> MIMEToIconMap = new Hashtable<String, Resource>();
+
+ static {
+
+ // Initialize extension to MIME map
+ final StringTokenizer lines = new StringTokenizer(initialExtToMIMEMap,
+ ",");
+ while (lines.hasMoreTokens()) {
+ final String line = lines.nextToken();
+ final StringTokenizer exts = new StringTokenizer(line);
+ final String type = exts.nextToken();
+ while (exts.hasMoreTokens()) {
+ final String ext = exts.nextToken();
+ addExtension(ext, type);
+ }
+ }
+
+ // Initialize Icons
+ ThemeResource folder = new ThemeResource("../runo/icons/16/folder.png");
+ addIcon("inode/drive", folder);
+ addIcon("inode/directory", folder);
+ }
+
+ /**
+ * Gets the mime-type of a file. Currently the mime-type is resolved based
+ * only on the file name extension.
+ *
+ * @param fileName
+ * the name of the file whose mime-type is requested.
+ * @return mime-type <code>String</code> for the given filename
+ */
+ public static String getMIMEType(String fileName) {
+
+ // Checks for nulls
+ if (fileName == null) {
+ throw new NullPointerException("Filename can not be null");
+ }
+
+ // Calculates the extension of the file
+ int dotIndex = fileName.indexOf(".");
+ while (dotIndex >= 0 && fileName.indexOf(".", dotIndex + 1) >= 0) {
+ dotIndex = fileName.indexOf(".", dotIndex + 1);
+ }
+ dotIndex++;
+
+ if (fileName.length() > dotIndex) {
+ String ext = fileName.substring(dotIndex);
+
+ // Ignore any query parameters
+ int queryStringStart = ext.indexOf('?');
+ if (queryStringStart > 0) {
+ ext = ext.substring(0, queryStringStart);
+ }
+
+ // Return type from extension map, if found
+ final String type = extToMIMEMap.get(ext.toLowerCase());
+ if (type != null) {
+ return type;
+ }
+ }
+
+ return DEFAULT_MIME_TYPE;
+ }
+
+ /**
+ * Gets the descriptive icon representing file, based on the filename. First
+ * the mime-type for the given filename is resolved, and then the
+ * corresponding icon is fetched from the internal icon storage. If it is
+ * not found the default icon is returned.
+ *
+ * @param fileName
+ * the name of the file whose icon is requested.
+ * @return the icon corresponding to the given file
+ */
+ public static Resource getIcon(String fileName) {
+ return getIconByMimeType(getMIMEType(fileName));
+ }
+
+ private static Resource getIconByMimeType(String mimeType) {
+ final Resource icon = MIMEToIconMap.get(mimeType);
+ if (icon != null) {
+ return icon;
+ }
+
+ // If nothing is known about the file-type, general file
+ // icon is used
+ return DEFAULT_ICON;
+ }
+
+ /**
+ * Gets the descriptive icon representing a file. First the mime-type for
+ * the given file name is resolved, and then the corresponding icon is
+ * fetched from the internal icon storage. If it is not found the default
+ * icon is returned.
+ *
+ * @param file
+ * the file whose icon is requested.
+ * @return the icon corresponding to the given file
+ */
+ public static Resource getIcon(File file) {
+ return getIconByMimeType(getMIMEType(file));
+ }
+
+ /**
+ * Gets the mime-type for a file. Currently the returned file type is
+ * resolved by the filename extension only.
+ *
+ * @param file
+ * the file whose mime-type is requested.
+ * @return the files mime-type <code>String</code>
+ */
+ public static String getMIMEType(File file) {
+
+ // Checks for nulls
+ if (file == null) {
+ throw new NullPointerException("File can not be null");
+ }
+
+ // Directories
+ if (file.isDirectory()) {
+ // Drives
+ if (file.getParentFile() == null) {
+ return "inode/drive";
+ } else {
+ return "inode/directory";
+ }
+ }
+
+ // Return type from extension
+ return getMIMEType(file.getName());
+ }
+
+ /**
+ * Adds a mime-type mapping for the given filename extension. If the
+ * extension is already in the internal mapping it is overwritten.
+ *
+ * @param extension
+ * the filename extension to be associated with
+ * <code>MIMEType</code>.
+ * @param MIMEType
+ * the new mime-type for <code>extension</code>.
+ */
+ public static void addExtension(String extension, String MIMEType) {
+ extToMIMEMap.put(extension.toLowerCase(), MIMEType);
+ }
+
+ /**
+ * Adds a icon for the given mime-type. If the mime-type also has a
+ * corresponding icon, it is replaced with the new icon.
+ *
+ * @param MIMEType
+ * the mime-type whose icon is to be changed.
+ * @param icon
+ * the new icon to be associated with <code>MIMEType</code>.
+ */
+ public static void addIcon(String MIMEType, Resource icon) {
+ MIMEToIconMap.put(MIMEType, icon);
+ }
+
+ /**
+ * Gets the internal file extension to mime-type mapping.
+ *
+ * @return unmodifiable map containing the current file extension to
+ * mime-type mapping
+ */
+ public static Map<String, String> getExtensionToMIMETypeMapping() {
+ return Collections.unmodifiableMap(extToMIMEMap);
+ }
+
+ /**
+ * Gets the internal mime-type to icon mapping.
+ *
+ * @return unmodifiable map containing the current mime-type to icon mapping
+ */
+ public static Map<String, Resource> getMIMETypeToIconMapping() {
+ return Collections.unmodifiableMap(MIMEToIconMap);
+ }
+}
diff --git a/server/src/main/java/com/vaadin/util/ReflectTools.java b/server/src/main/java/com/vaadin/util/ReflectTools.java
new file mode 100644
index 0000000000..2e2d3fe238
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/ReflectTools.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.util;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * An util class with helpers for reflection operations. Used internally by
+ * Vaadin and should not be used by application developers. Subject to change at
+ * any time.
+ *
+ * @since 6.2
+ */
+public class ReflectTools implements Serializable {
+ /**
+ * Locates the method in the given class. Returns null if the method is not
+ * found. Throws an ExceptionInInitializerError if there is a problem
+ * locating the method as this is mainly called from static blocks.
+ *
+ * @param cls
+ * Class that contains the method
+ * @param methodName
+ * The name of the method
+ * @param parameterTypes
+ * The parameter types for the method.
+ * @return A reference to the method
+ * @throws ExceptionInInitializerError
+ * Wraps any exception in an {@link ExceptionInInitializerError}
+ * so this method can be called from a static initializer.
+ */
+ public static Method findMethod(Class<?> cls, String methodName,
+ Class<?>... parameterTypes) throws ExceptionInInitializerError {
+ try {
+ return cls.getDeclaredMethod(methodName, parameterTypes);
+ } catch (Exception e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /**
+ * Returns the value of the java field.
+ * <p>
+ * Uses getter if present, otherwise tries to access even private fields
+ * directly.
+ *
+ * @param object
+ * The object containing the field
+ * @param field
+ * The field we want to get the value for
+ * @return The value of the field in the object
+ * @throws InvocationTargetException
+ * If the value could not be retrieved
+ * @throws IllegalAccessException
+ * If the value could not be retrieved
+ * @throws IllegalArgumentException
+ * If the value could not be retrieved
+ */
+ public static Object getJavaFieldValue(Object object,
+ java.lang.reflect.Field field) throws IllegalArgumentException,
+ IllegalAccessException, InvocationTargetException {
+ PropertyDescriptor pd;
+ try {
+ pd = new PropertyDescriptor(field.getName(), object.getClass());
+ Method getter = pd.getReadMethod();
+ if (getter != null) {
+ return getter.invoke(object, (Object[]) null);
+ }
+ } catch (IntrospectionException e1) {
+ // Ignore this and try to get directly using the field
+ }
+
+ // Try to get the value or throw an exception
+ if (!field.isAccessible()) {
+ // Try to gain access even if field is private
+ field.setAccessible(true);
+ }
+ return field.get(object);
+ }
+
+ /**
+ * Returns the value of the java field that is assignable to the property
+ * type.
+ * <p>
+ * Uses getter if a getter for the correct return type is present, otherwise
+ * tries to access even private fields directly. If the java field is not
+ * assignable to the property type throws an IllegalArgumentException.
+ *
+ * @param object
+ * The object containing the field
+ * @param field
+ * The field we want to get the value for
+ * @param propertyType
+ * The type the field must be assignable to
+ * @return The value of the field in the object
+ * @throws InvocationTargetException
+ * If the value could not be retrieved
+ * @throws IllegalAccessException
+ * If the value could not be retrieved
+ * @throws IllegalArgumentException
+ * If the value could not be retrieved
+ */
+ public static Object getJavaFieldValue(Object object,
+ java.lang.reflect.Field field, Class<?> propertyType)
+ throws IllegalArgumentException, IllegalAccessException,
+ InvocationTargetException {
+ PropertyDescriptor pd;
+ try {
+ pd = new PropertyDescriptor(field.getName(), object.getClass());
+ if (propertyType.isAssignableFrom(pd.getPropertyType())) {
+ Method getter = pd.getReadMethod();
+ if (getter != null) {
+ return getter.invoke(object, (Object[]) null);
+ }
+ }
+ } catch (IntrospectionException e1) {
+ // Ignore this and try to get directly using the field
+ }
+ // If the field's type cannot be casted in to the requested type
+ if (!propertyType.isAssignableFrom(field.getType())) {
+ throw new IllegalArgumentException();
+ }
+ // Try to get the value or throw an exception
+ if (!field.isAccessible()) {
+ // Try to gain access even if field is private
+ field.setAccessible(true);
+ }
+ return field.get(object);
+ }
+
+ /**
+ * Sets the value of a java field.
+ * <p>
+ * Uses setter if present, otherwise tries to access even private fields
+ * directly.
+ *
+ * @param object
+ * The object containing the field
+ * @param field
+ * The field we want to set the value for
+ * @param value
+ * The value to set
+ * @throws IllegalAccessException
+ * If the value could not be assigned to the field
+ * @throws IllegalArgumentException
+ * If the value could not be assigned to the field
+ * @throws InvocationTargetException
+ * If the value could not be assigned to the field
+ */
+ public static void setJavaFieldValue(Object object,
+ java.lang.reflect.Field field, Object value)
+ throws IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException {
+ PropertyDescriptor pd;
+ try {
+ pd = new PropertyDescriptor(field.getName(), object.getClass());
+ Method setter = pd.getWriteMethod();
+ if (setter != null) {
+ // Exceptions are thrown forward if this fails
+ setter.invoke(object, value);
+ }
+ } catch (IntrospectionException e1) {
+ // Ignore this and try to set directly using the field
+ }
+
+ // Try to set the value directly to the field or throw an exception
+ if (!field.isAccessible()) {
+ // Try to gain access even if field is private
+ field.setAccessible(true);
+ }
+ field.set(object, value);
+ }
+
+ /**
+ * @since 7.4
+ */
+ public static Class<?> convertPrimitiveType(Class<?> type) {
+ // Gets the return type from get method
+ if (type.isPrimitive()) {
+ if (type.equals(Boolean.TYPE)) {
+ type = Boolean.class;
+ } else if (type.equals(Integer.TYPE)) {
+ type = Integer.class;
+ } else if (type.equals(Float.TYPE)) {
+ type = Float.class;
+ } else if (type.equals(Double.TYPE)) {
+ type = Double.class;
+ } else if (type.equals(Byte.TYPE)) {
+ type = Byte.class;
+ } else if (type.equals(Character.TYPE)) {
+ type = Character.class;
+ } else if (type.equals(Short.TYPE)) {
+ type = Short.class;
+ } else if (type.equals(Long.TYPE)) {
+ type = Long.class;
+ }
+ }
+ return type;
+ }
+}
diff --git a/server/src/main/java/com/vaadin/util/SerializerHelper.java b/server/src/main/java/com/vaadin/util/SerializerHelper.java
new file mode 100644
index 0000000000..793488d892
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/SerializerHelper.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Helper class for performing serialization. Most of the methods are here are
+ * workarounds for problems in Google App Engine. Used internally by Vaadin and
+ * should not be used by application developers. Subject to change at any time.
+ *
+ * @since 6.0
+ */
+public class SerializerHelper {
+
+ /**
+ * Serializes the class reference so {@link #readClass(ObjectInputStream)}
+ * can deserialize it. Supports null class references.
+ *
+ * @param out
+ * The {@link ObjectOutputStream} to serialize to.
+ * @param cls
+ * A class or null.
+ * @throws IOException
+ * Rethrows any IOExceptions from the ObjectOutputStream
+ */
+ public static void writeClass(ObjectOutputStream out, Class<?> cls)
+ throws IOException {
+ if (cls == null) {
+ out.writeObject(null);
+ } else {
+ out.writeObject(cls.getName());
+ }
+
+ }
+
+ /**
+ * Serializes the class references so
+ * {@link #readClassArray(ObjectInputStream)} can deserialize it. Supports
+ * null class arrays.
+ *
+ * @param out
+ * The {@link ObjectOutputStream} to serialize to.
+ * @param classes
+ * An array containing class references or null.
+ * @throws IOException
+ * Rethrows any IOExceptions from the ObjectOutputStream
+ */
+ public static void writeClassArray(ObjectOutputStream out,
+ Class<?>[] classes) throws IOException {
+ if (classes == null) {
+ out.writeObject(null);
+ } else {
+ String[] classNames = new String[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ classNames[i] = classes[i].getName();
+ }
+ out.writeObject(classNames);
+ }
+ }
+
+ /**
+ * Deserializes a class references serialized by
+ * {@link #writeClassArray(ObjectOutputStream, Class[])}. Supports null
+ * class arrays.
+ *
+ * @param in
+ * {@link ObjectInputStream} to read from.
+ * @return Class array with the class references or null.
+ * @throws ClassNotFoundException
+ * If one of the classes could not be resolved.
+ * @throws IOException
+ * Rethrows IOExceptions from the ObjectInputStream
+ */
+ public static Class<?>[] readClassArray(ObjectInputStream in)
+ throws ClassNotFoundException, IOException {
+ String[] classNames = (String[]) in.readObject();
+ if (classNames == null) {
+ return null;
+ }
+ Class<?>[] classes = new Class<?>[classNames.length];
+ for (int i = 0; i < classNames.length; i++) {
+ classes[i] = resolveClass(classNames[i]);
+ }
+
+ return classes;
+ }
+
+ /**
+ * List of primitive classes. Google App Engine has problems
+ * serializing/deserializing these (#3064).
+ */
+ private static Class<?>[] primitiveClasses = new Class<?>[] { byte.class,
+ short.class, int.class, long.class, float.class, double.class,
+ boolean.class, char.class };
+
+ /**
+ * Resolves the class given by {@code className}.
+ *
+ * @param className
+ * The fully qualified class name.
+ * @return A {@code Class} reference.
+ * @throws ClassNotFoundException
+ * If the class could not be resolved.
+ */
+ public static Class<?> resolveClass(String className)
+ throws ClassNotFoundException {
+ for (Class<?> c : primitiveClasses) {
+ if (className.equals(c.getName())) {
+ return c;
+ }
+ }
+
+ return Class.forName(className);
+ }
+
+ /**
+ * Deserializes a class reference serialized by
+ * {@link #writeClass(ObjectOutputStream, Class)}. Supports null class
+ * references.
+ *
+ * @param in
+ * {@code ObjectInputStream} to read from.
+ * @return Class reference to the resolved class
+ * @throws ClassNotFoundException
+ * If the class could not be resolved.
+ * @throws IOException
+ * Rethrows IOExceptions from the ObjectInputStream
+ */
+ public static Class<?> readClass(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ String className = (String) in.readObject();
+ if (className == null) {
+ return null;
+ } else {
+ return resolveClass(className);
+
+ }
+
+ }
+
+}