Proposed fix for:
Bug 14909 Skin Resolution Algorithm Does Not Fallback Correctly .
Attached is changes to fix issue with portlet skin use.
/services/portaltoolkit/JetspeedPortalToolkitService.java
The software change fulfills the Jetspeed requirements to
>>>>- first check the current portlet(set), if no skin then
>>>> - fallback to its parent, if no skin then
>>>> - fallback to global setting
I ran the following tests.
1) no skin ref in PSML
RESULT: uses default skin
2) skin set a top level, no skin setting for children portlets
RESULT: children portlets use the top level skin setting
3) skin set at top level, and skin set in child portlet
RESULT: uses skin assigned for child portlet
4) no skin at top level, and skin set in child portlet
RESULT: uses skin assigned for child portlet, and all other portlets use
default
---- Begin change description -----
protected PortletConfig getPortletConfig( Portlets portlets )
{
PortletConfig pc = new BasePortletConfig();
pc.setName( portlets.getName() );
pc.setInitParameters( getParameters( portlets ) );
if (portlets.getSkin()!=null)
{
pc.setPortletSkin( getSkin( portlets.getSkin() ) );
}
- else
- {
- pc.setPortletSkin( getSkin( this.defaultSkin ) );
- }
--- End change description -----
--
Glen Carl
[EMAIL PROTECTED]
/* ====================================================================
* 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.portaltoolkit;
//jetspeed stuff
import org.apache.jetspeed.portal.*;
import org.apache.jetspeed.om.profile.*;
import org.apache.jetspeed.services.Profiler;
import org.apache.jetspeed.services.PortalToolkit;
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.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.util.Log;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.ServletConfig;
/**
* Simple implementation of the PortalFactoryService.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Rapha�l Luta</a>
* @author <a href="mailto:[EMAIL PROTECTED]">David Sean Taylor</a>
*
* @version $Id: JetspeedPortalToolkitService.java,v 1.3 2002/12/13 22:07:01 gcarl 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;
/**
* 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");
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;
}
/**
* Instanciates 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());
}
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();
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 ) );
if (portlets.getSkin()!=null)
{
pc.setPortletSkin( getSkin( portlets.getSkin() ) );
}
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;
}
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>