Save This Page
Home » cocoon-2.1.11-src » org.apache » cocoon » acting » [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   package org.apache.cocoon.acting;
   18   
   19   import org.apache.avalon.framework.configuration.Configuration;
   20   import org.apache.avalon.framework.parameters.Parameters;
   21   import org.apache.avalon.framework.thread.ThreadSafe;
   22   
   23   import org.apache.cocoon.Constants;
   24   import org.apache.cocoon.environment.ObjectModelHelper;
   25   import org.apache.cocoon.environment.Redirector;
   26   import org.apache.cocoon.environment.Request;
   27   import org.apache.cocoon.environment.Session;
   28   import org.apache.cocoon.environment.SourceResolver;
   29   import org.apache.commons.lang.BooleanUtils;
   30   
   31   import org.apache.xpath.XPathAPI;
   32   import org.apache.xpath.objects.XObject;
   33   import org.w3c.dom.Node;
   34   import org.xmldb.api.DatabaseManager;
   35   import org.xmldb.api.base.Collection;
   36   import org.xmldb.api.base.Database;
   37   import org.xmldb.api.base.ResourceIterator;
   38   import org.xmldb.api.base.ResourceSet;
   39   import org.xmldb.api.base.XMLDBException;
   40   import org.xmldb.api.modules.XMLResource;
   41   import org.xmldb.api.modules.XPathQueryService;
   42   
   43   import java.util.Collections;
   44   import java.util.HashMap;
   45   import java.util.Map;
   46   
   47   /**
   48    * This action is used to authenticate user by comparing several request
   49    * fields (username, password) with the values in a DBXML compliant database.
   50    * The description of the process is given via external xml description file
   51    * simiar to the one used for all actions derived from AbstractDatabaseAction.
   52    *
   53    * <pre>
   54    * <root>
   55    *   <connection>
   56    *     <driver>org.apache.xindice.client.xmldb.DatabaseImpl</driver>
   57    *     <base>xmldb:xindice:///db/beta</base>
   58    *   </connection>
   59    *
   60    *   <root name="users">
   61    *      <select element="username" request-param="username" to-session="username"/>
   62    *      <select element="password" request-param="password" nullable="yes"/>
   63    *
   64    *      <select element="role" to-session="role" type="string"/>
   65    *      <select element="skin" to-session="skin" type="string"/>
   66    *   </root>
   67    * </root>
   68    * </pre>
   69    *
   70    * The values specified via "request-param" describe the name of HTTP request
   71    * parameter, "element" indicates matching document node, "nullable" means
   72    * that request-param which is null or empty will not be included in the WHERE
   73    * clause. This way you can enable accounts with empty passwords, etc.
   74    * "to-session" attribute indicates under which name the value obtained from
   75    * database should be stored in the session. Of course new session is created
   76    * when authorization is successfull. The "type" attribute can be either
   77    * string, long or double and alters the type of object stored in session.
   78    * Additionally all parameters that are
   79    * propagated to the session are made available to the sitemap via {name}
   80    * expression.
   81    *
   82    * If there is no need to touch the session object, providing just one-time
   83    * verification, you can specify action parameter "create-session" to "no" or
   84    * "false". No values are then propagated to the sesion and session object is
   85    * not verified.
   86    *
   87    * @author <a href="mailto:czoffoli@littlepenguin.org">Christian Zoffoli</a>
   88    * @author <a href="mailto:Martin.Man@seznam.cz">Martin Man</a>
   89    * @since 2002/02/03
   90    * @version $Id: DbXMLAuthenticatorAction.java 433543 2006-08-22 06:22:54Z crossley $
   91    *
   92    * based on DatabaseAuthenticatorAction created by Martin Man <Martin.Man@seznam.cz>
   93    */
   94   public class DbXMLAuthenticatorAction extends AbstractDatabaseAction implements ThreadSafe
   95   {
   96   
   97     /**
   98     * Main invocation routine.
   99     */
  100     public Map act (Redirector redirector, SourceResolver resolver, Map objectModel, String src,
  101           Parameters parameters) throws Exception {
  102   
  103       ResourceSet rs = null;
  104   
  105       // read global parameter settings
  106       boolean reloadable = Constants.DESCRIPTOR_RELOADABLE_DEFAULT;
  107   
  108       if (this.settings.containsKey("reloadable")) {
  109           reloadable = Boolean.valueOf((String) this.settings.get("reloadable")).booleanValue();
  110       }
  111   
  112       // read local settings
  113       try {
  114           Configuration conf = this.getConfiguration (
  115             parameters.getParameter ("descriptor", (String) this.settings.get("descriptor")),
  116             resolver,
  117             parameters.getParameterAsBoolean("reloadable",
  118             reloadable));
  119   
  120   
  121           boolean cs = true;
  122           String create_session = parameters.getParameter ("create-session", (String) this.settings.get("create-session"));
  123   
  124           if (create_session != null && ("no".equals (create_session.trim ()) || "false".equals (create_session.trim ()))) {
  125             cs = false;
  126           }
  127   
  128           Request req = ObjectModelHelper.getRequest(objectModel);
  129   
  130           /* check request validity */
  131           if (req == null) {
  132             getLogger ().debug ("DBXMLAUTH: no request object");
  133             return null;
  134           }
  135   
  136           rs = this.Authenticate( conf, req );
  137   
  138           if (rs != null )
  139           {
  140             getLogger ().debug ("DBXMLAUTH: authorized successfully");
  141             Session session = null;
  142   
  143             if (cs) {
  144               session = req.getSession (false);
  145               if (session != null)
  146                   session.invalidate ();
  147               session = req.getSession (true);
  148               if (session == null)
  149                   return null;
  150               getLogger ().debug ("DBXMLAUTH: session created");
  151             } else {
  152               getLogger ().debug ("DBXMLAUTH: leaving session untouched");
  153             }
  154   
  155             HashMap actionMap = this.propagateParameters (conf, rs, session);
  156             return Collections.unmodifiableMap (actionMap);
  157           } else {
  158             //getLogger ().debug ("DBXMLAUTH: error ResourceSet is null");
  159           }
  160   
  161           req.setAttribute("message", "The username or password were incorrect, please check your CAPS LOCK key and try again.");
  162           getLogger ().debug ("DBXMLAUTH: no results for query");
  163   
  164       } catch (Exception e) {
  165   
  166           getLogger().debug ("exception: ", e);
  167           return null;
  168       }
  169   
  170       return null;
  171     }
  172   
  173   
  174     private String getAuthQuery ( Configuration conf, Request req )
  175     {
  176   
  177       StringBuffer queryBuffer = new StringBuffer ("//");
  178       StringBuffer queryBufferEnd = new StringBuffer ("");
  179   
  180       String dbcol, request_param, request_value, nullstr;
  181       boolean nullable = false;
  182   
  183       Configuration table = conf.getChild ("root");
  184       Configuration[] select = table.getChildren ("select");
  185   
  186       try {
  187   
  188           queryBuffer.append (table.getAttribute ("name"));
  189   
  190           for (int i = 0; i < select.length; i ++)
  191           {
  192   
  193             dbcol = "[" + select[i].getAttribute ("element");
  194   
  195             try {
  196               request_param = select[i].getAttribute ("request-param");
  197               if (request_param == null ||
  198                     request_param.trim().equals ("")) {
  199                   continue;
  200               }
  201             } catch (Exception e) {
  202               continue;
  203             }
  204   
  205             try {
  206               nullstr = select[i].getAttribute ("nullable");
  207   
  208               if (nullstr != null) nullstr = nullstr.trim ();
  209   
  210               if (BooleanUtils.toBoolean(nullstr)) {
  211                   nullable = true;
  212               }
  213   
  214             } catch (Exception e1) {
  215             }
  216   
  217             /* if there is a request parameter name,
  218             * but not the value, we exit immediately do
  219             * that authorization fails authomatically */
  220             request_value = req.getParameter (request_param);
  221   
  222             if (request_value == null || request_value.trim().equals ("")) {
  223               // value is null
  224               if (!nullable) {
  225                   getLogger ().debug ("DBXMLAUTH: request-param " + request_param + " does not exist");
  226                   return null;
  227               }
  228             } else {
  229               queryBufferEnd.append (dbcol).append("='").append(request_value).append("']");
  230             }
  231           }
  232   
  233           if (!queryBufferEnd.toString ().trim ().equals (""))
  234             queryBuffer.append (queryBufferEnd);
  235   
  236           return queryBuffer.toString ();
  237       } catch (Exception e) {
  238           getLogger ().debug ("DBXMLAUTH: got exception: " + e);
  239           return null;
  240       }
  241     }
  242   
  243   
  244     private ResourceSet Authenticate( Configuration conf, Request req) throws Exception, XMLDBException {
  245   
  246        ResourceSet rs = null;
  247   
  248       String query = this.getAuthQuery (conf, req);
  249       if (query == null) {
  250         getLogger ().debug ("DBXMLAUTH: have not got query");
  251         req.setAttribute("message", "The authenticator is misconfigured");
  252         return null;
  253       }
  254       getLogger ().debug ("DBXMLAUTH: query is: " + query);
  255   
  256   
  257       Collection col = CreateConnection(conf);
  258   
  259       if (col != null) {
  260         if (col.isOpen()) {
  261           try {
  262             XPathQueryService service = (XPathQueryService) col.getService("XPathQueryService", "1.0");
  263   
  264             rs = service.query(query);
  265             ResourceIterator results = rs.getIterator();
  266   
  267             if (results.hasMoreResources() == false) {
  268                 getLogger ().debug ("DBXMLAUTH: auth failed");
  269                 return null;
  270             } else {
  271               getLogger ().debug ("DBXMLAUTH: auth OK");
  272               return rs;
  273             }
  274           } catch (XMLDBException e) {
  275             getLogger ().debug ("DBXMLAUTH: got exception: " + e);
  276             return null;
  277           } finally {
  278             // close col
  279             try {
  280               col.close();
  281             } catch (Exception e) { /* ignore */ }
  282             getLogger ().debug ("DBXMLAUTH: collection closed");
  283   
  284           }
  285   
  286         } else {
  287           getLogger ().debug ("DBXMLAUTH: error: collection closed !!");
  288         }
  289   
  290       } else {
  291         getLogger ().debug ("DBXMLAUTH: couldn't open a connection with DB");
  292   
  293       }
  294   
  295       return null;
  296     }
  297   
  298   
  299     private Collection CreateConnection( Configuration conf ) throws Exception, XMLDBException {
  300   
  301       Collection col = null;
  302   
  303       Configuration conn = conf.getChild ("connection");
  304   
  305       try {
  306   
  307         Class c = Class.forName( conn.getChild("driver").getValue() );
  308   
  309         Database database = (Database) c.newInstance();
  310         DatabaseManager.registerDatabase(database);
  311   
  312         col = DatabaseManager.getCollection( conn.getChild("base").getValue() );
  313   
  314       } catch (XMLDBException e) {
  315         getLogger ().debug ("DBXMLAUTH: Exception occured " + e.errorCode);
  316       }
  317   
  318       return col;
  319     }
  320   
  321     private HashMap propagateParameters (Configuration conf,  ResourceSet resultSet, Session session) {
  322   
  323         Configuration table = conf.getChild ("root");
  324         Configuration[] select = table.getChildren ("select");
  325         String session_param, type;
  326         HashMap map = new HashMap();
  327   
  328         XObject xo;
  329         Node originalnode = null;
  330   
  331         try {
  332   
  333           ResourceIterator results = resultSet.getIterator();
  334   
  335           // Create an XObject to be used in Xpath query
  336           xo = new XObject();
  337   
  338           // Retrieve the next node
  339           XMLResource resource = (XMLResource) results.nextResource();
  340   
  341           originalnode = resource.getContentAsDOM();
  342   
  343         }
  344         catch (Exception e) {
  345           getLogger ().debug ("DBXMLAUTH: error creating XObject ");
  346         }
  347   
  348   
  349         try {
  350             for (int i = 0; i < select.length; i ++) {
  351               try {
  352                 session_param = select[i].getAttribute ("to-session");
  353                 if (session_param != null && !session_param.trim().equals (""))
  354                 {
  355   
  356                     String s = "";
  357   
  358                     try {
  359                       // Use Xalan xpath parser to extract data
  360                       xo = XPathAPI.eval(originalnode, "/" + table.getAttribute ("name") + "/" + select[i].getAttribute ("element") );
  361                       s = xo.toString();
  362                     }
  363                     catch (Exception e) {
  364                     }
  365   
  366                     /* propagate to session */
  367                     try {
  368                       type = select[i].getAttribute ("type");
  369                     } catch (Exception e) {
  370                       type = null;
  371                     }
  372   
  373                     if (type == null || "".equals (type.trim ())) {
  374                       type = "string";
  375                     }
  376                     Object o = null;
  377   
  378                     if ("string".equals (type)) {
  379                       o = s;
  380                     } else if ("long".equals (type)) {
  381                       Long l = Long.decode (s);
  382                       o = l;
  383                     } else if ("double".equals (type)) {
  384                       Double d = Double.valueOf (s);
  385                       o = d;
  386                     }
  387   
  388                     if (session != null) {
  389                       session.setAttribute (session_param, o);
  390                       getLogger ().debug ("DBXMLAUTH: propagating param " + session_param + "=" + s);
  391                     }
  392                     map.put (session_param, o);
  393                 }
  394               } catch (Exception e) {
  395               }
  396             }
  397             return map;
  398         } catch (Exception e) {
  399             getLogger().debug("exception: ", e);
  400         }
  401         return null;
  402       }
  403   }

Save This Page
Home » cocoon-2.1.11-src » org.apache » cocoon » acting » [javadoc | source]