public boolean usePortletURLs() {
return usePortletURLs;
}
-
+
public String getPortletUidlURLBase() {
return portletUidlURLBase;
}
-
+
public String getRootPanelId() {
return id;
}
+ /**
+ * Gets the application base URI. Using this other than as the download
+ * action URI can cause problems in Portlet 2.0 deployments.
+ *
+ * @return application base URI
+ */
public String getApplicationUri() {
return appUri;
}
} else {
$wnd.alert("Vaadin app failed to initialize: " + this.id);
}
-
+
}-*/;
/**
* Inits the ApplicationConfiguration by reading the DOM and instantiating
* ApplicationConnections accordingly. Call {@link #startNextApplication()}
* to actually start the applications.
- *
+ *
* @param widgetset
* the widgetset that is running the apps
*/
* once to start the first application; after that, each application should
* call this once it has started. This ensures that the applications are
* started synchronously, which is neccessary to avoid session-id problems.
- *
+ *
* @return true if an unstarted application was found
*/
public static boolean startNextApplication() {
* This is the client side communication "engine", managing client-server
* communication with its server side counterpart
* {@link AbstractCommunicationManager}.
- *
+ *
* Client-side widgets receive updates from the corresponding server-side
* components as calls to
* {@link Paintable#updateFromUIDL(UIDL, ApplicationConnection)} (not to be
* confused with the server side interface {@link com.vaadin.terminal.Paintable}
* ). Any client-side changes (typically resulting from user actions) are sent
* back to the server as variable changes (see {@link #updateVariable()}).
- *
+ *
* TODO document better
- *
+ *
* Entry point classes (widgetsets) define <code>onModuleLoad()</code>.
*/
public class ApplicationConnection {
* <li><code>vaadin.postRequestHooks</code> is a map of functions which gets
* called after each XHR made by vaadin application. Note, that it is
* attaching js functions responsibility to create the variable like this:
- *
+ *
* <code><pre>
* if(!vaadin.postRequestHooks) {vaadin.postRequestHooks = new Object();}
* postRequestHooks.myHook = function(appId) {
* </pre></code> First parameter passed to these functions is the identifier
* of Vaadin application that made the request.
* </ul>
- *
+ *
* TODO make this multi-app aware
*/
private native void initializeClientHooks()
/**
* Runs possibly registered client side post request hooks. This is expected
* to be run after each uidl request made by Vaadin application.
- *
+ *
* @param appId
*/
private static native void runPostRequestHooks(String appId)
/**
* Checks if client side is in debug mode. Practically this is invoked by
* adding ?debug parameter to URI.
- *
+ *
* @return true if client side is currently been debugged
*/
public native static boolean isDebugMode()
return re.test(uri);
}-*/;
+ /**
+ * Gets the application base URI. Using this other than as the download
+ * action URI can cause problems in Portlet 2.0 deployments.
+ *
+ * @return application base URI
+ */
public String getAppUri() {
return configuration.getApplicationUri();
};
/**
* Shows the communication error notification. The 'details' only go to the
* console for now.
- *
+ *
* @param details
* Optional details for debugging.
*/
/**
* This method is called after applying uidl change set to application.
- *
+ *
* It will clean current and queued variable change sets. And send next
* change set if it exists.
*/
/**
* Cleans given queue of variable changes of such changes that came from
* components that do not exist anymore.
- *
+ *
* @param variableBurst
*/
private void cleanVariableBurst(ArrayList<String> variableBurst) {
/**
* Returns Paintable element by its id
- *
+ *
* @param id
* Paintable ID
*/
/**
* This method sends currently queued variable changes to server. It is
* called when immediate variable update must happen.
- *
+ *
* To ensure correct order for variable changes (due servers multithreading
* or network), we always wait for active request to be handler before
* sending a new one. If there is an active request, we will put varible
* "burst" to queue that will be purged after current request is handled.
- *
+ *
*/
@SuppressWarnings("unchecked")
public void sendPendingVariableChanges() {
/**
* Build the variable burst and send it to server.
- *
+ *
* When sync is forced, we also force sending of all pending variable-bursts
* at the same time. This is ok as we can assume that DOM will never be
* updated after this.
- *
+ *
* @param pendingVariables
* Vector of variable changes to send
* @param forceSync
/**
* Update generic component features.
- *
+ *
* <h2>Selecting correct implementation</h2>
- *
+ *
* <p>
* The implementation of a component depends on many properties, including
* styles, component features, etc. Sometimes the user changes those
* the beginning of your updateFromUIDL -method automatically replaces your
* component with more appropriate if the requested implementation changes.
* </p>
- *
+ *
* <h2>Caption, icon, error messages and description</h2>
- *
+ *
* <p>
* Component can delegate management of caption, icon, error messages and
* description to parent layout. This is optional an should be decided by
* component author
* </p>
- *
+ *
* <h2>Component visibility and disabling</h2>
- *
+ *
* This method will manage component visibility automatically and if
* component is an instanceof FocusWidget, also handle component disabling
* when needed.
- *
+ *
* @param component
* Widget to be updated, expected to implement an instance of
* Paintable
* @param manageCaption
* True if you want to delegate caption, icon, description and
* error message management to parent.
- *
+ *
* @return Returns true iff no further painting is needed by caller
*/
public boolean updateComponent(Widget component, UIDL uidl,
/**
* Traverses recursively child widgets until ContainerResizedListener child
* widget is found. They will delegate it further if needed.
- *
+ *
* @param container
*/
private boolean runningLayout = false;
/**
* Converts relative sizes into pixel sizes.
- *
+ *
* @param child
* @return true if the child has a relative size
*/
/**
* Converts relative sizes into pixel sizes.
- *
+ *
* @param child
* @return true if the child has a relative size
*/
/**
* Get either existing or new Paintable for given UIDL.
- *
+ *
* If corresponding Paintable has been previously painted, return it.
* Otherwise create and register a new Paintable from UIDL. Caller must
* update the returned Paintable from UIDL after it has been connected to
* parent.
- *
+ *
* @param uidl
* UIDL to create Paintable from.
* @return Either existing or new Paintable corresponding to UIDL.
/**
* Returns a Paintable element by its root element
- *
+ *
* @param element
* Root element of the paintable
*/
/**
* Singleton method to get instance of app's context menu.
- *
+ *
* @return VContextMenu object
*/
public VContextMenu getContextMenu() {
* Translates custom protocols in UIDL URI's to be recognizable by browser.
* All uri's from UIDL should be routed via this method before giving them
* to browser due URI's in UIDL may contain custom protocols like theme://.
- *
+ *
* @param uidlUri
* Vaadin URI from uidl
* @return translated URI ready for browser
/**
* Listens for Notification hide event, and redirects. Used for system
* messages, such as session expired.
- *
+ *
*/
private class NotificationRedirect implements VNotification.EventListener {
String url;
/**
* Data showed in tooltips are stored centrilized as it may be needed in
* varios place: caption, layouts, and in owner components themselves.
- *
+ *
* Updating TooltipInfo is done in updateComponent method.
- *
+ *
*/
public TooltipInfo getTooltipTitleInfo(Paintable titleOwner, Object key) {
if (null == titleOwner) {
* Component may want to delegate Tooltip handling to client. Layouts add
* Tooltip (description, errors) to caption, but some components may want
* them to appear one other elements too.
- *
+ *
* Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
+ *
* @param event
* @param owner
*/
* Component may want to delegate Tooltip handling to client. Layouts add
* Tooltip (description, errors) to caption, but some components may want
* them to appear one other elements too.
- *
+ *
* Events wanted by this handler are same as in Tooltip.TOOLTIP_EVENTS
- *
+ *
* @param event
* @param owner
* @param key
/**
* Adds PNG-fix conditionally (only for IE6) to the specified IMG -element.
- *
+ *
* @param el
* the IMG element to fix
*/
* Reset the name of the current browser-window. This should reflect the
* window-name used in the server, but might be different from the
* window-object target-name on client.
- *
+ *
* @param stringAttribute
* New name for the window.
*/
* <p>
* This method can also be used to deregister tooltips by using null as
* tooltip
- *
+ *
* @param paintable
* Paintable "owning" this tooltip
* @param key
* key assosiated with given tooltip. Can be any object. For
* example a related dom element. Same key must be given for
* {@link #handleTooltipEvent(Event, Paintable, Object)} method.
- *
+ *
* @param tooltip
* the TooltipInfo object containing details shown in tooltip,
* null if deregistering tooltip
return defaultValue;
}
+ /**
+ * Return the URL from where static files, e.g. the widgetset and the theme,
+ * are served. In a standard configuration the VAADIN folder inside the
+ * returned folder is what is used for widgetsets and themes.
+ *
+ * @param request
+ * @return The location of static resources (inside which there should be a
+ * VAADIN directory). Does not end with a slash (/).
+ */
+ private String getStaticFilesLocation(PortletRequest request) {
+ // TODO allow overriding on portlet level?
+ String staticFileLocation = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH, request
+ .getPortalContext());
+ if (staticFileLocation != null) {
+ // remove trailing slash if any
+ while (staticFileLocation.endsWith(".")) {
+ staticFileLocation = staticFileLocation.substring(0,
+ staticFileLocation.length() - 1);
+ }
+ return staticFileLocation;
+ } else {
+ // default for Liferay
+ return "/html";
+ }
+ }
+
enum RequestType {
FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, UNKNOWN;
}
protected void handleRequest(PortletRequest request,
PortletResponse response) throws PortletException, IOException {
- // System.out.println("AbstractApplicationPortlet.handleRequest() "
- // + System.currentTimeMillis());
-
RequestType requestType = getRequestType(request);
- // System.out.println(" RequestType: " + requestType);
- // System.out.println(" WindowID: " + request.getWindowID());
-
if (requestType == RequestType.UNKNOWN) {
System.err.println("Unknown request type");
} else if (requestType == RequestType.DUMMY) {
- // System.out.println("Printing Dummy page");
/*
* This dummy page is used by action responses to redirect to, in
* order to prevent the boot strap code from being rendered into
/ 1000);
response.setProperty("Expires", "" + System.currentTimeMillis()
+ cacheTime);
- response.setProperty("Pragma", "cache"); // Required to apply
- // caching in some
- // Tomcats
+ // Required to apply caching in some Tomcats
+ response.setProperty("Pragma", "cache");
}
// Copy download stream parameters directly
final String resourceID = request.getResourceID();
final PortletContext pc = getPortletContext();
- // System.out.println("Trying to load resource [" + resourceID + "]");
-
InputStream is = pc.getResourceAsStream(resourceID);
if (is != null) {
final String mimetype = pc.getMimeType(resourceID);
.getApplicationContext(session);
final Collection<Application> applications = context.getApplications();
- for (final Iterator<Application> i = applications.iterator(); i
- .hasNext();) {
- final Application sessionApplication = i.next();
+ for (Application sessionApplication : applications) {
if (request.getWindowID().equals(
sessionApplication.getPortletWindowId())) {
if (sessionApplication.isRunning()) {
}
protected String getWidgetsetURL(String widgetset, PortletRequest request) {
- // TODO The widgetset URL is currently hard-corded for LifeRay
- return "/html/" + WIDGETSET_DIRECTORY_PATH + widgetset + "/"
+ return getStaticFilesLocation(request) + "/" + WIDGETSET_DIRECTORY_PATH
+ + widgetset + "/"
+ widgetset + ".nocache.js?" + new Date().getTime();
}
protected String getThemeURI(String themeName, PortletRequest request) {
- // TODO The theme URI is currently hard-corded for LifeRay
- return "/html/" + THEME_DIRECTORY_PATH + themeName;
+ return getStaticFilesLocation(request) + "/" + THEME_DIRECTORY_PATH
+ + themeName;
}
protected void writeAjaxPage(RenderRequest request,
RenderResponse response, Window window, Application application)
throws IOException, MalformedURLException, PortletException {
- System.out.println("writeAjaxPage");
-
response.setContentType("text/html");
final BufferedWriter page = new BufferedWriter(new OutputStreamWriter(
response.getPortletOutputStream(), "UTF-8"));
+ // TODO this is broken, not set as no servlet
String requestWidgetset = (String) request
.getAttribute(AbstractApplicationServlet.REQUEST_WIDGETSET);
- String sharedWidgetset = (String) request
- .getAttribute(AbstractApplicationServlet.REQUEST_SHARED_WIDGETSET);
+
+ String sharedWidgetset = getPortalProperty(
+ PORTAL_PARAMETER_VAADIN_WIDGETSET, request.getPortalContext());
if (requestWidgetset == null && sharedWidgetset == null) {
requestWidgetset = getApplicationOrSystemProperty(
PARAMETER_WIDGETSET, DEFAULT_WIDGETSET);
String widgetsetURL = getWidgetsetURL(widgetset, request);
String themeURI = getThemeURI(themeName, request);
- //System.out.println("themeName : " + themeName);
- //System.out.println("widgetsetURL : " + widgetsetURL);
- //System.out.println("themeURI : " + themeURI);
-
// fixed base theme to use - all portal pages with Vaadin
// applications will load this exactly once
String portalTheme = getPortalProperty(PORTAL_PARAMETER_VAADIN_THEME,
/*
* We need this in order to get uploads to work.
- *
- * TODO This may cause weird side effects on other places where appUri
- * is used!
*/
PortletURL appUri = response.createActionURL();
portalTheme = DEFAULT_THEME_NAME;
}
-// System.out.println("Printing default portal theme " + portalTheme);
-
page.write("if(!vaadin.themesLoaded['" + portalTheme + "']) {\n");
page.write("var defaultStylesheet = document.createElement('link');\n");
page.write("defaultStylesheet.setAttribute('rel', 'stylesheet');\n");
// Finds theme name
String themeName;
- if (request.getParameter(URL_PARAMETER_THEME) != null) {
- themeName = request.getParameter(URL_PARAMETER_THEME);
- } else {
- themeName = window.getTheme();
+ // theme defined for the window?
+ themeName = window.getTheme();
+
+ if (themeName == null) {
+ // no, is the default theme defined by the portal?
+ themeName = getPortalProperty(
+ Constants.PORTAL_PARAMETER_VAADIN_THEME, request
+ .getPortalContext());
}
if (themeName == null) {
- // no explicit theme for window defined
- if (request
- .getAttribute(AbstractApplicationServlet.REQUEST_DEFAULT_THEME) != null) {
- // the default theme is defined in request (by portal)
- themeName = (String) request
- .getAttribute(AbstractApplicationServlet.REQUEST_DEFAULT_THEME);
- } else {
- // using the default theme defined by Vaadin
- themeName = DEFAULT_THEME_NAME;
- }
+ // no, using the default theme defined by Vaadin
+ themeName = DEFAULT_THEME_NAME;
}
+
return themeName;
}
out.flush();
}
- private String getPortalProperty(String name, PortalContext context) {
+ private static String getPortalProperty(String name, PortalContext context) {
boolean isLifeRay = context.getPortalInfo().toLowerCase().contains(
"liferay");
return value;
}
- private String getLifeRayPortalProperty(String name) {
+ private static String getLifeRayPortalProperty(String name) {
String value;
try {
value = PropsUtil.get(name);
* @param request
* @return The location of static resources (should contain the VAADIN
* directory). Never ends with a slash (/).
- * @throws MalformedURLException
*/
- String getStaticFilesLocation(HttpServletRequest request) {
+ private String getStaticFilesLocation(HttpServletRequest request) {
// request may have an attribute explicitly telling location (portal
// case)
String staticFileLocation = (String) request
.getAttribute(REQUEST_VAADIN_STATIC_FILE_PATH);
if (staticFileLocation != null) {
+ // TODO remove trailing slash if any?
return staticFileLocation;
}
private static final String PORTLET_PARAMETER_STYLE = "style";\r
private static final String PORTLET_PARAMETER_WIDGETSET = "widgetset";\r
\r
- // portal configuration parameters\r
- private static final String PORTAL_PARAMETER_VAADIN_WIDGETSET = "vaadin.widgetset";\r
- private static final String PORTAL_PARAMETER_VAADIN_RESOURCE_PATH = "vaadin.resources.path";\r
- private static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";\r
-\r
// The application to show\r
protected String app = null;\r
// some applications might require forced height (and, more seldom, width)\r
// fixed base theme to use - all portal pages with Vaadin\r
// applications will load this exactly once\r
String portalTheme = getPortalProperty(\r
- PORTAL_PARAMETER_VAADIN_THEME, portalCtx);\r
+ Constants.PORTAL_PARAMETER_VAADIN_THEME, portalCtx);\r
\r
String portalWidgetset = getPortalProperty(\r
- PORTAL_PARAMETER_VAADIN_WIDGETSET, portalCtx);\r
+ Constants.PORTAL_PARAMETER_VAADIN_WIDGETSET, portalCtx);\r
\r
// location of the widgetset(s) and default theme (to which\r
// /VAADIN/widgetsets/...\r
// is appended)\r
String portalResourcePath = getPortalProperty(\r
- PORTAL_PARAMETER_VAADIN_RESOURCE_PATH, portalCtx);\r
+ Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH,\r
+ portalCtx);\r
\r
if (portalResourcePath != null) {\r
// if portalResourcePath is defined, set it as a request\r
/**
* TODO Document me!
- *
+ *
* @author peholmst
- *
+ *
*/
public interface Constants {
+ "===========================================================\n"
+ "WARNING: Cross-site request forgery protection is disabled!\n"
+ "===========================================================";
-
+
static final String URL_PARAMETER_RESTART_APPLICATION = "restartApplication";
static final String URL_PARAMETER_CLOSE_APPLICATION = "closeApplication";
static final String URL_PARAMETER_REPAINT_ALL = "repaintAll";
static final String INVALID_SECURITY_KEY_MSG = "Invalid security key.";
+ // portal configuration parameters
+ static final String PORTAL_PARAMETER_VAADIN_WIDGETSET = "vaadin.widgetset";
+ static final String PORTAL_PARAMETER_VAADIN_RESOURCE_PATH = "vaadin.resources.path";
+ static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
+
}
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
-
import com.vaadin.Application;
import com.vaadin.service.ApplicationContext;
/**
* TODO Write documentation, fix JavaDoc tags.
- *
+ *
+ * TODO is implementing HttpSessionBindingListener correct/useful?
+ *
* @author peholmst
*/
@SuppressWarnings("serial")
protected HashMap<Application, PortletCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, PortletCommunicationManager>();
- public void addTransactionListener(TransactionListener listener) {
- if (listeners == null) {
- listeners = new LinkedList<TransactionListener>();
- }
- listeners.add(listener);
- }
-
public Collection<Application> getApplications() {
return Collections.unmodifiableCollection(applications);
}
return null;
}
+ public void addTransactionListener(TransactionListener listener) {
+ if (listeners == null) {
+ listeners = new LinkedList<TransactionListener>();
+ }
+ listeners.add(listener);
+ }
+
public void removeTransactionListener(TransactionListener listener) {
if (listeners != null) {
listeners.remove(listener);