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.jetspeed.layout.impl;
018:
019: import java.util.List;
020: import java.util.Map;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.apache.jetspeed.JetspeedActions;
025: import org.apache.jetspeed.ajax.AJAXException;
026: import org.apache.jetspeed.ajax.AjaxAction;
027: import org.apache.jetspeed.ajax.AjaxBuilder;
028: import org.apache.jetspeed.components.portletregistry.PortletRegistry;
029: import org.apache.jetspeed.layout.PortletActionSecurityBehavior;
030: import org.apache.jetspeed.om.page.Fragment;
031: import org.apache.jetspeed.om.page.Page;
032: import org.apache.jetspeed.page.PageManager;
033: import org.apache.jetspeed.request.RequestContext;
034:
035: /**
036: * Add Portlet portlet placement action
037: *
038: * AJAX Parameters:
039: * id = portlet full name (pa::portletName) to be added
040: * page = (implied in the URL)
041: * Optional Parameters:
042: * row = the new row to move to
043: * col = the new column to move to
044: *
045: * @author <a>David Gurney </a>
046: * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
047: * @version $Id: $
048: */
049: public class AddPortletAction extends MovePortletAction implements
050: AjaxAction, AjaxBuilder, Constants {
051: protected Log log = LogFactory.getLog(AddPortletAction.class);
052: protected GetPortletsAction getPortletsAction = null;
053: protected boolean allowDuplicatePortlets = true;
054:
055: public AddPortletAction(String template, String errorTemplate,
056: PortletRegistry registry,
057: GetPortletsAction getPortletsAction) throws AJAXException {
058: this (template, errorTemplate, registry, null, null,
059: getPortletsAction, true);
060: }
061:
062: public AddPortletAction(String template, String errorTemplate,
063: PortletRegistry registry, PageManager pageManager,
064: PortletActionSecurityBehavior securityBehavior,
065: GetPortletsAction getPortletsAction) throws AJAXException {
066: this (template, errorTemplate, registry, pageManager,
067: securityBehavior, getPortletsAction, true);
068: }
069:
070: public AddPortletAction(String template, String errorTemplate,
071: PortletRegistry registry, PageManager pageManager,
072: PortletActionSecurityBehavior securityBehavior,
073: GetPortletsAction getPortletsAction,
074: boolean allowDuplicatePortlets) throws AJAXException {
075: super (template, errorTemplate, registry, pageManager,
076: securityBehavior);
077: this .getPortletsAction = getPortletsAction;
078: this .allowDuplicatePortlets = allowDuplicatePortlets;
079: }
080:
081: protected boolean runAction(RequestContext requestContext,
082: Map resultMap, boolean batch) throws AJAXException {
083: boolean success = true;
084: String status = "success";
085: try {
086: resultMap.put(ACTION, "add");
087: // Get the necessary parameters off of the request
088: String portletId = getActionParameter(requestContext,
089: PORTLETID);
090: if (portletId == null) {
091: throw new RuntimeException("portlet id not provided");
092: }
093: resultMap.put(PORTLETID, portletId);
094:
095: // Verify that the specified portlet id is valid and accessible
096: // If the portletid is not valid an exception will be thrown
097: verifyPortletId(requestContext, portletId);
098:
099: if (allowDuplicatePortlets == false) {
100: // Check to see if this portlet has already been added to the page
101: checkForDuplicatePortlet(requestContext, resultMap,
102: portletId);
103: }
104:
105: String layoutId = getActionParameter(requestContext,
106: LAYOUTID);
107:
108: if (false == checkAccess(requestContext,
109: JetspeedActions.EDIT)) {
110: NestedFragmentContext addToFragmentContext = null;
111: if (layoutId != null && layoutId.length() > 0) {
112: Page page = requestContext.getPage();
113: Fragment fragment = page.getFragmentById(layoutId);
114: if (fragment == null) {
115: success = false;
116: resultMap.put(REASON,
117: "Specified layout fragment not found: "
118: + layoutId);
119: return success;
120: }
121:
122: try {
123: addToFragmentContext = new NestedFragmentContext(
124: fragment, page, getPortletRegistry());
125: } catch (Exception ex) {
126: log.error(
127: "Failure to construct nested context for fragment "
128: + layoutId, ex);
129: success = false;
130: resultMap
131: .put(REASON,
132: "Cannot construct nested context for specified layout fragment");
133: return success;
134: }
135: }
136:
137: if (!createNewPageOnEdit(requestContext)) {
138: success = false;
139: resultMap.put(REASON,
140: "Insufficient access to edit page");
141: return success;
142: }
143: status = "refresh";
144:
145: if (addToFragmentContext != null) {
146: Page newPage = requestContext.getPage();
147:
148: // using NestedFragmentContext, find portlet id for copy of target portlet in the new page
149: Fragment newFragment = null;
150: try {
151: newFragment = addToFragmentContext
152: .getFragmentOnNewPage(newPage,
153: getPortletRegistry());
154: } catch (Exception ex) {
155: log.error("Failure to locate copy of fragment "
156: + layoutId, ex);
157: success = false;
158: resultMap.put(REASON,
159: "Failed to find new fragment for specified layout id: "
160: + layoutId);
161: return success;
162: }
163: layoutId = newFragment.getId();
164: }
165: }
166:
167: Page page = requestContext.getPage();
168:
169: Fragment fragment = pageManager.newFragment();
170: fragment.setType(Fragment.PORTLET);
171: fragment.setName(portletId);
172:
173: Fragment placeInLayoutFragment = null;
174: if (layoutId != null && layoutId.length() > 0) {
175: placeInLayoutFragment = page.getFragmentById(layoutId);
176: if (placeInLayoutFragment == null) {
177: throw new Exception("layout id not found: "
178: + layoutId);
179: }
180: } else {
181: placeInLayoutFragment = page.getRootFragment();
182: }
183:
184: success = placeFragment(requestContext, batch, resultMap,
185: fragment, placeInLayoutFragment);
186:
187: resultMap.put(PORTLETENTITY, fragment.getId());
188: if (success) {
189: resultMap.put(STATUS, status);
190: }
191: } catch (Exception e) {
192: // Log the exception
193: log.error("exception while adding a portlet", e);
194: resultMap.put(REASON, e.toString());
195:
196: // Return a failure indicator
197: success = false;
198: }
199:
200: return success;
201: }
202:
203: protected void verifyPortletId(RequestContext requestContext,
204: String portletId) throws Exception {
205: // Get the list of valid portlets from the getPortletAction
206: List portletList = getPortletsAction.retrievePortlets(
207: requestContext, null);
208: if (portletList != null) {
209: for (int i = 0; i < portletList.size(); i++) {
210: PortletInfo portletInfo = (PortletInfo) portletList
211: .get(i);
212: if (portletInfo != null) {
213: if (portletInfo.getName().equalsIgnoreCase(
214: portletId)) {
215: // A match was found there is no need to continue
216: return;
217: }
218: }
219: }
220: }
221: // If we got here, then no match was found
222: throw new Exception(
223: portletId
224: + " is not a valid portlet or not allowed for this user");
225: }
226:
227: protected void checkForDuplicatePortlet(
228: RequestContext requestContext, Map resultMap,
229: String portletId) throws AJAXException {
230: // Look at each portlet currently on the page
231: Page page = requestContext.getPage();
232:
233: boolean duplicateFound = isDuplicateFragment(page
234: .getRootFragment(), portletId);
235:
236: // Throw an exception if a duplicate is found
237: if (duplicateFound == true) {
238: throw new AJAXException(
239: portletId
240: + " is already on the page, duplicates are not allowed");
241: }
242: }
243:
244: protected boolean isDuplicateFragment(Fragment fragment,
245: String portletId) {
246: if (fragment != null) {
247: // Get the name of this fragment
248: String fragmentName = fragment.getName();
249: if (fragmentName.equals(portletId)) {
250: // Duplicate was found
251: return true;
252: } else {
253: // Process the child fragments if found
254: List childFragments = fragment.getFragments();
255: if (childFragments != null) {
256: for (int i = 0; i < childFragments.size(); i++) {
257: // Recursively call this method again to process the child fragments
258: if (isDuplicateFragment(
259: (Fragment) childFragments.get(i),
260: portletId) == true) {
261: // No need to continue to loop if a duplicate was found
262: return true;
263: }
264: }
265: }
266: }
267: }
268: // We will only get here if no duplicates were found
269: return false;
270: }
271: }
|