Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » authenticator » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   
   19   package org.apache.catalina.authenticator;
   20   
   21   
   22   import java.io.IOException;
   23   import java.security.MessageDigest;
   24   import java.security.NoSuchAlgorithmException;
   25   import java.security.Principal;
   26   import java.text.SimpleDateFormat;
   27   import java.util.Date;
   28   import java.util.Locale;
   29   import java.util.Random;
   30   
   31   import javax.servlet.ServletException;
   32   import javax.servlet.http.Cookie;
   33   
   34   import org.apache.catalina.Authenticator;
   35   import org.apache.catalina.Container;
   36   import org.apache.catalina.Context;
   37   import org.apache.catalina.Lifecycle;
   38   import org.apache.catalina.LifecycleException;
   39   import org.apache.catalina.LifecycleListener;
   40   import org.apache.catalina.Pipeline;
   41   import org.apache.catalina.Realm;
   42   import org.apache.catalina.Session;
   43   import org.apache.catalina.Valve;
   44   import org.apache.catalina.connector.Request;
   45   import org.apache.catalina.connector.Response;
   46   import org.apache.catalina.deploy.LoginConfig;
   47   import org.apache.catalina.deploy.SecurityConstraint;
   48   import org.apache.catalina.util.DateTool;
   49   import org.apache.catalina.util.LifecycleSupport;
   50   import org.apache.catalina.util.StringManager;
   51   import org.apache.catalina.valves.ValveBase;
   52   import org.apache.juli.logging.Log;
   53   import org.apache.juli.logging.LogFactory;
   54   
   55   
   56   /**
   57    * Basic implementation of the <b>Valve</b> interface that enforces the
   58    * <code>&lt;security-constraint&gt;</code> elements in the web application
   59    * deployment descriptor.  This functionality is implemented as a Valve
   60    * so that it can be ommitted in environments that do not require these
   61    * features.  Individual implementations of each supported authentication
   62    * method can subclass this base class as required.
   63    * <p>
   64    * <b>USAGE CONSTRAINT</b>:  When this class is utilized, the Context to
   65    * which it is attached (or a parent Container in a hierarchy) must have an
   66    * associated Realm that can be used for authenticating users and enumerating
   67    * the roles to which they have been assigned.
   68    * <p>
   69    * <b>USAGE CONSTRAINT</b>:  This Valve is only useful when processing HTTP
   70    * requests.  Requests of any other type will simply be passed through.
   71    *
   72    * @author Craig R. McClanahan
   73    * @version $Revision: 500626 $ $Date: 2007-01-27 22:25:41 +0100 (sam., 27 janv. 2007) $
   74    */
   75   
   76   
   77   public abstract class AuthenticatorBase
   78       extends ValveBase
   79       implements Authenticator, Lifecycle {
   80       private static Log log = LogFactory.getLog(AuthenticatorBase.class);
   81   
   82   
   83       // ----------------------------------------------------- Instance Variables
   84   
   85   
   86       /**
   87        * The default message digest algorithm to use if we cannot use
   88        * the requested one.
   89        */
   90       protected static final String DEFAULT_ALGORITHM = "MD5";
   91   
   92   
   93       /**
   94        * The number of random bytes to include when generating a
   95        * session identifier.
   96        */
   97       protected static final int SESSION_ID_BYTES = 16;
   98   
   99   
  100       /**
  101        * The message digest algorithm to be used when generating session
  102        * identifiers.  This must be an algorithm supported by the
  103        * <code>java.security.MessageDigest</code> class on your platform.
  104        */
  105       protected String algorithm = DEFAULT_ALGORITHM;
  106   
  107   
  108       /**
  109        * Should we cache authenticated Principals if the request is part of
  110        * an HTTP session?
  111        */
  112       protected boolean cache = true;
  113   
  114   
  115       /**
  116        * The Context to which this Valve is attached.
  117        */
  118       protected Context context = null;
  119   
  120   
  121       /**
  122        * Return the MessageDigest implementation to be used when
  123        * creating session identifiers.
  124        */
  125       protected MessageDigest digest = null;
  126   
  127   
  128       /**
  129        * A String initialization parameter used to increase the entropy of
  130        * the initialization of our random number generator.
  131        */
  132       protected String entropy = null;
  133   
  134   
  135       /**
  136        * Descriptive information about this implementation.
  137        */
  138       protected static final String info =
  139           "org.apache.catalina.authenticator.AuthenticatorBase/1.0";
  140   
  141       /**
  142        * Flag to determine if we disable proxy caching, or leave the issue
  143        * up to the webapp developer.
  144        */
  145       protected boolean disableProxyCaching = true;
  146   
  147       /**
  148        * Flag to determine if we disable proxy caching with headers incompatible
  149        * with IE 
  150        */
  151       protected boolean securePagesWithPragma = true;
  152       
  153       /**
  154        * The lifecycle event support for this component.
  155        */
  156       protected LifecycleSupport lifecycle = new LifecycleSupport(this);
  157   
  158   
  159       /**
  160        * A random number generator to use when generating session identifiers.
  161        */
  162       protected Random random = null;
  163   
  164   
  165       /**
  166        * The Java class name of the random number generator class to be used
  167        * when generating session identifiers.
  168        */
  169       protected String randomClass = "java.security.SecureRandom";
  170   
  171   
  172       /**
  173        * The string manager for this package.
  174        */
  175       protected static final StringManager sm =
  176           StringManager.getManager(Constants.Package);
  177   
  178   
  179       /**
  180        * The SingleSignOn implementation in our request processing chain,
  181        * if there is one.
  182        */
  183       protected SingleSignOn sso = null;
  184   
  185   
  186       /**
  187        * Has this component been started?
  188        */
  189       protected boolean started = false;
  190   
  191   
  192       /**
  193        * "Expires" header always set to Date(1), so generate once only
  194        */
  195       private static final String DATE_ONE =
  196           (new SimpleDateFormat(DateTool.HTTP_RESPONSE_DATE_HEADER,
  197                                 Locale.US)).format(new Date(1));
  198   
  199   
  200       // ------------------------------------------------------------- Properties
  201   
  202   
  203       /**
  204        * Return the message digest algorithm for this Manager.
  205        */
  206       public String getAlgorithm() {
  207   
  208           return (this.algorithm);
  209   
  210       }
  211   
  212   
  213       /**
  214        * Set the message digest algorithm for this Manager.
  215        *
  216        * @param algorithm The new message digest algorithm
  217        */
  218       public void setAlgorithm(String algorithm) {
  219   
  220           this.algorithm = algorithm;
  221   
  222       }
  223   
  224   
  225       /**
  226        * Return the cache authenticated Principals flag.
  227        */
  228       public boolean getCache() {
  229   
  230           return (this.cache);
  231   
  232       }
  233   
  234   
  235       /**
  236        * Set the cache authenticated Principals flag.
  237        *
  238        * @param cache The new cache flag
  239        */
  240       public void setCache(boolean cache) {
  241   
  242           this.cache = cache;
  243   
  244       }
  245   
  246   
  247       /**
  248        * Return the Container to which this Valve is attached.
  249        */
  250       public Container getContainer() {
  251   
  252           return (this.context);
  253   
  254       }
  255   
  256   
  257       /**
  258        * Set the Container to which this Valve is attached.
  259        *
  260        * @param container The container to which we are attached
  261        */
  262       public void setContainer(Container container) {
  263   
  264           if (!(container instanceof Context))
  265               throw new IllegalArgumentException
  266                   (sm.getString("authenticator.notContext"));
  267   
  268           super.setContainer(container);
  269           this.context = (Context) container;
  270   
  271       }
  272   
  273   
  274       /**
  275        * Return the entropy increaser value, or compute a semi-useful value
  276        * if this String has not yet been set.
  277        */
  278       public String getEntropy() {
  279   
  280           // Calculate a semi-useful value if this has not been set
  281           if (this.entropy == null)
  282               setEntropy(this.toString());
  283   
  284           return (this.entropy);
  285   
  286       }
  287   
  288   
  289       /**
  290        * Set the entropy increaser value.
  291        *
  292        * @param entropy The new entropy increaser value
  293        */
  294       public void setEntropy(String entropy) {
  295   
  296           this.entropy = entropy;
  297   
  298       }
  299   
  300   
  301       /**
  302        * Return descriptive information about this Valve implementation.
  303        */
  304       public String getInfo() {
  305   
  306           return (info);
  307   
  308       }
  309   
  310   
  311       /**
  312        * Return the random number generator class name.
  313        */
  314       public String getRandomClass() {
  315   
  316           return (this.randomClass);
  317   
  318       }
  319   
  320   
  321       /**
  322        * Set the random number generator class name.
  323        *
  324        * @param randomClass The new random number generator class name
  325        */
  326       public void setRandomClass(String randomClass) {
  327   
  328           this.randomClass = randomClass;
  329   
  330       }
  331   
  332       /**
  333        * Return the flag that states if we add headers to disable caching by
  334        * proxies.
  335        */
  336       public boolean getDisableProxyCaching() {
  337           return disableProxyCaching;
  338       }
  339   
  340       /**
  341        * Set the value of the flag that states if we add headers to disable
  342        * caching by proxies.
  343        * @param nocache <code>true</code> if we add headers to disable proxy 
  344        *              caching, <code>false</code> if we leave the headers alone.
  345        */
  346       public void setDisableProxyCaching(boolean nocache) {
  347           disableProxyCaching = nocache;
  348       }
  349       
  350       /**
  351        * Return the flag that states, if proxy caching is disabled, what headers
  352        * we add to disable the caching.
  353        */
  354       public boolean getSecurePagesWithPragma() {
  355           return securePagesWithPragma;
  356       }
  357   
  358       /**
  359        * Set the value of the flag that states what headers we add to disable
  360        * proxy caching.
  361        * @param securePagesWithPragma <code>true</code> if we add headers which 
  362        * are incompatible with downloading office documents in IE under SSL but
  363        * which fix a caching problem in Mozilla.
  364        */
  365       public void setSecurePagesWithPragma(boolean securePagesWithPragma) {
  366           this.securePagesWithPragma = securePagesWithPragma;
  367       }    
  368   
  369       // --------------------------------------------------------- Public Methods
  370   
  371   
  372       /**
  373        * Enforce the security restrictions in the web application deployment
  374        * descriptor of our associated Context.
  375        *
  376        * @param request Request to be processed
  377        * @param response Response to be processed
  378        *
  379        * @exception IOException if an input/output error occurs
  380        * @exception ServletException if thrown by a processing element
  381        */
  382       public void invoke(Request request, Response response)
  383           throws IOException, ServletException {
  384   
  385           if (log.isDebugEnabled())
  386               log.debug("Security checking request " +
  387                   request.getMethod() + " " + request.getRequestURI());
  388           LoginConfig config = this.context.getLoginConfig();
  389   
  390           // Have we got a cached authenticated Principal to record?
  391           if (cache) {
  392               Principal principal = request.getUserPrincipal();
  393               if (principal == null) {
  394                   Session session = request.getSessionInternal(false);
  395                   if (session != null) {
  396                       principal = session.getPrincipal();
  397                       if (principal != null) {
  398                           if (log.isDebugEnabled())
  399                               log.debug("We have cached auth type " +
  400                                   session.getAuthType() +
  401                                   " for principal " +
  402                                   session.getPrincipal());
  403                           request.setAuthType(session.getAuthType());
  404                           request.setUserPrincipal(principal);
  405                       }
  406                   }
  407               }
  408           }
  409   
  410           // Special handling for form-based logins to deal with the case
  411           // where the login form (and therefore the "j_security_check" URI
  412           // to which it submits) might be outside the secured area
  413           String contextPath = this.context.getPath();
  414           String requestURI = request.getDecodedRequestURI();
  415           if (requestURI.startsWith(contextPath) &&
  416               requestURI.endsWith(Constants.FORM_ACTION)) {
  417               if (!authenticate(request, response, config)) {
  418                   if (log.isDebugEnabled())
  419                       log.debug(" Failed authenticate() test ??" + requestURI );
  420                   return;
  421               }
  422           }
  423   
  424           Realm realm = this.context.getRealm();
  425           // Is this request URI subject to a security constraint?
  426           SecurityConstraint [] constraints
  427               = realm.findSecurityConstraints(request, this.context);
  428          
  429           if ((constraints == null) /* &&
  430               (!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
  431               if (log.isDebugEnabled())
  432                   log.debug(" Not subject to any constraint");
  433               getNext().invoke(request, response);
  434               return;
  435           }
  436   
  437           // Make sure that constrained resources are not cached by web proxies
  438           // or browsers as caching can provide a security hole
  439           if (disableProxyCaching && 
  440               // FIXME: Disabled for Mozilla FORM support over SSL 
  441               // (improper caching issue)
  442               //!request.isSecure() &&
  443               !"POST".equalsIgnoreCase(request.getMethod())) {
  444               if (securePagesWithPragma) {
  445                   // FIXME: These cause problems with downloading office docs
  446                   // from IE under SSL and may not be needed for newer Mozilla
  447                   // clients.
  448                   response.setHeader("Pragma", "No-cache");
  449                   response.setHeader("Cache-Control", "no-cache");
  450               } else {
  451                   response.setHeader("Cache-Control", "private");
  452               }
  453               response.setHeader("Expires", DATE_ONE);
  454           }
  455   
  456           int i;
  457           // Enforce any user data constraint for this security constraint
  458           if (log.isDebugEnabled()) {
  459               log.debug(" Calling hasUserDataPermission()");
  460           }
  461           if (!realm.hasUserDataPermission(request, response,
  462                                            constraints)) {
  463               if (log.isDebugEnabled()) {
  464                   log.debug(" Failed hasUserDataPermission() test");
  465               }
  466               /*
  467                * ASSERT: Authenticator already set the appropriate
  468                * HTTP status code, so we do not have to do anything special
  469                */
  470               return;
  471           }
  472   
  473           // Since authenticate modifies the response on failure,
  474           // we have to check for allow-from-all first.
  475           boolean authRequired = true;
  476           for(i=0; i < constraints.length && authRequired; i++) {
  477               if(!constraints[i].getAuthConstraint()) {
  478                   authRequired = false;
  479               } else if(!constraints[i].getAllRoles()) {
  480                   String [] roles = constraints[i].findAuthRoles();
  481                   if(roles == null || roles.length == 0) {
  482                       authRequired = false;
  483                   }
  484               }
  485           }
  486                
  487           if(authRequired) {  
  488               if (log.isDebugEnabled()) {
  489                   log.debug(" Calling authenticate()");
  490               }
  491               if (!authenticate(request, response, config)) {
  492                   if (log.isDebugEnabled()) {
  493                       log.debug(" Failed authenticate() test");
  494                   }
  495                   /*
  496                    * ASSERT: Authenticator already set the appropriate
  497                    * HTTP status code, so we do not have to do anything
  498                    * special
  499                    */
  500                   return;
  501               } 
  502           }
  503       
  504           if (log.isDebugEnabled()) {
  505               log.debug(" Calling accessControl()");
  506           }
  507           if (!realm.hasResourcePermission(request, response,
  508                                            constraints,
  509                                            this.context)) {
  510               if (log.isDebugEnabled()) {
  511                   log.debug(" Failed accessControl() test");
  512               }
  513               /*
  514                * ASSERT: AccessControl method has already set the
  515                * appropriate HTTP status code, so we do not have to do
  516                * anything special
  517                */
  518               return;
  519           }
  520       
  521           // Any and all specified constraints have been satisfied
  522           if (log.isDebugEnabled()) {
  523               log.debug(" Successfully passed all security constraints");
  524           }
  525           getNext().invoke(request, response);
  526   
  527       }
  528   
  529   
  530       // ------------------------------------------------------ Protected Methods
  531   
  532   
  533   
  534   
  535       /**
  536        * Associate the specified single sign on identifier with the
  537        * specified Session.
  538        *
  539        * @param ssoId Single sign on identifier
  540        * @param session Session to be associated
  541        */
  542       protected void associate(String ssoId, Session session) {
  543   
  544           if (sso == null)
  545               return;
  546           sso.associate(ssoId, session);
  547   
  548       }
  549   
  550   
  551       /**
  552        * Authenticate the user making this request, based on the specified
  553        * login configuration.  Return <code>true</code> if any specified
  554        * constraint has been satisfied, or <code>false</code> if we have
  555        * created a response challenge already.
  556        *
  557        * @param request Request we are processing
  558        * @param response Response we are creating
  559        * @param config    Login configuration describing how authentication
  560        *              should be performed
  561        *
  562        * @exception IOException if an input/output error occurs
  563        */
  564       protected abstract boolean authenticate(Request request,
  565                                               Response response,
  566                                               LoginConfig config)
  567           throws IOException;
  568   
  569   
  570       /**
  571        * Generate and return a new session identifier for the cookie that
  572        * identifies an SSO principal.
  573        */
  574       protected synchronized String generateSessionId() {
  575   
  576           // Generate a byte array containing a session identifier
  577           byte bytes[] = new byte[SESSION_ID_BYTES];
  578           getRandom().nextBytes(bytes);
  579           bytes = getDigest().digest(bytes);
  580   
  581           // Render the result as a String of hexadecimal digits
  582           StringBuffer result = new StringBuffer();
  583           for (int i = 0; i < bytes.length; i++) {
  584               byte b1 = (byte) ((bytes[i] & 0xf0) >> 4);
  585               byte b2 = (byte) (bytes[i] & 0x0f);
  586               if (b1 < 10)
  587                   result.append((char) ('0' + b1));
  588               else
  589                   result.append((char) ('A' + (b1 - 10)));
  590               if (b2 < 10)
  591                   result.append((char) ('0' + b2));
  592               else
  593                   result.append((char) ('A' + (b2 - 10)));
  594           }
  595           return (result.toString());
  596   
  597       }
  598   
  599   
  600       /**
  601        * Return the MessageDigest object to be used for calculating
  602        * session identifiers.  If none has been created yet, initialize
  603        * one the first time this method is called.
  604        */
  605       protected synchronized MessageDigest getDigest() {
  606   
  607           if (this.digest == null) {
  608               try {
  609                   this.digest = MessageDigest.getInstance(algorithm);
  610               } catch (NoSuchAlgorithmException e) {
  611                   try {
  612                       this.digest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
  613                   } catch (NoSuchAlgorithmException f) {
  614                       this.digest = null;
  615                   }
  616               }
  617           }
  618   
  619           return (this.digest);
  620   
  621       }
  622   
  623   
  624       /**
  625        * Return the random number generator instance we should use for
  626        * generating session identifiers.  If there is no such generator
  627        * currently defined, construct and seed a new one.
  628        */
  629       protected synchronized Random getRandom() {
  630   
  631           if (this.random == null) {
  632               try {
  633                   Class clazz = Class.forName(randomClass);
  634                   this.random = (Random) clazz.newInstance();
  635                   long seed = System.currentTimeMillis();
  636                   char entropy[] = getEntropy().toCharArray();
  637                   for (int i = 0; i < entropy.length; i++) {
  638                       long update = ((byte) entropy[i]) << ((i % 8) * 8);
  639                       seed ^= update;
  640                   }
  641                   this.random.setSeed(seed);
  642               } catch (Exception e) {
  643                   this.random = new java.util.Random();
  644               }
  645           }
  646   
  647           return (this.random);
  648   
  649       }
  650   
  651   
  652       /**
  653        * Attempts reauthentication to the <code>Realm</code> using
  654        * the credentials included in argument <code>entry</code>.
  655        *
  656        * @param ssoId identifier of SingleSignOn session with which the
  657        *              caller is associated
  658        * @param request   the request that needs to be authenticated
  659        */
  660       protected boolean reauthenticateFromSSO(String ssoId, Request request) {
  661   
  662           if (sso == null || ssoId == null)
  663               return false;
  664   
  665           boolean reauthenticated = false;
  666   
  667           Container parent = getContainer();
  668           if (parent != null) {
  669               Realm realm = parent.getRealm();
  670               if (realm != null) {
  671                   reauthenticated = sso.reauthenticate(ssoId, realm, request);
  672               }
  673           }
  674   
  675           if (reauthenticated) {
  676               associate(ssoId, request.getSessionInternal(true));
  677   
  678               if (log.isDebugEnabled()) {
  679                   log.debug(" Reauthenticated cached principal '" +
  680                             request.getUserPrincipal().getName() +
  681                             "' with auth type '" +  request.getAuthType() + "'");
  682               }
  683           }
  684   
  685           return reauthenticated;
  686       }
  687   
  688   
  689       /**
  690        * Register an authenticated Principal and authentication type in our
  691        * request, in the current session (if there is one), and with our
  692        * SingleSignOn valve, if there is one.  Set the appropriate cookie
  693        * to be returned.
  694        *
  695        * @param request The servlet request we are processing
  696        * @param response The servlet response we are generating
  697        * @param principal The authenticated Principal to be registered
  698        * @param authType The authentication type to be registered
  699        * @param username Username used to authenticate (if any)
  700        * @param password Password used to authenticate (if any)
  701        */
  702       protected void register(Request request, Response response,
  703                               Principal principal, String authType,
  704                               String username, String password) {
  705   
  706           if (log.isDebugEnabled())
  707               log.debug("Authenticated '" + principal.getName() + "' with type '"
  708                   + authType + "'");
  709   
  710           // Cache the authentication information in our request
  711           request.setAuthType(authType);
  712           request.setUserPrincipal(principal);
  713   
  714           Session session = request.getSessionInternal(false);
  715           // Cache the authentication information in our session, if any
  716           if (cache) {
  717               if (session != null) {
  718                   session.setAuthType(authType);
  719                   session.setPrincipal(principal);
  720                   if (username != null)
  721                       session.setNote(Constants.SESS_USERNAME_NOTE, username);
  722                   else
  723                       session.removeNote(Constants.SESS_USERNAME_NOTE);
  724                   if (password != null)
  725                       session.setNote(Constants.SESS_PASSWORD_NOTE, password);
  726                   else
  727                       session.removeNote(Constants.SESS_PASSWORD_NOTE);
  728               }
  729           }
  730   
  731           // Construct a cookie to be returned to the client
  732           if (sso == null)
  733               return;
  734   
  735           // Only create a new SSO entry if the SSO did not already set a note
  736           // for an existing entry (as it would do with subsequent requests
  737           // for DIGEST and SSL authenticated contexts)
  738           String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
  739           if (ssoId == null) {
  740               // Construct a cookie to be returned to the client
  741               ssoId = generateSessionId();
  742               Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, ssoId);
  743               cookie.setMaxAge(-1);
  744               cookie.setPath("/");
  745               
  746               // Bugzilla 41217
  747               cookie.setSecure(request.isSecure());
  748   
  749               // Bugzilla 34724
  750               String ssoDomain = sso.getCookieDomain();
  751               if(ssoDomain != null) {
  752                   cookie.setDomain(ssoDomain);
  753               }
  754   
  755               response.addCookie(cookie);
  756   
  757               // Register this principal with our SSO valve
  758               sso.register(ssoId, principal, authType, username, password);
  759               request.setNote(Constants.REQ_SSOID_NOTE, ssoId);
  760   
  761           } else {
  762               // Update the SSO session with the latest authentication data
  763               sso.update(ssoId, principal, authType, username, password);
  764           }
  765   
  766           // Fix for Bug 10040
  767           // Always associate a session with a new SSO reqistration.
  768           // SSO entries are only removed from the SSO registry map when
  769           // associated sessions are destroyed; if a new SSO entry is created
  770           // above for this request and the user never revisits the context, the
  771           // SSO entry will never be cleared if we don't associate the session
  772           if (session == null)
  773               session = request.getSessionInternal(true);
  774           sso.associate(ssoId, session);
  775   
  776       }
  777   
  778   
  779       // ------------------------------------------------------ Lifecycle Methods
  780   
  781   
  782       /**
  783        * Add a lifecycle event listener to this component.
  784        *
  785        * @param listener The listener to add
  786        */
  787       public void addLifecycleListener(LifecycleListener listener) {
  788   
  789           lifecycle.addLifecycleListener(listener);
  790   
  791       }
  792   
  793   
  794       /**
  795        * Get the lifecycle listeners associated with this lifecycle. If this 
  796        * Lifecycle has no listeners registered, a zero-length array is returned.
  797        */
  798       public LifecycleListener[] findLifecycleListeners() {
  799   
  800           return lifecycle.findLifecycleListeners();
  801   
  802       }
  803   
  804   
  805       /**
  806        * Remove a lifecycle event listener from this component.
  807        *
  808        * @param listener The listener to remove
  809        */
  810       public void removeLifecycleListener(LifecycleListener listener) {
  811   
  812           lifecycle.removeLifecycleListener(listener);
  813   
  814       }
  815   
  816   
  817       /**
  818        * Prepare for the beginning of active use of the public methods of this
  819        * component.  This method should be called after <code>configure()</code>,
  820        * and before any of the public methods of the component are utilized.
  821        *
  822        * @exception LifecycleException if this component detects a fatal error
  823        *  that prevents this component from being used
  824        */
  825       public void start() throws LifecycleException {
  826   
  827           // Validate and update our current component state
  828           if (started)
  829               throw new LifecycleException
  830                   (sm.getString("authenticator.alreadyStarted"));
  831           lifecycle.fireLifecycleEvent(START_EVENT, null);
  832           started = true;
  833   
  834           // Look up the SingleSignOn implementation in our request processing
  835           // path, if there is one
  836           Container parent = context.getParent();
  837           while ((sso == null) && (parent != null)) {
  838               if (!(parent instanceof Pipeline)) {
  839                   parent = parent.getParent();
  840                   continue;
  841               }
  842               Valve valves[] = ((Pipeline) parent).getValves();
  843               for (int i = 0; i < valves.length; i++) {
  844                   if (valves[i] instanceof SingleSignOn) {
  845                       sso = (SingleSignOn) valves[i];
  846                       break;
  847                   }
  848               }
  849               if (sso == null)
  850                   parent = parent.getParent();
  851           }
  852           if (log.isDebugEnabled()) {
  853               if (sso != null)
  854                   log.debug("Found SingleSignOn Valve at " + sso);
  855               else
  856                   log.debug("No SingleSignOn Valve is present");
  857           }
  858   
  859       }
  860   
  861   
  862       /**
  863        * Gracefully terminate the active use of the public methods of this
  864        * component.  This method should be the last one called on a given
  865        * instance of this component.
  866        *
  867        * @exception LifecycleException if this component detects a fatal error
  868        *  that needs to be reported
  869        */
  870       public void stop() throws LifecycleException {
  871   
  872           // Validate and update our current component state
  873           if (!started)
  874               throw new LifecycleException
  875                   (sm.getString("authenticator.notStarted"));
  876           lifecycle.fireLifecycleEvent(STOP_EVENT, null);
  877           started = false;
  878   
  879           sso = null;
  880   
  881       }
  882   
  883   
  884   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » authenticator » [javadoc | source]