diff options
author | Marc Englund <marc.englund@itmill.com> | 2007-09-18 14:31:18 +0000 |
---|---|---|
committer | Marc Englund <marc.englund@itmill.com> | 2007-09-18 14:31:18 +0000 |
commit | 5c0d7fa3fa0476e1a2e465295540d16b339f4499 (patch) | |
tree | 26788c928f73a84470ea01aef658fc645a375ec4 /src/com/itmill/toolkit | |
parent | 53c3889875d9c8024d3d3d49929af037a3e0a078 (diff) | |
download | vaadin-framework-5c0d7fa3fa0476e1a2e465295540d16b339f4499.tar.gz vaadin-framework-5c0d7fa3fa0476e1a2e465295540d16b339f4499.zip |
Widgetset extension changes, reservr example
svn changeset:2312/svn branch:trunk
Diffstat (limited to 'src/com/itmill/toolkit')
-rw-r--r-- | src/com/itmill/toolkit/demo/reservation/GoogleMap.java | 215 | ||||
-rw-r--r-- | src/com/itmill/toolkit/demo/reservation/ReservationApplication.java | 16 | ||||
-rw-r--r-- | src/com/itmill/toolkit/demo/reservation/gwt/WidgetSet.gwt.xml | 2 | ||||
-rw-r--r-- | src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSet.gwt.xml (renamed from src/com/itmill/toolkit/terminal/gwt/WidgetSet.gwt.xml) | 2 | ||||
-rw-r--r-- | src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSetNoEntry.gwt.xml (renamed from src/com/itmill/toolkit/terminal/gwt/WidgetSetNoEntry.gwt.xml) | 1 | ||||
-rw-r--r-- | src/com/itmill/toolkit/terminal/gwt/public/component-themes/button/css/button.css | 9 | ||||
-rw-r--r-- | src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css | 1 | ||||
-rw-r--r-- | src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java | 1958 |
8 files changed, 1231 insertions, 973 deletions
diff --git a/src/com/itmill/toolkit/demo/reservation/GoogleMap.java b/src/com/itmill/toolkit/demo/reservation/GoogleMap.java new file mode 100644 index 0000000000..68402a4ed6 --- /dev/null +++ b/src/com/itmill/toolkit/demo/reservation/GoogleMap.java @@ -0,0 +1,215 @@ +package com.itmill.toolkit.demo.reservation;
+
+import java.awt.geom.Point2D;
+import java.util.Collection;
+import java.util.Iterator;
+
+import com.itmill.toolkit.data.Container;
+import com.itmill.toolkit.data.Item;
+import com.itmill.toolkit.data.Property;
+import com.itmill.toolkit.data.util.IndexedContainer;
+import com.itmill.toolkit.terminal.PaintException;
+import com.itmill.toolkit.terminal.PaintTarget;
+import com.itmill.toolkit.terminal.Sizeable;
+import com.itmill.toolkit.ui.AbstractComponent;
+
+public class GoogleMap extends AbstractComponent implements Sizeable,
+ Container.Viewer {
+ private String TAG_MARKERS = "markers";
+ private String TAG_MARKER = "marker";
+ private int width = 400;
+ private int height = 300;
+ private int zoomLevel = 15;
+ private Point2D.Float mapCenter;
+
+ private Container dataSource;
+ private Object itemMarkerHtmlPropertyId = new Object();
+ private Object itemMarkerXPropertyId = new Object();
+ private Object itemMarkerYPropertyId = new Object();
+
+ public String getTag() {
+ return "googlemap";
+ }
+
+ public void paintContent(PaintTarget target) throws PaintException {
+ super.paintContent(target);
+ if (null != mapCenter) {
+ target.addAttribute("centerX", mapCenter.getX());
+ target.addAttribute("centerY", mapCenter.getY());
+ }
+ target.addAttribute("zoom", zoomLevel);
+ target.addAttribute("width", width);
+ target.addAttribute("height", height);
+
+ if (this.dataSource != null) {
+ target.startTag(TAG_MARKERS);
+ Collection itemIds = this.dataSource.getItemIds();
+ for (Iterator it = itemIds.iterator(); it.hasNext();) {
+ Object itemId = it.next();
+ Item item = this.dataSource.getItem(itemId);
+ Property p = item.getItemProperty(getItemMarkerXPropertyId());
+ Float x = (Float) (p != null ? p.getValue() : null);
+ p = item.getItemProperty(getItemMarkerYPropertyId());
+ Float y = (Float) (p != null ? p.getValue() : null);
+ if (x == null || y == null) {
+ continue;
+ }
+ target.startTag(TAG_MARKER);
+ target.addAttribute("x", x.floatValue());
+ target.addAttribute("y", y.floatValue());
+ p = item.getItemProperty(getItemMarkerHtmlPropertyId());
+ String h = (String) (p != null ? p.getValue() : null);
+ target.addAttribute("html", h);
+ target.endTag(TAG_MARKER);
+ }
+ target.endTag(TAG_MARKERS);
+ }
+ }
+
+ public void setZoomLevel(int zoomLevel) {
+ this.zoomLevel = zoomLevel;
+ requestRepaint();
+ }
+
+ public int getZoomLevel() {
+ return this.zoomLevel;
+ }
+
+ // Sizeable methods:
+
+ public int getHeight() {
+ return this.height;
+ }
+
+ public int getHeightUnits() {
+ return Sizeable.UNITS_PIXELS;
+ }
+
+ public int getWidth() {
+ return this.width;
+ }
+
+ public int getWidthUnits() {
+ return Sizeable.UNITS_PIXELS;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ requestRepaint();
+ }
+
+ public void setHeightUnits(int units) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ requestRepaint();
+ }
+
+ public void setWidthUnits(int units) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMapCenter(Point2D.Float center) {
+ this.mapCenter = center;
+ }
+
+ public Point2D.Float getMapCenter() {
+ return this.mapCenter;
+ }
+
+ // Container.Viewer methods:
+
+ public Container getContainerDataSource() {
+ return this.dataSource;
+ }
+
+ public void setContainerDataSource(Container newDataSource) {
+
+ this.dataSource = newDataSource;
+
+ requestRepaint();
+ }
+
+ // Item methods
+
+ public Object getItemMarkerHtmlPropertyId() {
+ return itemMarkerHtmlPropertyId;
+ }
+
+ public void setItemMarkerHtmlPropertyId(Object itemMarkerHtmlPropertyId) {
+ this.itemMarkerHtmlPropertyId = itemMarkerHtmlPropertyId;
+ requestRepaint();
+ }
+
+ public Object getItemMarkerXPropertyId() {
+ return itemMarkerXPropertyId;
+ }
+
+ public void setItemMarkerXPropertyId(Object itemMarkerXPropertyId) {
+ this.itemMarkerXPropertyId = itemMarkerXPropertyId;
+ requestRepaint();
+ }
+
+ public Object getItemMarkerYPropertyId() {
+ return itemMarkerYPropertyId;
+ }
+
+ public void setItemMarkerYPropertyId(Object itemMarkerYPropertyId) {
+ this.itemMarkerYPropertyId = itemMarkerYPropertyId;
+ requestRepaint();
+ }
+
+ // Marker add
+
+ public Object addMarker(String html, Point2D.Float location) {
+ if (location == null) {
+ throw new IllegalArgumentException("Location must be non-null");
+ }
+ if (this.dataSource == null) {
+ initDataSource();
+ }
+ Object markerId = this.dataSource.addItem();
+ if (markerId == null) {
+ return null;
+ }
+ Item marker = this.dataSource.getItem(markerId);
+ Property p = marker.getItemProperty(getItemMarkerXPropertyId());
+ p.setValue(new Float(location.x));
+ p = marker.getItemProperty(getItemMarkerYPropertyId());
+ p.setValue(new Float(location.y));
+ p = marker.getItemProperty(getItemMarkerHtmlPropertyId());
+ p.setValue(html);
+
+ requestRepaint();
+
+ return markerId;
+ }
+
+ public void removeMarker(Object markerId) {
+ if (this.dataSource != null) {
+ this.dataSource.removeItem(markerId);
+ requestRepaint();
+ }
+ }
+
+ public Item getMarkerItem(Object markerId) {
+ if (this.dataSource != null) {
+ return this.dataSource.getItem(markerId);
+ } else {
+ return null;
+ }
+ }
+
+ // dataSource init helper:
+ private void initDataSource() {
+ this.dataSource = new IndexedContainer();
+ this.dataSource.addContainerProperty(this.itemMarkerHtmlPropertyId,
+ String.class, null);
+ this.dataSource.addContainerProperty(this.itemMarkerXPropertyId,
+ Float.class, new Float(0));
+ this.dataSource.addContainerProperty(this.itemMarkerYPropertyId,
+ Float.class, new Float(0));
+ }
+}
\ No newline at end of file diff --git a/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java b/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java index 9e6363427a..42ebd7d74c 100644 --- a/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java +++ b/src/com/itmill/toolkit/demo/reservation/ReservationApplication.java @@ -1,5 +1,6 @@ package com.itmill.toolkit.demo.reservation;
+import java.awt.Point;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -44,7 +45,7 @@ public class ReservationApplication extends Application { Window mainWindow = new Window("Reservr");
setMainWindow(mainWindow);
- setTheme("example");
+ setTheme("reservr");
TabSheet mainTabs = new TabSheet();
mainWindow.addComponent(mainTabs);
@@ -79,7 +80,18 @@ public class ReservationApplication extends Application { infoLayout.addComponent(reservationButton);
statusLabel = new Label();
infoLayout.addComponent(statusLabel);
-
+
+ // TODO map
+ GoogleMap map = new GoogleMap();
+ map.setWidth(290);
+ map.setHeight(150);
+ map.setZoomLevel(2);
+ //map.setMapCenter(new Point.Float(60.453380f, 22.301850f));
+ infoLayout.addComponent(map);
+
+ map.addMarker("IT Mill", new Point.Float(60.453380f, 22.301850f));
+ map.addMarker("Romson a.k.a Rodskar", new Point.Float(63.509433f,22.276711f));
+
// TODO Use calendar, set following hour
Date now = new Date();
reservedFrom = new CalendarField();
diff --git a/src/com/itmill/toolkit/demo/reservation/gwt/WidgetSet.gwt.xml b/src/com/itmill/toolkit/demo/reservation/gwt/WidgetSet.gwt.xml index 2a360b6179..bcff23a087 100644 --- a/src/com/itmill/toolkit/demo/reservation/gwt/WidgetSet.gwt.xml +++ b/src/com/itmill/toolkit/demo/reservation/gwt/WidgetSet.gwt.xml @@ -1,6 +1,6 @@ <module> - <inherits name="com.itmill.toolkit.terminal.gwt.WidgetSetNoEntry" />
+ <inherits name="com.itmill.toolkit.terminal.gwt.DefaultWidgetSetNoEntry" />
<inherits name='com.mapitz.gwt.googleMaps.GoogleMaps' /> diff --git a/src/com/itmill/toolkit/terminal/gwt/WidgetSet.gwt.xml b/src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSet.gwt.xml index a5d027be61..30ead61889 100644 --- a/src/com/itmill/toolkit/terminal/gwt/WidgetSet.gwt.xml +++ b/src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -1,7 +1,7 @@ <module> <source path="client"/>
- <inherits name="com.itmill.toolkit.terminal.gwt.WidgetSetNoEntry"/> + <inherits name="com.itmill.toolkit.terminal.gwt.DefaultWidgetSetNoEntry"/> <entry-point class="com.itmill.toolkit.terminal.gwt.client.DefaultWidgetSet"/> </module> diff --git a/src/com/itmill/toolkit/terminal/gwt/WidgetSetNoEntry.gwt.xml b/src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSetNoEntry.gwt.xml index 62b16184c7..8c1c5f48cd 100644 --- a/src/com/itmill/toolkit/terminal/gwt/WidgetSetNoEntry.gwt.xml +++ b/src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSetNoEntry.gwt.xml @@ -16,5 +16,4 @@ <stylesheet src="component-themes/collection.css"/> - </module> diff --git a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/button/css/button.css b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/button/css/button.css new file mode 100644 index 0000000000..9bc7b86584 --- /dev/null +++ b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/button/css/button.css @@ -0,0 +1,9 @@ +button {
+ cursor: pointer;
+}
+button.link {
+ border: 0px;
+ text-align: left;
+ text-decoration: underline;
+ background: none;
+}
diff --git a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css index f3145a8b7d..28e8abb3e2 100644 --- a/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css +++ b/src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css @@ -1,4 +1,5 @@ @import "common/css/common.css";
+@import "button/css/button.css";
@import "textfield/css/textfield.css";
@import "select/css/select.css";
@import "panel/css/panel.css";
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java index cd76d4c1e7..7ad8a3258f 100644 --- a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java +++ b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java @@ -68,7 +68,7 @@ import com.itmill.toolkit.terminal.URIHandler; import com.itmill.toolkit.ui.Window; /** - * This servlet connects IT Mill Toolkit Application to Web. + * This servlet connects IT Mill Toolkit Application to Web. * * @author IT Mill Ltd. * @version @@ -78,1086 +78,1108 @@ import com.itmill.toolkit.ui.Window; public class ApplicationServlet extends HttpServlet { - private static final long serialVersionUID = -4937882979845826574L; + private static final long serialVersionUID = -4937882979845826574L; - /** - * Version number of this release. For example "4.0.0". - */ - public static final String VERSION; - - /** - * Major version number. For example 4 in 4.1.0. - */ - public static final int VERSION_MAJOR; + /** + * Version number of this release. For example "4.0.0". + */ + public static final String VERSION; - /** - * Minor version number. For example 1 in 4.1.0. - */ - public static final int VERSION_MINOR; + /** + * Major version number. For example 4 in 4.1.0. + */ + public static final int VERSION_MAJOR; - /** - * Builds number. For example 0-beta1 in 4.0.0-beta1. - */ - public static final String VERSION_BUILD; - - /* Initialize version numbers from string replaced by build-script. */ - static { - if ("@VERSION@".equals("@" + "VERSION" + "@")) - VERSION = "4.9.9-INTERNAL-NONVERSIONED-DEBUG-BUILD"; - else - VERSION = "@VERSION@"; - String[] digits = VERSION.split("\\."); - VERSION_MAJOR = Integer.parseInt(digits[0]); - VERSION_MINOR = Integer.parseInt(digits[1]); - VERSION_BUILD = digits[2]; - } + /** + * Minor version number. For example 1 in 4.1.0. + */ + public static final int VERSION_MINOR; - // Configurable parameter names - private static final String PARAMETER_DEBUG = "Debug"; + /** + * Builds number. For example 0-beta1 in 4.0.0-beta1. + */ + public static final String VERSION_BUILD; - private static final int DEFAULT_BUFFER_SIZE = 32 * 1024; + /* Initialize version numbers from string replaced by build-script. */ + static { + if ("@VERSION@".equals("@" + "VERSION" + "@")) + VERSION = "4.9.9-INTERNAL-NONVERSIONED-DEBUG-BUILD"; + else + VERSION = "@VERSION@"; + String[] digits = VERSION.split("\\."); + VERSION_MAJOR = Integer.parseInt(digits[0]); + VERSION_MINOR = Integer.parseInt(digits[1]); + VERSION_BUILD = digits[2]; + } - private static final int MAX_BUFFER_SIZE = 64 * 1024; + // Configurable parameter names + private static final String PARAMETER_DEBUG = "Debug"; - private static WeakHashMap applicationToLastRequestDate = new WeakHashMap(); + private static final int DEFAULT_BUFFER_SIZE = 32 * 1024; - private static WeakHashMap applicationToAjaxAppMgrMap = new WeakHashMap(); + private static final int MAX_BUFFER_SIZE = 64 * 1024; - // License for ApplicationServlets - private static WeakHashMap licenseForApplicationClass = new WeakHashMap(); + private static WeakHashMap applicationToLastRequestDate = new WeakHashMap(); - private static WeakHashMap licensePrintedForApplicationClass = new WeakHashMap(); + private static WeakHashMap applicationToAjaxAppMgrMap = new WeakHashMap(); - private static final String RESOURCE_URI = "/RES/"; + // License for ApplicationServlets + private static WeakHashMap licenseForApplicationClass = new WeakHashMap(); - private static final String AJAX_UIDL_URI = "/UIDL/"; + private static WeakHashMap licensePrintedForApplicationClass = new WeakHashMap(); - static final String THEME_DIRECTORY_PATH = "/theme/"; + private static final String RESOURCE_URI = "/RES/"; - // Maximum delay between request for an user to be considered active (in ms) - private static final long ACTIVE_USER_REQUEST_INTERVAL = 1000 * 45; - - private static final int DEFAULT_THEME_CACHETIME = 1000 * 60 * 60 * 24; + private static final String AJAX_UIDL_URI = "/UIDL/"; - // Private fields - private Class applicationClass; + static final String THEME_DIRECTORY_PATH = "/theme/"; - private Properties applicationProperties; + // Maximum delay between request for an user to be considered active (in ms) + private static final long ACTIVE_USER_REQUEST_INTERVAL = 1000 * 45; - private String resourcePath = null; + private static final int DEFAULT_THEME_CACHETIME = 1000 * 60 * 60 * 24; - private String debugMode = ""; + // Name of the default widget set, used if not specified in web.xml + private static final String DEFAULT_WIDGETSET = "com.itmill.toolkit.terminal.gwt.DefaultWidgetSet"; + // Widget set narameter name + private static final String PARAMETER_WIDGETSET = "widgetset"; - /** - * Called by the servlet container to indicate to a servlet that the servlet - * is being placed into service. - * - * @param servletConfig - * the object containing the servlet's configuration and - * initialization parameters - * @throws javax.servlet.ServletException - * if an exception has occurred that interferes with the - * servlet's normal operation. - */ - public void init(javax.servlet.ServletConfig servletConfig) - throws javax.servlet.ServletException { - super.init(servletConfig); - - // Gets the application class name - String applicationClassName = servletConfig - .getInitParameter("application"); - if (applicationClassName == null) { - Log.error("Application not specified in servlet parameters"); - } + // Private fields + private Class applicationClass; - // Stores the application parameters into Properties object - this.applicationProperties = new Properties(); - for (Enumeration e = servletConfig.getInitParameterNames(); e - .hasMoreElements();) { - String name = (String) e.nextElement(); - this.applicationProperties.setProperty(name, servletConfig - .getInitParameter(name)); - } + private Properties applicationProperties; - // Overrides with server.xml parameters - ServletContext context = servletConfig.getServletContext(); - for (Enumeration e = context.getInitParameterNames(); e - .hasMoreElements();) { - String name = (String) e.nextElement(); - this.applicationProperties.setProperty(name, context - .getInitParameter(name)); - } + private String resourcePath = null; - // Gets the debug window parameter - String debug = getApplicationOrSystemProperty(PARAMETER_DEBUG, "") - .toLowerCase(); - - // Enables application specific debug - if (!"".equals(debug) && !"true".equals(debug) - && !"false".equals(debug)) - throw new ServletException( - "If debug parameter is given for an application, it must be 'true' or 'false'"); - this.debugMode = debug; - - // Gets custom class loader - String classLoaderName = getApplicationOrSystemProperty( - "ClassLoader", null); - ClassLoader classLoader; - if (classLoaderName == null) - classLoader = getClass().getClassLoader(); - else { - try { - Class classLoaderClass = getClass().getClassLoader().loadClass(classLoaderName); - Constructor c = classLoaderClass.getConstructor(new Class[] {ClassLoader.class}); - classLoader = (ClassLoader) c.newInstance(new Object[] {getClass().getClassLoader()}); - } catch (Exception e) { - Log.error("Could not find specified class loader: " + classLoaderName); - throw new ServletException(e); - } - } + private String debugMode = ""; - // Loads the application class using the same class loader - // as the servlet itself - try { - this.applicationClass = classLoader.loadClass(applicationClassName); - } catch (ClassNotFoundException e) { - throw new ServletException("Failed to load application class: " - + applicationClassName); - } + /** + * Called by the servlet container to indicate to a servlet that the servlet + * is being placed into service. + * + * @param servletConfig + * the object containing the servlet's configuration and + * initialization parameters + * @throws javax.servlet.ServletException + * if an exception has occurred that interferes with the + * servlet's normal operation. + */ + public void init(javax.servlet.ServletConfig servletConfig) + throws javax.servlet.ServletException { + super.init(servletConfig); + // Gets the application class name + String applicationClassName = servletConfig + .getInitParameter("application"); + if (applicationClassName == null) { + Log.error("Application not specified in servlet parameters"); } - /** - * Gets an application or system property value. - * - * @param parameterName - * the Name or the parameter. - * @param defaultValue - * the Default to be used. - * @return String value or default if not found - */ - private String getApplicationOrSystemProperty(String parameterName, - String defaultValue) { - - // Try application properties - String val = this.applicationProperties.getProperty(parameterName); - if (val != null) { - return val; - } + // Stores the application parameters into Properties object + this.applicationProperties = new Properties(); + for (Enumeration e = servletConfig.getInitParameterNames(); e + .hasMoreElements();) { + String name = (String) e.nextElement(); + this.applicationProperties.setProperty(name, servletConfig + .getInitParameter(name)); + } - // Try lowercased application properties for backward compability with - // 3.0.2 and earlier - val = this.applicationProperties.getProperty(parameterName - .toLowerCase()); - if (val != null) { - return val; - } + // Overrides with server.xml parameters + ServletContext context = servletConfig.getServletContext(); + for (Enumeration e = context.getInitParameterNames(); e + .hasMoreElements();) { + String name = (String) e.nextElement(); + this.applicationProperties.setProperty(name, context + .getInitParameter(name)); + } - // Try system properties - String pkgName; - Package pkg = this.getClass().getPackage(); - if (pkg != null) { - pkgName = pkg.getName(); - } else { - String className = this.getClass().getName(); - pkgName = new String(className.toCharArray(), 0, className - .lastIndexOf('.')); - } - val = System.getProperty(pkgName + "." + parameterName); - if (val != null) { - return val; - } + // Gets the debug window parameter + String debug = getApplicationOrSystemProperty(PARAMETER_DEBUG, "") + .toLowerCase(); + + // Enables application specific debug + if (!"".equals(debug) && !"true".equals(debug) + && !"false".equals(debug)) + throw new ServletException( + "If debug parameter is given for an application, it must be 'true' or 'false'"); + this.debugMode = debug; + + // Gets custom class loader + String classLoaderName = getApplicationOrSystemProperty("ClassLoader", + null); + ClassLoader classLoader; + if (classLoaderName == null) + classLoader = getClass().getClassLoader(); + else { + try { + Class classLoaderClass = getClass().getClassLoader().loadClass( + classLoaderName); + Constructor c = classLoaderClass + .getConstructor(new Class[] { ClassLoader.class }); + classLoader = (ClassLoader) c + .newInstance(new Object[] { getClass().getClassLoader() }); + } catch (Exception e) { + Log.error("Could not find specified class loader: " + + classLoaderName); + throw new ServletException(e); + } + } - // Try lowercased system properties - val = System.getProperty(pkgName + "." + parameterName.toLowerCase()); - if (val != null) { - return val; - } + // Loads the application class using the same class loader + // as the servlet itself + try { + this.applicationClass = classLoader.loadClass(applicationClassName); + } catch (ClassNotFoundException e) { + throw new ServletException("Failed to load application class: " + + applicationClassName); + } - return defaultValue; + } + + /** + * Gets an application or system property value. + * + * @param parameterName + * the Name or the parameter. + * @param defaultValue + * the Default to be used. + * @return String value or default if not found + */ + private String getApplicationOrSystemProperty(String parameterName, + String defaultValue) { + + // Try application properties + String val = this.applicationProperties.getProperty(parameterName); + if (val != null) { + return val; } - /** - * Receives standard HTTP requests from the public service method and - * dispatches them. - * - * @param request - * the object that contains the request the client made of the - * servlet. - * @param response - * the object that contains the response the servlet returns to - * the client. - * @throws ServletException - * if an input or output error occurs while the servlet is - * handling the TRACE request. - * @throws IOException - * if the request for the TRACE cannot be handled. - */ - protected void service(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - - Application application = null; - try { - - // Update browser details - WebBrowser browser = WebApplicationContext.getApplicationContext(request.getSession()).getBrowser(); - browser.updateBrowserProperties(request); - // TODO Add screen height and width to the GWT client - - // Gets the application - application = getApplication(request); - - - // Sets the last application request date - synchronized (applicationToLastRequestDate) { - applicationToLastRequestDate.put(application, new Date()); - } + // Try lowercased application properties for backward compability with + // 3.0.2 and earlier + val = this.applicationProperties.getProperty(parameterName + .toLowerCase()); + if (val != null) { + return val; + } - // Invokes context transaction listeners - ((WebApplicationContext) application.getContext()) - .startTransaction(application, request); - - // Is this a download request from application - DownloadStream download = null; - - // The rest of the process is synchronized with the application - // in order to guarantee that no parallel variable handling is - // made - synchronized (application) { - - // Handles AJAX UIDL requests - String resourceId = request.getPathInfo(); - if (resourceId != null && resourceId.startsWith(AJAX_UIDL_URI)) { - getApplicationManager(application).handleUidlRequest( - request, response); - return; - } - - - // Handles the URI if the application is still running - if (application.isRunning()) - download = handleURI(application, request, response); - - // If this is not a download request - if (download == null) { - - // TODO Clean this branch - - // Window renders are not cacheable - response.setHeader("Cache-Control", "no-cache"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 0); - - // Finds the window within the application - Window window = null; - if (application.isRunning()) - window = getApplicationWindow(request, application); - - // Removes application if it has stopped - if (!application.isRunning()) { - endApplication(request, response, application); - return; - } - - // Sets terminal type for the window, if not already set - if (window.getTerminal() == null) { - window.setTerminal(browser); - } - - // Finds theme name - String themeName = window.getTheme(); - if (request.getParameter("theme") != null) { - themeName = request.getParameter("theme"); - } - - // Handles resource requests - if (handleResourceRequest(request, response, themeName)) - return; - - writeAjaxPage(request, response, - window, themeName); - } - } + // Try system properties + String pkgName; + Package pkg = this.getClass().getPackage(); + if (pkg != null) { + pkgName = pkg.getName(); + } else { + String className = this.getClass().getName(); + pkgName = new String(className.toCharArray(), 0, className + .lastIndexOf('.')); + } + val = System.getProperty(pkgName + "." + parameterName); + if (val != null) { + return val; + } - // For normal requests, transform the window - if (download != null) + // Try lowercased system properties + val = System.getProperty(pkgName + "." + parameterName.toLowerCase()); + if (val != null) { + return val; + } - handleDownload(download, request, response); - + return defaultValue; + } + + /** + * Receives standard HTTP requests from the public service method and + * dispatches them. + * + * @param request + * the object that contains the request the client made of + * the servlet. + * @param response + * the object that contains the response the servlet returns + * to the client. + * @throws ServletException + * if an input or output error occurs while the servlet is + * handling the TRACE request. + * @throws IOException + * if the request for the TRACE cannot be handled. + */ + protected void service(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + Application application = null; + try { + + // Update browser details + WebBrowser browser = WebApplicationContext.getApplicationContext( + request.getSession()).getBrowser(); + browser.updateBrowserProperties(request); + // TODO Add screen height and width to the GWT client + + // Gets the application + application = getApplication(request); + + // Sets the last application request date + synchronized (applicationToLastRequestDate) { + applicationToLastRequestDate.put(application, new Date()); + } + + // Invokes context transaction listeners + ((WebApplicationContext) application.getContext()) + .startTransaction(application, request); + + // Is this a download request from application + DownloadStream download = null; + + // The rest of the process is synchronized with the application + // in order to guarantee that no parallel variable handling is + // made + synchronized (application) { + + // Handles AJAX UIDL requests + String resourceId = request.getPathInfo(); + if (resourceId != null && resourceId.startsWith(AJAX_UIDL_URI)) { + getApplicationManager(application).handleUidlRequest( + request, response); + return; + } + // Handles the URI if the application is still running + if (application.isRunning()) + download = handleURI(application, request, response); - } catch (Throwable e) { - // Print stacktrace - e.printStackTrace(); - // Re-throw other exceptions - throw new ServletException(e); - } finally { + // If this is not a download request + if (download == null) { - // Notifies transaction end - if (application != null) - ((WebApplicationContext) application.getContext()) - .endTransaction(application, request); - } - } + // TODO Clean this branch - /** - * - * @param request - * the HTTP request. - * @param response - * the HTTP response to write to. - * @param out - * @param unhandledParameters - * @param window - * @param terminalType - * @param theme - * @throws IOException - * if the writing failed due to input/output error. - * @throws MalformedURLException - * if the application is denied access the persistent data store - * represented by the given URL. - */ - private void writeAjaxPage(HttpServletRequest request, - HttpServletResponse response, - Window window, String themeName) throws IOException, MalformedURLException { - response.setContentType("text/html"); - BufferedWriter page = new BufferedWriter(new OutputStreamWriter(response.getOutputStream())); - - String uri = request.getRequestURL().toString(); - boolean hasSlash = (uri.charAt(uri.length()-1) == '/') ? true : false; - - String relative = ""; - String t = request.getPathInfo().substring(1); - while (t.indexOf('/')>=0) { - t = t.substring(t.indexOf('/')+1); - relative += "../"; - } - - - page - .write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " - + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"); - - page.write("<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:v=\"urn:schemas-microsoft-com:vml\">\n<head>\n<title>IT Mill Toolkit 5</title>\n" + - "<script type=\"text/javascript\">\n" + - " var itmtk = {\n" + - " appUri:'"); - - String[] urlParts = getApplicationUrl(request).toString().split("\\/"); - String appUrl = ""; - // don't use server and port in uri. It may cause problems with some - // virtual server configurations which lose the server name - for (int i = 3; i < urlParts.length; i++) - appUrl += "/" + urlParts[i]; - if (appUrl.endsWith("/")) { - appUrl = appUrl.substring(0, appUrl.length() - 1); - } - - - page.write(appUrl); - - page.write("', pathInfo: '"+request.getPathInfo()+"'\n};\n" + - "</script>\n" + - - "<script src=\"http://maps.google.com/maps?file=api&v=2\" type=\"text/javascript\"></script>"+ - - "<script language='javascript' src='"+ (hasSlash ? "../" : "") + relative + "com.itmill.toolkit.demo.reservation.gwt.WidgetSet/com.itmill.toolkit.demo.reservation.gwt.WidgetSet.nocache.js'></script>" + - - "<link REL=\"stylesheet\" TYPE=\"text/css\" HREF=\""+request.getContextPath() + THEME_DIRECTORY_PATH+themeName+"/style.css\">" + - "</head>\n<body>\n" + - " <iframe id=\"__gwt_historyFrame\" style=\"width:0;height:0;border:0\"></iframe>\n" + - " <div id=\"itmtk-ajax-window\"></div>" + - " </body>\n" + - "</html>\n"); - - - page.close(); + // Window renders are not cacheable + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); - } + // Finds the window within the application + Window window = null; + if (application.isRunning()) + window = getApplicationWindow(request, application); - /** - * Handles the requested URI. An application can add handlers to do special - * processing, when a certain URI is requested. The handlers are invoked - * before any windows URIs are processed and if a DownloadStream is returned - * it is sent to the client. - * - * @param application - * the Application owning the URI. - * @param request - * the HTTP request instance. - * @param response - * the HTTP response to write to. - * @return boolean <code>true</code> if the request was handled and - * further processing should be suppressed, <code>false</code> - * otherwise. - * @see com.itmill.toolkit.terminal.URIHandler - */ - private DownloadStream handleURI(Application application, - HttpServletRequest request, HttpServletResponse response) { + // Removes application if it has stopped + if (!application.isRunning()) { + endApplication(request, response, application); + return; + } - String uri = request.getPathInfo(); + // Sets terminal type for the window, if not already set + if (window.getTerminal() == null) { + window.setTerminal(browser); + } - // If no URI is available - if (uri == null || uri.length() == 0 || uri.equals("/")) - return null; + // Finds theme name + String themeName = window.getTheme(); + if (request.getParameter("theme") != null) { + themeName = request.getParameter("theme"); + } - // Removes the leading / - while (uri.startsWith("/") && uri.length() > 0) - uri = uri.substring(1); + // Handles resource requests + if (handleResourceRequest(request, response, themeName)) + return; - // Handles the uri - DownloadStream stream = null; - try { - stream = application.handleURI(application.getURL(), uri); - } catch (Throwable t) { - application.terminalError(new URIHandlerErrorImpl(application, t)); + writeAjaxPage(request, response, window, themeName); } + } - return stream; - } + // For normal requests, transform the window + if (download != null) - /** - * Handles the requested URI. An application can add handlers to do special - * processing, when a certain URI is requested. The handlers are invoked - * before any windows URIs are processed and if a DownloadStream is returned - * it is sent to the client. - * - * @param stream - * the download stream. - * - * @param request - * the HTTP request instance. - * @param response - * the HTTP response to write to. - * - * @see com.itmill.toolkit.terminal.URIHandler - */ - private void handleDownload(DownloadStream stream, - HttpServletRequest request, HttpServletResponse response) { - - // Download from given stream - InputStream data = stream.getStream(); - if (data != null) { - - // Sets content type - response.setContentType(stream.getContentType()); - - // Sets cache headers - long cacheTime = stream.getCacheTime(); - if (cacheTime <= 0) { - response.setHeader("Cache-Control", "no-cache"); - response.setHeader("Pragma", "no-cache"); - response.setDateHeader("Expires", 0); - } else { - response.setHeader("Cache-Control", "max-age=" + cacheTime - / 1000); - response.setDateHeader("Expires", System.currentTimeMillis() - + cacheTime); - response.setHeader("Pragma", "cache"); // Required to apply - // caching in some - // Tomcats - } + handleDownload(download, request, response); - // Copy download stream parameters directly - // to HTTP headers. - Iterator i = stream.getParameterNames(); - if (i != null) { - while (i.hasNext()) { - String param = (String) i.next(); - response.setHeader((String) param, stream - .getParameter(param)); - } - } + } catch (Throwable e) { + // Print stacktrace + e.printStackTrace(); + // Re-throw other exceptions + throw new ServletException(e); + } finally { - int bufferSize = stream.getBufferSize(); - if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) - bufferSize = DEFAULT_BUFFER_SIZE; - byte[] buffer = new byte[bufferSize]; - int bytesRead = 0; - - try { - OutputStream out = response.getOutputStream(); - - while ((bytesRead = data.read(buffer)) > 0) { - out.write(buffer, 0, bytesRead); - out.flush(); - } - out.close(); - } catch (IOException ignored) { - } + // Notifies transaction end + if (application != null) + ((WebApplicationContext) application.getContext()) + .endTransaction(application, request); + } + } + + /** + * + * @param request + * the HTTP request. + * @param response + * the HTTP response to write to. + * @param out + * @param unhandledParameters + * @param window + * @param terminalType + * @param theme + * @throws IOException + * if the writing failed due to input/output error. + * @throws MalformedURLException + * if the application is denied access the persistent data + * store represented by the given URL. + */ + private void writeAjaxPage(HttpServletRequest request, + HttpServletResponse response, Window window, String themeName) + throws IOException, MalformedURLException { + response.setContentType("text/html"); + BufferedWriter page = new BufferedWriter(new OutputStreamWriter( + response.getOutputStream())); + + String uri = request.getRequestURL().toString(); + boolean hasSlash = (uri.charAt(uri.length() - 1) == '/') ? true : false; + + String relative = ""; + String t = request.getPathInfo().substring(1); + while (t.indexOf('/') >= 0) { + t = t.substring(t.indexOf('/') + 1); + relative += "../"; + } - } + // TODO remove GoogleMaps namespace and script + + page + .write("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " + + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"); + + page + .write("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title>IT Mill Toolkit 5</title>\n" + + "<script type=\"text/javascript\">\n" + + " var itmtk = {\n" + " appUri:'"); + + String[] urlParts = getApplicationUrl(request).toString().split("\\/"); + String appUrl = ""; + // don't use server and port in uri. It may cause problems with some + // virtual server configurations which lose the server name + for (int i = 3; i < urlParts.length; i++) + appUrl += "/" + urlParts[i]; + if (appUrl.endsWith("/")) { + appUrl = appUrl.substring(0, appUrl.length() - 1); + } + + page.write(appUrl); + String widgetset = this.applicationProperties + .getProperty(PARAMETER_WIDGETSET); + if (widgetset == null) { + widgetset = DEFAULT_WIDGETSET; } - - /** - * Handles theme resource file requests. Resources supplied with the themes - * are provided by the WebAdapterServlet. - * - * @param request - * the HTTP request. - * @param response - * the HTTP response. - * @return boolean <code>true</code> if the request was handled and - * further processing should be suppressed, <code>false</code> - * otherwise. - * @throws ServletException - * if an exception has occurred that interferes with the - * servlet's normal operation. - */ - private boolean handleResourceRequest(HttpServletRequest request, - HttpServletResponse response, String themeName) throws ServletException { - - // If the resource path is unassigned, initialize it - if (resourcePath == null) { - resourcePath = request.getContextPath() + request.getServletPath() - + RESOURCE_URI; - // WebSphere Application Server related fix - resourcePath = resourcePath.replaceAll("//", "/"); - } - String resourceId = request.getPathInfo(); + page + .write("', pathInfo: '" + + request.getPathInfo() + + "'\n};\n" + + "</script>\n" + + "<script language='javascript' src='" + + (hasSlash ? "../" : "") + + relative + + widgetset + + "/" + + widgetset + + ".nocache.js'></script>" + + "<link REL=\"stylesheet\" TYPE=\"text/css\" HREF=\"" + + request.getContextPath() + + THEME_DIRECTORY_PATH + + themeName + + "/styles.css\">" + + "</head>\n<body>\n" + + " <iframe id=\"__gwt_historyFrame\" style=\"width:0;height:0;border:0\"></iframe>\n" + + " <div id=\"itmtk-ajax-window\"></div>" + + " </body>\n" + "</html>\n"); + + page.close(); + + } + + /** + * Handles the requested URI. An application can add handlers to do special + * processing, when a certain URI is requested. The handlers are invoked + * before any windows URIs are processed and if a DownloadStream is returned + * it is sent to the client. + * + * @param application + * the Application owning the URI. + * @param request + * the HTTP request instance. + * @param response + * the HTTP response to write to. + * @return boolean <code>true</code> if the request was handled and + * further processing should be suppressed, <code>false</code> + * otherwise. + * @see com.itmill.toolkit.terminal.URIHandler + */ + private DownloadStream handleURI(Application application, + HttpServletRequest request, HttpServletResponse response) { + + String uri = request.getPathInfo(); + + // If no URI is available + if (uri == null || uri.length() == 0 || uri.equals("/")) + return null; + + // Removes the leading / + while (uri.startsWith("/") && uri.length() > 0) + uri = uri.substring(1); + + // Handles the uri + DownloadStream stream = null; + try { + stream = application.handleURI(application.getURL(), uri); + } catch (Throwable t) { + application.terminalError(new URIHandlerErrorImpl(application, t)); + } - // Checks if this really is a resource request - if (resourceId == null || !resourceId.startsWith(RESOURCE_URI)) - return false; - - // Checks the resource type - resourceId = resourceId.substring(RESOURCE_URI.length()); - InputStream data = null; - - // Gets theme resources - try { - data = getServletContext().getResourceAsStream(THEME_DIRECTORY_PATH + themeName + "/" + resourceId); - } catch (Exception e) { - Log.info(e.getMessage()); - data = null; + return stream; + } + + /** + * Handles the requested URI. An application can add handlers to do special + * processing, when a certain URI is requested. The handlers are invoked + * before any windows URIs are processed and if a DownloadStream is returned + * it is sent to the client. + * + * @param stream + * the download stream. + * + * @param request + * the HTTP request instance. + * @param response + * the HTTP response to write to. + * + * @see com.itmill.toolkit.terminal.URIHandler + */ + private void handleDownload(DownloadStream stream, + HttpServletRequest request, HttpServletResponse response) { + + // Download from given stream + InputStream data = stream.getStream(); + if (data != null) { + + // Sets content type + response.setContentType(stream.getContentType()); + + // Sets cache headers + long cacheTime = stream.getCacheTime(); + if (cacheTime <= 0) { + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + } else { + response.setHeader("Cache-Control", "max-age=" + cacheTime + / 1000); + response.setDateHeader("Expires", System.currentTimeMillis() + + cacheTime); + response.setHeader("Pragma", "cache"); // Required to apply + // caching in some + // Tomcats + } + + // Copy download stream parameters directly + // to HTTP headers. + Iterator i = stream.getParameterNames(); + if (i != null) { + while (i.hasNext()) { + String param = (String) i.next(); + response.setHeader((String) param, stream + .getParameter(param)); } + } - // Writes the response - try { - if (data != null) { - response.setContentType(FileTypeResolver - .getMIMEType(resourceId)); - - // Use default cache time for theme resources - response.setHeader("Cache-Control", "max-age=" - + DEFAULT_THEME_CACHETIME / 1000); - response.setDateHeader("Expires", System - .currentTimeMillis() - + DEFAULT_THEME_CACHETIME); - response.setHeader("Pragma", "cache"); // Required to apply - // caching in some - // Tomcats - - // Writes the data to client - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - int bytesRead = 0; - OutputStream out = response.getOutputStream(); - while ((bytesRead = data.read(buffer)) > 0) { - out.write(buffer, 0, bytesRead); - } - out.close(); - data.close(); - } else { - response.sendError(HttpServletResponse.SC_NOT_FOUND); - } + int bufferSize = stream.getBufferSize(); + if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE) + bufferSize = DEFAULT_BUFFER_SIZE; + byte[] buffer = new byte[bufferSize]; + int bytesRead = 0; + + try { + OutputStream out = response.getOutputStream(); - } catch (java.io.IOException e) { - Log.info("Resource transfer failed: " + request.getRequestURI() - + ". (" + e.getMessage() + ")"); + while ((bytesRead = data.read(buffer)) > 0) { + out.write(buffer, 0, bytesRead); + out.flush(); } + out.close(); + } catch (IOException ignored) { + } - return true; } + } + + /** + * Handles theme resource file requests. Resources supplied with the themes + * are provided by the WebAdapterServlet. + * + * @param request + * the HTTP request. + * @param response + * the HTTP response. + * @return boolean <code>true</code> if the request was handled and + * further processing should be suppressed, <code>false</code> + * otherwise. + * @throws ServletException + * if an exception has occurred that interferes with the + * servlet's normal operation. + */ + private boolean handleResourceRequest(HttpServletRequest request, + HttpServletResponse response, String themeName) + throws ServletException { + + // If the resource path is unassigned, initialize it + if (resourcePath == null) { + resourcePath = request.getContextPath() + request.getServletPath() + + RESOURCE_URI; + // WebSphere Application Server related fix + resourcePath = resourcePath.replaceAll("//", "/"); + } - /** - * Gets the current application URL from request. - * - * @param request - * the HTTP request. - * @throws MalformedURLException - * if the application is denied access to the persistent data - * store represented by the given URL. - */ - private URL getApplicationUrl(HttpServletRequest request) - throws MalformedURLException { - - URL applicationUrl; - try { - URL reqURL = new URL( - (request.isSecure() ? "https://" : "http://") - + request.getServerName() - + ((request.isSecure() && request.getServerPort() == 443) - || (!request.isSecure() && request - .getServerPort() == 80) ? "" : ":" - + request.getServerPort()) - + request.getRequestURI()); - String servletPath = request.getContextPath() - + request.getServletPath(); - if (servletPath.length() == 0 - || servletPath.charAt(servletPath.length() - 1) != '/') - servletPath = servletPath + "/"; - applicationUrl = new URL(reqURL, servletPath); - } catch (MalformedURLException e) { - Log.error("Error constructing application url " - + request.getRequestURI() + " (" + e + ")"); - throw e; - } + String resourceId = request.getPathInfo(); + + // Checks if this really is a resource request + if (resourceId == null || !resourceId.startsWith(RESOURCE_URI)) + return false; - return applicationUrl; + // Checks the resource type + resourceId = resourceId.substring(RESOURCE_URI.length()); + InputStream data = null; + + // Gets theme resources + try { + data = getServletContext().getResourceAsStream( + THEME_DIRECTORY_PATH + themeName + "/" + resourceId); + } catch (Exception e) { + Log.info(e.getMessage()); + data = null; } - /** - * Gets the existing application for given request. Looks for application - * instance for given request based on the requested URL. - * - * @param request - * the HTTP request. - * @return Application instance, or null if the URL does not map to valid - * application. - * @throws MalformedURLException - * if the application is denied access to the persistent data - * store represented by the given URL. - * @throws SAXException - * @throws LicenseViolation - * @throws InvalidLicenseFile - * @throws LicenseSignatureIsInvalid - * @throws LicenseFileHasNotBeenRead - * @throws IllegalAccessException - * @throws InstantiationException - */ - private Application getApplication(HttpServletRequest request) - throws MalformedURLException, LicenseFileHasNotBeenRead, - LicenseSignatureIsInvalid, InvalidLicenseFile, LicenseViolation, - SAXException, IllegalAccessException, InstantiationException { - - // Ensures that the session is still valid - HttpSession session = request.getSession(true); - - // Gets application list for the session. - Collection applications = WebApplicationContext.getApplicationContext(session).getApplications(); - - // Search for the application (using the application URI) from the list - for (Iterator i = applications.iterator(); i.hasNext();) { - Application a = (Application) i.next(); - String aPath = a.getURL().getPath(); - String servletPath = request.getContextPath() - + request.getServletPath(); - if (servletPath.length() < aPath.length()) - servletPath += "/"; - if (servletPath.equals(aPath)) { - - // Found a running application - if (a.isRunning()) - return a; - - // Application has stopped, so remove it before creating a new application - WebApplicationContext.getApplicationContext(session).removeApplication(a); - break; - } + // Writes the response + try { + if (data != null) { + response.setContentType(FileTypeResolver + .getMIMEType(resourceId)); + + // Use default cache time for theme resources + response.setHeader("Cache-Control", "max-age=" + + DEFAULT_THEME_CACHETIME / 1000); + response.setDateHeader("Expires", System.currentTimeMillis() + + DEFAULT_THEME_CACHETIME); + response.setHeader("Pragma", "cache"); // Required to apply + // caching in some + // Tomcats + + // Writes the data to client + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + int bytesRead = 0; + OutputStream out = response.getOutputStream(); + while ((bytesRead = data.read(buffer)) > 0) { + out.write(buffer, 0, bytesRead); } - - // Creates application, because a running one was not found - WebApplicationContext context = WebApplicationContext.getApplicationContext(request.getSession()); - URL applicationUrl = getApplicationUrl(request); - - // Creates new application and start it - try { - Application application = (Application) this.applicationClass.newInstance(); - context.addApplication(application); - - // Sets initial locale from the request - application.setLocale(request.getLocale()); - - // Starts application and check license - initializeLicense(application); - application.start(applicationUrl, this.applicationProperties, - context); - checkLicense(application); - - return application; - - } catch (IllegalAccessException e) { - Log.error("Illegal access to application class " - + this.applicationClass.getName()); - throw e; - } catch (InstantiationException e) { - Log.error("Failed to instantiate application class: " - + this.applicationClass.getName()); - throw e; - } + out.close(); + data.close(); + } else { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + + } catch (java.io.IOException e) { + Log.info("Resource transfer failed: " + request.getRequestURI() + + ". (" + e.getMessage() + ")"); } + return true; + } + + /** + * Gets the current application URL from request. + * + * @param request + * the HTTP request. + * @throws MalformedURLException + * if the application is denied access to the persistent + * data store represented by the given URL. + */ + private URL getApplicationUrl(HttpServletRequest request) + throws MalformedURLException { + + URL applicationUrl; + try { + URL reqURL = new URL( + (request.isSecure() ? "https://" : "http://") + + request.getServerName() + + ((request.isSecure() && request.getServerPort() == 443) + || (!request.isSecure() && request + .getServerPort() == 80) ? "" : ":" + + request.getServerPort()) + + request.getRequestURI()); + String servletPath = request.getContextPath() + + request.getServletPath(); + if (servletPath.length() == 0 + || servletPath.charAt(servletPath.length() - 1) != '/') + servletPath = servletPath + "/"; + applicationUrl = new URL(reqURL, servletPath); + } catch (MalformedURLException e) { + Log.error("Error constructing application url " + + request.getRequestURI() + " (" + e + ")"); + throw e; + } - /** - * - * @param application - */ - private void initializeLicense(Application application) { - License license; - synchronized (licenseForApplicationClass) { - license = (License) licenseForApplicationClass.get(application - .getClass()); - if (license == null) { - license = new License(); - licenseForApplicationClass.put(application.getClass(), license); - } - } - application.setToolkitLicense(license); + return applicationUrl; + } + + /** + * Gets the existing application for given request. Looks for application + * instance for given request based on the requested URL. + * + * @param request + * the HTTP request. + * @return Application instance, or null if the URL does not map to valid + * application. + * @throws MalformedURLException + * if the application is denied access to the persistent + * data store represented by the given URL. + * @throws SAXException + * @throws LicenseViolation + * @throws InvalidLicenseFile + * @throws LicenseSignatureIsInvalid + * @throws LicenseFileHasNotBeenRead + * @throws IllegalAccessException + * @throws InstantiationException + */ + private Application getApplication(HttpServletRequest request) + throws MalformedURLException, LicenseFileHasNotBeenRead, + LicenseSignatureIsInvalid, InvalidLicenseFile, LicenseViolation, + SAXException, IllegalAccessException, InstantiationException { + + // Ensures that the session is still valid + HttpSession session = request.getSession(true); + + // Gets application list for the session. + Collection applications = WebApplicationContext.getApplicationContext( + session).getApplications(); + + // Search for the application (using the application URI) from the list + for (Iterator i = applications.iterator(); i.hasNext();) { + Application a = (Application) i.next(); + String aPath = a.getURL().getPath(); + String servletPath = request.getContextPath() + + request.getServletPath(); + if (servletPath.length() < aPath.length()) + servletPath += "/"; + if (servletPath.equals(aPath)) { + + // Found a running application + if (a.isRunning()) + return a; + + // Application has stopped, so remove it before creating a new + // application + WebApplicationContext.getApplicationContext(session) + .removeApplication(a); + break; + } } - /** - * - * @param application - * @throws LicenseFileHasNotBeenRead - * if the license file has not been read. - * @throws LicenseSignatureIsInvalid - * if the license file has been changed or signature is - * otherwise invalid. - * @throws InvalidLicenseFile - * if the license file is not of correct XML format. - * @throws LicenseViolation - * - * @throws SAXException - * the Error parsing the license file. - */ - private void checkLicense(Application application) - throws LicenseFileHasNotBeenRead, LicenseSignatureIsInvalid, - InvalidLicenseFile, LicenseViolation, SAXException { - License license = application.getToolkitLicense(); - - if (!license.hasBeenRead()) - // Lock threads that have not yet read license - synchronized (license) { - if (!license.hasBeenRead()) { - InputStream lis; - try { - URL url = getServletContext().getResource( - "/WEB-INF/itmill-toolkit-license.xml"); - if (url == null) { - throw new RuntimeException( - "License file could not be read. " - + "You can install it to " - + "WEB-INF/itmill-toolkit-license.xml."); - } - lis = url.openStream(); - license.readLicenseFile(lis); - } catch (MalformedURLException e) { - // This should not happen - throw new RuntimeException(e); - } catch (IOException e) { - // This should not happen - throw new RuntimeException(e); - } - - // For each application class, print license description - - // once - if (!licensePrintedForApplicationClass - .containsKey(applicationClass)) { - licensePrintedForApplicationClass.put(applicationClass, - Boolean.TRUE); - if (license.shouldLimitsBePrintedOnInit()) { - System.out.println(license - .getDescription(application.getClass() - .toString())); - } - } - - // Checks license validity - try { - license.check(applicationClass, VERSION_MAJOR, - VERSION_MINOR, "IT Mill Toolkit", null); - } catch (LicenseFileHasNotBeenRead e) { - application.close(); - throw e; - } catch (LicenseSignatureIsInvalid e) { - application.close(); - throw e; - } catch (InvalidLicenseFile e) { - application.close(); - throw e; - } catch (LicenseViolation e) { - application.close(); - throw e; - } - } + // Creates application, because a running one was not found + WebApplicationContext context = WebApplicationContext + .getApplicationContext(request.getSession()); + URL applicationUrl = getApplicationUrl(request); + + // Creates new application and start it + try { + Application application = (Application) this.applicationClass + .newInstance(); + context.addApplication(application); + + // Sets initial locale from the request + application.setLocale(request.getLocale()); + + // Starts application and check license + initializeLicense(application); + application.start(applicationUrl, this.applicationProperties, + context); + checkLicense(application); + + return application; + + } catch (IllegalAccessException e) { + Log.error("Illegal access to application class " + + this.applicationClass.getName()); + throw e; + } catch (InstantiationException e) { + Log.error("Failed to instantiate application class: " + + this.applicationClass.getName()); + throw e; + } + } + + /** + * + * @param application + */ + private void initializeLicense(Application application) { + License license; + synchronized (licenseForApplicationClass) { + license = (License) licenseForApplicationClass.get(application + .getClass()); + if (license == null) { + license = new License(); + licenseForApplicationClass.put(application.getClass(), license); + } + } + application.setToolkitLicense(license); + } + + /** + * + * @param application + * @throws LicenseFileHasNotBeenRead + * if the license file has not been read. + * @throws LicenseSignatureIsInvalid + * if the license file has been changed or signature is + * otherwise invalid. + * @throws InvalidLicenseFile + * if the license file is not of correct XML format. + * @throws LicenseViolation + * + * @throws SAXException + * the Error parsing the license file. + */ + private void checkLicense(Application application) + throws LicenseFileHasNotBeenRead, LicenseSignatureIsInvalid, + InvalidLicenseFile, LicenseViolation, SAXException { + License license = application.getToolkitLicense(); + + if (!license.hasBeenRead()) + // Lock threads that have not yet read license + synchronized (license) { + if (!license.hasBeenRead()) { + InputStream lis; + try { + URL url = getServletContext().getResource( + "/WEB-INF/itmill-toolkit-license.xml"); + if (url == null) { + throw new RuntimeException( + "License file could not be read. " + + "You can install it to " + + "WEB-INF/itmill-toolkit-license.xml."); } + lis = url.openStream(); + license.readLicenseFile(lis); + } catch (MalformedURLException e) { + // This should not happen + throw new RuntimeException(e); + } catch (IOException e) { + // This should not happen + throw new RuntimeException(e); + } + + // For each application class, print license description - + // once + if (!licensePrintedForApplicationClass + .containsKey(applicationClass)) { + licensePrintedForApplicationClass.put(applicationClass, + Boolean.TRUE); + if (license.shouldLimitsBePrintedOnInit()) { + System.out.println(license + .getDescription(application.getClass() + .toString())); + } + } - // Checks concurrent user limit - try { - license.checkConcurrentUsers(getNumberOfActiveUsers() + 1); - } catch (LicenseViolation e) { + // Checks license validity + try { + license.check(applicationClass, VERSION_MAJOR, + VERSION_MINOR, "IT Mill Toolkit", null); + } catch (LicenseFileHasNotBeenRead e) { + application.close(); + throw e; + } catch (LicenseSignatureIsInvalid e) { + application.close(); + throw e; + } catch (InvalidLicenseFile e) { application.close(); throw e; + } catch (LicenseViolation e) { + application.close(); + throw e; + } } + } + + // Checks concurrent user limit + try { + license.checkConcurrentUsers(getNumberOfActiveUsers() + 1); + } catch (LicenseViolation e) { + application.close(); + throw e; } - - /** - * Gets the number of active application-user pairs. - * - * This returns total number of all applications in the server that are - * considered to be active. For an application to be active, it must have - * been accessed less than ACTIVE_USER_REQUEST_INTERVAL ms. - * - * @return the Number of active application instances in the server. - */ - private int getNumberOfActiveUsers() { - int active = 0; - - synchronized (applicationToLastRequestDate) { - Set apps = applicationToLastRequestDate.keySet(); - long now = System.currentTimeMillis(); - for (Iterator i = apps.iterator(); i.hasNext();) { - Date lastReq = (Date) applicationToLastRequestDate - .get(i.next()); - if (now - lastReq.getTime() < ACTIVE_USER_REQUEST_INTERVAL) - active++; - } - } - - return active; + } + + /** + * Gets the number of active application-user pairs. + * + * This returns total number of all applications in the server that are + * considered to be active. For an application to be active, it must have + * been accessed less than ACTIVE_USER_REQUEST_INTERVAL ms. + * + * @return the Number of active application instances in the server. + */ + private int getNumberOfActiveUsers() { + int active = 0; + + synchronized (applicationToLastRequestDate) { + Set apps = applicationToLastRequestDate.keySet(); + long now = System.currentTimeMillis(); + for (Iterator i = apps.iterator(); i.hasNext();) { + Date lastReq = (Date) applicationToLastRequestDate + .get(i.next()); + if (now - lastReq.getTime() < ACTIVE_USER_REQUEST_INTERVAL) + active++; + } } - /** - * Ends the application. - * - * @param request - * the HTTP request. - * @param response - * the HTTP response to write to. - * @param application - * the application to end. - * @throws IOException - * if the writing failed due to input/output error. - */ - private void endApplication(HttpServletRequest request, - HttpServletResponse response, Application application) - throws IOException { - - String logoutUrl = application.getLogoutURL(); - if (logoutUrl == null) - logoutUrl = application.getURL().toString(); - - HttpSession session = request.getSession(); - if (session != null) { - WebApplicationContext.getApplicationContext(session).removeApplication(application); - } + return active; + } + + /** + * Ends the application. + * + * @param request + * the HTTP request. + * @param response + * the HTTP response to write to. + * @param application + * the application to end. + * @throws IOException + * if the writing failed due to input/output error. + */ + private void endApplication(HttpServletRequest request, + HttpServletResponse response, Application application) + throws IOException { + + String logoutUrl = application.getLogoutURL(); + if (logoutUrl == null) + logoutUrl = application.getURL().toString(); + + HttpSession session = request.getSession(); + if (session != null) { + WebApplicationContext.getApplicationContext(session) + .removeApplication(application); + } - response.sendRedirect(response.encodeRedirectURL(logoutUrl)); + response.sendRedirect(response.encodeRedirectURL(logoutUrl)); + } + + /** + * Gets the existing application or create a new one. Get a window within an + * application based on the requested URI. + * + * @param request + * the HTTP Request. + * @param application + * the Application to query for window. + * @return Window matching the given URI or null if not found. + * @throws ServletException + * if an exception has occurred that interferes with the + * servlet's normal operation. + */ + private Window getApplicationWindow(HttpServletRequest request, + Application application) throws ServletException { + + Window window = null; + + // Finds the window where the request is handled + String path = request.getPathInfo(); + + // Main window as the URI is empty + if (path == null || path.length() == 0 || path.equals("/")) + window = application.getMainWindow(); + + // Try to search by window name + else { + String windowName = null; + if (path.charAt(0) == '/') + path = path.substring(1); + int index = path.indexOf('/'); + if (index < 0) { + windowName = path; + path = ""; + } else { + windowName = path.substring(0, index); + path = path.substring(index + 1); + } + window = application.getWindow(windowName); + + if (window == null) { + // By default, we use main window + window = application.getMainWindow(); + } else if (!window.isVisible()) { + // Implicitly painting without actually invoking paint() + window.requestRepaintRequests(); + + // If the window is invisible send a blank page + return null; + } } - /** - * Gets the existing application or create a new one. Get a window within an - * application based on the requested URI. - * - * @param request - * the HTTP Request. - * @param application - * the Application to query for window. - * @return Window matching the given URI or null if not found. - * @throws ServletException - * if an exception has occurred that interferes with the - * servlet's normal operation. - */ - private Window getApplicationWindow(HttpServletRequest request, - Application application) throws ServletException { - - Window window = null; - - // Finds the window where the request is handled - String path = request.getPathInfo(); - - // Main window as the URI is empty - if (path == null || path.length() == 0 || path.equals("/")) - window = application.getMainWindow(); - - // Try to search by window name - else { - String windowName = null; - if (path.charAt(0) == '/') - path = path.substring(1); - int index = path.indexOf('/'); - if (index < 0) { - windowName = path; - path = ""; - } else { - windowName = path.substring(0, index); - path = path.substring(index + 1); - } - window = application.getWindow(windowName); + return window; + } + + /** + * Gets relative location of a theme resource. + * + * @param theme + * the Theme name. + * @param resource + * the Theme resource. + * @return External URI specifying the resource + */ + public String getResourceLocation(String theme, ThemeResource resource) { + + if (resourcePath == null) + return resource.getResourceId(); + return resourcePath + theme + "/" + resource.getResourceId(); + } + + /** + * Checks if web adapter is in debug mode. Extra output is generated to log + * when debug mode is enabled. + * + * @param parameters + * @return <code>true</code> if the web adapter is in debug mode. + * otherwise <code>false</code>. + */ + public boolean isDebugMode(Map parameters) { + if (parameters != null) { + Object[] debug = (Object[]) parameters.get("debug"); + if (debug != null && !"false".equals(debug[0].toString()) + && !"false".equals(debugMode)) + return true; + } + return "true".equals(debugMode); + } - if (window == null) { - // By default, we use main window - window = application.getMainWindow(); - } else if (!window.isVisible()) { - // Implicitly painting without actually invoking paint() - window.requestRepaintRequests(); + /** + * Implementation of ParameterHandler.ErrorEvent interface. + */ + public class ParameterHandlerErrorImpl implements + ParameterHandler.ErrorEvent { - // If the window is invisible send a blank page - return null; - } - } + private ParameterHandler owner; - return window; - } + private Throwable throwable; /** - * Gets relative location of a theme resource. + * Gets the contained throwable. * - * @param theme - * the Theme name. - * @param resource - * the Theme resource. - * @return External URI specifying the resource + * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable() */ - public String getResourceLocation(String theme, ThemeResource resource) { - - if (resourcePath == null) - return resource.getResourceId(); - return resourcePath + theme + "/" + resource.getResourceId(); + public Throwable getThrowable() { + return this.throwable; } /** - * Checks if web adapter is in debug mode. Extra output is generated to log - * when debug mode is enabled. + * Gets the source ParameterHandler. * - * @param parameters - * @return <code>true</code> if the web adapter is in debug mode. - * otherwise <code>false</code>. + * @see com.itmill.toolkit.terminal.ParameterHandler.ErrorEvent#getParameterHandler() */ - public boolean isDebugMode(Map parameters) { - if (parameters != null) { - Object[] debug = (Object[]) parameters.get("debug"); - if (debug != null && !"false".equals(debug[0].toString()) - && !"false".equals(debugMode)) - return true; - } - return "true".equals(debugMode); + public ParameterHandler getParameterHandler() { + return this.owner; } + } - /** - * Implementation of ParameterHandler.ErrorEvent interface. - */ - public class ParameterHandlerErrorImpl implements - ParameterHandler.ErrorEvent { - - private ParameterHandler owner; - - private Throwable throwable; + /** + * Implementation of URIHandler.ErrorEvent interface. + */ + public class URIHandlerErrorImpl implements URIHandler.ErrorEvent { + private URIHandler owner; - /** - * Gets the contained throwable. - * - * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable() - */ - public Throwable getThrowable() { - return this.throwable; - } - - /** - * Gets the source ParameterHandler. - * - * @see com.itmill.toolkit.terminal.ParameterHandler.ErrorEvent#getParameterHandler() - */ - public ParameterHandler getParameterHandler() { - return this.owner; - } - - } + private Throwable throwable; /** - * Implementation of URIHandler.ErrorEvent interface. + * + * @param owner + * @param throwable */ - public class URIHandlerErrorImpl implements URIHandler.ErrorEvent { - - private URIHandler owner; - - private Throwable throwable; - - /** - * - * @param owner - * @param throwable - */ - private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) { - this.owner = owner; - this.throwable = throwable; - } - - /** - * Gets the contained throwable. - * - * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable() - */ - public Throwable getThrowable() { - return this.throwable; - } - - /** - * Gets the source URIHandler. - * - * @see com.itmill.toolkit.terminal.URIHandler.ErrorEvent#getURIHandler() - */ - public URIHandler getURIHandler() { - return this.owner; - } + private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) { + this.owner = owner; + this.throwable = throwable; } /** - * Gets AJAX application manager for an application. - * - * If this application has not been running in ajax mode before, new manager - * is created and web adapter stops listening to changes. + * Gets the contained throwable. * - * @param application - * @return AJAX Application Manager + * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable() */ - private CommunicationManager getApplicationManager(Application application) { - CommunicationManager mgr = (CommunicationManager) applicationToAjaxAppMgrMap - .get(application); - - // This application is going from Web to AJAX mode, create new manager - if (mgr == null) { - // Creates new manager - mgr = new CommunicationManager(application, this); - applicationToAjaxAppMgrMap.put(application, mgr); - - // Manager takes control over the application - mgr.takeControl(); - } - - return mgr; + public Throwable getThrowable() { + return this.throwable; } /** - * Gets resource path using different implementations. Required fo - * supporting different servlet container implementations (application - * servers). + * Gets the source URIHandler. * - * @param servletContext - * @param path - * the resource path. - * @return the resource path. + * @see com.itmill.toolkit.terminal.URIHandler.ErrorEvent#getURIHandler() */ - protected static String getResourcePath(ServletContext servletContext, - String path) { - String resultPath = null; - resultPath = servletContext.getRealPath(path); - if (resultPath != null) { - return resultPath; - } else { - try { - URL url = servletContext.getResource(path); - resultPath = url.getFile(); - } catch (Exception e) { - // ignored - } - } - return resultPath; + public URIHandler getURIHandler() { + return this.owner; + } + } + + /** + * Gets AJAX application manager for an application. + * + * If this application has not been running in ajax mode before, new manager + * is created and web adapter stops listening to changes. + * + * @param application + * @return AJAX Application Manager + */ + private CommunicationManager getApplicationManager(Application application) { + CommunicationManager mgr = (CommunicationManager) applicationToAjaxAppMgrMap + .get(application); + + // This application is going from Web to AJAX mode, create new manager + if (mgr == null) { + // Creates new manager + mgr = new CommunicationManager(application, this); + applicationToAjaxAppMgrMap.put(application, mgr); + + // Manager takes control over the application + mgr.takeControl(); + } + + return mgr; + } + + /** + * Gets resource path using different implementations. Required fo + * supporting different servlet container implementations (application + * servers). + * + * @param servletContext + * @param path + * the resource path. + * @return the resource path. + */ + protected static String getResourcePath(ServletContext servletContext, + String path) { + String resultPath = null; + resultPath = servletContext.getRealPath(path); + if (resultPath != null) { + return resultPath; + } else { + try { + URL url = servletContext.getResource(path); + resultPath = url.getFile(); + } catch (Exception e) { + // ignored + } } + return resultPath; + } }
\ No newline at end of file |