From 5c0d7fa3fa0476e1a2e465295540d16b339f4499 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Tue, 18 Sep 2007 14:31:18 +0000 Subject: [PATCH] Widgetset extension changes, reservr example svn changeset:2312/svn branch:trunk --- .../toolkit/demo/reservation/GoogleMap.java | 215 ++ .../reservation/ReservationApplication.java | 16 +- .../demo/reservation/gwt/WidgetSet.gwt.xml | 2 +- ...etSet.gwt.xml => DefaultWidgetSet.gwt.xml} | 2 +- ...wt.xml => DefaultWidgetSetNoEntry.gwt.xml} | 1 - .../component-themes/button/css/button.css | 9 + .../public/component-themes/collection.css | 1 + .../gwt/server/ApplicationServlet.java | 1958 +++++++++-------- 8 files changed, 1231 insertions(+), 973 deletions(-) create mode 100644 src/com/itmill/toolkit/demo/reservation/GoogleMap.java rename src/com/itmill/toolkit/terminal/gwt/{WidgetSet.gwt.xml => DefaultWidgetSet.gwt.xml} (62%) rename src/com/itmill/toolkit/terminal/gwt/{WidgetSetNoEntry.gwt.xml => DefaultWidgetSetNoEntry.gwt.xml} (99%) create mode 100644 src/com/itmill/toolkit/terminal/gwt/public/component-themes/button/css/button.css 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 @@ - + diff --git a/src/com/itmill/toolkit/terminal/gwt/WidgetSet.gwt.xml b/src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSet.gwt.xml similarity index 62% rename from src/com/itmill/toolkit/terminal/gwt/WidgetSet.gwt.xml rename to 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 @@ - + diff --git a/src/com/itmill/toolkit/terminal/gwt/WidgetSetNoEntry.gwt.xml b/src/com/itmill/toolkit/terminal/gwt/DefaultWidgetSetNoEntry.gwt.xml similarity index 99% rename from src/com/itmill/toolkit/terminal/gwt/WidgetSetNoEntry.gwt.xml rename to 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 @@ - 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("\n"); - - page.write("\n\nIT Mill Toolkit 5\n" + - "\n" + - - ""+ - - "" + - - "" + - "\n\n" + - " \n" + - "
" + - " \n" + - "\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 true if the request was handled and - * further processing should be suppressed, false - * 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("\n"); + + page + .write("\n\nIT Mill Toolkit 5\n" + + "\n" + + "" + + "" + + "\n\n" + + " \n" + + "
" + + " \n" + "\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 true if the request was handled and + * further processing should be suppressed, false + * 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 true if the request was handled and + * further processing should be suppressed, false + * 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 true if the web adapter is in debug mode. + * otherwise false. + */ + 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 true if the web adapter is in debug mode. - * otherwise false. + * @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 -- 2.39.5