/*
 * @(#)ReleasePageResourcesTag.java
 *
 * Copyright 2000-2002 by Oracle Corporation,
 * 500 Oracle Parkway, Redwood Shores, California, 94065, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Oracle Corporation.
 */

package oracle.jbo.html.jsp.datatags;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;
import javax.servlet.http.HttpServletResponse;

import oracle.jbo.JboException;
import oracle.jbo.common.PropertyMetadata;
import oracle.jbo.common.ampool.SessionCookie;
import oracle.jbo.html.HtmlServices;
import oracle.jbo.http.HttpContainer;

/**
 * A custom data tag that may be used to clear the JBO HTTP page cache.
 */
public class ReleasePageResourcesTag extends TagSupport
{
   private String mReleaseMode = null;
   private String applicationId = null;

   public String getReleasemode()
   {
      return mReleaseMode;
   }

   public void setReleasemode(String releaseMode)
   {
      mReleaseMode = releaseMode;
   }

   public void setreleasemode(String releaseMode)
   {
      mReleaseMode = releaseMode;
   }

   public String getAppid()
   {
      return applicationId;
   }

   public void setAppid(String applicationId)
   {
      this.applicationId = applicationId;
   }

   /**
    * Perform clean up tasks related to the end of a page request.
    */
   public int doEndTag() throws JspException
   {
      HttpContainer container = HttpContainer.getInstanceFromSession(pageContext.getSession());

      if (getAppid() != null)
      {
         SessionCookie cookie = container.getSessionCookie(getAppid());
         if (cookie == null)
         {
            throw new JboException(Res.format(Res.COOKIE_NOT_FOUND, getAppid()));
         }
         releaseApplicationModule(cookie);
      }
      else
      {
         SessionCookie[] cookies = container.getSessionCookies();
         for (int i = 0; i < cookies.length; i++)
         {
            if (cookies[i].isApplicationModuleReserved())
            {
               releaseApplicationModule(cookies[i]);
            }
         }
      }

      HtmlServices.releaseRequestParameters(pageContext);
      
      return SKIP_BODY;
   }

   private void releaseApplicationModule(SessionCookie cookie)
   {
      synchronized(cookie.getSyncLock())
      {
         if (cookie.getThreadRefCount() > 1)
         {
            // I know this looks weird.  But, basically if more than one
            // thread currently has exclusive ApplicationModule acces then
            // just release the potential lock.  Do not checkin the AM, and
            // do not failover.  In other words, this will leave the AM
            // alone. See bug 2410895.
            cookie.releaseApplicationModule(
               SessionCookie.UNSHARED, SessionCookie.STATE_UNMANAGED);
         }
         else
         {
            String releaseMode = (String)cookie.getUserData().remove(
               PropertyMetadata.AM_RELEASE_MODE.pName);

            // This is necessary to retain backwards compatibility
            if (releaseMode == null || releaseMode.length() <= 0)
            {
               releaseMode = mReleaseMode;
            }

            Utils.releaseApplicationModule(
               pageContext.getServletContext()
               , (HttpServletResponse) pageContext.getResponse()
               , cookie
               , releaseMode);
         }
      }
   }

   public void release()
   {
      super.release();

      mReleaseMode = null;
      applicationId = null;
   }
}

