/*  Copyright (c) 2000 by Oracle Corporation. All Rights Reserved. */

package oracle.portal.provider.v1.http;

import java.util.*;
import oracle.portal.provider.v1.*;
import oracle.portal.utils.xml.v1.XMLUtil;

/**
 * A portlet is implemented as a set of controllers: a renderer and optionally
 * a personalization manager and a security manager. The Portlet interface is a
 * container for these controllers as well as portlet meta-data. The
 * DefaultPortlet implements the Portlet interface. It is designed to work with
 * the DefaultProvider/provider.xml mechanism that allows you to describe the
 * characteristics of the portlet's controllers and meta-data using an XML
 * syntax rather then program them directly.<p>
 * 
 * The Portlet interface is a container interface; its function is to return
 * (pre)set values vs. perform computation. Because of this DefaultPortlet
 * should never need to be subclassed.<p>
 *
 * Portlets are encouraged to support multiple language versions of their
 * portlet meta-data. This is accomplished by storing the meta-data strings in
 * resource bundles and then registering the resource bundle with the Portlet
 * (in the provider.xml file this is specified within the
 * <code>&lt;resource></code> element of a <code>&lt;portlet></code> element).
 * The DefaultPortlet defines constants for the resource names it uses to
 * extract the meta-data from the resource file.
 */
public class DefaultPortlet implements PortletXtra3, MutablePortletXtra3
{

    private Provider mProvider;

    private String mName;
    private long mPortletId;
    private String mTitle;
    private String mShortTitle;
    private String mDescription;
    private Vector mInputParameters;
    private Vector mAcceptContentTypes;
    private int mTimeout;
    private String mTimeoutMessage;
    private int mMinEditAuthLevel = ProviderUser.USER_WEAK_AUTH;
    private boolean mShowEdit = false;
    private boolean mShowEditDefault = false;
    private boolean mShowPreview = false;
    private boolean mShowDetails = false;
    private boolean mHasHelp = false;
    private boolean mHasAbout = false;
    private boolean mShowLink = false;
    private boolean mCallIsRunnable = true;
    private boolean mCallGetPortlet = true;
    // default to an "empty" set of flags so always set.
    private MobileFlags mMobileFlags = new MobileFlags(MobileFlags.MOBILE_GENERIC);

    private PortletRenderer mRenderer;
    private PortletSecurityManager mSecurityMgr;
    private PortletPersonalizationManager mPersonalizationMgr;
    private PortletContainerRenderer mContainerRenderer;

    private String mResource;
    private ResourceBundle mBundle;
    private Locale mBundleLocale;

    private Locale mDefaultLocale;
    private Object mLock = new Object();

    /**
     * Null Constructor
     */
    public DefaultPortlet()
    {
        mAcceptContentTypes = new Vector(1);
        mAcceptContentTypes.addElement("text/html");
    }

    /**
     * Initializes the portlet. Portlets are instantiated by its provider via
     * its null constructor. Following instantiation, providers are expected to
     * call the portlet's <code>init()</code> method.
     *
     * @param p the provider that created this instance.
     */
    public void init(Provider p)
    {
        mProvider = p;
        mDefaultLocale = Locale.getDefault();
    }

    /* *********************************************************** */
    /*                                                             */
    /*                    Portlet methods                          */
    /*                                                             */
    /* *********************************************************** */

    /**
     * Gets the security manager for this portlet.  The security manager is
     * used to check whether a user is authorized to perform a specific action.
     * It is valid for a Portlet to not have a security manager.  I.e. this
     * method can return null.  If there is no security manager it is assumed
     * that all users have unrestricted access.
     */
    public PortletSecurityManager getSecurityManager()
    {
        return mSecurityMgr;
    }

    /**
     * Gets the personalization manager for this portlet.  The personalization
     * manager provides the interface between the renderer and the
     * personalization store that allows the renderer to get the user
     * customizations for this rendition.  It is valid for a Portlet to not
     * have a personalization manager.  I.e. this method can return null.
     */
    public PortletPersonalizationManager getPersonalizationManager()
    {
        return mPersonalizationMgr;
    }

    /**
     * Gets the renderer for this portlet.  The renderer is responsible for
     * emitting the visual aspects of the portlet (as markup).  All portlets
     * must have a renderer.
     */
    public PortletRenderer getRenderer()
    {
        return mRenderer;
    }

