taylor      01/07/29 21:51:25

  Added:       src/java/org/apache/jetspeed/services/psmlmanager
                        DatabasePsmlManagerService.java
  Log:
  - added DatabasePsmlManagerService.java Database-based PsmlManager implementation - 
from Atul Dambalkar, Anil Shinde, and Narendra Vaidya
  
  Revision  Changes    Path
  1.1                  
jakarta-jetspeed/src/java/org/apache/jetspeed/services/psmlmanager/DatabasePsmlManagerService.java
  
  Index: DatabasePsmlManagerService.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
   
  package org.apache.jetspeed.services.psmlmanager;
  
  // PSML Manager Service interface
  import org.apache.jetspeed.services.psmlmanager.PsmlManagerService;
  
  // Profile and ProfileLocator interface 
  import org.apache.jetspeed.om.profile.Profile;
  import org.apache.jetspeed.om.profile.ProfileLocator;
  import org.apache.jetspeed.om.profile.QueryLocator;
  //Castor defined API
  import org.apache.jetspeed.xml.api.portletmarkup.Portlets;
  import org.apache.jetspeed.om.profile.PSMLDocument;
  import org.apache.jetspeed.om.profile.BasePSMLDocument;
   
  //turbine stuff
  import org.apache.turbine.util.Log;
  import org.apache.turbine.services.TurbineBaseService;
  import org.apache.turbine.services.InitializationException;
  import org.apache.turbine.services.TurbineServices;
  import org.apache.turbine.services.resources.ResourceService;
  import org.apache.turbine.om.security.User;
  import org.apache.turbine.om.security.Group;
  import org.apache.turbine.om.security.Role;
  import org.apache.turbine.util.db.pool.DBConnection;
  import org.apache.turbine.services.db.TurbineDB; 
  
  //Servlet API
  import javax.servlet.ServletConfig;
   
  //castor support
  import org.exolab.castor.xml.MarshalException;
  import org.exolab.castor.xml.ValidationException;
  
  //standard java stuff
  import java.lang.Thread;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.StringWriter;
  import java.io.ByteArrayInputStream;
  import java.util.Iterator;
  import java.util.List;
  import java.util.ArrayList;
  import java.util.Map;
  import java.util.Set;
  import java.util.WeakHashMap;
  import java.sql.Connection;
  import java.sql.ResultSet;
  import java.sql.Statement;
  import java.sql.PreparedStatement;
  import java.sql.SQLException;
  import java.io.IOException;
  
  
  /**
   * This service is responsible for loading and saving PSML documents. It uses
   * database to persist the PSML documents.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Anil Shinde</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Narendra Vaidya</a>
   * @version 
   */
  public class DatabasePsmlManagerService extends TurbineBaseService 
                                       implements PsmlManagerService
  {
  
      private Map psmlCache = new WeakHashMap();
  
      /** The watcher for the document locations */
      private CacheRefresher refresher = null;
   
      /** the base refresh rate for documents */
      private long refreshRate;  // default will be 8 hours
  
      /** Anonymous user name */
      private String userName;  // default will be "anonymous" 
  
      private final static String REFRESH_RATE = "refresh-rate";
      private final static String USER_NAME = ".user.name";
      private final static long DEFAULT_REFRESH_RATE = 60 * 60 * 8 * 1000; //8hrs
  
      private final static String DEFAULT_USER_NAME = "anonymous";
  
      private final static String JETSPEED_USER_PROFILE = "jetspeed_user_profile";
      private final static String JETSPEED_GROUP_PROFILE = "jetspeed_group_profile";
      private final static String JETSPEED_ROLE_PROFILE = "jetspeed_role_profile";
      private final static String JETSPEED_USER_PROFILE_SEQ = 
"jetspeed_user_profile_seq";
      private final static String JETSPEED_GROUP_PROFILE_SEQ = 
"jetspeed_group_profile_seq"; 
      private final static String JETSPEED_ROLE_PROFILE_SEQ = 
"jetspeed_role_profile_seq"; 
  
   
      /**
       * This is the early initialization method called by the
       * Turbine <code>Service</code> framework
       */
      public void init( ServletConfig conf ) throws InitializationException 
      {
          Log.note("Initializing DatabasePsmlManagerService...");
          initConfiguration();
  
          //Mark that we are done
          setInit(true);
          Log.note("Done initializing DatabasePsmlManagerService.");
      }
  
      /**
       * Loads the configuration parameters for this service from the
       * JetspeedResources.properties file.
       *
       * @exception throws a <code>InitializationException</code> if the service
       * fails to initialize
       */
      private void initConfiguration() throws InitializationException
      {
          ResourceService serviceConf =
                        ((TurbineServices)TurbineServices.getInstance())
                                .getResources(PsmlManagerService.SERVICE_NAME);
          try
          {
              // get configuration parameters from Turbine Resources
              refreshRate = 
                        serviceConf.getLong(REFRESH_RATE, DEFAULT_REFRESH_RATE);
              userName = serviceConf.getString(USER_NAME, DEFAULT_USER_NAME);
          }
          catch (Throwable t)
          {
              throw new InitializationException( "Missing default refresh rate 
parameter, during initializing DatabasePsmlManagerService, using defaults");
          }
   
          this.refresher = new CacheRefresher();
          refresher.start();
      }
  
      /** Late init method from Turbine Service model */
      public void init( ) throws InitializationException
      {
          while( !getInit() )
          {
              //Not yet...
              try
              {
                  Thread.sleep( 500 );
              }
              catch (InterruptedException ie )
              {
                  Log.error( ie );
              }
          }
      }
   
      /**
       * A thread implementation of cache refreshing mechanism for database
       * persisted PSMLs. We have to refresh the cache after specific intervals 
       * if someone manually updates the PSML database.
       *
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */ 
      class CacheRefresher extends Thread
      {
          private boolean done = false;
             
          /**
           * Constructor to to set the priority.
           */ 
          CacheRefresher()
          {
              setDaemon(true);
              setPriority(Thread.MIN_PRIORITY+1);
          }
  
          /**
           * We are all done, system is shutting down.
           */ 
          void setDone(boolean done)
          {
              this.done = done;
          }
  
          /**
           * Method as needed for a Thread to run
           */ 
          public void run()
          {
              try
              {
                  while ( !done )
                  {
                      Log.note("Cache Refresher thread working now!");
                      try
                      {
                          synchronized (this)
                          {
                              Iterator i = psmlCache.keySet().iterator();
                 
                              while(i.hasNext())
                              {
                                  ProfileLocator locator = 
                                                     (ProfileLocator)i.next();
   
                                  // do refresh for the locator
                                  PSMLDocument doc = refresh(locator); 
  
                                  // over write the existing document in cache
                                  psmlCache.put(locator, doc);
                              }
                          }
                      }
                      catch (Exception e)
                      {
                          Log.error("CacheRefresher: Error in iteration...", e);
                      }
                      Log.note("Cache Refresher thread sleeping now!");
                      sleep (refreshRate);
                      Log.note("Cache Refresher thread woke up!");
                  }
              }
              catch (InterruptedException e)
              {
                  Log.note("CacheRefresher: recieved interruption, aborting.");
              }
          }     
      }
  
      public boolean saveDocument(PSMLDocument doc) 
      {
          // do nothing
          return false;
      }
  
      public PSMLDocument getDocument( String name )
      {
          // do mothing, deprecated
          return null;
      }
  
      public boolean saveDocument(String fileOrUrl, PSMLDocument doc)
      {
          // do mothing, deprecated
          return false;
      }
  
  
      /**
       * Returns a PSML document for the given locator
       *
       * @param locator The locator descriptor(ProfileLocator object) of the 
       * document to be retrieved.
       * @return psmldoc The PSMLDocument object
       * @author <a href="mailto:[EMAIL PROTECTED]";>Anil Shinde</a>
       */
      public PSMLDocument getDocument( ProfileLocator locator ) 
      {
          // check the cache for the req'e document if not available in cache
          // query the database for Portlets for the given locator
          // use unmarsheller to create  Portlets object, get PSMLDocument
          // object for it, update the cache so that next time when user logs in 
          // use cached PSMLDocument
  
          if (locator == null)
          {
              String message = "PSMLManager: Must specify a locator";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          PSMLDocument psmldoc = null;
  
          synchronized (psmlCache)
          {
              psmldoc = (PSMLDocument)psmlCache.get(locator);
          }
  
          if (psmldoc != null)
          {
              return psmldoc;
          }
  
          DBConnection dbConn = null;
          Statement stmt = null;
   
          try
          {
              dbConn = TurbineDB.getConnection();
  
              stmt = dbConn.createStatement();
              ResultSet rset = stmt.executeQuery (getQueryString(locator));
  
              while ( rset.next() )
              {
                  String page = rset.getString("page");
                  Portlets portlets = getPortlets(rset.getBinaryStream("profile"));
                  psmldoc = getPSMLDocument(page, portlets);
  
                  synchronized (psmlCache)
                  {
                      psmlCache.put(locator, psmldoc);
                  }
                  return psmldoc;
              }
  
          }
          catch (Exception e)
          {
              //From obtaining the connection or from your application code.
              Log.error("Unable to get a psml document from the database.", e);
          }
          finally
          {
              try
              {
                   if (stmt != null) 
                   {
                       stmt.close();
                       stmt = null;
                   } 
                   TurbineDB.releaseConnection(dbConn);
              }
              catch (Exception e)
              {
                   // Error releasing database connection back to pool.
                   Log.error("Release of connection failed.", e);
              }
          }
          return null;
      }
  
      /**
       * Stores the PSML document in DB for the given profile
       *
       * @param profile The profile that holds the PSMLDocument.
       * @return PSMLDocument The PSMLDocument that got created in DB.
       * @author <a href="mailto:[EMAIL PROTECTED]";>Narendra Vaidya</a>
       */
      public PSMLDocument createDocument( Profile profile ) 
      {
          // create record in the database for Portlets for the given 
          // profile/PSMLDocuemnt,use marsheller to create Portlets 
          // object and then put it in database, update the cache
  
          if (profile == null)
          {
              String message = "PSMLManager: Must specify a profile";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          PortletInputStream  portletInputStream = getPortletInputStream( 
profile.getDocument().getPortlets() );
  
          String tableName=null;
          String seqName=null;
          String name=null;
          if ( profile.getUser() != null )
          {
              tableName = JETSPEED_USER_PROFILE;
              name = profile.getUser().getUserName();
              seqName = JETSPEED_USER_PROFILE_SEQ + ".nextval";
          }
          else if ( profile.getGroup() != null )
          {
              tableName = JETSPEED_GROUP_PROFILE;
              name = profile.getGroup().getName();
              seqName = JETSPEED_GROUP_PROFILE_SEQ + ".nextval";
          }   
          else
          {
              tableName = JETSPEED_ROLE_PROFILE;
              name = profile.getRole().getName();
              seqName = JETSPEED_ROLE_PROFILE_SEQ + ".nextval";
          }   
  
          Log.note("Login Name: " + name);
   
          DBConnection dbConn = null;
          PreparedStatement pStatement = null;
          try
          {
              dbConn = TurbineDB.getConnection();
   
              String sqlString = "INSERT INTO " + tableName + " VALUES " +
                                 "(" +  seqName + ", ? , ? , ? , ? , ? , ?)";
   
              pStatement = dbConn.prepareStatement( sqlString );
   
              pStatement.setString(1, name);
              pStatement.setString(2, profile.getMediaType() );
              pStatement.setString(3, profile.getLanguage() );
              pStatement.setString(4, profile.getCountry() );
              pStatement.setString(5, profile.getName() );
  
              Log.error("SQL String for creating document " + pStatement);
              pStatement.setBinaryStream(6, portletInputStream , 
portletInputStream.length()  );
   
              if ( pStatement.executeUpdate() != 1 )
              {
                  // insert falied
                  Log.error("Insert in table " + tableName + " failed");
                  throw new RuntimeException( "Could not create new document in DB" );
              }
              else
              {
                  // insert successful
                  synchronized (psmlCache)
                  {
                      psmlCache.put( profile, profile.getDocument() );
                  }
              }
              return profile.getDocument();
          }
          catch (Exception e)
          {
              Log.error("Error occurred in Database PSML Manager: " + e);
          }
          finally
          {
              try
              {
                  if (pStatement != null)
                  {
                      pStatement.close() ;
                  }
                  TurbineDB.releaseConnection(dbConn);
                  if (portletInputStream != null )
                  {
                      portletInputStream.close();
                  }
              }
              catch (IOException e)
              {
                  Log.error("Error occurred while closing Input stream: " + e);
              }
              catch (Exception e)
              {
                  Log.error("Error occurred while releasing the connection: " + e);
              }
          }
          return null;  // shouldn't be here
      }
  
      /** 
       * Remove the PSMLDocument/profile for given locator object.
       * 
       * @param locator The profile locator criteria for profile to be removed.
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      public void removeDocument( ProfileLocator locator )
      {
          if (locator == null)
          {
              String message = "PSMLManager: Must specify a locator";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          DBConnection conn = null;   
          Statement stmt = null;
          String delete = getDeleteString(locator);
   
          try 
          {  
              conn = TurbineDB.getConnection();   
              conn.setAutoCommit(false);
              stmt = conn.createStatement();
   
              Log.note ("SQL Executing: " + delete);
              int rs = stmt.executeUpdate(delete);
              Log.note ("Number of rows deleted: " + rs);
          } 
          catch (Exception e)
          {
              Log.error("Error occurred in Database PSML Manager: " + e);
          }
          finally 
          {
              try
              {
                  // commit the delete
                  conn.commit();
  
                  // update the cache.
                  removeFromCache(locator);
  
                  if (stmt != null)
                  {
                      stmt.close();  // underlying ResultSet will also be closed
                      stmt = null;
                  }
                  TurbineDB.releaseConnection(conn);
              }
              catch (Exception e)
              {
                  Log.error("Error occurred while releasing the connection: "
                            + e);
              }
          }
      }
  
      /**
       * Prepare SQL delete string depending upon ProfileLocator object contents.
       *
       * @param locator The profile locator criteria.
       * @return SQL Delete String object for given locator object.
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      private String getDeleteString(ProfileLocator locator)
      {
          QueryHelper qhelper = new QueryHelper(locator);
         
          String mediaType  = qhelper.getMediaType();
          String language = qhelper.getLanguage();
          String country = qhelper.getCountry();
          String page = qhelper.getPage();
          String name = qhelper.getName(); 
          String column = qhelper.getColumn(); 
          String table = qhelper.getTable(); 
   
          if (name == null)
          {
              String message = "PSMLManager: Must specify a name to delete 
PSMLDocument";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          String whereClause = "";
  
          if (!name.equals("*")) 
          {
               whereClause = " where "
                   + column + " = '" + name + "' "
                   + ((page != null && page.length() > 0)?
                             " and page = '" + page + "' ":
                             ""
                     )
                   + ((mediaType != null && mediaType.length() > 0)?
                             " and media_type = '" + mediaType + "' ":
                             ""
                     )
                   + ((language != null && language.length() > 0)?
                             " and language = '" + language + "' ":
                             ""
                     )
                   + ((country != null && country.length() > 0)?
                             " and country = '" + country + "' ":
                             ""
                     );
          }
   
          return "delete from "
               + table
               + whereClause;
      }
  
       /**
       * Class to help creating the query string from the ProfileLocator object.
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      class QueryHelper 
      {
          private String mediaType;
          private String language;
          private String country;
          private String page;
          private String name;
          private String column;
          private String table; 
          
          QueryHelper(ProfileLocator locator)
          {
              mediaType = locator.getMediaType();
              language = locator.getLanguage();
              country = locator.getCountry();
              page = locator.getName();
              User user = locator.getUser();
              Group group = locator.getGroup();
              Role role = locator.getRole();
  
              if (user != null)
              {
                  table = JETSPEED_USER_PROFILE;
                  name = user.getUserName();
                  column = "login_name";
              } 
              else if (group != null)
              {
                  table = JETSPEED_GROUP_PROFILE;
                  name = group.getName();
                  column = "group_name";
              }
              else if (role != null)
              {
                  table = JETSPEED_ROLE_PROFILE;
                  name = role.getName();
                  column = "role_name";
              } 
              else // it's a anonymous access
              {
                  table = JETSPEED_USER_PROFILE;
                  name = userName;   // "anonymous" user name
                  column = "login_name";
              } 
          }
  
          String getMediaType() 
          {
              return mediaType;
          }
  
          String getLanguage() 
          {
              return language;
          }
  
          String getCountry() 
          {
              return country;
          }
  
          String getPage() 
          {
              return page;
          }
  
          String getName() 
          {
              return name;
          }
  
          String getTable() 
          {
              return table;
          }
  
          String getColumn() 
          {
              return column;
          }
      }
  
      /**
       * Remove PSMLDocuments from the cache matching locator object. If locator
       * object contains name as "*", we need to remove all those PSMLDocuments
       * from cache.
       */
      private void removeFromCache(ProfileLocator locator)
      {
          QueryHelper qhelper = new QueryHelper(locator);
  
          String name = qhelper.getName();
          String table = qhelper.getTable();
  
          if (name == null)
          {
              String message = "PSMLManager: Must specify a name to delete 
PSMLDocument";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          if (!name.equals("*")) 
          {
              synchronized (psmlCache)
              {
                  psmlCache.remove(locator);
              }
              return; 
          }
  
          // else, remove all the psml documents for the entire user/group/role
          // table
          synchronized (psmlCache)
          {
              Set keyset = psmlCache.keySet();
              Iterator iterator = keyset.iterator();
              while (iterator.hasNext())
              {
                  locator = (ProfileLocator)iterator.next();
                  if (
                      ((table.equals(JETSPEED_USER_PROFILE) 
                        && locator.getUser() != null))
                     || 
                      ((table.equals(JETSPEED_GROUP_PROFILE) 
                        && locator.getGroup() != null))
                     || 
                      ((table.equals(JETSPEED_ROLE_PROFILE)
                        && locator.getRole() != null))
                     )
                  {
                      psmlCache.remove(locator);
                  }
              }
          }
      }
  
      /** 
       * Query for a collection of profiles given a profile locator criteria.
       * Use SQL engine to get the required profiles.
       * 
       * @param locator The profile locator criteria.
       * @return Iterator object with the PSMLDocuments satisfying query
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      public Iterator query( QueryLocator locator )
      {
          if (locator == null)
          {
              String message = "PSMLManager: Must specify a locator";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          DBConnection conn = null;   
          Statement stmt = null;
          String query = getQueryString(locator);
  
          try 
          {
              conn = TurbineDB.getConnection();   
              stmt = conn.createStatement();
  
              List list = new ArrayList();
              Log.note ("SQL Executing: " + query);
              ResultSet rs = stmt.executeQuery(query);
              while (rs.next())
              {
                  String page = rs.getString("page");
                  Portlets portlets = getPortlets(rs.getBinaryStream("profile"));
                  list.add(getPSMLDocument(page, portlets));
              }
              return list.iterator();
          } 
          catch (Exception e)
          {
              Log.error("Error occurred in Database PSML Manager: " + e);
          }
          finally 
          {
              try 
              {
                  if (stmt != null)
                  {
                      stmt.close();  // underlying ResultSet will be also closed
                      stmt = null;
                  }
                  TurbineDB.releaseConnection(conn);
              }
              catch (Exception e) 
              {
                  Log.error("Error occurred while releasing the connection: " 
                            + e);
              }
          }
          return new ArrayList().iterator();  // return empty non-null iterator
      } 
  
    
      /**
       * Get PSMLDocument object for given pagename and portlets.
       *
       * @param portlets Portlets for the given page name
       * @param page page name for this resource
       * @return PSMLDocument object for given page and portlets 
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */ 
      private PSMLDocument getPSMLDocument(String page, Portlets portlets)
      {
          PSMLDocument psmldoc = new BasePSMLDocument();
          psmldoc.setName(page);
          psmldoc.setPortlets(portlets);
          return psmldoc;
      }  
  
      /**
       * Prepare SQL query string depending upon ProfileLocator object contents.
       *
       * @param locator The profile locator criteria.
       * @return Select query String object for given locator object. 
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      private String getQueryString(ProfileLocator locator)
      {
          QueryHelper qhelper = new QueryHelper(locator);
  
          String mediaType  = qhelper.getMediaType();
          String language = qhelper.getLanguage();
          String country = qhelper.getCountry();
          String page = qhelper.getPage();
          String name = qhelper.getName();
          String column = qhelper.getColumn();
          String table = qhelper.getTable();
  
          return "select page, profile from "
               + table 
               + " where "
               + column + " = '" + name + "' "
               + ((page != null && page.length() > 0)? 
                             " and page = '" + page + "' ": 
                             ""
                 )
               + ((mediaType != null && mediaType.length() > 0)? 
                             " and media_type = '" + mediaType + "' ": 
                             ""
                 )
               + ((language != null && language.length() > 0)? 
                             " and language = '" + language + "' ": 
                             ""
                 )
               + ((country != null && country.length() > 0)? 
                             " and country = '" + country + "' ": 
                             ""
                 );
      }
            
      /** 
       * Given ordered list of locators, find the first document matching
       * a profile locator, starting from the beginning of the list and working
       * to the end.
       *
       * @param locator The ordered list of profile locators.
       * @return PSMLDocument object for the first document matching a locator 
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      public PSMLDocument getDocument( List locators )
      {
          if (locators == null)
          {
              String message = "PSMLManager: Must specify a list of locators";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          // iterate over the list and invoke getDocument(locator) method
          for (int i = 0; i < locators.size(); i++) 
          {
              PSMLDocument psmldoc = getDocument((ProfileLocator)locators.get(i));
              if (psmldoc != null) 
              {
                  return psmldoc;
              }
          }
          // no document found for matching single locator, hypothetical
          return null;   
      }
  
      /**
       * Returns a PSML document for the given locator, it is called by the cache
       * refresher
       *   
       * @param locator The locator descriptor(ProfileLocator object) of the 
       * document to be retrieved.
       * @return psmldoc The PSMLDocument object
       * @author <a href="mailto:[EMAIL PROTECTED]";>Anil Shinde</a>
       */
      private PSMLDocument refresh( ProfileLocator locator )
      {
          // go to database and get the blob, and marshal the Portlets
  
          if (locator == null)
          {
              String message = "PSMLManager: Must specify a locator";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          DBConnection dbConn = null;
          Statement stmt = null;
  
          try
          {  
              dbConn = TurbineDB.getConnection();
  
              stmt = dbConn.createStatement();
              ResultSet rset = stmt.executeQuery(getQueryString(locator));
  
              while ( rset.next() )
              {
                  String page = rset.getString("page");
                  Portlets portlets = getPortlets(rset.getBinaryStream("profile"));
                  return getPSMLDocument(page, portlets);
              }
   
          }
          catch (Exception e)
          {
              // From obtaining the connection or from your application code.
              Log.error("Unable to get a psml document from the database.", e);
          }
          finally
          {
              try
              {
                   if (stmt != null) 
                   {
                       stmt.close();
                       stmt = null;
                   }
                   TurbineDB.releaseConnection(dbConn);
              }
              catch (Exception e)
              {
                   // Error releasing database connection back to pool.
                   Log.error("Release of connection failed.", e);
              }
          }
          return null;  // shouldn't be here
      }
  
      /** Deserialize a PSML structure read from the input stream using Castor
       *  XML unmarshaller
       *
       * @param in the input stream to load the PSML from
       * @return PSML structure Portlets object
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      private Portlets getPortlets(InputStream in) 
      {
          InputStreamReader reader = new InputStreamReader(in);
          try 
          {
              return Portlets.unmarshal(reader);
          }
          catch (MarshalException e)
          {
              Log.error("PSMLManager: Could not unmarshal the inputstream ", e);
          }  
          catch (ValidationException e)
          {
              Log.error("PSMLManager: document is not valid", e);
          }
          finally
          {
              try { reader.close(); } 
              catch (IOException e) { Log.error("", e); }
          }
          return null; // control shouldn't be here 
      }
  
      /** Serialize a PSML structure using string writer with Castor XML 
       * marshaller, put it in input stream and return it.
       *
       * @param portlets the structure to save
       * @param len integer object which contains the length for the PSML string 
       * @param PortletStream PortletStream object
       * @return PortletInputStream object
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      private PortletInputStream getPortletInputStream(Portlets portlets) 
      {
          if (portlets == null)
          {
              String message = "PSMLManager: Must specify portlets";
              Log.error( message );
              throw new IllegalArgumentException( message );
          }
  
          StringWriter writer = new StringWriter();
          try 
          {
              portlets.marshal(writer);
              return new PortletInputStream(writer.toString()); 
          }
          catch (MarshalException e)
          {
              Log.error("PSMLManager: Could not marshal the stringwriter ", e);
          }
          catch (ValidationException e)
          {
              Log.error("PSMLManager: document is not valid", e);
          }
          finally
          {
              try { writer.close(); } 
              catch (IOException e) { Log.error("", e); }
          }
          return null; // control shouldn't be here 
      }
  
      /**
       * Class to convert the marshalled PSML String object into InputStream 
       * @author <a href="mailto:[EMAIL PROTECTED]";>Atul Dambalkar</a>
       */
      class PortletInputStream extends ByteArrayInputStream
      {
          private int length;
  
          PortletInputStream(String psml)
          {
               /**** Platform's default character encoding will be used ****/
               super(psml.getBytes());
               this.length = psml.length();
          }
  
          public int length() 
          {
              return length;
          } 
      }
  
      /** Removes all documents for a given user.
       *
       * @param user The user object.
       */
      public void removeUserDocuments( User user )
      {
          // IMPLEMENT ME:
        }
  
      /** Removes all documents for a given role.
       *
       * @param role The role object.
       */
      public void removeRoleDocuments( Role role )
      {
          // IMPLEMENT ME:
        }
  
      /** Removes all documents for a given group.
       *
       * @param group The group object.
       */
      public void removeGroupDocuments( Group group )
        {
          // IMPLEMENT ME:
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to