001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.pluto.driver.portlets;
018:
019: import org.apache.commons.io.FileUtils;
020: import org.apache.commons.logging.Log;
021: import org.apache.commons.logging.LogFactory;
022: import org.apache.pluto.driver.AttributeKeys;
023: import org.apache.pluto.driver.PortalDriverServlet;
024: import org.apache.pluto.driver.config.DriverConfiguration;
025: import org.apache.pluto.driver.services.portal.PageConfig;
026: import org.apache.pluto.driver.services.portal.PortletWindowConfig;
027: import org.apache.pluto.driver.services.portal.RenderConfigService;
028:
029: import javax.portlet.ActionRequest;
030: import javax.portlet.ActionResponse;
031: import javax.portlet.PortletException;
032: import javax.portlet.RenderRequest;
033: import javax.portlet.RenderResponse;
034:
035: import java.io.File;
036: import java.io.IOException;
037: import java.util.ArrayList;
038: import java.util.Collection;
039: import java.util.Iterator;
040:
041: public class PageAdminPortlet extends GenericPlutoPortlet {
042:
043: private static final Log LOG = LogFactory
044: .getLog(PageAdminPortlet.class);
045: private static final String JSP_DIR = "/WEB-INF/fragments/admin/page/";
046: private static final String VIEW_PAGE = JSP_DIR + "view.jsp";
047: private static final String EDIT_PAGE = JSP_DIR + "edit.jsp";
048: private static final String HELP_PAGE = JSP_DIR + "help.jsp";
049:
050: private static final String CONFIG_FILE_PATH = "/WEB-INF/pluto-portal-driver-config.xml";
051: /** Token used to search for default page value in config file */
052: private static final String RENDER_CONFIG_SEARCH_TOKEN = "<render-config default=\"";
053:
054: public void processAction(ActionRequest request,
055: ActionResponse response) {
056: String command = request.getParameter("command");
057: try {
058: if ("Add Portlet".equalsIgnoreCase(command)) {
059: doAddPortlet(request);
060: } else if ("Remove Portlet".equalsIgnoreCase(command)) {
061: doRemovePortlet(request);
062: } else if ("Add Page".equalsIgnoreCase(command)) {
063: doAddPage(request);
064: } else if ("Remove Page".equalsIgnoreCase(command)) {
065: doRemovePage(request);
066: }
067: persistPages();
068: } catch (IOException e) {
069: String msg = "Problem persisting configuration changes. Changes will not be persisted.";
070: LOG.error(msg, e);
071: //TODO: send message back to UI
072: }
073: //TODO: send 'success' message back to UI
074: }
075:
076: public void doAddPortlet(ActionRequest request) {
077: String page = request.getParameter("page");
078: String applicationId = request.getParameter("applications");
079: String portletId = request.getParameter("availablePortlets");
080:
081: LOG.info("Request: Add [applicationId=" + applicationId
082: + ":portletId=" + portletId + "] to page '" + page
083: + "'");
084:
085: PageConfig config = getPageConfig(page);
086: config.addPortlet(applicationId, portletId);
087:
088: }
089:
090: /**
091: * Adds a page to the portal via the <code>RenderConfigService</code>.
092: *
093: * This does not add portlets to the new page. Do that when the page is created
094: * using the Add Portlet button.
095: *
096: * @param request The action request.
097: */
098: public void doAddPage(ActionRequest request) {
099: String page = request.getParameter("newPage");//newPage text input element
100: //Check if page is null or empty
101: if (page == null || page.equals("")) {
102: LOG
103: .warn("Page parameter is null or empty. Page addition will be ignored.");
104: //TODO: send message back to UI
105: return;
106: }
107: //TODO: add page URI input to form
108: String uri = request.getParameter("pageURI");
109: if (uri == null) {
110: uri = PortalDriverServlet.DEFAULT_PAGE_URI;
111: }
112: DriverConfiguration driverConfig = (DriverConfiguration) getPortletContext()
113: .getAttribute(AttributeKeys.DRIVER_CONFIG);
114: PageConfig pageConfig = new PageConfig();
115: pageConfig.setName(page);
116: pageConfig.setUri(uri);
117:
118: RenderConfigService renderConfig = driverConfig
119: .getRenderConfigService();
120: renderConfig.addPage(pageConfig);
121: }
122:
123: /**
124: * Removes a page from the portal ignoring any requests to remove the default page
125: * or the Pluto Admin page.
126: *
127: * The page's portlets are still available, but no longer associated with the deleted page.
128: *
129: * @param request The action request.
130: * @throws IOException If a problem occurs accessing the config file.
131: */
132: public void doRemovePage(ActionRequest request) throws IOException {
133: String page = request.getParameter("page");
134: DriverConfiguration driverConfig = (DriverConfiguration) getPortletContext()
135: .getAttribute(AttributeKeys.DRIVER_CONFIG);
136: //make sure we are not deleting the default page
137: String defaultPage = getDefaultPage();
138: if (page.equalsIgnoreCase(defaultPage)) {
139: LOG
140: .warn("Trying to delete the default page. Page deletion will be ignored.");
141: //TODO: send message back to UI
142: return;
143: }
144: //make sure we are not deleting the Pluto Admin page
145: if (page.equalsIgnoreCase("Pluto Admin")) {
146: LOG
147: .warn("Trying to delete the Pluto Admin page. Page deletion will be ignored.");
148: return;
149: }
150:
151: PageConfig pageConfig = getPageConfig(page);
152: RenderConfigService renderConfig = driverConfig
153: .getRenderConfigService();
154: renderConfig.removePage(pageConfig);
155: }
156:
157: public void doRemovePortlet(ActionRequest request) {
158: String page = request.getParameter("page");
159: String portletId = request.getParameter("placedPortlets");
160:
161: LOG.info("Request: Remove [portletId=" + portletId
162: + "] from page '" + page + "'");
163:
164: PageConfig config = getPageConfig(page);
165: config.removePortlet(portletId);
166: }
167:
168: private PageConfig getPageConfig(String page) {
169: DriverConfiguration driverConfig = (DriverConfiguration) getPortletContext()
170: .getAttribute(AttributeKeys.DRIVER_CONFIG);
171:
172: PageConfig config = driverConfig.getPageConfig(page);
173: return config;
174: }
175:
176: public void doView(RenderRequest request, RenderResponse response)
177: throws PortletException, IOException {
178: request.setAttribute("availablePages", getAvailablePages());
179: super .doView(request, response);
180: }
181:
182: public String getViewPage() {
183: return VIEW_PAGE;
184: }
185:
186: public String getEditPage() {
187: return EDIT_PAGE;
188: }
189:
190: public String getHelpPage(RenderRequest request) {
191: String incPage = HELP_PAGE;
192: String page = request.getParameter("helpPage");
193: if (page != null) {
194: incPage = JSP_DIR + page;
195: }
196: return incPage;
197: }
198:
199: public Collection getAvailablePages() {
200: DriverConfiguration configuration = (DriverConfiguration) getPortletContext()
201: .getAttribute(AttributeKeys.DRIVER_CONFIG);
202:
203: ArrayList list = new ArrayList();
204: Iterator it = configuration.getPages().iterator();
205: while (it.hasNext()) {
206: PageConfig config = (PageConfig) it.next();
207: ArrayList portlets = new ArrayList();
208: Iterator pids = config.getPortletIds().iterator();
209: while (pids.hasNext()) {
210: String pid = pids.next().toString();
211: String name = PortletWindowConfig.parsePortletName(pid);
212: portlets.add(new Placement(pid, name));
213: }
214: list.add(new Page(config.getName(), config.getName(),
215: portlets));
216: }
217:
218: return list;
219: }
220:
221: /**
222: * Persist page configuration changes to render-config section of pluto-portal-driver-config.xml.
223: *
224: * TODO: Use JAXB for config file parsing and persistence.
225: *
226: * @throws IOException
227: */
228: private void persistPages() throws IOException {
229: //TODO: Null checks??? Substitute empty string or throw an Exception
230: final String NL = System.getProperty("line.separator");
231: DriverConfiguration driverConfig = (DriverConfiguration) getPortletContext()
232: .getAttribute(AttributeKeys.DRIVER_CONFIG);
233: StringBuffer renderConfig = new StringBuffer();
234: //start with render-config element
235: renderConfig.append(" ");//indent
236: renderConfig.append(RENDER_CONFIG_SEARCH_TOKEN);
237: renderConfig.append(getDefaultPage());
238: renderConfig.append("\">");
239: renderConfig.append(NL);
240: Collection pages = getAvailablePages();
241: //iterate through pages
242: for (Iterator iter = pages.iterator(); iter.hasNext();) {
243: Page page = (Page) iter.next();
244: PageConfig config = driverConfig.getPageConfig(page
245: .getName());
246: renderConfig.append(" <page name=\"");
247: String pageName = config.getName();
248: renderConfig.append(pageName);
249: renderConfig.append("\" uri=\"");
250: String uri = config.getUri();
251: renderConfig.append(uri);
252: renderConfig.append("\">");
253: renderConfig.append(NL);
254:
255: //iterate through portlets in current page
256: Collection portletIds = config.getPortletIds();
257: for (Iterator iterator = portletIds.iterator(); iterator
258: .hasNext();) {
259: renderConfig.append(" <portlet context=\"");
260: String pid = (String) iterator.next();
261: String pletContext = PortletWindowConfig
262: .parseContextPath(pid);
263: renderConfig.append(pletContext);
264: renderConfig.append("\" name=\"");
265: String pletName = PortletWindowConfig
266: .parsePortletName(pid);
267: renderConfig.append(pletName);
268: renderConfig.append("\"/>");
269: renderConfig.append(NL);
270: }
271: renderConfig.append(" </page>");
272: renderConfig.append(NL);
273: }
274: renderConfig.append(" </render-config>");
275: renderConfig.append(NL);
276: renderConfig.append(NL);
277: renderConfig.append("</pluto-portal-driver>");
278: renderConfig.append(NL);
279: //create new config file content
280: StringBuffer newFileContents = new StringBuffer();
281: newFileContents
282: .append(getContentBeforeRenderConfig(getConfigFileContents()));
283: newFileContents.append(renderConfig);
284: //persist content to new config file
285: FileUtils.writeStringToFile(getConfigFile(), newFileContents
286: .toString());
287: }
288:
289: private String getConfigFileContents() throws IOException {
290: return FileUtils.readFileToString(getConfigFile());
291: }
292:
293: private File getConfigFile() {
294: String path = getPortletContext().getRealPath(CONFIG_FILE_PATH);
295: return new File(path);
296: }
297:
298: /**
299: * Get the page name of the default page from pluto-portal-driver-config.xml.
300: *
301: * @return
302: * @throws IOException
303: */
304: private String getDefaultPage() throws IOException {
305: String configFileContents = getConfigFileContents();
306: return parseDefaultPage(configFileContents);
307: }
308:
309: /**
310: * Gets the content of the config page before the render-config element
311: * (also including the default attribute of render-config - see RENDER_CONFIG_SEARCH_TOKEN above).
312: *
313: * @param contents pluto-portal-driver-config.xml file contents.
314: * @return
315: */
316: protected static String getContentBeforeRenderConfig(String contents) {
317: return contents.substring(0, contents
318: .indexOf(RENDER_CONFIG_SEARCH_TOKEN));
319: }
320:
321: /**
322: * Parse out default attribute value of render-config element in pluto-portal-driver-config.xml.
323: * This method is protected to allow unit testing (see <code>PageAdminPortletTest.testParseDefaultPage()</code>.)
324: *
325: * @param configFileContents Contents of pluto-portal-driver-config.xml file.
326: * @return The value of the default attribute in the render-config element.
327: */
328: protected static String parseDefaultPage(String configFileContents) {
329: String defPage = null;
330: //length of token used to find default page
331: final int DEF_TOK_LEN = RENDER_CONFIG_SEARCH_TOKEN.length();
332: //index of start of default attribute value
333: int startInd = configFileContents
334: .indexOf(RENDER_CONFIG_SEARCH_TOKEN)
335: + DEF_TOK_LEN;
336: //rest of file after DEFAULT_TOK
337: String restOfConfigFile = configFileContents
338: .substring(startInd);
339: //index of first quote in substring, which indicates end of default attribute value
340: int endInd = restOfConfigFile.indexOf('"');
341: defPage = configFileContents.substring(startInd, startInd
342: + endInd);
343: return defPage;
344: }
345:
346: public class Page {
347: private String id;
348: private String name;
349: private Collection portlets;
350:
351: public Page(String pageId, String pageName, Collection portlets) {
352: this .id = pageId;
353: this .name = pageName;
354: this .portlets = portlets;
355: }
356:
357: public String getName() {
358: return name;
359: }
360:
361: public void setName(String name) {
362: this .name = name;
363: }
364:
365: public String getId() {
366: return id;
367: }
368:
369: public void setId(String id) {
370: this .id = id;
371: }
372:
373: public Collection getPortlets() {
374: return portlets;
375: }
376:
377: public void setPortlets(Collection portlets) {
378: this .portlets = portlets;
379: }
380: }
381:
382: public class Placement {
383: private String id;
384: private String portletName;
385:
386: public Placement(String id, String portletName) {
387: this .id = id;
388: this .portletName = portletName;
389: }
390:
391: public String getId() {
392: return id;
393: }
394:
395: public void setId(String id) {
396: this .id = id;
397: }
398:
399: public String getPortletName() {
400: return portletName;
401: }
402:
403: public void setPortletName(String portletName) {
404: this.portletName = portletName;
405: }
406: }
407:
408: }
|