From 7bfc14d164cf2887913dea174d05ba6a723b847f Mon Sep 17 00:00:00 2001 From: hns Date: Fri, 31 May 2002 13:35:33 +0000 Subject: [PATCH] Merged in changes from Stefan Pollach's "usersession_05_15" branch. --- src/helma/framework/RequestBean.java | 61 +++++ src/helma/framework/ResponseBean.java | 138 +++++++++++ src/helma/framework/core/Application.java | 217 +++++++++++------- src/helma/framework/core/ApplicationBean.java | 195 ++++++++++++++++ .../framework/core/RequestEvaluator.java | 33 +-- src/helma/framework/core/Session.java | 131 +++++++++++ src/helma/framework/core/SessionBean.java | 73 ++++++ src/helma/framework/core/Skin.java | 5 +- src/helma/framework/core/User.java | 134 ----------- src/helma/scripting/fesi/ESAppNode.java | 149 ------------ src/helma/scripting/fesi/ESBeanWrapper.java | 59 +++++ src/helma/scripting/fesi/ESMapWrapper.java | 2 + src/helma/scripting/fesi/ESUser.java | 121 ---------- src/helma/scripting/fesi/FesiEvaluator.java | 49 +--- src/helma/scripting/fesi/HopExtension.java | 212 +---------------- .../scripting/fesi/extensions/ESMail.java | 1 - src/helma/util/SystemProperties.java | 6 + 17 files changed, 833 insertions(+), 753 deletions(-) create mode 100644 src/helma/framework/RequestBean.java create mode 100644 src/helma/framework/ResponseBean.java create mode 100644 src/helma/framework/core/ApplicationBean.java create mode 100644 src/helma/framework/core/Session.java create mode 100644 src/helma/framework/core/SessionBean.java delete mode 100644 src/helma/framework/core/User.java delete mode 100644 src/helma/scripting/fesi/ESAppNode.java create mode 100644 src/helma/scripting/fesi/ESBeanWrapper.java delete mode 100644 src/helma/scripting/fesi/ESUser.java diff --git a/src/helma/framework/RequestBean.java b/src/helma/framework/RequestBean.java new file mode 100644 index 00000000..c57f62b6 --- /dev/null +++ b/src/helma/framework/RequestBean.java @@ -0,0 +1,61 @@ +package helma.framework; + +import java.io.Serializable; +import java.util.Map; + +import helma.framework.core.Application; + +public class RequestBean implements Serializable { + + RequestTrans req; + + public RequestBean(RequestTrans req) { + this.req = req; + } + + public Object get (String name) { + return req.get (name); + } + + public boolean isGet () { + return req.isGet (); + } + + public boolean isPost () { + return req.isPost (); + } + + public String toString() { + return "[Request]"; + } + + // property related methods: + + public String getaction () { + return req.action; + } + + public Map getdata () { + return req.getRequestData (); + } + + public long getruntime () { + return (System.currentTimeMillis() - req.startTime); + } + + public String getpassword () { + return req.getPassword (); + } + + public String getpath () { + return req.path; + } + + public String getusername () { + return req.getUsername (); + } + +} + + + diff --git a/src/helma/framework/ResponseBean.java b/src/helma/framework/ResponseBean.java new file mode 100644 index 00000000..9b89ec6d --- /dev/null +++ b/src/helma/framework/ResponseBean.java @@ -0,0 +1,138 @@ +package helma.framework; + +import java.io.Serializable; +import java.util.Map; + +import helma.framework.core.Application; + +public class ResponseBean implements Serializable { + + ResponseTrans res; + + public ResponseBean(ResponseTrans res) { + this.res = res; + } + + public void encode (Object what) { + res.encode (what); + } + + public void encodeXml (Object what) { + res.encodeXml (what); + } + + public void format (Object what) { + res.format (what); + } + + public void pushStringBuffer () { + res.pushStringBuffer (); + } + + public String popStringBuffer () { + return res.popStringBuffer (); + } + + public void redirect (String url) throws RedirectException { + res.redirect (url); + } + + public void reset () { + res.reset (); + } + + public void setCookie (String key, String value) { + res.setCookie (key, value, -1); + } + + public void setCookie (String key, String value, int days) { + res.setCookie (key, value, days); + } + + public void write (Object what) { + res.write (what); + } + + public void writeln (Object what) { + res.writeln (what); + } + + public void writeBinary (byte[] what) { + res.writeBinary (what); + } + + public String toString() { + return "[Response]"; + } + + + // property-related methods: + + public boolean getcache () { + return res.cache; + } + + public void setcache (boolean cache) { + res.cache = cache; + } + + public String getcharset () { + return res.charset; + } + + public void setcharset (String charset) { + res.charset = charset; + } + + public String getcontentType () { + return res.contentType; + } + + public void setcontentType (String contentType) { + res.contentType = contentType; + } + + public Map getdata () { + return res.getResponseData (); + } + + public String geterror () { + return res.error; + } + + public String getmessage () { + return res.message; + } + + public void setmessage (String message) { + res.message = message; + } + + public String getrealm () { + return res.realm; + } + + public void setrealm (String realm) { + res.realm = realm; + } + + public void setskinpath (Object[] arr) { + res.setTranslatedSkinpath (arr); + } + + public Object[] getskinpath () { + return res.getTranslatedSkinpath (); + } + + public int getstatus () { + return res.status; + } + + public void setstatus (int status) { + res.status = status; + } + +} + + + diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index 87b87a5f..707185c2 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -8,7 +8,6 @@ import helma.doc.DocException; import helma.framework.*; import helma.main.Server; import helma.scripting.*; -import helma.scripting.fesi.ESUser; import helma.objectmodel.*; import helma.objectmodel.db.*; import helma.xmlrpc.*; @@ -66,10 +65,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat boolean stopped = false; boolean debug; - public long starttime; + long starttime; - public Hashtable sessions; - public Hashtable activeUsers; + Hashtable sessions; Hashtable dbMappings; Hashtable dbSources; @@ -86,7 +84,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat protected String templateExtension, scriptExtension, actionExtension, skinExtension; // A transient node that is shared among all evaluators - protected INode appnode; + protected INode cachenode; protected volatile long requestCount = 0; protected volatile long xmlrpcCount = 0; protected volatile long errorCount = 0; @@ -218,11 +216,10 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat skinExtension = ".skin"; sessions = new Hashtable (); - activeUsers = new Hashtable (); dbMappings = new Hashtable (); dbSources = new Hashtable (); - appnode = new TransientNode ("app"); + cachenode = new TransientNode ("app"); xmlrpc = helma.main.Server.getXmlRpcServer (); xmlrpcAccess = new XmlRpcAccess (this); } @@ -262,8 +259,11 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat String usernameField = userMapping.getNameField (); if (usernameField == null) usernameField = "name"; - p.put ("_properties", "user."+usernameField); + p.put ("_version","1.2"); + p.put ("_children", "collection(user)"); + p.put ("_children.accessname", usernameField); userRootMapping = new DbMapping (this, "__userroot__", p); + rewireDbMappings (); nmgr = new NodeManager (this, dbDir.getAbsolutePath (), props); @@ -399,7 +399,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat requestCount += 1; // get user for this request's session - User u = getUser (req.session); + Session session = checkSession (req.session); + session.touch(); ResponseTrans res = null; RequestEvaluator ev = null; @@ -418,7 +419,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat // if attachRequest returns null this means we came too late // and the other request was finished in the meantime ev = getEvaluator (); - res = ev.invoke (req, u); + res = ev.invoke (req, session); } } catch (ApplicationStoppedException stopped) { // let the servlet know that this application has gone to heaven @@ -441,7 +442,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat res.waitForClose (); } } - + return res; } @@ -530,8 +531,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat /** * Return a transient node that is shared by all evaluators of this application ("app node") */ - public INode getAppNode () { - return appnode; + public INode getCacheNode () { + return cachenode; } @@ -570,51 +571,130 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat } /** - * Retrurn a skin for a given object. The skin is found by determining the prototype + * Return a skin for a given object. The skin is found by determining the prototype * to use for the object, then looking up the skin for the prototype. */ public Skin getSkin (Object object, String skinname, Object[] skinpath) { - return skinmgr.getSkin (object, skinname, skinpath); + return skinmgr.getSkin (object, skinname, skinpath); } /** - * Return the user currently associated with a given Hop session ID. This may be - * a registered or an anonymous user. + * Return the session currently associated with a given Hop session ID. + * Create a new session if necessary. */ - public User getUser (String sessionID) { - if (sessionID == null) - return null; - - User u = (User) sessions.get (sessionID); - if (u != null) { - u.touch (); - } else { - u = new User (sessionID, this); - sessions.put (sessionID, u); + public Session checkSession (String sessionID) { + Session session = getSession(sessionID); + if ( session==null ) { + session = new Session (sessionID, this); + sessions.put (sessionID, session); } - return u; + return session; } + /** + * Remove the session from the sessions-table and logout the user. + */ + public void destroySession (String sessionID) { + logoutSession (getSession (sessionID)); + sessions.remove (sessionID); + } + + /** + * Remove the session from the sessions-table and logout the user. + */ + public void destroySession (Session session) { + logoutSession (session); + sessions.remove (session.getSessionID ()); + } + + public Enumeration getActiveUsers () { + return new SessionFilter (null); + } + + /** + * Return an array of session currently associated with a given Hop user object. + */ + public Enumeration getSessionsForUsername (String username) { + return new SessionFilter (username); + } + + class SessionFilter implements Enumeration { + String username; + Session nextSession; + Enumeration sessionEnum; + Vector usernames; + + SessionFilter (String username) { + this.username = username; + if (username==null) + usernames = new Vector(); + sessionEnum = sessions.elements (); + nextSession = nextValidSession (); + } + + public boolean hasMoreElements () { + if (nextSession==null) + return false; + else + return true; + } + + public Object nextElement () { + Session thisSession = nextSession; + nextSession = nextValidSession (); + return thisSession; + } + + private Session nextValidSession () { + while( sessionEnum.hasMoreElements () ) { + Session s = (Session)sessionEnum.nextElement (); + if(s==null) { + continue; + } else { + if (username!=null && username.equals(s.getUID ())) { + // returns a session if it is logged in and fits + // the given username + return s; + } else if (username==null && s.isLoggedIn()==true && !usernames.contains (s.getUID ()) ) { + // returns a session if it is logged in and has not been + // returned before (so for each logged-in user we get one + // session object, even if this user is logged in several + // times (used to retrieve the active users list). + usernames.add (s.getUID ()); + return s; + } + } + } + return null; + } + } + + + /** + * Return the session currently associated with a given Hop session ID. + */ + public Session getSession (String sessionID) { + if (sessionID == null) + return null; + return (Session) sessions.get (sessionID); + } /** * Register a user with the given user name and password. */ public INode registerUser (String uname, String password) { - // Register a user who already has a user object - // (i.e. who has been surfing around) if (uname == null) return null; uname = uname.toLowerCase ().trim (); if ("".equals (uname)) return null; - INode unode = null; try { INode users = getUserRoot (); unode = users.getNode (uname, false); - if (unode != null) + if (unode != null) return null; - + unode = users.createNode (uname); unode.setPrototype ("user"); unode.setDbMapping (userMapping); @@ -627,8 +707,6 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat unode.setName (uname); unode.setString (usernameProp, uname); unode.setString ("password", password); - // users.setNode (uname, unode); - // return users.getNode (uname, false); return unode; } catch (Exception x) { logEvent ("Error registering User: "+x); @@ -639,26 +717,23 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat /** * Log in a user given his or her user name and password. */ - public boolean loginUser (String uname, String password, ESUser u) { - // Check the name/password of a user who already has a user object - // (i.e. who has been surfing around) + public boolean loginSession (String uname, String password, Session session) { + // Check the name/password of a user and log it in to the current session if (uname == null) return false; uname = uname.toLowerCase ().trim (); if ("".equals (uname)) return false; - try { INode users = getUserRoot (); - INode unode = users.getNode (uname, false); + Node unode = (Node)users.getNode (uname, false); String pw = unode.getString ("password", false); if (pw != null && pw.equals (password)) { - // give the user his/her persistant node - u.setNode (unode); - activeUsers.put (unode.getName (), u.user); + // let the old user-object forget about this session + logoutSession(session); + session.login (unode); return true; } - } catch (Exception x) { return false; } @@ -666,18 +741,10 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat } /** - * Log out a user from this application. + * Log out a session from this application. */ - public boolean logoutUser (ESUser u) { - if (u.user != null) { - String uid = u.user.uid; - if (uid != null) - activeUsers.remove (uid); - - // switch back to the non-persistent user node as cache - u.setNode (null); - } - return true; + public void logoutSession (Session session) { + session.logout(); } /** @@ -725,13 +792,6 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat if (rootproto != null && rootproto.equals (getPrototypeName (p))) break; b.insert (0, divider); - - // users always have a canonical URL like /users/username - if ("user".equals (getPrototypeName (p))) { - b.insert (0, URLEncoder.encode (getElementName (p))); - p = users; - break; - } b.insert (0, URLEncoder.encode (getElementName (p))); p = getParentElement (p); @@ -739,11 +799,6 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat break; } - if (p == users) { - b.insert (0, divider); - b.insert (0, "users"); - } - if (actionName != null) b.append (URLEncoder.encode (actionName)); @@ -957,29 +1012,25 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat int sessionTimeout = 30; try { sessionTimeout = Math.max (0, Integer.parseInt (props.getProperty ("sessionTimeout", "30"))); - } catch (Exception ignore) {} + } catch (Exception ignore) { + System.out.println(ignore.toString()); + } long now = System.currentTimeMillis (); // check if we should clean up user sessions if (now - lastCleanup > cleanupSleep) try { lastCleanup = now; - // logEvent ("Cleaning up "+name+": " + sessions.size () + " sessions active"); Hashtable cloned = (Hashtable) sessions.clone (); for (Enumeration e = cloned.elements (); e.hasMoreElements (); ) { - User u = (User) e.nextElement (); - if (now - u.lastTouched () > sessionTimeout * 60000) { - if (u.uid != null) { - try { - eval.invokeFunction (u, "onLogout", new Object[0]); - } catch (Exception ignore) {} - activeUsers.remove (u.uid); - } - sessions.remove (u.getSessionID ()); - u.setNode (null); + Session session = (Session) e.nextElement (); + if (now - session.lastTouched () > sessionTimeout * 60000) { +// if (session.uid != null) { +// FIXME onlogout()! try {eval.invokeFunction (u, "onLogout", new Object[0]);} catch (Exception ignore) {} +// } + destroySession(session); } } - // logEvent ("Cleaned up "+name+": " + sessions.size () + " sessions remaining"); } catch (Exception cx) { logEvent ("Error cleaning up sessions: "+cx); cx.printStackTrace (); @@ -1126,9 +1177,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat return props.getProperty (propname, defvalue); } - public SystemProperties getProperties() { - return props; - } + public SystemProperties getProperties() { + return props; + } /** * diff --git a/src/helma/framework/core/ApplicationBean.java b/src/helma/framework/core/ApplicationBean.java new file mode 100644 index 00000000..4a37271c --- /dev/null +++ b/src/helma/framework/core/ApplicationBean.java @@ -0,0 +1,195 @@ +package helma.framework.core; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +import helma.objectmodel.INode; + +public class ApplicationBean implements Serializable { + + Application app; + + public ApplicationBean(Application app) { + this.app = app; + } + + public void clearCache () { + app.clearCache (); + } + + public void log (String msg) { + app.logEvent (msg); + } + + public void log (String logname, String msg) { + app.getLogger (logname).log (msg); + } + + public void debug (String msg) { + if (app.debug()) { + app.logEvent (msg); + } + } + + public void debug (String logname, String msg) { + if (app.debug()) { + app.getLogger (logname).log (msg); + } + } + + public int countSessions () { + return app.sessions.size(); + } + + public SessionBean getSession (String sessionID) { + if (sessionID==null) + return null; + Session session = app.getSession (sessionID.trim ()); + if (session == null) + return null; + return new SessionBean (session); + } + + public SessionBean createSession (String sessionID) { + if (sessionID==null) + return null; + Session session = session = app.checkSession (sessionID.trim ()); + if (session == null) + return null; + return new SessionBean (session); + } + + public SessionBean[] getSessions () { + SessionBean[] theArray = new SessionBean[app.sessions.size()]; + int i=0; + for (Enumeration e=app.sessions.elements(); e.hasMoreElements(); ) { + SessionBean sb = new SessionBean ((Session) e.nextElement ()); + theArray[i++] = sb; + } + return theArray; + } + + public INode registerUser (String username, String password) { + if (username==null || password==null || "".equals (username.trim ()) || "".equals (password.trim ()) ) + return null; + else + return app.registerUser (username, password); + } + + public INode getUser (String username) { + if (username==null || "".equals (username.trim()) ) + return null; + return app.getUserNode (username); + } + + public INode[] getActiveUsers () { + Enumeration loggedInSessions = app.getActiveUsers (); + if (loggedInSessions.hasMoreElements ()==false) + return new INode[0]; + ArrayList theArray = new ArrayList(); + while (loggedInSessions.hasMoreElements ()) { + INode usernode = ((Session) loggedInSessions.nextElement ()).getUserNode (); + if (usernode!=null) + theArray.add (usernode); + } + return (INode[]) theArray.toArray (new INode[0]); + } + + public SessionBean[] getSessionsForUser (INode usernode) { + if (usernode==null) + return new SessionBean[0]; + else + return getSessionsForUser(usernode.getName()); + } + + public SessionBean[] getSessionsForUser (String username) { + if (username==null || "".equals (username.trim ()) ) + return new SessionBean[0]; + Enumeration userSessions = app.getSessionsForUsername (username); + if (userSessions.hasMoreElements()==false ) + return new SessionBean[0]; + ArrayList theArray = new ArrayList(); + while (userSessions.hasMoreElements() ) { + SessionBean sb = new SessionBean ((Session) userSessions.nextElement ()); + theArray.add(sb); + } + return (SessionBean[]) theArray.toArray (new SessionBean[0]); + } + + // getter methods for readonly properties of this application + + public INode getdata() { + return app.getCacheNode (); + } + + public Date getupSince () { + return new Date (app.starttime); + } + + public long getrequestCount () { + return app.getRequestCount (); + } + + public long getxmlrpcCount () { + return app.getXmlrpcCount (); + } + + public long geterrorCount () { + return app.getErrorCount (); + } + + public Application get__app__ () { + return app; + } + + public Map getproperties () { + return app.getProperties (); + } + + public int getfreeThreads () { + return app.countFreeEvaluators (); + } + + public int getactiveThreads () { + return app.countActiveEvaluators (); + } + + public int getmaxThreads () { + return app.countEvaluators (); + } + + public void setmaxThreads (int n) { + // add one to the number to compensate for the internal scheduler. + app.setNumberOfEvaluators (n+1); + } + + public Map getskinfiles () { + Map skinz = new Hashtable (); + for (Iterator it = app.getPrototypes().iterator(); it.hasNext(); ) { + Prototype p = (Prototype) it.next (); + Map proto = new Hashtable (); + for (Iterator it2 = p.skins.values().iterator(); it2.hasNext(); ) { + SkinFile sf = (SkinFile) it2.next (); + String name = sf.getName (); + Skin skin = sf.getSkin (); + proto.put (name, skin.getSource ()); + } + skinz.put (p.getName (), proto); + } + return skinz; + } + + + public String toString() { + return "[Application " + app.getName() + "]"; + } + +} + + + diff --git a/src/helma/framework/core/RequestEvaluator.java b/src/helma/framework/core/RequestEvaluator.java index 96ce003c..9910bb7c 100644 --- a/src/helma/framework/core/RequestEvaluator.java +++ b/src/helma/framework/core/RequestEvaluator.java @@ -35,8 +35,8 @@ public class RequestEvaluator implements Runnable { // the method to be executed String method; - // the user object associated with the current request - User user; + // the session object associated with the current request + Session session; // arguments passed to the function Object[] args; @@ -113,17 +113,18 @@ public class RequestEvaluator implements Runnable { HashMap globals = new HashMap (); globals.put ("root", root); - globals.put ("user", user); + globals.put ("session", session); globals.put ("req", req); globals.put ("res", res); globals.put ("path", requestPath); - globals.put ("app", app.getAppNode()); + globals.put ("app", app); + req.startTime = System.currentTimeMillis (); if (error != null) res.error = error; - if (user.message != null) { + if (session.message != null) { // bring over the message from a redirect - res.message = user.message; - user.message = null; + res.message = session.message; + session.message = null; } try { @@ -284,7 +285,7 @@ public class RequestEvaluator implements Runnable { // res.redirect = redirect.getMessage (); // if there is a message set, save it on the user object for the next request if (res.message != null) - user.message = res.message; + session.message = res.message; done = true; } @@ -360,7 +361,7 @@ public class RequestEvaluator implements Runnable { HashMap globals = new HashMap (); globals.put ("root", root); globals.put ("res", res); - globals.put ("app", app.getAppNode()); + globals.put ("app", app); currentElement = root; @@ -419,7 +420,7 @@ public class RequestEvaluator implements Runnable { HashMap globals = new HashMap (); globals.put ("root", root); globals.put ("res", res); - globals.put ("app", app.getAppNode()); + globals.put ("app", app); app.scriptingEngine.invoke (thisObject, method, args, globals, this); commitTransaction (); @@ -497,10 +498,10 @@ public class RequestEvaluator implements Runnable { } catch (InterruptedException ir) {} } - public synchronized ResponseTrans invoke (RequestTrans req, User user) throws Exception { + public synchronized ResponseTrans invoke (RequestTrans req, Session session) throws Exception { this.reqtype = HTTP; this.req = req; - this.user = user; + this.session = session; this.res = new ResponseTrans (); app.activeRequests.put (req, this); @@ -534,7 +535,7 @@ public class RequestEvaluator implements Runnable { public synchronized Object invokeXmlRpc (String method, Object[] args) throws Exception { this.reqtype = XMLRPC; - this.user = null; + this.session = null; this.method = method; this.args = args; this.res = new ResponseTrans (); @@ -559,7 +560,7 @@ public class RequestEvaluator implements Runnable { public synchronized Object invokeFunction (Object object, String functionName, Object[] args) throws Exception { reqtype = INTERNAL; - user = null; + session = null; thisObject = object; method = functionName; this.args =args; @@ -579,10 +580,10 @@ public class RequestEvaluator implements Runnable { return result; } - public synchronized Object invokeFunction (User user, String functionName, Object[] args) + public synchronized Object invokeFunction (Session session, String functionName, Object[] args) throws Exception { reqtype = INTERNAL; - this.user = user; + this.session = session; thisObject = null; method = functionName; this.args = args; diff --git a/src/helma/framework/core/Session.java b/src/helma/framework/core/Session.java new file mode 100644 index 00000000..04c89822 --- /dev/null +++ b/src/helma/framework/core/Session.java @@ -0,0 +1,131 @@ +// Session.java + +package helma.framework.core; + +import java.io.*; +import java.util.*; +import java.net.URLEncoder; +import helma.objectmodel.*; +import helma.objectmodel.db.*; + +/** + * This represents a session currently using the Hop application. + * This comprends anybody who happens to surf the site. + * Depending on whether the user is logged in or not, the user object holds a + * persistent user node. + */ + +public class Session implements Serializable { + + Application app; + String sessionID; + + // the unique id (login name) for the user, if logged in + String uid; + + // the handle to this user's persistent db node, if logged in + NodeHandle userHandle; + + // the transient cache node that is exposed to javascript + // this stays the same across logins and logouts. + public TransientNode cacheNode; + + long onSince, lastTouched; + + // used to remember messages to the user between requests - + // used for redirects. + String message; + + public Session (String sessionID, Application app) { + this.sessionID = sessionID; + this.app = app; + this.uid = null; + this.userHandle = null; + cacheNode = new TransientNode ("session"); + onSince = System.currentTimeMillis (); + lastTouched = onSince; + } + + /** + * attach the given user node to this session. + */ + public void login (INode usernode) { + if (usernode==null) { + userHandle = null; + uid = null; + } else { + userHandle = ((Node)usernode).getHandle(); + uid = usernode.getElementName(); + } + } + + /** + * remove this sessions's user node. + */ + public void logout() { + userHandle = null; + uid = null; + } + + public boolean isLoggedIn() { + if (userHandle!=null && uid!=null) { + return true; + } else { + return false; + } + } + + /** + * Gets the user Node from this Application's NodeManager. + */ + public INode getUserNode() { + if (userHandle!=null) + return userHandle.getNode (app.getWrappedNodeManager()); + else + return null; + } + + /** + * Gets the transient cache node. + */ + public INode getCacheNode () { + return cacheNode; + } + + public Application getApp () { + return app; + } + + public String getSessionID () { + return sessionID; + } + + public void touch () { + lastTouched = System.currentTimeMillis (); + } + + public long lastTouched () { + return lastTouched; + } + + public long onSince () { + return onSince; + } + + public String toString () { + if ( uid!=null ) + return "[Session for user " + uid + "]"; + else + return "[Anonymous Session]"; + } + + /** + * Get the persistent user id of a registered user. This is usually the user name, or + * null if the user is not logged in. + */ + public String getUID () { + return uid; + } + +} + diff --git a/src/helma/framework/core/SessionBean.java b/src/helma/framework/core/SessionBean.java new file mode 100644 index 00000000..95144dac --- /dev/null +++ b/src/helma/framework/core/SessionBean.java @@ -0,0 +1,73 @@ +package helma.framework.core; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; + +import helma.objectmodel.INode; +import helma.scripting.ScriptingEnvironment; +import helma.scripting.ScriptingException; +import helma.scripting.fesi.*; + +public class SessionBean implements Serializable { + + // the wrapped session object + Session session; + + public SessionBean(Session session) { + this.session = session; + } + + public String toString() { + return session.toString (); + } + + public boolean login (String username, String password) { + boolean success = session.getApp().loginSession (username, password, session); + return success; + } + + public void logout () { + session.getApp().logoutSession (session); + } + + public void touch () { + session.touch (); + } + + public Date lastActive() { + return new Date (session.lastTouched ()); + } + + public Date onSince() { + return new Date (session.onSince ()); + } + + // property-related methods: + + public INode getdata() { + return session.getCacheNode (); + } + + public INode getuser() { + return session.getUserNode(); + } + + public String get_id () { + return session.getSessionID (); + } + + public String getcookie() { + return session.getSessionID (); + } + + public Date getlastActive() { + return new Date (session.lastTouched ()); + } + + public Date getonSince() { + return new Date (session.onSince ()); + } + +} + diff --git a/src/helma/framework/core/Skin.java b/src/helma/framework/core/Skin.java index c74749f7..c4b10e13 100644 --- a/src/helma/framework/core/Skin.java +++ b/src/helma/framework/core/Skin.java @@ -266,10 +266,7 @@ public class Skin { boolean objectFound = true; if (handler != null) { - if ("currentuser".equalsIgnoreCase (handler)) { - // as a special convention, we use "currentuser" to access macros in the current user object - handlerObject = reval.user.getNode (); - } else if (thisObject != null) { + if (thisObject != null) { // not a global macro - need to find handler object // was called with this object - check it or its parents for matching prototype if (!handler.equalsIgnoreCase ("this") && !handler.equalsIgnoreCase (app.getPrototypeName (thisObject))) { diff --git a/src/helma/framework/core/User.java b/src/helma/framework/core/User.java deleted file mode 100644 index 7ce3e1e9..00000000 --- a/src/helma/framework/core/User.java +++ /dev/null @@ -1,134 +0,0 @@ -// User.java -// Copyright (c) Hannes Wallnöfer 1998-2000 - -package helma.framework.core; - -import java.io.*; -import java.util.*; -import java.net.URLEncoder; -import helma.objectmodel.*; -import helma.objectmodel.db.*; - -/** - * This represents a user who is currently using the Hop application. This does - * not just comprend registered users, but anybody who happens to surf the site. - * Depending on whether the user is logged in or not, the user object holds a - * persistent user node or just a transient cache node - */ - -public class User implements Serializable { - - Application app; - String sessionID; - - // the unique id (login name) for the user, if logged in - String uid; - - // the handle to this user's persistent db node, if logged in - NodeHandle nhandle; - - // the transient cache node. This stays the same across logins and logouts. - // If logged out, this also represents the user's main node. - TransientNode cache; - - DbMapping umap; - long onSince, lastTouched; - - // used to remember messages to the user between requests - - // used for redirects. - String message; - - public User (String sid, Application app) { - this.uid = null; - this.nhandle = null; - this.app = app; - setNode (null); - umap = app.getDbMapping ("user"); - cache = new TransientNode ("[session cache]"); - cache.setPrototype ("user"); - cache.setDbMapping (umap); - sessionID = sid; - onSince = System.currentTimeMillis (); - lastTouched = onSince; - } - - - /** - * This is used to turn for login and logout. - * Calling this weith a DB Node object will turn an anonymous user into a registered or known one. - * The user object remains the same, but he or she gets some persistent storage. - * On the other side, calling this method with a parameter value of null is means the user - * is logged out and will be represented by its transient cache node. - */ - public void setNode (INode n) { - // IServer.getLogger().log ("esn = "+esn); - if (n == null) { - nhandle = null; - uid = null; - } else { - uid = n.getElementName (); - nhandle = ((Node) n).getHandle (); - } - // System.err.println ("User.setNode: "+nhandle); - } - - public INode getNode () { - if (nhandle == null) { - return cache; - } else { - // in some special cases, a user's node handle may go bad, for instance - // if something bad happens during registration. For this reason, we check - // if the handle actually works. If not, it is reset to the transient cache, which - // means the user is logged out. - Node n = nhandle.getNode (app.nmgr.safe); - if (n == null) { - setNode (null); - return cache; - } - return n; - } - } - - public String getSessionID () { - return sessionID; - } - - - public void touch () { - lastTouched = System.currentTimeMillis (); - } - - public long lastTouched () { - return lastTouched; - } - - public long onSince () { - return onSince; - } - - /** - * Get the persistent user id of a registered user. This is usually the user name, or - * null if the user is not logged in. - */ - public String getUID () { - return uid; - } - - /** - * Return the transient cache node for this user. - */ - public INode getCache () { - return cache; - } - - /** - * Reset the session cache node, clearing all properties. - * This is done by recreating the cache node object. - */ - public void clearCache () { - cache = new TransientNode ("[session cache]"); - cache.setPrototype ("user"); - cache.setDbMapping (umap); - } -} - diff --git a/src/helma/scripting/fesi/ESAppNode.java b/src/helma/scripting/fesi/ESAppNode.java deleted file mode 100644 index 83b3e15f..00000000 --- a/src/helma/scripting/fesi/ESAppNode.java +++ /dev/null @@ -1,149 +0,0 @@ -// ESAppNode.java -// Copyright (c) Hannes Wallnöfer 1998-2000 - -package helma.scripting.fesi; - -import helma.framework.core.*; -import helma.objectmodel.*; -import FESI.Exceptions.*; -import FESI.Data.*; -import FESI.Interpreter.Evaluator; -import java.util.Iterator; - -/** - * ESApp represents the app node of an application, providing an app-wide transient shared - * space as well as access to some app related runtime information. - */ - -public class ESAppNode extends ESNode { - - private Application app; - private DatePrototype createtime; - - public ESAppNode (INode node, FesiEvaluator eval) throws EcmaScriptException { - super (eval.getPrototype("hopobject"), eval.getEvaluator(), node, eval); - app = eval.getApplication(); - createtime = new DatePrototype (evaluator, node.created()); - FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype(); - putHiddenProperty("getThreads", new AppCountThreads ("getThreads", evaluator, fp)); - putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp)); - putHiddenProperty("getFreeThreads", new AppCountFreeEvaluators ("getFreeThreads", evaluator, fp)); - putHiddenProperty("getActiveThreads", new AppCountActiveEvaluators ("getActiveThreads", evaluator, fp)); - putHiddenProperty("getMaxActiveThreads", new AppCountMaxActiveEvaluators ("getMaxActiveThreads", evaluator, fp)); - putHiddenProperty("setMaxThreads", new AppSetNumberOfEvaluators ("setMaxThreads", evaluator, fp)); - putHiddenProperty("clearCache", new AppClearCache ("clearCache", evaluator, fp)); - } - - /** - * Overrides getProperty to return some app-specific properties - */ - public ESValue getProperty (String propname, int hash) throws EcmaScriptException { - if ("requestCount".equals (propname)) { - return new ESNumber (app.getRequestCount ()); - } - if ("xmlrpcCount".equals (propname)) { - return new ESNumber (app.getXmlrpcCount ()); - } - if ("errorCount".equals (propname)) { - return new ESNumber (app.getErrorCount ()); - } - if ("upSince".equals (propname)) { - return createtime; - } - if ("skinfiles".equals (propname)) { - ESObject skinz = new ObjectPrototype (null, evaluator); - for (Iterator it = app.getPrototypes().iterator(); it.hasNext(); ) { - Prototype p = (Prototype) it.next (); - ESObject proto = new ObjectPrototype (null, evaluator); - for (Iterator it2 = p.skins.values().iterator(); it2.hasNext(); ) { - SkinFile sf = (SkinFile) it2.next (); - String name = sf.getName (); - Skin skin = sf.getSkin (); - proto.putProperty (name, new ESString (skin.getSource ()), name.hashCode ()); - } - skinz.putProperty (p.getName (), proto, p.getName ().hashCode ()); - } - return skinz; - } - if ("__app__".equals (propname)) { - return new ESWrapper (app, evaluator); - } - return super.getProperty (propname, hash); - } - - - class AppCountEvaluators extends BuiltinFunctionObject { - AppCountEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 0); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.countEvaluators ()); - } - } - - class AppCountFreeEvaluators extends BuiltinFunctionObject { - AppCountFreeEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 0); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.countFreeEvaluators ()); - } - } - - class AppCountActiveEvaluators extends BuiltinFunctionObject { - AppCountActiveEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 0); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.countActiveEvaluators ()); - } - } - - class AppCountMaxActiveEvaluators extends BuiltinFunctionObject { - AppCountMaxActiveEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 0); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.countMaxActiveEvaluators ()); - } - } - - class AppCountThreads extends BuiltinFunctionObject { - AppCountThreads (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 0); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.countThreads ()); - } - } - - class AppSetNumberOfEvaluators extends BuiltinFunctionObject { - AppSetNumberOfEvaluators (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - RequestEvaluator ev = new RequestEvaluator (app); - if (arguments.length != 1) - return ESBoolean.makeBoolean (false); - // add one to the number to compensate for the internal scheduler. - return ESBoolean.makeBoolean (app.setNumberOfEvaluators (1 + arguments[0].toInt32())); - } - } - - class AppClearCache extends BuiltinFunctionObject { - AppClearCache (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - app.clearCache (); - return ESBoolean.makeBoolean (true); - } - } - - - public String toString () { - return ("AppNode "+node.getElementName ()); - } - -} - diff --git a/src/helma/scripting/fesi/ESBeanWrapper.java b/src/helma/scripting/fesi/ESBeanWrapper.java new file mode 100644 index 00000000..f44a0f21 --- /dev/null +++ b/src/helma/scripting/fesi/ESBeanWrapper.java @@ -0,0 +1,59 @@ +package helma.scripting.fesi; + +import java.util.Map; + +import helma.objectmodel.INode; + +import FESI.Interpreter.Evaluator; +import FESI.Exceptions.EcmaScriptException; +import FESI.Data.ESNull; +import FESI.Data.ESValue; +import FESI.Data.ESWrapper; + +/** + * Wrap a Java Bean for use in EcmaScript. + */ + +public class ESBeanWrapper extends ESWrapper { + + FesiEvaluator eval; + + public ESBeanWrapper (Object object, FesiEvaluator eval) { + super (object, eval.getEvaluator(),true); + this.eval = eval; + } + + /** + * Wrap getProperty, return ESNode if INode would be returned. + */ + public ESValue getProperty(String propertyName, int hash) + throws EcmaScriptException { + try { + ESValue val = super.getProperty (propertyName, hash); + if (val instanceof ESWrapper && ((ESWrapper)val).getJavaObject() instanceof INode) { + return eval.getNodeWrapper( (INode) ((ESWrapper)val).getJavaObject() ); + } else if (val instanceof ESWrapper && ((ESWrapper)val).getJavaObject() instanceof Map) { + return new ESMapWrapper(eval, (Map) ((ESWrapper)val).getJavaObject() ); + } else { + return val; + } + } catch (Exception rte) { + return ESNull.theNull; + } + } + + public void putProperty(String propertyName, ESValue propertyValue, int hash) + throws EcmaScriptException { + try { + super.putProperty (propertyName, propertyValue, hash); + } catch (Exception rte) { + // create a nice error message + throw new EcmaScriptException("can't set property " + propertyName + + " to this value on " + getJavaObject().toString() ); + } + } + +} + + + diff --git a/src/helma/scripting/fesi/ESMapWrapper.java b/src/helma/scripting/fesi/ESMapWrapper.java index dd1402e6..5f6b2de7 100644 --- a/src/helma/scripting/fesi/ESMapWrapper.java +++ b/src/helma/scripting/fesi/ESMapWrapper.java @@ -64,6 +64,8 @@ public class ESMapWrapper extends ESWrapper { return new ESString ((String) val); else if (val instanceof INode) return fesi.getNodeWrapper ((INode) val); + else if (val instanceof Map) + return new ESMapWrapper (fesi, (Map)val); else if (val instanceof ESValue) return (ESValue) val; return ESLoader.normalizeValue(val, evaluator); diff --git a/src/helma/scripting/fesi/ESUser.java b/src/helma/scripting/fesi/ESUser.java deleted file mode 100644 index 57819880..00000000 --- a/src/helma/scripting/fesi/ESUser.java +++ /dev/null @@ -1,121 +0,0 @@ -// ESUser.java -// Copyright (c) Hannes Wallnöfer 1998-2000 - -package helma.scripting.fesi; - -import helma.framework.core.*; -import helma.objectmodel.*; -import helma.objectmodel.db.Node; -import FESI.Interpreter.*; -import FESI.Exceptions.*; -import FESI.Data.*; - -/** - * The ESUser is a special kind of Node object that represents a user of - * a Helma application. The actual user session data are kept in class User. - * If the user is logged in as a registered member, the wrapped node represents - * the user object in the database, while for anonymous surfers the node object - * is just a transient node.

