You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by rg...@apache.org on 2004/11/07 23:26:17 UTC

svn commit: rev 56872 - in cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal: event/aspect/impl event/impl impl

Author: rgoers
Date: Sun Nov  7 14:26:17 2004
New Revision: 56872

Added:
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/event/aspect/impl/PageLabelEventAspect.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/event/impl/PageLabelEventConverter.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/impl/PageLabelLinkService.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/impl/PageLabelManager.java
Log:
bug 31857 - Add Portal PageLabels


Added: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/event/aspect/impl/PageLabelEventAspect.java
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/event/aspect/impl/PageLabelEventAspect.java	Sun Nov  7 14:26:17 2004
@@ -0,0 +1,97 @@
+/*
+ * Copyright 1999-2002,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.cocoon.portal.event.aspect.impl;
+
+import java.util.Iterator;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.portal.PortalService;
+import org.apache.cocoon.portal.impl.PageLabelManager;
+import org.apache.cocoon.portal.event.Event;
+import org.apache.cocoon.portal.event.Publisher;
+import org.apache.cocoon.portal.event.aspect.EventAspect;
+import org.apache.cocoon.portal.event.aspect.EventAspectContext;
+
+/**
+ * Converts links generated by the PageLabelLinkService into events and publishes them.
+ * Used in conjunction with the PageLabelLinkService, links generated from the layout
+ * portal.xml will be based upon the names of the named items.
+ *
+ * @author Ralph Goers
+ *
+ * @version CVS $Id:  $
+ */
+public class PageLabelEventAspect extends AbstractLogEnabled
+	implements EventAspect, ThreadSafe, Serviceable, Disposable {
+
+    protected ServiceManager manager;
+
+    protected PageLabelManager labelManager;
+
+    public void service(ServiceManager manager) throws ServiceException
+    {
+        this.manager = manager;
+        this.labelManager = (PageLabelManager)manager.lookup(PageLabelManager.ROLE);
+    }
+
+    public void dispose()
+    {
+        if (this.manager != null) {
+            if (this.labelManager != null) {
+                this.manager.release(this.labelManager);
+                this.labelManager = null;
+            }
+            this.manager = null;
+        }
+    }
+
+	/* (non-Javadoc)
+	 * @see org.apache.cocoon.portal.event.aspect.EventAspect#process(org.apache.cocoon.portal.event.aspect.EventAspectContext, org.apache.cocoon.portal.PortalService)
+	 */
+	public void process(EventAspectContext context, PortalService service) {
+        if (this.labelManager != null) {
+            final Publisher publisher = context.getEventPublisher();
+            final Request request = ObjectModelHelper.getRequest(context.getObjectModel());
+            final String parameterName = this.labelManager.getRequestParameterName();
+
+            String label = request.getParameter(parameterName);
+            // The pageLabel must be single valued
+            if (label != null) {
+                String previous = this.labelManager.getPreviousLabel();
+                if (previous != null && previous.equals(label)) {
+                    // Already on this page. Don't publish the pageLabel events
+                } else {
+                    Iterator iter = this.labelManager.getPageLabelEvents(label).iterator();
+                    // Publish all the events for this page label.
+                    while (iter.hasNext()) {
+                        Event event = (Event) iter.next();
+                        publisher.publish(event);
+                    }
+            //        return;
+                }
+            }
+        }
+
+        context.invokeNext( service );
+	}
+}
\ No newline at end of file

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/event/impl/PageLabelEventConverter.java
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/event/impl/PageLabelEventConverter.java	Sun Nov  7 14:26:17 2004
@@ -0,0 +1,123 @@
+/*
+ * Copyright 1999-2002,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.cocoon.portal.event.impl;
+
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.cocoon.portal.impl.PageLabelManager;
+import org.apache.cocoon.portal.event.Event;
+import org.apache.cocoon.portal.event.EventConverter;
+
+/**
+ * Convert events from and into strings.
+ * @author Ralph Goers
+ *
+ * @version CVS $Id:  $
+ */
+public class PageLabelEventConverter extends AbstractLogEnabled
+    implements EventConverter, Serviceable, ThreadSafe {
+
+    protected PageLabelManager labelManager;
+
+    private static final String ENCODE = "&ENCODE";
+    private static final String DECODE = "&DECODE";
+
+    protected ServiceManager manager;
+
+    /* (non-Javadoc)
+    * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+    */
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+        this.labelManager = (PageLabelManager)manager.lookup(PageLabelManager.ROLE);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.portal.event.EventConverter#encode(org.apache.cocoon.portal.event.Event)
+     */
+    public String encode(Event event) {
+
+        String pageLabel = this.labelManager.getCurrentLabel();
+        if (pageLabel == null) {
+            pageLabel = "";
+        }
+        Map map = this.labelManager.getPageEventMap();
+        String encode = pageLabel + ENCODE;
+        List list = (List)map.get(encode);
+
+        if (null == list) {
+            list = new ArrayList();
+            map.put(encode, list);
+        }
+
+        int index = list.indexOf(event);
+        if ( index == -1 ) {
+          list.add(event);
+          index = list.size() - 1;
+        }
+        return String.valueOf(index);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.cocoon.portal.event.EventConverter#decode(java.lang.String)
+     */
+    public Event decode(String value) {
+        String pageLabel = this.labelManager.getCurrentLabel();
+        if (pageLabel == null) {
+            pageLabel = "";
+        }
+        Map map = this.labelManager.getPageEventMap();
+        List list = (List)map.get(pageLabel + DECODE);
+
+        if ( null != list ) {
+            int index = new Integer(value).intValue();
+            if (index < list.size()) {
+                return (Event)list.get(index);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+    * @see org.apache.cocoon.portal.event.EventConverter#start()
+    */
+    public void start() {
+        String label = this.labelManager.setCurrentLabel();
+        Map map = this.labelManager.getPageEventMap();
+        String encode = label + ENCODE;
+        String decode = label + DECODE;
+
+        List list = (List)map.get(encode);
+
+        if (null != list) {
+            map.put(decode, list);
+            map.remove(encode);
+        }
+    }
+
+    /* (non-Javadoc)
+    * @see org.apache.cocoon.portal.event.EventConverter#finish()
+    */
+    public void finish() {
+    }
+}
\ No newline at end of file

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/impl/PageLabelLinkService.java
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/impl/PageLabelLinkService.java	Sun Nov  7 14:26:17 2004
@@ -0,0 +1,230 @@
+/*
+ * Copyright 1999-2002,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.cocoon.portal.impl;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.cocoon.portal.event.Event;
+import org.apache.cocoon.portal.event.impl.ChangeAspectDataEvent;
+import org.apache.cocoon.portal.layout.CompositeLayout;
+import org.apache.cocoon.portal.layout.Item;
+import org.apache.cocoon.portal.layout.NamedItem;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.excalibur.source.SourceUtil;
+
+/**
+ * The PageLabelLinkService generates links for named items defined in the layout portal.xml.
+ * Links for other entities are passed to the DefaultLinkService to be resolved.
+ *
+ * @author Ralph Goers
+ *
+ * @version CVS $Id: $
+ */
+public class PageLabelLinkService extends DefaultLinkService {
+
+    protected String apectName;
+
+    /** The label manager */
+    protected PageLabelManager labelManager;
+
+    /* (non-Javadoc)
+    * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+    */
+    public void service(ServiceManager manager) throws ServiceException {
+        super.service(manager);
+        this.labelManager = (PageLabelManager)this.manager.lookup(PageLabelManager.ROLE);
+    }
+
+    /**
+     * Get the uri for the coplet containing event
+     *
+     * @param event The event to find
+     * @return A URI
+     */
+    public String getLinkURI(Event event) {
+        if (event == null) {
+            return this.getRefreshLinkURI();
+        }
+        if (this.labelManager == null) {
+            super.getLinkURI(event);
+        }
+
+        String requestParameterName = this.labelManager.getRequestParameterName();
+
+        if (event instanceof ChangeAspectDataEvent &&
+            ((ChangeAspectDataEvent) event).getTarget() instanceof CompositeLayout) {
+
+            ChangeAspectDataEvent e = (ChangeAspectDataEvent)event;
+            CompositeLayout layout = (CompositeLayout)e.getTarget();
+            int i = ((Integer)e.getData()).intValue();
+
+            Item item = layout.getItem(i);
+            if (item instanceof NamedItem) {
+                StringBuffer key = new StringBuffer("");
+                getKey(item, key);
+
+                if (this.labelManager.getPageLabelEvents(key.toString()) != null) {
+                    final Info info = this.getInfo();
+                    boolean hasParams = info.hasParameters;
+                    final StringBuffer buffer = new StringBuffer(info.linkBase.toString());
+                    if (hasParams) {
+                        buffer.append('&');
+                    }
+                    else {
+                        buffer.append('?');
+                    }
+                    buffer.append(requestParameterName).append('=')
+                        .append(SourceUtil.encode(key.toString()));
+                    return buffer.toString();
+                }
+            }
+        }
+
+        String label = this.labelManager.getCurrentLabel();
+
+        return getLink(super.getLinkURI(event), requestParameterName, label);
+    }
+
+    /**
+     * Get the uri for this coplet containing the additional events.
+     *
+     * @param events The events that will be processed by the generated uri.
+     * @return A URI
+     */
+    public String getLinkURI(List events)
+    {
+        if (events == null || events.size() == 0) {
+            return this.getRefreshLinkURI();
+        }
+        if (this.labelManager == null) {
+            super.getLinkURI(events);
+        }
+
+        String requestParameterName = this.labelManager.getRequestParameterName();
+        final Info info = this.getInfo();
+        final StringBuffer buffer = new StringBuffer(info.linkBase.toString());
+        boolean hasParams = info.hasParameters;
+        Iterator iter = events.iterator();
+        StringBuffer value = new StringBuffer("");
+
+        while (iter.hasNext())
+        {
+            Event event = (Event)iter.next();
+
+            if (event instanceof ChangeAspectDataEvent &&
+                ((ChangeAspectDataEvent) event).getTarget() instanceof CompositeLayout) {
+
+                ChangeAspectDataEvent e = (ChangeAspectDataEvent) event;
+                CompositeLayout layout = (CompositeLayout) e.getTarget();
+                int i = ((Integer) e.getData()).intValue();
+
+                Item item = layout.getItem(i);
+                if (value.length() > 0) {
+                    value.append('.');
+                }
+                if (item instanceof NamedItem) {
+                    value.append(((NamedItem)item).getName());
+                }
+                else {
+                    value.append(Integer.toString(i));
+                }
+            }
+            else {
+                String label = this.labelManager.getCurrentLabel();
+
+                return getLink(super.getLinkURI(events), requestParameterName, label);
+            }
+        }
+
+        if (value.length() > 0 && this.labelManager.getPageLabelEvents(value.toString()) != null) {
+            if (hasParams) {
+                buffer.append('&');
+            }
+            else {
+                buffer.append('?');
+            }
+            buffer.append(requestParameterName).append('=')
+                .append(SourceUtil.encode(value.toString()));
+
+            return buffer.toString();
+        }
+
+        String label = this.labelManager.getCurrentLabel();
+
+        return getLink(super.getLinkURI(events), requestParameterName, label);
+    }
+
+    /* (non-Javadoc)
+    * @see org.apache.avalon.framework.activity.Disposable#dispose()
+    */
+    public void dispose() {
+        if (this.manager != null) {
+            if (this.labelManager != null) {
+                this.manager.release(this.labelManager);
+                this.labelManager = null;
+            }
+        }
+        super.dispose();
+    }
+
+    /*
+     * Generates the page label.
+     * @param item An Item.
+     * @param key The StringBuffer in which to create the page label.
+     */
+    private void getKey(Item item, StringBuffer key) {
+        CompositeLayout parentLayout = item.getParent();
+        Item parentItem = parentLayout.getParent();
+
+        if (parentItem != null) {
+            getKey(parentItem, key);
+        }
+
+        if (key.length() > 0) {
+            key.append('.');
+        }
+        if (item instanceof NamedItem) {
+            key.append(((NamedItem) item).getName());
+        }
+        else {
+            key.append(parentLayout.getItems().indexOf(item));
+        }
+    }
+
+    /*
+     * Append the page label to the link.
+     * @param link The link to add the label to.
+     * @param parmName The request parameter name.
+     * @param label The page label.
+     * @return The modified link.
+     */
+    private String getLink(String link, String parmName, String label)
+    {
+        if (label == null) {
+            return link;
+        }
+        StringBuffer uri = new StringBuffer(link);
+        if (link.indexOf('?') >= 0) {
+            uri.append('&');
+        } else {
+            uri.append('?');
+        }
+        uri.append(parmName).append('=').append(SourceUtil.encode(label));
+        return uri.toString();
+    }
+}
\ No newline at end of file

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/impl/PageLabelManager.java
==============================================================================
--- (empty file)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/impl/PageLabelManager.java	Sun Nov  7 14:26:17 2004
@@ -0,0 +1,305 @@
+/*
+ * Copyright 1999-2002,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.cocoon.portal.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.cocoon.portal.PortalService;
+import org.apache.cocoon.portal.layout.Layout;
+import org.apache.cocoon.portal.layout.CompositeLayout;
+import org.apache.cocoon.portal.layout.Item;
+import org.apache.cocoon.portal.layout.NamedItem;
+import org.apache.cocoon.portal.event.impl.ChangeAspectDataEvent;
+import org.apache.cocoon.util.HashMap;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.components.ContextHelper;
+
+/**
+ * Manages the various activities required for page labels.
+ *
+ * The name of the request parameter used to identify the page labelmay be configured
+ * here by declaring
+ * <br><parameter-name><i>request-parm-name</i></parameter-name><br>
+ * in the configuration for this component. The default request parameter name is
+ * 'pageLabel'.
+ * @author Ralph Goers
+ *
+ * @version CVS $Id: $
+ */
+public class PageLabelManager
+    extends AbstractLogEnabled
+    implements ThreadSafe, Serviceable, Configurable, Contextualizable, Component {
+
+    public static final String ROLE = PageLabelManager.class.getName();
+
+    /** The service manager */
+    protected ServiceManager manager;
+    /** The cocoon context */
+    protected Context context;
+    protected String aspectName = null;
+    private String requestParameterName;
+    private boolean nonStickyTabs;
+
+    protected static final String LABEL_ARRAY = PageLabelManager.class.getName() + "A";
+    protected static final String LABEL_MAP = PageLabelManager.class.getName() + "M";
+    protected static final String EVENT_MAP = PageLabelManager.class.getName() + "E";
+    private static final String DEFAULT_REQUEST_PARAMETER_NAME = "pageLabel";
+
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    /* (non-Javadoc)
+    * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+    */
+    public void configure(Configuration config)
+    {
+        this.requestParameterName =
+            config.getChild("parameterName").getValue(DEFAULT_REQUEST_PARAMETER_NAME);
+        this.aspectName = config.getChild("aspectName").getValue("tab");
+        this.nonStickyTabs =
+            Boolean.valueOf(config.getChild("nonStickyTabs").getValue("false")).booleanValue();
+    }
+
+    /* (non-Javadoc)
+    * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+    */
+    public void contextualize(Context context) throws ContextException {
+        this.context = context;
+    }
+
+    /**
+     * Return the current page label.
+     * @return The current page label.
+     */
+    public String getCurrentLabel() {
+        String[] labels = getLabels();
+
+        return labels[0];
+    }
+
+    /**
+     * Return the page label from the previous request.
+     * @return The previous page label.
+     */
+    public String getPreviousLabel() {
+        String[] labels = getLabels();
+
+        return labels[1];
+    }
+
+    /**
+     * Sets the current page label.
+     * @return The current page label.
+     */
+    public String  setCurrentLabel() {
+        final Request request =
+            ObjectModelHelper.getRequest(ContextHelper.getObjectModel(this.context));
+        String value = request.getParameter(this.requestParameterName);
+        String[] labels = getLabels();
+
+        if (value != null) {
+            labels[1] = labels[0];
+            labels[0] = value;
+        }
+        return labels[0];
+    }
+
+    /**
+     * Returns the request parameter being used to identify the page label.
+     * @return A String containing the request parameter name used for page labels.
+     */
+    public String getRequestParameterName() {
+        return this.requestParameterName;
+    }
+
+
+    /**
+     * Return the Map that contains events for all the page labels.
+     * @return The Map to use for converting events to and from urls.
+     */
+    public Map getPageEventMap()
+    {
+        PortalService service = null;
+        try {
+            service = (PortalService) this.manager.lookup(PortalService.ROLE);
+            Map map = (Map) service.getAttribute(EVENT_MAP);
+            if (null == map) {
+                map = new HashMap();
+                service.setAttribute(EVENT_MAP, map);
+            }
+
+            return map;
+        }
+        catch (ServiceException ce) {
+            throw new CascadingRuntimeException("Unable to lookup component.", ce);
+        }
+        finally {
+            this.manager.release(service);
+        }
+    }
+
+    /**
+     * Retrieve the events associated with the specified page label.
+     *
+     * @param pageLabel The label to retrieve the events for.
+     * @return A List containing all the events associated with the page label in the order they
+     *         should occur.
+     */
+    public List getPageLabelEvents(String pageLabel) {
+        PortalService service = null;
+        try {
+            service = (PortalService) this.manager.lookup(PortalService.ROLE);
+            Map map = (Map) service.getAttribute(LABEL_MAP);
+            if (null == map) {
+                map = initializeLabels(service);
+                service.setAttribute(LABEL_MAP, map);
+            }
+
+            List list = (List) map.get(pageLabel);
+
+            if (list == null) {
+                list = new ArrayList();
+                map.put(pageLabel, list);
+            }
+
+            return list;
+        }
+        catch (ServiceException ce) {
+            throw new CascadingRuntimeException("Unable to lookup component.", ce);
+        }
+        finally {
+            this.manager.release(service);
+        }
+    }
+
+    /*
+     * Return the array containing the current and previous labels.
+     */
+    private String[] getLabels() {
+        PortalService service = null;
+        try {
+            service = (PortalService) this.manager.lookup(PortalService.ROLE);
+            String[] labels = (String[]) service.getAttribute(LABEL_ARRAY);
+            if (null == labels) {
+                labels = new String[2];
+                service.setAttribute(LABEL_ARRAY, labels);
+            }
+            return labels;
+        }
+        catch (ServiceException ce) {
+            throw new CascadingRuntimeException("Unable to lookup component.", ce);
+        }
+        finally {
+            this.manager.release(service);
+        }
+    }
+
+    /**
+     * Create the page label event map and return it.
+     *
+     * @param service The portal service
+     * @return The page label map.
+     */
+    private Map initializeLabels(PortalService service) {
+        Map map = new HashMap();
+
+        Layout portalLayout = service.getEntryLayout(null);
+        if (portalLayout == null) {
+            portalLayout =
+                service.getComponentManager().getProfileManager().getPortalLayout(null, null);
+        }
+
+        if (portalLayout instanceof CompositeLayout) {
+            populate((CompositeLayout) portalLayout, map, "", new ArrayList());
+        }
+
+        return map;
+    }
+
+
+    /**
+     * Populate the event map
+     *
+     * @param layout
+     * @param map
+     * @param name
+     * @param parentEvents
+     */
+    private List populate(CompositeLayout layout, Map map, String name, List parentEvents) {
+        List lhList = null;
+        for (int j = 0; j < layout.getSize(); j++) {
+            Item tab = layout.getItem(j);
+            ChangeAspectDataEvent event =
+                new ChangeAspectDataEvent(layout, this.aspectName, new Integer(j));
+            StringBuffer label = new StringBuffer(name);
+            if (label.length() > 0) {
+                label.append(".");
+            }
+            label.append((tab instanceof NamedItem) ? ((NamedItem) tab).getName() :
+                Integer.toString(j));
+            List events = new ArrayList(parentEvents);
+            events.add(event);
+            Layout child = tab.getLayout();
+            List allEvents = null;
+            if (child != null && child instanceof CompositeLayout) {
+                allEvents = populate((CompositeLayout) child, map, label.toString(), events);
+            }
+            if (this.nonStickyTabs) {
+                // With non-sticky tabs the non-leaf nodes always display
+                // the left-most child tabs
+                if (lhList == null)
+                {
+                    if (allEvents != null)
+                    {
+                        lhList = allEvents;
+                    }
+                    else
+                    {
+                        lhList = events;
+                    }
+                }
+                if (allEvents != null) {
+                    map.put(label.toString(), allEvents);
+                } else {
+                    map.put(label.toString(), events);
+                }
+            } else {
+                map.put(label.toString(), events);
+            }
+        }
+        return lhList;
+    }
+}
\ No newline at end of file