/* ====================================================================
* 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 apache@apache.org.
*
* 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.portaltoolkit;
//jetspeed stuff
import org.apache.jetspeed.portal.PortletControl;
import org.apache.jetspeed.portal.PortletController;
import org.apache.jetspeed.portal.PortletSkin;
import org.apache.jetspeed.portal.PortletSet;
import org.apache.jetspeed.portal.Portlet;
import org.apache.jetspeed.portal.PortletConfig;
import org.apache.jetspeed.portal.BasePortletConfig;
import org.apache.jetspeed.portal.PortletControlConfig;
import org.apache.jetspeed.portal.BasePortletControlConfig;
import org.apache.jetspeed.portal.PortletControllerConfig;
import org.apache.jetspeed.portal.BasePortletControllerConfig;
import org.apache.jetspeed.portal.BasePortletSkin;
import org.apache.jetspeed.portal.BasePortletSet;
import org.apache.jetspeed.om.profile.Control;
import org.apache.jetspeed.om.profile.Controller;
import org.apache.jetspeed.om.profile.Skin;
import org.apache.jetspeed.om.profile.Portlets;
import org.apache.jetspeed.om.profile.Layout;
import org.apache.jetspeed.om.profile.Profile;
import org.apache.jetspeed.om.profile.Parameter;
import org.apache.jetspeed.om.profile.MetaInfo;
import org.apache.jetspeed.om.profile.Entry;
import org.apache.jetspeed.om.profile.ProfileLocator;
import org.apache.jetspeed.om.profile.PSMLDocument;
import org.apache.jetspeed.services.Profiler;
import org.apache.jetspeed.services.rundata.JetspeedRunData;
import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
import org.apache.jetspeed.services.Registry;
import org.apache.jetspeed.services.PortletFactory;
import org.apache.jetspeed.om.registry.PortletEntry;
import org.apache.jetspeed.om.registry.PortletControlEntry;
import org.apache.jetspeed.om.registry.PortletControllerEntry;
import org.apache.jetspeed.om.registry.SkinEntry;
import org.apache.jetspeed.util.MetaData;
import org.apache.jetspeed.util.JetspeedException;
import org.apache.jetspeed.util.ServiceUtil;
import org.apache.jetspeed.om.BaseSecurityReference;
import org.apache.jetspeed.om.SecurityReference;
import org.apache.jetspeed.om.registry.SecurityEntry;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.services.TurbineBaseService;
import org.apache.turbine.services.InitializationException;
import org.apache.turbine.services.resources.ResourceService;
import org.apache.turbine.services.rundata.RunDataService;
import org.apache.turbine.util.Log;
import java.util.Iterator;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.ServletConfig;
/**
* Simple implementation of the PortalFactoryService.
*
* @author <a href="mailto:raphael@apache.org">Rapha�l Luta</a>
* @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
* @author <a href="mailto:morciuch@apache.org">Mark Orciuch</a>
*
* @version $Id: JetspeedPortalToolkitService.java,v 1.29 2003/04/11 16:01:57 weaver Exp $
*/
public class JetspeedPortalToolkitService
extends TurbineBaseService
implements PortalToolkitService
{
/** The default control to use when none is specified */
private String defaultControl = null;
/** The default controller to use when none is specified */
private String defaultController = null;
/** The default skin to use when none is specified */
private String defaultSkin = null;
/** The default user security ref to use when none is specified */
private String defaultUserSecurityRef = null;
/** The default anonymous user security ref to use when none is specified */
private String defaultAnonSecurityRef = null;
/** The default role security ref to use when none is specified */
private String defaultRoleSecurityRef = null;
/** The default group security ref to use when none is specified */
private String defaultGroupSecurityRef = null;
/**
* This is the early initialization method called by the
* Turbine <code>Service</code> framework
*/
public void init(ServletConfig conf) throws InitializationException
{
ResourceService serviceConf =
((TurbineServices) TurbineServices.getInstance()).getResources(
PortalToolkitService.SERVICE_NAME);
this.defaultControl = serviceConf.getString("default.control");
this.defaultController = serviceConf.getString("default.controller");
this.defaultSkin = serviceConf.getString("default.skin");
this.defaultUserSecurityRef = serviceConf.getString("default.user.security.ref");
this.defaultAnonSecurityRef = serviceConf.getString("default.anon.security.ref");
this.defaultRoleSecurityRef = serviceConf.getString("default.role.security.ref");
this.defaultGroupSecurityRef = serviceConf.getString("default.group.security.ref");
setInit(true);
}
/**
* Instanciates a PortletControl based on a Registry entry, if available
* or directly from a classname.
*
* @param name a PortletControl name available in the registry or a classname
* @return the created PortletControl
*/
public PortletControl getControl(String name)
{
PortletControl pc = null;
PortletControlEntry entry = null;
if (name != null)
{
entry = (PortletControlEntry) Registry.getEntry(Registry.PORTLET_CONTROL, name);
}
Map params = null;
try
{
if (entry == null)
{
if (name != null)
{
pc = (PortletControl) Class.forName(name).newInstance();
params = new Hashtable();
}
}
else
{
pc = (PortletControl) Class.forName(entry.getClassname()).newInstance();
params = entry.getParameterMap();
}
}
catch (Exception e)
{
Log.error("Unable to instanciate control " + name + ", using default", e);
}
if ((pc == null) && (defaultControl != null) && (!defaultControl.equals(name)))
{
return getControl(defaultControl);
}
PortletControlConfig pcConf = new BasePortletControlConfig();
pcConf.setName(name);
pcConf.setInitParameters(params);
pc.setConfig(pcConf);
return pc;
}
/**
* Instanciates a PortletControl based on a PSML Control object
*
* @param control the PSML control object
* @return the created PortletControl
*/
public PortletControl getControl(Control control)
{
PortletControl pc = null;
if (control != null)
{
pc = getControl(control.getName());
pc.getConfig().getInitParameters().putAll(getParameters(control));
}
else
{
if (defaultControl != null)
{
pc = getControl(this.defaultControl);
}
}
return pc;
}
protected PortletControl getControl(Control control, PortletEntry entry)
{
PortletControl pc = null;
if (control != null)
{
pc = getControl(control.getName());
pc.getConfig().getInitParameters().putAll(getParameters(control));
}
else
{
org.apache.jetspeed.om.registry.Parameter dftPortletCtrl =
entry.getParameter("_control");
if (dftPortletCtrl != null)
{
pc = getControl(dftPortletCtrl.getValue());
}
else if (defaultControl != null)
{
pc = getControl(this.defaultControl);
}
}
return pc;
}
/**
* Instanciates a PortletController based on a Registry entry, if available
* or directly from a classname.
*
* @param name a PortletController name available in the registry or a classname
* @return the created PortletController
*/
public PortletController getController(String name)
{
PortletController pc = null;
PortletControllerEntry entry = null;
if (name != null)
{
entry = (PortletControllerEntry) Registry.getEntry(Registry.PORTLET_CONTROLLER, name);
}
Map params = null;
try
{
if (entry == null)
{
if (name != null)
{
pc = (PortletController) Class.forName(name).newInstance();
params = new Hashtable();
}
}
else
{
pc = (PortletController) Class.forName(entry.getClassname()).newInstance();
params = entry.getParameterMap();
}
}
catch (Exception e)
{
Log.error("Unable to instanciate controller " + name + ", using default");
}
if ((pc == null) && (defaultController != null) && (!defaultController.equals(name)))
{
return getController(defaultController);
}
PortletControllerConfig pcConf = new BasePortletControllerConfig();
pcConf.setName(name);
pcConf.setInitParameters(params);
pc.setConfig(pcConf);
pc.init();
return pc;
}
/**
* Instantiates a PortletController based on a PSML Controller object
*
* @param controller the PSML controller object
* @return the created PortletController
*/
public PortletController getController(Controller controller)
{
PortletController pc = null;
if (controller != null)
{
pc = getController(controller.getName());
pc.getConfig().getInitParameters().putAll(getParameters(controller));
}
else
{
if (defaultController != null)
{
pc = getController(this.defaultController);
}
}
pc.init();
return pc;
}
/**
* Create a PortletSkin object based on a Registry skin name
*
* @param name the registry SkinEntry name
* @return the new PortletSkin object
*/
public PortletSkin getSkin(String name)
{
BasePortletSkin result = new BasePortletSkin();
SkinEntry entry = null;
if (name != null)
{
entry = (SkinEntry) Registry.getEntry(Registry.SKIN, name);
}
// either we don't have any skin defined, the skin reference is null
// or the skin reference is invalid, in all case, retrieve the default
// skin entry
if (entry == null)
{
entry = (SkinEntry) Registry.getEntry(Registry.SKIN, this.defaultSkin);
}
if (entry != null)
{
// build the PortletSkin object
result.setName(entry.getName());
result.putAll(entry.getParameterMap());
}
// Make the skin aware of what the user agent is capable of.
JetspeedRunDataService jrds =
(JetspeedRunDataService) ServiceUtil.getServiceByName(RunDataService.SERVICE_NAME);
JetspeedRunData jData = jrds.getCurrentRunData();
if(jData != null)
{
result.setCapabilityMap(jData.getCapability());
}
return result;
}
/**
* Create a PortletSkin object based on PSML skin description
*
* @param skin the PSML Skin object
* @return the new PortletSkin object
*/
public PortletSkin getSkin(Skin skin)
{
PortletSkin result = null;
String name = null;
if (skin != null)
{
name = skin.getName();
// create the PortletSkin corresponding to this entry
result = getSkin(name);
// override the values with the locally defined properties
result.putAll(getParameters(skin));
}
return result;
}
/**
* Creates a PortletSet from a PSML portlets description
*
* @param portlets the PSML portlet set description
* @return a new instance of PortletSet
*/
public PortletSet getSet(Portlets portlets)
{
VariableInteger lastID = new VariableInteger(0);
return getSet(portlets, new VariableInteger(0));
}
/**
* Creates a PortletSet from a PSML portlets description, updating
* the portletset name based on its position within the tree
*
* @param portlets the PSML portlet set description
* @param count the portletset number within the complete tree
* @return a new instance of PortletSet
*/
protected PortletSet getSet(Portlets portlets, VariableInteger theCount)
{
// Create a new BasePortletSet to handle the portlets
BasePortletSet set = new BasePortletSet();
PortletController controller = getController(portlets.getController());
set.setController(controller);
String name = portlets.getName();
if (name != null)
{
set.setName(name);
}
else
set.setName(String.valueOf(theCount.getValue()));
set.setID(portlets.getId());
theCount.setValue(theCount.getValue() + 1);
//FIXME: this sucks ! we should either associate the portlet set
//with its portlets peer or set the porpoerties directly on the portlet
//set object
//Unfortunately, this would change the API too drastically for now...
set.setPortletConfig(getPortletConfig(portlets));
// Add all sub portlet sets in the main set
// Portlets[] subsets = portlets.getPortlets();
// for (int i=0; i < subsets.length; i++ )
for (Iterator it = portlets.getPortletsIterator(); it.hasNext();)
{
Portlets subset = (Portlets) it.next();
// Set this subset's parent Portlets collection.
subset.setParentPortlets(portlets);
Map constraints = getParameters(subset.getLayout());
int position = getPosition(subset.getLayout());
set.addPortlet(
getSet(subset, theCount),
controller.getConstraints(constraints),
position);
}
// Populate the PortletSet with Portlets
// Entry[] entries = portlets.getEntry();
// for( int i = 0; i < entries.length; ++i )
for (Iterator eit = portlets.getEntriesIterator(); eit.hasNext();)
{
try
{
Entry psmlEntry = (Entry) eit.next();
PortletEntry entry =
(PortletEntry) Registry.getEntry(Registry.PORTLET, psmlEntry.getParent());
if (entry != null)
{
Portlet p = PortletFactory.getPortlet(psmlEntry);
if (p != null)
{
Map constraints = getParameters(psmlEntry.getLayout());
int position = getPosition(psmlEntry.getLayout());
PortletControl control = getControl(psmlEntry.getControl(), entry);
set.addPortlet(
initControl(control, p),
controller.getConstraints(constraints),
position);
}
}
else
{
Log.error(
" The portlet "
+ psmlEntry.getParent()
+ " does not exist in the Registry ");
continue;
}
}
catch (JetspeedException e)
{
Log.error(e);
continue;
}
}
// Decorate with a control if required and return
if (portlets.getControl() != null)
{
PortletControl control = getControl(portlets.getControl());
return initControl(control, set);
}
set.sortPortletSet();
// Or return the set
return set;
}
/**
* Associates a PortletControl wit an existing Portlet and
* returns the Control
*
* @param pc the existing PortletControl
* @param portlet the existing Portlet to be associated with the control
* @return first PortletControl associated with the portlet
*/
protected PortletControl initControl(PortletControl pc, Portlet portlet)
{
if (portlet == null)
{
throw new IllegalArgumentException("Portlet not specified");
}
if (pc == null)
{
throw new IllegalArgumentException("PortletControl not specified");
}
pc.init(portlet);
return pc;
}
/**
Given a PSML Portlets, get the value of what its PortletConfig would be.
@param entry the Portlets containing the config
@return the newly created PortletConfig object
*/
protected PortletConfig getPortletConfig(Portlets portlets)
{
PortletConfig pc = new BasePortletConfig();
pc.setName(portlets.getName());
pc.setInitParameters(getParameters(portlets));
//Invocation of new skin-locating algorithim
pc.setPortletSkin(getSkin(findSkin(portlets)));
pc.setSecurityRef(portlets.getSecurityRef());
pc.setMetainfo(getMetaData(portlets));
return pc;
}
/**
* Fetches the parameters out of a PSML Portlets entry
*
* @param portlets the Portlets entry to check for parameters
* @return a Map containing the parameters names/values, an empty Dictionary
* is returned if there are no parameters
*/
protected static Map getParameters(Portlets portlets)
{
Hashtable hash = new Hashtable();
if (portlets != null)
{
Parameter[] props = portlets.getParameter();
for (int i = 0; i < props.length; ++i)
{
hash.put(props[i].getName(), props[i].getValue());
}
}
return hash;
}
/**
* Retrieves the parameters from a PSML Control object
*
* @param control the PSML object to explore
* @return a Map of the existing control parameters or an empty map
*/
protected static Map getParameters(Control control)
{
Hashtable hash = new Hashtable();
if (control != null)
{
Parameter[] params = control.getParameter();
for (int i = 0; i < params.length; i++)
{
hash.put(params[i].getName(), params[i].getValue());
}
}
return hash;
}
/**
* Retrieves the parameters from a PSML Controller object
*
* @param controller the PSML object to explore
* @return a Map of the existing controller parameters or an empty map
*/
protected static Map getParameters(Controller controller)
{
Hashtable hash = new Hashtable();
if (controller != null)
{
Parameter[] params = controller.getParameter();
for (int i = 0; i < params.length; i++)
{
hash.put(params[i].getName(), params[i].getValue());
}
}
return hash;
}
/**
* Retrieves a parameter Map from an array of PSML Layout object
*
* @param layout the Layout object to use
* @return a Map containing the names/values, an empty map
* is returned if there are no properties
*/
protected static Map getParameters(Layout layout)
{
Hashtable hash = new Hashtable();
if (layout != null)
{
Parameter[] props = layout.getParameter();
for (int i = 0; i < props.length; ++i)
{
hash.put(props[i].getName(), props[i].getValue());
}
}
return hash;
}
/**
* Retrieves a parameter Map from a PSML skin object
*
* @param skin the Skin object to use
* @return a Map containing the names/values, an empty map
* is returned if there are no properties
*/
protected static Map getParameters(Skin skin)
{
Hashtable hash = new Hashtable();
if (skin != null)
{
Parameter[] props = skin.getParameter();
for (int i = 0; i < props.length; ++i)
{
hash.put(props[i].getName(), props[i].getValue());
}
}
return hash;
}
/**
Create a MetaData object from a PSML Metainfo object
@param meta the Metainfo to copy
@return the new MetaData object, empty if meta is null
*/
protected static MetaData getMetaData(Portlets portlets)
{
MetaData data = new MetaData();
MetaInfo meta = portlets.getMetaInfo();
if (meta != null)
{
if (meta.getTitle() != null)
{
data.setTitle(meta.getTitle());
}
if (meta.getDescription() != null)
{
data.setDescription(meta.getDescription());
}
if (meta.getImage() != null)
{
data.setImage(meta.getImage());
}
}
return data;
}
/**
* Get the position value in a Layout object
*
* @param layout the Layout object to use
*
* @return the defined position or -1 if undefined
*/
protected static int getPosition(Layout layout)
{
int pos = -1;
try
{
pos = (int) layout.getPosition();
}
catch (RuntimeException e)
{
// either layout is null or the position isn't an integer
// keep the default value
}
return pos;
}
protected static class VariableInteger
{
int value;
public VariableInteger(int value)
{
this.value = value;
}
public int getValue()
{
return this.value;
}
public void setValue(int value)
{
this.value = value;
}
}
/**
* Given a locator String path, returns a Portlets collecton
*
* @param locatorPath ProfileLocator resource path identifier
* @return a portlets collection from the PSML resource
*/
public Portlets getReference(String locatorPath)
{
ProfileLocator locator = Profiler.createLocator();
locator.createFromPath(locatorPath);
String id = locator.getId();
try
{
Profile profile = Profiler.getProfile(locator);
PSMLDocument doc = profile.getDocument();
if (doc == null)
{
return null;
}
Portlets portlets = doc.getPortlets();
return portlets;
}
catch (Exception e)
{
Log.error(e);
return null;
}
}
/**
* Helps locate a skin, recursively if neccesary.
* <ul>
* <li>First: return the name of the skin defined for this <code>Portlets</code>
* collection.</li>
* <li> If the this <code>Portlets</code> collection has no skin defined, it's
* parent is checked, then it's parent's parent and so on until either a skin
* is found.</li>
* <li> If the previous two attempts fail the, the system default skin is used</li>
* @param Portlets portlets Portlets collection whose skin needs to be located.
*/
protected String findSkin(Portlets portlets)
{
if (portlets.getSkin() != null)
{
return portlets.getSkin().getName();
}
else if (portlets.getParentPortlets() != null)
{
return findSkin(portlets.getParentPortlets());
}
else
{
return this.defaultSkin;
}
}
/**
* Gets default security ref based on the profile type (user|role|group). Returns
* null if no default is defined.
*
* @param profile
* @return default security reference
*/
public SecurityReference getDefaultSecurityRef(Profile profile)
{
String type = null;
if (profile.getUserName() != null)
{
if (profile.getAnonymous())
{
type = Profiler.PARAM_ANON;
}
else
{
type = Profiler.PARAM_USER;
}
}
else if (profile.getRoleName() != null)
{
type = Profiler.PARAM_ROLE;
}
else if (profile.getGroupName() != null)
{
type = Profiler.PARAM_GROUP;
}
return getDefaultSecurityRef(type);
}
/**
* Gets default security ref based on the profile type (user|role|group). Returns
* null if no default is defined.
*
* @param type of entity to return default security ref for
* @return default security reference
*/
public SecurityReference getDefaultSecurityRef(String type)
{
BaseSecurityReference result = null;
SecurityEntry entry = null;
String defaultRef = null;
if (type.equals(Profiler.PARAM_USER))
{
defaultRef = this.defaultUserSecurityRef;
}
else if (type.equals(Profiler.PARAM_ANON))
{
defaultRef = this.defaultAnonSecurityRef;
}
else if (type.equals(Profiler.PARAM_ROLE))
{
defaultRef = this.defaultRoleSecurityRef;
}
else if (type.equals(Profiler.PARAM_GROUP))
{
defaultRef = this.defaultGroupSecurityRef;
}
entry = (SecurityEntry) Registry.getEntry(Registry.SECURITY, defaultRef);
if (Log.getLogger().isDebugEnabled())
{
Log.debug(
"JetspeedPortalToolkit: default security for type: " + type + " is " + defaultRef);
}
if (entry != null)
{
result = new BaseSecurityReference();
result.setParent(entry.getName());
if (Log.getLogger().isDebugEnabled())
{
Log.debug(
"JetspeedPortalToolkit: default security for type: "
+ type
+ " was set to "
+ entry.getName());
}
}
return result;
}
}