/*
* Copyright 2000-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jetspeed.portal.security.portlets;
// Jetspeed
import org.apache.jetspeed.om.security.JetspeedUser;
import org.apache.jetspeed.portal.Portlet;
import org.apache.jetspeed.portal.PortletState;
import org.apache.jetspeed.portal.PortletConfig;
import org.apache.jetspeed.portal.PortletException;
import org.apache.jetspeed.portal.PortletInstance;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.portletcache.Cacheable;
import org.apache.jetspeed.services.security.PortalResource;
import org.apache.jetspeed.services.JetspeedSecurity;
import org.apache.jetspeed.util.template.JetspeedLink;
import org.apache.jetspeed.util.template.JetspeedLinkFactory;
import org.apache.jetspeed.util.MimeType;
import org.apache.jetspeed.services.PortletStats;
// Turbine imports
import org.apache.turbine.util.RunData;
import org.apache.turbine.services.localization.Localization;
// ECS
import org.apache.ecs.ConcreteElement;
import org.apache.jetspeed.util.JetspeedClearElement;
/**
<p>
This object is used to wrap a Portlet, ensuring that access control rules are enforced.
</p>
@author <A HREF="mailto:sgala@apache.org">Santiago Gala</A>
@version $Id: PortletWrapper.java,v 1.25 2004/03/29 21:38:43 taylor Exp $
*/
public class PortletWrapper implements Portlet
{
/**
* Static initialization of the logger for this class
*/
private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(PortletWrapper.class.getName());
/*
* The portlet we are wrapping
*/
private Portlet wrappedPortlet = null;
private PortalResource portalResource = null;
private ConcreteElement content = null;
public PortletWrapper(Portlet inner)
{
wrappedPortlet = inner;
portalResource = new PortalResource(wrappedPortlet);
}
/**
*/
public final String getName()
{
//This means name is accessible for every Portlet
return wrappedPortlet.getName();
}
/**
*/
public final void setName(String name)
{
//if we want to secure this, we need a context for the check
wrappedPortlet.setName(name);
}
/**
*/
public final PortletConfig getPortletConfig()
{
return wrappedPortlet.getPortletConfig();
}
/**
*/
public final void setPortletConfig(PortletConfig pc)
{
//if we want to secure this, we need a context for the check
wrappedPortlet.setPortletConfig(pc);
}
/**
*/
public ConcreteElement getContent(RunData rundata)
{
if (checkPermission(rundata, JetspeedSecurity.PERMISSION_VIEW))
{
if (PortletStats.isEnabled())
{
long start = System.currentTimeMillis();
content = wrappedPortlet.getContent(rundata);
long time = System.currentTimeMillis() - start; // time it took to get the content for this portlet
PortletStats.logAccess(rundata, this, PortletStats.ACCESS_OK, time);
} else {
content = wrappedPortlet.getContent(rundata);
}
return content;
}
else
{
if (PortletStats.isEnabled())
{
PortletStats.logAccess(rundata, this, PortletStats.ACCESS_DENIED);
}
return new JetspeedClearElement(Localization.getString(rundata, "SECURITY_NO_ACCESS_TO_PORTLET"));
}
}
/**
Provide a description within PML if the user has specified one.
@return a null entry if the user hasn't defined anything
*/
public String getDescription()
{
return wrappedPortlet.getDescription();
}
public String getDescription(String instanceDescription)
{
return wrappedPortlet.getDescription(instanceDescription);
}
/**
*/
public void setDescription(String description)
{
wrappedPortlet.setDescription(description);
}
/**
* @see Portlet#getImage
*/
public String getImage(String instanceImage)
{
return wrappedPortlet.getImage(instanceImage);
}
/**
* @see Portlet#setImge
*/
public void setImage(String image)
{
wrappedPortlet.setImage(image);
}
/**
* @see Portlet#getTitle
*/
public String getTitle()
{
/* FIXME, no rundata here if( !checkPermission(rundata,
JetspeedSecurity.PERMISSION_VIEW ) )
{ */
return wrappedPortlet.getTitle();
/* } */
}
/**
* @see Portlet#getImage
*/
public String getTitle(String instanceTitle)
{
return wrappedPortlet.getTitle(instanceTitle);
}
/**
Set the title for this Portlet
*/
public void setTitle(String title)
{
/* FIXME, no rundata here if( !checkPermission(rundata,
JetspeedSecurity.PERMISSION_CUSTOMIZE ) )
{ */
wrappedPortlet.setTitle(title);
/* } */
}
/**
*/
public boolean getAllowEdit(RunData rundata)
{
return checkPermission(rundata, JetspeedSecurity.PERMISSION_CUSTOMIZE);
}
/**
*/
public boolean getAllowView(RunData rundata)
{
if (checkPermission(rundata, JetspeedSecurity.PERMISSION_VIEW))
{
return wrappedPortlet.getAllowView(rundata);
}
return false;
}
/**
*/
public boolean getAllowMaximize(RunData rundata)
{
return checkPermission(rundata, JetspeedSecurity.PERMISSION_MAXIMIZE);
}
/**
By default don't provide any initialization
*/
public void init() throws PortletException
{
/* FIXME, no rundata here if( !checkPermission(rundata,
JetspeedSecurity.PERMISSION_CUSTOMIZE) )
{ */
wrappedPortlet.init();
/* } */
}
/**
@see Portlet#getCreationTime
*/
public long getCreationTime()
{
/* FIXME, no rundata here if( !checkPermission(rundata,
JetspeedSecurity.PERMISSION_VIEW) )
{ */
return wrappedPortlet.getCreationTime();
/* } */
}
/**
@see Portlet#setCreationTime
*/
public void setCreationTime(long creationTime)
{
/* FIXME, no rundata here if( !checkPermission(rundata,
JetspeedSecurity.PERMISSION_CUSTOMIZE) )
{ */
wrappedPortlet.setCreationTime(creationTime);
}
/**
@see Portlet#supportsType
*/
public boolean supportsType(MimeType mimeType)
{
/* FIXME, no rundata here if( !checkPermission(rundata,
JetspeedSecurity.PERMISSION_VIEW) )
{ */
return wrappedPortlet.supportsType(mimeType);
/* } */
}
/**
* Utility method for checking Permissions on myself.
* @param rundata A rundata Object
* @param permissionName String the name of the Permission requested
* @return boolean is it granted?
*/
protected boolean checkPermission(RunData rundata, String permissionName)
{
try
{
JetspeedLink jsLink = JetspeedLinkFactory.getInstance(rundata);
portalResource.setOwner(jsLink.getUserName());
JetspeedLinkFactory.putInstance(jsLink);
}
catch (Exception e)
{
logger.warn(e.getMessage(), e);
portalResource.setOwner(null);
}
if (logger.isDebugEnabled())
{
logger.debug("checking for Portlet permission: "
+ permissionName
+ " for portlet: "
+ wrappedPortlet.getName()
+ " Owner = "
+ portalResource.getOwner());
}
return JetspeedSecurity.checkPermission((JetspeedUser) rundata.getUser(),
portalResource,
permissionName);
}
// utility methods
/**
Returns TRUE if the title bar in should be displayed. The title bar includes
the portlet title and action buttons.
NOTE(FIXME) Not in Portlet interface. Called a la Bean from Velocity.
@param rundata A RunData object
*/
public boolean isShowTitleBar(RunData rundata)
{
if (wrappedPortlet.getPortletConfig() != null)
{
// Parameter can exist in PSML or <portlet-entry>
return Boolean.valueOf(wrappedPortlet.getPortletConfig().getInitParameter("_showtitlebar", "true")).booleanValue();
}
return getAttribute("_showtitlebar", "true", rundata).equals("true");
}
/**
Retrieve a portlet attribute from persistent storage
@param attrName The attribute to retrieve
@parm attrDefValue The value if the attr doesn't exists
@param rundata A RunData object
@return The attribute value
*/
public String getAttribute(String attrName, String attrDefValue, RunData rundata)
{
if (checkPermission(rundata, JetspeedSecurity.PERMISSION_VIEW))
{
return wrappedPortlet.getAttribute(attrName, attrDefValue, rundata);
}
else
{
//FIXME: for the moment we will allow this call to succeed...
//throw new TurbineRuntimeException( "Security check failed" );
return wrappedPortlet.getAttribute(attrName, attrDefValue, rundata);
}
}
/**
* Sets a portlet attribute to persistent storage
*
* @param attrName The attribute to retrieve
* @param attrValue The value
* @param rundata A RunData object
*/
public void setAttribute(String attrName, String attrValue, RunData rundata)
{
if (checkPermission(rundata, JetspeedSecurity.PERMISSION_VIEW))
{
wrappedPortlet.setAttribute(attrName, attrValue, rundata);
}
else
{
//FIXME: for the moment we will allow this call to succeed...
//throw new TurbineRuntimeException( "Security check failed" );
wrappedPortlet.setAttribute(attrName, attrValue, rundata);
}
}
/**
* Gets the portlet instance associated with this portlet.
*
* @param rundata A RunData object
* @return PortletInstance
*/
public PortletInstance getInstance(RunData rundata)
{
return wrappedPortlet.getInstance(rundata);
}
/**
* <p>Return an instance of one of the classes in this package
* making tests before calling the wrapped portlet</p>
* <p>Different wrapper classes must be used with the current API
* depending on the interfaces implemented by the portlet. :-(</p>
*
*/
public static Portlet wrap(Portlet aPortlet)
{
//SGP Security test
if (aPortlet instanceof PortletState)
{
if (aPortlet instanceof Cacheable)
{
return new CacheableStatefulPortletWrapper(aPortlet);
}
return new StatefulPortletWrapper(aPortlet);
}
if (aPortlet instanceof Cacheable)
{
return new CacheablePortletWrapper(aPortlet);
}
return new PortletWrapper(aPortlet);
}
public String getID()
{
return wrappedPortlet.getID();
}
public void setID(String id)
{
wrappedPortlet.setID(id);
}
/**
* @return true if the portlet does its own customization
*/
public boolean providesCustomization()
{
return wrappedPortlet.providesCustomization();
}
public Portlet getPortlet()
{
return wrappedPortlet;
}
}