0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.cocoon.webapps.portal.components;
0018:
0019: import java.io.IOException;
0020: import java.util.ArrayList;
0021: import java.util.Enumeration;
0022: import java.util.HashMap;
0023: import java.util.Iterator;
0024: import java.util.List;
0025: import java.util.Map;
0026:
0027: import org.apache.avalon.excalibur.pool.Recyclable;
0028: import org.apache.avalon.framework.activity.Disposable;
0029: import org.apache.avalon.framework.component.Component;
0030: import org.apache.avalon.framework.component.ComponentException;
0031: import org.apache.avalon.framework.component.ComponentManager;
0032: import org.apache.avalon.framework.component.Composable;
0033: import org.apache.avalon.framework.component.Recomposable;
0034: import org.apache.avalon.framework.configuration.Configuration;
0035: import org.apache.avalon.framework.configuration.ConfigurationException;
0036: import org.apache.avalon.framework.context.Context;
0037: import org.apache.avalon.framework.context.ContextException;
0038: import org.apache.avalon.framework.context.Contextualizable;
0039: import org.apache.avalon.framework.logger.AbstractLogEnabled;
0040: import org.apache.cocoon.ProcessingException;
0041: import org.apache.cocoon.components.ContextHelper;
0042: import org.apache.cocoon.components.sax.XMLDeserializer;
0043: import org.apache.cocoon.components.source.SourceUtil;
0044: import org.apache.cocoon.environment.CocoonRunnable;
0045: import org.apache.cocoon.environment.Redirector;
0046: import org.apache.cocoon.environment.Request;
0047: import org.apache.cocoon.environment.Response;
0048: import org.apache.cocoon.environment.Session;
0049: import org.apache.cocoon.webapps.authentication.AuthenticationManager;
0050: import org.apache.cocoon.webapps.authentication.user.RequestState;
0051: import org.apache.cocoon.webapps.portal.PortalConstants;
0052: import org.apache.cocoon.webapps.session.ContextManager;
0053: import org.apache.cocoon.webapps.session.MediaManager;
0054: import org.apache.cocoon.webapps.session.SessionManager;
0055: import org.apache.cocoon.webapps.session.TransactionManager;
0056: import org.apache.cocoon.webapps.session.context.SessionContext;
0057: import org.apache.cocoon.webapps.session.xml.XMLUtil;
0058: import org.apache.cocoon.xml.IncludeXMLConsumer;
0059: import org.apache.cocoon.xml.XMLConsumer;
0060: import org.apache.cocoon.xml.XMLUtils;
0061: import org.apache.cocoon.xml.dom.DOMUtil;
0062: import org.apache.excalibur.source.Source;
0063: import org.apache.excalibur.source.SourceException;
0064: import org.apache.excalibur.source.SourceParameters;
0065: import org.apache.excalibur.source.SourceResolver;
0066: import org.apache.excalibur.store.Store;
0067: import org.apache.excalibur.xml.xpath.XPathProcessor;
0068: import org.w3c.dom.Document;
0069: import org.w3c.dom.DocumentFragment;
0070: import org.w3c.dom.Element;
0071: import org.w3c.dom.NamedNodeMap;
0072: import org.w3c.dom.Node;
0073: import org.w3c.dom.NodeList;
0074: import org.w3c.dom.Text;
0075: import org.xml.sax.Attributes;
0076: import org.xml.sax.SAXException;
0077: import org.xml.sax.helpers.AttributesImpl;
0078:
0079: /**
0080: * This is the basis portal component
0081: *
0082: * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
0083: * @version CVS $Id: PortalManagerImpl.java 433543 2006-08-22 06:22:54Z crossley $
0084: */
0085: public final class PortalManagerImpl extends AbstractLogEnabled
0086: implements Disposable, Composable, Recomposable, Recyclable,
0087: Contextualizable, Component, PortalManager {
0088:
0089: /** The cache (store) for the profiles */
0090: private Store profileStore;
0091:
0092: /** The authenticationManager */
0093: private AuthenticationManager authenticationManager;
0094:
0095: /** The media manager */
0096: private MediaManager mediaManager;
0097:
0098: /** The XPath Processor */
0099: private XPathProcessor xpathProcessor;
0100:
0101: /** The session manager */
0102: private SessionManager sessionManager;
0103:
0104: /** The Context manager */
0105: private ContextManager contextManager;
0106:
0107: /** The transaction manager */
0108: private TransactionManager transactionManager;
0109:
0110: /** The component manager */
0111: protected ComponentManager manager;
0112:
0113: /** The current source resolver */
0114: protected SourceResolver resolver;
0115:
0116: /** The context */
0117: protected Context componentContext;
0118:
0119: /** Are we already setup for this request? */
0120: protected boolean initialized = false;
0121:
0122: /* (non-Javadoc)
0123: * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
0124: */
0125: public void recycle() {
0126: if (this .manager != null) {
0127: this .manager.release(this .profileStore);
0128: this .manager
0129: .release((Component) this .authenticationManager);
0130: this .manager.release((Component) this .mediaManager);
0131: this .manager.release((Component) this .sessionManager);
0132: this .manager.release((Component) this .contextManager);
0133: this .manager.release((Component) this .transactionManager);
0134: this .profileStore = null;
0135: this .authenticationManager = null;
0136: this .mediaManager = null;
0137: this .transactionManager = null;
0138: this .sessionManager = null;
0139: this .contextManager = null;
0140: }
0141: this .initialized = false;
0142: }
0143:
0144: /**
0145: * Get the current authentication state
0146: */
0147: protected RequestState getRequestState() {
0148: AuthenticationManager authManager = null;
0149: try {
0150: authManager = (AuthenticationManager) this .manager
0151: .lookup(AuthenticationManager.ROLE);
0152: return authManager.getState();
0153: } catch (ComponentException ce) {
0154: // ignore this here
0155: return null;
0156: } finally {
0157: this .manager.release((Component) authManager);
0158: }
0159: }
0160:
0161: /* (non-Javadoc)
0162: * @see org.apache.avalon.framework.component.Composable#compose(org.apache.avalon.framework.component.ComponentManager)
0163: */
0164: public void compose(ComponentManager manager)
0165: throws ComponentException {
0166: this .manager = manager;
0167: this .resolver = (SourceResolver) manager
0168: .lookup(SourceResolver.ROLE);
0169: this .xpathProcessor = (XPathProcessor) this .manager
0170: .lookup(XPathProcessor.ROLE);
0171: }
0172:
0173: /* (non-Javadoc)
0174: * @see org.apache.avalon.framework.component.Recomposable#recompose(org.apache.avalon.framework.component.ComponentManager)
0175: */
0176: public void recompose(ComponentManager manager)
0177: throws ComponentException {
0178: this .manager = manager;
0179: }
0180:
0181: /* (non-Javadoc)
0182: * @see org.apache.avalon.framework.activity.Disposable#dispose()
0183: */
0184: public void dispose() {
0185: if (this .manager != null) {
0186: this .manager.release((Component) this .xpathProcessor);
0187: this .xpathProcessor = null;
0188: this .manager.release(this .resolver);
0189: this .resolver = null;
0190: }
0191: }
0192:
0193: /* (non-Javadoc)
0194: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
0195: */
0196: public void contextualize(Context context) throws ContextException {
0197: this .componentContext = context;
0198: }
0199:
0200: /**
0201: * Get the profile store
0202: */
0203: protected Store getProfileStore() throws ProcessingException {
0204: if (this .profileStore == null) {
0205: try {
0206: this .profileStore = (Store) this .manager
0207: .lookup(Store.ROLE);
0208: } catch (ComponentException ce) {
0209: throw new ProcessingException(
0210: "Error during lookup of store component.", ce);
0211: }
0212: }
0213: return this .profileStore;
0214: }
0215:
0216: /**
0217: * Get the authentication manager
0218: */
0219: protected AuthenticationManager getAuthenticationManager()
0220: throws ProcessingException {
0221: if (this .authenticationManager == null) {
0222: try {
0223: this .authenticationManager = (AuthenticationManager) this .manager
0224: .lookup(AuthenticationManager.ROLE);
0225: } catch (ComponentException ce) {
0226: throw new ProcessingException(
0227: "Error during lookup of AuthenticationManager.",
0228: ce);
0229: }
0230: }
0231: return this .authenticationManager;
0232: }
0233:
0234: /**
0235: * Get the media manager
0236: */
0237: protected MediaManager getMediaManager() throws ProcessingException {
0238: if (this .mediaManager == null) {
0239: try {
0240: this .mediaManager = (MediaManager) this .manager
0241: .lookup(MediaManager.ROLE);
0242: } catch (ComponentException ce) {
0243: throw new ProcessingException(
0244: "Error during lookup of MediaManager.", ce);
0245: }
0246: }
0247: return this .mediaManager;
0248: }
0249:
0250: /**
0251: * Setup this component
0252: */
0253: protected void setup() throws ProcessingException {
0254: if (!this .initialized) {
0255:
0256: final Request request = ContextHelper
0257: .getRequest(this .componentContext);
0258:
0259: if (request.getAttribute(PortalManager.ROLE) == null) {
0260:
0261: request.setAttribute(PortalManager.ROLE, Boolean.TRUE);
0262:
0263: // Get and ignore the configuration
0264: this .getConfiguration();
0265:
0266: try {
0267: this .changeProfile();
0268: } catch (SAXException se) {
0269: throw new ProcessingException(se);
0270: } catch (IOException ioe) {
0271: throw new ProcessingException(ioe);
0272: }
0273: }
0274:
0275: this .initialized = true;
0276: }
0277: }
0278:
0279: /* (non-Javadoc)
0280: * @see org.apache.cocoon.webapps.portal.components.PortalManager#configurationTest()
0281: */
0282: public void configurationTest() throws ProcessingException,
0283: IOException, SAXException {
0284: // no sync required
0285: if (this .getLogger().isDebugEnabled()) {
0286: this .getLogger().debug("BEGIN configurationTest");
0287: }
0288:
0289: this .setup();
0290:
0291: // Ignore result
0292: this .getConfiguration();
0293:
0294: if (this .getLogger().isDebugEnabled()) {
0295: this .getLogger().debug("END configurationTest");
0296: }
0297: }
0298:
0299: /* (non-Javadoc)
0300: * @see org.apache.cocoon.webapps.portal.components.PortalManager#getContext(boolean)
0301: */
0302: public SessionContext getContext(boolean create)
0303: throws ProcessingException, IOException, SAXException {
0304: // synchronized
0305: if (this .getLogger().isDebugEnabled()) {
0306: this .getLogger().debug("BEGIN getContext create=" + create);
0307: }
0308: this .setup();
0309: SessionContext context = null;
0310:
0311: final Session session = this .getSessionManager().getSession(
0312: false);
0313: if (session != null) {
0314: synchronized (session) {
0315: String appName = this .getRequestState()
0316: .getApplicationName();
0317: String attrName = PortalConstants.PRIVATE_SESSION_CONTEXT_NAME;
0318: if (appName != null) {
0319: attrName = attrName + ':' + appName;
0320: }
0321: context = this .getContextManager().getContext(attrName);
0322: if (context == null && create) {
0323:
0324: // create new context
0325:
0326: context = this .getAuthenticationManager()
0327: .createApplicationContext(attrName, null,
0328: null);
0329:
0330: }
0331: } // end synchronized
0332: }
0333:
0334: if (this .getLogger().isDebugEnabled()) {
0335: this .getLogger().debug("END getContext context=" + context);
0336: }
0337: return context;
0338: }
0339:
0340: /* (non-Javadoc)
0341: * @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)
0342: */
0343: public void streamConfiguration(XMLConsumer consumer,
0344: String requestURI, String profileID, String media,
0345: String contextID) throws IOException, SAXException,
0346: ProcessingException {
0347: // synchronized not req.
0348: this .setup();
0349: Response response = ContextHelper
0350: .getResponse(this .componentContext);
0351:
0352: XMLUtils.startElement(consumer,
0353: PortalConstants.ELEMENT_CONFIGURATION);
0354:
0355: // set the portal-page uri:
0356: StringBuffer buffer = new StringBuffer(requestURI);
0357: buffer.append((requestURI.indexOf('?') == -1 ? '?' : '&'))
0358: .append(PortalManagerImpl.REQ_PARAMETER_PROFILE)
0359: .append('=').append(profileID);
0360: String uri = response.encodeURL(buffer.toString());
0361: XMLUtils.startElement(consumer, "uri");
0362: XMLUtils.data(consumer, uri);
0363: XMLUtils.endElement(consumer, "uri");
0364:
0365: Map config = this .getConfiguration();
0366: String portalURI = response.encodeURL((String) config
0367: .get(PortalConstants.CONF_PORTAL_URI));
0368:
0369: XMLUtils.startElement(consumer, "portal");
0370: XMLUtils.data(consumer, portalURI);
0371: XMLUtils.endElement(consumer, "portal");
0372:
0373: XMLUtils
0374: .startElement(consumer, PortalConstants.ELEMENT_PROFILE);
0375: XMLUtils.data(consumer, profileID);
0376: XMLUtils.endElement(consumer, PortalConstants.ELEMENT_PROFILE);
0377:
0378: if (media != null) {
0379: XMLUtils.startElement(consumer, "media");
0380: XMLUtils.data(consumer, media);
0381: XMLUtils.endElement(consumer, "media");
0382: }
0383:
0384: if (contextID != null) {
0385: XMLUtils.startElement(consumer, "context");
0386: XMLUtils.data(consumer, contextID);
0387: XMLUtils.endElement(consumer, "context");
0388: }
0389:
0390: XMLUtils.endElement(consumer,
0391: PortalConstants.ELEMENT_CONFIGURATION);
0392: }
0393:
0394: /* (non-Javadoc)
0395: * @see org.apache.cocoon.webapps.portal.components.PortalManager#showAdminConf(org.apache.cocoon.xml.XMLConsumer)
0396: */
0397: public void showAdminConf(XMLConsumer consumer)
0398: throws SAXException, ProcessingException, IOException {
0399: // synchronized
0400: if (this .getLogger().isDebugEnabled()) {
0401: this .getLogger().debug(
0402: "BEGIN showAdminConf consumer=" + consumer);
0403: }
0404: this .setup();
0405: Request request = ContextHelper
0406: .getRequest(this .componentContext);
0407: try {
0408: String profileID = "global";
0409: String copletID = request
0410: .getParameter(PortalManagerImpl.REQ_PARAMETER_COPLET);
0411:
0412: SessionContext context = this .getContext(true);
0413:
0414: Map configuration = this .getConfiguration();
0415:
0416: DocumentFragment copletsFragment = (DocumentFragment) context
0417: .getAttribute(ATTRIBUTE_ADMIN_COPLETS);
0418: String command = request
0419: .getParameter(PortalManagerImpl.REQ_PARAMETER_ADMIN_COPLETS);
0420: if (command != null && copletsFragment != null) {
0421: try {
0422: this .getTransactionManager()
0423: .startWritingTransaction(context);
0424: // save : save coplets base
0425: // new : new coplet
0426: // delete : use id to delete coplet
0427: // change : change the coplet
0428: // cache : cleans the cache
0429: if (command.equals("delete") && copletID != null) {
0430: Node coplet = DOMUtil.getSingleNode(
0431: copletsFragment,
0432: "coplets-profile/coplets/coplet[@id='"
0433: + copletID + "']",
0434: this .xpathProcessor);
0435: if (coplet != null) {
0436: coplet.getParentNode().removeChild(coplet);
0437: }
0438: } else if (command.equals("change")
0439: && copletID != null) {
0440: Node coplet = DOMUtil.getSingleNode(
0441: copletsFragment,
0442: "coplets-profile/coplets/coplet[@id='"
0443: + copletID + "']",
0444: this .xpathProcessor);
0445: if (coplet != null) {
0446: // now get the information
0447: String value;
0448:
0449: value = request
0450: .getParameter("portaladmin_title");
0451: if (value != null)
0452: DOMUtil.setValueOfNode(DOMUtil
0453: .getSingleNode(coplet, "title",
0454: this .xpathProcessor),
0455: value);
0456:
0457: value = request
0458: .getParameter("portaladmin_mand");
0459: if (value != null)
0460: DOMUtil
0461: .setValueOfNode(
0462: DOMUtil
0463: .getSingleNode(
0464: coplet,
0465: "configuration/mandatory",
0466: this .xpathProcessor),
0467: value);
0468:
0469: value = request
0470: .getParameter("portaladmin_sizable");
0471: if (value != null)
0472: DOMUtil
0473: .setValueOfNode(
0474: DOMUtil
0475: .getSingleNode(
0476: coplet,
0477: "configuration/sizable",
0478: this .xpathProcessor),
0479: value);
0480:
0481: value = request
0482: .getParameter("portaladmin_active");
0483: if (value != null)
0484: DOMUtil.setValueOfNode(DOMUtil
0485: .getSingleNode(coplet,
0486: "configuration/active",
0487: this .xpathProcessor),
0488: value);
0489:
0490: value = request
0491: .getParameter("portaladmin_handsize");
0492: if (value != null)
0493: DOMUtil
0494: .setValueOfNode(
0495: DOMUtil
0496: .selectSingleNode(
0497: coplet,
0498: "configuration/handlesSizable",
0499: this .xpathProcessor),
0500: value);
0501:
0502: value = request
0503: .getParameter("portaladmin_handpar");
0504: if (value != null)
0505: DOMUtil
0506: .setValueOfNode(
0507: DOMUtil
0508: .selectSingleNode(
0509: coplet,
0510: "configuration/handlesParameters",
0511: this .xpathProcessor),
0512: value);
0513:
0514: value = request
0515: .getParameter("portaladmin_timeout");
0516: if (value != null)
0517: DOMUtil
0518: .setValueOfNode(
0519: DOMUtil
0520: .selectSingleNode(
0521: coplet,
0522: "configuration/timeout",
0523: this .xpathProcessor),
0524: value);
0525:
0526: value = request
0527: .getParameter("portaladmin_customizable");
0528: if (value != null)
0529: DOMUtil
0530: .setValueOfNode(
0531: DOMUtil
0532: .selectSingleNode(
0533: coplet,
0534: "configuration/customizable",
0535: this .xpathProcessor),
0536: value);
0537:
0538: value = request
0539: .getParameter("portaladmin_persistent");
0540: if (value != null)
0541: DOMUtil
0542: .setValueOfNode(
0543: DOMUtil
0544: .selectSingleNode(
0545: coplet,
0546: "configuration/persistent",
0547: this .xpathProcessor),
0548: value);
0549:
0550: String resource = request
0551: .getParameter("portaladmin_resource");
0552: if (resource != null) {
0553: Element resourceNode = (Element) DOMUtil
0554: .getSingleNode(coplet,
0555: "resource",
0556: this .xpathProcessor);
0557: resourceNode.getParentNode()
0558: .removeChild(resourceNode);
0559: resourceNode = coplet
0560: .getOwnerDocument()
0561: .createElementNS(null,
0562: "resource");
0563: resourceNode.setAttributeNS(null,
0564: "uri", resource);
0565: coplet.appendChild(resourceNode);
0566: }
0567: resource = request
0568: .getParameter("portaladmin_cust");
0569: boolean isCustom = DOMUtil
0570: .getValueAsBooleanOf(
0571: coplet,
0572: "configuration/customizable",
0573: false, this .xpathProcessor);
0574: if (resource != null && isCustom) {
0575: Element resourceNode = (Element) DOMUtil
0576: .getSingleNode(coplet,
0577: "customization",
0578: this .xpathProcessor);
0579: if (resourceNode != null)
0580: resourceNode.getParentNode()
0581: .removeChild(resourceNode);
0582: resourceNode = coplet
0583: .getOwnerDocument()
0584: .createElementNS(null,
0585: "customization");
0586: resourceNode.setAttributeNS(null,
0587: "uri", resource);
0588: coplet.appendChild(resourceNode);
0589: }
0590: if (!isCustom) {
0591: Element resourceNode = (Element) DOMUtil
0592: .getSingleNode(coplet,
0593: "customization",
0594: this .xpathProcessor);
0595: if (resourceNode != null)
0596: resourceNode.getParentNode()
0597: .removeChild(resourceNode);
0598: }
0599:
0600: // transformations
0601: value = request
0602: .getParameter("portaladmin_newxsl");
0603: if (value != null) {
0604: Element tNode = (Element) DOMUtil
0605: .selectSingleNode(coplet,
0606: "transformation",
0607: this .xpathProcessor);
0608: Element sNode = tNode
0609: .getOwnerDocument()
0610: .createElementNS(null,
0611: "stylesheet");
0612: tNode.appendChild(sNode);
0613: sNode.appendChild(sNode
0614: .getOwnerDocument()
0615: .createTextNode(value));
0616: }
0617:
0618: // now get all transformation stylesheets, mark
0619: // all stylesheets which should be deleted with
0620: // an attribute delete
0621: Enumeration keys = request
0622: .getParameterNames();
0623: Element sNode;
0624: String key;
0625: while (keys.hasMoreElements()) {
0626: key = (String) keys.nextElement();
0627: if (key.startsWith("portaladmin_xsl_")) {
0628: value = key.substring(key
0629: .lastIndexOf('_') + 1);
0630: sNode = (Element) DOMUtil
0631: .getSingleNode(coplet,
0632: "transformation/stylesheet[position()="
0633: + value
0634: + "]",
0635: this .xpathProcessor);
0636: if (sNode != null) {
0637: String xslName = request
0638: .getParameter(key);
0639: if (xslName.equals("true"))
0640: xslName = "**STYLESHEET**";
0641: DOMUtil.setValueOfNode(sNode,
0642: xslName);
0643: }
0644: } else if (key
0645: .startsWith("portaladmin_delxsl_")) {
0646: value = key.substring(key
0647: .lastIndexOf('_') + 1);
0648: sNode = (Element) DOMUtil
0649: .getSingleNode(coplet,
0650: "transformation/stylesheet[position()="
0651: + value
0652: + "]",
0653: this .xpathProcessor);
0654: if (sNode != null) {
0655: sNode.setAttributeNS(null,
0656: "delete", "true");
0657: }
0658: }
0659: }
0660: NodeList delete = DOMUtil
0661: .selectNodeList(
0662: coplet,
0663: "transformation/stylesheet[@delete]",
0664: this .xpathProcessor);
0665: if (delete != null) {
0666: for (int i = 0; i < delete.getLength(); i++) {
0667: delete
0668: .item(i)
0669: .getParentNode()
0670: .removeChild(delete.item(i));
0671: }
0672: }
0673: }
0674: } else if (command.equals("new")) {
0675: // first we have to invent a new coplet id!
0676: int index = 0;
0677: boolean found = false;
0678: Element coplet;
0679: Element subNode;
0680:
0681: while (!found) {
0682: copletID = "S" + index;
0683: coplet = (Element) DOMUtil.getSingleNode(
0684: copletsFragment,
0685: "coplets-profile/coplets/coplet[@id='"
0686: + copletID + "']",
0687: this .xpathProcessor);
0688: if (coplet == null) {
0689: found = true;
0690: } else {
0691: index++;
0692: }
0693: }
0694: coplet = copletsFragment.getOwnerDocument()
0695: .createElementNS(null, "coplet");
0696: coplet.setAttributeNS(null, "id", copletID);
0697: subNode = coplet.getOwnerDocument()
0698: .createElementNS(null, "resource");
0699: coplet.appendChild(subNode);
0700: subNode.setAttributeNS(null, "uri",
0701: "uri_in_sitemap");
0702:
0703: String title = request
0704: .getParameter("portaladmin_title");
0705: if (title == null || title.trim().length() == 0)
0706: title = "**NEW COPLET**";
0707: DOMUtil.setValueOfNode(DOMUtil
0708: .selectSingleNode(coplet,
0709: "configuration/mandatory",
0710: this .xpathProcessor), "false");
0711: DOMUtil.setValueOfNode(DOMUtil
0712: .selectSingleNode(coplet,
0713: "configuration/sizable",
0714: this .xpathProcessor), "true");
0715: DOMUtil.setValueOfNode(DOMUtil
0716: .selectSingleNode(coplet,
0717: "configuration/active",
0718: this .xpathProcessor), "false");
0719: DOMUtil
0720: .setValueOfNode(
0721: DOMUtil
0722: .selectSingleNode(
0723: coplet,
0724: "configuration/handlesParameters",
0725: this .xpathProcessor),
0726: "true");
0727: DOMUtil.setValueOfNode(DOMUtil
0728: .selectSingleNode(coplet,
0729: "configuration/handlesSizable",
0730: this .xpathProcessor), "false");
0731: DOMUtil.setValueOfNode(DOMUtil
0732: .selectSingleNode(coplet, "title",
0733: this .xpathProcessor), title);
0734: DOMUtil.setValueOfNode(DOMUtil
0735: .selectSingleNode(coplet,
0736: "status/visible",
0737: this .xpathProcessor), "true");
0738: DOMUtil.setValueOfNode(DOMUtil
0739: .selectSingleNode(coplet,
0740: "status/size",
0741: this .xpathProcessor), "max");
0742: DOMUtil.getSingleNode(copletsFragment,
0743: "coplets-profile/coplets",
0744: this .xpathProcessor)
0745: .appendChild(coplet);
0746: } else if (command.equals("save")) {
0747:
0748: SourceParameters pars = new SourceParameters();
0749: pars.setSingleParameterValue("profile",
0750: "coplet-base");
0751: RequestState state = this .getRequestState();
0752: pars.setSingleParameterValue("application",
0753: state.getApplicationName());
0754: pars.setSingleParameterValue("handler", state
0755: .getHandlerName());
0756:
0757: String saveResource = (String) configuration
0758: .get(PortalConstants.CONF_COPLETBASE_SAVE_RESOURCE);
0759:
0760: if (saveResource == null) {
0761: throw new ProcessingException(
0762: "portal: No save resource defined for type coplet-base.");
0763: } else {
0764:
0765: SourceUtil.writeDOM(saveResource, null,
0766: pars, copletsFragment,
0767: this .resolver, "xml");
0768:
0769: // now the hardest part, clean up the whole cache
0770: this
0771: .cleanUpCache(null, null,
0772: configuration);
0773: }
0774: }
0775: } finally {
0776: this .getTransactionManager()
0777: .stopWritingTransaction(context);
0778: }
0779: }
0780:
0781: // general commands
0782: if (command != null && command.equals("cleancache")) {
0783: this .cleanUpCache(null, null, configuration);
0784: }
0785:
0786: String state = request
0787: .getParameter(PortalManagerImpl.REQ_PARAMETER_STATE);
0788: if (state == null) {
0789: state = (String) context.getAttribute(
0790: ATTRIBUTE_ADMIN_STATE,
0791: PortalConstants.STATE_MAIN);
0792: }
0793:
0794: // now start producing xml:
0795: consumer.startElement("",
0796: PortalConstants.ELEMENT_ADMINCONF,
0797: PortalConstants.ELEMENT_ADMINCONF,
0798: XMLUtils.EMPTY_ATTRIBUTES);
0799:
0800: context.setAttribute(ATTRIBUTE_ADMIN_STATE, state);
0801: consumer.startElement("", PortalConstants.ELEMENT_STATE,
0802: PortalConstants.ELEMENT_STATE,
0803: XMLUtils.EMPTY_ATTRIBUTES);
0804: consumer.characters(state.toCharArray(), 0, state.length());
0805: consumer.endElement("", PortalConstants.ELEMENT_STATE,
0806: PortalConstants.ELEMENT_STATE);
0807:
0808: if (state.equals(PortalConstants.STATE_MAIN)) {
0809:
0810: Document rolesDF = this .getRoles();
0811: Node roles = null;
0812: if (rolesDF != null)
0813: roles = DOMUtil.getSingleNode(rolesDF, "roles",
0814: this .xpathProcessor);
0815: IncludeXMLConsumer.includeNode(roles, consumer,
0816: consumer);
0817: }
0818:
0819: if (state.equals(PortalConstants.STATE_MAIN_ROLE)) {
0820:
0821: Document rolesDF = this .getRoles();
0822: Node roles = null;
0823: if (rolesDF != null)
0824: roles = DOMUtil.getSingleNode(rolesDF, "roles",
0825: this .xpathProcessor);
0826: IncludeXMLConsumer.includeNode(roles, consumer,
0827: consumer);
0828:
0829: String role = request
0830: .getParameter(PortalManagerImpl.REQ_PARAMETER_ROLE);
0831: if (role == null) {
0832: role = (String) context
0833: .getAttribute(ATTRIBUTE_ADMIN_ROLE);
0834: }
0835: context.setAttribute(ATTRIBUTE_ADMIN_ROLE, role);
0836: if (role != null) {
0837: XMLUtils.startElement(consumer, "roleusers");
0838: XMLUtils.startElement(consumer, "name");
0839: XMLUtils.data(consumer, role);
0840: XMLUtils.endElement(consumer, "name");
0841: Document userDF = this .getUsers(role, null);
0842: Node users = null;
0843: if (userDF != null)
0844: users = DOMUtil.getSingleNode(userDF, "users",
0845: this .xpathProcessor);
0846: IncludeXMLConsumer.includeNode(users, consumer,
0847: consumer);
0848: XMLUtils.endElement(consumer, "roleusers");
0849: }
0850: }
0851:
0852: if (state.equals(PortalConstants.STATE_GLOBAL)) {
0853: profileID = this .getProfileID(
0854: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null,
0855: null, true);
0856: Map profile = this .retrieveProfile(profileID);
0857: if (profile == null) {
0858: this .createProfile(context,
0859: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
0860: null, null, true);
0861: profile = this .retrieveProfile(profileID);
0862: }
0863: this .showPortal(consumer, true, context, profile,
0864: profileID);
0865: }
0866:
0867: if (state.equals(PortalConstants.STATE_ROLE)) {
0868: String role = request
0869: .getParameter(PortalManagerImpl.REQ_PARAMETER_ROLE);
0870: if (role == null) {
0871: role = (String) context
0872: .getAttribute(ATTRIBUTE_ADMIN_ROLE);
0873: }
0874: context.setAttribute(ATTRIBUTE_ADMIN_ROLE, role);
0875: if (role != null) {
0876: consumer.startElement("",
0877: PortalConstants.ELEMENT_ROLE,
0878: PortalConstants.ELEMENT_ROLE,
0879: XMLUtils.EMPTY_ATTRIBUTES);
0880: consumer.characters(role.toCharArray(), 0, role
0881: .length());
0882: consumer.endElement("",
0883: PortalConstants.ELEMENT_ROLE,
0884: PortalConstants.ELEMENT_ROLE);
0885: profileID = this .getProfileID(
0886: PortalManagerImpl.BUILDTYPE_VALUE_ROLE,
0887: role, null, true);
0888: Map profile = this .retrieveProfile(profileID);
0889: if (profile == null) {
0890: this .createProfile(context,
0891: PortalManagerImpl.BUILDTYPE_VALUE_ROLE,
0892: role, null, true);
0893: profile = this .retrieveProfile(profileID);
0894: }
0895: this .showPortal(consumer, true, context, profile,
0896: profileID);
0897: }
0898: }
0899: if (state.equals(PortalConstants.STATE_USER)) {
0900: String role = request
0901: .getParameter(PortalManagerImpl.REQ_PARAMETER_ROLE);
0902: String id = request
0903: .getParameter(PortalManagerImpl.REQ_PARAMETER_ID);
0904: if (role == null) {
0905: role = (String) context
0906: .getAttribute(ATTRIBUTE_ADMIN_ROLE);
0907: }
0908: if (id == null) {
0909: id = (String) context
0910: .getAttribute(ATTRIBUTE_ADMIN_ID);
0911: }
0912: context.setAttribute(ATTRIBUTE_ADMIN_ID, id);
0913: context.setAttribute(ATTRIBUTE_ADMIN_ROLE, role);
0914: if (role != null && id != null) {
0915: consumer.startElement("",
0916: PortalConstants.ELEMENT_ROLE,
0917: PortalConstants.ELEMENT_ROLE,
0918: XMLUtils.EMPTY_ATTRIBUTES);
0919: consumer.characters(role.toCharArray(), 0, role
0920: .length());
0921: consumer.endElement("",
0922: PortalConstants.ELEMENT_ROLE,
0923: PortalConstants.ELEMENT_ROLE);
0924: consumer.startElement("",
0925: PortalConstants.ELEMENT_ID,
0926: PortalConstants.ELEMENT_ID,
0927: XMLUtils.EMPTY_ATTRIBUTES);
0928: consumer.characters(id.toCharArray(), 0, id
0929: .length());
0930: consumer.endElement("", PortalConstants.ELEMENT_ID,
0931: PortalConstants.ELEMENT_ID);
0932:
0933: profileID = this .getProfileID(
0934: PortalManagerImpl.BUILDTYPE_VALUE_ID, role,
0935: id, true);
0936: Map profile = this .retrieveProfile(profileID);
0937: if (profile == null) {
0938: this .createProfile(context,
0939: PortalManagerImpl.BUILDTYPE_VALUE_ID,
0940: role, id, true);
0941: profile = this .retrieveProfile(profileID);
0942: }
0943: this .showPortal(consumer, true, context, profile,
0944: profileID);
0945: }
0946: }
0947: // one coplet
0948: if (state.equals(PortalConstants.STATE_COPLET)) {
0949: if (copletsFragment != null && copletID != null) {
0950: Node coplet = DOMUtil.getSingleNode(
0951: copletsFragment,
0952: "coplets-profile/coplets/coplet[@id='"
0953: + copletID + "']",
0954: this .xpathProcessor);
0955: if (coplet != null) {
0956: IncludeXMLConsumer.includeNode(coplet,
0957: consumer, consumer);
0958: }
0959: } else {
0960: state = PortalConstants.STATE_COPLETS;
0961: }
0962: }
0963: if (state.equals(PortalConstants.STATE_COPLETS)) {
0964: consumer.startElement("",
0965: PortalConstants.ELEMENT_COPLETS,
0966: PortalConstants.ELEMENT_COPLETS,
0967: XMLUtils.EMPTY_ATTRIBUTES);
0968:
0969: // load the base coplets profile
0970: if (copletsFragment == null) {
0971: SourceParameters pars = new SourceParameters();
0972: RequestState reqstate = this .getRequestState();
0973: pars.setSingleParameterValue("application",
0974: reqstate.getApplicationName());
0975: String res = (String) configuration
0976: .get(PortalConstants.CONF_COPLETBASE_RESOURCE);
0977: if (res == null) {
0978: throw new ProcessingException(
0979: "No configuration for portal-coplet base profile found.");
0980: }
0981: copletsFragment = SourceUtil.readDOM(res, null,
0982: pars, this .resolver);
0983: context.setAttribute(ATTRIBUTE_ADMIN_COPLETS,
0984: copletsFragment);
0985: }
0986: IncludeXMLConsumer
0987: .includeNode(DOMUtil.selectSingleNode(
0988: copletsFragment, "coplets-profile",
0989: this .xpathProcessor), consumer,
0990: consumer);
0991: consumer.endElement("",
0992: PortalConstants.ELEMENT_COPLETS,
0993: PortalConstants.ELEMENT_COPLETS);
0994: }
0995:
0996: // configuration
0997: this .streamConfiguration(consumer, request.getRequestURI(),
0998: profileID, null, null);
0999:
1000: consumer.endElement("", PortalConstants.ELEMENT_ADMINCONF,
1001: PortalConstants.ELEMENT_ADMINCONF);
1002: } catch (javax.xml.transform.TransformerException local) {
1003: throw new ProcessingException("TransformerException: "
1004: + local, local);
1005: }
1006:
1007: if (this .getLogger().isDebugEnabled()) {
1008: this .getLogger().debug("END showAdminConf");
1009: }
1010: }
1011:
1012: /* (non-Javadoc)
1013: * @see org.apache.cocoon.webapps.portal.components.PortalManager#getStatusProfile()
1014: */
1015: public Element getStatusProfile() throws SAXException, IOException,
1016: ProcessingException {
1017: // synchronized
1018: if (this .getLogger().isDebugEnabled()) {
1019: this .getLogger().debug("BEGIN getStatusProfile");
1020: }
1021: this .setup();
1022: SessionContext context = this .getContext(true);
1023: String profileID = null;
1024: Map storedProfile = null;
1025: Element statusProfile = null;
1026:
1027: if (context
1028: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE) != null) {
1029: profileID = this
1030: .getProfileID(
1031: PortalManagerImpl.BUILDTYPE_VALUE_ID,
1032: (String) context
1033: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE),
1034: (String) context
1035: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID),
1036: false);
1037: storedProfile = this .retrieveProfile(profileID);
1038: }
1039:
1040: if (storedProfile != null) {
1041: DocumentFragment profile = (DocumentFragment) storedProfile
1042: .get(PortalConstants.PROFILE_PROFILE);
1043: try {
1044: statusProfile = (Element) DOMUtil.getSingleNode(
1045: profile, "profile/status-profile",
1046: this .xpathProcessor);
1047: } catch (javax.xml.transform.TransformerException ignore) {
1048: }
1049: }
1050:
1051: if (this .getLogger().isDebugEnabled()) {
1052: this
1053: .getLogger()
1054: .debug(
1055: "END getStatusProfile statusProfile="
1056: + (statusProfile == null ? "null"
1057: : XMLUtils
1058: .serializeNode(
1059: statusProfile,
1060: XMLUtils
1061: .createPropertiesForXML(false))));
1062: }
1063: return statusProfile;
1064: }
1065:
1066: /* (non-Javadoc)
1067: * @see org.apache.cocoon.webapps.portal.components.PortalManager#showPortal(org.apache.cocoon.xml.XMLConsumer, boolean, boolean)
1068: */
1069: public void showPortal(XMLConsumer consumer, boolean configMode,
1070: boolean adminProfile) throws SAXException,
1071: ProcessingException, IOException {
1072: // synchronized
1073: if (this .getLogger().isDebugEnabled()) {
1074: this .getLogger().debug(
1075: "BEGIN showPortal consumer=" + consumer
1076: + ", configMode=" + configMode
1077: + ", adminProfile=" + adminProfile);
1078: }
1079: this .setup();
1080:
1081: SessionContext context = this .getContext(true);
1082: String profileID = null;
1083: Map storedProfile = null;
1084:
1085: if (this .getLogger().isDebugEnabled()) {
1086: this .getLogger().debug("start portal generation");
1087: }
1088: if (context
1089: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE) != null) {
1090: profileID = this
1091: .getProfileID(
1092: PortalManagerImpl.BUILDTYPE_VALUE_ID,
1093: (String) context
1094: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE),
1095: (String) context
1096: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID),
1097: adminProfile);
1098: storedProfile = this .retrieveProfile(profileID);
1099: }
1100: if (storedProfile == null) {
1101:
1102: if (this .getLogger().isDebugEnabled()) {
1103: this .getLogger().debug("start building profile");
1104: }
1105: this .createProfile(context,
1106: PortalManagerImpl.BUILDTYPE_VALUE_ID, null, null,
1107: adminProfile);
1108: // get the profileID
1109: profileID = this
1110: .getProfileID(
1111: PortalManagerImpl.BUILDTYPE_VALUE_ID,
1112: (String) context
1113: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE),
1114: (String) context
1115: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID),
1116: adminProfile);
1117: storedProfile = this .retrieveProfile(profileID);
1118: if (storedProfile == null) {
1119: throw new ProcessingException(
1120: "portal: No portal profile found.");
1121: }
1122: if (this .getLogger().isDebugEnabled()) {
1123: this .getLogger().debug("end building profile");
1124: }
1125: }
1126:
1127: if (this .getLogger().isDebugEnabled()) {
1128: this .getLogger().debug("start showing profile");
1129: }
1130: this .showPortal(consumer, configMode, context, storedProfile,
1131: profileID);
1132: if (this .getLogger().isDebugEnabled()) {
1133: this .getLogger().debug("end showing profile");
1134: this .getLogger().debug("end portal generation");
1135: }
1136: if (this .getLogger().isDebugEnabled()) {
1137: this .getLogger().debug("END showPortal");
1138: }
1139: }
1140:
1141: /**
1142: * Stream all layout information for the current portal
1143: * to the consumer.
1144: * The resulting XML:
1145: * <layout>
1146: * <portal>
1147: * ...
1148: * </portal>
1149: * <coplets>
1150: * ...
1151: * </coplets>
1152: * </layout>
1153: */
1154: public static void streamLayoutProfile(XMLConsumer consumer,
1155: Map portalLayouts, Map copletLayouts, String mediaType)
1156: throws SAXException {
1157: Element element;
1158: NodeList childs;
1159: Attributes attr = new AttributesImpl();
1160:
1161: consumer.startElement("", PortalConstants.ELEMENT_LAYOUT,
1162: PortalConstants.ELEMENT_LAYOUT, attr);
1163:
1164: // first: layout of portal
1165: consumer.startElement("", PortalConstants.ELEMENT_PORTAL,
1166: PortalConstants.ELEMENT_PORTAL, attr);
1167:
1168: element = (Element) portalLayouts.get(mediaType);
1169: childs = element.getChildNodes();
1170: for (int ci = 0; ci < childs.getLength(); ci++) {
1171: IncludeXMLConsumer.includeNode(childs.item(ci), consumer,
1172: consumer);
1173: }
1174: consumer.endElement("", PortalConstants.ELEMENT_PORTAL,
1175: PortalConstants.ELEMENT_PORTAL);
1176:
1177: // second: layout of coplets
1178: consumer.startElement("", PortalConstants.ELEMENT_COPLETS,
1179: PortalConstants.ELEMENT_COPLETS, attr);
1180: element = (Element) copletLayouts.get(mediaType);
1181: childs = element.getChildNodes();
1182: for (int ci = 0; ci < childs.getLength(); ci++) {
1183: IncludeXMLConsumer.includeNode(childs.item(ci), consumer,
1184: consumer);
1185: }
1186: consumer.endElement("", PortalConstants.ELEMENT_COPLETS,
1187: PortalConstants.ELEMENT_COPLETS);
1188:
1189: consumer.endElement("", PortalConstants.ELEMENT_LAYOUT,
1190: PortalConstants.ELEMENT_LAYOUT);
1191: }
1192:
1193: /**
1194: * Show the portal.
1195: * The portal is included in the current stream.
1196: */
1197: private void showPortal(XMLConsumer consumer, boolean configMode,
1198: SessionContext context, Map storedProfile, String profileID)
1199: throws SAXException, ProcessingException, IOException {
1200: // synchronized
1201: if (this .getLogger().isDebugEnabled()) {
1202: this .getLogger().debug(
1203: "BEGIN showPortal consumer=" + consumer
1204: + ", configMode=" + configMode
1205: + ", context=" + context + ", profile="
1206: + storedProfile);
1207: }
1208: Request request = ContextHelper
1209: .getRequest(this .componentContext);
1210: try {
1211: this .getTransactionManager().startReadingTransaction(
1212: context);
1213:
1214: DocumentFragment profile;
1215: Map defaultCoplets;
1216: Map mediaCoplets;
1217: Map portalLayouts;
1218: Map copleyLayouts;
1219: Node[] miscNodes;
1220: String mediaType = this .getMediaManager().getMediaType();
1221:
1222: profile = (DocumentFragment) storedProfile
1223: .get(PortalConstants.PROFILE_PROFILE);
1224: portalLayouts = (Map) storedProfile
1225: .get(PortalConstants.PROFILE_PORTAL_LAYOUTS);
1226: copleyLayouts = (Map) storedProfile
1227: .get(PortalConstants.PROFILE_COPLET_LAYOUTS);
1228: miscNodes = (Node[]) storedProfile
1229: .get(PortalConstants.PROFILE_MISC_POINTER);
1230: defaultCoplets = (Map) storedProfile
1231: .get(PortalConstants.PROFILE_DEFAULT_COPLETS);
1232: mediaCoplets = (Map) storedProfile
1233: .get(PortalConstants.PROFILE_MEDIA_COPLETS);
1234: if (profile == null || defaultCoplets == null
1235: || mediaCoplets == null || portalLayouts == null
1236: || copleyLayouts == null || miscNodes == null) {
1237: throw new ProcessingException(
1238: "portal: No portal profile found.");
1239: }
1240:
1241: // get the configuration
1242: Map config = this .getConfiguration();
1243: if (config == null) {
1244: throw new ProcessingException(
1245: "No configuration for portal found.");
1246: }
1247: boolean processCopletsParallel = false;
1248: long defaultCopletTimeout = 600000;
1249:
1250: Boolean boolValue = (Boolean) config
1251: .get(PortalConstants.CONF_PARALLEL_COPLETS);
1252: if (boolValue != null)
1253: processCopletsParallel = boolValue.booleanValue();
1254: Long longValue = (Long) config
1255: .get(PortalConstants.CONF_COPLET_TIMEOUT);
1256: if (longValue != null)
1257: defaultCopletTimeout = longValue.longValue();
1258:
1259: Element element;
1260:
1261: // now start producing xml:
1262: AttributesImpl attr = new AttributesImpl();
1263: if (configMode) {
1264: XMLUtils.startElement(consumer,
1265: PortalConstants.ELEMENT_PORTALCONF);
1266: } else {
1267: XMLUtils.startElement(consumer,
1268: PortalConstants.ELEMENT_PORTAL);
1269: }
1270:
1271: // configuration
1272: this .streamConfiguration(consumer, request.getRequestURI(),
1273: profileID, mediaType, null);
1274:
1275: // LAYOUT:
1276: if (configMode) {
1277: IncludeXMLConsumer.includeNode(DOMUtil
1278: .getFirstNodeFromPath(profile, new String[] {
1279: "profile", "layout-profile" }, false),
1280: consumer, consumer);
1281: // copletsConfiguration (only for configMode)
1282: IncludeXMLConsumer.includeNode(DOMUtil
1283: .getFirstNodeFromPath(profile, new String[] {
1284: "profile", "coplets-profile" }, false),
1285: consumer, consumer);
1286: IncludeXMLConsumer.includeNode(DOMUtil
1287: .getFirstNodeFromPath(profile,
1288: new String[] { "profile",
1289: "type-profile", "typedefs" },
1290: false), consumer, consumer);
1291: IncludeXMLConsumer.includeNode(DOMUtil
1292: .getFirstNodeFromPath(profile, new String[] {
1293: "profile", "portal-profile" }, false),
1294: consumer, consumer);
1295: IncludeXMLConsumer.includeNode(
1296: DOMUtil.getFirstNodeFromPath(profile,
1297: new String[] { "profile",
1298: "personal-profile" }, false),
1299: consumer, consumer);
1300: IncludeXMLConsumer.includeNode(DOMUtil
1301: .getFirstNodeFromPath(profile, new String[] {
1302: "profile", "status-profile" }, false),
1303: consumer, consumer);
1304: } else {
1305: PortalManagerImpl.streamLayoutProfile(consumer,
1306: portalLayouts, copleyLayouts, mediaType);
1307: }
1308: // END LAYOUT
1309:
1310: if (!configMode) {
1311: Element statusProfile = (Element) DOMUtil
1312: .getFirstNodeFromPath(profile, new String[] {
1313: "profile", "status-profile" }, false);
1314:
1315: String copletNotAvailableMessage = "The coplet is currently not available.";
1316: Node messages = miscNodes[PortalConstants.PROFILE_MISC_MESSAGES_NODE];
1317: if (messages != null) {
1318: messages = DOMUtil.getFirstNodeFromPath(messages,
1319: new String[] { "coplet_not_available" },
1320: false);
1321: if (messages != null)
1322: copletNotAvailableMessage = DOMUtil
1323: .getValueOfNode(messages,
1324: copletNotAvailableMessage);
1325: }
1326:
1327: // LOAD COPLETS
1328: List[] copletContents;
1329:
1330: List[] temp = (List[]) context
1331: .getAttribute(PortalConstants.ATTRIBUTE_COPLET_REPOSITORY);
1332: if (temp != null) {
1333: copletContents = new List[temp.length];
1334: for (int i = 0; i < temp.length; i++) {
1335: if (temp[i] == null) {
1336: copletContents[i] = null;
1337: } else {
1338: copletContents[i] = new ArrayList(temp[i]);
1339: }
1340: }
1341: } else {
1342: copletContents = new List[PortalConstants.MAX_COLUMNS + 2];
1343: context
1344: .setAttribute(
1345: PortalConstants.ATTRIBUTE_COPLET_REPOSITORY,
1346: copletContents);
1347: }
1348:
1349: if (copletContents[0] == null) {
1350: copletContents[0] = new ArrayList(1);
1351: } else {
1352: copletContents[0].clear();
1353: }
1354: if (copletContents[1] == null) {
1355: copletContents[1] = new ArrayList(1);
1356: } else {
1357: copletContents[1].clear();
1358: }
1359:
1360: // test for header
1361: String value;
1362: value = DOMUtil
1363: .getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_HEADER_NODE]);
1364: if (value != null && new Boolean(value).booleanValue()) {
1365: element = (Element) miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE];
1366: if (element != null) {
1367: this .loadCoplets(element, defaultCoplets,
1368: mediaCoplets, copletContents[0],
1369: processCopletsParallel,
1370: defaultCopletTimeout, statusProfile);
1371: }
1372: }
1373:
1374: // content
1375: value = DOMUtil
1376: .getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE]);
1377:
1378: // for a simpler XSL-Stylesheet: The columns must be inserted in the
1379: // correct order!!!
1380: if (value != null && new Integer(value).intValue() > 0) {
1381:
1382: Element columnElement;
1383: int columns = new Integer(value).intValue();
1384: if (columns > PortalConstants.MAX_COLUMNS) {
1385: throw new ProcessingException(
1386: "portal: Maximum number of columns supported is: "
1387: + PortalConstants.MAX_COLUMNS);
1388: }
1389:
1390: for (int colindex = 1; colindex <= columns; colindex++) {
1391: if (copletContents[colindex + 1] == null) {
1392: copletContents[colindex + 1] = new ArrayList(
1393: 10);
1394: } else {
1395: copletContents[colindex + 1].clear();
1396: }
1397: columnElement = (Element) miscNodes[7 + colindex];
1398: element = (Element) DOMUtil
1399: .getFirstNodeFromPath(columnElement,
1400: new String[] { "coplets" },
1401: false);
1402: if (element != null) {
1403: this
1404: .loadCoplets(
1405: element,
1406: defaultCoplets,
1407: mediaCoplets,
1408: copletContents[colindex + 1],
1409: processCopletsParallel,
1410: defaultCopletTimeout,
1411: statusProfile);
1412: }
1413:
1414: }
1415: for (int colindex = columns + 2; colindex <= PortalConstants.MAX_COLUMNS + 1; colindex++) {
1416: if (copletContents[colindex] != null) {
1417: copletContents[colindex] = null;
1418: }
1419: }
1420:
1421: } else {
1422: for (int colindex = 1; colindex <= PortalConstants.MAX_COLUMNS; colindex++) {
1423: if (copletContents[colindex + 1] != null) {
1424: copletContents[colindex + 1] = null;
1425: }
1426: }
1427: }
1428:
1429: // test for footer
1430: value = DOMUtil
1431: .getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_FOOTER_NODE]);
1432: if (value != null && new Boolean(value).booleanValue()) {
1433: element = (Element) miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE];
1434: if (element != null) {
1435: this .loadCoplets(element, defaultCoplets,
1436: mediaCoplets, copletContents[1],
1437: processCopletsParallel,
1438: defaultCopletTimeout, statusProfile);
1439: }
1440: }
1441: // END LOAD COPLETS
1442:
1443: // DESIGN
1444: // test for header
1445: if (copletContents[0].size() > 0) {
1446: consumer.startElement("", "header", "header", attr);
1447: this .processCopletList(copletContents[0], consumer,
1448: copletNotAvailableMessage,
1449: defaultCopletTimeout);
1450: consumer.endElement("", "header", "header");
1451: }
1452:
1453: // content
1454: value = DOMUtil
1455: .getValueOfNode(miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE]);
1456:
1457: // for a simpler XSL-Stylesheet: The columns must be inserted in the
1458: // correct order!!!
1459: if (value != null && new Integer(value).intValue() > 0) {
1460: attr.addAttribute("", "number", "number", "CDATA",
1461: value);
1462: XMLUtils.startElement(consumer, "columns", attr);
1463: attr.clear();
1464:
1465: int columns = new Integer(value).intValue();
1466: if (columns > PortalConstants.MAX_COLUMNS) {
1467: throw new ProcessingException(
1468: "portal: Maximum number of columns supported is: "
1469: + PortalConstants.MAX_COLUMNS);
1470: }
1471:
1472: // determine the width of the columns
1473: String[] width = new String[columns];
1474: int normalWidth = 100 / columns;
1475: Element columnElement;
1476:
1477: for (int colindex = 1; colindex <= columns; colindex++) {
1478: columnElement = (Element) miscNodes[7 + colindex];
1479: value = DOMUtil.getValueOf(columnElement,
1480: "width", this .xpathProcessor);
1481: if (value == null) {
1482: width[colindex - 1] = "" + normalWidth
1483: + "%";
1484: } else {
1485: width[colindex - 1] = value;
1486: }
1487: }
1488:
1489: for (int colindex = 1; colindex <= columns; colindex++) {
1490: attr.addAttribute("", "position", "position",
1491: "CDATA", "" + colindex);
1492: attr.addAttribute("", "width", "width",
1493: "CDATA", width[colindex - 1]);
1494: XMLUtils.startElement(consumer, "column", attr);
1495: attr.clear();
1496:
1497: this .processCopletList(
1498: copletContents[colindex + 1], consumer,
1499: copletNotAvailableMessage,
1500: defaultCopletTimeout);
1501:
1502: XMLUtils.endElement(consumer, "column");
1503: }
1504: XMLUtils.endElement(consumer, "columns");
1505: } else {
1506: attr.addAttribute("", "number", "number", "CDATA",
1507: "0");
1508: XMLUtils.startElement(consumer, "columns", attr);
1509: XMLUtils.endElement(consumer, "columns");
1510: attr.clear();
1511: }
1512:
1513: // test for footer
1514: if (copletContents[1].size() > 0) {
1515: XMLUtils.startElement(consumer, "footer");
1516: this .processCopletList(copletContents[1], consumer,
1517: copletNotAvailableMessage,
1518: defaultCopletTimeout);
1519: XMLUtils.endElement(consumer, "footer");
1520: }
1521: // END DESIGN
1522:
1523: for (int i = 0; i < copletContents.length; i++) {
1524: if (copletContents[i] != null)
1525: copletContents[i].clear();
1526: }
1527:
1528: // Personal information and status information
1529: this .sendEvents(consumer, DOMUtil.getFirstNodeFromPath(
1530: profile, new String[] { "profile",
1531: "personal-profile" }, false));
1532: this .sendEvents(consumer, statusProfile);
1533: }
1534:
1535: if (configMode) {
1536: XMLUtils.endElement(consumer,
1537: PortalConstants.ELEMENT_PORTALCONF);
1538: } else {
1539: XMLUtils.endElement(consumer,
1540: PortalConstants.ELEMENT_PORTAL);
1541: }
1542:
1543: } catch (javax.xml.transform.TransformerException local) { // end synchronized
1544: throw new ProcessingException("TransformerException: "
1545: + local, local);
1546: } finally {
1547: this .getTransactionManager()
1548: .stopReadingTransaction(context);
1549: }
1550: if (this .getLogger().isDebugEnabled()) {
1551: this .getLogger().debug("END showPortal");
1552: }
1553: }
1554:
1555: /**
1556: * Building the profile.
1557: * This includes several steps which are declared in detail inside this method...
1558: */
1559: protected void buildProfile(String type, String role, String id,
1560: boolean adminProfile) throws ProcessingException,
1561: IOException, SAXException {
1562: // synchronized
1563: if (this .getLogger().isDebugEnabled()) {
1564: this .getLogger().debug(
1565: "BEGIN buildProfile type=" + type + ", role="
1566: + role + ", id=" + id + ", adminProfile="
1567: + adminProfile);
1568: }
1569: try {
1570: // check parameter
1571: if (type == null) {
1572: throw new ProcessingException(
1573: "buildProfile: Type is required");
1574: }
1575: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)
1576: || type
1577: .equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)) {
1578: // nothing to do here
1579: } else if (type
1580: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) {
1581: if (role == null) {
1582: throw new ProcessingException(
1583: "buildProfile: Role is required");
1584: }
1585: } else if (type
1586: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
1587: if (role == null) {
1588: throw new ProcessingException(
1589: "buildProfile: Role is required");
1590: }
1591: if (id == null) {
1592: throw new ProcessingException(
1593: "buildProfile: ID is required");
1594: }
1595: } else {
1596: throw new ProcessingException(
1597: "buildProfile: Type unknown: " + type);
1598: }
1599:
1600: SessionContext context = this .getContext(true);
1601: try {
1602: this .getTransactionManager().startWritingTransaction(
1603: context);
1604:
1605: String profileID = this .getProfileID(type, role, id,
1606: adminProfile);
1607: Map theProfile = null;
1608:
1609: // get the configuration
1610: Map config = this .getConfiguration();
1611: if (config == null) {
1612: throw new ProcessingException(
1613: "No configuration for portal found.");
1614: }
1615:
1616: // is the ID profile cached?
1617: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
1618: theProfile = this .getCachedProfile(profileID,
1619: config);
1620: }
1621:
1622: if (theProfile == null) {
1623:
1624: boolean doBase = false;
1625: boolean doGlobal = false;
1626: boolean doRole = false;
1627: boolean doID = false;
1628: String previousID;
1629:
1630: if (type
1631: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
1632: doID = true;
1633: previousID = this .getProfileID(
1634: PortalManagerImpl.BUILDTYPE_VALUE_ROLE,
1635: role, null, adminProfile);
1636: theProfile = this .getCachedProfile(previousID,
1637: config);
1638: if (theProfile == null) {
1639: doRole = true;
1640: previousID = this
1641: .getProfileID(
1642: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
1643: null, null, adminProfile);
1644: theProfile = this .getCachedProfile(
1645: previousID, config);
1646: if (theProfile == null) {
1647: doGlobal = true;
1648: previousID = this
1649: .getProfileID(
1650: PortalManagerImpl.BUILDTYPE_VALUE_BASIC,
1651: null, null,
1652: adminProfile);
1653: theProfile = this .getCachedProfile(
1654: previousID, config);
1655: }
1656: }
1657: } else if (type
1658: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) {
1659: theProfile = this .getCachedProfile(profileID,
1660: config);
1661: if (theProfile == null) {
1662: doRole = true;
1663: previousID = this
1664: .getProfileID(
1665: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
1666: null, null, adminProfile);
1667: theProfile = this .getCachedProfile(
1668: previousID, config);
1669: if (theProfile == null) {
1670: doGlobal = true;
1671: previousID = this
1672: .getProfileID(
1673: PortalManagerImpl.BUILDTYPE_VALUE_BASIC,
1674: null, null,
1675: adminProfile);
1676: theProfile = this .getCachedProfile(
1677: previousID, config);
1678: }
1679: }
1680: } else if (type
1681: .equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) {
1682: theProfile = this .getCachedProfile(profileID,
1683: config);
1684: if (theProfile == null) {
1685: doGlobal = true;
1686: previousID = this
1687: .getProfileID(
1688: PortalManagerImpl.BUILDTYPE_VALUE_BASIC,
1689: null, null, adminProfile);
1690: theProfile = this .getCachedProfile(
1691: previousID, config);
1692: }
1693: } else { // basic profile
1694: theProfile = this .getCachedProfile(profileID,
1695: config);
1696: }
1697:
1698: // build the profile
1699: if (theProfile == null) {
1700: theProfile = new HashMap(8, 2);
1701: doBase = true;
1702: }
1703:
1704: Element profileRoot;
1705: DocumentFragment profile;
1706:
1707: if (doBase) {
1708: // build the base level
1709: profile = this .buildBaseProfile(config,
1710: adminProfile);
1711: profileRoot = (Element) profile.getFirstChild();
1712: theProfile.put(PortalConstants.PROFILE_PROFILE,
1713: profile);
1714: this
1715: .cacheProfile(
1716: this
1717: .getProfileID(
1718: PortalManagerImpl.BUILDTYPE_VALUE_BASIC,
1719: null, null,
1720: adminProfile),
1721: theProfile, config);
1722: } else {
1723: profile = (DocumentFragment) theProfile
1724: .get(PortalConstants.PROFILE_PROFILE);
1725: profileRoot = (Element) profile.getFirstChild();
1726: }
1727:
1728: // load the global delta if type is global, role or user (but not basic!)
1729: if (doGlobal) {
1730: this .buildGlobalProfile(profileRoot, config,
1731: adminProfile);
1732: this
1733: .cacheProfile(
1734: this
1735: .getProfileID(
1736: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
1737: null, null,
1738: adminProfile),
1739: theProfile, config);
1740: }
1741:
1742: // load the role delta if type is role or user
1743: if (doRole) {
1744: this .buildRoleProfile(profileRoot, config,
1745: role, adminProfile);
1746: this .cacheProfile(this .getProfileID(
1747: PortalManagerImpl.BUILDTYPE_VALUE_ROLE,
1748: role, null, adminProfile), theProfile,
1749: config);
1750: }
1751:
1752: // load the user delta if type is user
1753: if (doID) {
1754: this .buildUserProfile(profileRoot, config,
1755: role, id, adminProfile);
1756: }
1757:
1758: // load the status profile when type is user
1759: if (type
1760: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
1761: this .buildUserStatusProfile(profileRoot,
1762: config, role, id);
1763: }
1764:
1765: if (!type
1766: .equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)) {
1767: this .buildRunProfile(theProfile, context,
1768: profile);
1769:
1770: theProfile.put(
1771: PortalConstants.PROFILE_PORTAL_LAYOUTS,
1772: this .buildPortalLayouts(context,
1773: profile));
1774: theProfile.put(
1775: PortalConstants.PROFILE_COPLET_LAYOUTS,
1776: this .buildcopleyLayouts(context,
1777: profile));
1778:
1779: this .buildTypeProfile(theProfile, context,
1780: profile);
1781: }
1782:
1783: // cache the profile, if user
1784: if (doID) {
1785: this
1786: .cacheProfile(profileID, theProfile,
1787: config);
1788: }
1789: } else {
1790: // load the status profile when type is user
1791: if (type
1792: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
1793: DocumentFragment profile = (DocumentFragment) theProfile
1794: .get(PortalConstants.PROFILE_PROFILE);
1795: Element profileRoot = (Element) profile
1796: .getFirstChild();
1797: this .buildUserStatusProfile(profileRoot,
1798: config, role, id);
1799: }
1800: }
1801:
1802: // store the whole profile
1803: this .storeProfile(profileID, theProfile);
1804:
1805: // now put role and id into the context if type is ID
1806: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)
1807: && !adminProfile) {
1808: context.setAttribute(
1809: PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE,
1810: role);
1811: context.setAttribute(
1812: PortalManagerImpl.ATTRIBUTE_PORTAL_ID, id);
1813: }
1814: } finally {
1815: this .getTransactionManager().stopWritingTransaction(
1816: context);
1817: }// end synchronized
1818: } catch (javax.xml.transform.TransformerException local) {
1819: throw new ProcessingException("TransformerException: "
1820: + local, local);
1821: }
1822:
1823: if (this .getLogger().isDebugEnabled()) {
1824: this .getLogger().debug("END buildProfile");
1825: }
1826: }
1827:
1828: /**
1829: * Build the profile delta
1830: */
1831: private DocumentFragment buildProfileDelta(String type,
1832: String role, String id, boolean adminProfile)
1833: throws SAXException, ProcessingException, IOException,
1834: javax.xml.transform.TransformerException {
1835: // calling method must be synchronized
1836: if (this .getLogger().isDebugEnabled()) {
1837: this .getLogger().debug(
1838: "END buildProfileDeltaN type=" + type + ", role="
1839: + role + ", id=" + id);
1840: }
1841:
1842: Map originalProfile;
1843: Map baseProfile;
1844: String baseType, baseRole, baseID, rootElementName;
1845: DocumentFragment originalFragment;
1846: DocumentFragment delta;
1847: SessionContext context = this .getContext(true);
1848:
1849: originalProfile = this .retrieveProfile(this .getProfileID(type,
1850: role, id, adminProfile));
1851: if (originalProfile == null) {
1852: throw new ProcessingException(
1853: "buildProfileDelta: no profile found for " + type
1854: + " - " + role + " - " + id + ".");
1855: }
1856:
1857: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
1858: baseType = PortalManagerImpl.BUILDTYPE_VALUE_ROLE;
1859: baseRole = role;
1860: baseID = null;
1861: rootElementName = "user-delta";
1862: } else if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) {
1863: baseType = PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL;
1864: baseRole = null;
1865: baseID = null;
1866: rootElementName = "role-delta";
1867: } else if (type
1868: .equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) {
1869: baseType = PortalManagerImpl.BUILDTYPE_VALUE_BASIC;
1870: baseRole = null;
1871: baseID = null;
1872: rootElementName = "global-delta";
1873: } else {
1874: throw new ProcessingException("buildProfileDelta: type '"
1875: + type + "' not allowed.");
1876: }
1877:
1878: // the profile is created as we dont want to use any memory representation!
1879: this .createProfile(context, baseType, baseRole, baseID,
1880: adminProfile);
1881: baseProfile = this .retrieveProfile(this .getProfileID(baseType,
1882: baseRole, baseID, adminProfile));
1883: if (baseProfile == null) {
1884: throw new ProcessingException(
1885: "buildProfileDelta: no baseProfile found.");
1886: }
1887:
1888: originalFragment = (DocumentFragment) originalProfile
1889: .get(PortalConstants.PROFILE_PROFILE);
1890: delta = originalFragment.getOwnerDocument()
1891: .createDocumentFragment();
1892: delta.appendChild(delta.getOwnerDocument().createElementNS(
1893: null, rootElementName));
1894:
1895: // Copy portal content
1896: Node profileDelta = DOMUtil.getFirstNodeFromPath(
1897: originalFragment,
1898: new String[] { "profile", "portal-profile" }, false)
1899: .cloneNode(true);
1900: delta.getFirstChild().appendChild(profileDelta);
1901:
1902: // Diff layout profile, coplet profile, personal profile but not status profile!
1903: this .diff(originalFragment, (DocumentFragment) baseProfile
1904: .get(PortalConstants.PROFILE_PROFILE),
1905: "profile/layout-profile", (Element) delta
1906: .getFirstChild());
1907: this .diff(originalFragment, (DocumentFragment) baseProfile
1908: .get(PortalConstants.PROFILE_PROFILE),
1909: "profile/coplets-profile", (Element) delta
1910: .getFirstChild());
1911: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) {
1912: profileDelta = DOMUtil.getFirstNodeFromPath(
1913: originalFragment,
1914: new String[] { "profile", "personal-profile" },
1915: false).cloneNode(true);
1916: delta.getFirstChild().appendChild(profileDelta);
1917: } else {
1918: this .diff(originalFragment, (DocumentFragment) baseProfile
1919: .get(PortalConstants.PROFILE_PROFILE),
1920: "profile/personal-profile", (Element) delta
1921: .getFirstChild());
1922: }
1923:
1924: // check for the highes coplet number
1925: Node[] miscNodes = (Node[]) originalProfile
1926: .get(PortalConstants.PROFILE_MISC_POINTER);
1927: Element lastCoplet = (Element) miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE];
1928: if (lastCoplet != null) {
1929: String lastNumber = lastCoplet.getAttributeNS(null,
1930: "number");
1931: if (lastNumber != null) {
1932: int value = new Integer(lastNumber).intValue();
1933: if (value > 1000000) {
1934: NodeList coplets = DOMUtil
1935: .selectNodeList(
1936: delta,
1937: "profile/portal-profile/descendant::coplet[@id and @number]",
1938: this .xpathProcessor);
1939: if (coplets != null) {
1940: Element copletNode;
1941: String oldNumber;
1942: String copletId;
1943: Element statusNode;
1944: boolean copletsChanged = false;
1945: for (int i = 0; i < coplets.getLength(); i++) {
1946: copletNode = (Element) coplets.item(i);
1947: oldNumber = copletNode.getAttributeNS(null,
1948: "number");
1949: copletId = copletNode.getAttributeNS(null,
1950: "id");
1951: statusNode = (Element) DOMUtil
1952: .getSingleNode(delta,
1953: "status-profile/customization/coplet[@id='"
1954: + copletId
1955: + "' and @number='"
1956: + oldNumber + "']",
1957: this .xpathProcessor);
1958: copletNode.setAttributeNS(null, "number",
1959: "" + (i + 1));
1960: if (statusNode != null) {
1961: statusNode.setAttributeNS(null,
1962: "number", "" + (i + 1));
1963: copletsChanged = true;
1964: }
1965: }
1966: if (copletsChanged) {
1967: this .saveUserStatusProfile(originalProfile,
1968: this .getConfiguration(), role, id);
1969: }
1970: }
1971: }
1972: }
1973: }
1974:
1975: // Last part: strip type information
1976: NodeList typeElements = DOMUtil
1977: .selectNodeList(
1978: delta,
1979: "descendant::*[@formpath and @formdescription and @formtype]",
1980: this .xpathProcessor);
1981: if (typeElements != null) {
1982: for (int i = 0; i < typeElements.getLength(); i++) {
1983: ((Element) typeElements.item(i)).removeAttributeNS(
1984: null, "formpath");
1985: ((Element) typeElements.item(i)).removeAttributeNS(
1986: null, "formdescription");
1987: ((Element) typeElements.item(i)).removeAttributeNS(
1988: null, "formtype");
1989: }
1990: }
1991:
1992: if (this .getLogger().isDebugEnabled()) {
1993: this .getLogger().debug(
1994: "END buildProfileDelta delta=" + delta);
1995: }
1996: return delta;
1997: }
1998:
1999: /**
2000: * Make the difference :-)
2001: */
2002: private void diff(DocumentFragment original, DocumentFragment base,
2003: String path, Element deltaElement) throws SAXException,
2004: javax.xml.transform.TransformerException {
2005: // calling method is already synchronized
2006: Element originalRoot = (Element) DOMUtil.getSingleNode(
2007: original, path, this .xpathProcessor);
2008: Element baseRoot = (Element) DOMUtil.getSingleNode(base, path,
2009: this .xpathProcessor);
2010: if (originalRoot != null && baseRoot != null) {
2011: List nodeStack = new ArrayList();
2012: String name = baseRoot.getNodeName();
2013: name = name.substring(0, name.indexOf("-profile"))
2014: + "-delta";
2015: nodeStack.add(originalRoot.getOwnerDocument()
2016: .createElementNS(null, name));
2017:
2018: this .diffNode(baseRoot, originalRoot, nodeStack,
2019: deltaElement);
2020: }
2021: }
2022:
2023: /**
2024: * Diff one node
2025: */
2026: private void diffNode(Element baseNode, Element originalNode,
2027: List nodeStack, Element deltaElement) throws SAXException,
2028: javax.xml.transform.TransformerException {
2029: // calling method is already synchronized
2030: NodeList baseChilds;
2031: NodeList originalChilds;
2032: int i, len;
2033: int m, l;
2034: boolean found;
2035: Node currentOrigNode = null;
2036: Node currentBaseNode = null;
2037:
2038: originalChilds = originalNode.getChildNodes();
2039: len = originalChilds.getLength();
2040: baseChilds = baseNode.getChildNodes();
2041: l = baseChilds.getLength();
2042:
2043: for (i = 0; i < len; i++) {
2044: currentOrigNode = originalChilds.item(i);
2045: if (currentOrigNode.getNodeType() == Node.ELEMENT_NODE) {
2046:
2047: // search the delta node in the profile
2048: m = 0;
2049: found = false;
2050: while (!found && m < l) {
2051: currentBaseNode = baseChilds.item(m);
2052: if (currentBaseNode.getNodeType() == Node.ELEMENT_NODE
2053: && currentBaseNode.getNodeName().equals(
2054: currentOrigNode.getNodeName())) {
2055:
2056: // now we have found a node with the same name
2057: // next: the attributes must match also
2058: found = this .compareAttributes(currentBaseNode,
2059: currentOrigNode);
2060: }
2061: if (!found)
2062: m++;
2063: }
2064:
2065: if (found) {
2066: // do we have elements as children or text?
2067: currentOrigNode.normalize();
2068: if (currentOrigNode.hasChildNodes()) {
2069:
2070: // do a recursive call for sub elements
2071: nodeStack.add(currentOrigNode);
2072: this .diffNode((Element) currentBaseNode,
2073: (Element) currentOrigNode, nodeStack,
2074: deltaElement);
2075:
2076: // and now compare the text nodes
2077: String baseString = DOMUtil.getValueOfNode(
2078: currentBaseNode, "").trim();
2079: String originalString = DOMUtil.getValueOfNode(
2080: currentOrigNode, "").trim();
2081:
2082: if (!baseString.equals(originalString)) {
2083: // this is the tricky part:
2084: // we have to process all nodes on the stack
2085: // and insert them in the deltaElement
2086: Element currentElement;
2087: Element contextElement = deltaElement;
2088: NodeList possibleChilds;
2089: boolean foundChild;
2090: int cIndex;
2091:
2092: for (int p = 0; p < nodeStack.size(); p++) {
2093: currentElement = (Element) nodeStack
2094: .get(p);
2095: possibleChilds = DOMUtil
2096: .getNodeListFromPath(
2097: contextElement,
2098: new String[] { currentElement
2099: .getNodeName() });
2100: foundChild = false;
2101: cIndex = 0;
2102: if (possibleChilds != null) {
2103: while (!foundChild
2104: && cIndex < possibleChilds
2105: .getLength()) {
2106: foundChild = this
2107: .compareAttributes(
2108: currentElement,
2109: possibleChilds
2110: .item(cIndex));
2111: if (!foundChild)
2112: cIndex++;
2113: }
2114: }
2115: if (foundChild) {
2116: contextElement = (Element) possibleChilds
2117: .item(cIndex);
2118: } else {
2119: currentElement = (Element) currentElement
2120: .cloneNode(false);
2121: contextElement
2122: .appendChild(currentElement);
2123: contextElement = currentElement;
2124: }
2125: }
2126: // now add the text
2127: contextElement.appendChild(contextElement
2128: .getOwnerDocument().createTextNode(
2129: originalString));
2130: }
2131:
2132: nodeStack.remove(nodeStack.size() - 1);
2133: }
2134: }
2135: }
2136:
2137: }
2138:
2139: }
2140:
2141: /* (non-Javadoc)
2142: * @see org.apache.cocoon.webapps.portal.components.PortalManager#getProfileID(java.lang.String, java.lang.String, java.lang.String, boolean)
2143: */
2144: public String getProfileID(String type, String role, String id,
2145: boolean adminProfile) throws ProcessingException {
2146: // No sync required
2147: this .setup();
2148: StringBuffer key = new StringBuffer((adminProfile ? "aprofile:"
2149: : "uprofile:"));
2150: RequestState reqstate = this .getRequestState();
2151: key.append(reqstate.getHandlerName()).append('|').append(
2152: reqstate.getApplicationName()).append(':').append(type);
2153:
2154: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)
2155: || type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
2156: role = XMLUtil.encode(role);
2157: key.append('_').append(role.length()).append('_').append(
2158: role);
2159: }
2160: if (type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
2161: id = XMLUtil.encode(id);
2162: key.append('_').append(id);
2163: }
2164: return key.toString();
2165: }
2166:
2167: /**
2168: * Get the profile role from the key
2169: */
2170: private boolean getIsAdminProfile(String profileID) {
2171: // No sync required
2172: return profileID.startsWith("a");
2173: }
2174:
2175: /**
2176: * Get the profile role from the key
2177: */
2178: private String getRole(String profileID) {
2179: // No sync required
2180: profileID = XMLUtil.decode(profileID);
2181: int pos = profileID.indexOf('_');
2182: if (pos == -1) {
2183: return null;
2184: } else {
2185: String lastPart = profileID.substring(pos + 1);
2186: pos = lastPart.indexOf('_');
2187: if (pos == -1)
2188: return null;
2189: int len = new Integer(lastPart.substring(0, pos))
2190: .intValue();
2191: lastPart = lastPart.substring(pos + 1, pos + 1 + len);
2192: return lastPart;
2193: }
2194: }
2195:
2196: /**
2197: * Get the profile ID from the key
2198: */
2199: private String getID(String profileID) {
2200: // No sync required
2201: profileID = XMLUtil.decode(profileID);
2202: int pos = profileID.indexOf('_');
2203: if (pos == -1) {
2204: return null;
2205: } else {
2206: String lastPart = profileID.substring(pos + 1);
2207: pos = lastPart.indexOf('_');
2208: if (pos == -1) {
2209: return null;
2210: } else {
2211: lastPart = lastPart.substring(pos + 1);
2212: pos = lastPart.indexOf('_');
2213: if (pos == -1) {
2214: return null;
2215: } else {
2216: return lastPart.substring(pos + 1);
2217: }
2218: }
2219: }
2220: }
2221:
2222: /**
2223: * Get the profile type from the key
2224: */
2225: private String getType(String profileID) {
2226: // No sync required
2227: profileID = XMLUtil.decode(profileID);
2228: int endPos = profileID.indexOf('_');
2229: if (endPos == -1) {
2230: int startPos = profileID.lastIndexOf(':');
2231: return profileID.substring(startPos + 1);
2232: } else {
2233: int startPos = profileID.lastIndexOf(':', endPos);
2234: return profileID.substring(startPos + 1, endPos);
2235: }
2236: }
2237:
2238: /**
2239: * Store the profil
2240: */
2241: private void storeProfile(String profileID, Map profile)
2242: throws ProcessingException {
2243: // synchronized
2244: if (this .getLogger().isDebugEnabled()) {
2245: this .getLogger().debug(
2246: "BEGIN storeProfile id=" + profileID + ", profile="
2247: + profile);
2248: }
2249:
2250: Session session = this .getSessionManager().getSession(true);
2251: synchronized (session) {
2252: session.setAttribute(profileID, profile);
2253: }
2254:
2255: if (this .getLogger().isDebugEnabled()) {
2256: this .getLogger().debug("END storeProfile");
2257: }
2258: }
2259:
2260: /* (non-Javadoc)
2261: * @see org.apache.cocoon.webapps.portal.components.PortalManager#retrieveProfile(java.lang.String)
2262: */
2263: public Map retrieveProfile(String profileID)
2264: throws ProcessingException {
2265: // synchronized
2266: if (this .getLogger().isDebugEnabled()) {
2267: this .getLogger().debug(
2268: "BEGIN retrieveProfile id=" + profileID);
2269: }
2270: this .setup();
2271: Session session = this .getSessionManager().getSession(true);
2272: Map result;
2273: synchronized (session) {
2274: result = (Map) session.getAttribute(profileID);
2275: }
2276:
2277: if (this .getLogger().isDebugEnabled()) {
2278: this .getLogger()
2279: .debug(
2280: "END retrieveProfile profile="
2281: + (result != null ? "**PROFILE**"
2282: : "null"));
2283: }
2284:
2285: return result;
2286: }
2287:
2288: /**
2289: * Cache the profile (if cache is turned on)
2290: */
2291: private void cacheProfile(String profileID, Map profile,
2292: Map configuration) {
2293: // synchronized
2294: if (this .getLogger().isDebugEnabled()) {
2295: this .getLogger().debug(
2296: "BEGIN cacheProfile id=" + profileID + ", profile="
2297: + profile);
2298: }
2299: try {
2300: if (configuration != null
2301: && !this .getIsAdminProfile(profileID)) {
2302: String storePrefix = (String) configuration
2303: .get(PortalConstants.CONF_PROFILE_CACHE);
2304: if (storePrefix != null) {
2305: String key = profileID.substring(1);
2306: this .getProfileStore().store(key, profile);
2307: }
2308: }
2309: } catch (Exception local) {
2310: this .getLogger().warn("Caching Profile failed.", local);
2311: // local exceptions are ignored
2312: // we dont want to get an exception response due to cache problems
2313: }
2314: if (this .getLogger().isDebugEnabled()) {
2315: this .getLogger().debug("END cacheProfile");
2316: }
2317: }
2318:
2319: /**
2320: * Retrieve the cached profil if available
2321: */
2322: private Map getCachedProfile(String profileID, Map configuration) {
2323: // synchronized
2324: if (this .getLogger().isDebugEnabled()) {
2325: this .getLogger().debug(
2326: "BEGIN getCachedProfile id=" + profileID);
2327: }
2328:
2329: Map result = null;
2330:
2331: try {
2332: if (configuration != null
2333: && !this .getIsAdminProfile(profileID)) {
2334: final String storePrefix = (String) configuration
2335: .get(PortalConstants.CONF_PROFILE_CACHE);
2336: if (storePrefix != null) {
2337: final String key = profileID.substring(1);
2338: final Store store = this .getProfileStore();
2339: if (store.containsKey(key)) {
2340: result = (Map) store.get(key);
2341: }
2342: }
2343: }
2344: } catch (Exception local) {
2345: // local exceptions are ignored
2346: // we dont want to get an exception response due to cache problems
2347: this .getLogger().warn("Getting cached Profile failed.",
2348: local);
2349: result = null;
2350: }
2351:
2352: if (this .getLogger().isDebugEnabled()) {
2353: this .getLogger()
2354: .debug(
2355: "END getCachedProfile profile="
2356: + (result != null ? "**PROFILE**"
2357: : "null"));
2358: }
2359: return result;
2360: }
2361:
2362: /**
2363: * Clean up the cache, if the global profile was saved, delete all role and user profiles.
2364: * If a role profile was saved delete all user profiles. If the basic profile was
2365: * saved delete all profiles.
2366: */
2367: private void cleanUpCache(String type, String role,
2368: Map configuration) throws ProcessingException {
2369: if (this .getLogger().isDebugEnabled()) {
2370: this .getLogger().debug(
2371: "BEGIN cleanUpCache type=" + type + ", role="
2372: + role + ", config=" + configuration);
2373: }
2374: if (configuration != null && type != null
2375: && !type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
2376: String storePrefix = (String) configuration
2377: .get(PortalConstants.CONF_PROFILE_CACHE);
2378: if (storePrefix != null) {
2379: Store store = this .getProfileStore();
2380: Enumeration keys = store.keys();
2381: String currentKey;
2382: String deleteGlobal = null;
2383: String deleteRole = null;
2384: String deleteUser = null;
2385:
2386: if (type
2387: .equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)
2388: || type
2389: .equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) {
2390: if (type
2391: .equals(PortalManagerImpl.BUILDTYPE_VALUE_BASIC)) {
2392: deleteGlobal = this
2393: .getProfileID(
2394: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
2395: null, null, false).substring(1);
2396: }
2397: deleteRole = this .getProfileID(
2398: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
2399: null, null, false);
2400: deleteRole = deleteRole.substring(1, deleteRole
2401: .lastIndexOf(':') + 1)
2402: + PortalManagerImpl.BUILDTYPE_VALUE_ROLE;
2403: deleteUser = this .getProfileID(
2404: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL,
2405: null, null, false);
2406: deleteUser = deleteUser.substring(1, deleteUser
2407: .lastIndexOf(':') + 1)
2408: + PortalManagerImpl.BUILDTYPE_VALUE_ID;
2409: } else { // role
2410: deleteGlobal = this .getProfileID(
2411: PortalManagerImpl.BUILDTYPE_VALUE_ROLE,
2412: role, null, false).substring(1);
2413: deleteUser = this .getProfileID(
2414: PortalManagerImpl.BUILDTYPE_VALUE_ID, role,
2415: "a", false);
2416: deleteUser = deleteUser.substring(1, deleteUser
2417: .length() - 1);
2418: }
2419:
2420: while (keys.hasMoreElements()) {
2421: Object k = keys.nextElement();
2422: if (k instanceof String) {
2423: currentKey = (String) k;
2424: if (deleteGlobal != null
2425: && currentKey.equals(deleteGlobal)) {
2426: store.remove(currentKey);
2427: } else if (deleteRole != null
2428: && currentKey.startsWith(deleteRole)) {
2429: store.remove(currentKey);
2430: } else if (deleteUser != null
2431: && currentKey.startsWith(deleteUser)) {
2432: store.remove(currentKey);
2433: }
2434: }
2435: }
2436: }
2437: } else if (configuration != null && type == null) {
2438: // clean whole cache
2439: String storePrefix = (String) configuration
2440: .get(PortalConstants.CONF_PROFILE_CACHE);
2441: if (storePrefix != null) {
2442: Store store = this .getProfileStore();
2443: Enumeration keys = store.keys();
2444: String currentKey;
2445: String delete;
2446:
2447: delete = this .getProfileID(
2448: PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL, null,
2449: null, false);
2450: delete = delete.substring(1,
2451: delete.lastIndexOf(':') + 1);
2452: while (keys.hasMoreElements()) {
2453: Object k = keys.nextElement();
2454: if (k instanceof String) {
2455: currentKey = (String) k;
2456: if (currentKey.startsWith(delete)) {
2457: store.remove(currentKey);
2458: }
2459: }
2460: }
2461: }
2462: }
2463:
2464: if (this .getLogger().isDebugEnabled()) {
2465: this .getLogger().debug("END cleanUpCache");
2466: }
2467: }
2468:
2469: /**
2470: * Build the run profil and store it in the <code>profileMap</code>.
2471: */
2472: private void buildRunProfile(Map profileMap,
2473: SessionContext context, DocumentFragment baseProfile)
2474: throws ProcessingException,
2475: javax.xml.transform.TransformerException {
2476: // calling method is synced
2477: if (this .getLogger().isDebugEnabled()) {
2478: this .getLogger().debug(
2479: "BEGIN buildRunProfile context=" + context
2480: + ", profile=" + baseProfile);
2481: }
2482:
2483: // The map containing the coplets which appear on each medium
2484: Map defaultCoplets = new HashMap(20, 5);
2485: // The map containing for each media type a map with coplets which
2486: // appear only for the given media
2487: Map mediaCoplets = new HashMap(5, 2);
2488:
2489: profileMap.put(PortalConstants.PROFILE_DEFAULT_COPLETS,
2490: defaultCoplets);
2491: profileMap.put(PortalConstants.PROFILE_MEDIA_COPLETS,
2492: mediaCoplets);
2493:
2494: // get AuthenticationManager instance
2495: String[] types = this .getMediaManager().getMediaTypes();
2496: Map mediaMap;
2497: for (int i = 0; i < types.length; i++) {
2498: mediaCoplets.put(types[i], new HashMap(5, 3));
2499: }
2500:
2501: // build misc nodes
2502: Node[] miscNodes = new Node[13];
2503: miscNodes[PortalConstants.PROFILE_MISC_HEADER_NODE] = DOMUtil
2504: .getFirstNodeFromPath(baseProfile, new String[] {
2505: "profile", "layout-profile", "portal",
2506: "header", "exists" }, false);
2507: miscNodes[PortalConstants.PROFILE_MISC_FOOTER_NODE] = DOMUtil
2508: .getFirstNodeFromPath(baseProfile, new String[] {
2509: "profile", "layout-profile", "portal",
2510: "footer", "exists" }, false);
2511: miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE] = DOMUtil
2512: .getFirstNodeFromPath(baseProfile, new String[] {
2513: "profile", "portal-profile", "content",
2514: "header" }, false);
2515: miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE] = DOMUtil
2516: .getFirstNodeFromPath(baseProfile, new String[] {
2517: "profile", "portal-profile", "content",
2518: "footer" }, false);
2519: miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE] = DOMUtil
2520: .getFirstNodeFromPath(baseProfile, new String[] {
2521: "profile", "layout-profile", "portal",
2522: "columns", "number" }, false);
2523: miscNodes[PortalConstants.PROFILE_MISC_MESSAGES_NODE] = DOMUtil
2524: .getFirstNodeFromPath(baseProfile, new String[] {
2525: "profile", "personal-profile", "messages" },
2526: false);
2527: for (int i = 1; i <= PortalConstants.MAX_COLUMNS; i++) {
2528: miscNodes[7 + i] = DOMUtil.getSingleNode(baseProfile,
2529: "profile/portal-profile/content/column[@position='"
2530: + i + "']", this .xpathProcessor);
2531: }
2532:
2533: profileMap.put(PortalConstants.PROFILE_MISC_POINTER, miscNodes);
2534:
2535: // build coplet configs
2536: NodeList coplets;
2537: int i, l;
2538: Element configElement;
2539: String copletID;
2540: String copletMedia;
2541:
2542: coplets = DOMUtil.getNodeListFromPath(baseProfile,
2543: new String[] { "profile", "coplets-profile", "coplets",
2544: "coplet" });
2545:
2546: if (coplets != null) {
2547:
2548: l = coplets.getLength();
2549: for (i = 0; i < l; i++) {
2550: configElement = (Element) coplets.item(i);
2551: if (DOMUtil.getValueAsBooleanOf(configElement,
2552: "configuration/active", this .xpathProcessor)) {
2553:
2554: copletID = configElement.getAttributeNS(null, "id");
2555: if (configElement.hasAttributeNS(null, "media")) {
2556: copletMedia = configElement.getAttributeNS(
2557: null, "media");
2558: mediaMap = (Map) mediaCoplets.get(copletMedia);
2559: if (mediaMap != null) {
2560: mediaMap.put(copletID, configElement);
2561: }
2562: } else {
2563: copletMedia = null;
2564: defaultCoplets.put(copletID, configElement);
2565: }
2566:
2567: // Now: add the coplet if mandatory and missing
2568: if (DOMUtil.getValueAsBooleanOf(configElement,
2569: "configuration/mandatory",
2570: this .xpathProcessor)) {
2571: // get all coplet instances
2572: NodeList copletElements;
2573:
2574: // the next is crap, but it works....
2575: // search all coplets (columns, header, footer)
2576: if (copletMedia == null) {
2577: copletElements = DOMUtil.selectNodeList(
2578: baseProfile,
2579: "profile/portal-profile/content/column/coplets/coplet[@id='"
2580: + copletID
2581: + "' and not(@media)]",
2582: this .xpathProcessor);
2583: } else {
2584: copletElements = DOMUtil.selectNodeList(
2585: baseProfile,
2586: "profile/portal-profile/content/column/coplets/coplet[@id='"
2587: + copletID
2588: + "' and media='"
2589: + copletMedia + "']",
2590: this .xpathProcessor);
2591: }
2592:
2593: if (copletElements == null
2594: || copletElements.getLength() == 0) {
2595: if (copletMedia == null) {
2596: copletElements = DOMUtil
2597: .selectNodeList(
2598: baseProfile,
2599: "profile/portal-profile/content/header/coplet[@id='"
2600: + copletID
2601: + "' and not(@media)]",
2602: this .xpathProcessor);
2603: } else {
2604: copletElements = DOMUtil
2605: .selectNodeList(
2606: baseProfile,
2607: "profile/portal-profile/content/header/coplet[@id='"
2608: + copletID
2609: + "' and media='"
2610: + copletMedia
2611: + "']",
2612: this .xpathProcessor);
2613: }
2614: }
2615:
2616: if (copletElements == null
2617: || copletElements.getLength() == 0) {
2618: if (copletMedia == null) {
2619: copletElements = DOMUtil
2620: .selectNodeList(
2621: baseProfile,
2622: "profile/portal-profile/content/footer/coplet[@id='"
2623: + copletID
2624: + "' and not(@media)]",
2625: this .xpathProcessor);
2626: } else {
2627: copletElements = DOMUtil
2628: .selectNodeList(
2629: baseProfile,
2630: "profile/portal-profile/content/footer/coplet[@id='"
2631: + copletID
2632: + "' and media='"
2633: + copletMedia
2634: + "']",
2635: this .xpathProcessor);
2636: }
2637: }
2638:
2639: if (copletElements == null
2640: || copletElements.getLength() == 0) {
2641: // mandatory coplet is not configured, so add it to the first column
2642: Node content = DOMUtil
2643: .getSingleNode(
2644: baseProfile,
2645: "profile/portal-profile/content/column[@position='1']/coplets",
2646: this .xpathProcessor);
2647: if (content == null)
2648: throw new ProcessingException(
2649: "Element not found: portal-profile/content/column/coplets");
2650: Element el = content.getOwnerDocument()
2651: .createElementNS(null, "coplet");
2652: el.setAttributeNS(null, "id", copletID);
2653: if (copletMedia != null) {
2654: el.setAttributeNS(null, "media",
2655: copletMedia);
2656: }
2657: // Set position attribute
2658: NodeList childs = DOMUtil
2659: .getNodeListFromPath(content,
2660: new String[] { "coplet" });
2661: int childsCount = (childs == null ? 0
2662: : childs.getLength());
2663: el.setAttributeNS(null, "position", ""
2664: + (childsCount + 1));
2665: Text t;
2666: content.appendChild(el);
2667: content = el;
2668: el = content.getOwnerDocument()
2669: .createElementNS(null, "status");
2670: content.appendChild(el);
2671: content = el;
2672: el = content.getOwnerDocument()
2673: .createElementNS(null, "visible");
2674: content.appendChild(el);
2675: content = el;
2676: t = content.getOwnerDocument()
2677: .createTextNode("true");
2678: content.appendChild(t);
2679: } else {
2680: // is any of them visible?
2681: boolean found;
2682: boolean origVisible = DOMUtil
2683: .getValueAsBooleanOf(configElement,
2684: "status/visible",
2685: this .xpathProcessor);
2686: int si, sl;
2687: sl = copletElements.getLength();
2688: si = 0;
2689: found = false;
2690: while (si < sl && !found) {
2691: found = DOMUtil.getValueAsBooleanOf(
2692: copletElements.item(si),
2693: "status/visible", origVisible,
2694: this .xpathProcessor);
2695: si++;
2696: }
2697: if (!found) {
2698: // set first to visible
2699: // first: is status node available
2700: Node statusElem = DOMUtil
2701: .getFirstNodeFromPath(
2702: copletElements.item(0),
2703: new String[] { "status" },
2704: false);
2705: if (statusElem == null) {
2706: statusElem = copletElements.item(0)
2707: .getOwnerDocument()
2708: .createElementNS(null,
2709: "status");
2710: copletElements.item(0).appendChild(
2711: statusElem);
2712: }
2713: // second: is visible node available
2714: Node visibleElem = DOMUtil
2715: .getFirstNodeFromPath(
2716: statusElem,
2717: new String[] { "visible" },
2718: false);
2719: if (visibleElem == null) {
2720: visibleElem = statusElem
2721: .getOwnerDocument()
2722: .createElementNS(null,
2723: "visible");
2724: statusElem.appendChild(visibleElem);
2725: }
2726: // remove old childs
2727: while (visibleElem.hasChildNodes()) {
2728: visibleElem.removeChild(visibleElem
2729: .getFirstChild());
2730: }
2731: visibleElem.appendChild(statusElem
2732: .getOwnerDocument()
2733: .createTextNode("true"));
2734: }
2735: }
2736: }
2737: }
2738: }
2739: }
2740:
2741: // Numerate all coplets by adding an attribute number with a unique value
2742: // and put them into the corresponding maps.
2743: // update the status section of the coplet: Only the values of the coplet
2744: // configuration are allowed. Not less and not more!
2745: // All coplets are required to have
2746: // the number attribute! So this is only a compatibility function
2747: // which adds the first time the number to the coplets
2748: // If the number attribute is available, the node with the highest
2749: // number is searched
2750: NodeList copletElements;
2751: int number = 0;
2752: Element content = (Element) DOMUtil.getFirstNodeFromPath(
2753: baseProfile, new String[] { "profile",
2754: "portal-profile", "content" }, false);
2755: Element currentCoplet;
2756: NodeList statusConfigList;
2757: NodeList statusCopletList;
2758: Element statusCopletElement;
2759: int list_index, list_length;
2760: Node currentStatus;
2761: int highestCopletNumber = -1;
2762:
2763: for (i = 0; i < 7; i++) {
2764: if (i == 0) {
2765: copletElements = DOMUtil.getNodeListFromPath(content,
2766: new String[] { "header", "coplet" });
2767: } else if (i == 1) {
2768: copletElements = DOMUtil.getNodeListFromPath(content,
2769: new String[] { "footer", "coplet" });
2770: } else {
2771: copletElements = DOMUtil.selectNodeList(content,
2772: "column[@position='" + (i - 1)
2773: + "']/coplets/coplet",
2774: this .xpathProcessor);
2775: }
2776: if (copletElements != null
2777: && copletElements.getLength() > 0) {
2778: Element[] list = new Element[copletElements.getLength()];
2779: for (int index = 0; index < copletElements.getLength(); index++) {
2780: list[index] = (Element) copletElements.item(index);
2781: }
2782:
2783: for (int index = 0; index < list.length; index++) {
2784: // get coplet element
2785: currentCoplet = list[index];
2786:
2787: String numberValue = currentCoplet.getAttributeNS(
2788: null, "number");
2789: if (numberValue == null
2790: || numberValue.length() == 0) {
2791: // create unique number attribute
2792: currentCoplet.setAttributeNS(null, "number", ""
2793: + number);
2794: miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE] = currentCoplet;
2795: number++;
2796: } else {
2797: int currentNumber = new Integer(numberValue)
2798: .intValue();
2799: if (currentNumber > highestCopletNumber) {
2800: highestCopletNumber = currentNumber;
2801: number = highestCopletNumber + 1;
2802: miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE] = currentCoplet;
2803: }
2804: }
2805: // update status
2806: configElement = this .getCopletConfiguration(
2807: currentCoplet.getAttributeNS(null, "id"),
2808: defaultCoplets, mediaCoplets);
2809: if (configElement != null) {
2810: statusCopletElement = (Element) DOMUtil
2811: .selectSingleNode(configElement,
2812: "status", this .xpathProcessor);
2813: statusConfigList = DOMUtil.selectNodeList(
2814: statusCopletElement, "*",
2815: this .xpathProcessor);
2816: statusCopletList = DOMUtil.selectNodeList(
2817: currentCoplet, "status/*",
2818: this .xpathProcessor);
2819: // first test if each status is included in the config
2820: if (statusCopletList != null) {
2821: list_length = statusCopletList.getLength();
2822: for (list_index = list_length - 1; list_index >= 0; list_index--) {
2823: currentStatus = statusCopletList
2824: .item(list_index);
2825: if (currentStatus.getNodeType() == Node.ELEMENT_NODE) {
2826: if (DOMUtil
2827: .getFirstNodeFromPath(
2828: configElement,
2829: new String[] {
2830: "status",
2831: currentStatus
2832: .getNodeName() },
2833: false) == null) {
2834: currentStatus.getParentNode()
2835: .removeChild(
2836: currentStatus);
2837: }
2838: }
2839: }
2840: }
2841: // second, test if each status attribute of the config is included
2842: if (statusConfigList != null) {
2843: list_length = statusConfigList.getLength();
2844: for (list_index = 0; list_index < list_length; list_index++) {
2845: currentStatus = statusConfigList
2846: .item(list_index);
2847: if (currentStatus.getNodeType() == Node.ELEMENT_NODE) {
2848: if (DOMUtil
2849: .getFirstNodeFromPath(
2850: statusCopletElement,
2851: new String[] { currentStatus
2852: .getNodeName() },
2853: false) == null) {
2854: // create a new element
2855: statusCopletElement
2856: .appendChild(statusCopletElement
2857: .getOwnerDocument()
2858: .importNode(
2859: currentStatus,
2860: true));
2861: }
2862: }
2863: }
2864: }
2865: } else {
2866: // coplet not in configuration
2867: // adopt position of following coplets and then remove
2868: String posAttr = currentCoplet.getAttributeNS(
2869: null, "position");
2870: NodeList followUps = DOMUtil
2871: .selectNodeList(currentCoplet
2872: .getParentNode(),
2873: "coplet[@position > '"
2874: + posAttr + "']",
2875: this .xpathProcessor);
2876: if (followUps != null) {
2877: int value;
2878: for (int iq = 0; iq < followUps.getLength(); iq++) {
2879: value = new Integer(
2880: ((Element) followUps.item(iq))
2881: .getAttributeNS(null,
2882: "position"))
2883: .intValue();
2884: value -= 1;
2885: ((Element) followUps.item(iq))
2886: .setAttributeNS(null,
2887: "position", "" + value);
2888: }
2889: }
2890: currentCoplet.getParentNode().removeChild(
2891: currentCoplet);
2892: }
2893: }
2894: }
2895: }
2896:
2897: if (this .getLogger().isDebugEnabled()) {
2898: this .getLogger().debug("END buildRunProfile");
2899: }
2900: }
2901:
2902: /**
2903: * Add the type information to the profile and do some type checkings
2904: */
2905: private void buildTypeProfile(Map theProfile,
2906: SessionContext context, DocumentFragment baseProfile)
2907: throws javax.xml.transform.TransformerException {
2908: // calling method is synced
2909: if (this .getLogger().isDebugEnabled()) {
2910: this .getLogger().debug(
2911: "BEGIN buildTypeProfile context=" + context
2912: + ", profile=" + baseProfile);
2913: }
2914: List list = new ArrayList(25);
2915: List confList = new ArrayList(25);
2916:
2917: theProfile.put(PortalConstants.PROFILE_TYPE_PATHS, list);
2918: theProfile.put(PortalConstants.PROFILE_TYPE_CONF_PATHS,
2919: confList);
2920:
2921: Element typeElement;
2922:
2923: typeElement = (Element) DOMUtil.getFirstNodeFromPath(
2924: baseProfile, new String[] { "profile", "type-profile",
2925: "elements" }, false);
2926: if (typeElement != null) {
2927: if (typeElement.hasChildNodes())
2928: this .addTypePath(list, typeElement.getChildNodes(),
2929: "profile");
2930:
2931: // now we have the list with the xpaths
2932: this .setTypeInfo(baseProfile, list, null);
2933:
2934: // build the conf paths
2935: int i, l, pos;
2936: String current;
2937:
2938: l = list.size();
2939: for (i = 0; i < l; i++) {
2940: current = (String) list.get(i);
2941:
2942: // now the path has to be changed: the new attributes must be included
2943: pos = current.lastIndexOf('/');
2944: current = current.substring(0, pos);
2945:
2946: pos = current.lastIndexOf('[');
2947: if (current.substring(pos + 1).equals("not(@*)]")) {
2948: current = current.substring(0, pos + 1);
2949: } else {
2950: current = current
2951: .substring(0, current.length() - 1)
2952: + " and ";
2953: }
2954: current += "@formtype and @formpath and @formdescription]";
2955: confList.add(current);
2956: }
2957:
2958: }
2959:
2960: // and now the type checking part:
2961: //
2962: // If the default layout has changed the number of columns and the current
2963: // user (or role) is not allowed to change this, we have to adjust the
2964: // profile. Otherwise the current number of columns has to be stored
2965: // into the profile layout part.
2966: Element layoutColumnsNode = (Element) DOMUtil
2967: .getFirstNodeFromPath(baseProfile, new String[] {
2968: "profile", "layout-profile", "portal",
2969: "columns", "number" }, false);
2970: String layoutValue = DOMUtil.getValueOfNode(layoutColumnsNode);
2971: int layoutColumns = 0;
2972: if (layoutValue != null
2973: && new Integer(layoutValue).intValue() > 0) {
2974: layoutColumns = new Integer(layoutValue).intValue();
2975: }
2976: NodeList columnNodes = DOMUtil.selectNodeList(baseProfile,
2977: "profile/portal-profile/content/column[@position]",
2978: this .xpathProcessor);
2979: int columns = columnNodes.getLength();
2980: if (columns != layoutColumns) {
2981: if (layoutColumnsNode.hasAttributeNS(null, "formtype")) {
2982: DOMUtil.setValueOfNode(layoutColumnsNode, "" + columns);
2983: } else {
2984: this
2985: .changeColumns(
2986: baseProfile,
2987: columns,
2988: layoutColumns,
2989: (Node[]) theProfile
2990: .get(PortalConstants.PROFILE_MISC_POINTER));
2991: this
2992: .setTypeInfo(
2993: baseProfile,
2994: (List) theProfile
2995: .get(PortalConstants.PROFILE_TYPE_PATHS),
2996: (List) theProfile
2997: .get(PortalConstants.PROFILE_TYPE_CONF_PATHS));
2998: }
2999: }
3000:
3001: if (this .getLogger().isDebugEnabled()) {
3002: this .getLogger().debug("END buildTypeProfile");
3003: }
3004: }
3005:
3006: /**
3007: * Set the tpe information
3008: */
3009: private void setTypeInfo(DocumentFragment baseProfile, List paths,
3010: List confPaths)
3011: throws javax.xml.transform.TransformerException {
3012: // calling method is synced
3013: if (this .getLogger().isDebugEnabled()) {
3014: this .getLogger().debug(
3015: "BEGIN setTypeInfo profile=" + baseProfile
3016: + ", paths=" + paths);
3017: }
3018: if (baseProfile != null && paths != null) {
3019: int pos;
3020: String currentPath;
3021: String value;
3022: String description;
3023: NodeList nodes;
3024: int nodes_count;
3025: int path_count = paths.size();
3026: Node currentNode;
3027:
3028: for (int i = 0; i < path_count; i++) {
3029: currentPath = (String) paths.get(i);
3030: pos = currentPath.lastIndexOf('/');
3031: value = currentPath.substring(pos + 1);
3032: currentPath = currentPath.substring(0, pos);
3033: pos = value.indexOf("|");
3034: if (pos != -1) {
3035: description = value.substring(pos + 1);
3036: value = value.substring(0, pos);
3037: } else {
3038: description = "UNKNOWN";
3039: }
3040:
3041: // get all nodes
3042: boolean changed = false;
3043: nodes = DOMUtil.selectNodeList(baseProfile,
3044: currentPath, this .xpathProcessor);
3045: if (nodes != null) {
3046: nodes_count = nodes.getLength();
3047: for (int m = 0; m < nodes_count; m++) {
3048: currentNode = nodes.item(m);
3049: if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
3050: ((Element) currentNode).setAttributeNS(
3051: null, "formtype", value);
3052: ((Element) currentNode)
3053: .setAttributeNS(
3054: null,
3055: "formpath",
3056: PortalManagerImpl.REQ_PARAMETER_CONF
3057: + '.' + i + '.' + m);
3058: ((Element) currentNode).setAttributeNS(
3059: null, "formdescription",
3060: description);
3061: changed = true;
3062: }
3063: }
3064: }
3065: if (changed && confPaths != null) {
3066: currentPath = (String) confPaths.get(i);
3067: nodes = DOMUtil.selectNodeList(baseProfile,
3068: currentPath, this .xpathProcessor);
3069: if (nodes != null) {
3070: nodes_count = nodes.getLength();
3071: for (int m = 0; m < nodes_count; m++) {
3072: currentNode = nodes.item(m);
3073: if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
3074: ((Element) currentNode)
3075: .setAttributeNS(
3076: null,
3077: "formpath",
3078: PortalManagerImpl.REQ_PARAMETER_CONF
3079: + '.'
3080: + i
3081: + '.'
3082: + m);
3083: }
3084: }
3085: }
3086: }
3087: }
3088: }
3089:
3090: if (this .getLogger().isDebugEnabled()) {
3091: this .getLogger().debug("END setTypeInfo");
3092: }
3093: }
3094:
3095: /**
3096: * Add the type info to the xpath. This is done recursevly
3097: */
3098: private void addTypePath(List list, NodeList childs, String path) {
3099: // calling method is synced
3100: int i, l;
3101: Element current;
3102: StringBuffer newPath;
3103:
3104: l = childs.getLength();
3105: for (i = 0; i < l; i++) {
3106: if (childs.item(i).getNodeType() == Node.ELEMENT_NODE) {
3107: current = (Element) childs.item(i);
3108: newPath = new StringBuffer(path);
3109: newPath.append('/').append(current.getNodeName());
3110: if (current.hasAttributes()) {
3111: NamedNodeMap nnm = current.getAttributes();
3112: int ia, la;
3113: boolean first = true;
3114: StringBuffer expression = new StringBuffer();
3115: la = nnm.getLength();
3116: newPath.append('[');
3117: for (ia = 0; ia < la; ia++) {
3118: if (!nnm.item(ia).getNodeName().equals("type")
3119: && !nnm.item(ia).getNodeName().equals(
3120: "description")) {
3121: if (!first)
3122: expression.append(" and ");
3123: if (!nnm.item(ia).getNodeValue()
3124: .equals("*")) {
3125: expression
3126: .append('@')
3127: .append(
3128: nnm.item(ia)
3129: .getNodeName())
3130: .append("='")
3131: .append(
3132: nnm.item(ia)
3133: .getNodeValue())
3134: .append("'");
3135: } else {
3136: expression.append('@').append(
3137: nnm.item(ia).getNodeName());
3138: }
3139: first = false;
3140: }
3141: }
3142: if (first) {
3143: newPath.append("not(@*)");
3144: } else {
3145: newPath.append(expression);
3146: }
3147: newPath.append(']');
3148: } else {
3149: newPath.append("[not(@*)]");
3150: }
3151: if (current.getAttributeNS(null, "type").length() > 0) {
3152: list.add(newPath.toString()
3153: + '/'
3154: + current.getAttributeNS(null, "type")
3155: + '|'
3156: + current.getAttributeNS(null,
3157: "description"));
3158: } else {
3159: if (current.hasChildNodes()) {
3160: this .addTypePath(list, current.getChildNodes(),
3161: newPath.toString());
3162: }
3163: }
3164: }
3165: }
3166: }
3167:
3168: /**
3169: * Build the Map with the portal layouts
3170: */
3171: private Map buildPortalLayouts(SessionContext context,
3172: DocumentFragment baseProfile) throws ProcessingException,
3173: javax.xml.transform.TransformerException {
3174: // calling method is synced
3175: if (this .getLogger().isDebugEnabled()) {
3176: this .getLogger().debug(
3177: "BEGIN buildPortalLayouts context=" + context
3178: + ", profile=" + baseProfile);
3179: }
3180: Map layouts = new HashMap(5, 2);
3181: Element defLayout = (Element) DOMUtil
3182: .getSingleNode(
3183: baseProfile,
3184: "profile/layout-profile/portal/layouts/layout[not(@*)]",
3185: this .xpathProcessor);
3186: Node currentLayout;
3187: String[] types = this .getMediaManager().getMediaTypes();
3188:
3189: for (int i = 0; i < types.length; i++) {
3190: currentLayout = DOMUtil.getSingleNode(baseProfile,
3191: "profile/layout-profile/portal/layouts/layout[media='"
3192: + types[i] + "']", this .xpathProcessor);
3193: layouts.put(types[i], (currentLayout == null ? defLayout
3194: : currentLayout));
3195: }
3196:
3197: if (this .getLogger().isDebugEnabled()) {
3198: this .getLogger().debug(
3199: "END buildPortalLayouts layouts=" + layouts);
3200: }
3201: return layouts;
3202: }
3203:
3204: /**
3205: * Build the Map with the coplet layouts
3206: */
3207: private Map buildcopleyLayouts(SessionContext context,
3208: DocumentFragment baseProfile) throws ProcessingException,
3209: javax.xml.transform.TransformerException {
3210: // calling method is synced
3211: if (this .getLogger().isDebugEnabled()) {
3212: this .getLogger().debug(
3213: "BEGIN buildcopleyLayouts context=" + context
3214: + ", profile=" + baseProfile);
3215: }
3216: Map layouts = new HashMap(5, 2);
3217: Element defLayout = (Element) DOMUtil
3218: .getSingleNode(
3219: baseProfile,
3220: "profile/layout-profile/coplets/layouts/layout[not(@*)]",
3221: this .xpathProcessor);
3222: Node currentLayout;
3223: String[] types = this .getMediaManager().getMediaTypes();
3224:
3225: for (int i = 0; i < types.length; i++) {
3226: currentLayout = DOMUtil.getSingleNode(baseProfile,
3227: "profile/layout-profile/coplets/layouts/layout[media='"
3228: + types[i] + "']", this .xpathProcessor);
3229: layouts.put(types[i], (currentLayout == null ? defLayout
3230: : currentLayout));
3231: }
3232:
3233: if (this .getLogger().isDebugEnabled()) {
3234: this .getLogger().debug(
3235: "END buildcopleyLayouts layouts=" + layouts);
3236: }
3237: return layouts;
3238: }
3239:
3240: /**
3241: * Import a delta into the profile
3242: */
3243: private void importProfileDelta(Element profileRoot,
3244: DocumentFragment delta, String deltaRootTagName,
3245: String deltaTag) throws ProcessingException {
3246: // calling method is synced
3247: if (this .getLogger().isDebugEnabled()) {
3248: this .getLogger()
3249: .debug(
3250: "BEGIN importProfileDelta root="
3251: + profileRoot + ", delta=" + delta
3252: + ", deltaRoot:" + deltaRootTagName
3253: + ", delta: " + deltaTag);
3254: }
3255: Node deltaRoot = null;
3256:
3257: deltaRoot = DOMUtil.getFirstNodeFromPath(delta, new String[] {
3258: deltaRootTagName, deltaTag }, false);
3259:
3260: if (deltaRoot != null) {
3261: // root tag found in delta , now search root tag in profile
3262: String searchName = deltaRoot.getNodeName().substring(0,
3263: deltaRoot.getNodeName().lastIndexOf("-delta"));
3264: searchName = searchName + "-profile";
3265:
3266: profileRoot = (Element) DOMUtil.getFirstNodeFromPath(
3267: profileRoot, new String[] { searchName }, false);
3268: if (profileRoot == null) {
3269: throw new ProcessingException("Importing Delta: Tag "
3270: + searchName + " not found in profile.");
3271: }
3272:
3273: // now import it
3274: this .importNode(profileRoot, (Element) deltaRoot);
3275: }
3276:
3277: if (this .getLogger().isDebugEnabled()) {
3278: this .getLogger().debug("END importProfileDelta");
3279: }
3280: }
3281:
3282: /**
3283: * Add the node to the profile (replace an existing one)
3284: */
3285: private void addProfilePart(Element profileRoot,
3286: DocumentFragment delta, String deltaRootTagName,
3287: String deltaTag) {
3288: // calling method is synced
3289: if (this .getLogger().isDebugEnabled()) {
3290: this .getLogger()
3291: .debug(
3292: "BEGIN addProfilePart root=" + profileRoot
3293: + ", delta=" + delta
3294: + ", deltaRoot:" + deltaRootTagName
3295: + ", delta: " + deltaTag);
3296: }
3297: Node deltaRoot = null;
3298: Node oldNode = null;
3299:
3300: if (deltaRootTagName != null) {
3301: deltaRoot = DOMUtil.getFirstNodeFromPath(delta,
3302: new String[] { deltaRootTagName, deltaTag }, false);
3303: } else {
3304: deltaRoot = DOMUtil.getFirstNodeFromPath(delta,
3305: new String[] { deltaTag }, false);
3306: }
3307:
3308: if (deltaRoot != null) {
3309: // root tag found in delta found, now search root tag in profile
3310: oldNode = DOMUtil.getFirstNodeFromPath(profileRoot,
3311: new String[] { deltaTag }, false);
3312: if (oldNode == null) {
3313: profileRoot.appendChild(profileRoot.getOwnerDocument()
3314: .importNode(deltaRoot, true));
3315: } else {
3316: profileRoot.replaceChild(profileRoot.getOwnerDocument()
3317: .importNode(deltaRoot, true), oldNode);
3318: }
3319: }
3320:
3321: if (this .getLogger().isDebugEnabled()) {
3322: this .getLogger().debug("END addProfilePart");
3323: }
3324: }
3325:
3326: /**
3327: * This is the hardest part. Incorporting a node into the profile.
3328: * For performance reasons there is now tracing here.
3329: */
3330: private void importNode(Element profile, Element delta) {
3331: // calling method is synced
3332: NodeList profileChilds = null;
3333: NodeList deltaChilds = delta.getChildNodes();
3334: int i, len;
3335: int m, l;
3336: boolean found;
3337: Node currentDelta = null;
3338: Node currentProfile = null;
3339:
3340: len = deltaChilds.getLength();
3341: for (i = 0; i < len; i++) {
3342: currentDelta = deltaChilds.item(i);
3343: if (currentDelta.getNodeType() == Node.ELEMENT_NODE) {
3344: // search the delta node in the profile
3345: profileChilds = profile.getChildNodes();
3346: l = profileChilds.getLength();
3347: m = 0;
3348: found = false;
3349: while (!found && m < l) {
3350: currentProfile = profileChilds.item(m);
3351: if (currentProfile.getNodeType() == Node.ELEMENT_NODE
3352: && currentProfile.getNodeName().equals(
3353: currentDelta.getNodeName())) {
3354:
3355: // now we have found a node with the same name
3356: // next: the attributes must match also
3357: found = this .compareAttributes(currentProfile,
3358: currentDelta);
3359: }
3360: if (!found)
3361: m++;
3362: }
3363: if (found) {
3364: // this is not new
3365:
3366: // do we have elements as children or text?
3367: if (currentDelta.hasChildNodes()) {
3368: currentDelta.normalize();
3369: currentProfile.normalize();
3370: // do a recursive call for sub elements
3371: this .importNode((Element) currentProfile,
3372: (Element) currentDelta);
3373: // and now the text nodes: Remove all from the profile and add all
3374: // of the delta
3375: NodeList childs = currentProfile
3376: .getChildNodes();
3377: int index, max;
3378: max = childs.getLength();
3379: for (index = max - 1; index >= 0; index--) {
3380: if (childs.item(index).getNodeType() == Node.TEXT_NODE) {
3381: currentProfile.removeChild(childs
3382: .item(index));
3383: }
3384: }
3385: childs = currentDelta.getChildNodes();
3386: max = childs.getLength();
3387: for (index = 0; index < max; index++) {
3388: if (childs.item(index).getNodeType() == Node.TEXT_NODE) {
3389: currentProfile
3390: .appendChild(currentProfile
3391: .getOwnerDocument()
3392: .createTextNode(
3393: childs
3394: .item(
3395: index)
3396: .getNodeValue()));
3397: }
3398: }
3399: }
3400: } else {
3401: // this is a new node, so it is considered as an old information
3402: // No inserting: profile.appendChild(profile.getOwnerDocument().importNode(currentDelta, true));
3403: }
3404: }
3405:
3406: }
3407:
3408: }
3409:
3410: /**
3411: * Compare Attributes of two nodes. This method returns true only if both
3412: * nodes have the same number of attributes and the same attributes with equal
3413: * values.
3414: * Namespacedefinition nodes are ignored
3415: * BUT: For type handling the attributes <code>formtype</code>,
3416: * <code>formdescription</code> and <code>formpath</code> are ignored!
3417: */
3418: private boolean compareAttributes(Node first, Node second) {
3419: // calling method is synced
3420: NamedNodeMap attr1 = first.getAttributes();
3421: NamedNodeMap attr2 = second.getAttributes();
3422: String value;
3423:
3424: if (attr1 == null && attr2 == null)
3425: return true;
3426: if (attr1 == null || attr2 == null)
3427: return false;
3428: int attr1Len = (attr1 == null ? 0 : attr1.getLength());
3429: int attr2Len = (attr2 == null ? 0 : attr2.getLength());
3430: if (attr1Len > 0) {
3431: if (attr1.getNamedItemNS(null, "formtype") != null)
3432: attr1Len--;
3433: if (attr1.getNamedItemNS(null, "formpath") != null)
3434: attr1Len--;
3435: if (attr1.getNamedItemNS(null, "formdescription") != null)
3436: attr1Len--;
3437: int l = attr1.getLength();
3438: for (int i = 0; i < l; i++) {
3439: if (attr1.item(i).getNodeName().startsWith("xmlns:"))
3440: attr1Len--;
3441: }
3442: }
3443: if (attr2Len > 0) {
3444: if (attr2.getNamedItemNS(null, "formtype") != null)
3445: attr2Len--;
3446: if (attr2.getNamedItemNS(null, "formpath") != null)
3447: attr2Len--;
3448: if (attr2.getNamedItemNS(null, "formdescription") != null)
3449: attr2Len--;
3450: int l = attr2.getLength();
3451: for (int i = 0; i < l; i++) {
3452: if (attr2.item(i).getNodeName().startsWith("xmlns:"))
3453: attr2Len--;
3454: }
3455: }
3456: if (attr1Len != attr2Len)
3457: return false;
3458: int i, l;
3459: int m, l2;
3460: i = 0;
3461: l = attr1.getLength();
3462: l2 = attr2.getLength();
3463: boolean ok = true;
3464: // each attribute of first must be in second with the same value
3465: while (i < l && ok) {
3466: value = attr1.item(i).getNodeName();
3467: if (!value.equals("formtype") && !value.equals("formpath")
3468: && !value.equals("formdescription")
3469: && !value.startsWith("xmlns:")) {
3470: ok = false;
3471: m = 0;
3472: while (m < l2 && !ok) {
3473: if (attr2.item(m).getNodeName().equals(value)) {
3474: // same name, same value?
3475: ok = attr1.item(i).getNodeValue().equals(
3476: attr2.item(m).getNodeValue());
3477: }
3478: m++;
3479: }
3480:
3481: }
3482: i++;
3483: }
3484: return ok;
3485: }
3486:
3487: /**
3488: * Parse the fragment(tree denoted by the element)
3489: * and include the processed xml in the output
3490: */
3491: private void processCopletList(List copletList,
3492: XMLConsumer consumer, String copletNotAvailableMessage,
3493: long defaultCopletTimeout) throws ProcessingException,
3494: SAXException, javax.xml.transform.TransformerException {
3495: // calling method is synced
3496: for (int i = 0; i < copletList.size(); i++) {
3497: this .processCoplet((Object[]) copletList.get(i), consumer,
3498: copletNotAvailableMessage, defaultCopletTimeout);
3499: }
3500: }
3501:
3502: /**
3503: * Parse the fragment(tree denoted by the element)
3504: * and include the processed xml in the output
3505: */
3506: private void loadCoplets(Element element, Map defaultCoplets,
3507: Map mediaCoplets, List copletList, boolean parallelCoplets,
3508: long defaultCopletTimeout, Element statusProfile)
3509: throws ProcessingException,
3510: javax.xml.transform.TransformerException {
3511: // calling method is synced
3512: // All children, which are coplets are processed, all other tags
3513: // are ignored
3514: if (element.hasChildNodes()) {
3515: NodeList childs = element.getChildNodes();
3516: Node current = null;
3517: int i, l;
3518: l = childs.getLength();
3519: for (i = 0; i < l; i++) {
3520: current = childs.item(i);
3521: if (current.getNodeType() == Node.ELEMENT_NODE
3522: && current.getNodeName().equals("coplet")) {
3523:
3524: // now we have a coplet
3525: this .loadCoplet((Element) current, defaultCoplets,
3526: mediaCoplets, copletList, parallelCoplets,
3527: defaultCopletTimeout, statusProfile);
3528: }
3529: }
3530: }
3531: }
3532:
3533: /**
3534: * Load a coplet and store the binary output in the list
3535: */
3536: private void loadCoplet(Element element, Map defaultCoplets,
3537: Map mediaCoplets, List copletList, boolean parallelCoplets,
3538: long defaultCopletTimeout, Element statusProfile)
3539: throws ProcessingException,
3540: javax.xml.transform.TransformerException {
3541: // calling method is synced
3542: String copletID = element.getAttributeNS(null, "id");
3543:
3544: Element copletConf = this .getCopletConfiguration(copletID,
3545: defaultCoplets, mediaCoplets);
3546: if (copletConf != null) {
3547:
3548: // first: check visibility
3549: boolean visible = DOMUtil.getValueAsBooleanOf(element,
3550: "status/visible", this .xpathProcessor);
3551: // second: check media
3552: String media = this .getMediaManager().getMediaType();
3553: if (visible && copletConf.hasAttributeNS(null, "media")) {
3554: String copletMedia = copletConf.getAttributeNS(null,
3555: "media");
3556: visible = media.equals(copletMedia);
3557: }
3558:
3559: if (visible) {
3560:
3561: Object[] loadedCoplet = new Object[8];
3562: copletList.add(loadedCoplet);
3563:
3564: boolean isCustomizable = DOMUtil.getValueAsBooleanOf(
3565: copletConf, "configuration/customizable",
3566: false, this .xpathProcessor);
3567: if (isCustomizable) {
3568: boolean showCustomizePage = DOMUtil
3569: .getValueAsBooleanOf(element,
3570: "status/customize", false,
3571: this .xpathProcessor);
3572: boolean hasConfig = false;
3573: if (statusProfile != null) {
3574: Element customInfo = (Element) DOMUtil
3575: .getSingleNode(
3576: statusProfile,
3577: "customization/coplet[@id='"
3578: + copletID
3579: + "' and @number='"
3580: + element
3581: .getAttributeNS(
3582: null,
3583: "number")
3584: + "']",
3585: this .xpathProcessor);
3586: hasConfig = (customInfo != null);
3587: }
3588: if (showCustomizePage || !hasConfig) {
3589: Node node = DOMUtil
3590: .selectSingleNode(element,
3591: "status/customize",
3592: this .xpathProcessor);
3593: DOMUtil.setValueOfNode(node, "true");
3594: } else {
3595: Node node = DOMUtil
3596: .selectSingleNode(element,
3597: "status/customize",
3598: this .xpathProcessor);
3599: DOMUtil.setValueOfNode(node, "false");
3600: }
3601: } else {
3602: Node node = DOMUtil.selectSingleNode(element,
3603: "status/customize", this .xpathProcessor);
3604: DOMUtil.setValueOfNode(node, "false");
3605: }
3606:
3607: // Create the parameters for the coplet:
3608: // The <status> part is mapped to parameters
3609: // id, number and media are added
3610: SourceParameters p = DOMUtil
3611: .createParameters(DOMUtil.getFirstNodeFromPath(
3612: element, new String[] { "status" },
3613: false), null);
3614: p.setSingleParameterValue(PortalConstants.PARAMETER_ID,
3615: copletID);
3616: p.setSingleParameterValue(
3617: PortalConstants.PARAMETER_NUMBER, element
3618: .getAttributeNS(null, "number"));
3619: p.setSingleParameterValue(
3620: PortalConstants.PARAMETER_MEDIA, media);
3621: String isPersistent = DOMUtil.getValueOf(copletConf,
3622: "configuration/persistent", "false",
3623: this .xpathProcessor);
3624: p.setSingleParameterValue(
3625: PortalConstants.PARAMETER_PERSISTENT,
3626: isPersistent);
3627:
3628: // the coplet loading is a tricky part:
3629: // we create an object array containing all information
3630: // for later processing of the coplet
3631: // so the processCoplet() method needs no lookup for information
3632: // again
3633: loadedCoplet[0] = null;
3634: loadedCoplet[1] = copletConf;
3635: loadedCoplet[2] = p;
3636: loadedCoplet[3] = element;
3637: loadedCoplet[4] = new Long(System.currentTimeMillis());
3638: loadedCoplet[5] = new Long(DOMUtil.getValueOf(
3639: copletConf, "configuration/timeout", "-1",
3640: this .xpathProcessor));
3641: loadedCoplet[7] = statusProfile;
3642:
3643: CopletThread copletThread = new CopletThread();
3644: Thread theThread = new Thread(new CocoonRunnable(
3645: copletThread));
3646: loadedCoplet[6] = copletThread;
3647: copletThread.init(copletID, ContextHelper
3648: .getObjectModel(this .componentContext), this
3649: .getLogger(), loadedCoplet, this .manager,
3650: this .resolver, this .xpathProcessor);
3651: theThread.start();
3652: Thread.yield();
3653:
3654: if (!parallelCoplets) {
3655: copletThread = (CopletThread) loadedCoplet[6];
3656: if (copletThread != null) {
3657: long startTime = System.currentTimeMillis()
3658: - ((Long) loadedCoplet[4]).longValue();
3659: long timeout = ((Long) loadedCoplet[5])
3660: .longValue();
3661: long waitTime;
3662: if (timeout == -1) {
3663: waitTime = defaultCopletTimeout;
3664: } else {
3665: waitTime = timeout - startTime;
3666: }
3667:
3668: while (copletThread != null && waitTime > 2) {
3669: try {
3670: Thread.sleep(15);
3671: waitTime -= 15;
3672: } catch (InterruptedException local) {
3673: // ignore
3674: }
3675: copletThread = (CopletThread) loadedCoplet[6];
3676: }
3677: loadedCoplet[6] = null; // mark as loaded
3678: }
3679: }
3680:
3681: }
3682:
3683: }
3684: }
3685:
3686: /**
3687: * Process a coplet which is previously loaded
3688: */
3689: private void processCoplet(Object[] loadedCoplet,
3690: XMLConsumer consumer, String notAvailableMessage,
3691: long defaultCopletTimeout) throws ProcessingException,
3692: SAXException, javax.xml.transform.TransformerException {
3693: // calling method is synced
3694:
3695: Element copletConf = (Element) loadedCoplet[1];
3696: Element element = (Element) loadedCoplet[3];
3697:
3698: String copletID = element.getAttributeNS(null, "id");
3699: if (copletConf != null) {
3700: AttributesImpl attr = new AttributesImpl();
3701: attr.addAttribute("", "id", "id", "CDATA", copletID);
3702: attr.addAttribute("", "number", "number", "CDATA", element
3703: .getAttributeNS(null, "number"));
3704: attr.addAttribute("", "position", "position", "CDATA",
3705: element.getAttributeNS(null, "position"));
3706: consumer.startElement("", "coplet", "coplet", attr);
3707: attr.clear();
3708:
3709: // now include all children of the coplet element except status
3710: NodeList children = copletConf.getChildNodes();
3711: if (children != null && children.getLength() > 0) {
3712: int l = children.getLength();
3713: for (int i = 0; i < l; i++) {
3714: if (!children.item(i).getNodeName()
3715: .equals("status")
3716: && children.item(i).getNodeType() == Node.ELEMENT_NODE) {
3717: IncludeXMLConsumer.includeNode(
3718: children.item(i), consumer, consumer);
3719: }
3720: }
3721: }
3722:
3723: // now the status parameter
3724: // SourceParameters p = DOMUtil.createParameters(DOMUtil.getFirstNodeFromPath(element, new String[] {"status"}, false), null);
3725: consumer.startElement("", "status", "status", attr);
3726: children = DOMUtil.selectNodeList(element, "status/*",
3727: this .xpathProcessor);
3728: if (children != null && children.getLength() > 0) {
3729: int l = children.getLength();
3730: for (int i = 0; i < l; i++) {
3731: if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
3732: IncludeXMLConsumer.includeNode(
3733: children.item(i), consumer, consumer);
3734: }
3735: }
3736: }
3737: consumer.endElement("", "status", "status");
3738:
3739: // now the content:
3740: consumer.startElement("", "content", "content", attr);
3741:
3742: CopletThread thread = (CopletThread) loadedCoplet[6];
3743: if (thread != null) {
3744: long startTime = System.currentTimeMillis()
3745: - ((Long) loadedCoplet[4]).longValue();
3746: long timeout = ((Long) loadedCoplet[5]).longValue();
3747: long waitTime;
3748: if (timeout == -1) {
3749: waitTime = defaultCopletTimeout;
3750: } else {
3751: waitTime = timeout - startTime;
3752: }
3753:
3754: while (thread != null && waitTime > 2) {
3755: try {
3756: Thread.sleep(15);
3757: waitTime -= 15;
3758: } catch (InterruptedException local) {
3759: // ignore
3760: }
3761: thread = (CopletThread) loadedCoplet[6];
3762: }
3763: }
3764: byte[] content = (byte[]) loadedCoplet[0];
3765: if (content != null) {
3766: if (content.length > 0) {
3767: XMLDeserializer interpreter = null;
3768: try {
3769: interpreter = (XMLDeserializer) this .manager
3770: .lookup(XMLDeserializer.ROLE);
3771: interpreter.setConsumer(new IncludeXMLConsumer(
3772: consumer, consumer));
3773: interpreter.deserialize(content);
3774: } catch (ComponentException e) {
3775: throw new ProcessingException(
3776: "Component for XMLDeserializer not found."
3777: + e, e);
3778: } finally {
3779: if (interpreter != null)
3780: this .manager.release(interpreter);
3781: }
3782: }
3783: } else {
3784: notAvailableMessage = DOMUtil.getValueOf(copletConf,
3785: "configuration/messages/coplet_not_available",
3786: notAvailableMessage, this .xpathProcessor);
3787: consumer.characters(notAvailableMessage.toCharArray(),
3788: 0, notAvailableMessage.length());
3789: }
3790: consumer.endElement("", "content", "content");
3791: consumer.endElement("", "coplet", "coplet");
3792:
3793: }
3794: }
3795:
3796: /* (non-Javadoc)
3797: * @see org.apache.cocoon.webapps.portal.components.PortalManager#getMediaType()
3798: */
3799: public String getMediaType() throws ProcessingException {
3800: this .setup();
3801: return this .getMediaManager().getMediaType();
3802: }
3803:
3804: /**
3805: * Get the coplet with the id
3806: */
3807: private Element getCopletConfiguration(String copletID,
3808: Map defaultCoplets, Map mediaCoplets)
3809: throws ProcessingException {
3810: // calling method is synced
3811: String media = this .getMediaManager().getMediaType();
3812: Map coplets = (Map) mediaCoplets.get(media);
3813: Element coplet = null;
3814: if (coplets != null)
3815: coplet = (Element) coplets.get(copletID);
3816: if (coplet == null)
3817: coplet = (Element) defaultCoplets.get(copletID);
3818: return coplet;
3819: }
3820:
3821: /**
3822: * Get the coplet Element
3823: */
3824: private Element getCopletElement(String copletID, String copletNr,
3825: Node[] miscNodes)
3826: throws javax.xml.transform.TransformerException {
3827: // calling method is synced
3828: Element node = null;
3829:
3830: // first test content, then header and then footer
3831: int colindex = 8;
3832: while (node == null && colindex < 13) {
3833: if (miscNodes[colindex] != null) {
3834: node = (Element) DOMUtil.getSingleNode(
3835: miscNodes[colindex], "coplets/coplet[@id='"
3836: + copletID + "' and @number='"
3837: + copletNr + "']", this .xpathProcessor);
3838: colindex++;
3839: } else {
3840: colindex = 13;
3841: }
3842: }
3843: if (node == null
3844: && miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE] != null) {
3845: node = (Element) DOMUtil
3846: .getSingleNode(
3847: miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE],
3848: "coplet[@id='" + copletID
3849: + "' and @number='" + copletNr
3850: + "']", this .xpathProcessor);
3851: }
3852: if (node == null
3853: && miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE] != null) {
3854: node = (Element) DOMUtil
3855: .getSingleNode(
3856: miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE],
3857: "coplet[@id='" + copletID
3858: + "' and @number='" + copletNr
3859: + "']", this .xpathProcessor);
3860: }
3861: return node;
3862: }
3863:
3864: /**
3865: * Modify the coplet.
3866: * This method returns true if the type informations must be recalculated
3867: */
3868: private boolean modifyCoplet(String requestString,
3869: SessionContext context, Map theProfile,
3870: DocumentFragment profile) throws ProcessingException,
3871: javax.xml.transform.TransformerException {
3872: // synchronized as the caller is synced
3873: if (this .getLogger().isDebugEnabled()) {
3874: this .getLogger().debug(
3875: "BEGIN modifyCoplet request=" + requestString);
3876: }
3877: boolean result = false;
3878:
3879: int pos, pos2;
3880: pos = requestString.indexOf('_');
3881: pos2 = requestString.indexOf('_', pos + 1);
3882: if (pos != -1 && pos2 != -1) {
3883: Element coplet = null;
3884:
3885: String copletID;
3886: String copletNr;
3887: String argument = null;
3888:
3889: copletID = requestString.substring(pos + 1, pos2);
3890: copletNr = requestString.substring(pos2 + 1);
3891: pos = copletNr.indexOf('_');
3892: if (pos != -1) {
3893: argument = copletNr.substring(pos + 1);
3894: copletNr = copletNr.substring(0, pos);
3895: }
3896:
3897: // create a new coplet: in the given column, header or footer
3898: if (requestString.startsWith(PortalManagerImpl.REQ_CMD_NEW)
3899: && this
3900: .isCopletAvailable(
3901: context,
3902: copletID,
3903: (Map) theProfile
3904: .get(PortalConstants.PROFILE_DEFAULT_COPLETS),
3905: (Map) theProfile
3906: .get(PortalConstants.PROFILE_MEDIA_COPLETS))) {
3907: Node[] miscNodes = (Node[]) theProfile
3908: .get(PortalConstants.PROFILE_MISC_POINTER);
3909: // determine the coplet number
3910: Node lastCoplet = miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE];
3911: String lastNumber = null;
3912: if (lastCoplet != null) {
3913: lastNumber = ((Element) lastCoplet).getAttributeNS(
3914: null, "number");
3915: if (lastNumber != null) {
3916: int value = new Integer(lastNumber).intValue();
3917: value++;
3918: lastNumber = "" + value;
3919: }
3920: }
3921: if (lastNumber == null)
3922: lastNumber = "0";
3923:
3924: Node copletsNode;
3925: if (copletNr.equals("header")) {
3926: copletsNode = miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE];
3927: if (copletsNode == null) {
3928: copletsNode = DOMUtil
3929: .selectSingleNode(
3930: profile,
3931: "profile/portal-profile/content/header",
3932: this .xpathProcessor);
3933: miscNodes[PortalConstants.PROFILE_MISC_HEADER_CONTENT_NODE] = copletsNode;
3934: } else { // remove old coplet
3935: Node oldCoplet = DOMUtil.getFirstNodeFromPath(
3936: copletsNode, new String[] { "coplet" },
3937: false);
3938: if (oldCoplet != null)
3939: copletsNode.removeChild(oldCoplet);
3940: }
3941: } else if (copletNr.equals("footer")) {
3942: copletsNode = miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE];
3943: if (copletsNode == null) {
3944: copletsNode = DOMUtil
3945: .selectSingleNode(
3946: profile,
3947: "profile/portal-profile/content/footer",
3948: this .xpathProcessor);
3949: miscNodes[PortalConstants.PROFILE_MISC_FOOTER_CONTENT_NODE] = copletsNode;
3950: } else { // remove old coplet
3951: Node oldCoplet = DOMUtil.getFirstNodeFromPath(
3952: copletsNode, new String[] { "coplet" },
3953: false);
3954: if (oldCoplet != null)
3955: copletsNode.removeChild(oldCoplet);
3956: }
3957: } else {
3958: Node columnNode = miscNodes[7 + new Integer(
3959: copletNr).intValue()];
3960: copletsNode = DOMUtil.getFirstNodeFromPath(
3961: columnNode, new String[] { "coplets" },
3962: false);
3963: }
3964: Element copletNode;
3965: Document doc = copletsNode.getOwnerDocument();
3966: copletNode = doc.createElementNS(null, "coplet");
3967: copletsNode.appendChild(copletNode);
3968: copletNode.setAttributeNS(null, "id", copletID);
3969: copletNode.setAttributeNS(null, "number", lastNumber);
3970: // set position
3971: NodeList childs = DOMUtil.getNodeListFromPath(
3972: copletsNode, new String[] { "coplet" });
3973: int childsCount = (childs == null ? 0 : childs
3974: .getLength());
3975: copletNode.setAttributeNS(null, "position", ""
3976: + (childsCount));
3977: miscNodes[PortalConstants.PROFILE_MISC_LAST_COPLET_NODE] = copletNode;
3978:
3979: // copy status
3980: Element configElement = this
3981: .getCopletConfiguration(
3982: copletID,
3983: (Map) theProfile
3984: .get(PortalConstants.PROFILE_DEFAULT_COPLETS),
3985: (Map) theProfile
3986: .get(PortalConstants.PROFILE_MEDIA_COPLETS));
3987: Element configStatus = (Element) DOMUtil
3988: .getFirstNodeFromPath(configElement,
3989: new String[] { "status" }, false);
3990: copletNode.appendChild(configStatus.cloneNode(true));
3991:
3992: // clear type information for each status
3993: Element status = (Element) copletNode
3994: .getElementsByTagName("status").item(0);
3995: NodeList parameters = status.getChildNodes();
3996: Node current;
3997: Element statusNode;
3998: if (parameters != null) {
3999: for (int i = 0; i < parameters.getLength(); i++) {
4000: current = parameters.item(i);
4001: if (current.getNodeType() == Node.ELEMENT_NODE) {
4002: statusNode = (Element) current;
4003: if (statusNode.hasAttributeNS(null,
4004: "formpath"))
4005: statusNode.removeAttributeNS(null,
4006: "formpath");
4007: if (statusNode.hasAttributeNS(null,
4008: "formtype"))
4009: statusNode.removeAttributeNS(null,
4010: "formtype");
4011: if (statusNode.hasAttributeNS(null,
4012: "formdescription"))
4013: statusNode.removeAttributeNS(null,
4014: "formdescription");
4015: }
4016: }
4017: }
4018: result = true;
4019:
4020: } else {
4021: coplet = this
4022: .getCopletElement(
4023: copletID,
4024: copletNr,
4025: (Node[]) theProfile
4026: .get(PortalConstants.PROFILE_MISC_POINTER));
4027: if (coplet != null) {
4028: if (requestString
4029: .startsWith(PortalManagerImpl.REQ_CMD_CLOSE)
4030: || requestString
4031: .startsWith(PortalManagerImpl.REQ_CMD_HIDE)) {
4032: Node node = DOMUtil.selectSingleNode(coplet,
4033: "status/visible", this .xpathProcessor);
4034: DOMUtil.setValueOfNode(node, "false");
4035: } else if (requestString
4036: .startsWith(PortalManagerImpl.REQ_CMD_OPEN)
4037: || requestString
4038: .startsWith(PortalManagerImpl.REQ_CMD_SHOW)) {
4039: Node node = DOMUtil.selectSingleNode(coplet,
4040: "status/visible", this .xpathProcessor);
4041: DOMUtil.setValueOfNode(node, "true");
4042: } else if (requestString
4043: .startsWith(PortalManagerImpl.REQ_CMD_MINIMIZE)) {
4044: Node node = DOMUtil.selectSingleNode(coplet,
4045: "status/size", this .xpathProcessor);
4046: DOMUtil.setValueOfNode(node, "min");
4047: } else if (requestString
4048: .startsWith(PortalManagerImpl.REQ_CMD_MAXIMIZE)) {
4049: Node node = DOMUtil.selectSingleNode(coplet,
4050: "status/size", this .xpathProcessor);
4051: DOMUtil.setValueOfNode(node, "max");
4052: } else if (requestString
4053: .startsWith(PortalManagerImpl.REQ_CMD_CUSTOMIZE)) {
4054: Node node = DOMUtil
4055: .selectSingleNode(coplet,
4056: "status/customize",
4057: this .xpathProcessor);
4058: DOMUtil.setValueOfNode(node, "true");
4059: } else if (requestString
4060: .startsWith(PortalManagerImpl.REQ_CMD_UPDATE)) {
4061: Node node = DOMUtil
4062: .selectSingleNode(coplet,
4063: "status/customize",
4064: this .xpathProcessor);
4065: DOMUtil.setValueOfNode(node, "false");
4066: } else if (requestString
4067: .startsWith(PortalManagerImpl.REQ_CMD_DELETE)) {
4068: // delete the status of the coplet
4069: Node statusNode = DOMUtil.getSingleNode(
4070: profile,
4071: "profile/status-profile/customization/coplet[@id='"
4072: + copletID + "' and @number='"
4073: + copletNr + "']",
4074: this .xpathProcessor);
4075: if (statusNode != null) {
4076: statusNode.getParentNode().removeChild(
4077: statusNode);
4078: Element configElement = this
4079: .getCopletConfiguration(
4080: copletID,
4081: (Map) theProfile
4082: .get(PortalConstants.PROFILE_DEFAULT_COPLETS),
4083: (Map) theProfile
4084: .get(PortalConstants.PROFILE_MEDIA_COPLETS));
4085: boolean isPersistent = DOMUtil
4086: .getValueAsBooleanOf(configElement,
4087: "configuration/persistent",
4088: false, this .xpathProcessor);
4089: if (isPersistent) {
4090: // mark the status profile to be saved
4091: theProfile
4092: .put(
4093: PortalConstants.PROFILE_SAVE_STATUS_FLAG,
4094: "true");
4095: }
4096: }
4097: String posAttr = coplet.getAttributeNS(null,
4098: "position");
4099: NodeList followUps = DOMUtil
4100: .selectNodeList(coplet.getParentNode(),
4101: "coplet[@position > '"
4102: + posAttr + "']",
4103: this .xpathProcessor);
4104: coplet.getParentNode().removeChild(coplet);
4105: coplet = null;
4106: if (followUps != null) {
4107: int value;
4108: for (int i = 0; i < followUps.getLength(); i++) {
4109: value = new Integer(
4110: ((Element) followUps.item(i))
4111: .getAttributeNS(null,
4112: "position"))
4113: .intValue();
4114: value -= 1;
4115: ((Element) followUps.item(i))
4116: .setAttributeNS(null,
4117: "position", "" + value);
4118: }
4119: }
4120: } else if (requestString
4121: .startsWith(PortalManagerImpl.REQ_CMD_MOVE)) {
4122: if (argument != null) {
4123: Element copletsElement = (Element) DOMUtil
4124: .getSingleNode(profile,
4125: "profile/portal-profile/content/column[@position='"
4126: + argument
4127: + "']/coplets",
4128: this .xpathProcessor);
4129: if (copletsElement != null) {
4130: if (!coplet.getParentNode().equals(
4131: copletsElement)) {
4132: String posAttr = coplet
4133: .getAttributeNS(null,
4134: "position");
4135: NodeList followUps = DOMUtil
4136: .selectNodeList(coplet
4137: .getParentNode(),
4138: "coplet[@position > '"
4139: + posAttr
4140: + "']",
4141: this .xpathProcessor);
4142: coplet.getParentNode().removeChild(
4143: coplet);
4144: // set position attribute
4145: NodeList childs = DOMUtil
4146: .getNodeListFromPath(
4147: copletsElement,
4148: new String[] { "coplet" });
4149: int childsCount = (childs == null ? 0
4150: : childs.getLength());
4151: coplet
4152: .setAttributeNS(
4153: null,
4154: "position",
4155: ""
4156: + (childsCount + 1));
4157: copletsElement.appendChild(coplet);
4158: if (followUps != null) {
4159: int value;
4160: for (int i = 0; i < followUps
4161: .getLength(); i++) {
4162: value = new Integer(
4163: ((Element) followUps
4164: .item(i))
4165: .getAttributeNS(
4166: null,
4167: "position"))
4168: .intValue();
4169: value -= 1;
4170: ((Element) followUps
4171: .item(i))
4172: .setAttributeNS(
4173: null,
4174: "position",
4175: "" + value);
4176: }
4177: }
4178: }
4179: }
4180: }
4181: } else if (requestString
4182: .startsWith(PortalManagerImpl.REQ_CMD_MOVEROW)) {
4183: if (argument != null) {
4184: Element newCoplet = (Element) DOMUtil
4185: .getSingleNode(coplet
4186: .getParentNode(),
4187: "coplet[@position='"
4188: + argument + "']",
4189: this .xpathProcessor);
4190: if (newCoplet != null) {
4191: String position = coplet
4192: .getAttributeNS(null,
4193: "position");
4194: coplet.removeAttributeNS(null,
4195: "position");
4196: coplet.setAttributeNS(null, "position",
4197: argument);
4198: newCoplet.removeAttributeNS(null,
4199: "position");
4200: newCoplet.setAttributeNS(null,
4201: "position", position);
4202: }
4203: }
4204: }
4205: }
4206: }
4207: }
4208:
4209: if (this .getLogger().isDebugEnabled()) {
4210: this .getLogger().debug(
4211: "END modifyCoplet calculate=" + result);
4212: }
4213: return result;
4214: }
4215:
4216: /**
4217: * Check if the coplet is available for the current logged in user
4218: * If the user is not logged in, this returns false.
4219: * First the default coplets are searched. If none is found then
4220: * the coplets for each media are searched.
4221: */
4222: private boolean isCopletAvailable(SessionContext context,
4223: String copletID, Map defaultCoplets, Map mediaCoplets) {
4224: // no sync required
4225: if (this .getLogger().isDebugEnabled()) {
4226: this .getLogger().debug(
4227: "BEGIN isCopletAvailable coplet=" + copletID);
4228: }
4229: boolean result = false;
4230:
4231: if (context != null) {
4232: result = defaultCoplets.containsKey(copletID);
4233: if (!result) {
4234: Iterator iter = mediaCoplets.values().iterator();
4235: while (!result && iter.hasNext()) {
4236: result = ((Map) iter.next()).containsKey(copletID);
4237: }
4238: }
4239: }
4240:
4241: if (this .getLogger().isDebugEnabled()) {
4242: this .getLogger().debug(
4243: "END isCopletAvailable result=" + result);
4244: }
4245: return result;
4246: }
4247:
4248: /* (non-Javadoc)
4249: * @see org.apache.cocoon.webapps.portal.components.PortalManager#checkAuthentication(org.apache.cocoon.environment.Redirector, java.lang.String)
4250: */
4251: public boolean checkAuthentication(Redirector redirector,
4252: String copletID) throws SAXException, IOException,
4253: ProcessingException {
4254: // synchronized
4255: if (this .getLogger().isDebugEnabled()) {
4256: this .getLogger().debug(
4257: "BEGIN checkAuthentication coplet=" + copletID);
4258: }
4259: this .setup();
4260: boolean result = false;
4261: SessionContext context = this .getContext(false);
4262: if (context != null
4263: && context
4264: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE) != null) {
4265:
4266: try {
4267: this .getTransactionManager().startReadingTransaction(
4268: context);
4269: Map theProfile = this
4270: .retrieveProfile(this
4271: .getProfileID(
4272: PortalManagerImpl.BUILDTYPE_VALUE_ID,
4273: (String) context
4274: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ROLE),
4275: (String) context
4276: .getAttribute(PortalManagerImpl.ATTRIBUTE_PORTAL_ID),
4277: false));
4278:
4279: if (theProfile != null) {
4280: if (copletID == null
4281: || copletID.trim().length() == 0) {
4282: result = true;
4283: } else {
4284: result = this
4285: .isCopletAvailable(
4286: context,
4287: copletID,
4288: (Map) theProfile
4289: .get(PortalConstants.PROFILE_DEFAULT_COPLETS),
4290: (Map) theProfile
4291: .get(PortalConstants.PROFILE_MEDIA_COPLETS));
4292: }
4293: }
4294: } finally {
4295: this .getTransactionManager().stopReadingTransaction(
4296: context);
4297: } // end synced
4298: }
4299:
4300: if (!result) {
4301: Map config = this .getConfiguration();
4302: if (config != null) {
4303: String redirectURI = (String) config
4304: .get(PortalConstants.CONF_AUTH_REDIRECT);
4305: if (redirectURI == null) {
4306: redirectURI = (String) config
4307: .get(PortalConstants.CONF_PORTAL_URI);
4308: }
4309: if (redirectURI != null) {
4310: redirector.globalRedirect(false, redirectURI);
4311: }
4312: }
4313: }
4314:
4315: if (this .getLogger().isDebugEnabled()) {
4316: this .getLogger().debug(
4317: "END checkAuthentication result=" + result);
4318: }
4319: return result;
4320: }
4321:
4322: /**
4323: * Get the configuration. This configuration is an authentication application configuration
4324: * for the current application with the name "portal".
4325: * The first time this configuration is build it is stored in the session
4326: * so later requests get the cached result.
4327: */
4328: private Map getConfiguration() throws ProcessingException {
4329: // synchronized
4330: if (this .getLogger().isDebugEnabled()) {
4331: this .getLogger().debug("BEGIN getConfiguration");
4332: }
4333: Map result = null;
4334: RequestState reqstate = this .getRequestState();
4335: String appName = reqstate.getApplicationName();
4336: String handlerName = reqstate.getHandlerName();
4337: Session session = this .getSessionManager().getSession(false);
4338: if (session != null && appName != null && handlerName != null) {
4339:
4340: synchronized (session) {
4341: result = (Map) session
4342: .getAttribute(PortalConstants.ATTRIBUTE_CONFIGURATION
4343: + handlerName + ':' + appName);
4344: if (result == null) {
4345:
4346: try {
4347: Configuration config;
4348:
4349: Configuration conf = reqstate
4350: .getModuleConfiguration(PortalConstants.AUTHENTICATION_MODULE_NAME);
4351: if (conf == null) {
4352: throw new ProcessingException(
4353: "portal: Configuration for application '"
4354: + appName + "' not found.");
4355: }
4356: result = new HashMap(10, 2);
4357: // auth-redirect (optional)
4358: config = conf.getChild("auth-redirect", false);
4359: if (config != null) {
4360: result.put(
4361: PortalConstants.CONF_AUTH_REDIRECT,
4362: config.getValue());
4363: }
4364:
4365: // portal-uri (required)
4366: config = conf.getChild("portal-uri", false);
4367: if (config == null) {
4368: throw new ProcessingException(
4369: "portal: portal-uri required for application '"
4370: + appName + "'");
4371: }
4372: result.put(PortalConstants.CONF_PORTAL_URI,
4373: config.getValue());
4374:
4375: // profile-cache (optional)
4376: config = conf.getChild("profile-cache", false);
4377: if (config != null
4378: && config.getValueAsBoolean()) {
4379: result.put(
4380: PortalConstants.CONF_PROFILE_CACHE,
4381: appName);
4382: }
4383:
4384: // parallel coplets
4385: config = conf.getChild(
4386: "process-coplets-parallel", false);
4387: if (config != null) {
4388: result
4389: .put(
4390: PortalConstants.CONF_PARALLEL_COPLETS,
4391: new Boolean(
4392: config
4393: .getValueAsBoolean(false)));
4394: } else {
4395: result
4396: .put(
4397: PortalConstants.CONF_PARALLEL_COPLETS,
4398: Boolean.FALSE);
4399: }
4400:
4401: // timeout
4402: config = conf.getChild(
4403: "default-coplet-timeout", false);
4404: if (config != null) {
4405: result
4406: .put(
4407: PortalConstants.CONF_COPLET_TIMEOUT,
4408: new Long(
4409: config
4410: .getValueAsLong(600000)));
4411: } else {
4412: result
4413: .put(
4414: PortalConstants.CONF_COPLET_TIMEOUT,
4415: new Long(600000));
4416: }
4417:
4418: // and now the profile
4419: config = conf.getChild("profile", false);
4420: if (config == null)
4421: throw new ProcessingException(
4422: "portal: profile configuration required for application '"
4423: + appName + "'");
4424: Configuration child;
4425:
4426: // build resource (optional)
4427: child = config.getChild("buildprofile", false);
4428: if (child != null) {
4429: result
4430: .put(
4431: PortalConstants.CONF_BUILD_RESOURCE,
4432: child.getAttribute("uri"));
4433: }
4434:
4435: // base resource, type is optional
4436: child = config.getChild("layout-base", false);
4437: if (child == null) {
4438: throw new ProcessingException(
4439: "portal: layout-base required for application '"
4440: + appName + "'");
4441: }
4442: result
4443: .put(
4444: PortalConstants.CONF_LAYOUTBASE_RESOURCE,
4445: child.getAttribute("uri"));
4446: child = config.getChild("coplet-base", false);
4447: if (child == null) {
4448: throw new ProcessingException(
4449: "portal: coplet-base required for application '"
4450: + appName + "'");
4451: }
4452: result
4453: .put(
4454: PortalConstants.CONF_COPLETBASE_RESOURCE,
4455: child.getAttribute("uri"));
4456: child = config.getChild("type-base", false);
4457: if (child != null) {
4458: result
4459: .put(
4460: PortalConstants.CONF_TYPEBASE_RESOURCE,
4461: child.getAttribute("uri"));
4462: }
4463:
4464: // coplet base save (is optional)
4465: child = config.getChild("coplet-base-save",
4466: false);
4467: if (child != null) {
4468: result
4469: .put(
4470: PortalConstants.CONF_COPLETBASE_SAVE_RESOURCE,
4471: child.getAttribute("uri"));
4472: }
4473:
4474: // global delta (load required)
4475: child = config.getChild("global-delta-load",
4476: false);
4477: if (child == null) {
4478: throw new ProcessingException(
4479: "portal: global-delta-load required for application '"
4480: + appName + "'");
4481: }
4482: result
4483: .put(
4484: PortalConstants.CONF_GLOBALDELTA_LOADRESOURCE,
4485: child.getAttribute("uri"));
4486: child = config.getChild("global-delta-save",
4487: false);
4488: if (child != null) {
4489: result
4490: .put(
4491: PortalConstants.CONF_GLOBALDELTA_SAVERESOURCE,
4492: child.getAttribute("uri"));
4493: }
4494: child = config.getChild("global-type-delta",
4495: false);
4496: if (child != null) {
4497: result
4498: .put(
4499: PortalConstants.CONF_GLOBALDELTA_TYPERESOURCE,
4500: child.getAttribute("uri"));
4501: }
4502:
4503: // role delta (optional)
4504: child = config.getChild("role-delta-load",
4505: false);
4506: if (child != null) {
4507: result
4508: .put(
4509: PortalConstants.CONF_ROLEDELTA_LOADRESOURCE,
4510: child.getAttribute("uri"));
4511: }
4512: child = config.getChild("role-delta-save",
4513: false);
4514: if (child != null) {
4515: result
4516: .put(
4517: PortalConstants.CONF_ROLEDELTA_SAVERESOURCE,
4518: child.getAttribute("uri"));
4519: }
4520: child = config.getChild("role-type-delta",
4521: false);
4522: if (child != null) {
4523: result
4524: .put(
4525: PortalConstants.CONF_ROLEDELTA_TYPERESOURCE,
4526: child.getAttribute("uri"));
4527: }
4528:
4529: // User delta
4530: child = config.getChild("user-delta-load",
4531: false);
4532: if (child != null) {
4533: result
4534: .put(
4535: PortalConstants.CONF_USERDELTA_LOADRESOURCE,
4536: child.getAttribute("uri"));
4537: }
4538: child = config.getChild("user-delta-save",
4539: false);
4540: if (child != null) {
4541: result
4542: .put(
4543: PortalConstants.CONF_USERDELTA_SAVERESOURCE,
4544: child.getAttribute("uri"));
4545: }
4546: child = config.getChild("user-type-delta",
4547: false);
4548: if (child != null) {
4549: result
4550: .put(
4551: PortalConstants.CONF_USERDELTA_TYPERESOURCE,
4552: child.getAttribute("uri"));
4553: }
4554:
4555: // Personal information
4556: child = config.getChild("user-status-load",
4557: false);
4558: if (child != null) {
4559: result
4560: .put(
4561: PortalConstants.CONF_STATUS_LOADRESOURCE,
4562: child.getAttribute("uri"));
4563: }
4564: child = config.getChild("user-status-save",
4565: false);
4566: if (child != null) {
4567: result
4568: .put(
4569: PortalConstants.CONF_STATUS_SAVERESOURCE,
4570: child.getAttribute("uri"));
4571: }
4572:
4573: // Admin Type profil
4574: child = config.getChild("admin-type-base",
4575: false);
4576: if (child != null) {
4577: result
4578: .put(
4579: PortalConstants.CONF_ADMIN_TYPE_BASE,
4580: child.getAttribute("uri"));
4581: }
4582:
4583: // store the config in the session
4584: session.setAttribute(
4585: PortalConstants.ATTRIBUTE_CONFIGURATION
4586: + handlerName + ':' + appName,
4587: result);
4588: } catch (ConfigurationException conf) {
4589: throw new ProcessingException(
4590: "ConfigurationException: " + conf, conf);
4591: }
4592: }
4593: }
4594:
4595: }
4596:
4597: if (this .getLogger().isDebugEnabled()) {
4598: this .getLogger().debug(
4599: "END getConfiguration conf=" + result);
4600: }
4601: return result;
4602: }
4603:
4604: /**
4605: * Build the profile for the required level if not already done
4606: */
4607: private void createProfile(SessionContext context, String type,
4608: String role, String id, boolean adminProfile)
4609: throws SAXException, IOException, ProcessingException {
4610: // no sync required
4611: if (this .getLogger().isDebugEnabled()) {
4612: this .getLogger().debug(
4613: "BEGIN createProfile context=" + context
4614: + ", type=" + type + ", role=" + role
4615: + ", id=" + id);
4616: }
4617:
4618: RequestState reqstate = this .getRequestState();
4619: SourceParameters pars = reqstate.getHandler().getContext()
4620: .getContextInfoAsParameters();
4621: pars.setSingleParameterValue("type", type);
4622: pars.setSingleParameterValue("admin", (adminProfile ? "true"
4623: : "false"));
4624:
4625: if (!type.equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)
4626: || role != null) {
4627: pars.setSingleParameterValue("ID", id);
4628: pars.setSingleParameterValue("role", role);
4629: } else {
4630: id = pars.getParameter("ID", null);
4631: role = pars.getParameter("role", null);
4632: }
4633:
4634: Map map = this .getConfiguration();
4635: if (map == null) {
4636: throw new ProcessingException(
4637: "portal Configuration not found.");
4638: }
4639:
4640: // is the configuration build by using a own resource?
4641: String resource = (String) map
4642: .get(PortalConstants.CONF_BUILD_RESOURCE);
4643: if (resource != null) {
4644: if (this .getLogger().isInfoEnabled()) {
4645: this .getLogger().info(
4646: "Building portal profile: " + resource);
4647: }
4648: SourceUtil.readDOM(resource, null, pars, this .resolver);
4649: } else {
4650: this .buildProfile(type, role, id, adminProfile);
4651: }
4652:
4653: if (this .getLogger().isDebugEnabled()) {
4654: this .getLogger().debug("END createProfile");
4655: }
4656:
4657: }
4658:
4659: /**
4660: * Get the base profile for the current application.
4661: * The base profile consists of the layout and the coplet profile
4662: * and optional the type profile
4663: */
4664: private DocumentFragment buildBaseProfile(Map config,
4665: boolean adminProfile) throws ProcessingException {
4666: // calling method is synced
4667: if (this .getLogger().isDebugEnabled()) {
4668: this .getLogger().debug(
4669: "BEGIN buildBaseProfile config=" + config
4670: + ", adminProfile=" + adminProfile);
4671: }
4672: DocumentFragment copletsFragment;
4673: DocumentFragment layoutFragment;
4674: DocumentFragment typeFragment;
4675: DocumentFragment profile;
4676: Document profileDoc;
4677: Element profileRoot;
4678: String res;
4679:
4680: SourceParameters pars = new SourceParameters();
4681: RequestState reqstate = this .getRequestState();
4682: pars.setSingleParameterValue("application", reqstate
4683: .getApplicationName());
4684: pars.setSingleParameterValue("handler", reqstate
4685: .getHandlerName());
4686: pars.setSingleParameterValue("profile", "coplet-base");
4687:
4688: // First load the base profiles: copletProfile + layoutProfile
4689: res = (String) config
4690: .get(PortalConstants.CONF_COPLETBASE_RESOURCE);
4691: if (res == null) {
4692: throw new ProcessingException(
4693: "No configuration for portal-coplet base profile found.");
4694: }
4695: if (this .getLogger().isDebugEnabled()) {
4696: this .getLogger().debug("Loading coplet base profile");
4697: }
4698: copletsFragment = SourceUtil.readDOM(res, null, pars,
4699: this .resolver);
4700:
4701: if (this .getLogger().isDebugEnabled()) {
4702: this .getLogger().debug("coplet base profile loaded");
4703: }
4704: res = (String) config
4705: .get(PortalConstants.CONF_LAYOUTBASE_RESOURCE);
4706: if (res == null) {
4707: throw new ProcessingException(
4708: "No configuration for portal-layout base profile found.");
4709: }
4710: if (this .getLogger().isDebugEnabled()) {
4711: this .getLogger().debug("loading layout base profile");
4712: }
4713: pars.setSingleParameterValue("profile", "layout-base");
4714: layoutFragment = SourceUtil.readDOM(res, null, pars,
4715: this .resolver);
4716:
4717: if (this .getLogger().isDebugEnabled()) {
4718: this .getLogger().debug("layout base profile loaded");
4719: }
4720: // now create the base profile containing the above profiles
4721: profileDoc = DOMUtil.createDocument();
4722: profile = profileDoc.createDocumentFragment();
4723: profileRoot = profileDoc.createElementNS(null, "profile");
4724: profile.appendChild(profileRoot);
4725: profileRoot.appendChild(profileDoc.importNode(DOMUtil
4726: .selectSingleNode(layoutFragment, "layout-profile",
4727: this .xpathProcessor), true));
4728: profileRoot.appendChild(profileDoc.importNode(DOMUtil
4729: .selectSingleNode(copletsFragment, "coplets-profile",
4730: this .xpathProcessor), true));
4731:
4732: // if avalailable append the type profile
4733: if (adminProfile) {
4734: res = (String) config
4735: .get(PortalConstants.CONF_ADMIN_TYPE_BASE);
4736: pars.setSingleParameterValue("profile", "admin-type-base");
4737: } else {
4738: res = (String) config
4739: .get(PortalConstants.CONF_TYPEBASE_RESOURCE);
4740: pars.setSingleParameterValue("profile", "type-base");
4741: }
4742: if (res != null) {
4743: if (this .getLogger().isDebugEnabled()) {
4744: this .getLogger().debug("loading type base profile");
4745: }
4746: typeFragment = SourceUtil.readDOM(res, null, pars,
4747: this .resolver);
4748: profileRoot.appendChild(profileDoc.importNode(DOMUtil
4749: .selectSingleNode(typeFragment, "type-profile",
4750: this .xpathProcessor), true));
4751:
4752: if (this .getLogger().isDebugEnabled()) {
4753: this .getLogger().debug("type base profile loaded");
4754: }
4755: }
4756:
4757: if (this .getLogger().isDebugEnabled()) {
4758: this .getLogger().debug(
4759: "END buildBaseProfile profile=" + profile);
4760: }
4761: return profile;
4762: }
4763:
4764: /**
4765: * Build the global profile.
4766: */
4767: private void buildGlobalProfile(Element profileRoot, Map config,
4768: boolean adminProfile) throws ProcessingException {
4769: // calling method is synced
4770: if (this .getLogger().isDebugEnabled()) {
4771: this .getLogger().debug(
4772: "BEGIN buildGlobalProfile profileRoot="
4773: + profileRoot + ", config=" + config
4774: + ", adminProfile=" + adminProfile);
4775: }
4776: DocumentFragment globalFragment;
4777: String res = (String) config
4778: .get(PortalConstants.CONF_GLOBALDELTA_LOADRESOURCE);
4779: if (res == null) {
4780: throw new ProcessingException(
4781: "No configuration for portal-role delta profile found.");
4782: }
4783: SourceParameters pars = new SourceParameters();
4784: RequestState reqstate = this .getRequestState();
4785: pars.setSingleParameterValue("application", reqstate
4786: .getApplicationName());
4787: pars.setSingleParameterValue("handler", reqstate
4788: .getHandlerName());
4789: pars.setSingleParameterValue("profile", "global-delta");
4790:
4791: if (this .getLogger().isDebugEnabled()) {
4792: this .getLogger().debug("loading global profile");
4793: }
4794: globalFragment = SourceUtil.readDOM(res, null, pars,
4795: this .resolver);
4796: if (this .getLogger().isDebugEnabled()) {
4797: this .getLogger().debug("global profile loaded");
4798: }
4799: this .importProfileDelta(profileRoot, globalFragment,
4800: "global-delta", "layout-delta");
4801: this .importProfileDelta(profileRoot, globalFragment,
4802: "global-delta", "coplets-delta");
4803: this .addProfilePart(profileRoot, globalFragment,
4804: "global-delta", "portal-profile");
4805: this .addProfilePart(profileRoot, globalFragment,
4806: "global-delta", "personal-profile");
4807:
4808: // types
4809: res = (String) config
4810: .get(PortalConstants.CONF_GLOBALDELTA_TYPERESOURCE);
4811: if (!adminProfile && res != null) {
4812: pars
4813: .setSingleParameterValue("profile",
4814: "global-type-delta");
4815: if (this .getLogger().isDebugEnabled()) {
4816: this .getLogger().debug("loading global type profile");
4817: }
4818: globalFragment = SourceUtil.readDOM(res, null, pars,
4819: this .resolver);
4820: if (this .getLogger().isDebugEnabled()) {
4821: this .getLogger().debug("global type profile loaded");
4822: }
4823: this .addProfilePart(profileRoot, globalFragment,
4824: "global-delta", "type-profile");
4825: }
4826: if (this .getLogger().isDebugEnabled()) {
4827: this .getLogger().debug("END buildGlobalProfile");
4828: }
4829: }
4830:
4831: /**
4832: * Build the role profile
4833: */
4834: private void buildRoleProfile(Element profileRoot, Map config,
4835: String role, boolean adminProfile)
4836: throws ProcessingException {
4837: // calling method is synced
4838:
4839: DocumentFragment roleFragment;
4840: RequestState reqstate = this .getRequestState();
4841: SourceParameters pars;
4842: pars = new SourceParameters();
4843: pars.setSingleParameterValue("role", role);
4844: pars.setSingleParameterValue("application", reqstate
4845: .getApplicationName());
4846: pars.setSingleParameterValue("handler", reqstate
4847: .getHandlerName());
4848: pars.setSingleParameterValue("profile", "role-delta");
4849:
4850: String res = (String) config
4851: .get(PortalConstants.CONF_ROLEDELTA_LOADRESOURCE);
4852: if (res != null) {
4853: if (this .getLogger().isDebugEnabled()) {
4854: this .getLogger().debug("loading role profile");
4855: }
4856: roleFragment = SourceUtil.readDOM(res, null, pars,
4857: this .resolver);
4858: if (this .getLogger().isDebugEnabled()) {
4859: this .getLogger().debug("role profile loaded");
4860: }
4861: this .importProfileDelta(profileRoot, roleFragment,
4862: "role-delta", "layout-delta");
4863: this .importProfileDelta(profileRoot, roleFragment,
4864: "role-delta", "coplets-delta");
4865: this .addProfilePart(profileRoot, roleFragment,
4866: "role-delta", "portal-profile");
4867: this .importProfileDelta(profileRoot, roleFragment,
4868: "role-delta", "personal-delta");
4869: }
4870:
4871: // types
4872: res = (String) config
4873: .get(PortalConstants.CONF_ROLEDELTA_TYPERESOURCE);
4874: if (!adminProfile && res != null) {
4875: pars.setSingleParameterValue("profile", "role-type-delta");
4876: if (this .getLogger().isDebugEnabled()) {
4877: this .getLogger().debug("loading role type profile");
4878: }
4879: roleFragment = SourceUtil.readDOM(res, null, pars,
4880: this .resolver);
4881: if (this .getLogger().isDebugEnabled()) {
4882: this .getLogger().debug("role type profile loaded");
4883: }
4884: this .addProfilePart(profileRoot, roleFragment,
4885: "role-delta", "type-profile");
4886: }
4887: }
4888:
4889: /**
4890: * Build the user profile
4891: */
4892: private void buildUserProfile(Element profileRoot, Map config,
4893: String role, String id, boolean adminProfile)
4894: throws ProcessingException {
4895: // calling method is synced
4896: DocumentFragment userFragment;
4897: RequestState reqstate = this .getRequestState();
4898: SourceParameters pars;
4899: pars = new SourceParameters();
4900: pars.setSingleParameterValue("ID", id);
4901: pars.setSingleParameterValue("role", role);
4902: pars.setSingleParameterValue("application", reqstate
4903: .getApplicationName());
4904: pars.setSingleParameterValue("handler", reqstate
4905: .getHandlerName());
4906: pars.setSingleParameterValue("profile", "user-delta");
4907:
4908: String res = (String) config
4909: .get(PortalConstants.CONF_USERDELTA_LOADRESOURCE);
4910: if (res != null) {
4911: if (this .getLogger().isDebugEnabled()) {
4912: this .getLogger().debug("loading user profile");
4913: }
4914: userFragment = SourceUtil.readDOM(res, null, pars,
4915: this .resolver);
4916: if (this .getLogger().isDebugEnabled()) {
4917: this .getLogger().debug("user profile loaded");
4918: }
4919: this .importProfileDelta(profileRoot, userFragment,
4920: "user-delta", "layout-delta");
4921: this .importProfileDelta(profileRoot, userFragment,
4922: "user-delta", "coplets-delta");
4923: this .addProfilePart(profileRoot, userFragment,
4924: "user-delta", "portal-profile");
4925: this .importProfileDelta(profileRoot, userFragment,
4926: "user-delta", "personal-delta");
4927: }
4928:
4929: // types
4930: res = (String) config
4931: .get(PortalConstants.CONF_USERDELTA_TYPERESOURCE);
4932: if (!adminProfile && res != null) {
4933: pars.setSingleParameterValue("profile", "user-type-delta");
4934: if (this .getLogger().isDebugEnabled()) {
4935: this .getLogger().debug("loading user type profile");
4936: }
4937: userFragment = SourceUtil.readDOM(res, null, pars,
4938: this .resolver);
4939: if (this .getLogger().isDebugEnabled()) {
4940: this .getLogger().debug("user type profile loaded");
4941: }
4942: this .addProfilePart(profileRoot, userFragment,
4943: "user-delta", "type-profile");
4944: }
4945: }
4946:
4947: /**
4948: * Load the user status profile (if available)
4949: */
4950: private void buildUserStatusProfile(Element profileRoot,
4951: Map config, String role, String id)
4952: throws ProcessingException {
4953: // calling method is synced
4954: String res = (String) config
4955: .get(PortalConstants.CONF_STATUS_LOADRESOURCE);
4956:
4957: // remove the old status profile
4958: Node statusProfile = DOMUtil.getFirstNodeFromPath(profileRoot,
4959: new String[] { "status-profile" }, false);
4960: if (statusProfile != null) {
4961: profileRoot.removeChild(statusProfile);
4962: }
4963:
4964: if (res != null) {
4965: DocumentFragment userFragment;
4966: SourceParameters pars;
4967: RequestState reqstate = this .getRequestState();
4968: pars = new SourceParameters();
4969: pars.setSingleParameterValue("ID", id);
4970: pars.setSingleParameterValue("role", role);
4971: pars.setSingleParameterValue("application", reqstate
4972: .getApplicationName());
4973: pars.setSingleParameterValue("handler", reqstate
4974: .getHandlerName());
4975: pars.setSingleParameterValue("profile", "user-status");
4976: if (this .getLogger().isDebugEnabled()) {
4977: this .getLogger().debug("loading user status profile");
4978: }
4979: userFragment = SourceUtil.readDOM(res, null, pars,
4980: this .resolver);
4981: if (this .getLogger().isDebugEnabled()) {
4982: this .getLogger().debug("user status profile loaded");
4983: }
4984: this .addProfilePart(profileRoot, userFragment, null,
4985: "status-profile");
4986: }
4987: // test if the status-profile node is available
4988: // if not create one
4989: if (DOMUtil.getFirstNodeFromPath(profileRoot,
4990: new String[] { "status-profile" }, false) == null) {
4991: statusProfile = profileRoot.getOwnerDocument()
4992: .createElementNS(null, "status-profile");
4993: profileRoot.appendChild(statusProfile);
4994: }
4995: }
4996:
4997: /**
4998: * Save the user status profile (if available)
4999: */
5000: private void saveUserStatusProfile(Map profile, Map config,
5001: String role, String id) throws ProcessingException {
5002: // calling method is synced
5003: String res = (String) config
5004: .get(PortalConstants.CONF_STATUS_SAVERESOURCE);
5005: Element statusProfile = (Element) DOMUtil.getFirstNodeFromPath(
5006: (DocumentFragment) profile
5007: .get(PortalConstants.PROFILE_PROFILE),
5008: new String[] { "profile", "status-profile" }, false);
5009: if (res != null && statusProfile != null) {
5010: DocumentFragment userFragment = statusProfile
5011: .getOwnerDocument().createDocumentFragment();
5012: Element saveStatus = (Element) statusProfile
5013: .cloneNode(true);
5014: userFragment.appendChild(saveStatus);
5015: // now filter all not persistent coplets!
5016: NodeList list = DOMUtil.getNodeListFromPath(saveStatus,
5017: new String[] { "customization", "coplet" });
5018: String copletID;
5019: Element coplet;
5020: Element copletConfig;
5021: Map copletConfigs = (Map) profile
5022: .get(PortalConstants.PROFILE_DEFAULT_COPLETS);
5023: Map mediaCopletConfigs = (Map) profile
5024: .get(PortalConstants.PROFILE_MEDIA_COPLETS);
5025: boolean isPersistent;
5026: for (int i = 0; i < list.getLength(); i++) {
5027: coplet = (Element) list.item(i);
5028: copletID = coplet.getAttributeNS(null, "id");
5029: copletConfig = this .getCopletConfiguration(copletID,
5030: copletConfigs, mediaCopletConfigs);
5031: isPersistent = DOMUtil.getValueAsBooleanOf(
5032: copletConfig, "configuration/persistent",
5033: false, this .xpathProcessor);
5034: if (!isPersistent) {
5035: coplet.getParentNode().removeChild(coplet);
5036: }
5037: }
5038:
5039: try {
5040:
5041: RequestState reqstate = this .getRequestState();
5042: SourceParameters pars;
5043: pars = new SourceParameters();
5044: pars.setSingleParameterValue("ID", id);
5045: pars.setSingleParameterValue("role", role);
5046: pars.setSingleParameterValue("application", reqstate
5047: .getApplicationName());
5048: pars.setSingleParameterValue("handler", reqstate
5049: .getHandlerName());
5050: pars.setSingleParameterValue("profile", "user-status");
5051:
5052: SourceUtil.writeDOM(res, null, pars, userFragment,
5053: this .resolver, "xml");
5054:
5055: } finally {
5056: userFragment.removeChild(saveStatus);
5057: }
5058: }
5059: }
5060:
5061: /**
5062: * Change the profile according to the request parameter
5063: */
5064: private void changeProfile() throws ProcessingException,
5065: SAXException, IOException {
5066: // synchronized
5067: if (this .getLogger().isDebugEnabled()) {
5068: this .getLogger().debug("BEGIN changeProfile");
5069: }
5070: Request request = ContextHelper
5071: .getRequest(this .componentContext);
5072: SessionContext context = this .getContext(false);
5073:
5074: if (context != null) {
5075: try {
5076: Map theProfile = null;
5077: String profileID = request
5078: .getParameter(PortalManagerImpl.REQ_PARAMETER_PROFILE);
5079: if (profileID != null) {
5080: theProfile = this .retrieveProfile(profileID);
5081: }
5082:
5083: if (theProfile != null) {
5084: synchronized (context) {
5085: DocumentFragment profile = (DocumentFragment) theProfile
5086: .get(PortalConstants.PROFILE_PROFILE);
5087: Node[] miscNodes = (Node[]) theProfile
5088: .get(PortalConstants.PROFILE_MISC_POINTER);
5089: Element columns = (Element) miscNodes[PortalConstants.PROFILE_MISC_COLUMNS_NODE];
5090: Enumeration enumeration = request
5091: .getParameterNames();
5092: String current;
5093: boolean saveProfile = false;
5094:
5095: // first iteration: all changing commands
5096: while (enumeration.hasMoreElements()) {
5097: current = (String) enumeration
5098: .nextElement();
5099: if (current
5100: .startsWith(PortalManagerImpl.REQ_PARAMETER_CONF)) {
5101: int pos1, pos2;
5102: pos1 = current.indexOf('.');
5103: pos2 = current.indexOf('.', pos1 + 1);
5104: if (pos1 != -1 && pos2 != -1) {
5105: int pathIndex = new Integer(current
5106: .substring(pos1 + 1, pos2))
5107: .intValue();
5108: int place = new Integer(current
5109: .substring(pos2 + 1))
5110: .intValue();
5111: List typePaths = (List) theProfile
5112: .get(PortalConstants.PROFILE_TYPE_CONF_PATHS);
5113: String path = (String) typePaths
5114: .get(pathIndex);
5115: if (path != null) {
5116: NodeList nodes = DOMUtil
5117: .selectNodeList(
5118: profile,
5119: path,
5120: this .xpathProcessor);
5121: if (nodes != null) {
5122: Node node = nodes
5123: .item(place);
5124: if (node != null) {
5125: if (!node
5126: .equals(columns)) {
5127: DOMUtil
5128: .setValueOfNode(
5129: node,
5130: request
5131: .getParameter(current));
5132: }
5133: }
5134: }
5135:
5136: }
5137: }
5138: }
5139: }
5140:
5141: // second: all new
5142: boolean calculate = false;
5143: enumeration = request.getParameterNames();
5144: while (enumeration.hasMoreElements()) {
5145:
5146: current = (String) enumeration
5147: .nextElement();
5148: if (current
5149: .startsWith(PortalManagerImpl.REQ_PARAMETER_CONF)) {
5150: int pos1, pos2;
5151: pos1 = current.indexOf('.');
5152: pos2 = current.indexOf('.', pos1 + 1);
5153: if (pos1 != -1 && pos2 != -1) {
5154: int pathIndex = new Integer(current
5155: .substring(pos1 + 1, pos2))
5156: .intValue();
5157: int place = new Integer(current
5158: .substring(pos2 + 1))
5159: .intValue();
5160: List typePaths = (List) theProfile
5161: .get(PortalConstants.PROFILE_TYPE_CONF_PATHS);
5162: String path = (String) typePaths
5163: .get(pathIndex);
5164: if (path != null) {
5165: NodeList nodes = DOMUtil
5166: .selectNodeList(
5167: profile,
5168: path,
5169: this .xpathProcessor);
5170: if (nodes != null) {
5171: Node node = nodes
5172: .item(place);
5173: if (node != null) {
5174: if (node
5175: .equals(columns)) {
5176: int columnNumber = new Integer(
5177: request
5178: .getParameter(current))
5179: .intValue();
5180: int oldNumber = new Integer(
5181: DOMUtil
5182: .getValueOfNode(columns))
5183: .intValue();
5184: if (columnNumber > 0
5185: && columnNumber != oldNumber
5186: && columnNumber <= PortalConstants.MAX_COLUMNS) {
5187: this
5188: .changeColumns(
5189: profile,
5190: oldNumber,
5191: columnNumber,
5192: miscNodes);
5193: calculate = true;
5194: DOMUtil
5195: .setValueOfNode(
5196: node,
5197: request
5198: .getParameter(current));
5199: }
5200: }
5201: }
5202: }
5203:
5204: }
5205: }
5206:
5207: } else if (current
5208: .equals(PortalManagerImpl.REQ_PARAMETER_CMD)) {
5209: String[] cmds = request
5210: .getParameterValues(current);
5211: if (cmds != null && cmds.length > 0) {
5212: for (int i = 0; i < cmds.length; i++) {
5213: if (cmds[i]
5214: .equals(PortalManagerImpl.REQ_CMD_SAVEPROFILE)) {
5215: saveProfile = true;
5216: } else {
5217: if (this
5218: .modifyCoplet(
5219: cmds[i],
5220: context,
5221: theProfile,
5222: profile)) {
5223: calculate = true;
5224: }
5225: }
5226: }
5227: }
5228: }
5229: }
5230: // set type infos
5231: if (calculate) {
5232: this
5233: .setTypeInfo(
5234: profile,
5235: (List) theProfile
5236: .get(PortalConstants.PROFILE_TYPE_PATHS),
5237: (List) theProfile
5238: .get(PortalConstants.PROFILE_TYPE_CONF_PATHS));
5239: }
5240:
5241: // test if the status profile changed
5242: Object statusChanged = theProfile
5243: .get(PortalConstants.PROFILE_SAVE_STATUS_FLAG);
5244: if (statusChanged != null) {
5245: theProfile
5246: .remove(PortalConstants.PROFILE_SAVE_STATUS_FLAG);
5247: this .saveUserStatusProfile(theProfile, this
5248: .getConfiguration(), this
5249: .getRole(profileID), this
5250: .getID(profileID));
5251: }
5252:
5253: // save the profile
5254: if (saveProfile) {
5255: Map conf = this .getConfiguration();
5256: String role = this .getRole(profileID);
5257: String id = this .getID(profileID);
5258: String type = this .getType(profileID);
5259: String saveResource;
5260: String profileType;
5261:
5262: if (type
5263: .equals(PortalManagerImpl.BUILDTYPE_VALUE_GLOBAL)) {
5264: saveResource = (String) conf
5265: .get(PortalConstants.CONF_GLOBALDELTA_SAVERESOURCE);
5266: profileType = "global-delta";
5267: } else if (type
5268: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ROLE)) {
5269: saveResource = (String) conf
5270: .get(PortalConstants.CONF_ROLEDELTA_SAVERESOURCE);
5271: profileType = "role-delta";
5272: } else if (type
5273: .equals(PortalManagerImpl.BUILDTYPE_VALUE_ID)) {
5274: saveResource = (String) conf
5275: .get(PortalConstants.CONF_USERDELTA_SAVERESOURCE);
5276: profileType = "user-delta";
5277: } else {
5278: throw new ProcessingException(
5279: "portal: No save resource defined for type '"
5280: + type + "'.");
5281: }
5282:
5283: // patch
5284: // search for all "status/customize" nodes and set them
5285: // to false
5286: NodeList statusNodes = DOMUtil
5287: .selectNodeList(
5288: profile,
5289: "profile/portal-profile/content/descendant::status/customize",
5290: this .xpathProcessor);
5291: if (statusNodes != null) {
5292: String value;
5293: for (int l = 0; l < statusNodes
5294: .getLength(); l++) {
5295: value = DOMUtil
5296: .getValueOfNode(statusNodes
5297: .item(l));
5298: if (value.equals("true")) {
5299: DOMUtil.setValueOfNode(
5300: statusNodes.item(l),
5301: "false");
5302: }
5303: }
5304: }
5305:
5306: // build delta
5307: RequestState reqstate = this
5308: .getRequestState();
5309: DocumentFragment delta;
5310: delta = this .buildProfileDelta(type, role,
5311: id,
5312: this .getIsAdminProfile(profileID));
5313: SourceParameters pars = new SourceParameters();
5314: pars.setSingleParameterValue("type",
5315: profileType);
5316: if (id != null)
5317: pars.setSingleParameterValue("ID", id);
5318: if (role != null)
5319: pars.setSingleParameterValue("role",
5320: role);
5321: pars.setSingleParameterValue("application",
5322: reqstate.getApplicationName());
5323: pars.setSingleParameterValue("handler",
5324: reqstate.getHandlerName());
5325: SourceUtil.writeDOM(saveResource, null,
5326: pars, delta, this .resolver, "xml");
5327:
5328: if (delta.getParentNode() != null)
5329: delta.getParentNode()
5330: .removeChild(delta);
5331: delta = null;
5332:
5333: // cache the profile
5334: // The profile is only cached if it is already in the cache!
5335: // Why? During login the profile is build and cached, so it is in the cache.
5336: // But: If a user logs in, the profile is cached.
5337: // Now the admin logs in, changes the global profile and saves it.
5338: // The cache is invalidated, including the user profile.
5339: // Now the user changes his profile and saves it.
5340: // If it now would be cached, it would be invalid as it would
5341: // not reflect the changes by the admin.
5342: // But if the old profile is still in the cache, nobody
5343: // has changed a profile above.
5344: // Note CZ: The above is correct, but for building the delta
5345: // the "previous" profile is build and cached ! Thus we can
5346: // easily cache the new profile.
5347: // if (this.isProfileCached(profileID, conf)) {
5348: this .cacheProfile(profileID, theProfile,
5349: conf); // cache it
5350: // now the hardest part, clean up the cache
5351: this .cleanUpCache(type, role, conf);
5352: // }
5353:
5354: }
5355:
5356: } // end synchronized
5357: }
5358: } catch (javax.xml.transform.TransformerException local) {
5359: throw new ProcessingException("TransformerException: "
5360: + local, local);
5361: }
5362: }
5363: if (this .getLogger().isDebugEnabled()) {
5364: this .getLogger().debug("END changeProfile");
5365: }
5366: }
5367:
5368: /**
5369: * Change the number of the columns
5370: */
5371: private void changeColumns(DocumentFragment profile, int oldNumber,
5372: int columnNumber, Node[] miscNodes)
5373: throws javax.xml.transform.TransformerException {
5374: // calling method is (hopefully) synced
5375: if (columnNumber < oldNumber) {
5376: // remove columns and all coplets to the first one
5377: Node columnNode;
5378: Node firstColumn = DOMUtil
5379: .getSingleNode(
5380: profile,
5381: "profile/portal-profile/content/column[@position='1']/coplets",
5382: this .xpathProcessor);
5383: NodeList firstColumnCoplets = DOMUtil.getNodeListFromPath(
5384: firstColumn, new String[] { "coplet" });
5385: int copletsCount = (firstColumnCoplets == null ? 0
5386: : firstColumnCoplets.getLength());
5387: for (int i = columnNumber + 1; i <= oldNumber; i++) {
5388: columnNode = miscNodes[7 + i];
5389: if (columnNode != null) {
5390: NodeList coplets = DOMUtil.getNodeListFromPath(
5391: columnNode, new String[] { "coplets",
5392: "coplet" });
5393: Node coplet;
5394: if (coplets != null && coplets.getLength() > 0) {
5395: for (int m = 0; m < coplets.getLength(); m++) {
5396: coplet = coplets.item(m);
5397: coplet.getParentNode().removeChild(coplet);
5398: copletsCount++;
5399: ((Element) coplet).setAttributeNS(null,
5400: "position", "" + copletsCount);
5401: firstColumn.appendChild(coplet);
5402: }
5403: }
5404: columnNode.getParentNode().removeChild(columnNode);
5405: miscNodes[7 + i] = null;
5406: }
5407: }
5408: } else if (columnNumber <= PortalConstants.MAX_COLUMNS) {
5409: // add new columns
5410: Node contentNode = DOMUtil.getFirstNodeFromPath(profile,
5411: new String[] { "profile", "portal-profile",
5412: "content" }, false);
5413: Document doc = contentNode.getOwnerDocument();
5414: Element newColumn;
5415: Element el;
5416: for (int i = oldNumber + 1; i <= columnNumber; i++) {
5417: newColumn = doc.createElementNS(null, "column");
5418: newColumn.setAttributeNS(null, "position", "" + i);
5419: miscNodes[7 + i] = newColumn;
5420: contentNode.appendChild(newColumn);
5421: el = doc.createElementNS(null, "width");
5422: el.appendChild(doc.createTextNode("5%"));
5423: newColumn.appendChild(el);
5424: el = doc.createElementNS(null, "coplets");
5425: newColumn.appendChild(el);
5426: }
5427: }
5428: }
5429:
5430: /**
5431: * Send SAX events to the next pipeline component.
5432: * The node is parsed and the events are send to
5433: * the next component in the pipeline.
5434: * @param node The tree to be included.
5435: */
5436: protected void sendEvents(XMLConsumer consumer, Node node)
5437: throws SAXException {
5438: IncludeXMLConsumer.includeNode(node, consumer, consumer);
5439: }
5440:
5441: /**
5442: * Get all users in a document fragment with the following children:
5443: * <users>
5444: * <user>
5445: * <ID>...</ID>
5446: * <role>...</role> <!-- optional -->
5447: * <data>
5448: * ...
5449: * </data>
5450: * </user>
5451: * ....
5452: * </users>
5453: * The document fragment might contain further nodes at the root!
5454: * If <code>role</code> is <code>null</code> all users are fetched,
5455: * otherwise only the users for this role.
5456: * If also ID is not null only the single user is fetched.
5457: */
5458: private Document getUsers(String role, String ID)
5459: throws IOException, ProcessingException, SAXException {
5460: // calling method is syned
5461: if (this .getLogger().isDebugEnabled()) {
5462: this .getLogger().debug(
5463: "BEGIN getUsers role=" + role + ", ID=" + ID);
5464: }
5465: RequestState reqstate = this .getRequestState();
5466: Document frag = null;
5467: Configuration conf = reqstate
5468: .getModuleConfiguration("single-role-user-management");
5469: if (conf != null) {
5470:
5471: // get load-users resource (optional)
5472: Configuration child = conf.getChild("load-users", false);
5473: if (child != null) {
5474: String loadUsersResource = child.getAttribute("uri",
5475: null);
5476: SourceParameters loadUsersResourceParameters = SourceParameters
5477: .create(child);
5478:
5479: if (loadUsersResource != null) {
5480: SourceParameters parameters = (loadUsersResourceParameters == null) ? new SourceParameters()
5481:
5482: : loadUsersResourceParameters;
5483: if (reqstate.getApplicationName() != null)
5484: parameters.setSingleParameterValue(
5485: "application", reqstate
5486: .getApplicationName());
5487: if (ID != null) {
5488: parameters.setSingleParameterValue("type",
5489: "user");
5490: parameters.setSingleParameterValue("ID", ID);
5491: } else {
5492: parameters.setSingleParameterValue("type",
5493: "users");
5494: }
5495: if (role != null)
5496: parameters
5497: .setSingleParameterValue("role", role);
5498: frag = this .loadResource(loadUsersResource,
5499: parameters);
5500:
5501: }
5502: }
5503: }
5504:
5505: if (this .getLogger().isDebugEnabled()) {
5506: this
5507: .getLogger()
5508: .debug(
5509: "END getUsers fragment="
5510: + (frag == null ? "null"
5511: : XMLUtils
5512: .serializeNode(
5513: frag,
5514: XMLUtils
5515: .createPropertiesForXML(false))));
5516: }
5517: return frag;
5518: }
5519:
5520: /**
5521: * Get all roles in a document fragment with the following children:
5522: * <roles>
5523: * <role>...</role>
5524: * ....
5525: * </roles>
5526: * The document fragment might contain further nodes at the root!
5527: */
5528: private Document getRoles() throws IOException,
5529: ProcessingException, SAXException {
5530: // calling method is syned
5531: if (this .getLogger().isDebugEnabled()) {
5532: this .getLogger().debug("BEGIN getRoles");
5533: }
5534: Document frag = null;
5535:
5536: RequestState reqstate = this .getRequestState();
5537:
5538: Configuration conf = reqstate
5539: .getModuleConfiguration("single-role-user-management");
5540: if (conf != null) {
5541:
5542: // get load-roles resource (optional)
5543: Configuration child = conf.getChild("load-roles", false);
5544: if (child != null) {
5545: String loadRolesResource = child.getAttribute("uri",
5546: null);
5547: SourceParameters loadRolesResourceParameters = SourceParameters
5548: .create(child);
5549: if (loadRolesResource != null) {
5550: SourceParameters parameters = (loadRolesResourceParameters == null) ? new SourceParameters()
5551: : loadRolesResourceParameters;
5552: if (reqstate.getApplicationName() != null)
5553: parameters.setSingleParameterValue(
5554: "application", reqstate
5555: .getApplicationName());
5556: parameters.setSingleParameterValue("type", "roles");
5557: frag = this .loadResource(loadRolesResource,
5558: parameters);
5559: }
5560: }
5561: }
5562:
5563: if (this .getLogger().isDebugEnabled()) {
5564: this .getLogger().debug("END getRoles fragment=" + frag);
5565: }
5566: return frag;
5567: }
5568:
5569: /**
5570: * Load XML resource
5571: */
5572: private Document loadResource(String resource,
5573: SourceParameters parameters) throws IOException,
5574: ProcessingException, SAXException {
5575: Source source = null;
5576: try {
5577: source = SourceUtil.getSource(resource, null, parameters,
5578: this .resolver);
5579: return SourceUtil.toDOM(source);
5580: } catch (SourceException se) {
5581: throw SourceUtil.handle(se);
5582: } finally {
5583: this .resolver.release(source);
5584: }
5585: }
5586:
5587: /**
5588: * Get the SessionManager component
5589: */
5590: protected SessionManager getSessionManager()
5591: throws ProcessingException {
5592: if (this .sessionManager == null) {
5593: try {
5594: this .sessionManager = (SessionManager) this .manager
5595: .lookup(SessionManager.ROLE);
5596: } catch (ComponentException ce) {
5597: throw new ProcessingException(
5598: "Error during lookup of SessionManager component.",
5599: ce);
5600: }
5601: }
5602: return this .sessionManager;
5603: }
5604:
5605: /**
5606: * Get the ContextManager component
5607: */
5608: protected ContextManager getContextManager()
5609: throws ProcessingException {
5610: if (this .contextManager == null) {
5611: try {
5612: this .contextManager = (ContextManager) this .manager
5613: .lookup(ContextManager.ROLE);
5614: } catch (ComponentException ce) {
5615: throw new ProcessingException(
5616: "Error during lookup of ContextManager component.",
5617: ce);
5618: }
5619: }
5620: return this .contextManager;
5621: }
5622:
5623: /**
5624: * Get the ContextManager component
5625: */
5626: protected TransactionManager getTransactionManager()
5627: throws ProcessingException {
5628: if (this .transactionManager == null) {
5629: try {
5630: this .transactionManager = (TransactionManager) this .manager
5631: .lookup(TransactionManager.ROLE);
5632: } catch (ComponentException ce) {
5633: throw new ProcessingException(
5634: "Error during lookup of TransactionManager component.",
5635: ce);
5636: }
5637: }
5638: return this.transactionManager;
5639: }
5640:
5641: }
|