- * This means that the wrapped node will be swapped when the user logs in or out. - * To save session state across logins and logouts, the - * cache property of the user object stays the same for the whole time the user - * spends on this site. - */ - -public class ESUser extends ESNode { - - /** if the user is online, this is his/her online session object */ - public User user; - - public ESUser (INode node, FesiEvaluator eval, User user) { - super (eval.getPrototype("user"), eval.getEvaluator(), node, eval); - this.user = user; - if (user != null) { - cache = user.getCache (); - cacheWrapper = new ESNode (cache, eval); - } - } - - /** - * Overrides getProperty to return the uid (which is not a regular property) - */ - public ESValue getProperty (String propname, int hash) throws EcmaScriptException { - // if there is a user session object, we expose some of its properties. - // Otherwise, we call the parent's class getProperty method. - if ("uid".equals (propname)) { - if (user == null || user.getUID () == null) - return ESNull.theNull; - else - return new ESString (user.getUID ()); - } - if ("sessionID".equals (propname)) { - if (user == null || user.getSessionID () == null) - return ESNull.theNull; - else - return new ESString (user.getSessionID ()); - } - // if this represents an active user object, we override - // the cache property to come from the user session object - // instead of the Node object. - if ("cache".equals (propname) && user != null) { - cache = user.getCache (); - cacheWrapper.node = cache; - return cacheWrapper; - } - return super.getProperty (propname, hash); - } - - - /** - * The node for a user object changes at login and logout, so we don't use our - * own node, but just reach through to the session user object instead. - */ - public void setNode (INode node) { - // this only makes sense if this wrapper represents an active user - if (user == null) - return; - // set the node on the transient user session object - user.setNode (node); - if (node != null) { - this.node = node; - } else { - // user.getNode will never return null. If the node is set to null (=user logged out) - // it will user the original transient cache node again. - this.node = user.getNode (); - } - // set node handle to wrapped node - if (node instanceof Node) - handle = ((Node) node).getHandle (); - else - handle = null; - // we don't take over the transient cache from the node, - // because we always stick to the one from the user object. - } - - public void updateNodeFromUser () { - // this only makes sense if this wrapper represents an active user - if (user == null) - return; - node = user.getNode (); - // set node handle to wrapped node - if (node instanceof Node) - handle = ((Node) node).getHandle (); - else - handle = null; - - } - - public boolean clearCache () { - if (user != null) - user.clearCache (); - else - super.clearCache (); - return true; - } - - public String toString () { - return ("UserObject "+node.getName ()); - } - -} - diff --git a/src/helma/scripting/fesi/FesiEvaluator.java b/src/helma/scripting/fesi/FesiEvaluator.java index 213b26d7..a80d6a8b 100644 --- a/src/helma/scripting/fesi/FesiEvaluator.java +++ b/src/helma/scripting/fesi/FesiEvaluator.java @@ -29,7 +29,7 @@ public final class FesiEvaluator { // The FESI evaluator Evaluator evaluator; - + // the global object GlobalObject global; @@ -78,7 +78,7 @@ public final class FesiEvaluator { // fake a cache member like the one found in ESNodes global.putHiddenProperty ("cache", new ESNode (new TransientNode ("cache"), this)); global.putHiddenProperty ("undefined", ESUndefined.theUndefined); - ESAppNode appnode = new ESAppNode (app.getAppNode (), this); + ESBeanWrapper appnode = new ESBeanWrapper (new ApplicationBean (app), this); global.putHiddenProperty ("app", appnode); initialize(); } catch (Exception e) { @@ -227,11 +227,13 @@ public final class FesiEvaluator { // comfortable to EcmaScript coders, i.e. we use a lot of custom wrappers // that expose properties and functions in a special way instead of just going // with the standard java object wrappers. + + if (v instanceof RequestTrans) - ((RequestTrans) v).data = new ESMapWrapper (this, ((RequestTrans) v).getRequestData ()); + sv = new ESBeanWrapper (new RequestBean ((RequestTrans) v), this); else if (v instanceof ResponseTrans) - ((ResponseTrans) v).data = new ESMapWrapper (this, ((ResponseTrans) v).getResponseData ()); - if (v instanceof Map) + sv = new ESBeanWrapper (new ResponseBean ((ResponseTrans) v), this); + else if (v instanceof Map) sv = new ESMapWrapper (this, (Map) v); else if ("path".equals (k)) { ArrayPrototype parr = new ArrayPrototype (evaluator.getArrayPrototype(), evaluator); @@ -246,10 +248,10 @@ public final class FesiEvaluator { parr.putHiddenProperty (protoname, wrappedElement); } sv = parr; - } else if ("user".equals (k)) { - sv = getNodeWrapper ((User) v); + } else if ("session".equals (k)) { + sv = new ESBeanWrapper (new SessionBean ((Session)v), this); } else if ("app".equals (k)) { - sv = new ESAppNode ((INode) v, this); + sv = new ESBeanWrapper (new ApplicationBean ((Application)v), this); } else sv = ESLoader.normalizeValue (v, evaluator); @@ -432,7 +434,7 @@ public final class FesiEvaluator { * Get a script wrapper for an implemntation of helma.objectmodel.INode */ public ESNode getNodeWrapper (INode n) { - + // FIXME: should this return ESNull.theNull? if (n == null) return null; @@ -455,12 +457,7 @@ public final class FesiEvaluator { if (op == null) op = getPrototype("hopobject"); - - DbMapping dbm = n.getDbMapping (); - if (dbm != null && dbm.isInstanceOf ("user")) - esn = new ESUser (n, this, null); - else - esn = new ESNode (op, evaluator, n, this); + esn = new ESNode (op, evaluator, n, this); wrappercache.put (n, esn); // app.logEvent ("Wrapper for "+n+" created"); @@ -478,28 +475,6 @@ public final class FesiEvaluator { wrappercache.put (n, esn); } - /** - * Get a scripting wrapper object for a user object. Active user objects are represented by - * the special ESUser wrapper class. - */ - public ESNode getNodeWrapper (User u) { - if (u == null) - return null; - - ESUser esn = (ESUser) wrappercache.get (u); - - if (esn == null) { - esn = new ESUser (u.getNode(), this, u); - wrappercache.put (u, esn); - } else { - // the user node may have changed (login/logout) while the ESUser was - // lingering in the cache. - esn.updateNodeFromUser (); - } - - return esn; - } - /** * Return the RequestEvaluator owning and driving this FESI evaluator. */ diff --git a/src/helma/scripting/fesi/HopExtension.java b/src/helma/scripting/fesi/HopExtension.java index be0a8653..30134a2d 100644 --- a/src/helma/scripting/fesi/HopExtension.java +++ b/src/helma/scripting/fesi/HopExtension.java @@ -20,7 +20,7 @@ import org.xml.sax.InputSource; /** * This is the basic Extension for FESI interpreters used in Helma. It sets up * varios constructors, global functions and properties on the HopObject prototype - * (Node objects), the user prototype, the global prototype etc. + * (Node objects), the global prototype, the session object etc. */ public class HopExtension { @@ -61,8 +61,8 @@ public class HopExtension { ObjectPrototype esObjectPrototype = new ObjectPrototype (op, evaluator); // the Node prototype ObjectPrototype esNodePrototype = new ObjectPrototype(op, evaluator); - // the User prototype - ObjectPrototype esUserPrototype = new ObjectPrototype (esNodePrototype, evaluator); + // the Session prototype + ObjectPrototype esSessionPrototype = new ObjectPrototype (esNodePrototype, evaluator); // the Node constructor ESObject node = new NodeConstructor ("Node", fp, fesi); @@ -97,12 +97,6 @@ public class HopExtension { go.putHiddenProperty("HopObject", node); // HopObject is the new name for node. go.putHiddenProperty("getProperty", new GlobalGetProperty ("getProperty", evaluator, fp)); go.putHiddenProperty("token", new GlobalGetProperty ("token", evaluator, fp)); - go.putHiddenProperty("getUser", new GlobalGetUser ("getUser", evaluator, fp)); - go.putHiddenProperty("getUserBySession", new GlobalGetUserBySession ("getUserBySession", evaluator, fp)); - go.putHiddenProperty("getAllUsers", new GlobalGetAllUsers ("getAllUsers", evaluator, fp)); - go.putHiddenProperty("getActiveUsers", new GlobalGetActiveUsers ("getActiveUsers", evaluator, fp)); - go.putHiddenProperty("countActiveUsers", new GlobalCountActiveUsers ("countActiveUsers", evaluator, fp)); - go.putHiddenProperty("isActive", new GlobalIsActive ("isActive", evaluator, fp)); go.putHiddenProperty("getAge", new GlobalGetAge ("getAge", evaluator, fp)); go.putHiddenProperty("getURL", new GlobalGetURL ("getURL", evaluator, fp)); go.putHiddenProperty("encode", new GlobalEncode ("encode", evaluator, fp)); @@ -120,20 +114,11 @@ public class HopExtension { go.putHiddenProperty("authenticate", new GlobalAuthenticate ("authenticate", evaluator, fp)); go.deleteProperty("exit", "exit".hashCode()); - // and some methods for session management from JS... - esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp)); - esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp)); - esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp)); - esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp)); - esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp)); - esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp)); - esUserPrototype.putHiddenProperty("touch", new UserTouch ("touch", evaluator, fp)); - // register object prototypes with FesiEvaluator fesi.putPrototype ("global", go); fesi.putPrototype ("hopobject", esNodePrototype); fesi.putPrototype ("__javaobject__", esObjectPrototype); - fesi.putPrototype ("user", esUserPrototype); +// fesi.putPrototype ("session", esSessionPrototype); } class NodeAdd extends BuiltinFunctionObject { @@ -415,92 +400,6 @@ public class HopExtension { } } - class UserLogin extends BuiltinFunctionObject { - UserLogin (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - if (arguments.length < 2) - return ESBoolean.makeBoolean(false); - ESUser u = (ESUser) thisObject; - if (u.user == null) - throw new EcmaScriptException ("login() can only be called for user objects that are online at the moment!"); - boolean success = app.loginUser (arguments[0].toString (), arguments[1].toString (), u); - try { - u.doIndirectCall (this.evaluator, u, "onLogin", new ESValue[0]); - } catch (Exception nosuch) {} - return ESBoolean.makeBoolean (success); - } - } - - class UserRegister extends BuiltinFunctionObject { - UserRegister (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 2); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - if (arguments.length < 2) - return ESBoolean.makeBoolean(false); - INode unode = app.registerUser (arguments[0].toString (), arguments[1].toString ()); - if (unode == null) - return ESNull.theNull; - else - return fesi.getNodeWrapper (unode); - } - } - - class UserLogout extends BuiltinFunctionObject { - UserLogout (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - ESUser u = (ESUser) thisObject; - if (u.user == null) - return ESBoolean.makeBoolean (true); - try { - u.doIndirectCall (this.evaluator, u, "onLogout", new ESValue[0]); - } catch (Exception nosuch) {} - return ESBoolean.makeBoolean (app.logoutUser (u)); - } - } - - class UserOnSince extends BuiltinFunctionObject { - UserOnSince (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - ESUser u = (ESUser) thisObject; - if (u.user == null) - throw new EcmaScriptException ("onSince() can only be called for users that are online at the moment!"); - DatePrototype date = new DatePrototype(this.evaluator, new Date (u.user.onSince ())); - return date; - } - } - - class UserLastActive extends BuiltinFunctionObject { - UserLastActive (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - ESUser u = (ESUser) thisObject; - if (u.user == null) - throw new EcmaScriptException ("lastActive() can only be called for users that are online at the moment!"); - DatePrototype date = new DatePrototype(this.evaluator, new Date (u.user.lastTouched ())); - return date; - } - } - - class UserTouch extends BuiltinFunctionObject { - UserTouch (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - ESUser u = (ESUser) thisObject; - if (u.user != null) - u.user.touch (); - return ESNull.theNull; - } - } - class GlobalGetProperty extends BuiltinFunctionObject { GlobalGetProperty (String name, Evaluator evaluator, FunctionPrototype fp) { super (fp, evaluator, name, 1); @@ -625,109 +524,6 @@ public class HopExtension { } - - class GlobalGetUser extends BuiltinFunctionObject { - GlobalGetUser (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - INode user = null; - if (arguments.length > 0) { - String uname = arguments[0].toString ().trim (); - user = app.getUserNode (uname); - } - if (user == null) - return ESNull.theNull; - return fesi.getNodeWrapper (user); - } - } - - class GlobalGetUserBySession extends BuiltinFunctionObject { - GlobalGetUserBySession (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - User user = null; - if (arguments.length > 0) { - String sid = arguments[0].toString ().trim (); - user = app.getUser (sid); - } - if (user == null || user.getUID() == null) - return ESNull.theNull; - user.touch (); - return fesi.getNodeWrapper (user.getNode ()); - } - } - - - class GlobalGetAllUsers extends BuiltinFunctionObject { - GlobalGetAllUsers (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - INode users = app.getUserRoot (); - ESObject ap = this.evaluator.getArrayPrototype(); - ArrayPrototype theArray = new ArrayPrototype(ap, this.evaluator); - int i=0; - for (Enumeration e=users.properties (); e.hasMoreElements (); ) { - String propname = (String) e.nextElement (); - theArray.putProperty (i++, new ESString (propname)); - } - return theArray; - } - } - - class GlobalGetActiveUsers extends BuiltinFunctionObject { - GlobalGetActiveUsers (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - Hashtable sessions = (Hashtable) app.sessions.clone (); - ESObject ap = this.evaluator.getArrayPrototype(); - ArrayPrototype theArray = new ArrayPrototype (ap, this.evaluator); - theArray.setSize (sessions.size ()); - int i=0; - // Hashtable visited = new Hashtable (); - for (Enumeration e=sessions.elements(); e.hasMoreElements(); ) { - User u = (User) e.nextElement (); - // Note: we previously sorted out duplicate users - now we simply enumerate all active sessions. - // if (u.uid == null || !visited.containsKey (u.uid)) { - theArray.setElementAt (fesi.getNodeWrapper (u), i++); - // if (u.uid != null) visited.put (u.uid, u); - // } - } - return theArray; - } - } - - class GlobalCountActiveUsers extends BuiltinFunctionObject { - GlobalCountActiveUsers (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - return new ESNumber (app.sessions.size ()); - } - } - - class GlobalIsActive extends BuiltinFunctionObject { - GlobalIsActive (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - if (arguments.length < 1) - return ESBoolean.makeBoolean (false); - String username = null; - boolean active = false; - if (arguments[0] instanceof ESUser) { - ESUser esu = (ESUser) arguments[0]; - active = (esu.user != null); - } else { - active = app.activeUsers.contains (arguments[0].toString ()); - } - return ESBoolean.makeBoolean (active); - } - } - class GlobalGetAge extends BuiltinFunctionObject { GlobalGetAge (String name, Evaluator evaluator, FunctionPrototype fp) { super (fp, evaluator, name, 1); diff --git a/src/helma/scripting/fesi/extensions/ESMail.java b/src/helma/scripting/fesi/extensions/ESMail.java index 5bd5883a..b244e9c6 100644 --- a/src/helma/scripting/fesi/extensions/ESMail.java +++ b/src/helma/scripting/fesi/extensions/ESMail.java @@ -9,7 +9,6 @@ import javax.mail.internet.*; import javax.activation.*; import java.io.*; import java.util.*; -import helma.framework.core.*; import helma.util.*; import FESI.Data.*; import FESI.Interpreter.*; diff --git a/src/helma/util/SystemProperties.java b/src/helma/util/SystemProperties.java index 01c0a4e4..d7fbfcf0 100644 --- a/src/helma/util/SystemProperties.java +++ b/src/helma/util/SystemProperties.java @@ -141,6 +141,12 @@ public final class SystemProperties extends Properties { return props.keys(); } + public Set keySet () { + if (System.currentTimeMillis () - lastcheck > cacheTime) + checkFile (); + return props.keySet(); + } + public Enumeration elements () { if (System.currentTimeMillis () - lastcheck > cacheTime) checkFile ();