org.wings.session.Session Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2000,2005 wingS development team.
*
* This file is part of wingS (http://wingsframework.org).
*
* wingS is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* Please see COPYING for the complete licence.
*/
package org.wings.session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wings.*;
import org.wings.comet.Comet;
import org.wings.comet.CometWingServlet;
import org.wings.sdnd.SDragAndDropManager;
import org.wings.dnd.DragAndDropManager;
import org.wings.event.*;
import org.wings.externalizer.ExternalizeManager;
import org.wings.externalizer.ExternalizedResource;
import org.wings.plaf.*;
import org.wings.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.swing.event.EventListenerList;
import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.util.*;
import java.awt.datatransfer.Clipboard;
/**
* This class represents a wingS session meaning an application user session instance.
* Please do not mix this with a servlet {@link javax.servlet.http.HttpSession}!
* A wings Session is a session instance hold by the global {@link WingServlet} servlet. It aggregates all per--user-session
* data (mainly the root {@link SFrame}s and provides some information about the client like the browser {@link #getUserAgent()},
* the current character encoding {@link #getCharacterEncoding()} or the used Locale {@link #getLocale()}.
*
* @author Holger Engels
*/
public class Session implements PropertyService, Serializable {
private final static Logger log = LoggerFactory.getLogger(Session.class);
/**
* The property name of the locale
*/
public final static String LOCALE_PROPERTY = "locale";
/**
* The property name of the sessions character encoding
*/
public final static String CHARACTER_ENCODING_PROPERTY = "characterEncoding";
/**
* The property name of the look&feel
*/
public final static String LOOK_AND_FEEL_PROPERTY = "lookAndFeel";
private final SessionStatistics statistics = new SessionStatistics();
/**
* Every session has its own {@link CGManager}.
*
*/
private CGManager CGManager = new CGManager();
private SToolTipManager toolTipManager = new SToolTipManager();
private ReloadManager reloadManager = null;
private MenuManager menuManager = null;
private transient ExternalizeManager externalizeManager;
private LowLevelEventDispatcher dispatcher = new LowLevelEventDispatcher(this);
private final HashMap props = new HashMap<>();
private final HashSet frames = new HashSet<>();
private long uniqueIdCounter = 1;
/**
* Maximum upload content length. This is used by the {@link org.wings.session.SessionServlet}
* to avoid denial of service attacks.
*/
private int maxContentLength = 64;
private transient ServletContext servletContext;
private Browser browser;
protected transient HttpServletResponse servletResponse;
protected transient HttpServletRequest servletRequest;
private String redirectAddress;
private String exitAddress;
private Locale locale = Locale.getDefault();
private boolean localeFromHeader = true;
private DragAndDropManager dndManager;
private SDragAndDropManager sDndManager;
private Clipboard clipboard;
private SCursor cursor;
private ScriptManager scriptManager;
private Comet comet = null;
private HttpServlet wingServlet;
/**
* Which locales are supported by this servlet. If null, every locale from
* the userAgent is accepted. If not null only locales listed in this array
* are supported.
*/
private Locale[] supportedLocales = null;
/**
* The current character encoding used for the communication with the clients userAgent.
* If null
then the current characterEncoding is determined by the current
* session Locale via the charset.properties map.
*/
private String characterEncoding = null;
/**
* Store here only weak references.
*/
protected final EventListenerList listenerList = new EventListenerList();
private final WeakPropertyChangeSupport propertyChangeSupport = new WeakPropertyChangeSupport(this);
private ResourceMapper resourceMapper;
private Localizer localizer;
public final SessionStatistics getStatistics() {
return statistics;
}
static boolean collectStatistics = true;
static final SRequestListener SESSION_STATISTIC_COLLECTOR = e -> {
Session session = SessionManager.getSession();
if (session == null) {
/* while exiting or destroy() the session: it
* might already be null in the session manager.
*/
return;
}
switch (e.getType()) {
case SRequestEvent.DISPATCH_START:
session.statistics.startDispatching();
break;
case SRequestEvent.DISPATCH_DONE:
session.statistics.endDispatching();
break;
case SRequestEvent.DELIVER_START:
session.statistics.startDelivering();
break;
case SRequestEvent.DELIVER_DONE:
session.statistics.endDelivering();
break;
case SRequestEvent.REQUEST_START:
session.statistics.startRequest();
break;
case SRequestEvent.REQUEST_END:
session.statistics.endRequest();
break;
}
};
public Session() {
//log.debug("new session()");
if (collectStatistics) {
WingsStatistics.getStatistics().incrementSessionCount();
WingsStatistics.getStatistics().incrementActiveSessionCount();
WingsStatistics.getStatistics().incrementAllocatedSessionCount();
addRequestListener(SESSION_STATISTIC_COLLECTOR);
} // end of if ()
}
public Session(HttpServlet wingServlet) {
this();
this.wingServlet = wingServlet;
}
/**
* Detect user agent (userAgent). Copy init parameters. Set max content length for uploads / requests.
* Install look and feel.
*
* @param servletConfig a ServletConfig
value
* @param request a HttpServletRequest
value
* @param response
* @throws ServletException if an error occurs
*/
public void init(ServletConfig servletConfig, HttpServletRequest request, HttpServletResponse response) throws ServletException {
servletContext = request.getSession().getServletContext();
this.servletRequest = request;
this.servletResponse = response;
setUserAgentFromRequest(request);
if (isCometWingServletEnabled()) {
comet = new Comet(this, wingServlet);
comet.getConnectionManager().setBrowserId(request, response);
}
initProps(servletConfig);
initMaxContentLength();
try {
LookAndFeel lookAndFeel = LookAndFeelFactory.getLookAndFeelFactory().create();
CGManager.setLookAndFeel(lookAndFeel);
} catch (Exception ex) {
log.error("could not load look and feel: " +
servletContext.getInitParameter("wings.lookandfeel.factory"), ex);
throw new ServletException(ex);
}
}
/**
* Detect user agent (userAgent). Copy init parameters. Set max content length for uploads / requests.
* Install look and feel.
*
* @param request a HttpServletRequest
value
* @throws ServletException if an error occurs
*/
public void init(HttpServletRequest request) throws ServletException {
servletContext = request.getSession().getServletContext();
this.servletRequest = request;
setUserAgentFromRequest(request);
initProps(request.getSession().getServletContext());
initMaxContentLength();
try {
LookAndFeel lookAndFeel = LookAndFeelFactory.getLookAndFeelFactory().create();
CGManager.setLookAndFeel(lookAndFeel);
} catch (Exception ex) {
log.error("could not load look and feel: " +
servletContext.getInitParameter("wings.lookandfeel.factory"), ex);
throw new ServletException(ex);
}
}
protected void initMaxContentLength() {
String maxCL = servletContext.getInitParameter("content.maxlength");
if (maxCL != null) {
try {
maxContentLength = Integer.parseInt(maxCL);
} catch (NumberFormatException e) {
log.warn("invalid content.maxlength: " + maxCL, e);
}
}
}
/**
* Copy the init parameters.
*/
protected void initProps(ServletConfig servletConfig) {
Enumeration params = servletConfig.getInitParameterNames();
while (params.hasMoreElements()) {
String name = (String) params.nextElement();
props.put(name, servletConfig.getInitParameter(name));
}
}
protected void initProps(ServletContext servletContext) {
Enumeration params = servletContext.getInitParameterNames();
while (params.hasMoreElements()) {
String name = (String) params.nextElement();
props.put(name, servletContext.getInitParameter(name));
}
}
void setServletRequest(HttpServletRequest servletRequest) {
this.servletRequest = servletRequest;
}
public HttpServletRequest getServletRequest() {
return servletRequest;
}
/**
* Sets the current servlet response in progress. Used by wingS framework
*/
void setServletResponse(HttpServletResponse servletResponse) {
this.servletResponse = servletResponse;
}
/**
* The current HTTP servlet response which the framework will deliver
* after processing the current request. This is a part of the Servlet
* architecture.
*
* @return The current servlet response about to send to the client
*/
public HttpServletResponse getServletResponse() {
return servletResponse;
}
/**
* The current servlet context provided by the underlying
* servlet container.
* This value is retrieved from the initial servlet request
* for this session.
*
* @return The current servlet context provided by the underlying
* servlet container.
*/
public ServletContext getServletContext() {
return servletContext;
}
/**
* Override the current reload manager.
*
* @param reloadManager You customized reload manager implementation.
*/
public void setReloadManager(ReloadManager reloadManager) {
this.reloadManager = reloadManager;
}
/**
* The reload manager responsible for the component invalidation
* of the components contained in this wingS session. (Epoch counter)
*
* @return Lazily constructs {@link DefaultReloadManager} if no other reload
* manager has been set
*/
public ReloadManager getReloadManager() {
if (reloadManager == null)
reloadManager = new DefaultReloadManager();
return reloadManager;
}
public MenuManager getMenuManager() {
if (menuManager == null)
menuManager = new MenuManager();
return menuManager;
}
/**
* The Externalize manager is response to provide all {@link org.wings.Resource}
* via HTTP to the client.
*
* @return The externalize manager responsible to externalize all sort
* of resources contained in this session.
*/
public ExternalizeManager getExternalizeManager() {
if (externalizeManager == null)
externalizeManager = new ExternalizeManager();
return externalizeManager;
}
/**
* The Script manager collects scripts
*
* @return The script manager responsible to script all sort
* of resources contained in this session.
*/
public ScriptManager getScriptManager() {
if (scriptManager == null)
scriptManager = new ScriptManager();
return scriptManager;
}
/**
* The CG manager is responsible to provide the renderer implementation (aka. PLAF)
* for a given component class.
*
* @return The current CG manager
*/
public CGManager getCGManager() {
return CGManager;
}
/**
* @return The tooltip manager object containing configuration values on the components
* tooltip behaviour
*/
public SToolTipManager getToolTipManager() {
return toolTipManager;
}
/**
* Returns the current browser of the client detected by the
* User-Agent
parameter of the initial HTTP request
* for this user session.
*
* @return A {@link Browser} object providing browser type, os type and
* other informations from the HTTP User-Agent
string.
*/
public Browser getUserAgent() {
return browser;
}
/* * This would be a better naming!
* Returns the current browser of the client detected by the
* User-Agent
parameter of the initial HTTP request
* for this user session.
*
* @return A {@link Browser} object providing browser type, os type and
* other informations from the HTTP User-Agent
string.
* /
public Browser getBrowser() {
return browser;
} */
/**
* Describe setUserAgentFromRequest
method here.
*
* @param request a HttpServletRequest
value
*/
public void setUserAgentFromRequest(HttpServletRequest request) {
try {
final String userAgentString = request.getHeader("User-Agent");
browser = new Browser(userAgentString,request.getLocale());
log.debug("Browser is detected as " + browser+". User-Agent was: "+userAgentString);
log.debug("major version = "+browser.getMajorVersion()+", id = "+browser.getBrowserType().ordinal());
log.debug("short name = "+browser.getBrowserType().getName());
} catch (Exception ex) {
log.warn("Cannot get User-Agent from request", ex);
}
}
/**
* The low level event dispatcher is responsible for taking an HTTP request,
* parse it contents and delegate the so called low level events to the
* registered {@link org.wings.LowLevelEventListener}s (i.e. Buttons, etc.)
*
* @return The low level event dispatcher responsible for this session.
*/
public LowLevelEventDispatcher getDispatcher() {
return dispatcher;
}
/**
* Describe addFrame
method here.
*
* @param frame a SFrame
value
*/
public void addFrame(SFrame frame) {
frames.add(frame);
}
/**
* Describe removeFrame
method here.
*
* @param frame a SFrame
value
*/
public void removeFrame(SFrame frame) {
frames.remove(frame);
}
/**
* Describe frames
method here.
*
* @return a Set
value
*/
public Set getFrames() {
return Collections.unmodifiableSet(frames);
}
/**
* The root frame is the first shown frame.
*
* @return a SFrame
value
*/
public SFrame getRootFrame() {
if (frames.isEmpty())
return null;
SFrame rootFrame = frames.iterator().next();
while (rootFrame.getParent() != null)
rootFrame = (SFrame) rootFrame.getParent();
return rootFrame;
}
public SComponent getComponentByName( String name ) {
return getComponentByName( this.getRootFrame(), name );
}
/**
* Search in the given SContainer for the SComponent with the given name.
* @param container The SContainer where you want to search for the SComponent with the given name.
* @param name The Name of the SComponent
* @return the SComponent with the given name
*/
public static SComponent getComponentByName(SContainer container, String name) {
SComponent component = null;
SComponent[] components = container.getComponents();
for (SComponent component_x : components) {
if (component_x.getName().equals(name)) {
component = component_x;
break;
} else if (component_x instanceof SContainer) {
component = getComponentByName((SContainer) component_x, name);
if (component != null) {
break;
}
}
}
return component;
}
/**
* Describe getProperties
method here.
*
* @return a Map
value
*/
@Override
public final Map getProperties() {
return Collections.unmodifiableMap(props);
}
/**
* Gets the session property indicated by the specified key.
*
* @param key the name of the session property.
* @return the string value of the session property,
* or null
if there is no property with that key.
*/
@Override
public Object getProperty(String key) {
return props.get(key);
}
/**
* Gets the session property indicated by the specified key.
*
* @param key the name of the session property.
* @param def a default value.
* @return the string value of the session property,
* or the default value if there is no property with that key.
* @see org.wings.session.PropertyService#getProperties()
*/
@Override
public Object getProperty(String key, Object def) {
if (!props.containsKey(key)) {
return def;
} else {
return props.get(key);
}
}
/**
* Sets the session property indicated by the specified key.
*
* @param key the name of the session property.
* @param value the value of the session property.
* @return the previous value of the session property,
* or null
if it did not have one.
* @see org.wings.session.PropertyService#getProperty(java.lang.String)
* @see org.wings.session.PropertyService#getProperty(java.lang.String, java.lang.Object)
*/
@Override
public Object setProperty(String key, Object value) {
Object old = props.put(key, value);
propertyChangeSupport.firePropertyChange(key, old, value);
return old;
}
/* @see PropertyService */
@Override
public boolean containsProperty(String key) {
return props.containsKey(key);
}
/* @see PropertyService */
@Override
public Object removeProperty(String key) {
Object old = props.remove(key);
propertyChangeSupport.firePropertyChange(key, old, null);
return old;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
/**
* Describe addPropertyChangeListener
method here.
*
* @param propertyName a String
value
* @param listener a PropertyChangeListener
value
*/
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
}
/**
* Describe removePropertyChangeListener
method here.
*
* @param propertyName a String
value
* @param listener a PropertyChangeListener
value
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(propertyName, listener);
}
/**
* Sets the locale for this session. A property change event is fired, if the locale has actually changed.
*
* @param locale the locale to be associated with this session.
*/
public void setLocale(Locale locale) throws IllegalArgumentException {
Locale old = this.locale;
if (locale == null || this.locale.equals(locale))
return;
this.locale = locale;
propertyChangeSupport.firePropertyChange(LOCALE_PROPERTY, old, locale);
}
/**
* The Locale of the current session. This Locale reflects the Locale of the clients userAgent.
*
* @return a Locale
value
*/
public Locale getLocale() {
return locale;
}
/**
* Indicates if the wings session servlet should adopt the clients Locale provided by the
* browsers in the HTTP header.
*
* @param adoptLocale if true, try to determine, false ignore
*/
public final void setLocaleFromHeader(boolean adoptLocale) {
localeFromHeader = adoptLocale;
if (localeFromHeader)
determineLocale();
}
/**
* Indicates if the wings session servlet should adopt the clients Locale provided by the
* browsers in the HTTP header.
*/
public final boolean getLocaleFromHeader() {
return localeFromHeader;
}
/**
* sets the locales, supported by this application. If empty or null, all locales are supported.
*/
public final void setSupportedLocales(Locale... locales) {
supportedLocales = locales;
localeFromHeader = true;
determineLocale();
}
void determineLocale() {
if (supportedLocales == null) {
setLocale(servletRequest.getLocale());
}
Enumeration requestedLocales = servletRequest.getLocales();
if (supportedLocales != null) {
while (requestedLocales.hasMoreElements()) {
Locale locale = requestedLocales.nextElement();
for (Locale supportedLocale : supportedLocales) {
if (locale.equals(supportedLocale)) {
setLocale(supportedLocale);
return;
}
}
}
log.warn(buildLocaleNotSupportedMessage(servletRequest));
setLocale(supportedLocales[0]);
} else {
setLocale(requestedLocales.nextElement());
}
}
private static String buildLocaleNotSupportedMessage(ServletRequest servletRequest) {
Enumeration requestedLocales = servletRequest.getLocales();
StringBuilder sb = new StringBuilder();
sb.append("Locale(s) not supported:");
while (requestedLocales.hasMoreElements()) {
Locale locale = requestedLocales.nextElement();
sb.append(' ').append(locale);
}
return sb.toString();
}
/**
* Returns the locales, supported by this application. If empty or null, all locales are supported.
*/
public final Locale[] getSupportedLocales() {
return supportedLocales;
}
/**
* The current character encoding used for the communication with the clients userAgent.
* If null
then the current characterEncoding is determined by the current
* session Locale via the charset.properties map.
*
* @param characterEncoding The charcterEncoding which should be enforces for this session (i.e. "utf-8"),
* or null
if it should be determined by the clients userAgent Locale.
*/
public void setCharacterEncoding(String characterEncoding) {
String oldEncoding = this.characterEncoding;
this.characterEncoding = characterEncoding;
propertyChangeSupport.firePropertyChange(CHARACTER_ENCODING_PROPERTY, oldEncoding, characterEncoding);
}
/**
* The current character encoding used for the communication with the clients userAgent.
* If null
then the current characterEncoding is determined by the current
* session Locale via the charset.properties map.
*
* @return The characterEncoding set for this sesson or determined by the current Locale.
*/
public String getCharacterEncoding() {
if (this.characterEncoding == null) {
return LocaleCharSet.getInstance().getCharSet(locale);
} else {
return this.characterEncoding;
}
}
private final long getUniqueId() {
return uniqueIdCounter++;
}
/**
* Creates a session context unique ID, that can be used as an identifier,
* i.e. it is guaranteed to start with a letter
*
* @return a String
value
*/
public String createUniqueId() {
return StringUtil.toIdentifierString(getUniqueId());
}
/**
* Get the maximum content length (file size) for a post
* request.
*
* @return maximum size in kB (1024 Byte)
* @see org.wings.session.MultipartRequest
*/
public final int getMaxContentLength() {
return maxContentLength;
}
/**
* Set the maximum content length (file size) for a post
* request.
*
* @param l size in kB (1024 Byte)
* @see org.wings.session.MultipartRequest
*/
public final void setMaxContentLength(int l) {
maxContentLength = l;
}
protected void destroy() {
try {
firePrepareExit(true);
} catch (ExitVetoException ex) {
// ignore this, because no veto possible
}
if (collectStatistics) {
WingsStatistics.getStatistics().decrementActiveSessionCount();
} // end of if ()
/*
Iterator it = frames.iterator();
while (it.hasNext()) {
SContainer container = ((SFrame) it.next()).getContentPane();
if (container != null)
container.removeAll();
}
reloadManager.clear();
reloadManager = null;
if (externalizeManager != null) // eexternalizeManager is transient!
externalizeManager.clear();
externalizeManager = null;
dispatcher.clear();
dispatcher = null;
frames.clear();
props.clear();
*/
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
listenerList.remove((Class) listeners[i], (EventListener) listeners[i + 1]);
} // end of for (int i=0; i<; i++)
}
/**
* Exit the current session and redirect to other URL.
*
* This removes the session and its associated
* application from memory. The userAgent is redirected to the given
* URL. Note, that it is not even possible for the user to re-enter
* the application with the BACK-button, since all information is
* removed.
*
* Always exit an application by calling an
* exit()
method, especially, if it is an application
* that requires a login and thus handles sensitive information accessible
* through the session. Usually, you will call this on behalf of an
* event within an ActionListener.actionPerformed()
like for
* a pressed 'EXIT'-Button.
*
* @param redirectAddress the address, the userAgent is redirected after
* removing this session. This must be a String
* containing the complete URL (no relative URL)
* to the place to be redirected. If 'null', nothing
* happens.
*/
public void exit(String redirectAddress) {
this.exitAddress = redirectAddress;
getReloadManager().setSuppressMode(true);
new ArrayList<>(frames).forEach(SFrame::hide);
getReloadManager().setSuppressMode(false);
}
/**
* Exit the current session and redirect to new application instance.
*
* This removes the session and its associated
* application from memory. The userAgent is redirected to the same
* application with a fresh session. Note, that it is not even
* possible for the user to re-enter the old application with the
* BACK-button, since all information is removed.
*
* Always exit an application by calling an
* exit()
method, especially, if it is an application
* that requires an login and thus handles sensitive information accessible
* through the session. Usually, you will call this on behalf of an
* event within an ActionListener.actionPerformed()
like for
* a pressed 'EXIT'-Button.
*/
public void exit() {
exit("");
}
public String getExitAddress() {
return exitAddress;
}
public String getRedirectAddress() {
return redirectAddress;
}
public void setRedirectAddress(String redirectAddress) {
this.redirectAddress = redirectAddress;
}
public void addExitListener(SExitListener listener) {
listenerList.add(SExitListener.class,
listener);
}
public void removeExitListener(SExitListener listener) {
listenerList.remove(SExitListener.class,
listener);
}
public SExitListener[] getExitListeners() {
return (SExitListener[]) listenerList.getListeners(SExitListener.class);
}
/**
* Fire an RequestEvent at each registered listener.
*/
final void firePrepareExit() throws ExitVetoException {
firePrepareExit(false);
}
final void firePrepareExit(boolean ignoreVeto) throws ExitVetoException {
SExitEvent event = null;
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == SExitListener.class) {
// Lazily create the event:
if (event == null) {
event = new SExitEvent(this, !ignoreVeto);
}
((SExitListener) listeners[i + 1]).prepareExit(event);
}
}
}
public void addRequestListener(SRequestListener listener) {
listenerList.add(SRequestListener.class, listener);
}
public void removeRequestListener(SRequestListener listener) {
listenerList.remove(SRequestListener.class, listener);
}
/**
* Fire an RequestEvent at each registered listener.
*/
void fireRequestEvent(int type) {
fireRequestEvent(type, null);
}
/**
* Fire an RequestEvent at each registered listener.
*/
void fireRequestEvent(int type, ExternalizedResource resource) {
SRequestEvent event = null;
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == SRequestListener.class) {
// Lazily create the event:
if (event == null) {
event = new SRequestEvent(this, type, resource);
}
((SRequestListener) listeners[i + 1]).processRequest(event);
}
}
}
@Override
protected void finalize() {
log.debug("gc session");
if (collectStatistics) {
WingsStatistics.getStatistics().decrementAllocatedSessionCount();
} // end of if ()
}
public SCursor getCursor() {
if(this.cursor == null)
this.cursor = new SCursor();
return this.cursor;
}
public Clipboard getClipboard() {
if(this.clipboard == null)
this.clipboard = new Clipboard("wingS Clipboard");
return this.clipboard;
}
public boolean hasSDragAndDropManager() {
return sDndManager != null;
}
public SDragAndDropManager getSDragAndDropManager() {
if(sDndManager == null)
sDndManager = new SDragAndDropManager();
return sDndManager;
}
public boolean hasDragAndDropManager() {
return dndManager != null;
}
public DragAndDropManager getDragAndDropManager() {
if (dndManager == null) {
dndManager = new DragAndDropManager();
}
return dndManager;
}
public void setDndManager(DragAndDropManager dndManager) {
this.dndManager = dndManager;
}
public ResourceMapper getResourceMapper() {
return resourceMapper;
}
public void setResourceMapper(ResourceMapper resourceMapper) {
this.resourceMapper = resourceMapper;
}
public Comet getComet() {
return comet;
}
public boolean isCometWingServletEnabled() {
return (wingServlet instanceof CometWingServlet);
}
public Localizer getLocalizer() {
if (localizer == null)
localizer = key -> {
return ResourceBundle.getBundle("Bundle", locale).getString(key);
};
return localizer;
}
public void setLocalizer(Localizer localizer) {
this.localizer = localizer;
}
}