home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2000 November / APCD25112k.iso / feature / webserv / SAMBAR43.ZIP / _SETUP.1 / javaeng.jar / com / sambar / javaeng / SambarContext.java < prev    next >
Encoding:
Java Source  |  2000-04-03  |  11.0 KB  |  520 lines

  1. /*
  2. **         Sambar Server JAVA Engine Implementation
  3. **
  4. **        Confidential Property of Tod Sambar
  5. **        (c) Copyright Tod Sambar 1999
  6. **        All rights reserved.
  7. */
  8. package com.sambar.javaeng;
  9.  
  10. import java.io.*;
  11. import java.net.*;
  12. import java.util.*;
  13. import javax.servlet.*;
  14. import javax.servlet.http.*;
  15. import com.sambar.javaeng.SambarAPI;
  16.  
  17. class SambarContext implements ServletConfig, ServletContext, 
  18.         HttpSessionContext, Runnable
  19. {
  20.     public Vector                emptyVector;
  21.     private long                 javaeng;
  22.     static private int             sessionCount = 0;
  23.     protected Hashtable            servletHash;
  24.     protected Hashtable         sessionHash;
  25.     protected Hashtable         contextData;
  26.     protected SambarClassLoader    loader;
  27.  
  28.     int                         sessionTimeout;
  29.     int                         sessionCheckFrequency;
  30.  
  31.     private static class ServletEntry
  32.     {
  33.         int            count;
  34.         Servlet        servlet;
  35.     }
  36.  
  37.     public SambarContext(long javaeng) throws RuntimeException
  38.     {
  39.         String    val;
  40.  
  41.         this.javaeng = javaeng;
  42.         this.sessionTimeout = 0;
  43.         this.sessionCheckFrequency = 0;
  44.  
  45.         val = System.getProperty("sessionTimeout");
  46.         if (val != null)
  47.             this.sessionTimeout = Integer.parseInt(val);
  48.  
  49.         val = System.getProperty("sessionCheckFrequency");
  50.         if (val != null)
  51.             this.sessionCheckFrequency = Integer.parseInt(val);
  52.  
  53.         if (this.sessionTimeout <= 1000)
  54.             this.sessionTimeout = 1800000;
  55.         if (this.sessionCheckFrequency <= 1000)
  56.             this.sessionCheckFrequency = 5000;
  57.  
  58.         servletHash = new Hashtable();
  59.         sessionHash = new Hashtable();
  60.         contextData = new Hashtable();
  61.         emptyVector = new Vector();
  62.         String path = SambarAPI.getServletsPath(javaeng);
  63.         Vector classRepository = parsepath(path);
  64.  
  65.         try
  66.         {
  67.             loader = new SambarClassLoader(this, classRepository, true);
  68.         }
  69.         catch (IllegalArgumentException e)
  70.         {
  71.             log("SambarClassLoader failed (invalid CLASSPATH?) - " + 
  72.                 e.toString()); 
  73.  
  74.             throw new RuntimeException("SambarClassLoader failed: " + 
  75.                 e.toString());
  76.         }
  77.  
  78.         Thread housekeeping = new Thread(this);
  79.         housekeeping.setDaemon(true);
  80.         housekeeping.start();
  81.     }
  82.  
  83.     public Vector parsepath(String classpath) 
  84.     {
  85.         Vector    path = new Vector();
  86.  
  87.         if (classpath == null)
  88.             return path;
  89.  
  90.         StringTokenizer stok = new StringTokenizer(classpath, ";");
  91.         while (stok.hasMoreTokens())
  92.         {
  93.             String tok = stok.nextToken();
  94.             if (tok.length() > 0)        
  95.                 path.addElement(tok);
  96.         }
  97.  
  98.         return path;
  99.     }
  100.  
  101.     public ServletContext getServletContext() 
  102.     {
  103.         return this;
  104.     }
  105.  
  106.     public String getInitParameter(String name) 
  107.     {
  108.         return SambarAPI.getInitParameter(javaeng, name);
  109.     }
  110.  
  111.     public Enumeration getInitParameterNames()
  112.     {
  113.         return emptyVector.elements();
  114.     }
  115.  
  116.     public void log(String msg) 
  117.     {
  118.         SambarAPI.logctx(javaeng, msg);
  119.     }
  120.  
  121.     public void log(Exception e, String msg)
  122.     {
  123.         log(msg + " - " + e.toString());
  124.     }
  125.  
  126.     public void log(String msg, Throwable throwable) 
  127.     {
  128.         log(msg + " - " + throwable.toString());
  129.     }
  130.  
  131.     public ServletContext getContext(String uripath) 
  132.     {
  133.         return this;
  134.     }
  135.  
  136.     public int getMajorVersion() 
  137.     {
  138.         return 2;
  139.     }
  140.  
  141.     public int getMinorVersion() 
  142.     {
  143.         return 1;
  144.     }
  145.  
  146.     public String getMimeType(String file) 
  147.     {
  148.         return SambarAPI.getMimeType(javaeng, file);
  149.     }
  150.  
  151.     public String getRealPath(String path) 
  152.     {
  153.         return SambarAPI.getRealPath(javaeng, path);
  154.     }
  155.  
  156.     public String getServerInfo() 
  157.     {
  158.         return SambarAPI.getServerInfo(javaeng);
  159.     }
  160.  
  161.     public Object getAttribute(String name) 
  162.     {
  163.         return contextData.get(name);
  164.     }
  165.  
  166.     public void removeAttribute(String name) 
  167.     {
  168.         contextData.remove(name);
  169.     }
  170.  
  171.     public Enumeration getAttributeNames() 
  172.     {
  173.         return contextData.keys();
  174.     }
  175.  
  176.     public void setAttribute(String name, Object object) 
  177.     {
  178.         contextData.put(name, object);
  179.     }
  180.  
  181.     public URL getResource(String path) throws MalformedURLException
  182.     {
  183.         return new URL("file:" + getRealPath(path));
  184.     }
  185.  
  186.     public InputStream getResourceAsStream(String path)
  187.     {
  188.         InputStream is = null;
  189.         URL u = null;
  190.         try
  191.         {
  192.             u = getResource(path);
  193.         }
  194.         catch (MalformedURLException mue)
  195.         {
  196.             u = null;
  197.         }
  198.  
  199.         if (u != null)
  200.         {
  201.             try
  202.             {
  203.                 is = u.openStream();
  204.             } 
  205.             catch (IOException ioe)
  206.             {
  207.             }
  208.         }
  209.  
  210.         return is;
  211.     }
  212.  
  213.     public RequestDispatcher getRequestDispatcher(String urlpath)
  214.     {
  215.         if ((urlpath == null)  || !(urlpath.startsWith("/"))) 
  216.         {
  217.             // Return null if we can't return a dispather
  218.             return null; 
  219.         }
  220.  
  221.         SambarRequestDispatcher rd = new SambarRequestDispatcher(this);
  222.         rd.setPath(urlpath);
  223.  
  224.         return rd;
  225.     }
  226.  
  227.     public synchronized Servlet getServlet(String name, boolean cache) 
  228.         throws ServletException
  229.     {
  230.         // Strip .class from the servlet if it is present.
  231.         if ((name.length() > 6) &&
  232.             (name.endsWith(".class") || name.endsWith(".CLASS")))
  233.         {
  234.             name = name.substring(0, name.length() - 6);
  235.         }
  236.  
  237.         ServletEntry entry = null;
  238.  
  239.         if (loader.shouldReload(name))
  240.         {
  241.             log("SambarClassLoader reloading...");
  242.             loader = loader.reinstantiate();
  243.  
  244.             // Destroy the old cached servlet (if it exists)
  245.             entry = (ServletEntry)servletHash.get(name);
  246.             if (entry != null)
  247.             {
  248.                 try
  249.                 {
  250.                     servletHash.remove(name);
  251.                 }
  252.                 catch(Exception e)
  253.                 {
  254.                     log("Servlet '"+name+"' destroy failure - "+e.toString());
  255.                 }
  256.             }
  257.         }
  258.  
  259.         entry = null;
  260.         if (cache)
  261.         {
  262.             entry = (ServletEntry)servletHash.get(name);
  263.             if (entry != null)
  264.             {
  265.                 entry.count++;
  266.                 return entry.servlet;
  267.             }
  268.         }
  269.  
  270.         Servlet servlet = null;
  271.  
  272.         try
  273.         {
  274.             servlet = (Servlet)loader.loadClass(name).newInstance();
  275.         }
  276.         catch (NoClassDefFoundError e)
  277.         {
  278.             log("NoClassDefFoundError: " + name + " - " + e.toString());
  279.             return null;
  280.         }
  281.         catch (ClassNotFoundException e)
  282.         {
  283.             log("ClassNotFoundException: " + name + " - " + e.toString());
  284.             return null;
  285.         }
  286.         catch (ClassFormatError e)
  287.         {
  288.             log("ClassFormatError: " + name + " - " + e.toString());
  289.             return null;
  290.         }
  291.         catch (IllegalAccessException e)
  292.         {
  293.             log("IllegalAccessException: " + name + " - " + e.toString());
  294.             return null;
  295.         }
  296.         catch (InstantiationException e)
  297.         {
  298.             log("InstantiationException: " + name + " - " + e.toString());
  299.             return null;
  300.         }
  301.         catch (Exception e)
  302.         {
  303.             log("Exception: " + name + " - " + e.toString());
  304.             return null;
  305.         }
  306.  
  307.         try
  308.         {
  309.             servlet.init(this);
  310.         }
  311.         catch (ServletException e)
  312.         {
  313.             log("ServletException: " + name + " - " + e.toString());
  314.             return null;
  315.         }
  316.         catch (Exception e)
  317.         {
  318.             log("Exception: " + name + " - " + e.toString());
  319.             return null;
  320.         }
  321.  
  322.         if (cache)
  323.         {
  324.             entry = new ServletEntry();
  325.             entry.count = 1;
  326.             entry.servlet = servlet;
  327.  
  328.             servletHash.put(name, entry);
  329.         }
  330.  
  331.         return servlet;
  332.     }
  333.  
  334.     public synchronized Servlet getServlet(String name) 
  335.         throws ServletException
  336.     {
  337.         return getServlet(name, true); 
  338.     }
  339.  
  340.     public Enumeration getServlets()
  341.     {
  342.         return emptyVector.elements();
  343.     }
  344.  
  345.     public Enumeration getServletNames()
  346.     {
  347.         return emptyVector.elements();
  348.     }
  349.  
  350.     public synchronized void destroyServlet(String name)
  351.     {
  352.         destroyServlet(name, false);
  353.     }
  354.  
  355.     public synchronized void destroyServlet(String name, boolean force)
  356.     {
  357.         if (name == null)
  358.             return;
  359.  
  360.         ServletEntry entry = (ServletEntry)servletHash.get(name);
  361.         if (entry == null)
  362.             return;
  363.  
  364.         // Don't destroy the servlet if it is in use.
  365.         if (!force)
  366.         {
  367.             entry.count--;
  368.             if (entry.count > 0)
  369.                 return;
  370.         }
  371.  
  372.         try
  373.         {
  374.             entry.servlet.destroy();
  375.             servletHash.remove(name);
  376.         }
  377.         catch(Exception e)
  378.         {
  379.             log("Servlet '" + name + "' destroy failure - " + e.toString());
  380.         }
  381.     }
  382.  
  383.     public synchronized void destroyServlets()
  384.     {
  385.         int i = 0;
  386.         String[] tmpServlets = new String[servletHash.size()];
  387.         Enumeration servletEnum = servletHash.keys();
  388.         while (servletEnum.hasMoreElements())
  389.         {
  390.             tmpServlets[i++] = (String)servletEnum.nextElement();
  391.         }
  392.  
  393.         try
  394.         {
  395.             while (i > 0)
  396.             {
  397.                 i--;
  398.                 destroyServlet(tmpServlets[i], true);
  399.             }
  400.         }
  401.         finally
  402.         {
  403.             servletHash.clear();
  404.         }
  405.     }
  406.  
  407.     public synchronized HttpSession getSession(String sessionId) 
  408.     {
  409.         return (HttpSession)sessionHash.get(sessionId);
  410.     }
  411.  
  412.     public synchronized SambarSession createSession(SambarConnection sconn)
  413.     {
  414.         SambarSession session;
  415.  
  416.         session = new SambarSession(getIdentifier(), this, sessionTimeout);
  417.         sessionHash.put(session.id, session);
  418.  
  419.         Cookie cookie = new Cookie(SambarAPI.SESSION_ID, session.id);
  420.         cookie.setPath("/");
  421.         sconn.addCookie(cookie);
  422.  
  423.         return session;
  424.     }
  425.  
  426.     public synchronized void removeSession(SambarSession session)
  427.     {
  428.         sessionHash.remove(session.id);
  429.     }
  430.  
  431.     /*
  432.     ** Create a suitable string for session identification
  433.     ** Use count and synchronized to ensure uniqueness.
  434.     ** Use timestamp because it useful in session timeouts.
  435.     ** Use random string to ensure timestamp cannot be guessed
  436.     ** by programmed attack.
  437.     **
  438.     ** format of id is <random-hex-string>.<count>.<timestamp-ms>
  439.     */
  440.     static synchronized private String getIdentifier() 
  441.     {
  442.         String time;
  443.         String random;
  444.  
  445.         random = Long.toHexString(Double.doubleToLongBits(Math.random()));
  446.         time = Long.toString(System.currentTimeMillis());
  447.         sessionCount++;
  448.  
  449.         return random + "-" + time + "-" + sessionCount;
  450.     }
  451.  
  452.     synchronized private String getIdentifier(String jsIdent) 
  453.     {
  454.         if (jsIdent != null)
  455.             return getIdentifier() + "-" + jsIdent;
  456.  
  457.         return getIdentifier();
  458.     }
  459.  
  460.     /*
  461.     ** Returns an enumeration of all of the session IDs in this context.
  462.     */
  463.     public synchronized Enumeration getIds() 
  464.     {
  465.         Vector ids = new Vector();
  466.         Enumeration idEnum = sessionHash.keys();
  467.         while (idEnum.hasMoreElements()) 
  468.             ids.addElement( idEnum.nextElement() );
  469.  
  470.         return ids.elements();
  471.     }
  472.  
  473.     
  474.     /*
  475.     ** The housekeeping thread
  476.     ** Checks for sessions that have not been used for a certain
  477.     ** amount of time and invalidates them.
  478.     */
  479.     public void run() 
  480.     {
  481.         Enumeration sessions;
  482.         SambarSession session;
  483.         long sysMillis;
  484.  
  485.         while (true) 
  486.         {
  487.             // sleep for 5 seconds.
  488.             try 
  489.             {
  490.                 Thread.sleep(sessionCheckFrequency);
  491.             } 
  492.             catch(InterruptedException exc) 
  493.             {
  494.             }
  495.  
  496.             // walk through all sessions and invalidate old ones
  497.             sessions = sessionHash.elements();
  498.             sysMillis = System.currentTimeMillis();            
  499.             while (sessions.hasMoreElements()) 
  500.             {
  501.                 session = (SambarSession)sessions.nextElement();
  502.                 synchronized (session) 
  503.                 {
  504.                     if (sysMillis - session.lastAccessTime > 
  505.                         session.getMaxInactiveInterval())
  506.                     {
  507.                         try
  508.                         {
  509.                             session.invalidate();
  510.                         }
  511.                         catch (IllegalStateException ignored) 
  512.                         {
  513.                         }
  514.                     }
  515.                 }
  516.             }
  517.         }
  518.     }
  519. }
  520.