/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.webapps.portal.components; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.activity.Disposable; import org.apache.avalon.framework.component.Component; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.component.Recomposable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.configuration.ConfigurationException; 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.cocoon.ProcessingException; import org.apache.cocoon.components.ContextHelper; import org.apache.cocoon.components.sax.XMLDeserializer; import org.apache.cocoon.components.source.SourceUtil; import org.apache.cocoon.environment.CocoonRunnable; import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.Response; import org.apache.cocoon.environment.Session; import org.apache.cocoon.webapps.authentication.AuthenticationManager; import org.apache.cocoon.webapps.authentication.user.RequestState; import org.apache.cocoon.webapps.portal.PortalConstants; import org.apache.cocoon.webapps.session.ContextManager; import org.apache.cocoon.webapps.session.MediaManager; import org.apache.cocoon.webapps.session.SessionManager; import org.apache.cocoon.webapps.session.TransactionManager; import org.apache.cocoon.webapps.session.context.SessionContext; import org.apache.cocoon.webapps.session.xml.XMLUtil; import org.apache.cocoon.xml.IncludeXMLConsumer; import org.apache.cocoon.xml.XMLConsumer; import org.apache.cocoon.xml.XMLUtils; import org.apache.cocoon.xml.dom.DOMUtil; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.apache.excalibur.source.SourceParameters; import org.apache.excalibur.source.SourceResolver; import org.apache.excalibur.store.Store; import org.apache.excalibur.xml.xpath.XPathProcessor; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; /** * This is the basis portal component * * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a> * @version CVS $Id$ */ public final class PortalManagerImpl extends AbstractLogEnabled implements Disposable, Composable, Recomposable, Recyclable, Contextualizable, Component, PortalManager { /** The cache (store) for the profiles */ private Store profileStore; /** The authenticationManager */ private AuthenticationManager authenticationManager; /** The media manager */ private MediaManager mediaManager; /** The XPath Processor */ private XPathProcessor xpathProcessor; /** The session manager */ private SessionManager sessionManager; /** The Context manager */ private ContextManager contextManager; /** The transaction manager */ private TransactionManager transactionManager; /** The component manager */ protected ComponentManager manager; /** The current source resolver */ protected SourceResolver resolver; /** The context */ protected Context componentContext; /** Are we already setup for this request? */ protected boolean initialized = false; /* (non-Javadoc) * @see org.apache.avalon.excalibur.pool.Recyclable#recycle() */ public void recycle() { if (this.manager != null) { this.manager.release(this.profileStore); this.manager.release( (Component)this.authenticationManager); this.manager.release( (Component)this.mediaManager); this.manager.release( (Component)this.sessionManager); this.manager.release( (Component)this.contextManager); this.manager.release( (Component)this.transactionManager); this.profileStore = null; this.authenticationManager = null; this.mediaManager = null; this.transactionManager = null; this.sessionManager = null; this.contextManager = null; } this.initialized = false; } /** * Get the current authentication state */ protected RequestState getRequestState() { AuthenticationManager authManager = null; try { authManager = (AuthenticationManager)this.manager.lookup(AuthenticationManager.ROLE); return authManager.getState(); } catch (ComponentException ce) { // ignore this here return null; } finally { this.manager.release( (Component)authManager ); } } /* (non-Javadoc) * @see org.apache.avalon.framework.component.Composable#compose(org.apache.avalon.framework.component.ComponentManager) */ public void compose(ComponentManager manager) throws ComponentException { this.manager = manager; this.resolver = (SourceResolver)manager.lookup(SourceResolver.ROLE); this.xpathProcessor = (XPathProcessor)this.manager.lookup(XPathProcessor.ROLE); } /* (non-Javadoc) * @see org.apache.avalon.framework.component.Recomposable#recompose(org.apache.avalon.framework.component.ComponentManager) */ public void recompose(ComponentManager manager) throws ComponentException { this.manager = manager; } /* (non-Javadoc) * @see org.apache.avalon.framework.activity.Disposable#dispose() */ public void dispose() { if ( this.manager != null ) { this.manager.release( (Component)this.xpathProcessor ); this.xpathProcessor = null; this.manager.release( (Component)this.resolver ); this.resolver = null; } } /* (non-Javadoc) * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context) */ public void contextualize(Context context) throws ContextException { this.componentContext = context; } /** * Get the profile store */ protected Store getProfileStore() throws ProcessingException { if (this.profileStore == null) { try { this.profileStore = (Store)this.manager.lookup(Store.ROLE); } catch (ComponentException ce) { throw new ProcessingException("Error during lookup of store component.", ce); } } return this.profileStore; } /** * Get the authentication manager */ protected AuthenticationManager getAuthenticationManager() throws ProcessingException { if (this.authenticationManager == null) { try { this.authenticationManager = (AuthenticationManager)this.manager.lookup(AuthenticationManager.ROLE); } catch (ComponentException ce) { throw new ProcessingException("Error during lookup of AuthenticationManager.", ce); } } return this.authenticationManager; } /** * Get the media manager */ protected MediaManager getMediaManager() throws ProcessingException { if (this.mediaManager == null) { try { this.mediaManager = (MediaManager)this.manager.lookup(MediaManager.ROLE); } catch (ComponentException ce) { throw new ProcessingException("Error during lookup of MediaManager.", ce); } } return this.mediaManager; } /** * Setup this component */ protected void setup() throws ProcessingException { if ( !this.initialized ) { final Request request = ContextHelper.getRequest(this.componentContext); if ( request.getAttribute(PortalManager.ROLE) == null ) { request.setAttribute(PortalManager.ROLE, Boolean.TRUE); // Get and ignore the configuration this.getConfiguration(); try { this.changeProfile(); } catch (SAXException se) { throw new ProcessingException(se); } catch (IOException ioe) { throw new ProcessingException(ioe); } } this.initialized = true; } } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#configurationTest() */ public void configurationTest() throws ProcessingException, IOException, SAXException { // no sync required if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN configurationTest"); } this.setup(); // Ignore result this.getConfiguration(); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END configurationTest"); } } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#getContext(boolean) */ public SessionContext getContext(boolean create) throws ProcessingException, IOException, SAXException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN getContext create="+create); } this.setup(); SessionContext context = null; final Session session = this.getSessionManager().getSession(false); if (session != null) { synchronized(session) { String appName = this.getRequestState().getApplicationName(); String attrName = PortalConstants.PRIVATE_SESSION_CONTEXT_NAME; if (appName != null) { attrName = attrName + ':' + appName; } context = this.getContextManager().getContext(attrName); if (context == null && create) { // create new context context = this.getAuthenticationManager().createApplicationContext(attrName, null, null); } } // end synchronized } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END getContext context="+context); } return context; } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#streamConfiguration(org.apache.cocoon.xml.XMLConsumer, java.lang.String, java.lang.String, java.lang.String, java.lang.String) */ public void streamConfiguration(XMLConsumer consumer, String requestURI, String profileID, String media, String contextID) throws IOException, SAXException, ProcessingException { // synchronized not req. this.setup(); Response response = ContextHelper.getResponse(this.componentContext); XMLUtils.startElement(consumer, PortalConstants.ELEMENT_CONFIGURATION); // set the portal-page uri: StringBuffer buffer = new StringBuffer(requestURI); buffer.append((requestURI.indexOf('?') == -1 ? '?' : '&')) .append(PortalManagerImpl.REQ_PARAMETER_PROFILE) .append('=') .append(profileID); String uri = response.encodeURL(buffer.toString()); XMLUtils.startElement(consumer, "uri"); XMLUtils.data(consumer, uri); XMLUtils.endElement(consumer, "uri"); Map config = this.getConfiguration(); String portalURI = response.encodeURL((String)config.get(PortalConstants.CONF_PORTAL_URI)); XMLUtils.startElement(consumer, "portal"); XMLUtils.data(consumer, portalURI); XMLUtils.endElement(consumer, "portal"); XMLUtils.startElement(consumer, PortalConstants.ELEMENT_PROFILE); XMLUtils.data(consumer, profileID); XMLUtils.endElement(consumer, PortalConstants.ELEMENT_PROFILE); if (media != null) { XMLUtils.startElement(consumer, "media"); XMLUtils.data(consumer, media); XMLUtils.endElement(consumer, "media"); } if (contextID != null) { XMLUtils.startElement(consumer, "context"); XMLUtils.data(consumer, contextID); XMLUtils.endElement(consumer, "context"); } XMLUtils.endElement(consumer, PortalConstants.ELEMENT_CONFIGURATION); } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#showAdminConf(org.apache.cocoon.xml.XMLConsumer) */ public void showAdminConf(XMLConsumer consumer) throws SAXException, ProcessingException, IOException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN showAdminConf consumer=" + consumer); } this.setup(); Request request = ContextHelper.getRequest(this.componentContext); try { String profileID = "global"; String copletID = request.getParameter(PortalManagerImpl.REQ_PARAMETER_COPLET); SessionContext context = this.getContext(true); Map configuration = this.getConfiguration(); DocumentFragment copletsFragment = (DocumentFragment)context.getAttribute(ATTRIBUTE_ADMIN_COPLETS); String command = request.getParameter(PortalManagerImpl.REQ_PARAMETER_ADMIN_COPLETS); if (command != null && copletsFragment != null) { try { this.getTransactionManager().startWritingTransaction(context); // save : save coplets base // new : new coplet // delete : use id to delete coplet // change : change the coplet // cache : cleans the cache if (command.equals("delete") && copletID != null) { Node coplet = DOMUtil.getSingleNode(copletsFragment, "coplets-profile/coplets/coplet[@id='"+copletID+"']", this.xpathProcessor); if (coplet != null) { coplet.getParentNode().removeChild(coplet); } } else if (command.equals("change") && copletID != null) { Node coplet = DOMUtil.getSingleNode(copletsFragment, "coplets-profile/coplets/coplet[@id='"+copletID+"']", this.xpathProcessor); if (coplet != null) { // now get the information String value; value = request.getParameter("portaladmin_title"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.getSingleNode(coplet, "title", this.xpathProcessor), value); value = request.getParameter("portaladmin_mand"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.getSingleNode(coplet, "configuration/mandatory", this.xpathProcessor), value); value = request.getParameter("portaladmin_sizable"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.getSingleNode(coplet, "configuration/sizable", this.xpathProcessor), value); value = request.getParameter("portaladmin_active"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.getSingleNode(coplet, "configuration/active", this.xpathProcessor), value); value = request.getParameter("portaladmin_handsize"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/handlesSizable", this.xpathProcessor), value); value = request.getParameter("portaladmin_handpar"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/handlesParameters", this.xpathProcessor), value); value = request.getParameter("portaladmin_timeout"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/timeout", this.xpathProcessor), value); value = request.getParameter("portaladmin_customizable"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/customizable", this.xpathProcessor), value); value = request.getParameter("portaladmin_persistent"); if (value != null) DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/persistent", this.xpathProcessor), value); String resource = request.getParameter("portaladmin_resource"); if (resource != null) { Element resourceNode = (Element)DOMUtil.getSingleNode(coplet, "resource", this.xpathProcessor); resourceNode.getParentNode().removeChild(resourceNode); resourceNode = coplet.getOwnerDocument().createElementNS(null, "resource"); resourceNode.setAttributeNS(null, "uri", resource); coplet.appendChild(resourceNode); } resource = request.getParameter("portaladmin_cust"); boolean isCustom = DOMUtil.getValueAsBooleanOf(coplet, "configuration/customizable", false, this.xpathProcessor); if (resource != null && isCustom ) { Element resourceNode = (Element)DOMUtil.getSingleNode(coplet, "customization", this.xpathProcessor); if (resourceNode != null) resourceNode.getParentNode().removeChild(resourceNode); resourceNode = coplet.getOwnerDocument().createElementNS(null, "customization"); resourceNode.setAttributeNS(null, "uri", resource); coplet.appendChild(resourceNode); } if (!isCustom) { Element resourceNode = (Element)DOMUtil.getSingleNode(coplet, "customization", this.xpathProcessor); if (resourceNode != null) resourceNode.getParentNode().removeChild(resourceNode); } // transformations value = request.getParameter("portaladmin_newxsl"); if (value != null) { Element tNode = (Element)DOMUtil.selectSingleNode(coplet, "transformation", this.xpathProcessor); Element sNode = tNode.getOwnerDocument().createElementNS(null, "stylesheet"); tNode.appendChild(sNode); sNode.appendChild(sNode.getOwnerDocument().createTextNode(value)); } // now get all transformation stylesheets, mark // all stylesheets which should be deleted with // an attribute delete Enumeration keys = request.getParameterNames(); Element sNode; String key; while (keys.hasMoreElements() ) { key = (String)keys.nextElement(); if (key.startsWith("portaladmin_xsl_") ) { value = key.substring(key.lastIndexOf('_')+ 1); sNode = (Element)DOMUtil.getSingleNode(coplet, "transformation/stylesheet[position()="+value+"]", this.xpathProcessor); if (sNode != null) { String xslName = request.getParameter(key); if (xslName.equals("true") ) xslName = "**STYLESHEET**"; DOMUtil.setValueOfNode(sNode, xslName); } } else if (key.startsWith("portaladmin_delxsl_") ) { value = key.substring(key.lastIndexOf('_')+ 1); sNode = (Element)DOMUtil.getSingleNode(coplet, "transformation/stylesheet[position()="+value+"]", this.xpathProcessor); if (sNode != null) { sNode.setAttributeNS(null, "delete", "true"); } } } NodeList delete = DOMUtil.selectNodeList(coplet, "transformation/stylesheet[@delete]", this.xpathProcessor); if (delete != null) { for(int i=0; i < delete.getLength(); i++) { delete.item(i).getParentNode().removeChild(delete.item(i)); } } } } else if (command.equals("new") ) { // first we have to invent a new coplet id! int index = 0; boolean found = false; Element coplet; Element subNode; while (!found) { copletID = "S"+index; coplet = (Element)DOMUtil.getSingleNode(copletsFragment, "coplets-profile/coplets/coplet[@id='"+copletID+"']", this.xpathProcessor); if (coplet == null) { found = true; } else { index++; } } coplet = copletsFragment.getOwnerDocument().createElementNS(null, "coplet"); coplet.setAttributeNS(null, "id", copletID); subNode = coplet.getOwnerDocument().createElementNS(null, "resource"); coplet.appendChild(subNode); subNode.setAttributeNS(null, "uri", "uri_in_sitemap"); String title = request.getParameter("portaladmin_title"); if (title == null || title.trim().length() == 0) title = "**NEW COPLET**"; DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/mandatory", this.xpathProcessor), "false"); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/sizable", this.xpathProcessor), "true"); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/active", this.xpathProcessor), "false"); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/handlesParameters", this.xpathProcessor), "true"); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "configuration/handlesSizable", this.xpathProcessor), "false"); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "title", this.xpathProcessor), title); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "status/visible", this.xpathProcessor), "true"); DOMUtil.setValueOfNode(DOMUtil.selectSingleNode(coplet, "status/size", this.xpathProcessor), "max"); DOMUtil.getSingleNode(copletsFragment, "coplets-profile/coplets", this.xpathProcessor).appendChild(coplet); } else if (command.equals("save") ) { SourceParameters pars = new SourceParameters(); pars.setSingleParameterValue("profile", "coplet-base"); RequestState state = this.getRequestState(); pars.setSingleParameterValue("application", state.getApplicationName()); pars.setSingleParameterValue("handler", state.getHandlerName()); String saveResource = (String)configuration.get(PortalConstants.CONF_COPLETBASE_SAVE_RESOURCE); if (saveResource == null) { throw new ProcessingException("portal: No save resource defined for type coplet-base."); } else { SourceUtil.writeDOM(saveResource, null, pars, copletsFragment, this.resolver, "xml"); // now the hardest part, clean up the whole cache this.cleanUpCache(null, null, configuration); } } } finally { this.getTransactionManager().stopWritingTransaction(context); } } // general commands if (command != null && command.equals("cleancache") ) { this.cleanUpCache(null, null, configuration); } String state = request.getParameter(PortalManagerImpl.REQ_PARAMETER_STATE); if (state == null) { state = (String)context.getAttribute(ATTRIBUTE_ADMIN_STATE, PortalConstants.STATE_MAIN); } // now start producing xml: consumer.startElement("", PortalConstants.ELEMENT_ADMINCONF, PortalConstants.ELEMENT_ADMINCONF, XMLUtils.EMPTY_ATTRIBUTES); context.setAttribute(ATTRIBUTE_ADMIN_STATE, state); consumer.startElement("", PortalConstants.ELEMENT_STATE, PortalConstants.ELEMENT_STATE, XMLUtils.EMPTY_ATTRIBUTES); consumer.characters(state.toCharArray(), 0, state.length()); consumer.endElement("", PortalConstants.ELEMENT_STATE, PortalConstants.ELEMENT_STATE); if (state.equals(PortalConstants.STATE_MAIN) ) { Document rolesDF = this.getRoles(); Node roles = null; if (rolesDF != null) roles = DOMUtil.getSingleNode(rolesDF, "roles", this.xpathProcessor); IncludeXMLConsumer.includeNode(roles, consumer, consumer); } if (state.equals(PortalConstants.STATE_MAIN_ROLE) ) { Document rolesDF = this.getRoles(); Node roles = null; if (rolesDF != null) roles = DOMUtil.getSingleNode(rolesDF, "roles", this.xpathProcessor); IncludeXMLConsumer.includeNode(roles, consumer, consumer); String role = request.getParameter(PortalManagerImpl.REQ_PARAMETER_ROLE); if (role == null) { role = (String)context.getAttribute(ATTRIBUTE_ADMIN_ROLE); } context.setAttribute(ATTRIBUTE_ADMIN_ROLE, role); if (role != null) { XMLUtils.startElement(consumer, "roleusers"); XMLUtils.startElement(consumer, "name"); XMLUtils.data(consumer, role); XMLUtils.endElement(consumer, "name"); Document userDF = this.getUsers(role, null); Node users = null; if (userDF != null) users = DOMUtil.getSingleNode(userDF, "users", this.xpathProcessor); IncludeXMLConsumer.includeNode(users, consumer, consumer); XMLUtils.endElement(consumer, "roleusers"); } } if (state.equals(PortalConstants.STATE_GLOBAL)) { profileID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, true); Map profile = this.retrieveProfile(profileID); if (profile == null) { this.createProfile(context, PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, true); profile = this.retrieveProfile(profileID); } this.showPortal(consumer, true, context, profile, profileID); } if (state.equals(PortalConstants.STATE_ROLE) ) { String role = request.getParameter(PortalManagerImpl.REQ_PARAMETER_ROLE); if (role == null) { role = (String)context.getAttribute(ATTRIBUTE_ADMIN_ROLE); } context.setAttribute(ATTRIBUTE_ADMIN_ROLE, role); if (role != null) { consumer.startElement("", PortalConstants.ELEMENT_ROLE, PortalConstants.ELEMENT_ROLE, XMLUtils.EMPTY_ATTRIBUTES); consumer.characters(role.toCharArray(), 0, role.length()); consumer.endElement("", PortalConstants.ELEMENT_ROLE, PortalConstants.ELEMENT_ROLE); profileID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ROLE, role, null, true); Map profile = this.retrieveProfile(profileID); if (profile == null) { this.createProfile(context, PortalManagerImpl.BUILDTYPE_VALUE_ROLE, role, null, true); profile = this.retrieveProfile(profileID); } this.showPortal(consumer, true, context, profile, profileID); } } if (state.equals(PortalConstants.STATE_USER) ) { String role = request.getParameter(PortalManagerImpl.REQ_PARAMETER_ROLE); String id = request.getParameter(PortalManagerImpl.REQ_PARAMETER_ID); if (role == null) { role = (String)context.getAttribute(ATTRIBUTE_ADMIN_ROLE); } if (id == null) { id = (String)context.getAttribute(ATTRIBUTE_ADMIN_ID); } context.setAttribute(ATTRIBUTE_ADMIN_ID, id); context.setAttribute(ATTRIBUTE_ADMIN_ROLE, role); if (role != null && id != null) { consumer.startElement("", PortalConstants.ELEMENT_ROLE, PortalConstants.ELEMENT_ROLE, XMLUtils.EMPTY_ATTRIBUTES); consumer.characters(role.toCharArray(), 0, role.length()); consumer.endElement("", PortalConstants.ELEMENT_ROLE, PortalConstants.ELEMENT_ROLE); consumer.startElement("", PortalConstants.ELEMENT_ID, PortalConstants.ELEMENT_ID, XMLUtils.EMPTY_ATTRIBUTES); consumer.characters(id.toCharArray(), 0, id.length()); consumer.endElement("", PortalConstants.ELEMENT_ID, PortalConstants.ELEMENT_ID); profileID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ID, role, id, true); Map profile = this.retrieveProfile(profileID); if (profile == null) { this.createProfile(context, PortalManagerImpl.BUILDTYPE_VALUE_ID, role, id, true); profile = this.retrieveProfile(profileID); } this.showPortal(consumer, true, context, profile, profileID); } } // one coplet if (state.equals(PortalConstants.STATE_COPLET) ) { if (copletsFragment != null && copletID != null) { Node coplet = DOMUtil.getSingleNode(copletsFragment, "coplets-profile/coplets/coplet[@id='"+copletID+"']", this.xpathProcessor); if (coplet != null) { IncludeXMLConsumer.includeNode(coplet, consumer, consumer); } } else { state = PortalConstants.STATE_COPLETS; } } if (state.equals(PortalConstants.STATE_COPLETS) ) { consumer.startElement("", PortalConstants.ELEMENT_COPLETS, PortalConstants.ELEMENT_COPLETS, XMLUtils.EMPTY_ATTRIBUTES); // load the base coplets profile if (copletsFragment == null) { SourceParameters pars = new SourceParameters(); RequestState reqstate = this.getRequestState(); pars.setSingleParameterValue("application", reqstate.getApplicationName()); String res = (String)configuration.get(PortalConstants.CONF_COPLETBASE_RESOURCE); if (res == null) { throw new ProcessingException("No configuration for portal-coplet base profile found."); } copletsFragment = SourceUtil.readDOM(res, null, pars, this.resolver); context.setAttribute(ATTRIBUTE_ADMIN_COPLETS, copletsFragment); } IncludeXMLConsumer.includeNode(DOMUtil.selectSingleNode(copletsFragment, "coplets-profile", this.xpathProcessor), consumer, consumer); consumer.endElement("", PortalConstants.ELEMENT_COPLETS, PortalConstants.ELEMENT_COPLETS); } // configuration this.streamConfiguration(consumer, request.getRequestURI(), profileID, null, null); consumer.endElement("", PortalConstants.ELEMENT_ADMINCONF, PortalConstants.ELEMENT_ADMINCONF); } catch (javax.xml.transform.TransformerException local) { throw new ProcessingException("TransformerException: " + local, local); } if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("END showAdminConf"); } } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#getStatusProfile() */ public Element getStatusProfile() throws SAXException, IOException, ProcessingException { // synchronized if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("BEGIN getStatusProfile"); } this.setup(); SessionContext context = this.getContext(true); String profileID = null; Map storedProfile = null; Element statusProfile = null; if (context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE) != null) { profileID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ID, (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE), (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID), false); storedProfile = this.retrieveProfile(profileID); } if (storedProfile != null) { DocumentFragment profile = (DocumentFragment)storedProfile.get(PortalConstants.PROFILE_PROFILE); try { statusProfile = (Element)DOMUtil.getSingleNode(profile, "profile/status-profile", this.xpathProcessor); } catch (javax.xml.transform.TransformerException ignore) { } } if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("END getStatusProfile statusProfile="+(statusProfile == null ? "null" : XMLUtils.serializeNode(statusProfile, XMLUtils.createPropertiesForXML(false)))); } return statusProfile; } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#showPortal(org.apache.cocoon.xml.XMLConsumer, boolean, boolean) */ public void showPortal(XMLConsumer consumer, boolean configMode, boolean adminProfile) throws SAXException, ProcessingException, IOException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN showPortal consumer=" + consumer+", configMode="+ configMode+", adminProfile="+adminProfile); } this.setup(); SessionContext context = this.getContext(true); String profileID = null; Map storedProfile = null; if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("start portal generation"); } if (context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE) != null) { profileID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ID, (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE), (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID), adminProfile); storedProfile = this.retrieveProfile(profileID); } if (storedProfile == null) { if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("start building profile"); } this.createProfile(context, PortalManagerImpl.BUILDTYPE_VALUE_ID, null, null, adminProfile); // get the profileID profileID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ID, (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE), (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID), adminProfile); storedProfile = this.retrieveProfile(profileID); if (storedProfile == null) { throw new ProcessingException("portal: No portal profile found."); } if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("end building profile"); } } if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("start showing profile"); } this.showPortal(consumer, configMode, context, storedProfile, profileID); if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("end showing profile"); this.getLogger().debug("end portal generation"); } if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("END showPortal"); } } /** * Stream all layout information for the current portal * to the consumer. * The resulting XML: * <layout> * <portal> * ... * </portal> * <coplets> * ... * </coplets> * </layout> */ public static void streamLayoutProfile(XMLConsumer consumer, Map portalLayouts, Map copletLayouts, String mediaType) throws SAXException { Element element; NodeList childs; Attributes attr = new AttributesImpl(); consumer.startElement("", PortalConstants.ELEMENT_LAYOUT, PortalConstants.ELEMENT_LAYOUT, attr); // first: layout of portal consumer.startElement("", PortalConstants.ELEMENT_PORTAL, PortalConstants.ELEMENT_PORTAL, attr); element = (Element)portalLayouts.get(mediaType); childs = element.getChildNodes(); for(int ci = 0; ci < childs.getLength(); ci++) { IncludeXMLConsumer.includeNode(childs.item(ci), consumer, consumer); } consumer.endElement("", PortalConstants.ELEMENT_PORTAL, PortalConstants.ELEMENT_PORTAL); // second: layout of coplets consumer.startElement("", PortalConstants.ELEMENT_COPLETS, PortalConstants.ELEMENT_COPLETS, attr); element = (Element)copletLayouts.get(mediaType); childs = element.getChildNodes(); for(int ci = 0; ci < childs.getLength(); ci++) { IncludeXMLConsumer.includeNode(childs.item(ci), consumer, consumer); } consumer.endElement("", PortalConstants.ELEMENT_COPLETS, PortalConstants.ELEMENT_COPLETS); consumer.endElement("", PortalConstants.ELEMENT_LAYOUT, PortalConstants.ELEMENT_LAYOUT); } /** * Show the portal. * The portal is included in the current stream. */ private void showPortal(XMLConsumer consumer, boolean configMode, SessionContext context, Map storedProfile, String profileID) throws SAXException, ProcessingException, IOException { // synchronized if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("BEGIN showPortal consumer=" + consumer+", configMode="+configMode+", context="+context+ ", profile="+storedProfile); } Request request = ContextHelper.getRequest(this.componentContext); try { this.getTransactionManager().startReadingTransaction(context); DocumentFragment profile; Map defaultCoplets; Map mediaCoplets; Map portalLayouts; Map copleyLayouts; Node[] miscNodes; String mediaType = this.getMediaManager().getMediaType(); profile = (DocumentFragment)storedProfile.get(PortalConstants.PROFILE_PROFILE); portalLayouts = (Map)storedProfile.get(PortalConstants.PROFILE_PORTAL_LAYOUTS); copleyLayouts = (Map)storedProfile.get(PortalConstants.PROFILE_COPLET_LAYOUTS); miscNodes = (Node[])storedProfile.get(PortalConstants.PROFILE_MISC_POINTER); defaultCoplets = (Map)storedProfile.get(PortalConstants.PROFILE_DEFAULT_COPLETS); mediaCoplets = (Map)storedProfile.get(PortalConstants.PROFILE_MEDIA_COPLETS); if (profile == null || defaultCoplets == null || mediaCoplets == null || portalLayouts == null || copleyLayouts == null || miscNodes == null) { throw new ProcessingException("portal: No portal profile found."); } // get the configuration Map config = this.getConfiguration(); if (config == null) { throw new ProcessingException("No configuration for portal found."); } boolean processCopletsParallel = false; long defaultCopletTimeout = 600000; Boolean boolValue = (Boolean)config.get(PortalConstants.CONF_PARALLEL_COPLETS); if (boolValue != null) processCopletsParallel = boolValue.booleanValue(); Long longValue = (Long)config.get(PortalConstants.CONF_COPLET_TIMEOUT); if (longValue != null) defaultCopletTimeout = longValue.longValue(); Element element; // now start producing xml: AttributesImpl attr = new AttributesImpl(); if (configMode) { XMLUtils.startElement(consumer, PortalConstants.ELEMENT_PORTALCONF); } else { XMLUtils.startElement(consumer, PortalConstants.ELEMENT_PORTAL); } // configuration this.streamConfiguration(consumer, request.getRequestURI(), profileID, mediaType, null); // LAYOUT: if (configMode) { IncludeXMLConsumer.includeNode(DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","layout-profile"}, false), consumer, consumer); // copletsConfiguration (only for configMode) IncludeXMLConsumer.includeNode(DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","coplets-profile"}, false), consumer, consumer); IncludeXMLConsumer.includeNode(DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","type-profile","typedefs"}, false), consumer, consumer); IncludeXMLConsumer.includeNode(DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","portal-profile"}, false), consumer, consumer); IncludeXMLConsumer.includeNode(DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","personal-profile"}, false), consumer, consumer); IncludeXMLConsumer.includeNode(DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","status-profile"}, false), consumer, consumer); } else { PortalManagerImpl.streamLayoutProfile(consumer, portalLayouts, copleyLayouts, mediaType); } // END LAYOUT if (!configMode) { Element statusProfile = (Element)DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","status-profile"}, false); String copletNotAvailableMessage = "The coplet is currently not available."; Node messages = miscNodes[PortalConstants.PROFILE_MISC_MESSAGES_NODE]; if (messages != null) { messages = DOMUtil.getFirstNodeFromPath(messages, new String[] {"coplet_not_available"}, false); if (messages != null) copletNotAvailableMessage = DOMUtil.getValueOfNode(messages, copletNotAvailableMessage); } // LOAD COPLETS List[] copletContents; List[] temp = (List[])context.getAttribute(PortalConstants.ATTRIBUTE_COPLET_REPOSITORY); if (temp != null) { copletContents = new List[temp.length]; for (int i = 0; i < temp.length; i++) { if (temp[i] == null) { copletContents[i] = null; } else { copletContents[i] = new ArrayList(temp[i]); } } } else { copletContents = new List[PortalConstants.MAX_COLUMNS+2]; context.setAttribute(PortalConstants.ATTRIBUTE_COPLET_REPOSITORY, copletContents); } if (copletContents[0] == null) { copletContents[0] = new ArrayList(1); } else { copletContents[0].clear(); } if (copletContents[1] == null) { copletContents[1] = new ArrayList(1); } else { copletContents[1].clear(); } // test for header String value; value = DOMUtil.getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_HEADER_NODE]); if (value != null && new Boolean(value).booleanValue()) { element = (Element)miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE]; if (element != null) { this.loadCoplets(element, defaultCoplets, mediaCoplets, copletContents[0], processCopletsParallel, defaultCopletTimeout, statusProfile); } } // content value = DOMUtil.getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE]); // for a simpler XSL-Stylesheet: The columns must be inserted in the // correct order!!! if (value != null && new Integer(value).intValue() > 0) { Element columnElement; int columns = new Integer(value).intValue(); if (columns > PortalConstants.MAX_COLUMNS) { throw new ProcessingException("portal: Maximum number of columns supported is: "+PortalConstants.MAX_COLUMNS); } for(int colindex = 1; colindex <= columns; colindex++) { if (copletContents[colindex+1] == null) { copletContents[colindex+1] = new ArrayList(10); } else { copletContents[colindex+1].clear(); } columnElement = (Element)miscNodes[7 + colindex]; element = (Element)DOMUtil.getFirstNodeFromPath(columnElement, new String[] {"coplets"}, false); if (element != null) { this.loadCoplets(element, defaultCoplets, mediaCoplets, copletContents[colindex+1], processCopletsParallel, defaultCopletTimeout, statusProfile); } } for(int colindex = columns+2; colindex <= PortalConstants.MAX_COLUMNS+1; colindex++) { if (copletContents[colindex] != null) { copletContents[colindex] = null; } } } else { for(int colindex = 1; colindex <= PortalConstants.MAX_COLUMNS; colindex++) { if (copletContents[colindex+1] != null) { copletContents[colindex+1] = null; } } } // test for footer value = DOMUtil.getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_FOOTER_NODE]); if (value != null && new Boolean(value).booleanValue()) { element = (Element)miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE]; if (element != null) { this.loadCoplets(element, defaultCoplets, mediaCoplets, copletContents[1], processCopletsParallel, defaultCopletTimeout, statusProfile); } } // END LOAD COPLETS // DESIGN // test for header if (copletContents[0].size() > 0) { consumer.startElement("", "header", "header", attr); this.processCopletList(copletContents[0], consumer, copletNotAvailableMessage, defaultCopletTimeout); consumer.endElement("", "header", "header"); } // content value = DOMUtil.getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE]); // for a simpler XSL-Stylesheet: The columns must be inserted in the // correct order!!! if (value != null && new Integer(value).intValue() > 0) { attr.addAttribute("", "number", "number", "CDATA", value); XMLUtils.startElement(consumer, "columns", attr); attr.clear(); int columns = new Integer(value).intValue(); if (columns > PortalConstants.MAX_COLUMNS) { throw new ProcessingException("portal: Maximum number of columns supported is: "+PortalConstants.MAX_COLUMNS); } // determine the width of the columns String[] width = new String[columns]; int normalWidth = 100 / columns; Element columnElement; for(int colindex = 1; colindex <= columns; colindex++) { columnElement = (Element)miscNodes[7 + colindex]; value = DOMUtil.getValueOf(columnElement, "width", this.xpathProcessor); if (value == null) { width[colindex-1] = "" + normalWidth + "%"; } else { width[colindex-1] = value; } } for(int colindex = 1; colindex <= columns; colindex++) { attr.addAttribute("", "position", "position", "CDATA", "" + colindex); attr.addAttribute("", "width", "width", "CDATA", width[colindex-1]); XMLUtils.startElement(consumer, "column", attr); attr.clear(); this.processCopletList(copletContents[colindex+1], consumer, copletNotAvailableMessage, defaultCopletTimeout); XMLUtils.endElement(consumer, "column"); } XMLUtils.endElement(consumer, "columns"); } else { attr.addAttribute("", "number", "number", "CDATA", "0"); XMLUtils.startElement(consumer, "columns", attr); XMLUtils.endElement(consumer, "columns"); attr.clear(); } // test for footer if (copletContents[1].size() > 0) { XMLUtils.startElement(consumer, "footer"); this.processCopletList(copletContents[1], consumer, copletNotAvailableMessage, defaultCopletTimeout); XMLUtils.endElement(consumer, "footer"); } // END DESIGN for(int i=0; i<copletContents.length;i++) { if (copletContents[i]!=null) copletContents[i].clear(); } // Personal information and status information this.sendEvents(consumer, DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","personal-profile"}, false)); this.sendEvents(consumer, statusProfile); } if (configMode) { XMLUtils.endElement(consumer, PortalConstants.ELEMENT_PORTALCONF); } else { XMLUtils.endElement(consumer, PortalConstants.ELEMENT_PORTAL); } } catch (javax.xml.transform.TransformerException local) { // end synchronized throw new ProcessingException("TransformerException: " + local, local); } finally { this.getTransactionManager().stopReadingTransaction(context); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END showPortal"); } } /** * Building the profile. * This includes several steps which are declared in detail inside this method... */ protected void buildProfile(String type, String role, String id, boolean adminProfile) throws ProcessingException, IOException, SAXException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildProfile type=" + type + ", role=" + role + ", id=" +id+", adminProfile="+adminProfile); } try { // check parameter if (type == null) { throw new ProcessingException("buildProfile: Type is required"); } if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL) || type.equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)) { // nothing to do here } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) { if (role == null) { throw new ProcessingException("buildProfile: Role is required"); } } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { if (role == null) { throw new ProcessingException("buildProfile: Role is required"); } if (id == null) { throw new ProcessingException("buildProfile: ID is required"); } } else { throw new ProcessingException("buildProfile: Type unknown: " + type); } SessionContext context = this.getContext(true); try { this.getTransactionManager().startWritingTransaction(context); String profileID = this.getProfileID(type, role, id, adminProfile); Map theProfile = null; // get the configuration Map config = this.getConfiguration(); if (config == null) { throw new ProcessingException("No configuration for portal found."); } // is the ID profile cached? if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID) ) { theProfile = this.getCachedProfile(profileID, config); } if (theProfile == null) { boolean doBase = false; boolean doGlobal = false; boolean doRole = false; boolean doID = false; String previousID; if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { doID = true; previousID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ROLE, role, null, adminProfile); theProfile = this.getCachedProfile(previousID, config); if (theProfile == null) { doRole = true; previousID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, adminProfile); theProfile = this.getCachedProfile(previousID, config); if (theProfile == null) { doGlobal = true; previousID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_BASIC, null, null, adminProfile); theProfile = this.getCachedProfile(previousID, config); } } } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) { theProfile = this.getCachedProfile(profileID, config); if (theProfile == null) { doRole = true; previousID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, adminProfile); theProfile = this.getCachedProfile(previousID, config); if (theProfile == null) { doGlobal = true; previousID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_BASIC, null, null, adminProfile); theProfile = this.getCachedProfile(previousID, config); } } } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) { theProfile = this.getCachedProfile(profileID, config); if (theProfile == null) { doGlobal = true; previousID = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_BASIC, null, null, adminProfile); theProfile = this.getCachedProfile(previousID, config); } } else { // basic profile theProfile = this.getCachedProfile(profileID, config); } // build the profile if (theProfile == null) { theProfile = new HashMap(8,2); doBase = true; } Element profileRoot; DocumentFragment profile; if (doBase) { // build the base level profile = this.buildBaseProfile(config, adminProfile); profileRoot = (Element)profile.getFirstChild(); theProfile.put(PortalConstants.PROFILE_PROFILE, profile); this.cacheProfile(this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_BASIC, null, null, adminProfile), theProfile, config); } else { profile = (DocumentFragment)theProfile.get(PortalConstants.PROFILE_PROFILE); profileRoot = (Element)profile.getFirstChild(); } // load the global delta if type is global, role or user (but not basic!) if (doGlobal) { this.buildGlobalProfile(profileRoot, config, adminProfile); this.cacheProfile(this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, adminProfile), theProfile, config); } // load the role delta if type is role or user if (doRole) { this.buildRoleProfile(profileRoot, config, role, adminProfile); this.cacheProfile(this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ROLE, role, null, adminProfile), theProfile, config); } // load the user delta if type is user if (doID) { this.buildUserProfile(profileRoot, config, role, id, adminProfile); } // load the status profile when type is user if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { this.buildUserStatusProfile(profileRoot, config, role, id); } if (!type.equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)) { this.buildRunProfile(theProfile, context, profile); theProfile.put(PortalConstants.PROFILE_PORTAL_LAYOUTS, this.buildPortalLayouts(context, profile)); theProfile.put(PortalConstants.PROFILE_COPLET_LAYOUTS, this.buildcopleyLayouts(context, profile)); this.buildTypeProfile(theProfile, context, profile); } // cache the profile, if user if (doID) { this.cacheProfile(profileID, theProfile, config); } } else { // load the status profile when type is user if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { DocumentFragment profile = (DocumentFragment)theProfile.get(PortalConstants.PROFILE_PROFILE); Element profileRoot = (Element)profile.getFirstChild(); this.buildUserStatusProfile(profileRoot, config, role, id); } } // store the whole profile this.storeProfile(profileID, theProfile); // now put role and id into the context if type is ID if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID) && !adminProfile) { context.setAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE, role); context.setAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID, id); } } finally { this.getTransactionManager().stopWritingTransaction(context); }// end synchronized } catch (javax.xml.transform.TransformerException local) { throw new ProcessingException("TransformerException: " + local, local); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildProfile"); } } /** * Build the profile delta */ private DocumentFragment buildProfileDelta(String type, String role, String id, boolean adminProfile) throws SAXException, ProcessingException, IOException, javax.xml.transform.TransformerException { // calling method must be synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildProfileDeltaN type="+type+", role="+role+", id="+id); } Map originalProfile; Map baseProfile; String baseType, baseRole, baseID, rootElementName; DocumentFragment originalFragment; DocumentFragment delta; SessionContext context = this.getContext(true); originalProfile = this.retrieveProfile(this.getProfileID(type, role, id, adminProfile)); if (originalProfile == null) { throw new ProcessingException("buildProfileDelta: no profile found for " + type + " - " + role + " - " + id + "."); } if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { baseType = PortalManagerImpl.BUILDTYPE_VALUE_ROLE; baseRole = role; baseID = null; rootElementName = "user-delta"; } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) { baseType = PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL; baseRole = null; baseID = null; rootElementName = "role-delta"; } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) { baseType = PortalManagerImpl.BUILDTYPE_VALUE_BASIC; baseRole = null; baseID = null; rootElementName = "global-delta"; } else { throw new ProcessingException("buildProfileDelta: type '"+type+"' not allowed."); } // the profile is created as we dont want to use any memory representation! this.createProfile(context, baseType, baseRole, baseID, adminProfile); baseProfile = this.retrieveProfile(this.getProfileID(baseType, baseRole, baseID, adminProfile)); if (baseProfile == null) { throw new ProcessingException("buildProfileDelta: no baseProfile found."); } originalFragment = (DocumentFragment)originalProfile.get(PortalConstants.PROFILE_PROFILE); delta = originalFragment.getOwnerDocument().createDocumentFragment(); delta.appendChild(delta.getOwnerDocument().createElementNS(null, rootElementName)); // Copy portal content Node profileDelta = DOMUtil.getFirstNodeFromPath(originalFragment, new String[] {"profile","portal-profile"}, false).cloneNode(true); delta.getFirstChild().appendChild(profileDelta); // Diff layout profile, coplet profile, personal profile but not status profile! this.diff(originalFragment, (DocumentFragment)baseProfile.get(PortalConstants.PROFILE_PROFILE), "profile/layout-profile", (Element)delta.getFirstChild()); this.diff(originalFragment, (DocumentFragment)baseProfile.get(PortalConstants.PROFILE_PROFILE), "profile/coplets-profile", (Element)delta.getFirstChild()); if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) { profileDelta = DOMUtil.getFirstNodeFromPath(originalFragment, new String[] {"profile","personal-profile"}, false).cloneNode(true); delta.getFirstChild().appendChild(profileDelta); } else { this.diff(originalFragment, (DocumentFragment)baseProfile.get(PortalConstants.PROFILE_PROFILE), "profile/personal-profile", (Element)delta.getFirstChild()); } // check for the highes coplet number Node[] miscNodes = (Node[])originalProfile.get(PortalConstants.PROFILE_MISC_POINTER); Element lastCoplet = (Element)miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE]; if (lastCoplet != null) { String lastNumber = lastCoplet.getAttributeNS(null, "number"); if (lastNumber != null) { int value = new Integer(lastNumber).intValue(); if (value > 1000000) { NodeList coplets = DOMUtil.selectNodeList(delta, "profile/portal-profile/descendant::coplet[@id and @number]", this.xpathProcessor); if (coplets != null) { Element copletNode; String oldNumber; String copletId; Element statusNode; boolean copletsChanged = false; for(int i=0; i <coplets.getLength(); i++) { copletNode = (Element)coplets.item(i); oldNumber = copletNode.getAttributeNS(null, "number"); copletId = copletNode.getAttributeNS(null, "id"); statusNode = (Element)DOMUtil.getSingleNode(delta, "status-profile/customization/coplet[@id='"+copletId+"' and @number='"+oldNumber+"']", this.xpathProcessor); copletNode.setAttributeNS(null, "number", ""+(i+1)); if (statusNode != null) { statusNode.setAttributeNS(null, "number", ""+(i+1)); copletsChanged = true; } } if (copletsChanged) { this.saveUserStatusProfile(originalProfile, this.getConfiguration(), role, id); } } } } } // Last part: strip type information NodeList typeElements = DOMUtil.selectNodeList(delta, "descendant::*[@formpath and @formdescription and @formtype]", this.xpathProcessor); if (typeElements != null) { for(int i = 0; i < typeElements.getLength(); i++) { ((Element)typeElements.item(i)).removeAttributeNS(null, "formpath"); ((Element)typeElements.item(i)).removeAttributeNS(null, "formdescription"); ((Element)typeElements.item(i)).removeAttributeNS(null, "formtype"); } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildProfileDelta delta="+delta); } return delta; } /** * Make the difference :-) */ private void diff(DocumentFragment original, DocumentFragment base, String path, Element deltaElement) throws SAXException, javax.xml.transform.TransformerException { // calling method is already synchronized Element originalRoot = (Element)DOMUtil.getSingleNode(original, path, this.xpathProcessor); Element baseRoot = (Element)DOMUtil.getSingleNode(base, path, this.xpathProcessor); if (originalRoot != null && baseRoot != null) { List nodeStack = new ArrayList(); String name = baseRoot.getNodeName(); name = name.substring(0, name.indexOf("-profile")) + "-delta"; nodeStack.add(originalRoot.getOwnerDocument().createElementNS(null, name)); this.diffNode(baseRoot, originalRoot, nodeStack, deltaElement); } } /** * Diff one node */ private void diffNode(Element baseNode, Element originalNode, List nodeStack, Element deltaElement) throws SAXException, javax.xml.transform.TransformerException { // calling method is already synchronized NodeList baseChilds; NodeList originalChilds; int i, len; int m, l; boolean found; Node currentOrigNode = null; Node currentBaseNode = null; originalChilds = originalNode.getChildNodes(); len = originalChilds.getLength(); baseChilds = baseNode.getChildNodes(); l = baseChilds.getLength(); for(i = 0; i < len; i++) { currentOrigNode = originalChilds.item(i); if (currentOrigNode.getNodeType() == Node.ELEMENT_NODE) { // search the delta node in the profile m = 0; found = false; while (!found && m < l) { currentBaseNode = baseChilds.item(m); if (currentBaseNode.getNodeType() == Node.ELEMENT_NODE && currentBaseNode.getNodeName().equals(currentOrigNode.getNodeName()) ) { // now we have found a node with the same name // next: the attributes must match also found = this.compareAttributes(currentBaseNode, currentOrigNode); } if (!found) m++; } if (found) { // do we have elements as children or text? currentOrigNode.normalize(); if (currentOrigNode.hasChildNodes()) { // do a recursive call for sub elements nodeStack.add(currentOrigNode); this.diffNode((Element)currentBaseNode, (Element)currentOrigNode, nodeStack, deltaElement); // and now compare the text nodes String baseString = DOMUtil.getValueOfNode(currentBaseNode, "").trim(); String originalString = DOMUtil.getValueOfNode(currentOrigNode, "").trim(); if (!baseString.equals(originalString)) { // this is the tricky part: // we have to process all nodes on the stack // and insert them in the deltaElement Element currentElement; Element contextElement = deltaElement; NodeList possibleChilds; boolean foundChild; int cIndex; for(int p = 0; p < nodeStack.size(); p++) { currentElement = (Element)nodeStack.get(p); possibleChilds = DOMUtil.getNodeListFromPath(contextElement, new String[] {currentElement.getNodeName()}); foundChild = false; cIndex = 0; if (possibleChilds != null) { while (!foundChild && cIndex < possibleChilds.getLength()) { foundChild = this.compareAttributes(currentElement, possibleChilds.item(cIndex)); if (!foundChild) cIndex++; } } if (foundChild) { contextElement = (Element)possibleChilds.item(cIndex); } else { currentElement = (Element)currentElement.cloneNode(false); contextElement.appendChild(currentElement); contextElement = currentElement; } } // now add the text contextElement.appendChild(contextElement.getOwnerDocument().createTextNode(originalString)); } nodeStack.remove(nodeStack.size()-1); } } } } } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#getProfileID(java.lang.String, java.lang.String, java.lang.String, boolean) */ public String getProfileID(String type, String role, String id, boolean adminProfile) throws ProcessingException { // No sync required this.setup(); StringBuffer key = new StringBuffer((adminProfile ? "aprofile:" : "uprofile:")); RequestState reqstate = this.getRequestState(); key.append(reqstate.getHandlerName()) .append('|') .append(reqstate.getApplicationName()) .append(':') .append(type); if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE) || type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { role = XMLUtil.encode(role); key.append('_').append(role.length()).append('_').append(role); } if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { id = XMLUtil.encode(id); key.append('_').append(id); } return key.toString(); } /** * Get the profile role from the key */ private boolean getIsAdminProfile(String profileID) { // No sync required return profileID.startsWith("a"); } /** * Get the profile role from the key */ private String getRole(String profileID) { // No sync required profileID = XMLUtil.decode(profileID); int pos = profileID.indexOf('_'); if (pos == -1) { return null; } else { String lastPart = profileID.substring(pos+1); pos = lastPart.indexOf('_'); if (pos == -1) return null; int len = new Integer(lastPart.substring(0, pos)).intValue(); lastPart = lastPart.substring(pos+1, pos+1+len); return lastPart; } } /** * Get the profile ID from the key */ private String getID(String profileID) { // No sync required profileID = XMLUtil.decode(profileID); int pos = profileID.indexOf('_'); if (pos == -1) { return null; } else { String lastPart = profileID.substring(pos+1); pos = lastPart.indexOf('_'); if (pos == -1) { return null; } else { lastPart = lastPart.substring(pos+1); pos = lastPart.indexOf('_'); if (pos == -1) { return null; } else { return lastPart.substring(pos+1); } } } } /** * Get the profile type from the key */ private String getType(String profileID) { // No sync required profileID = XMLUtil.decode(profileID); int endPos = profileID.indexOf('_'); if (endPos == -1) { int startPos = profileID.lastIndexOf(':'); return profileID.substring(startPos+1); } else { int startPos = profileID.lastIndexOf(':', endPos); return profileID.substring(startPos+1, endPos); } } /** * Store the profil */ private void storeProfile(String profileID, Map profile) throws ProcessingException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN storeProfile id="+profileID+", profile="+profile); } Session session = this.getSessionManager().getSession(true); synchronized(session) { session.setAttribute(profileID, profile); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END storeProfile"); } } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#retrieveProfile(java.lang.String) */ public Map retrieveProfile(String profileID) throws ProcessingException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN retrieveProfile id="+profileID); } this.setup(); Session session = this.getSessionManager().getSession(true); Map result; synchronized(session) { result = (Map)session.getAttribute(profileID); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END retrieveProfile profile="+(result != null ? "**PROFILE**" : "null")); } return result; } /** * Cache the profile (if cache is turned on) */ private void cacheProfile(String profileID, Map profile, Map configuration) { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN cacheProfile id="+profileID+", profile="+profile); } try { if (configuration != null && !this.getIsAdminProfile(profileID)) { String storePrefix = (String)configuration.get(PortalConstants.CONF_PROFILE_CACHE); if (storePrefix != null) { String key = profileID.substring(1); this.getProfileStore().store(key, profile); } } } catch (Exception local) { this.getLogger().warn("Caching Profile failed.", local); // local exceptions are ignored // we dont want to get an exception response due to cache problems } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END cacheProfile"); } } /** * Retrieve the cached profil if available */ private Map getCachedProfile(String profileID, Map configuration) { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN getCachedProfile id="+profileID); } Map result = null; try { if (configuration != null && !this.getIsAdminProfile(profileID)) { final String storePrefix = (String)configuration.get(PortalConstants.CONF_PROFILE_CACHE); if (storePrefix != null) { final String key = profileID.substring(1); final Store store = this.getProfileStore(); if (store.containsKey(key)) { result = (Map)store.get(key); } } } } catch (Exception local) { // local exceptions are ignored // we dont want to get an exception response due to cache problems this.getLogger().warn("Getting cached Profile failed.", local); result = null; } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END getCachedProfile profile="+(result != null ? "**PROFILE**" : "null")); } return result; } /** * Clean up the cache, if the global profile was saved, delete all role and user profiles. * If a role profile was saved delete all user profiles. If the basic profile was * saved delete all profiles. */ private void cleanUpCache(String type, String role, Map configuration) throws ProcessingException { if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN cleanUpCache type="+type+", role="+role+", config="+configuration); } if (configuration != null && type != null && !type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { String storePrefix = (String)configuration.get(PortalConstants.CONF_PROFILE_CACHE); if (storePrefix != null) { Store store = this.getProfileStore(); Enumeration keys = store.keys(); String currentKey; String deleteGlobal = null; String deleteRole = null; String deleteUser = null; if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC) || type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) { if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)) { deleteGlobal = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, false).substring(1); } deleteRole = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, false); deleteRole = deleteRole.substring(1, deleteRole.lastIndexOf(':')+1) + PortalManagerImpl.BUILDTYPE_VALUE_ROLE; deleteUser = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, false); deleteUser = deleteUser.substring(1, deleteUser.lastIndexOf(':')+1) + PortalManagerImpl.BUILDTYPE_VALUE_ID; } else { // role deleteGlobal = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ROLE, role, null, false).substring(1); deleteUser = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ID, role, "a", false); deleteUser = deleteUser.substring(1, deleteUser.length()-1); } while (keys.hasMoreElements()) { Object k = keys.nextElement(); if ( k instanceof String ) { currentKey = (String)k; if (deleteGlobal != null && currentKey.equals(deleteGlobal)) { store.remove(currentKey); } else if (deleteRole != null && currentKey.startsWith(deleteRole)) { store.remove(currentKey); } else if (deleteUser != null && currentKey.startsWith(deleteUser)) { store.remove(currentKey); } } } } } else if (configuration != null && type == null) { // clean whole cache String storePrefix = (String)configuration.get(PortalConstants.CONF_PROFILE_CACHE); if (storePrefix != null) { Store store = this.getProfileStore(); Enumeration keys = store.keys(); String currentKey; String delete; delete = this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null, null, false); delete = delete.substring(1, delete.lastIndexOf(':') + 1); while (keys.hasMoreElements()) { Object k = keys.nextElement(); if ( k instanceof String ) { currentKey = (String)k; if (currentKey.startsWith(delete)) { store.remove(currentKey); } } } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END cleanUpCache"); } } /** * Build the run profil and store it in the <code>profileMap</code>. */ private void buildRunProfile(Map profileMap, SessionContext context, DocumentFragment baseProfile) throws ProcessingException, javax.xml.transform.TransformerException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildRunProfile context="+context+", profile="+baseProfile); } // The map containing the coplets which appear on each medium Map defaultCoplets = new HashMap(20, 5); // The map containing for each media type a map with coplets which // appear only for the given media Map mediaCoplets = new HashMap(5, 2); profileMap.put(PortalConstants.PROFILE_DEFAULT_COPLETS, defaultCoplets); profileMap.put(PortalConstants.PROFILE_MEDIA_COPLETS, mediaCoplets); // get AuthenticationManager instance String[] types = this.getMediaManager().getMediaTypes(); Map mediaMap; for(int i = 0; i < types.length; i++) { mediaCoplets.put(types[i], new HashMap(5, 3)); } // build misc nodes Node[] miscNodes = new Node[13]; miscNodes[PortalConstants.PROFILE_MISC_HEADER_NODE] = DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","layout-profile","portal","header","exists"}, false); miscNodes[PortalConstants.PROFILE_MISC_FOOTER_NODE] = DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","layout-profile","portal","footer","exists"}, false); miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE] = DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","portal-profile","content","header"}, false); miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE] = DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","portal-profile","content","footer"}, false); miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE]= DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","layout-profile","portal","columns","number"}, false); miscNodes[PortalConstants.PROFILE_MISC_MESSAGES_NODE]= DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","personal-profile","messages"}, false); for(int i = 1; i <= PortalConstants.MAX_COLUMNS; i++) { miscNodes[7 + i] = DOMUtil.getSingleNode(baseProfile, "profile/portal-profile/content/column[@position='"+i+"']", this.xpathProcessor); } profileMap.put(PortalConstants.PROFILE_MISC_POINTER, miscNodes); // build coplet configs NodeList coplets; int i, l; Element configElement; String copletID; String copletMedia; coplets = DOMUtil.getNodeListFromPath(baseProfile, new String[] {"profile","coplets-profile","coplets","coplet"}); if (coplets != null) { l = coplets.getLength(); for(i = 0; i < l; i++) { configElement = (Element)coplets.item(i); if (DOMUtil.getValueAsBooleanOf(configElement, "configuration/active", this.xpathProcessor)) { copletID = configElement.getAttributeNS(null, "id"); if (configElement.hasAttributeNS(null, "media")) { copletMedia = configElement.getAttributeNS(null, "media"); mediaMap = (Map)mediaCoplets.get(copletMedia); if (mediaMap != null) { mediaMap.put(copletID, configElement); } } else { copletMedia = null; defaultCoplets.put(copletID, configElement); } // Now: add the coplet if mandatory and missing if (DOMUtil.getValueAsBooleanOf(configElement, "configuration/mandatory", this.xpathProcessor)) { // get all coplet instances NodeList copletElements; // the next is crap, but it works.... // search all coplets (columns, header, footer) if (copletMedia == null) { copletElements = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/column/coplets/coplet[@id='"+copletID+"' and not(@media)]", this.xpathProcessor); } else { copletElements = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/column/coplets/coplet[@id='"+copletID+"' and media='"+copletMedia+"']", this.xpathProcessor); } if (copletElements == null || copletElements.getLength() == 0) { if (copletMedia == null) { copletElements = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/header/coplet[@id='"+copletID+"' and not(@media)]", this.xpathProcessor); } else { copletElements = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/header/coplet[@id='"+copletID+"' and media='"+copletMedia+"']", this.xpathProcessor); } } if (copletElements == null || copletElements.getLength() == 0) { if (copletMedia == null) { copletElements = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/footer/coplet[@id='"+copletID+"' and not(@media)]", this.xpathProcessor); } else { copletElements = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/footer/coplet[@id='"+copletID+"' and media='"+copletMedia+"']", this.xpathProcessor); } } if (copletElements == null || copletElements.getLength() == 0) { // mandatory coplet is not configured, so add it to the first column Node content = DOMUtil.getSingleNode(baseProfile, "profile/portal-profile/content/column[@position='1']/coplets", this.xpathProcessor); if (content == null) throw new ProcessingException("Element not found: portal-profile/content/column/coplets"); Element el = content.getOwnerDocument().createElementNS(null, "coplet"); el.setAttributeNS(null, "id", copletID); if (copletMedia != null) { el.setAttributeNS(null, "media", copletMedia); } // Set position attribute NodeList childs = DOMUtil.getNodeListFromPath(content, new String[] {"coplet"}); int childsCount = (childs == null ? 0 : childs.getLength()); el.setAttributeNS(null, "position", ""+(childsCount+1)); Text t; content.appendChild(el); content = el; el = content.getOwnerDocument().createElementNS(null, "status"); content.appendChild(el); content = el; el = content.getOwnerDocument().createElementNS(null, "visible"); content.appendChild(el); content = el; t = content.getOwnerDocument().createTextNode("true"); content.appendChild(t); } else { // is any of them visible? boolean found; boolean origVisible = DOMUtil.getValueAsBooleanOf(configElement, "status/visible", this.xpathProcessor); int si, sl; sl = copletElements.getLength(); si = 0; found = false; while (si < sl && !found) { found = DOMUtil.getValueAsBooleanOf(copletElements.item(si), "status/visible", origVisible, this.xpathProcessor); si++; } if (!found) { // set first to visible // first: is status node available Node statusElem = DOMUtil.getFirstNodeFromPath(copletElements.item(0), new String[] {"status"}, false); if (statusElem == null) { statusElem = copletElements.item(0).getOwnerDocument().createElementNS(null, "status"); copletElements.item(0).appendChild(statusElem); } // second: is visible node available Node visibleElem = DOMUtil.getFirstNodeFromPath(statusElem, new String[] {"visible"}, false); if (visibleElem == null) { visibleElem = statusElem.getOwnerDocument().createElementNS(null, "visible"); statusElem.appendChild(visibleElem); } // remove old childs while (visibleElem.hasChildNodes()) { visibleElem.removeChild(visibleElem.getFirstChild()); } visibleElem.appendChild(statusElem.getOwnerDocument().createTextNode("true")); } } } } } } // Numerate all coplets by adding an attribute number with a unique value // and put them into the corresponding maps. // update the status section of the coplet: Only the values of the coplet // configuration are allowed. Not less and not more! // All coplets are required to have // the number attribute! So this is only a compatibility function // which adds the first time the number to the coplets // If the number attribute is available, the node with the highest // number is searched NodeList copletElements; int number = 0; Element content = (Element)DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","portal-profile","content"}, false); Element currentCoplet; NodeList statusConfigList; NodeList statusCopletList; Element statusCopletElement; int list_index, list_length; Node currentStatus; int highestCopletNumber = -1; for(i = 0; i < 7; i++) { if (i == 0) { copletElements = DOMUtil.getNodeListFromPath(content, new String[] {"header","coplet"}); } else if (i == 1) { copletElements = DOMUtil.getNodeListFromPath(content, new String[] {"footer","coplet"}); } else { copletElements = DOMUtil.selectNodeList(content, "column[@position='"+(i-1)+"']/coplets/coplet", this.xpathProcessor); } if (copletElements != null && copletElements.getLength() > 0) { Element[] list = new Element[copletElements.getLength()]; for(int index = 0; index < copletElements.getLength(); index++) { list[index] = (Element)copletElements.item(index); } for(int index = 0; index < list.length; index++) { // get coplet element currentCoplet = list[index]; String numberValue = currentCoplet.getAttributeNS(null, "number"); if (numberValue == null || numberValue.length() == 0) { // create unique number attribute currentCoplet.setAttributeNS(null, "number", ""+number); miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE] = currentCoplet; number++; } else { int currentNumber = new Integer(numberValue).intValue(); if (currentNumber > highestCopletNumber) { highestCopletNumber = currentNumber; number = highestCopletNumber+1; miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE] = currentCoplet; } } // update status configElement = this.getCopletConfiguration(currentCoplet.getAttributeNS(null, "id"), defaultCoplets, mediaCoplets); if (configElement != null) { statusCopletElement = (Element)DOMUtil.selectSingleNode(configElement, "status", this.xpathProcessor); statusConfigList = DOMUtil.selectNodeList(statusCopletElement, "*", this.xpathProcessor); statusCopletList = DOMUtil.selectNodeList(currentCoplet, "status/*", this.xpathProcessor); // first test if each status is included in the config if (statusCopletList != null) { list_length = statusCopletList.getLength(); for(list_index = list_length-1; list_index >= 0; list_index--) { currentStatus = statusCopletList.item(list_index); if (currentStatus.getNodeType() == Node.ELEMENT_NODE) { if (DOMUtil.getFirstNodeFromPath(configElement, new String[] {"status", currentStatus.getNodeName()}, false) == null) { currentStatus.getParentNode().removeChild(currentStatus); } } } } // second, test if each status attribute of the config is included if (statusConfigList != null) { list_length = statusConfigList.getLength(); for(list_index = 0; list_index < list_length; list_index++) { currentStatus = statusConfigList.item(list_index); if (currentStatus.getNodeType() == Node.ELEMENT_NODE) { if (DOMUtil.getFirstNodeFromPath(statusCopletElement, new String[] {currentStatus.getNodeName()}, false) == null) { // create a new element statusCopletElement.appendChild(statusCopletElement.getOwnerDocument().importNode(currentStatus, true)); } } } } } else { // coplet not in configuration // adopt position of following coplets and then remove String posAttr = currentCoplet.getAttributeNS(null, "position"); NodeList followUps = DOMUtil.selectNodeList(currentCoplet.getParentNode(), "coplet[@position > '"+posAttr+"']", this.xpathProcessor); if (followUps != null) { int value; for(int iq = 0; iq < followUps.getLength(); iq++) { value = new Integer(((Element)followUps.item(iq)).getAttributeNS(null, "position")).intValue(); value -= 1; ((Element)followUps.item(iq)).setAttributeNS(null, "position", "" + value); } } currentCoplet.getParentNode().removeChild(currentCoplet); } } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildRunProfile"); } } /** * Add the type information to the profile and do some type checkings */ private void buildTypeProfile(Map theProfile, SessionContext context, DocumentFragment baseProfile) throws javax.xml.transform.TransformerException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildTypeProfile context="+context+", profile="+baseProfile); } List list = new ArrayList(25); List confList = new ArrayList(25); theProfile.put(PortalConstants.PROFILE_TYPE_PATHS, list); theProfile.put(PortalConstants.PROFILE_TYPE_CONF_PATHS, confList); Element typeElement; typeElement = (Element)DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","type-profile","elements"}, false); if (typeElement != null) { if (typeElement.hasChildNodes()) this.addTypePath(list, typeElement.getChildNodes(), "profile"); // now we have the list with the xpaths this.setTypeInfo(baseProfile, list, null); // build the conf paths int i, l, pos; String current; l = list.size(); for(i = 0; i < l; i++) { current = (String)list.get(i); // now the path has to be changed: the new attributes must be included pos = current.lastIndexOf('/'); current = current.substring(0, pos); pos = current.lastIndexOf('['); if (current.substring(pos+1).equals("not(@*)]")) { current = current.substring(0, pos+1); } else { current = current.substring(0, current.length()-1) + " and "; } current += "@formtype and @formpath and @formdescription]"; confList.add(current); } } // and now the type checking part: // // If the default layout has changed the number of columns and the current // user (or role) is not allowed to change this, we have to adjust the // profile. Otherwise the current number of columns has to be stored // into the profile layout part. Element layoutColumnsNode = (Element)DOMUtil.getFirstNodeFromPath(baseProfile, new String[] {"profile","layout-profile","portal","columns","number"}, false); String layoutValue = DOMUtil.getValueOfNode(layoutColumnsNode); int layoutColumns = 0; if (layoutValue != null && new Integer(layoutValue).intValue() > 0) { layoutColumns = new Integer(layoutValue).intValue(); } NodeList columnNodes = DOMUtil.selectNodeList(baseProfile, "profile/portal-profile/content/column[@position]", this.xpathProcessor); int columns = columnNodes.getLength(); if (columns != layoutColumns) { if (layoutColumnsNode.hasAttributeNS(null, "formtype")) { DOMUtil.setValueOfNode(layoutColumnsNode, ""+columns); } else { this.changeColumns(baseProfile, columns, layoutColumns, (Node[])theProfile.get(PortalConstants.PROFILE_MISC_POINTER)); this.setTypeInfo(baseProfile, (List)theProfile.get(PortalConstants.PROFILE_TYPE_PATHS), (List)theProfile.get(PortalConstants.PROFILE_TYPE_CONF_PATHS)); } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildTypeProfile"); } } /** * Set the tpe information */ private void setTypeInfo(DocumentFragment baseProfile, List paths, List confPaths) throws javax.xml.transform.TransformerException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN setTypeInfo profile="+baseProfile+", paths="+paths); } if (baseProfile != null && paths != null) { int pos; String currentPath; String value; String description; NodeList nodes; int nodes_count; int path_count = paths.size(); Node currentNode; for(int i = 0; i < path_count; i++) { currentPath = (String)paths.get(i); pos = currentPath.lastIndexOf('/'); value = currentPath.substring(pos + 1); currentPath = currentPath.substring(0, pos); pos = value.indexOf("|"); if (pos != -1) { description = value.substring(pos + 1); value = value.substring(0, pos); } else { description = "UNKNOWN"; } // get all nodes boolean changed = false; nodes = DOMUtil.selectNodeList(baseProfile, currentPath, this.xpathProcessor); if (nodes != null) { nodes_count = nodes.getLength(); for(int m = 0; m < nodes_count; m++) { currentNode = nodes.item(m); if (currentNode.getNodeType() == Node.ELEMENT_NODE) { ((Element)currentNode).setAttributeNS(null, "formtype", value); ((Element)currentNode).setAttributeNS(null, "formpath", PortalManagerImpl.REQ_PARAMETER_CONF + '.' + i + '.' + m); ((Element)currentNode).setAttributeNS(null, "formdescription", description); changed = true; } } } if (changed && confPaths != null) { currentPath = (String)confPaths.get(i); nodes = DOMUtil.selectNodeList(baseProfile, currentPath, this.xpathProcessor); if (nodes != null) { nodes_count = nodes.getLength(); for(int m = 0; m < nodes_count; m++) { currentNode = nodes.item(m); if (currentNode.getNodeType() == Node.ELEMENT_NODE) { ((Element)currentNode).setAttributeNS(null, "formpath", PortalManagerImpl.REQ_PARAMETER_CONF + '.' + i + '.' + m); } } } } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END setTypeInfo"); } } /** * Add the type info to the xpath. This is done recursevly */ private void addTypePath(List list, NodeList childs, String path) { // calling method is synced int i, l; Element current; StringBuffer newPath; l = childs.getLength(); for(i = 0; i < l; i++) { if (childs.item(i).getNodeType() == Node.ELEMENT_NODE) { current = (Element)childs.item(i); newPath = new StringBuffer(path); newPath.append('/').append(current.getNodeName()); if (current.hasAttributes()) { NamedNodeMap nnm = current.getAttributes(); int ia, la; boolean first = true; StringBuffer expression = new StringBuffer(); la = nnm.getLength(); newPath.append('['); for(ia = 0; ia < la; ia++) { if (!nnm.item(ia).getNodeName().equals("type") && !nnm.item(ia).getNodeName().equals("description")) { if (!first) expression.append(" and "); if (!nnm.item(ia).getNodeValue().equals("*")) { expression.append('@') .append(nnm.item(ia).getNodeName()) .append("='") .append(nnm.item(ia).getNodeValue()) .append("'"); } else { expression.append('@').append(nnm.item(ia).getNodeName()); } first = false; } } if (first) { newPath.append("not(@*)"); } else { newPath.append(expression); } newPath.append(']'); } else { newPath.append("[not(@*)]"); } if (current.getAttributeNS(null, "type").length() > 0) { list.add(newPath.toString() + '/' + current.getAttributeNS(null, "type") + '|' + current.getAttributeNS(null, "description")); } else { if (current.hasChildNodes()) { this.addTypePath(list, current.getChildNodes(), newPath.toString()); } } } } } /** * Build the Map with the portal layouts */ private Map buildPortalLayouts(SessionContext context, DocumentFragment baseProfile) throws ProcessingException, javax.xml.transform.TransformerException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildPortalLayouts context="+context+", profile="+baseProfile); } Map layouts = new HashMap(5, 2); Element defLayout = (Element)DOMUtil.getSingleNode(baseProfile, "profile/layout-profile/portal/layouts/layout[not(@*)]", this.xpathProcessor); Node currentLayout; String[] types = this.getMediaManager().getMediaTypes(); for(int i = 0; i < types.length; i++) { currentLayout = DOMUtil.getSingleNode(baseProfile, "profile/layout-profile/portal/layouts/layout[media='"+types[i]+"']", this.xpathProcessor); layouts.put(types[i], (currentLayout == null ? defLayout : currentLayout)); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildPortalLayouts layouts="+layouts); } return layouts; } /** * Build the Map with the coplet layouts */ private Map buildcopleyLayouts(SessionContext context, DocumentFragment baseProfile) throws ProcessingException, javax.xml.transform.TransformerException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildcopleyLayouts context="+context+", profile="+baseProfile); } Map layouts = new HashMap(5, 2); Element defLayout = (Element)DOMUtil.getSingleNode(baseProfile, "profile/layout-profile/coplets/layouts/layout[not(@*)]", this.xpathProcessor); Node currentLayout; String[] types = this.getMediaManager().getMediaTypes(); for(int i = 0; i < types.length; i++) { currentLayout = DOMUtil.getSingleNode(baseProfile, "profile/layout-profile/coplets/layouts/layout[media='"+types[i]+"']", this.xpathProcessor); layouts.put(types[i], (currentLayout == null ? defLayout : currentLayout)); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildcopleyLayouts layouts="+layouts); } return layouts; } /** * Import a delta into the profile */ private void importProfileDelta(Element profileRoot, DocumentFragment delta, String deltaRootTagName, String deltaTag) throws ProcessingException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN importProfileDelta root=" + profileRoot + ", delta=" + delta + ", deltaRoot:" + deltaRootTagName + ", delta: " + deltaTag); } Node deltaRoot = null; deltaRoot = DOMUtil.getFirstNodeFromPath(delta, new String[] {deltaRootTagName, deltaTag}, false); if (deltaRoot != null) { // root tag found in delta , now search root tag in profile String searchName = deltaRoot.getNodeName().substring(0, deltaRoot.getNodeName().lastIndexOf("-delta")); searchName = searchName + "-profile"; profileRoot = (Element)DOMUtil.getFirstNodeFromPath(profileRoot, new String[] {searchName}, false); if (profileRoot == null) { throw new ProcessingException("Importing Delta: Tag " + searchName + " not found in profile."); } // now import it this.importNode(profileRoot, (Element)deltaRoot); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END importProfileDelta"); } } /** * Add the node to the profile (replace an existing one) */ private void addProfilePart(Element profileRoot, DocumentFragment delta, String deltaRootTagName, String deltaTag) { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN addProfilePart root=" + profileRoot + ", delta=" + delta + ", deltaRoot:" + deltaRootTagName + ", delta: " + deltaTag); } Node deltaRoot = null; Node oldNode = null; if (deltaRootTagName != null) { deltaRoot = DOMUtil.getFirstNodeFromPath(delta, new String[] {deltaRootTagName, deltaTag}, false); } else { deltaRoot = DOMUtil.getFirstNodeFromPath(delta, new String[] {deltaTag}, false); } if (deltaRoot != null) { // root tag found in delta found, now search root tag in profile oldNode = DOMUtil.getFirstNodeFromPath(profileRoot, new String[] {deltaTag}, false); if (oldNode == null) { profileRoot.appendChild(profileRoot.getOwnerDocument().importNode(deltaRoot, true)); } else { profileRoot.replaceChild(profileRoot.getOwnerDocument().importNode(deltaRoot, true), oldNode); } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END addProfilePart"); } } /** * This is the hardest part. Incorporting a node into the profile. * For performance reasons there is now tracing here. */ private void importNode(Element profile, Element delta) { // calling method is synced NodeList profileChilds = null; NodeList deltaChilds = delta.getChildNodes(); int i, len; int m, l; boolean found; Node currentDelta = null; Node currentProfile = null; len = deltaChilds.getLength(); for(i = 0; i < len; i++) { currentDelta = deltaChilds.item(i); if (currentDelta.getNodeType() == Node.ELEMENT_NODE) { // search the delta node in the profile profileChilds = profile.getChildNodes(); l = profileChilds.getLength(); m = 0; found = false; while (!found && m < l) { currentProfile = profileChilds.item(m); if (currentProfile.getNodeType() == Node.ELEMENT_NODE && currentProfile.getNodeName().equals(currentDelta.getNodeName())) { // now we have found a node with the same name // next: the attributes must match also found = this.compareAttributes(currentProfile, currentDelta); } if (!found) m++; } if (found) { // this is not new // do we have elements as children or text? if (currentDelta.hasChildNodes()) { currentDelta.normalize(); currentProfile.normalize(); // do a recursive call for sub elements this.importNode((Element)currentProfile, (Element)currentDelta); // and now the text nodes: Remove all from the profile and add all // of the delta NodeList childs = currentProfile.getChildNodes(); int index, max; max = childs.getLength(); for(index = max - 1; index >= 0; index--) { if (childs.item(index).getNodeType() == Node.TEXT_NODE) { currentProfile.removeChild(childs.item(index)); } } childs = currentDelta.getChildNodes(); max = childs.getLength(); for(index = 0; index < max; index++) { if (childs.item(index).getNodeType() == Node.TEXT_NODE) { currentProfile.appendChild(currentProfile.getOwnerDocument() .createTextNode(childs.item(index).getNodeValue())); } } } } else { // this is a new node, so it is considered as an old information // No inserting: profile.appendChild(profile.getOwnerDocument().importNode(currentDelta, true)); } } } } /** * Compare Attributes of two nodes. This method returns true only if both * nodes have the same number of attributes and the same attributes with equal * values. * Namespacedefinition nodes are ignored * BUT: For type handling the attributes <code>formtype</code>, * <code>formdescription</code> and <code>formpath</code> are ignored! */ private boolean compareAttributes(Node first, Node second) { // calling method is synced NamedNodeMap attr1 = first.getAttributes(); NamedNodeMap attr2 = second.getAttributes(); String value; if (attr1 == null && attr2 == null) return true; if (attr1 == null || attr2 == null) return false; int attr1Len = (attr1 == null ? 0 : attr1.getLength()); int attr2Len = (attr2 == null ? 0 : attr2.getLength()); if (attr1Len > 0) { if (attr1.getNamedItemNS(null, "formtype") != null) attr1Len--; if (attr1.getNamedItemNS(null, "formpath") != null) attr1Len--; if (attr1.getNamedItemNS(null, "formdescription") != null) attr1Len--; int l = attr1.getLength(); for(int i=0;i<l;i++) { if (attr1.item(i).getNodeName().startsWith("xmlns:")) attr1Len--; } } if (attr2Len > 0) { if (attr2.getNamedItemNS(null, "formtype") != null) attr2Len--; if (attr2.getNamedItemNS(null, "formpath") != null) attr2Len--; if (attr2.getNamedItemNS(null, "formdescription") != null) attr2Len--; int l = attr2.getLength(); for(int i=0;i<l;i++) { if (attr2.item(i).getNodeName().startsWith("xmlns:")) attr2Len--; } } if (attr1Len != attr2Len) return false; int i, l; int m, l2; i = 0; l = attr1.getLength(); l2 = attr2.getLength(); boolean ok = true; // each attribute of first must be in second with the same value while (i < l && ok) { value = attr1.item(i).getNodeName(); if (!value.equals("formtype") && !value.equals("formpath") && !value.equals("formdescription") && !value.startsWith("xmlns:")) { ok = false; m = 0; while (m < l2 && !ok) { if (attr2.item(m).getNodeName().equals(value)) { // same name, same value? ok = attr1.item(i).getNodeValue().equals(attr2.item(m).getNodeValue()); } m++; } } i++; } return ok; } /** * Parse the fragment(tree denoted by the element) * and include the processed xml in the output */ private void processCopletList(List copletList, XMLConsumer consumer, String copletNotAvailableMessage, long defaultCopletTimeout) throws ProcessingException, SAXException, javax.xml.transform.TransformerException { // calling method is synced for(int i = 0; i < copletList.size(); i++) { this.processCoplet((Object[])copletList.get(i), consumer, copletNotAvailableMessage, defaultCopletTimeout); } } /** * Parse the fragment(tree denoted by the element) * and include the processed xml in the output */ private void loadCoplets(Element element, Map defaultCoplets, Map mediaCoplets, List copletList, boolean parallelCoplets, long defaultCopletTimeout, Element statusProfile) throws ProcessingException, javax.xml.transform.TransformerException { // calling method is synced // All children, which are coplets are processed, all other tags // are ignored if (element.hasChildNodes()) { NodeList childs = element.getChildNodes(); Node current = null; int i, l; l = childs.getLength(); for(i = 0; i < l; i++) { current = childs.item(i); if (current.getNodeType() == Node.ELEMENT_NODE && current.getNodeName().equals("coplet")) { // now we have a coplet this.loadCoplet((Element)current, defaultCoplets, mediaCoplets, copletList, parallelCoplets, defaultCopletTimeout, statusProfile); } } } } /** * Load a coplet and store the binary output in the list */ private void loadCoplet(Element element, Map defaultCoplets, Map mediaCoplets, List copletList, boolean parallelCoplets, long defaultCopletTimeout, Element statusProfile) throws ProcessingException, javax.xml.transform.TransformerException { // calling method is synced String copletID = element.getAttributeNS(null, "id"); Element copletConf = this.getCopletConfiguration(copletID, defaultCoplets, mediaCoplets); if (copletConf != null) { // first: check visibility boolean visible = DOMUtil.getValueAsBooleanOf(element, "status/visible", this.xpathProcessor); // second: check media String media = this.getMediaManager().getMediaType(); if (visible && copletConf.hasAttributeNS(null, "media")) { String copletMedia = copletConf.getAttributeNS(null, "media"); visible = media.equals(copletMedia); } if (visible) { Object[] loadedCoplet = new Object[8]; copletList.add(loadedCoplet); boolean isCustomizable = DOMUtil.getValueAsBooleanOf(copletConf, "configuration/customizable", false, this.xpathProcessor); if (isCustomizable) { boolean showCustomizePage = DOMUtil.getValueAsBooleanOf(element, "status/customize", false, this.xpathProcessor); boolean hasConfig = false; if (statusProfile != null) { Element customInfo = (Element)DOMUtil.getSingleNode(statusProfile, "customization/coplet[@id='"+copletID+"' and @number='"+element.getAttributeNS(null, "number")+"']", this.xpathProcessor); hasConfig = (customInfo != null); } if (showCustomizePage || !hasConfig ) { Node node = DOMUtil.selectSingleNode(element, "status/customize", this.xpathProcessor); DOMUtil.setValueOfNode(node, "true"); } else { Node node = DOMUtil.selectSingleNode(element, "status/customize", this.xpathProcessor); DOMUtil.setValueOfNode(node, "false"); } } else { Node node = DOMUtil.selectSingleNode(element, "status/customize", this.xpathProcessor); DOMUtil.setValueOfNode(node, "false"); } // Create the parameters for the coplet: // The <status> part is mapped to parameters // id, number and media are added SourceParameters p = DOMUtil.createParameters(DOMUtil.getFirstNodeFromPath(element, new String[] {"status"}, false), null); p.setSingleParameterValue(PortalConstants.PARAMETER_ID, copletID); p.setSingleParameterValue(PortalConstants.PARAMETER_NUMBER, element.getAttributeNS(null, "number")); p.setSingleParameterValue(PortalConstants.PARAMETER_MEDIA, media); String isPersistent = DOMUtil.getValueOf(copletConf, "configuration/persistent", "false", this.xpathProcessor); p.setSingleParameterValue(PortalConstants.PARAMETER_PERSISTENT, isPersistent); // the coplet loading is a tricky part: // we create an object array containing all information // for later processing of the coplet // so the processCoplet() method needs no lookup for information // again loadedCoplet[0] = null; loadedCoplet[1] = copletConf; loadedCoplet[2] = p; loadedCoplet[3] = element; loadedCoplet[4] = new Long(System.currentTimeMillis()); loadedCoplet[5] = new Long(DOMUtil.getValueOf(copletConf, "configuration/timeout", "-1", this.xpathProcessor)); loadedCoplet[7] = statusProfile; CopletThread copletThread = new CopletThread(); Thread theThread = new Thread(new CocoonRunnable(copletThread)); loadedCoplet[6] = copletThread; copletThread.init(copletID, ContextHelper.getObjectModel(this.componentContext), this.getLogger(), loadedCoplet, this.manager, this.resolver, this.xpathProcessor); theThread.start(); Thread.yield(); if (!parallelCoplets) { copletThread = (CopletThread)loadedCoplet[6]; if (copletThread != null) { long startTime = System.currentTimeMillis() - ((Long)loadedCoplet[4]).longValue(); long timeout = ((Long)loadedCoplet[5]).longValue(); long waitTime; if (timeout == -1) { waitTime = defaultCopletTimeout; } else { waitTime = timeout - startTime; } while (copletThread != null && waitTime > 2) { try { Thread.sleep(15); waitTime -= 15; } catch(InterruptedException local) { // ignore } copletThread = (CopletThread)loadedCoplet[6]; } loadedCoplet[6] = null; // mark as loaded } } } } } /** * Process a coplet which is previously loaded */ private void processCoplet(Object[] loadedCoplet, XMLConsumer consumer, String notAvailableMessage, long defaultCopletTimeout) throws ProcessingException, SAXException, javax.xml.transform.TransformerException { // calling method is synced Element copletConf = (Element)loadedCoplet[1]; Element element = (Element)loadedCoplet[3]; String copletID = element.getAttributeNS(null, "id"); if (copletConf != null) { AttributesImpl attr = new AttributesImpl(); attr.addAttribute("", "id", "id", "CDATA", copletID); attr.addAttribute("", "number", "number", "CDATA", element.getAttributeNS(null, "number")); attr.addAttribute("", "position", "position", "CDATA", element.getAttributeNS(null, "position")); consumer.startElement("", "coplet", "coplet", attr); attr.clear(); // now include all children of the coplet element except status NodeList children = copletConf.getChildNodes(); if (children != null && children.getLength() > 0) { int l = children.getLength(); for(int i = 0; i < l; i++) { if (!children.item(i).getNodeName().equals("status") && children.item(i).getNodeType() == Node.ELEMENT_NODE) { IncludeXMLConsumer.includeNode(children.item(i), consumer, consumer); } } } // now the status parameter // SourceParameters p = DOMUtil.createParameters(DOMUtil.getFirstNodeFromPath(element, new String[] {"status"}, false), null); consumer.startElement("", "status", "status", attr); children = DOMUtil.selectNodeList(element, "status/*", this.xpathProcessor); if (children != null && children.getLength() > 0) { int l = children.getLength(); for(int i = 0; i < l; i++) { if (children.item(i).getNodeType() == Node.ELEMENT_NODE) { IncludeXMLConsumer.includeNode(children.item(i), consumer, consumer); } } } consumer.endElement("", "status", "status"); // now the content: consumer.startElement("", "content", "content", attr); CopletThread thread = (CopletThread)loadedCoplet[6]; if (thread != null) { long startTime = System.currentTimeMillis() - ((Long)loadedCoplet[4]).longValue(); long timeout = ((Long)loadedCoplet[5]).longValue(); long waitTime; if (timeout == -1) { waitTime = defaultCopletTimeout; } else { waitTime = timeout - startTime; } while (thread != null && waitTime > 2) { try { Thread.sleep(15); waitTime -= 15; } catch(InterruptedException local) { // ignore } thread = (CopletThread)loadedCoplet[6]; } } byte[] content = (byte[])loadedCoplet[0]; if (content != null) { if (content.length > 0) { XMLDeserializer interpreter = null; try { interpreter = (XMLDeserializer)this.manager.lookup(XMLDeserializer.ROLE); interpreter.setConsumer(new IncludeXMLConsumer(consumer, consumer)); interpreter.deserialize(content); } catch (ComponentException e) { throw new ProcessingException("Component for XMLDeserializer not found." + e, e); } finally { if (interpreter != null) this.manager.release(interpreter); } } } else { notAvailableMessage = DOMUtil.getValueOf(copletConf, "configuration/messages/coplet_not_available", notAvailableMessage, this.xpathProcessor); consumer.characters(notAvailableMessage.toCharArray(), 0, notAvailableMessage.length()); } consumer.endElement("", "content", "content"); consumer.endElement("", "coplet", "coplet"); } } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#getMediaType() */ public String getMediaType() throws ProcessingException { this.setup(); return this.getMediaManager().getMediaType(); } /** * Get the coplet with the id */ private Element getCopletConfiguration(String copletID, Map defaultCoplets, Map mediaCoplets) throws ProcessingException { // calling method is synced String media = this.getMediaManager().getMediaType(); Map coplets = (Map)mediaCoplets.get(media); Element coplet = null; if (coplets != null) coplet = (Element)coplets.get(copletID); if (coplet == null) coplet = (Element)defaultCoplets.get(copletID); return coplet; } /** * Get the coplet Element */ private Element getCopletElement(String copletID, String copletNr, Node[] miscNodes) throws javax.xml.transform.TransformerException { // calling method is synced Element node = null; // first test content, then header and then footer int colindex = 8; while (node == null && colindex < 13) { if (miscNodes[colindex] != null) { node = (Element)DOMUtil.getSingleNode(miscNodes[colindex], "coplets/coplet[@id='"+copletID+"' and @number='"+copletNr+"']", this.xpathProcessor); colindex++; } else { colindex = 13; } } if (node == null && miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE] != null) { node = (Element)DOMUtil.getSingleNode(miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE], "coplet[@id='"+copletID+"' and @number='"+copletNr+"']", this.xpathProcessor); } if (node == null && miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE] != null) { node = (Element)DOMUtil.getSingleNode(miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE], "coplet[@id='"+copletID+"' and @number='"+copletNr+"']", this.xpathProcessor); } return node; } /** * Modify the coplet. * This method returns true if the type informations must be recalculated */ private boolean modifyCoplet(String requestString, SessionContext context, Map theProfile, DocumentFragment profile) throws ProcessingException, javax.xml.transform.TransformerException { // synchronized as the caller is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN modifyCoplet request=" + requestString); } boolean result = false; int pos, pos2; pos = requestString.indexOf('_'); pos2 = requestString.indexOf('_', pos+1); if (pos != -1 && pos2 != -1) { Element coplet = null; String copletID; String copletNr; String argument = null; copletID = requestString.substring(pos+1,pos2); copletNr = requestString.substring(pos2+1); pos = copletNr.indexOf('_'); if (pos != -1) { argument = copletNr.substring(pos+1); copletNr = copletNr.substring(0, pos); } // create a new coplet: in the given column, header or footer if (requestString.startsWith(PortalManagerImpl.REQ_CMD_NEW) && this.isCopletAvailable(context, copletID, (Map)theProfile.get(PortalConstants.PROFILE_DEFAULT_COPLETS), (Map)theProfile.get(PortalConstants.PROFILE_MEDIA_COPLETS))) { Node[] miscNodes = (Node[])theProfile.get(PortalConstants.PROFILE_MISC_POINTER); // determine the coplet number Node lastCoplet = miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE]; String lastNumber = null; if (lastCoplet != null) { lastNumber = ((Element)lastCoplet).getAttributeNS(null, "number"); if (lastNumber != null) { int value = new Integer(lastNumber).intValue(); value++; lastNumber = ""+value; } } if (lastNumber == null) lastNumber = "0"; Node copletsNode; if (copletNr.equals("header")) { copletsNode = miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE]; if (copletsNode == null) { copletsNode = DOMUtil.selectSingleNode(profile, "profile/portal-profile/content/header", this.xpathProcessor); miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE] = copletsNode; } else { // remove old coplet Node oldCoplet = DOMUtil.getFirstNodeFromPath(copletsNode, new String[] {"coplet"}, false); if (oldCoplet != null) copletsNode.removeChild(oldCoplet); } } else if (copletNr.equals("footer")) { copletsNode = miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE]; if (copletsNode == null) { copletsNode = DOMUtil.selectSingleNode(profile, "profile/portal-profile/content/footer", this.xpathProcessor); miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE] = copletsNode; } else { // remove old coplet Node oldCoplet = DOMUtil.getFirstNodeFromPath(copletsNode, new String[] {"coplet"}, false); if (oldCoplet != null) copletsNode.removeChild(oldCoplet); } } else { Node columnNode = miscNodes[7+new Integer(copletNr).intValue()]; copletsNode = DOMUtil.getFirstNodeFromPath(columnNode, new String[] {"coplets"}, false); } Element copletNode; Document doc = copletsNode.getOwnerDocument(); copletNode = doc.createElementNS(null, "coplet"); copletsNode.appendChild(copletNode); copletNode.setAttributeNS(null, "id", copletID); copletNode.setAttributeNS(null, "number", lastNumber); // set position NodeList childs = DOMUtil.getNodeListFromPath(copletsNode, new String[] {"coplet"}); int childsCount = (childs == null ? 0 : childs.getLength()); copletNode.setAttributeNS(null, "position", ""+(childsCount)); miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE] = copletNode; // copy status Element configElement = this.getCopletConfiguration(copletID, (Map)theProfile.get(PortalConstants.PROFILE_DEFAULT_COPLETS), (Map)theProfile.get(PortalConstants.PROFILE_MEDIA_COPLETS)); Element configStatus = (Element)DOMUtil.getFirstNodeFromPath(configElement, new String[] {"status"}, false); copletNode.appendChild(configStatus.cloneNode(true)); // clear type information for each status Element status = (Element)copletNode.getElementsByTagName("status").item(0); NodeList parameters = status.getChildNodes(); Node current; Element statusNode; if (parameters != null) { for(int i = 0; i < parameters.getLength(); i++) { current = parameters.item(i); if (current.getNodeType() == Node.ELEMENT_NODE) { statusNode = (Element)current; if (statusNode.hasAttributeNS(null, "formpath")) statusNode.removeAttributeNS(null, "formpath"); if (statusNode.hasAttributeNS(null, "formtype")) statusNode.removeAttributeNS(null, "formtype"); if (statusNode.hasAttributeNS(null, "formdescription")) statusNode.removeAttributeNS(null, "formdescription"); } } } result = true; } else { coplet = this.getCopletElement(copletID, copletNr, (Node[])theProfile.get(PortalConstants.PROFILE_MISC_POINTER)); if (coplet != null) { if (requestString.startsWith(PortalManagerImpl.REQ_CMD_CLOSE) || requestString.startsWith(PortalManagerImpl.REQ_CMD_HIDE)) { Node node = DOMUtil.selectSingleNode(coplet, "status/visible", this.xpathProcessor); DOMUtil.setValueOfNode(node, "false"); } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_OPEN) || requestString.startsWith(PortalManagerImpl.REQ_CMD_SHOW)) { Node node = DOMUtil.selectSingleNode(coplet, "status/visible", this.xpathProcessor); DOMUtil.setValueOfNode(node, "true"); } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_MINIMIZE)) { Node node = DOMUtil.selectSingleNode(coplet, "status/size", this.xpathProcessor); DOMUtil.setValueOfNode(node, "min"); } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_MAXIMIZE)) { Node node = DOMUtil.selectSingleNode(coplet, "status/size", this.xpathProcessor); DOMUtil.setValueOfNode(node, "max"); } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_CUSTOMIZE)) { Node node = DOMUtil.selectSingleNode(coplet, "status/customize", this.xpathProcessor); DOMUtil.setValueOfNode(node, "true"); } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_UPDATE)) { Node node = DOMUtil.selectSingleNode(coplet, "status/customize", this.xpathProcessor); DOMUtil.setValueOfNode(node, "false"); } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_DELETE)) { // delete the status of the coplet Node statusNode = DOMUtil.getSingleNode(profile, "profile/status-profile/customization/coplet[@id='"+copletID+"' and @number='"+copletNr+"']", this.xpathProcessor); if (statusNode != null) { statusNode.getParentNode().removeChild(statusNode); Element configElement = this.getCopletConfiguration(copletID, (Map)theProfile.get(PortalConstants.PROFILE_DEFAULT_COPLETS), (Map)theProfile.get(PortalConstants.PROFILE_MEDIA_COPLETS)); boolean isPersistent = DOMUtil.getValueAsBooleanOf(configElement, "configuration/persistent", false, this.xpathProcessor); if (isPersistent) { // mark the status profile to be saved theProfile.put(PortalConstants.PROFILE_SAVE_STATUS_FLAG, "true"); } } String posAttr = coplet.getAttributeNS(null, "position"); NodeList followUps = DOMUtil.selectNodeList(coplet.getParentNode(), "coplet[@position > '"+posAttr+"']", this.xpathProcessor); coplet.getParentNode().removeChild(coplet); coplet = null; if (followUps != null) { int value; for(int i = 0; i < followUps.getLength(); i++) { value = new Integer(((Element)followUps.item(i)).getAttributeNS(null, "position")).intValue(); value -= 1; ((Element)followUps.item(i)).setAttributeNS(null, "position", "" + value); } } } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_MOVE)) { if (argument != null) { Element copletsElement = (Element)DOMUtil.getSingleNode(profile, "profile/portal-profile/content/column[@position='"+argument+"']/coplets", this.xpathProcessor); if (copletsElement != null) { if (!coplet.getParentNode().equals(copletsElement)) { String posAttr = coplet.getAttributeNS(null, "position"); NodeList followUps = DOMUtil.selectNodeList(coplet.getParentNode(), "coplet[@position > '"+posAttr+"']", this.xpathProcessor); coplet.getParentNode().removeChild(coplet); // set position attribute NodeList childs = DOMUtil.getNodeListFromPath(copletsElement, new String[] {"coplet"}); int childsCount = (childs == null ? 0 : childs.getLength()); coplet.setAttributeNS(null, "position", "" + (childsCount + 1)); copletsElement.appendChild(coplet); if (followUps != null) { int value; for(int i = 0; i < followUps.getLength(); i++) { value = new Integer(((Element)followUps.item(i)).getAttributeNS(null, "position")).intValue(); value -= 1; ((Element)followUps.item(i)).setAttributeNS(null, "position", "" + value); } } } } } } else if (requestString.startsWith(PortalManagerImpl.REQ_CMD_MOVEROW)) { if (argument != null) { Element newCoplet = (Element)DOMUtil.getSingleNode(coplet.getParentNode(), "coplet[@position='"+argument+"']", this.xpathProcessor); if (newCoplet != null) { String position = coplet.getAttributeNS(null, "position"); coplet.removeAttributeNS(null, "position"); coplet.setAttributeNS(null, "position", argument); newCoplet.removeAttributeNS(null, "position"); newCoplet.setAttributeNS(null, "position", position); } } } } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END modifyCoplet calculate="+result); } return result; } /** * Check if the coplet is available for the current logged in user * If the user is not logged in, this returns false. * First the default coplets are searched. If none is found then * the coplets for each media are searched. */ private boolean isCopletAvailable(SessionContext context, String copletID, Map defaultCoplets, Map mediaCoplets) { // no sync required if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN isCopletAvailable coplet="+copletID); } boolean result = false; if (context != null) { result = defaultCoplets.containsKey(copletID); if (!result) { Iterator iter = mediaCoplets.values().iterator(); while (!result && iter.hasNext()) { result = ((Map)iter.next()).containsKey(copletID); } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END isCopletAvailable result=" + result); } return result; } /* (non-Javadoc) * @see org.apache.cocoon.webapps.portal.components.PortalManager#checkAuthentication(org.apache.cocoon.environment.Redirector, java.lang.String) */ public boolean checkAuthentication(Redirector redirector, String copletID) throws SAXException, IOException, ProcessingException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN checkAuthentication coplet="+copletID); } this.setup(); boolean result = false; SessionContext context = this.getContext(false); if (context != null && context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE) != null) { try { this.getTransactionManager().startReadingTransaction(context); Map theProfile = this.retrieveProfile(this.getProfileID(PortalManagerImpl.BUILDTYPE_VALUE_ID, (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE), (String)context.getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID), false)); if (theProfile != null) { if (copletID == null || copletID.trim().length() == 0) { result = true; } else { result = this.isCopletAvailable(context, copletID, (Map)theProfile.get(PortalConstants.PROFILE_DEFAULT_COPLETS), (Map)theProfile.get(PortalConstants.PROFILE_MEDIA_COPLETS)); } } } finally { this.getTransactionManager().stopReadingTransaction(context); } // end synced } if (!result) { Map config = this.getConfiguration(); if (config != null) { String redirectURI = (String)config.get(PortalConstants.CONF_AUTH_REDIRECT); if (redirectURI == null) { redirectURI = (String)config.get(PortalConstants.CONF_PORTAL_URI); } if (redirectURI != null) { redirector.globalRedirect( false, redirectURI ); } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END checkAuthentication result=" + result); } return result; } /** * Get the configuration. This configuration is an authentication application configuration * for the current application with the name "portal". * The first time this configuration is build it is stored in the session * so later requests get the cached result. */ private Map getConfiguration() throws ProcessingException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN getConfiguration"); } Map result = null; RequestState reqstate = this.getRequestState(); String appName = reqstate.getApplicationName(); String handlerName = reqstate.getHandlerName(); Session session = this.getSessionManager().getSession(false); if (session != null && appName != null && handlerName != null) { synchronized (session) { result = (Map)session.getAttribute(PortalConstants.ATTRIBUTE_CONFIGURATION + handlerName + ':' + appName); if (result == null) { try { Configuration config; Configuration conf = reqstate.getModuleConfiguration(PortalConstants.AUTHENTICATION_MODULE_NAME); if (conf == null) { throw new ProcessingException("portal: Configuration for application '" + appName + "' not found."); } result = new HashMap(10, 2); // auth-redirect (optional) config = conf.getChild("auth-redirect", false); if (config != null) { result.put(PortalConstants.CONF_AUTH_REDIRECT, config.getValue()); } // portal-uri (required) config = conf.getChild("portal-uri", false); if (config == null) { throw new ProcessingException("portal: portal-uri required for application '"+appName+"'"); } result.put(PortalConstants.CONF_PORTAL_URI, config.getValue()); // profile-cache (optional) config = conf.getChild("profile-cache", false); if (config != null && config.getValueAsBoolean()) { result.put(PortalConstants.CONF_PROFILE_CACHE, appName); } // parallel coplets config = conf.getChild("process-coplets-parallel", false); if (config != null) { result.put(PortalConstants.CONF_PARALLEL_COPLETS, new Boolean(config.getValueAsBoolean(false))); } else { result.put(PortalConstants.CONF_PARALLEL_COPLETS, Boolean.FALSE); } // timeout config = conf.getChild("default-coplet-timeout", false); if (config != null) { result.put(PortalConstants.CONF_COPLET_TIMEOUT, new Long(config.getValueAsLong(600000))); } else { result.put(PortalConstants.CONF_COPLET_TIMEOUT, new Long(600000)); } // and now the profile config = conf.getChild("profile", false); if (config == null) throw new ProcessingException("portal: profile configuration required for application '" + appName + "'"); Configuration child; // build resource (optional) child = config.getChild("buildprofile", false); if (child != null) { result.put(PortalConstants.CONF_BUILD_RESOURCE, child.getAttribute("uri")); } // base resource, type is optional child = config.getChild("layout-base", false); if (child == null) { throw new ProcessingException("portal: layout-base required for application '" + appName + "'"); } result.put(PortalConstants.CONF_LAYOUTBASE_RESOURCE, child.getAttribute("uri")); child = config.getChild("coplet-base", false); if (child == null) { throw new ProcessingException("portal: coplet-base required for application '" + appName + "'"); } result.put(PortalConstants.CONF_COPLETBASE_RESOURCE, child.getAttribute("uri")); child = config.getChild("type-base", false); if (child != null) { result.put(PortalConstants.CONF_TYPEBASE_RESOURCE, child.getAttribute("uri")); } // coplet base save (is optional) child = config.getChild("coplet-base-save", false); if (child != null) { result.put(PortalConstants.CONF_COPLETBASE_SAVE_RESOURCE, child.getAttribute("uri")); } // global delta (load required) child = config.getChild("global-delta-load", false); if (child == null) { throw new ProcessingException("portal: global-delta-load required for application '" + appName + "'"); } result.put(PortalConstants.CONF_GLOBALDELTA_LOADRESOURCE, child.getAttribute("uri")); child = config.getChild("global-delta-save", false); if (child != null) { result.put(PortalConstants.CONF_GLOBALDELTA_SAVERESOURCE, child.getAttribute("uri")); } child = config.getChild("global-type-delta", false); if (child != null) { result.put(PortalConstants.CONF_GLOBALDELTA_TYPERESOURCE, child.getAttribute("uri")); } // role delta (optional) child = config.getChild("role-delta-load", false); if (child != null) { result.put(PortalConstants.CONF_ROLEDELTA_LOADRESOURCE, child.getAttribute("uri")); } child = config.getChild("role-delta-save", false); if (child != null) { result.put(PortalConstants.CONF_ROLEDELTA_SAVERESOURCE, child.getAttribute("uri")); } child = config.getChild("role-type-delta", false); if (child != null) { result.put(PortalConstants.CONF_ROLEDELTA_TYPERESOURCE, child.getAttribute("uri")); } // User delta child = config.getChild("user-delta-load", false); if (child != null) { result.put(PortalConstants.CONF_USERDELTA_LOADRESOURCE, child.getAttribute("uri")); } child = config.getChild("user-delta-save", false); if (child != null) { result.put(PortalConstants.CONF_USERDELTA_SAVERESOURCE, child.getAttribute("uri")); } child = config.getChild("user-type-delta", false); if (child != null) { result.put(PortalConstants.CONF_USERDELTA_TYPERESOURCE, child.getAttribute("uri")); } // Personal information child = config.getChild("user-status-load", false); if (child != null) { result.put(PortalConstants.CONF_STATUS_LOADRESOURCE, child.getAttribute("uri")); } child = config.getChild("user-status-save", false); if (child != null) { result.put(PortalConstants.CONF_STATUS_SAVERESOURCE, child.getAttribute("uri")); } // Admin Type profil child = config.getChild("admin-type-base", false); if (child != null) { result.put(PortalConstants.CONF_ADMIN_TYPE_BASE, child.getAttribute("uri")); } // store the config in the session session.setAttribute(PortalConstants.ATTRIBUTE_CONFIGURATION + handlerName + ':' + appName, result); } catch (ConfigurationException conf) { throw new ProcessingException("ConfigurationException: " + conf, conf); } } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END getConfiguration conf="+result); } return result; } /** * Build the profile for the required level if not already done */ private void createProfile(SessionContext context, String type, String role, String id, boolean adminProfile) throws SAXException, IOException, ProcessingException { // no sync required if (this.getLogger().isDebugEnabled() ) { this.getLogger().debug("BEGIN createProfile context="+context+ ", type="+type+ ", role="+role+ ", id="+id); } RequestState reqstate = this.getRequestState(); SourceParameters pars = reqstate.getHandler().getContext().getContextInfoAsParameters(); pars.setSingleParameterValue("type", type); pars.setSingleParameterValue("admin", (adminProfile ? "true" : "false")); if (!type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID) || role != null) { pars.setSingleParameterValue("ID", id); pars.setSingleParameterValue("role", role); } else { id = pars.getParameter("ID", null); role = pars.getParameter("role", null); } Map map = this.getConfiguration(); if (map == null) { throw new ProcessingException("portal Configuration not found."); } // is the configuration build by using a own resource? String resource = (String)map.get(PortalConstants.CONF_BUILD_RESOURCE); if (resource != null) { if (this.getLogger().isInfoEnabled()) { this.getLogger().info("Building portal profile: " + resource); } SourceUtil.readDOM(resource, null, pars, this.resolver); } else { this.buildProfile(type, role, id, adminProfile); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END createProfile"); } } /** * Get the base profile for the current application. * The base profile consists of the layout and the coplet profile * and optional the type profile */ private DocumentFragment buildBaseProfile(Map config, boolean adminProfile) throws ProcessingException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildBaseProfile config="+config+", adminProfile="+adminProfile); } DocumentFragment copletsFragment; DocumentFragment layoutFragment; DocumentFragment typeFragment; DocumentFragment profile; Document profileDoc; Element profileRoot; String res; SourceParameters pars = new SourceParameters(); RequestState reqstate = this.getRequestState(); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); pars.setSingleParameterValue("profile", "coplet-base"); // First load the base profiles: copletProfile + layoutProfile res = (String)config.get(PortalConstants.CONF_COPLETBASE_RESOURCE); if (res == null) { throw new ProcessingException("No configuration for portal-coplet base profile found."); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("Loading coplet base profile"); } copletsFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("coplet base profile loaded"); } res = (String)config.get(PortalConstants.CONF_LAYOUTBASE_RESOURCE); if (res == null) { throw new ProcessingException("No configuration for portal-layout base profile found."); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading layout base profile"); } pars.setSingleParameterValue("profile", "layout-base"); layoutFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("layout base profile loaded"); } // now create the base profile containing the above profiles profileDoc = DOMUtil.createDocument(); profile = profileDoc.createDocumentFragment(); profileRoot = profileDoc.createElementNS(null, "profile"); profile.appendChild(profileRoot); profileRoot.appendChild(profileDoc.importNode(DOMUtil.selectSingleNode(layoutFragment, "layout-profile", this.xpathProcessor), true)); profileRoot.appendChild(profileDoc.importNode(DOMUtil.selectSingleNode(copletsFragment, "coplets-profile", this.xpathProcessor), true)); // if avalailable append the type profile if (adminProfile) { res = (String)config.get(PortalConstants.CONF_ADMIN_TYPE_BASE); pars.setSingleParameterValue("profile", "admin-type-base"); } else { res = (String)config.get(PortalConstants.CONF_TYPEBASE_RESOURCE); pars.setSingleParameterValue("profile", "type-base"); } if (res != null) { if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading type base profile"); } typeFragment = SourceUtil.readDOM(res, null, pars, this.resolver); profileRoot.appendChild(profileDoc.importNode(DOMUtil.selectSingleNode(typeFragment, "type-profile", this.xpathProcessor), true)); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("type base profile loaded"); } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildBaseProfile profile=" + profile); } return profile; } /** * Build the global profile. */ private void buildGlobalProfile(Element profileRoot, Map config, boolean adminProfile) throws ProcessingException { // calling method is synced if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN buildGlobalProfile profileRoot="+profileRoot+", config="+config+", adminProfile="+adminProfile); } DocumentFragment globalFragment; String res = (String)config.get(PortalConstants.CONF_GLOBALDELTA_LOADRESOURCE); if (res == null) { throw new ProcessingException("No configuration for portal-role delta profile found."); } SourceParameters pars = new SourceParameters(); RequestState reqstate = this.getRequestState(); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); pars.setSingleParameterValue("profile", "global-delta"); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading global profile"); } globalFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("global profile loaded"); } this.importProfileDelta(profileRoot, globalFragment, "global-delta", "layout-delta"); this.importProfileDelta(profileRoot, globalFragment, "global-delta", "coplets-delta"); this.addProfilePart(profileRoot, globalFragment, "global-delta", "portal-profile"); this.addProfilePart(profileRoot, globalFragment, "global-delta", "personal-profile"); // types res = (String)config.get(PortalConstants.CONF_GLOBALDELTA_TYPERESOURCE); if (!adminProfile && res != null) { pars.setSingleParameterValue("profile", "global-type-delta"); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading global type profile"); } globalFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("global type profile loaded"); } this.addProfilePart(profileRoot, globalFragment, "global-delta", "type-profile"); } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END buildGlobalProfile"); } } /** * Build the role profile */ private void buildRoleProfile(Element profileRoot, Map config, String role, boolean adminProfile) throws ProcessingException { // calling method is synced DocumentFragment roleFragment; RequestState reqstate = this.getRequestState(); SourceParameters pars; pars = new SourceParameters(); pars.setSingleParameterValue("role", role); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); pars.setSingleParameterValue("profile", "role-delta"); String res = (String)config.get(PortalConstants.CONF_ROLEDELTA_LOADRESOURCE); if (res != null) { if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading role profile"); } roleFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("role profile loaded"); } this.importProfileDelta(profileRoot, roleFragment, "role-delta", "layout-delta"); this.importProfileDelta(profileRoot, roleFragment, "role-delta", "coplets-delta"); this.addProfilePart(profileRoot, roleFragment, "role-delta", "portal-profile"); this.importProfileDelta(profileRoot, roleFragment, "role-delta", "personal-delta"); } // types res = (String)config.get(PortalConstants.CONF_ROLEDELTA_TYPERESOURCE); if (!adminProfile && res != null) { pars.setSingleParameterValue("profile", "role-type-delta"); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading role type profile"); } roleFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("role type profile loaded"); } this.addProfilePart(profileRoot, roleFragment, "role-delta", "type-profile"); } } /** * Build the user profile */ private void buildUserProfile(Element profileRoot, Map config, String role, String id, boolean adminProfile) throws ProcessingException { // calling method is synced DocumentFragment userFragment; RequestState reqstate = this.getRequestState(); SourceParameters pars; pars = new SourceParameters(); pars.setSingleParameterValue("ID", id); pars.setSingleParameterValue("role", role); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); pars.setSingleParameterValue("profile", "user-delta"); String res = (String)config.get(PortalConstants.CONF_USERDELTA_LOADRESOURCE); if (res != null) { if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading user profile"); } userFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("user profile loaded"); } this.importProfileDelta(profileRoot, userFragment, "user-delta", "layout-delta"); this.importProfileDelta(profileRoot, userFragment, "user-delta", "coplets-delta"); this.addProfilePart(profileRoot, userFragment, "user-delta", "portal-profile"); this.importProfileDelta(profileRoot, userFragment, "user-delta", "personal-delta"); } // types res = (String)config.get(PortalConstants.CONF_USERDELTA_TYPERESOURCE); if (!adminProfile && res != null) { pars.setSingleParameterValue("profile", "user-type-delta"); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading user type profile"); } userFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("user type profile loaded"); } this.addProfilePart(profileRoot, userFragment, "user-delta", "type-profile"); } } /** * Load the user status profile (if available) */ private void buildUserStatusProfile(Element profileRoot, Map config, String role, String id) throws ProcessingException { // calling method is synced String res = (String)config.get(PortalConstants.CONF_STATUS_LOADRESOURCE); // remove the old status profile Node statusProfile = DOMUtil.getFirstNodeFromPath(profileRoot, new String[] {"status-profile"}, false); if (statusProfile != null) { profileRoot.removeChild(statusProfile); } if (res != null) { DocumentFragment userFragment; SourceParameters pars; RequestState reqstate = this.getRequestState(); pars = new SourceParameters(); pars.setSingleParameterValue("ID", id); pars.setSingleParameterValue("role", role); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); pars.setSingleParameterValue("profile", "user-status"); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("loading user status profile"); } userFragment = SourceUtil.readDOM(res, null, pars, this.resolver); if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("user status profile loaded"); } this.addProfilePart(profileRoot, userFragment, null, "status-profile"); } // test if the status-profile node is available // if not create one if (DOMUtil.getFirstNodeFromPath(profileRoot, new String[] {"status-profile"}, false) == null) { statusProfile = profileRoot.getOwnerDocument().createElementNS(null, "status-profile"); profileRoot.appendChild(statusProfile); } } /** * Save the user status profile (if available) */ private void saveUserStatusProfile(Map profile, Map config, String role, String id) throws ProcessingException { // calling method is synced String res = (String)config.get(PortalConstants.CONF_STATUS_SAVERESOURCE); Element statusProfile = (Element)DOMUtil.getFirstNodeFromPath((DocumentFragment)profile.get(PortalConstants.PROFILE_PROFILE), new String[] {"profile","status-profile"}, false); if (res != null && statusProfile != null) { DocumentFragment userFragment = statusProfile.getOwnerDocument().createDocumentFragment(); Element saveStatus = (Element)statusProfile.cloneNode(true); userFragment.appendChild(saveStatus); // now filter all not persistent coplets! NodeList list = DOMUtil.getNodeListFromPath(saveStatus, new String[] {"customization","coplet"}); String copletID; Element coplet; Element copletConfig; Map copletConfigs = (Map)profile.get(PortalConstants.PROFILE_DEFAULT_COPLETS); Map mediaCopletConfigs = (Map)profile.get(PortalConstants.PROFILE_MEDIA_COPLETS); boolean isPersistent; for(int i = 0; i < list.getLength(); i++) { coplet = (Element)list.item(i); copletID = coplet.getAttributeNS(null, "id"); copletConfig = this.getCopletConfiguration(copletID, copletConfigs, mediaCopletConfigs); isPersistent = DOMUtil.getValueAsBooleanOf(copletConfig, "configuration/persistent", false, this.xpathProcessor); if (!isPersistent) { coplet.getParentNode().removeChild(coplet); } } try { RequestState reqstate = this.getRequestState(); SourceParameters pars; pars = new SourceParameters(); pars.setSingleParameterValue("ID", id); pars.setSingleParameterValue("role", role); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); pars.setSingleParameterValue("profile", "user-status"); SourceUtil.writeDOM(res, null, pars, userFragment, this.resolver, "xml"); } finally { userFragment.removeChild(saveStatus); } } } /** * Change the profile according to the request parameter */ private void changeProfile() throws ProcessingException, SAXException, IOException { // synchronized if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN changeProfile"); } Request request = ContextHelper.getRequest(this.componentContext); SessionContext context = this.getContext(false); if (context != null) { try { Map theProfile = null; String profileID = request.getParameter(PortalManagerImpl.REQ_PARAMETER_PROFILE); if (profileID != null) { theProfile = this.retrieveProfile(profileID); } if (theProfile != null) { synchronized (context) { DocumentFragment profile = (DocumentFragment)theProfile.get(PortalConstants.PROFILE_PROFILE); Node[] miscNodes = (Node[])theProfile.get(PortalConstants.PROFILE_MISC_POINTER); Element columns = (Element)miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE]; Enumeration enumeration = request.getParameterNames(); String current; boolean saveProfile = false; // first iteration: all changing commands while (enumeration.hasMoreElements()) { current = (String)enumeration.nextElement(); if (current.startsWith(PortalManagerImpl.REQ_PARAMETER_CONF)) { int pos1, pos2; pos1 = current.indexOf('.'); pos2 = current.indexOf('.', pos1+1); if (pos1 != -1 && pos2 != -1) { int pathIndex = new Integer(current.substring(pos1+1, pos2)).intValue(); int place= new Integer(current.substring(pos2+1)).intValue(); List typePaths = (List)theProfile.get(PortalConstants.PROFILE_TYPE_CONF_PATHS); String path = (String)typePaths.get(pathIndex); if (path != null) { NodeList nodes = DOMUtil.selectNodeList(profile, path, this.xpathProcessor); if (nodes != null) { Node node = nodes.item(place); if (node != null) { if (!node.equals(columns)) { DOMUtil.setValueOfNode(node, request.getParameter(current)); } } } } } } } // second: all new boolean calculate = false; enumeration = request.getParameterNames(); while (enumeration.hasMoreElements()) { current = (String)enumeration.nextElement(); if (current.startsWith(PortalManagerImpl.REQ_PARAMETER_CONF)) { int pos1, pos2; pos1 = current.indexOf('.'); pos2 = current.indexOf('.', pos1+1); if (pos1 != -1 && pos2 != -1) { int pathIndex = new Integer(current.substring(pos1+1, pos2)).intValue(); int place= new Integer(current.substring(pos2+1)).intValue(); List typePaths = (List)theProfile.get(PortalConstants.PROFILE_TYPE_CONF_PATHS); String path = (String)typePaths.get(pathIndex); if (path != null) { NodeList nodes = DOMUtil.selectNodeList(profile, path, this.xpathProcessor); if (nodes != null) { Node node = nodes.item(place); if (node != null) { if (node.equals(columns)) { int columnNumber = new Integer(request.getParameter(current)).intValue(); int oldNumber = new Integer(DOMUtil.getValueOfNode(columns)).intValue(); if (columnNumber > 0 && columnNumber != oldNumber && columnNumber <= PortalConstants.MAX_COLUMNS) { this.changeColumns(profile, oldNumber, columnNumber, miscNodes); calculate = true; DOMUtil.setValueOfNode(node, request.getParameter(current)); } } } } } } } else if (current.equals(PortalManagerImpl.REQ_PARAMETER_CMD)) { String[] cmds = request.getParameterValues(current); if (cmds != null && cmds.length > 0) { for(int i = 0; i < cmds.length; i++) { if (cmds[i].equals(PortalManagerImpl.REQ_CMD_SAVEPROFILE)) { saveProfile = true; } else { if (this.modifyCoplet(cmds[i], context, theProfile, profile)) { calculate = true; } } } } } } // set type infos if (calculate) { this.setTypeInfo(profile, (List)theProfile.get(PortalConstants.PROFILE_TYPE_PATHS), (List)theProfile.get(PortalConstants.PROFILE_TYPE_CONF_PATHS)); } // test if the status profile changed Object statusChanged = theProfile.get(PortalConstants.PROFILE_SAVE_STATUS_FLAG); if (statusChanged != null) { theProfile.remove(PortalConstants.PROFILE_SAVE_STATUS_FLAG); this.saveUserStatusProfile(theProfile, this.getConfiguration(), this.getRole(profileID), this.getID(profileID)); } // save the profile if (saveProfile) { Map conf = this.getConfiguration(); String role = this.getRole(profileID); String id = this.getID(profileID); String type = this.getType(profileID); String saveResource; String profileType; if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) { saveResource = (String)conf.get(PortalConstants.CONF_GLOBALDELTA_SAVERESOURCE); profileType = "global-delta"; } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) { saveResource = (String)conf.get(PortalConstants.CONF_ROLEDELTA_SAVERESOURCE); profileType = "role-delta"; } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) { saveResource = (String)conf.get(PortalConstants.CONF_USERDELTA_SAVERESOURCE); profileType = "user-delta"; } else { throw new ProcessingException("portal: No save resource defined for type '"+type+"'."); } // patch // search for all "status/customize" nodes and set them // to false NodeList statusNodes = DOMUtil.selectNodeList(profile, "profile/portal-profile/content/descendant::status/customize", this.xpathProcessor); if (statusNodes != null) { String value; for(int l=0; l < statusNodes.getLength(); l++) { value = DOMUtil.getValueOfNode(statusNodes.item(l)); if (value.equals("true")) { DOMUtil.setValueOfNode(statusNodes.item(l), "false"); } } } // build delta RequestState reqstate = this.getRequestState(); DocumentFragment delta; delta = this.buildProfileDelta(type, role, id, this.getIsAdminProfile(profileID)); SourceParameters pars = new SourceParameters(); pars.setSingleParameterValue("type", profileType); if (id != null) pars.setSingleParameterValue("ID", id); if (role != null) pars.setSingleParameterValue("role", role); pars.setSingleParameterValue("application", reqstate.getApplicationName()); pars.setSingleParameterValue("handler", reqstate.getHandlerName()); SourceUtil.writeDOM(saveResource, null, pars, delta, this.resolver, "xml"); if (delta.getParentNode() != null) delta.getParentNode().removeChild(delta); delta = null; // cache the profile // The profile is only cached if it is already in the cache! // Why? During login the profile is build and cached, so it is in the cache. // But: If a user logs in, the profile is cached. // Now the admin logs in, changes the global profile and saves it. // The cache is invalidated, including the user profile. // Now the user changes his profile and saves it. // If it now would be cached, it would be invalid as it would // not reflect the changes by the admin. // But if the old profile is still in the cache, nobody // has changed a profile above. // Note CZ: The above is correct, but for building the delta // the "previous" profile is build and cached ! Thus we can // easily cache the new profile. // if (this.isProfileCached(profileID, conf)) { this.cacheProfile(profileID, theProfile, conf); // cache it // now the hardest part, clean up the cache this.cleanUpCache(type, role, conf); // } } } // end synchronized } } catch (javax.xml.transform.TransformerException local) { throw new ProcessingException("TransformerException: " + local, local); } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END changeProfile"); } } /** * Change the number of the columns */ private void changeColumns(DocumentFragment profile, int oldNumber, int columnNumber, Node[] miscNodes) throws javax.xml.transform.TransformerException { // calling method is (hopefully) synced if (columnNumber < oldNumber) { // remove columns and all coplets to the first one Node columnNode; Node firstColumn = DOMUtil.getSingleNode(profile, "profile/portal-profile/content/column[@position='1']/coplets", this.xpathProcessor); NodeList firstColumnCoplets = DOMUtil.getNodeListFromPath(firstColumn, new String[] {"coplet"}); int copletsCount = (firstColumnCoplets == null ? 0 : firstColumnCoplets.getLength()); for(int i = columnNumber + 1; i <= oldNumber; i++) { columnNode = miscNodes[7+i]; if (columnNode != null) { NodeList coplets = DOMUtil.getNodeListFromPath(columnNode, new String[] {"coplets","coplet"}); Node coplet; if (coplets != null && coplets.getLength() > 0) { for(int m = 0; m < coplets.getLength(); m++) { coplet = coplets.item(m); coplet.getParentNode().removeChild(coplet); copletsCount++; ((Element)coplet).setAttributeNS(null, "position", "" + copletsCount); firstColumn.appendChild(coplet); } } columnNode.getParentNode().removeChild(columnNode); miscNodes[7+i] = null; } } } else if (columnNumber <= PortalConstants.MAX_COLUMNS) { // add new columns Node contentNode = DOMUtil.getFirstNodeFromPath(profile, new String[] {"profile","portal-profile","content"}, false); Document doc = contentNode.getOwnerDocument(); Element newColumn; Element el; for(int i = oldNumber + 1; i <= columnNumber; i++) { newColumn = doc.createElementNS(null, "column"); newColumn.setAttributeNS(null, "position", ""+i); miscNodes[7+i] = newColumn; contentNode.appendChild(newColumn); el = doc.createElementNS(null, "width"); el.appendChild(doc.createTextNode("5%")); newColumn.appendChild(el); el = doc.createElementNS(null, "coplets"); newColumn.appendChild(el); } } } /** * Send SAX events to the next pipeline component. * The node is parsed and the events are send to * the next component in the pipeline. * @param node The tree to be included. */ protected void sendEvents(XMLConsumer consumer, Node node) throws SAXException { IncludeXMLConsumer.includeNode(node, consumer, consumer); } /** * Get all users in a document fragment with the following children: * <users> * <user> * <ID>...</ID> * <role>...</role> <!-- optional --> * <data> * ... * </data> * </user> * .... * </users> * The document fragment might contain further nodes at the root! * If <code>role</code> is <code>null</code> all users are fetched, * otherwise only the users for this role. * If also ID is not null only the single user is fetched. */ private Document getUsers(String role, String ID) throws IOException, ProcessingException, SAXException { // calling method is syned if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN getUsers role="+role+", ID="+ID); } RequestState reqstate = this.getRequestState(); Document frag = null; Configuration conf = reqstate.getModuleConfiguration("single-role-user-management"); if (conf != null) { // get load-users resource (optional) Configuration child = conf.getChild("load-users", false); if (child != null) { String loadUsersResource = child.getAttribute("uri", null); SourceParameters loadUsersResourceParameters = SourceParameters.create(child); if (loadUsersResource != null) { SourceParameters parameters = (loadUsersResourceParameters == null) ? new SourceParameters() : loadUsersResourceParameters; if (reqstate.getApplicationName() != null) parameters.setSingleParameterValue("application", reqstate.getApplicationName()); if (ID != null) { parameters.setSingleParameterValue("type", "user"); parameters.setSingleParameterValue("ID", ID); } else { parameters.setSingleParameterValue("type", "users"); } if (role != null) parameters.setSingleParameterValue("role", role); frag = this.loadResource(loadUsersResource, parameters); } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END getUsers fragment="+(frag == null ? "null" : XMLUtils.serializeNode(frag, XMLUtils.createPropertiesForXML(false)))); } return frag; } /** * Get all roles in a document fragment with the following children: * <roles> * <role>...</role> * .... * </roles> * The document fragment might contain further nodes at the root! */ private Document getRoles() throws IOException, ProcessingException, SAXException { // calling method is syned if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("BEGIN getRoles"); } Document frag = null; RequestState reqstate = this.getRequestState(); Configuration conf = reqstate.getModuleConfiguration("single-role-user-management"); if (conf != null) { // get load-roles resource (optional) Configuration child = conf.getChild("load-roles", false); if (child != null) { String loadRolesResource = child.getAttribute("uri", null); SourceParameters loadRolesResourceParameters = SourceParameters.create(child); if (loadRolesResource != null) { SourceParameters parameters = (loadRolesResourceParameters == null) ? new SourceParameters() : loadRolesResourceParameters; if (reqstate.getApplicationName() != null) parameters.setSingleParameterValue("application", reqstate.getApplicationName()); parameters.setSingleParameterValue("type", "roles"); frag = this.loadResource(loadRolesResource, parameters); } } } if (this.getLogger().isDebugEnabled()) { this.getLogger().debug("END getRoles fragment="+frag); } return frag; } /** * Load XML resource */ private Document loadResource(String resource, SourceParameters parameters) throws IOException, ProcessingException, SAXException { Source source = null; try { source = SourceUtil.getSource(resource, null, parameters, this.resolver); return SourceUtil.toDOM(source); } catch (SourceException se) { throw SourceUtil.handle(se); } finally { this.resolver.release(source); } } /** * Get the SessionManager component */ protected SessionManager getSessionManager() throws ProcessingException { if (this.sessionManager == null) { try { this.sessionManager = (SessionManager)this.manager.lookup(SessionManager.ROLE); } catch (ComponentException ce) { throw new ProcessingException("Error during lookup of SessionManager component.", ce); } } return this.sessionManager; } /** * Get the ContextManager component */ protected ContextManager getContextManager() throws ProcessingException { if (this.contextManager == null) { try { this.contextManager = (ContextManager)this.manager.lookup(ContextManager.ROLE); } catch (ComponentException ce) { throw new ProcessingException("Error during lookup of ContextManager component.", ce); } } return this.contextManager; } /** * Get the ContextManager component */ protected TransactionManager getTransactionManager() throws ProcessingException { if (this.transactionManager == null) { try { this.transactionManager = (TransactionManager)this.manager.lookup(TransactionManager.ROLE); } catch (ComponentException ce) { throw new ProcessingException("Error during lookup of TransactionManager component.", ce); } } return this.transactionManager; } }