    /**
     * Gets the Provider that created this instance.
     *
     * @return the Provider that creatd this instance.
     */
    public Provider getProvider()
    {
        return mProvider;
    }

    /**
     * Gets this Portlet's default locale.  The default locale can be declared
     * in the provider.xml file: <defaultLocale>en.US</defaultLocale>.  The
     * Locale is specified using the standard ISO 2 letter language and country
     * codes.  If not specified in provider.xml (or code) the VMs default
     * locale is returned.
     */
    public Locale getDefaultLocale()
    {
        return mDefaultLocale;
    }

    /**
     * Gets the string resource (bundle) for this Portlet.
     *
     * @param l the Locale of the resource bundle being requested.
     * @return the string resource (bundle) for this Portlet.  <b>null</b> if
     * there isn't one.
     */
    public ResourceBundle getResourceBundle(Locale l)
    {
        if (mResource == null) return null;

        if (l == null)
        {
            l = Locale.getDefault();
        }

        if (mBundle == null || mBundleLocale == null || !l.equals(mBundleLocale))
        {
            mBundle = ResourceBundle.getBundle(mResource, l);
            mBundleLocale = l;
        }

        return mBundle;
    }

    /**
     * Sets the name of the default resource bundle class for this Portlet
     *
     * @param resourceClassName full name of class extending {@link
     * java.util.ResourceBundle}.
     */
    public void setResource(String resourceClassName)
    {
        mResource = resourceClassName;
    }

