0001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
0002: * See license distributed with this file and
0003: * available online at http://www.uportal.org/license.html
0004: */
0005:
0006: package org.jasig.portal.channels;
0007:
0008: import java.util.ArrayList;
0009: import java.util.HashMap;
0010: import java.util.Iterator;
0011: import java.util.List;
0012: import java.util.Map;
0013:
0014: import org.jasig.portal.ChannelRegistryManager;
0015: import org.jasig.portal.ChannelRuntimeData;
0016: import org.jasig.portal.ChannelStaticData;
0017: import org.jasig.portal.GeneralRenderingException;
0018: import org.jasig.portal.IChannel;
0019: import org.jasig.portal.IServant;
0020: import org.jasig.portal.PortalException;
0021: import org.jasig.portal.channels.groupsmanager.CGroupsManagerServantFactory;
0022: import org.jasig.portal.groups.IGroupMember;
0023: import org.jasig.portal.security.IAuthorizationPrincipal;
0024: import org.jasig.portal.security.IPermissionManager;
0025: import org.jasig.portal.security.IPerson;
0026: import org.jasig.portal.services.AuthorizationService;
0027: import org.jasig.portal.services.EntityNameFinderService;
0028: import org.jasig.portal.services.GroupService;
0029: import org.jasig.portal.utils.DocumentFactory;
0030: import org.jasig.portal.utils.XSLT;
0031: import org.w3c.dom.Document;
0032: import org.w3c.dom.Element;
0033: import org.w3c.dom.Node;
0034: import org.xml.sax.ContentHandler;
0035:
0036: /**
0037: * CChannelManager is a Channel used to manage other Channels.
0038: * This is a replacement for CPublisher.
0039: *
0040: * @author Ken Weiner, kweiner@unicon.net
0041: * @version $Revision: 36001 $
0042: */
0043: public class CChannelManager extends BaseChannel {
0044:
0045: protected static final String sslLocation = "CChannelManager/CChannelManager.ssl";
0046: protected static final Document emptyDoc = DocumentFactory
0047: .getNewDocument();
0048: protected short state;
0049: protected static final short DEFAULT_STATE = 0;
0050: protected static final short CHANNEL_TYPE_STATE = 1;
0051: protected static final short GENERAL_SETTINGS_STATE = 2;
0052: protected static final short CUSTOM_SETTINGS_STATE = 3;
0053: protected static final short CHANNEL_DEF_STATE = 4;
0054: protected static final short CHANNEL_CONTROLS_STATE = 5;
0055: protected static final short CHANNEL_CATEGORIES_STATE = 6;
0056: protected static final short CHANNEL_GROUPS_STATE = 7;
0057: protected static final short CHANNEL_REVIEW_STATE = 8;
0058: protected static final short MODIFY_CHANNEL_STATE = 9;
0059: protected String action;
0060: protected String reset;
0061: protected String stepID;
0062: protected Document channelManagerDoc;
0063: protected ChannelDefinition channelDef = new ChannelDefinition();
0064: protected ModifyChannelSettings modChanSettings = new ModifyChannelSettings();
0065: protected IPerson person;
0066: protected IServant categoryServant;
0067: protected IServant groupServant;
0068: protected String errorMsg;
0069: protected String callingChannelActionUrl = null;
0070:
0071: // Called after publishing so that you won't see any previous settings
0072: // on the next publish attempt
0073: protected void resetSettings() {
0074: channelDef = new ChannelDefinition();
0075: modChanSettings = new ModifyChannelSettings();
0076: categoryServant = null;
0077: groupServant = null;
0078: errorMsg = null;
0079: }
0080:
0081: public void setStaticData(ChannelStaticData sd)
0082: throws PortalException {
0083: staticData = sd;
0084: person = sd.getPerson();
0085: }
0086:
0087: public void setRuntimeData(ChannelRuntimeData rd)
0088: throws PortalException {
0089: // see if we are running in delegate mode for admin navigation channel
0090: // if so then this url is used for all cancel button operations to
0091: // return to the admin nav channel.
0092: String caller = rd.getParameter("uPAN_caller");
0093:
0094: if (caller != null && !caller.equals(""))
0095: this .callingChannelActionUrl = rd.getFnameActionURL(caller);
0096:
0097: runtimeData = rd;
0098: action = runtimeData.getParameter("uPCM_action");
0099: // handle category selection servant
0100: if ((action != null && action.equals("selectCategories"))
0101: || (action == null && state == CHANNEL_CATEGORIES_STATE)) {
0102: action = "selectCategories";
0103: state = CHANNEL_CATEGORIES_STATE;
0104: ((IChannel) getCategoryServant()).setRuntimeData(rd);
0105: }
0106: // handle group selection servant
0107: if ((action != null && action.equals("selectGroups"))
0108: || (action == null && state == CHANNEL_GROUPS_STATE)) {
0109: action = "selectGroups";
0110: state = CHANNEL_GROUPS_STATE;
0111: ((IChannel) getGroupServant()).setRuntimeData(rd);
0112: }
0113: if (action != null && action.equals("selectChannelType")) {
0114: reset = runtimeData.getParameter("uPCM_reset");
0115: }
0116: // Capture information that the user entered on previous screen
0117: doCapture(); // Keep after "action = " because action might change inside doCapture()
0118: // Prepare the appropriate XML documents for the destination screen
0119: doAction();
0120: }
0121:
0122: public void renderXML(ContentHandler out) throws PortalException {
0123: XSLT xslt = XSLT.getTransformer(this , runtimeData.getLocales());
0124: xslt.setXML(channelManagerDoc);
0125: xslt.setXSL(sslLocation, runtimeData.getBrowserInfo());
0126: xslt.setTarget(out);
0127: xslt.setStylesheetParameter("baseActionURL", runtimeData
0128: .getBaseActionURL());
0129: xslt.setStylesheetParameter("stylesheetCacheSize", XSLT
0130: .getStylesheetCacheSize()
0131: + "");
0132:
0133: if (callingChannelActionUrl != null)
0134: xslt.setStylesheetParameter("callingChannelActionUrl",
0135: callingChannelActionUrl);
0136:
0137: String action = null;
0138: switch (state) {
0139: case DEFAULT_STATE:
0140: action = "none";
0141: break;
0142: case CHANNEL_TYPE_STATE:
0143: action = "selectChannelType";
0144: break;
0145: case GENERAL_SETTINGS_STATE:
0146: action = "selectGeneralSettings";
0147: break;
0148: case CUSTOM_SETTINGS_STATE:
0149: action = "customSettings";
0150: break;
0151: case CHANNEL_DEF_STATE:
0152: action = "channelDef";
0153: xslt.setStylesheetParameter("stepID", fixStepID(stepID));
0154: break;
0155: case CHANNEL_CONTROLS_STATE:
0156: action = "selectControls";
0157: break;
0158: case CHANNEL_CATEGORIES_STATE:
0159: action = "selectCategories";
0160: break;
0161: case CHANNEL_GROUPS_STATE:
0162: action = "selectGroups";
0163: break;
0164: case CHANNEL_REVIEW_STATE:
0165: action = "reviewChannel";
0166: if (errorMsg != null)
0167: xslt.setStylesheetParameter("errorMsg", errorMsg);
0168: errorMsg = null;
0169: break;
0170: case MODIFY_CHANNEL_STATE:
0171: action = "selectModifyChannel";
0172: break;
0173: default:
0174: action = "none";
0175: break;
0176: }
0177: xslt.setStylesheetParameter("action", action);
0178: xslt.transform();
0179: if (categoryServant != null
0180: && action.equals("selectCategories")) {
0181: ((IChannel) categoryServant).renderXML(out);
0182: xslt.setStylesheetParameter("action",
0183: "selectCategoriesButtons");
0184: xslt.transform();
0185: }
0186: if (groupServant != null && action.equals("selectGroups")) {
0187: ((IChannel) groupServant).renderXML(out);
0188: xslt
0189: .setStylesheetParameter("action",
0190: "selectGroupsButtons");
0191: xslt.transform();
0192: }
0193: }
0194:
0195: /**
0196: * Produces a group servant
0197: * @return the group servant
0198: */
0199: protected synchronized IServant getGroupServant() {
0200: if (groupServant == null) {
0201: try {
0202: // create the appropriate servant
0203: if (channelDef.ID == null) {
0204: groupServant = CGroupsManagerServantFactory
0205: .getGroupsServantforSelection(
0206: staticData,
0207: "Please select groups or people who should have access to this channel:",
0208: GroupService.EVERYONE, false, true);
0209: } else {
0210: IGroupMember[] members;
0211: IPermissionManager pm = AuthorizationService
0212: .instance().newPermissionManager(
0213: "UP_FRAMEWORK");
0214: IAuthorizationPrincipal[] prins = pm
0215: .getAuthorizedPrincipals("SUBSCRIBE",
0216: "CHAN_ID."
0217: + channelDef.ID
0218: .substring(4));
0219: members = new IGroupMember[prins.length];
0220: for (int mp = 0; mp < prins.length; mp++) {
0221: members[mp] = AuthorizationService.instance()
0222: .getGroupMember(prins[mp]);
0223: }
0224: groupServant = CGroupsManagerServantFactory
0225: .getGroupsServantforSelection(
0226: staticData,
0227: "Please select groups or people who should have access to this channel:",
0228: GroupService.EVERYONE, false, true,
0229: members);
0230: }
0231: ((IChannel) groupServant)
0232: .setRuntimeData((ChannelRuntimeData) runtimeData
0233: .clone());
0234: } catch (Exception e) {
0235: log.error(e, e);
0236: }
0237: log
0238: .debug("CChannelManager.getGroupServant(): created new servant");
0239: }
0240: return groupServant;
0241: }
0242:
0243: /**
0244: * Produces a category servant
0245: * @return the category servant
0246: */
0247: protected synchronized IServant getCategoryServant() {
0248: if (categoryServant == null) {
0249: try {
0250: if (channelDef.ID == null) {
0251: categoryServant = CGroupsManagerServantFactory
0252: .getGroupsServantforSelection(
0253: staticData,
0254: "Please select channel categories for this channel:",
0255: GroupService.CHANNEL_CATEGORIES,
0256: false, false);
0257: } else {
0258: IGroupMember this Chan = GroupService
0259: .getEntity(
0260: channelDef.ID.substring(4),
0261: Class
0262: .forName(GroupService.CHANNEL_CATEGORIES));
0263: categoryServant = CGroupsManagerServantFactory
0264: .getGroupsServantforGroupMemberships(
0265: this .staticData,
0266: "Please select channel categories for this channel:",
0267: this Chan, false);
0268: }
0269: ((IChannel) categoryServant)
0270: .setRuntimeData((ChannelRuntimeData) runtimeData
0271: .clone());
0272: } catch (Exception e) {
0273: log.error(e, e);
0274: }
0275: log
0276: .debug("CChannelManager.getCategoryServant(): created new servant");
0277: }
0278: return categoryServant;
0279: }
0280:
0281: /**
0282: * Make sure that the step ID is always a valid one
0283: * or else set it to "1"
0284: * @param stepID
0285: * @return the fixed step ID
0286: */
0287: private String fixStepID(String stepID) {
0288: if (stepID == null) {
0289: stepID = "1";
0290: } else {
0291: try {
0292: Integer.parseInt(stepID);
0293: } catch (java.lang.NumberFormatException nfe) {
0294: stepID = "1";
0295: }
0296: }
0297: return stepID;
0298: }
0299:
0300: /**
0301: * Collect the appropriate request parameters for a particular
0302: * screen in this channel's workflow.
0303: */
0304: protected void doCapture() {
0305: stepID = runtimeData.getParameter("uPCM_step");
0306: String capture = runtimeData.getParameter("uPCM_capture");
0307: if (capture != null) {
0308: // Channel types
0309: if (capture.equals("selectChannelType")) {
0310: String typeID = runtimeData.getParameter("ID");
0311: if (typeID != null) {
0312: if (!typeID.equals(channelDef.getTypeID())) {
0313: channelDef.setTypeID(typeID);
0314: channelDef.resetChannelControls();
0315: channelDef.removeParameters();
0316: }
0317: } else
0318: action = "selectChannelType";
0319: // General Settings (name and timeout)
0320: } else if (capture.equals("selectGeneralSettings")) {
0321: String name = runtimeData.getParameter("name");
0322: String fname = runtimeData.getParameter("fname");
0323: String description = runtimeData
0324: .getParameter("description");
0325: String title = runtimeData.getParameter("title");
0326: String timeout = runtimeData.getParameter("timeout");
0327: String javaClass = runtimeData.getParameter("class");
0328: String secure = runtimeData.getParameter("secure");
0329: if (name != null)
0330: channelDef.setName(name.trim());
0331: if (fname != null)
0332: channelDef.setFunctionalName(fname.trim());
0333: if (description != null)
0334: channelDef.setDescription(description.trim());
0335: if (title != null)
0336: channelDef.setTitle(title.trim());
0337: if (timeout != null)
0338: channelDef.setTimeout(timeout.trim());
0339: if (javaClass != null)
0340: channelDef.setJavaClass(javaClass.trim());
0341:
0342: channelDef.setIsSecure(secure != null ? "true"
0343: : "false");
0344: // Custom parameters
0345: } else if (capture.equals("customSettings")) {
0346: String subAction = runtimeData
0347: .getParameter("uPCM_subAction");
0348: if (subAction != null) {
0349: String name = runtimeData.getParameter("name");
0350: if (name != null)
0351: name = name.trim();
0352: // The name prefix appears when there are arbitrary parameters
0353: // that need the prefix to differentiate the arbitrary ones
0354: // from the non-arbitrary ones. For example, applet parameters
0355: // in CApplet get prefixed with "APPLET."
0356: String namePrefix = runtimeData
0357: .getParameter("uPCM_namePrefix");
0358: if (namePrefix != null)
0359: name = namePrefix + name;
0360: if (subAction.equals("addParameter")) {
0361: String value = runtimeData
0362: .getParameter("value");
0363: if (value != null)
0364: value = value.trim();
0365: String override = runtimeData
0366: .getParameter("override");
0367: channelDef.addParameter(name, value,
0368: (override != null ? "yes" : "no"));
0369: } else if (subAction.equals("deleteParameter")) {
0370: channelDef.removeParameter(name);
0371: }
0372: }
0373: // CPD parameters
0374: } else if (capture.equals("channelDef")) {
0375: Iterator iter = ((java.util.Hashtable) runtimeData)
0376: .keySet().iterator();
0377: while (iter.hasNext()) {
0378: String name = (String) iter.next();
0379: // Ignore parameters whose name starts with "uPCM_"
0380: if (name.startsWith("uPCM_"))
0381: continue;
0382: String value = runtimeData.getParameter(name);
0383: String override = runtimeData.getParameter("uPCM_"
0384: + name + "_sub");
0385: channelDef.addParameter(name, value,
0386: (override != null ? "yes" : "no"));
0387: }
0388: // Channel controls
0389: } else if (capture.equals("selectControls")) {
0390: String editable = runtimeData.getParameter("editable");
0391: channelDef.setEditable(editable != null ? "true"
0392: : "false");
0393: String hasHelp = runtimeData.getParameter("hasHelp");
0394: channelDef.setHasHelp(hasHelp != null ? "true"
0395: : "false");
0396: String hasAbout = runtimeData.getParameter("hasAbout");
0397: channelDef.setHasAbout(hasAbout != null ? "true"
0398: : "false");
0399: // Categories
0400: }
0401: }
0402: }
0403:
0404: /**
0405: * Controller method that reacts to the action parameter.
0406: * @exception PortalException
0407: */
0408: protected void doAction() throws PortalException {
0409: if (action != null) {
0410: if (action.equals("selectChannelType")) {
0411: // this will clear out any remnants of a prior
0412: // channel
0413: if (null != reset && reset.equals("true"))
0414: resetSettings();
0415: state = CHANNEL_TYPE_STATE;
0416: Workflow workflow = new Workflow();
0417: // Add channel types and channel def
0418: WorkflowSection chanTypeSection = new WorkflowSection(
0419: "selectChannelType");
0420: WorkflowStep step = new WorkflowStep("1",
0421: "Channel Type");
0422: step.addDataElement(ChannelRegistryManager
0423: .getChannelTypes().getDocumentElement());
0424: step.addDataElement(channelDef.toXML());
0425: chanTypeSection.addStep(step);
0426: workflow.setChannelTypesSection(chanTypeSection);
0427: channelManagerDoc = workflow.toXML();
0428: } else if (action.equals("selectGeneralSettings")) {
0429: state = GENERAL_SETTINGS_STATE;
0430: Workflow workflow = new Workflow();
0431: // Add General Settings section
0432: WorkflowSection gsSection = new WorkflowSection(
0433: "selectGeneralSettings");
0434: workflow.setGeneralSettingsSection(gsSection);
0435: WorkflowStep step = new WorkflowStep("1",
0436: "General Settings");
0437: step.addDataElement(channelDef.toXML());
0438: gsSection.addStep(step);
0439: channelManagerDoc = workflow.toXML();
0440: } else if (action.equals("channelParams")
0441: || action.equals("customSettings")
0442: || action.equals("channelDef")) {
0443: Workflow workflow = new Workflow();
0444: // Add CPD document if channel is "generic", otherwise custom settings
0445: if (channelDef.getTypeID().equals("-1")) {
0446: state = CUSTOM_SETTINGS_STATE;
0447: WorkflowSection csSection = new WorkflowSection(
0448: "customSettings");
0449: WorkflowStep step = new WorkflowStep("1",
0450: "Channel Parameters");
0451: step.addDataElement(channelDef.toXML());
0452: csSection.addStep(step);
0453: workflow.setChannelParamsSection(csSection);
0454: } else {
0455: state = CHANNEL_DEF_STATE;
0456: CPDWorkflowSection cpdSection = new CPDWorkflowSection(
0457: channelDef.getTypeID());
0458: cpdSection.addToStep(channelDef.toXML(),
0459: fixStepID(stepID));
0460: workflow.setChannelParamsSection(cpdSection);
0461: }
0462: channelManagerDoc = workflow.toXML();
0463: } else if (action.equals("selectControls")) {
0464: state = CHANNEL_CONTROLS_STATE;
0465: Workflow workflow = new Workflow();
0466: // Add controlsSection
0467: WorkflowSection controlsSection = new WorkflowSection(
0468: "selectControls");
0469: if (channelDef.getEditable() == null) // if one is null, they are all null
0470: channelDef.resetChannelControls();
0471: WorkflowStep step = new WorkflowStep("1",
0472: "Channel Controls");
0473: step.addDataElement(channelDef.toXML());
0474: controlsSection.addStep(step);
0475: workflow.setControlsSection(controlsSection);
0476: channelManagerDoc = workflow.toXML();
0477: } else if (action.equals("reviewChannel")) {
0478: state = CHANNEL_REVIEW_STATE;
0479: Workflow workflow = new Workflow();
0480: // Channel types
0481: WorkflowSection ctSection = new WorkflowSection(
0482: "selectChannelType");
0483: WorkflowStep ctStep = new WorkflowStep("1",
0484: "Channel Type");
0485: ctStep.addDataElement(ChannelRegistryManager
0486: .getChannelTypes().getDocumentElement());
0487: ctSection.addStep(ctStep);
0488: workflow.setChannelTypesSection(ctSection);
0489: // Selected categories
0490: WorkflowSection regSection = new WorkflowSection(
0491: "selectCategories");
0492: WorkflowStep regStep = new WorkflowStep("1",
0493: "Categories");
0494: regStep.addDataElement(getCategoriesXML());
0495: regSection.addStep(regStep);
0496: workflow.setCategoriesSection(regSection);
0497: // Selected groups
0498: WorkflowSection groupsSection = new WorkflowSection(
0499: "selectGroups");
0500: WorkflowStep groupsStep = new WorkflowStep("1",
0501: "Groups");
0502: groupsStep.addDataElement(getGroupsXML());
0503: groupsSection.addStep(groupsStep);
0504: workflow.setGroupsSection(groupsSection);
0505: // Review (with channel definition)
0506: WorkflowSection reviewSection = new WorkflowSection(
0507: "reviewChannel");
0508: WorkflowStep step = new WorkflowStep("1", "Review");
0509: step.addDataElement(channelDef.toXML());
0510: reviewSection.addStep(step);
0511: workflow.setReviewSection(reviewSection);
0512: channelManagerDoc = workflow.toXML();
0513: } else if (action.equals("finished")) {
0514: state = DEFAULT_STATE; // we need to add a confirmation and channel preview screen
0515: // collect select channel categories
0516: String[] catIDs;
0517: IGroupMember[] ctgs = (IGroupMember[]) getCategoryServant()
0518: .getResults();
0519: // If no categories were selected, return to review screen.
0520: if (ctgs.length == 0) {
0521: action = "reviewChannel";
0522: errorMsg = "NO_CATEGORIES";
0523: doAction();
0524: return;
0525: }
0526: catIDs = new String[ctgs.length];
0527: for (int c = 0; c < ctgs.length; c++) {
0528: catIDs[c] = ctgs[c].getKey();
0529: }
0530: // collect groups and/or people that can subscribe
0531: IGroupMember[] groupMembers = (IGroupMember[]) getGroupServant()
0532: .getResults();
0533: if (groupMembers.length == 0) {
0534: action = "reviewChannel";
0535: errorMsg = "NO_GROUP_MEMBERS";
0536: doAction();
0537: return;
0538: }
0539: try {
0540: Element channelE = channelDef.toXML();
0541: ChannelRegistryManager.publishChannel(channelE,
0542: catIDs, groupMembers, person);
0543: resetSettings();
0544:
0545: // see if we are running in delegate mode from the admin
0546: // navigation channel. If so then we don't return to the
0547: // default state showing the "modify existing channel" and
0548: // "publish new channel" links. Instead, go to the modify
0549: // existing state showing he list of available channels
0550: // including the one that was just published. Then the
0551: // user can select the cancel link there to return to the
0552: // admin navigation channel.
0553: if (this .callingChannelActionUrl != null) {
0554: state = MODIFY_CHANNEL_STATE;
0555: channelManagerDoc = getChannelManagerDoc(modChanSettings);
0556: }
0557: } catch (Exception e) {
0558: // Need to revisit this and handle the error!
0559: throw new PortalException(e);
0560: }
0561: } else if (action.equals("selectModifyChannel")) {
0562: state = MODIFY_CHANNEL_STATE;
0563: channelManagerDoc = getChannelManagerDoc(modChanSettings);
0564: } else if (action.equals("changePage")) {
0565: String newPage = runtimeData.getParameter("newPage");
0566: if (newPage != null) {
0567: modChanSettings.setCurrentPage(newPage);
0568: channelManagerDoc = getChannelManagerDoc(modChanSettings);
0569: }
0570: } else if (action.equals("changeRecordsPerPage")) {
0571: String recordsPerPage = runtimeData
0572: .getParameter("recordsPerPage");
0573: if (recordsPerPage != null) {
0574: // Figure out what page we should be on based on the change in records per page.
0575: try {
0576: int oldPage = Integer.parseInt(modChanSettings
0577: .getCurrentPage());
0578: int oldRecordsPerPage = Integer
0579: .parseInt(modChanSettings
0580: .getRecordsPerPage());
0581: int recsPerPage = Integer
0582: .parseInt(recordsPerPage);
0583: if (recsPerPage > 0
0584: && recsPerPage != oldRecordsPerPage) {
0585: // Thanks to jweight@campuspipeline.com for the following formula:
0586: String newPage = String
0587: .valueOf(((((oldPage - 1) * oldRecordsPerPage) + 1)
0588: / (recsPerPage) + 1));
0589: modChanSettings.setCurrentPage(newPage);
0590: modChanSettings
0591: .setRecordsPerPage(recordsPerPage);
0592: channelManagerDoc = getChannelManagerDoc(modChanSettings);
0593: }
0594: } catch (NumberFormatException nfe) {
0595: // do nothing here, just leave the current page as is.
0596: }
0597: }
0598: } else if (action.equals("filterByCategory")) {
0599: String filterByID = runtimeData
0600: .getParameter("newCategory");
0601: if (filterByID != null) {
0602: // User may be beyond the last page of this filtered set so put them back on page 1.
0603: modChanSettings.setCurrentPage("1");
0604: modChanSettings.setFilterByID(filterByID);
0605: channelManagerDoc = getChannelManagerDoc(modChanSettings);
0606: }
0607: } else if (action.equals("editChannelSettings")) {
0608: resetSettings(); // so previous chan views don't appear in workflow
0609: String str_channelPublishId = runtimeData
0610: .getParameter("channelID");
0611: // Set the channel definition
0612: channelDef.setChannelDefinition(ChannelRegistryManager
0613: .getChannel(str_channelPublishId));
0614: action = "reviewChannel";
0615: doAction();
0616: } else if (action.equals("removePublishedChannel")) {
0617: String channelPublishId = runtimeData
0618: .getParameter("channelID");
0619: if (channelPublishId != null) {
0620: try {
0621: ChannelRegistryManager.removeChannel(
0622: channelPublishId, person);
0623: } catch (Exception e) {
0624: throw new GeneralRenderingException(e);
0625: }
0626: }
0627: channelManagerDoc = getChannelManagerDoc(modChanSettings);
0628: }
0629:
0630: else if (action.equals("purgeStylesheetCache")) {
0631: state = DEFAULT_STATE;
0632: XSLT.purgeStylesheetCache();
0633: action = null;
0634: }
0635:
0636: }
0637: if (action == null || action.equals("cancel")) {
0638: state = DEFAULT_STATE;
0639: channelManagerDoc = emptyDoc;
0640: channelDef = new ChannelDefinition();
0641: categoryServant = null;
0642: groupServant = null;
0643: }
0644: }
0645:
0646: /**
0647: * Produces an XML document used as an input to
0648: * this channel's XSLT transformation.
0649: * @param modChanSettings
0650: * @return
0651: * @exception PortalException
0652: */
0653: protected Document getChannelManagerDoc(
0654: ModifyChannelSettings modChanSettings)
0655: throws PortalException {
0656: Document channelManagerDoc = DocumentFactory.getNewDocument();
0657: // Add the top level <manageChannels> to the document
0658: Element channelManager = channelManagerDoc
0659: .createElement("manageChannels");
0660: channelManagerDoc.appendChild(channelManager);
0661: // Get the channel registry
0662: Document channelRegistryDoc = ChannelRegistryManager
0663: .getChannelRegistry();
0664: // Set the registry ID attribute to "-1"
0665: Element registry = channelRegistryDoc.getDocumentElement();
0666: registry.setAttribute("ID", "-1");
0667: // Add the <registry> to <manageChannels>
0668: Element channelRegistry = (Element) channelManagerDoc
0669: .importNode(channelRegistryDoc.getDocumentElement(),
0670: true);
0671: channelManager.appendChild(channelRegistry);
0672: // Add a <userSettings> fragment to <manageChannels>
0673: appendModifyChannelSettings(channelManager, modChanSettings);
0674: return channelManagerDoc;
0675: }
0676:
0677: protected Element getGroupsXML() {
0678: Element el = emptyDoc.createElement("userSettings");
0679: Element browsingGroupE = emptyDoc
0680: .createElement("browsingGroup");
0681: browsingGroupE.appendChild(emptyDoc.createTextNode("top"));
0682: el.appendChild(browsingGroupE);
0683: IGroupMember[] gms = (IGroupMember[]) getGroupServant()
0684: .getResults();
0685: // Add selected groups if there are any
0686: if (gms != null && gms.length > 0) {
0687: Element selectedGroupsE = emptyDoc
0688: .createElement("selectedGroups");
0689: try {
0690: for (int c = 0; c < gms.length; c++) {
0691: Element selectedGroupE = emptyDoc
0692: .createElement("selectedGroup");
0693: selectedGroupE.setAttribute("name",
0694: EntityNameFinderService.instance()
0695: .getNameFinder(gms[c].getType())
0696: .getName(gms[c].getKey()));
0697: selectedGroupE.appendChild(emptyDoc
0698: .createTextNode(gms[c].getKey()));
0699: selectedGroupsE.appendChild(selectedGroupE);
0700: }
0701: } catch (Exception e) {
0702: log.error(e, e);
0703: }
0704: el.appendChild(selectedGroupsE);
0705: }
0706: return el;
0707: }
0708:
0709: protected Element getCategoriesXML() {
0710: Element userSettingsE = emptyDoc.createElement("userSettings");
0711: Element browsingCategoryE = emptyDoc
0712: .createElement("browsingCategory");
0713: browsingCategoryE.appendChild(emptyDoc.createTextNode("top"));
0714: userSettingsE.appendChild(browsingCategoryE);
0715: IGroupMember[] gms = (IGroupMember[]) getCategoryServant()
0716: .getResults();
0717: // Add selected categories if there are any
0718: if (gms != null && gms.length > 0) {
0719: Element selectedCategoriesE = emptyDoc
0720: .createElement("selectedCategories");
0721: try {
0722: for (int c = 0; c < gms.length; c++) {
0723: Element selectedCategoryE = emptyDoc
0724: .createElement("selectedCategory");
0725: selectedCategoryE.setAttribute("name",
0726: EntityNameFinderService.instance()
0727: .getNameFinder(gms[c].getType())
0728: .getName(gms[c].getKey()));
0729: selectedCategoryE.appendChild(emptyDoc
0730: .createTextNode((gms[c].getKey())));
0731: selectedCategoriesE.appendChild(selectedCategoryE);
0732: }
0733: } catch (Exception e) {
0734: log.error(e, e);
0735: }
0736: userSettingsE.appendChild(selectedCategoriesE);
0737: }
0738: return userSettingsE;
0739: }
0740:
0741: protected static void appendModifyChannelSettings(
0742: Element channelManager,
0743: ModifyChannelSettings modChanSettings) {
0744: Document doc = channelManager.getOwnerDocument();
0745: Element userSettingsE = doc.createElement("userSettings");
0746: Element modifyView = doc.createElement("modifyView");
0747: userSettingsE.appendChild(modifyView);
0748: Element recordsPerPageE = doc.createElement("recordsPerPage");
0749: recordsPerPageE.appendChild(doc.createTextNode(modChanSettings
0750: .getRecordsPerPage()));
0751: modifyView.appendChild(recordsPerPageE);
0752: Element currentPageE = doc.createElement("currentPage");
0753: currentPageE.appendChild(doc.createTextNode(modChanSettings
0754: .getCurrentPage()));
0755: modifyView.appendChild(currentPageE);
0756: Element filterByIDE = doc.createElement("filterByID");
0757: filterByIDE.appendChild(doc.createTextNode(modChanSettings
0758: .getFilterByID()));
0759: modifyView.appendChild(filterByIDE);
0760: channelManager.appendChild(userSettingsE);
0761: }
0762:
0763: /**
0764: * Keeps track of page settings for MODIFY_CHANNEL_STATE
0765: */
0766: protected class ModifyChannelSettings {
0767: private String recordsPerPage;
0768: private String currentPage;
0769: private String filterByID;
0770:
0771: /**
0772: * put your documentation comment here
0773: */
0774: protected ModifyChannelSettings() {
0775: recordsPerPage = "15";
0776: currentPage = "1";
0777: filterByID = "-1";
0778: }
0779:
0780: // Accessor methods
0781: protected String getRecordsPerPage() {
0782: return recordsPerPage;
0783: }
0784:
0785: protected String getCurrentPage() {
0786: return currentPage;
0787: }
0788:
0789: protected String getFilterByID() {
0790: return filterByID;
0791: }
0792:
0793: protected void setRecordsPerPage(String recordsPerPage) {
0794: this .recordsPerPage = recordsPerPage;
0795: }
0796:
0797: protected void setCurrentPage(String currentPage) {
0798: this .currentPage = currentPage;
0799: }
0800:
0801: protected void setFilterByID(String filterByID) {
0802: this .filterByID = filterByID;
0803: }
0804: }
0805:
0806: /**
0807: * <p>This Workflow class represents the collection of workflow sections and can
0808: * produce an XML version of itself for passing to the XSLT stylesheets. When a
0809: * particular section is not explicitly set, a minimal XML fragment will still
0810: * be included so that the channel can render the workflow sections at the top.
0811: * The channel parameters section is included every time except when the channel
0812: * type is not known.</p>
0813: */
0814: protected class Workflow {
0815: protected WorkflowSection channelTypesSection;
0816: protected WorkflowSection generalSettingsSection;
0817: protected WorkflowSection channelParamsSection;
0818: protected WorkflowSection controlsSection;
0819: protected WorkflowSection categoriesSection;
0820: protected WorkflowSection groupsSection;
0821: protected WorkflowSection reviewSection;
0822:
0823: protected void setChannelTypesSection(
0824: WorkflowSection channelTypesSection) {
0825: this .channelTypesSection = channelTypesSection;
0826: }
0827:
0828: protected void setGeneralSettingsSection(
0829: WorkflowSection generalSettingsSection) {
0830: this .generalSettingsSection = generalSettingsSection;
0831: }
0832:
0833: protected void setChannelParamsSection(
0834: WorkflowSection channelParamsSection) {
0835: this .channelParamsSection = channelParamsSection;
0836: }
0837:
0838: protected void setControlsSection(
0839: WorkflowSection controlsSection) {
0840: this .controlsSection = controlsSection;
0841: }
0842:
0843: protected void setCategoriesSection(
0844: WorkflowSection categoriesSection) {
0845: this .categoriesSection = categoriesSection;
0846: }
0847:
0848: protected void setGroupsSection(WorkflowSection groupsSection) {
0849: this .groupsSection = groupsSection;
0850: }
0851:
0852: protected void setReviewSection(WorkflowSection reviewSection) {
0853: this .reviewSection = reviewSection;
0854: }
0855:
0856: protected Document toXML() throws PortalException {
0857: Document doc = DocumentFactory.getNewDocument();
0858: // Add the top level <manageChannels> to the document
0859: Element channelManagerE = doc
0860: .createElement("manageChannels");
0861: doc.appendChild(channelManagerE);
0862: // Add all the sections
0863: addSection(channelTypesSection, "selectChannelType",
0864: "Channel Type", channelManagerE);
0865: addSection(generalSettingsSection, "selectGeneralSettings",
0866: "General Settings", channelManagerE);
0867: addChannelParamsSection(channelManagerE);
0868: addSection(controlsSection, "selectControls",
0869: "Channel Controls", channelManagerE);
0870: addSection(categoriesSection, "selectCategories",
0871: "Categories", channelManagerE);
0872: addSection(groupsSection, "selectGroups", "Groups",
0873: channelManagerE);
0874: addSection(reviewSection, "reviewChannel", "Review",
0875: channelManagerE);
0876: return doc;
0877: }
0878:
0879: private void addSection(WorkflowSection section,
0880: String sectionElementName, String stepTitle, Element e) {
0881: // For sections that haven't been set, add an empty one with one step
0882: if (section == null) {
0883: section = new WorkflowSection(sectionElementName);
0884: section.addStep(new WorkflowStep("1", stepTitle));
0885: }
0886: e.appendChild(section.toXML(e.getOwnerDocument()));
0887: }
0888:
0889: private void addChannelParamsSection(Element e)
0890: throws PortalException {
0891: if (channelParamsSection == null) {
0892: // Add CPD document if channel is "generic", otherwise custom settings
0893: String channelTypeID = channelDef.getTypeID();
0894: if (channelTypeID != null) {
0895: if (channelTypeID.equals("-1")) {
0896: WorkflowSection csSection = new WorkflowSection(
0897: "customSettings");
0898: WorkflowStep step = new WorkflowStep("1",
0899: "Channel Parameters");
0900: csSection.addStep(step);
0901: setChannelParamsSection(csSection);
0902: } else {
0903: CPDWorkflowSection cpdSection = new CPDWorkflowSection(
0904: channelDef.getTypeID());
0905: setChannelParamsSection(cpdSection);
0906: }
0907: } else {
0908: return;
0909: }
0910: }
0911: e.appendChild(channelParamsSection.toXML(e
0912: .getOwnerDocument()));
0913: }
0914: }
0915:
0916: protected class WorkflowSection {
0917: protected String name;
0918: protected List steps;
0919:
0920: protected WorkflowSection() {
0921: }
0922:
0923: protected WorkflowSection(String name) {
0924: this .name = name;
0925: steps = new ArrayList();
0926: }
0927:
0928: protected void setName(String name) {
0929: this .name = name;
0930: }
0931:
0932: protected void addStep(WorkflowStep step) {
0933: steps.add(step);
0934: }
0935:
0936: protected Element toXML(Document doc) {
0937: // Add this step's workflow element
0938: Element sectionE = doc.createElement(name);
0939: // Add the <params> element
0940: Element paramsE = doc.createElement("params");
0941: sectionE.appendChild(paramsE);
0942: // Add all the <step> elements
0943: Iterator iter = steps.iterator();
0944: while (iter.hasNext()) {
0945: WorkflowStep step = (WorkflowStep) iter.next();
0946: paramsE.appendChild(step.toXML(doc));
0947: }
0948: return sectionE;
0949: }
0950: }
0951:
0952: protected class CPDWorkflowSection extends WorkflowSection {
0953: protected Document cpdDoc;
0954:
0955: protected CPDWorkflowSection(String chanTypeID)
0956: throws PortalException {
0957: super ();
0958: cpdDoc = ChannelRegistryManager.getCPD(chanTypeID);
0959: }
0960:
0961: protected void addToStep(Element element, String stepID) {
0962: for (Node n1 = cpdDoc.getDocumentElement().getFirstChild(); n1 != null; n1 = n1
0963: .getNextSibling()) {
0964: if (n1.getNodeType() == Node.ELEMENT_NODE
0965: && n1.getNodeName().equals("params")) {
0966: for (Node n2 = n1.getFirstChild(); n2 != null; n2 = n2
0967: .getNextSibling()) {
0968: if (n2.getNodeType() == Node.ELEMENT_NODE
0969: && n2.getNodeName().equals("step")) {
0970: for (Node n3 = n2.getFirstChild(); n3 != null; n3 = n3
0971: .getNextSibling()) {
0972: if (n3.getNodeType() == Node.ELEMENT_NODE
0973: && n3.getNodeName()
0974: .equals("ID")) {
0975: for (Node n4 = n3.getFirstChild(); n4 != null; n4 = n4
0976: .getNextSibling()) {
0977: if (n4.getNodeType() == Node.TEXT_NODE) {
0978: String ID = n4
0979: .getNodeValue();
0980: if (ID.equals(stepID)) {
0981: n2
0982: .appendChild(cpdDoc
0983: .importNode(
0984: element,
0985: true));
0986: break;
0987: }
0988: }
0989: }
0990: }
0991: }
0992: }
0993: }
0994: }
0995: }
0996: }
0997:
0998: protected Element toXML(Document doc) {
0999: return (Element) doc.importNode(
1000: cpdDoc.getDocumentElement(), true);
1001: }
1002: }
1003:
1004: protected class WorkflowStep {
1005: protected String ID;
1006: protected String name;
1007: protected List dataElements;
1008:
1009: protected WorkflowStep(String ID, String name) {
1010: this .ID = ID;
1011: this .name = name;
1012: this .dataElements = new ArrayList();
1013: }
1014:
1015: // Accessor methods
1016: protected String getID() {
1017: return ID;
1018: }
1019:
1020: protected String getName() {
1021: return name;
1022: }
1023:
1024: protected void setID(String ID) {
1025: this .ID = ID;
1026: }
1027:
1028: protected void setName(String name) {
1029: this .name = name;
1030: }
1031:
1032: protected void addDataElement(Element dataElement) {
1033: this .dataElements.add(dataElement);
1034: }
1035:
1036: protected Element toXML(Document doc) {
1037: Element stepE = doc.createElement("step");
1038: Element IDE = doc.createElement("ID");
1039: IDE.appendChild(doc.createTextNode(ID));
1040: stepE.appendChild(IDE);
1041: Element nameE = doc.createElement("name");
1042: nameE.appendChild(doc.createTextNode(name));
1043: stepE.appendChild(nameE);
1044: Iterator iter = dataElements.iterator();
1045: while (iter.hasNext()) {
1046: stepE.appendChild(doc.importNode((Element) iter.next(),
1047: true));
1048: }
1049: return stepE;
1050: }
1051: }
1052:
1053: protected class ChannelDefinition {
1054: private static final String DEFAULT_TIMEOUT = "5000";
1055:
1056: protected String ID;
1057: protected String typeID;
1058: protected String name;
1059: protected String description;
1060: protected String title;
1061: protected String timeout = DEFAULT_TIMEOUT;
1062: protected String fname;
1063: protected String javaClass;
1064: protected String editable;
1065: protected String hasHelp;
1066: protected String hasAbout;
1067: protected String secure;
1068: protected Map parameters;
1069:
1070: protected class Parameter {
1071: protected String name;
1072: protected String value;
1073: protected String override; // "yes" or "no"
1074:
1075: protected Parameter(String name, String value,
1076: String override) {
1077: this .name = name;
1078: this .value = value;
1079: this .override = override;
1080: }
1081:
1082: protected String getName() {
1083: return name;
1084: }
1085:
1086: protected String getValue() {
1087: return value;
1088: }
1089:
1090: protected String getOverride() {
1091: return override;
1092: }
1093:
1094: protected void setName(String name) {
1095: this .name = name;
1096: }
1097:
1098: protected void setValue(String value) {
1099: this .value = value;
1100: }
1101:
1102: protected void setOverride(String override) {
1103: this .override = override;
1104: }
1105: }
1106:
1107: protected ChannelDefinition() {
1108: parameters = new HashMap();
1109: }
1110:
1111: protected String getTypeID() {
1112: return typeID;
1113: }
1114:
1115: protected String getEditable() {
1116: return editable;
1117: }
1118:
1119: protected String getHasHelp() {
1120: return hasHelp;
1121: }
1122:
1123: protected String getHasAbout() {
1124: return hasAbout;
1125: }
1126:
1127: protected String isSecure() {
1128: return secure;
1129: }
1130:
1131: protected void setTypeID(String typeID) {
1132: this .typeID = typeID;
1133: }
1134:
1135: protected void setName(String name) {
1136: this .name = name;
1137: }
1138:
1139: protected void setFunctionalName(String fname) {
1140: this .fname = fname;
1141: }
1142:
1143: protected void setDescription(String description) {
1144: this .description = description;
1145: }
1146:
1147: protected void setTitle(String title) {
1148: this .title = title;
1149: }
1150:
1151: /**
1152: * Set the channel timeout, which is a String representation of a number
1153: * of milliseconds the channel should be allowed to try to render before being
1154: * replaced with the Error channel.
1155: * This setter checks its argument and does nothing but log the irregularity
1156: * in the case where the argument does not represent a positive number of
1157: * milliseconds.
1158: * @param timeout a String representing a positive number of milliseconds
1159: */
1160: protected void setTimeout(String timeout) {
1161: if (timeout != null && !"".equals(timeout)) {
1162: try {
1163: int timeoutInt = Integer.parseInt(timeout);
1164: if (timeoutInt > 0) {
1165: this .timeout = timeout;
1166: } else {
1167: log
1168: .warn("There was an attempt to set a channel timeout to ["
1169: + timeout
1170: + "] but we blocked it because you can't have a negative timeout.");
1171: }
1172:
1173: } catch (Throwable t) {
1174: log
1175: .warn("There was an attempt to set a channel timeout to ["
1176: + timeout
1177: + "] but we blocked it because it was invalid.");
1178: }
1179: }
1180: }
1181:
1182: protected void setJavaClass(String javaClass) {
1183: this .javaClass = javaClass;
1184: }
1185:
1186: protected void setEditable(String editable) {
1187: this .editable = editable;
1188: }
1189:
1190: protected void setHasHelp(String hasHelp) {
1191: this .hasHelp = hasHelp;
1192: }
1193:
1194: protected void setHasAbout(String hasAbout) {
1195: this .hasAbout = hasAbout;
1196: }
1197:
1198: /**
1199: * Sets channel secure setting.
1200: * @param secure 'true' or 'false'
1201: */
1202: protected void setIsSecure(String secure) {
1203: this .secure = secure;
1204: }
1205:
1206: private void setAttribute(Element e, String attName,
1207: String attVal) {
1208: // Only set the attribute if it has a non-null value
1209: if (attVal != null)
1210: e.setAttribute(attName, attVal);
1211: }
1212:
1213: protected void addParameter(String name, String value,
1214: String modType) {
1215: parameters.put(name, new Parameter(name, value, modType));
1216: }
1217:
1218: protected void removeParameter(String name) {
1219: parameters.remove(name);
1220: }
1221:
1222: protected void removeParameters() {
1223: parameters = new HashMap();
1224: }
1225:
1226: protected void resetChannelControls() {
1227: try {
1228: // Look inside CPD for controls.
1229: Document cpdDoc = ChannelRegistryManager.getCPD(typeID);
1230: if (cpdDoc != null) {
1231: for (Node n1 = cpdDoc.getDocumentElement()
1232: .getFirstChild(); n1 != null; n1 = n1
1233: .getNextSibling()) {
1234: if (n1.getNodeType() == Node.ELEMENT_NODE
1235: && n1.getNodeName().equals("controls")) {
1236: for (Node n2 = n1.getFirstChild(); n2 != null; n2 = n2
1237: .getNextSibling()) {
1238: if (n2.getNodeType() == Node.ELEMENT_NODE
1239: && n2.getNodeName().equals(
1240: "control")) {
1241: Element control = (Element) n2;
1242: String type = control
1243: .getAttribute("type");
1244: if (type != null) {
1245: if (type.equals("edit")) {
1246: String editAtt = control
1247: .getAttribute("include");
1248: editable = editAtt != null
1249: && editAtt
1250: .equals("yes") ? "true"
1251: : "false";
1252: } else if (type.equals("about")) {
1253: String aboutAtt = control
1254: .getAttribute("include");
1255: hasAbout = aboutAtt != null
1256: && aboutAtt
1257: .equals("yes") ? "true"
1258: : "false";
1259: } else if (type.equals("help")) {
1260: String helpAtt = control
1261: .getAttribute("include");
1262: hasHelp = helpAtt != null
1263: && helpAtt
1264: .equals("yes") ? "true"
1265: : "false";
1266: }
1267: }
1268: }
1269: }
1270: }
1271: }
1272: }
1273: } catch (PortalException pe) {
1274: // Unable to open CPDDoc, just leave values uninitialized
1275: log.warn(pe, pe);
1276: }
1277: }
1278:
1279: protected void setChannelDefinition(Element channelE)
1280: throws PortalException {
1281: ID = channelE.getAttribute("ID");
1282: typeID = channelE.getAttribute("typeID");
1283: name = channelE.getAttribute("name");
1284: description = channelE.getAttribute("description");
1285: title = channelE.getAttribute("title");
1286: timeout = channelE.getAttribute("timeout");
1287: fname = channelE.getAttribute("fname");
1288: javaClass = channelE.getAttribute("class");
1289: editable = channelE.getAttribute("editable");
1290: hasHelp = channelE.getAttribute("hasHelp");
1291: hasAbout = channelE.getAttribute("hasAbout");
1292: secure = channelE.getAttribute("secure");
1293: for (Node n = channelE.getFirstChild(); n != null; n = n
1294: .getNextSibling()) {
1295: if (n.getNodeType() == Node.ELEMENT_NODE
1296: && n.getNodeName().equals("parameter")) {
1297: Element parameterE = (Element) n;
1298: String name = parameterE.getAttribute("name");
1299: String value = parameterE.getAttribute("value");
1300: String override = parameterE
1301: .getAttribute("override");
1302: parameters.put(name, new Parameter(name, value,
1303: override));
1304: }
1305: }
1306: }
1307:
1308: protected Element toXML() {
1309: Element channelE = emptyDoc.createElement("channel");
1310: setAttribute(channelE, "ID", ID);
1311: setAttribute(channelE, "typeID", typeID);
1312: setAttribute(channelE, "name", name);
1313: setAttribute(channelE, "description", description);
1314: setAttribute(channelE, "title", title);
1315: setAttribute(channelE, "fname", fname);
1316: setAttribute(channelE, "class", javaClass);
1317: setAttribute(channelE, "timeout", timeout);
1318: setAttribute(channelE, "editable", editable);
1319: setAttribute(channelE, "hasAbout", hasAbout);
1320: setAttribute(channelE, "hasHelp", hasHelp);
1321: setAttribute(channelE, "secure", secure);
1322: Iterator iter = parameters.keySet().iterator();
1323: while (iter.hasNext()) {
1324: String name = (String) iter.next();
1325: Parameter param = (Parameter) parameters.get(name);
1326: Element parameterE = emptyDoc
1327: .createElement("parameter");
1328: parameterE.setAttribute("name", param.getName());
1329: parameterE.setAttribute("value", param.getValue());
1330: parameterE
1331: .setAttribute("override", param.getOverride());
1332: channelE.appendChild(parameterE);
1333: }
1334: return channelE;
1335: }
1336: }
1337: }
|