    /**
     * Gets the Portlet name.
     *
     * @param l the Locale (language) the requested name should be
     * retrieved/returned in.
     * @return the Portlet name.  This is the Portlet's non-unique display
     * name.
     */
    public String getName(Locale l)
    {
        if (mName != null)
        {
            return mName;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                return b.getString(PortletConstants.NAME);
            }
        }
        return null;
    }

    /**
     * Gets the Portlet unique ID.
     *
     * @return the Portlet (unique) ID.  Value should be unique with respect to
     * the Provider.
     */
    public long getId()
    {
        return mPortletId;
    }

    /**
     * Gets the Portlet title.
     *
     * @param l the Locale (language) the requested title should be
     * retrieved/returned in.
     * @return the title of this Portlet.  This is the name that shows up in a
     * portlet's title bar.
     */
    public String getTitle(Locale l)
    {
        if (mTitle != null)
        {
            return mTitle;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                return b.getString(PortletConstants.TITLE);
            }
        }
        return null;
    }

    /**
     * Gets the Portlet short title.
     *
     * @param l the Locale (language) the requested shorttitle should be
     * retrieved/returned in.
     * @return the shorttitle of this Portlet.  This is the name used when real
     * estate is at a premium such as when rendering a mobile link.
     */
    public String getShortTitle(Locale l)
    {
        if (mShortTitle != null)
        {
            return mShortTitle;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                try
                {
                    return b.getString(PortletConstants.SHORTTITLE);
                }
                catch (MissingResourceException mre)
                {
                    // Make this an optional string
                }
            }
        }
        return null;
    }

    /**
     * Gets the Portlet description.
     *
     * @param l the Locale (language) the requested description should be
     * retrieved/returned in.
     * @return a short description of what this portlet is.  Displayed at
     * design-time along with the name and thumbnail image when a user is
     * choosing to add a portlet to a page.
     */
    public String getDescription(Locale l)
    {
        if (mDescription != null)
        {
            return mDescription;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                return b.getString(PortletConstants.DESCRIPTION);
            }
        }
        return null;
    }

    /**
     * Gets an array of (input) parameters that this portlet recognizes when
     * requested to render to control/affect the rendering.
     *
     * @return array of PortletParameters.
     */
    public PortletParameter[] getInputParameters()
    {
      if (mInputParameters == null)
      {
          return null;
      }
      PortletParameter[] inputParameters =
          new PortletParameter[mInputParameters.size()];

      mInputParameters.copyInto(inputParameters);

      return inputParameters;
    }

    /**
     * Gets an array of mime-types (represented as Strings) that this Portlet
     * can render.  For example {"text/html", "text/xml"}.
     *
     * @return array containing a list of mime-types.
     */
    public String[] getAcceptContentTypes()
    {
        if (mAcceptContentTypes == null)
        {
            return null;
        }
        String[] contentTypes =
            new String[mAcceptContentTypes.size()];

        mAcceptContentTypes.copyInto(contentTypes);

        return contentTypes;
    }

    /**
     * Gets the number of seconds the portal should wait before timing out a
     * request to this portlet.
     *
     * @return timeout period in seconds.
     */
    public int getTimeout()
    {
        return mTimeout;
    }

    /**
     * Gets the timeout messsage that the portal should use in its response
     * when a request to this Portlet times out.
     *
     * @param l the Locale (language) the requested timeout message should be
     * retrieved/returned in.
     * @return Timeout message.
     */
    public String getTimeoutMessage(Locale l)
    {
        if (mTimeoutMessage != null)
        {
            return mTimeoutMessage;
        }
        else
        {
            ResourceBundle b = getResourceBundle(l);
            if (b != null)
            {
                return b.getString(PortletConstants.TIMEOUTMSG);
            }
        }
        return null;
    }

    /**
     * Returns true if this Portlet supports per user personalization, false
     * otherwise.
     *
     * @return returns true if this Portlet supports per user personalization,
     * false otherwise.
     */
    public boolean hasShowEdit()
    {
        return mShowEdit;
    }

    /**
     * Returns true if this Portlet exposes per user personalization to the
     * public (non-logged in) user.  The default for portlets is false.  In
     * general allowing the public user to personalize a portlet is a bad idea
     * as the personalization is seen by all public users.  Instead it is
     * recommended that controlled users be allowed to edit the portlet's
     * defaults which are then exposed through to the public users (and any
     * other user that doesn't personalize the portlet).
     *
     * @return returns true if this Portlet exposes per user personalization to
     * the public (non-logged in) user, false otherwise.
     */
    public boolean getShowEditToPublic()
    {
        if (mMinEditAuthLevel == ProviderUser.NOT_AUTHENTICATED)
        {
            return true;
        }
        return false;
    }

    /**
     * Returns true if this Portlet supports per portlet customization, false
     * otherwise.  Per portlet customizations means that all users of this
     * instance see a customized version of the portlet vs. the generic
     * version.  Users are then free to further personalize this instance (via
     * showEdit).
     *
     * @return returns true if this Portlet supports per portlet customization,
     * false otherwise.
     */
    public boolean hasShowEditDefault()
    {
        return mShowEditDefault;
    }

    /**
     * Returns true if this Portlet is capable of displaying a design-time
     * preview of itself (after customization or personalization). Returns
     * false otherwise.
     *
     * @return returns true if this Portlet is capable of displaying a
     * design-time preview of itself (after customization or
     * personalization). Returns false otherwise.
     */
    public boolean hasShowPreview()
    {
        return mShowPreview;
    }

    /**
     * Return returns true if this Portlet is capable of displaying a
     * full-screen (detailed) version of itself.
     *
     * @return returns true if this Portlet is capable of displaying a
     * full-screen (detailed) version of itself.
     *
     */
    public boolean hasShowDetails()
    {
        return mShowDetails;
    }

    /**
     * Return returns true if this Portlet is capable of displaying help
     * information.
     *
     * @return returns true if this Portlet is capable of displaying help
     * information.
     *
     */
    public boolean hasHelp()
    {
        return mHasHelp;
    }

    /**
     * Return returns true if this Portlet is capable of displaying about
     * information.
     *
     * @return returns true if this Portlet is capable of displaying about
     * information.
     *
     */
    public boolean hasAbout()
    {
        return mHasAbout;
    }

    /**
     * @deprecated as of iAS 9.0.1 this is deprecated for hasShowLink()<p>
     * Returns true if this Portlet is capable of rendering content for link
     * mode.
     *
     * @return returns true if this Portlet is capable of rendering content for
     * link mode.
     */
    public boolean hasShowLinkMode()
    {
        return hasShowLink();
    }

    /**
     * Returns true if this Portlet is capable of rendering content for link
     * mode.
     *
     * @return returns true if this Portlet is capable of rendering content for
     * link mode.
     */
    public boolean hasShowLink()
    {
        return mShowLink;
    }

    /**
     * Returns true if calls to <code>isPortletRunnable</code> should be made
     * to this Portlet before displaying in the portlet repository. If false,
     * the portlet is treated as a public portlet visible to all users.
     *
     * @return returns true if calls to <code>isPortletRunnable</code> should
     * be made to this Portlet.
     */
    public boolean callIsRunnable()
    {
        return mCallIsRunnable;
    }

    /**
     * Returns true if calls to retrieve this Portlet's meta data should be
     * made. before displaying in the portlet repository.  If false, the
     * default meta data will be displayed for all users.
     *
     * @return returns true if calls to retrieve this Portlet's meta data
     * should be made.
     */
    public boolean callGetPortlet()
    {
        return mCallGetPortlet;
    }

    /**
     * Returns the portlet's mobile settings as a bitwise flag.
     * The flags values are defined in the interface <code>MobileFlags</code>.
     *
     * @return the portlet's mobile setting in a bitwise flag
     */
    public MobileFlags getMobileFlags()
    {
        return mMobileFlags;
    }

    /* *********************************************************** */
    /*                                                             */
    /*               LoadablePortletFactory methods                */
    /*                                                             */
    /* *********************************************************** */

    /**
     * Sets the Portlet security manager.
     *
     * @param mgr Object implementing the {@link
     * oracle.portal.provider.v1.PortletSecurityManager} interface.
     * @exception oracle.portal.provider.v1.PortletException if the given
     * Object is not a valid {@link
     * oracle.portal.provider.v1.PortletSecurityManager}
     */
    public void setSecurityManager(Object mgr) throws PortletException
    {
        if (!(mgr instanceof PortletSecurityManager))
        {
            throw new PortletException("Object not a PortletSecurityManager");
        }
        mSecurityMgr = (PortletSecurityManager)mgr;
    }

    /**
     * Sets the Portlet personalization manager.
     *
     * @param mgr Object implementing the {@link
     * oracle.portal.provider.v1.PortletPersonalizationManager} interface.
     * @exception oracle.portal.provider.v1.PortletException if the given
     * Object is not a valid {@link
     * oracle.portal.provider.v1.PortletPersonalizationManager}
     */
    public void setPersonalizationManager(Object mgr) throws PortletException
    {
        if (!(mgr instanceof PortletPersonalizationManager))
        {
            throw new PortletException("Object not a PortletPersonalizationManager");
        }
        mPersonalizationMgr = (PortletPersonalizationManager)mgr;
    }

    /**
     * Sets the Portlet renderer.
     *
     * @param renderer Object implementing the {@link
     * oracle.portal.provider.v1.PortletRenderer} interface.
     * @exception oracle.portal.provider.v1.PortletException if the given
     * Object is not a valid {@link oracle.portal.provider.v1.PortletRenderer}
     */
    public void setRenderer(Object renderer) throws PortletException
    {
        if (!(renderer instanceof PortletRenderer))
        {
            throw new PortletException("Object not a PortletRenderer");
        } 
        mRenderer = (PortletRenderer)renderer;
    }

    /**
     * Sets the Portlet name.
     *
     * @param name the Portlet name. This is the Portlet's non-unique display
     * name.
     */
    public void setName(String name)
    {
        mName = name;
    }

    /**
     * Sets the Portlet unique ID.
     *
     * @param id the Portlet (unique ID). Value should be a String
     * representation of a long value, unique with respect to the Provider.
     * @exception oracle.portal.provider.v1.PortletException if the given
     * String does not represent a valid <code>long</code>.
     */
    public void setId(String id) throws PortletException
    {
        try
        {
            mPortletId = Long.parseLong(id);
        }
        catch (NumberFormatException e)
        {
            throw new PortletException(e);
        }
    }

    /**
     * Sets the Portlet title.
     *
     * @param title the title of this Portlet. This is the name that shows up
     * in a portlet's title bar.
     */
    public void setTitle(String title)
    {
        mTitle = title;
    }

    /**
     * Sets the Portlet short title.
     *
     * @param sthe short title of this Portlet. This is the name used when real
     * estate is at a premium such as when rendering a mobile link.
     */
    public void setShortTitle(String title)
    {
        mShortTitle = title;
    }

    /**
     * Sets the Portlet description.
     *
     * @param description a short description of what this portlet is.
     * Displayed at design-time along with the name and thumbnail image when a
     * user is choosing to add a portlet to a page.
     */
    public void setDescription(String description)
    {
        mDescription = description;
    }

    /**
     * Adds to the array of (input) parameters that this portlet recognizes
     * when requested to render to control/affect the rendering.
     *
     * @param parameter Object implementing the {@link
     * oracle.portal.provider.v1.PortletParameter} interface.
     * @exception oracle.portal.provider.v1.PortletException if the given
     * Object is not a valid {@link oracle.portal.provider.v1.PortletParameter}
     */
    public void addInputParameter(Object parameter) throws PortletException
    {
        if (mInputParameters == null)
        {
            mInputParameters = new Vector();
        }
        if (!(parameter instanceof PortletParameter))
        {
            throw new PortletException("Object not a PortletParameter");   
        }
        mInputParameters.addElement(parameter);
    }

    /**
     * Adds to the set of mime-types (represented as Strings) that this Portlet
     * can render.
     *
     * @param type mime-type String, e.g. "text/html" or "text/xml".
     */
    public void addAcceptContentType(String type)
    {
        mAcceptContentTypes.addElement(type);
    }

    /**
     * Sets the number of seconds the portal should wait before timing out a
     * request to this portlet.
     *
     * @param timeout timeout period, as a String representation of an integer
     * number of seconds.
     * @exception oracle.portal.provider.v1.PortletException if the given
     * String does not represent a valid <code>int</code>.
     */
    public void setTimeout(String timeout) throws PortletException
    {
        try
        {
            mTimeout = Integer.parseInt(timeout);
        }
        catch (NumberFormatException e)
        {
            throw new PortletException(e);
        }
    }

    /**
     * Sets the timeout messsage that the portal should use in its response
     * when a request to this Portlet times out.
     *
     * @param msg timeout message.
     */
    public void setTimeoutMessage(String msg)
    {
        mTimeoutMessage = msg;
    }


    /**
     * Controls whether this Portlet supports per user personalization.
     *
     * @param canEdit String representation of boolean value. Should be "true"
     * if this Portlet is to support per user personalization, "false"
     * otherwise.
     */
    public void setShowEdit(String canEdit)
    {
        mShowEdit = XMLUtil.getBooleanValue(canEdit);
    }

    /**
     * Controls whether this Portlet exposes per user personalization to the
     * public non-logged in user.
     *
     * @param canEdit String representation of boolean value. Should be "true"
     * if this Portlet exposes per user personalization to the public
     * non-logged in user, "false" otherwise.
     *
     * @deprecated use setMinEditAuthLevel()
     */
    public void setShowEditToPublic(String canEditString)
    {
        boolean canEdit = XMLUtil.getBooleanValue(canEditString);
        if (canEdit)
        {
            mMinEditAuthLevel = ProviderUser.NOT_AUTHENTICATED;
        }
        else
        {
            mMinEditAuthLevel = ProviderUser.PUBLIC_STRONG_AUTH;
        }
    }

    /**
     * Controls whether this Portlet supports per portlet customization. Per
     * portlet customizations means that all users of this instance see a
     * customized version of the portlet vs. the generic version. Users are
     * then free to further personalize this instance (via showEdit).
     *
     * @param canEditDefault String representation of boolean value. Should be
     * "true" if this Portlet supports per portlet customization, "false"
     * otherwise.
     */
    public void setShowEditDefault(String canEditDefault)
    {
        mShowEditDefault = XMLUtil.getBooleanValue(canEditDefault);
    }


    /**
     * Controls whether this Portlet is capable of displaying a design-time
     * preview of itself (after customization or personalization).
     *
     * @param canPreview String representation of boolean value. Should be
     * "true" if this Portlet is capable of displaying a design-time preview of
     * itself (after customization or personalization), or "false" otherwise.
     */
    public void setShowPreview(String canPreview)
    {
        mShowPreview = XMLUtil.getBooleanValue(canPreview);
    }

    /**
     * Controls whether this Portlet displays "detailed" mode. Detailed mode is
     * a full page mode where this portlet is expected to display a finer level
     * of information.
     *
     * @param hasDetails String representation of boolean value. Should be
     * "true" if this Portlet is capable of displaying a "detailed" mode, or
     * "false" otherwise.
     */
    public void setShowDetails(String hasDetails)
    {
        mShowDetails = XMLUtil.getBooleanValue(hasDetails);
    }

    /**
     * Controls whether this Portlet displays help information.
     *
     * @param hasHelp String representation of boolean value. Should be "true"
     * if this Portlet is capable of displaying a help information, or "false"
     * otherwise.
     */
    public void setHasHelp(String hasHelp)
    {
        mHasHelp = XMLUtil.getBooleanValue(hasHelp);
    }

    /**
     * Controls whether this Portlet displays about information.
     *
     * @param hasAbout String representation of boolean value. Should be "true"
     * if this Portlet is capable of displaying about information, or "false"
     * otherwise.
     */
    public void setHasAbout(String hasAbout)
    {
        mHasAbout = XMLUtil.getBooleanValue(hasAbout);
    }

    /**
     * Sets the default Locale for this Portal
     *
     * @param lang a String specifying a Locale, in the form
     * "language.country".
     */
    public void setDefaultLocale(String lang)
    {
        String language = "", country = "";

        int i = lang.indexOf(".");

        if (i == -1)
        {
            language = lang;
        }
        else
        {
            language = lang.substring(0, i);
            country = lang.substring(i+1);
        }
        mDefaultLocale = new Locale(language, country);
    }

    /**
     * @deprecated as of iAS 9.0.1 this is deprecated for setShowLink()<p>
     * Controls whether this Portlet is capable of rendering content for link
     * mode.
     *
     * @param value boolean flag.
     */
    public void setShowLinkMode(boolean value)
    {
        setShowLink(value);
    }

    /**
     * @deprecated as of iAS 9.0.1 this is deprecated for setShowLink()<p>
     * Controls whether this Portlet is capable of rendering content for link
     * mode.
     *
     * @param value String representing a boolean.
     */
    public void setShowLinkMode(String value)
    {
        setShowLink(value);
    }

    /**
     * Controls whether this Portlet is capable of rendering content for link
     * mode.
     *
     * @param value boolean flag.
     */
    public void setShowLink(boolean value)
    {
        mShowLink = value;
    }

    /**
     * Controls whether this Portlet is capable of rendering content for link
     * mode.
     *
     * @param value String representing a boolean.
     */
    public void setShowLink(String value)
    {
        setShowLink(XMLUtil.getBooleanValue(value));
    }


    /**
     * Controls whether calls to <code>isPortletRunnable</code> should be made
     * to this Portlet before displaying in the portlet repository. If false,
     * the portlet is treated as a public portlet visible to all users.
     *
     * @param value boolean flag.
     */
    public void setCallIsRunnable(boolean value)
    {
        mCallIsRunnable = value;
    }

    /**
     * Controls whether calls to <code>isPortletRunnable</code> should be made
     * to this Portlet before displaying in the portlet repository. If false,
     * the portlet is treated as a public portlet visible to all users.
     *
     * @param value String representing a boolean.
     */
    public void setCallIsRunnable(String value)
    {
        mCallIsRunnable = XMLUtil.getBooleanValue(value);
    }

    /**
     * Controls whether calls to retrieve this Portlet's meta data should be
     * made before displaying in the portlet repository.  If false, the default
     * meta data will be displayed for all users.
     *
     * @param value boolean flag.
     */
    public void setCallGetPortlet(boolean value)
    {
        mCallGetPortlet = value;
    }

    /**
     * Controls whether calls to retrieve this Portlet's meta data should be
     * made before displaying in the portlet repository.  If false, the default
     * meta data will be displayed for all users.
     *
     * @param value String representing a boolean.
     */
    public void setCallGetPortlet(String value)
    {
        mCallGetPortlet = XMLUtil.getBooleanValue(value);
    }


    /**
     * Sets the portlet's mobile settings.
     * The flags values are defined in the <code>MobileFlags</code> inteface.
     *
     * @param the portlet's mobile setting in a bitwise flag
     */
    public void setMobileFlags(long flags)
    {
        if (mMobileFlags != null)
        {
            mMobileFlags.setValue(flags);
        }
        else
        {
            mMobileFlags = new MobileFlags(flags);
        }
    }

    /**
     * Sets the portlet's mobile settings. The flags values are defined by the
     * <code>MobileFlags</code> interface.
     * This form allows you to set the flags as a string.
     * The string can either be the (case insensitive) delimited
     * names of the flags or the number itself (as a String).  E.g.
     * passing "MOBILE_ONLY | EXTERNAL_SHOW" is the same as
     * passing the string "3" to the method.
     *
     *
     * @param the portlet's mobile setting in a bitwise flag
     */
    public void setMobileFlags(String flags) throws IllegalArgumentException
    {
        if (mMobileFlags != null)
        {
            mMobileFlags.setValue(flags);
        }
        else
        {
            mMobileFlags = new MobileFlags(flags);
        }
    }

    /**
     * Returns the minimum user authentication level required for the
     * customize link to be displayed in the portlet header
     *
     * If the authentication level of a user is less than the minimum
     * authentication level specified, the customize link will not be
     * displayed in the portlet header.
     *
     * @return the min. authentication level required to edit the portlet.
     */
    public int getMinEditAuthLevel()
    {
        return mMinEditAuthLevel;
    }


     /**
     * Sets the minimum user authentication level required for the
     * customize link to be displayed in the portlet header
     *
     * If the authentication level of a user is less than the minimum
     * authentication level specified, the customize link will not be
     * displayed in the portlet header.
     *
     * @param authLevel minimum authentication level. Possible values are
     *                  "PUBLIC", "WEAK", "STRONG"
     */
    public void setMinEditAuthLevel(String authLevel) throws PortletException
    {
        if (authLevel == null)
        {
            throw new PortletException("Authentication level cannot be NULL");
        }
        else if (authLevel.equalsIgnoreCase("PUBLIC"))
        {
            mMinEditAuthLevel = ProviderUser.NOT_AUTHENTICATED;
        }
        else if (authLevel.equalsIgnoreCase("WEAK"))
        {
            mMinEditAuthLevel = ProviderUser.PUBLIC_WEAK_AUTH;
        }
        else if (authLevel.equalsIgnoreCase("STRONG"))
        {
            mMinEditAuthLevel = ProviderUser.PUBLIC_STRONG_AUTH;
        }
        else
        {
            throw new PortletException("Invalid authentication level: " + authLevel);
        }
    }


    /**
     * Returns the controller that will render this portlet's container.
     *
     * The container renderer is responsible for rendering the portlet
     * container in each of the show modes the portlet supports
     *
     * @return the portlet container renderer that should be used to render
     *         the container for this portlet
     */
    public PortletContainerRenderer getContainerRenderer()
    {
        if (mContainerRenderer != null)
            return mContainerRenderer;

        // since this method is called during the processing of portlet requests
        // and it modifies the state of the PortletDefinition (which is shared)
        // this portion of the code should be synchronized
        synchronized(mLock)
        {
            // portlet does not have a container renderer so see if we can get
            // one from the provider - provider must implement the ProviderXtra
            // interface
            if (mProvider instanceof ProviderXtra)
            {
                ProviderXtra temp = (ProviderXtra)mProvider;
                mContainerRenderer = temp.getContainerRenderer();
            }

            // if we still do not have a container renderer, use the default.
            if (mContainerRenderer == null)
            {
                mContainerRenderer = new DefaultContainerRenderer();
            }
        }
        return mContainerRenderer;
    }


    /**
     * Sets the controller that will render this portlet's container.
     *
     * The container renderer is responsible for rendering the portlet
     * container in each of the show modes the portlet supports
     *
     * @param renderer the portlet container renderer
     */
    public void setContainerRenderer(PortletContainerRenderer renderer)
        throws PortletException
    {
        mContainerRenderer = renderer;
    }

    /**
     * Sets the controller that will render this portlet's container.
     *
     * The container renderer is responsible for rendering the portlet
     * container in each of the show modes the portlet supports
     *
     * @param renderer the portlet container renderer. Even though the type
     *                 of the parameter is Object, the parameter must be an
     *                 instance of PortletContainerRenderer
     */
    public void setContainerRenderer(Object renderer) throws PortletException
    {
        if (renderer != null && renderer instanceof PortletContainerRenderer)
        {
            setContainerRenderer((PortletContainerRenderer)renderer);
        }
        else
        {
            throw new PortletException("Object must be an instance of PortletContainerRenderer");
        }
    }

}
