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.security.Principal;
020: import java.util.Map;
021: import java.util.Iterator;
022:
023: import javax.security.auth.Subject;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027: import org.apache.jetspeed.JetspeedActions;
028: import org.apache.jetspeed.administration.PortalConfiguration;
029: import org.apache.jetspeed.ajax.AJAXException;
030: import org.apache.jetspeed.ajax.AjaxAction;
031: import org.apache.jetspeed.ajax.AjaxBuilder;
032: import org.apache.jetspeed.components.portletregistry.PortletRegistry;
033: import org.apache.jetspeed.layout.Coordinate;
034: import org.apache.jetspeed.layout.PortletActionSecurityBehavior;
035: import org.apache.jetspeed.layout.PortletPlacementException;
036: import org.apache.jetspeed.layout.PortletPlacementContext;
037: import org.apache.jetspeed.om.page.Fragment;
038: import org.apache.jetspeed.om.page.Page;
039: import org.apache.jetspeed.page.PageManager;
040: import org.apache.jetspeed.page.document.NodeException;
041: import org.apache.jetspeed.portalsite.PortalSiteRequestContext;
042: import org.apache.jetspeed.profiler.impl.ProfilerValveImpl;
043: import org.apache.jetspeed.request.RequestContext;
044: import org.apache.jetspeed.security.RolePrincipal;
045: import org.apache.jetspeed.security.impl.RolePrincipalImpl;
046: import org.apache.jetspeed.Jetspeed;
047:
048: /**
049: * Move Portlet portlet placement action
050: *
051: * AJAX Parameters:
052: * id = the fragment id of the portlet to move
053: * page = (implied in the URL)
054: * Additional Absolute Parameters:
055: * row = the new row to move to
056: * col = the new column to move to
057: * Additional Relative Parameters: (move left, right, up, down)
058: * none
059: *
060: * @author <a>David Gurney</a>
061: * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
062: * @version $Id: $
063: */
064: public class MovePortletAction extends BasePortletAction implements
065: AjaxAction, AjaxBuilder, Constants {
066: protected static final Log log = LogFactory
067: .getLog(MovePortletAction.class);
068: protected static final String eol = System
069: .getProperty("line.separator");
070:
071: private PortletRegistry registry;
072: private int iMoveType = -1;
073: private String sMoveType = null;
074:
075: public MovePortletAction(String template, String errorTemplate,
076: PortletRegistry registry, String sMoveType)
077: throws AJAXException {
078: this (template, errorTemplate, registry, sMoveType, null, null);
079: }
080:
081: public MovePortletAction(String template, String errorTemplate,
082: PortletRegistry registry, PageManager pageManager,
083: PortletActionSecurityBehavior securityBehavior)
084: throws AJAXException {
085: this (template, errorTemplate, registry, "moveabs", pageManager,
086: securityBehavior);
087: }
088:
089: public MovePortletAction(String template, String errorTemplate,
090: PortletRegistry registry, String sMoveType,
091: PageManager pageManager,
092: PortletActionSecurityBehavior securityBehavior)
093: throws AJAXException {
094: super (template, errorTemplate, pageManager, securityBehavior);
095: setMoveType(sMoveType);
096: this .registry = registry;
097: }
098:
099: // Convert the move type into an integer
100: public void setMoveType(String p_sMoveType) throws AJAXException {
101: sMoveType = p_sMoveType;
102:
103: if (p_sMoveType.equalsIgnoreCase("moveabs")) {
104: iMoveType = ABS;
105: } else if (p_sMoveType.equalsIgnoreCase("moveup")) {
106: iMoveType = UP;
107: } else if (p_sMoveType.equalsIgnoreCase("movedown")) {
108: iMoveType = DOWN;
109: } else if (p_sMoveType.equalsIgnoreCase("moveleft")) {
110: iMoveType = LEFT;
111: } else if (p_sMoveType.equalsIgnoreCase("moveright")) {
112: iMoveType = RIGHT;
113: } else if (p_sMoveType.equalsIgnoreCase("move")) {
114: iMoveType = CARTESIAN;
115: } else {
116: throw new AJAXException("invalid move type of:"
117: + p_sMoveType);
118: }
119: }
120:
121: public boolean runBatch(RequestContext requestContext, Map resultMap)
122: throws AJAXException {
123: return runAction(requestContext, resultMap, true);
124: }
125:
126: public boolean run(RequestContext requestContext, Map resultMap)
127: throws AJAXException {
128: return runAction(requestContext, resultMap, false);
129: }
130:
131: protected boolean runAction(RequestContext requestContext,
132: Map resultMap, boolean batch) throws AJAXException {
133: boolean success = true;
134: String status = "success";
135: try {
136: resultMap.put(ACTION, sMoveType);
137: // Get the necessary parameters off of the request
138: String moveFragmentId = getActionParameter(requestContext,
139: FRAGMENTID);
140: String layoutId = getActionParameter(requestContext,
141: LAYOUTID);
142: if (moveFragmentId == null) {
143: throw new Exception(
144: FRAGMENTID
145: + " not provided; must specify portlet or layout id");
146: }
147: resultMap.put(FRAGMENTID, moveFragmentId);
148:
149: Fragment currentLayoutFragment = null;
150: Fragment moveToLayoutFragment = null;
151: // when layoutId is null we use old behavior, ignoring everything to do with multiple layout fragments
152: if (layoutId != null && layoutId.length() > 0
153: && iMoveType != CARTESIAN) {
154: Page page = requestContext.getPage();
155: currentLayoutFragment = page.getFragmentById(layoutId);
156: if (currentLayoutFragment == null) {
157: throw new Exception("layout id not found: "
158: + layoutId);
159: } else {
160: // determine if layoutId parameter refers to the current layout fragment or to some other layout fragment
161: moveToLayoutFragment = currentLayoutFragment;
162: Iterator layoutChildIter = moveToLayoutFragment
163: .getFragments().iterator();
164: while (layoutChildIter.hasNext()) {
165: Fragment childFrag = (Fragment) layoutChildIter
166: .next();
167: if (childFrag != null) {
168: if (moveFragmentId
169: .equals(childFrag.getId())) {
170: moveToLayoutFragment = null;
171: break;
172: }
173: }
174: }
175: if (moveToLayoutFragment != null) {
176: // figure out the current layout fragment - must know to be able to find the portlet
177: // fragment by row/col when a new page is created
178: Fragment root = requestContext.getPage()
179: .getRootFragment();
180: currentLayoutFragment = getParentFragmentById(
181: moveFragmentId, root);
182: }
183: }
184: if (currentLayoutFragment == null) {
185: // report error
186: throw new Exception(
187: "parent layout id not found for portlet id:"
188: + moveFragmentId);
189: }
190: }
191:
192: if (false == checkAccess(requestContext,
193: JetspeedActions.EDIT)) {
194: if (!isPageQualifiedForCreateNewPageOnEdit(requestContext)) {
195: success = false;
196: resultMap
197: .put(REASON,
198: "Page is not qualified for create-new-page-on-edit");
199: return success;
200: }
201:
202: Page page = requestContext.getPage();
203: Fragment fragment = page
204: .getFragmentById(moveFragmentId);
205: if (fragment == null) {
206: success = false;
207: resultMap.put(REASON, "Fragment not found");
208: return success;
209: }
210: NestedFragmentContext moveFragmentContext = null;
211: NestedFragmentContext moveToFragmentContext = null;
212: try {
213: moveFragmentContext = new NestedFragmentContext(
214: fragment, page, registry);
215: //log.info( "moveFragmentContext original : " + eol + moveFragmentContext.toString() );
216: if (moveToLayoutFragment != null) {
217: moveToFragmentContext = new NestedFragmentContext(
218: moveToLayoutFragment, page, registry);
219: //log.info( "moveToFragmentContext original : " + eol + moveToFragmentContext.toString() );
220: }
221: } catch (Exception ex) {
222: log.error(
223: "Failure to construct nested context for fragment "
224: + moveFragmentId, ex);
225: success = false;
226: resultMap
227: .put(REASON,
228: "Cannot construct nested context for fragment");
229: return success;
230: }
231:
232: //log.info("before createNewPageOnEdit page-name=" + page.getName() + " page-path=" + page.getPath() + " page-url=" + page.getUrl() );
233: if (!createNewPageOnEdit(requestContext)) {
234: success = false;
235: resultMap.put(REASON,
236: "Insufficient access to edit page");
237: return success;
238: }
239: status = "refresh";
240:
241: Page newPage = requestContext.getPage();
242: //log.info("after createNewPageOnEdit page-name=" + newPage.getName() + " page-path=" + newPage.getPath() + " page-url=" + newPage.getUrl() );
243: Fragment newPageRootFragment = newPage
244: .getRootFragment();
245:
246: // using NestedFragmentContext, find portlet id for copy of target portlet in the new page
247: Fragment newFragment = null;
248: try {
249: newFragment = moveFragmentContext
250: .getFragmentOnNewPage(newPage, registry);
251: //log.info( "npe newFragment: " + newFragment.getType() + " " + newFragment.getId() );
252: } catch (Exception ex) {
253: log.error("Failure to locate copy of fragment "
254: + moveFragmentId, ex);
255: success = false;
256: resultMap.put(REASON,
257: "Failed to find new fragment for portlet id: "
258: + moveFragmentId);
259: return success;
260: }
261:
262: moveFragmentId = newFragment.getId();
263: currentLayoutFragment = getParentFragmentById(
264: moveFragmentId, newPageRootFragment);
265: if (currentLayoutFragment == null) {
266: success = false;
267: resultMap.put(REASON,
268: "Failed to find parent layout for copied fragment "
269: + moveFragmentId);
270: return success;
271: }
272: //log.info( "npe newParentFragment: " + currentLayoutFragment.getType() + " " + currentLayoutFragment.getId() );
273: if (moveToLayoutFragment != null) {
274: Fragment newMoveToFragment = null;
275: try {
276: newMoveToFragment = moveToFragmentContext
277: .getFragmentOnNewPage(newPage, registry);
278: //log.info( "npe newMoveToFragment: " + newMoveToFragment.getType() + " " + newMoveToFragment.getId() );
279: } catch (Exception ex) {
280: log.error(
281: "Failure to locate copy of destination fragment "
282: + moveToLayoutFragment.getId(),
283: ex);
284: success = false;
285: resultMap
286: .put(REASON,
287: "Failed to find copy of destination fragment");
288: return success;
289: }
290: moveToLayoutFragment = newMoveToFragment;
291: }
292: }
293:
294: if (moveToLayoutFragment != null) {
295: success = moveToOtherLayoutFragment(requestContext,
296: batch, resultMap, moveFragmentId,
297: moveToLayoutFragment, currentLayoutFragment);
298: } else {
299: PortletPlacementContext placement = null;
300: Page page = requestContext.getPage();
301:
302: if (currentLayoutFragment == null)
303: currentLayoutFragment = getParentFragmentById(
304: moveFragmentId, page.getRootFragment());
305:
306: if (currentLayoutFragment != null)
307: placement = new PortletPlacementContextImpl(page,
308: registry, currentLayoutFragment);
309: else
310: placement = new PortletPlacementContextImpl(page,
311: registry);
312:
313: Fragment fragment = placement
314: .getFragmentById(moveFragmentId);
315: if (fragment == null) {
316: success = false;
317: resultMap.put(REASON,
318: "Failed to find fragment for portlet id: "
319: + moveFragmentId);
320: return success;
321: }
322:
323: success = moveInFragment(requestContext, placement,
324: fragment, null, resultMap, batch);
325: }
326: if (success) {
327: resultMap.put(STATUS, status);
328: }
329: } catch (Exception e) {
330: // Log the exception
331: log.error("exception while moving a portlet", e);
332: resultMap.put(REASON, e.toString());
333: // Return a failure indicator
334: success = false;
335: }
336:
337: return success;
338: }
339:
340: protected boolean moveInFragment(RequestContext requestContext,
341: PortletPlacementContext placement, Fragment fragment,
342: Fragment placeInLayoutFragment, Map resultMap, boolean batch)
343: throws PortletPlacementException, NodeException,
344: AJAXException {
345: boolean success = true;
346:
347: String moveFragmentId = fragment.getId();
348: boolean addFragment = (placeInLayoutFragment != null);
349: Coordinate returnCoordinate = null;
350: float oldX = 0f, oldY = 0f, oldZ = 0f, oldWidth = 0f, oldHeight = 0f;
351: float x = -1f, y = -1f, z = -1f, width = -1f, height = -1f;
352: boolean absHeightChanged = false;
353:
354: // desktop extended
355: String posExtended = getActionParameter(requestContext,
356: DESKTOP_EXTENDED);
357: if (posExtended != null) {
358: Map fragmentProperties = fragment.getProperties();
359: if (fragmentProperties == null) {
360: success = false;
361: resultMap.put(REASON,
362: "Failed to acquire fragment properties map for portlet id: "
363: + moveFragmentId);
364: return success;
365: }
366: String oldDeskExt = (String) fragmentProperties
367: .get(DESKTOP_EXTENDED);
368: resultMap.put(OLD_DESKTOP_EXTENDED,
369: ((oldDeskExt != null) ? oldDeskExt : ""));
370: fragmentProperties.put(DESKTOP_EXTENDED, posExtended);
371: }
372:
373: // only required for moveabs
374: if (iMoveType == ABS) {
375: Coordinate newCoordinate = getCoordinateFromParams(requestContext);
376: returnCoordinate = placement.moveAbsolute(fragment,
377: newCoordinate, addFragment);
378: String sHeight = getActionParameter(requestContext, HEIGHT);
379: if (sHeight != null && sHeight.length() > 0) {
380: oldHeight = fragment.getLayoutHeight();
381: height = Float.parseFloat(sHeight);
382: fragment.setLayoutHeight(height);
383: absHeightChanged = true;
384: }
385: } else if (iMoveType == LEFT) {
386: returnCoordinate = placement.moveLeft(fragment);
387: } else if (iMoveType == RIGHT) {
388: returnCoordinate = placement.moveRight(fragment);
389: } else if (iMoveType == UP) {
390: returnCoordinate = placement.moveUp(fragment);
391: } else if (iMoveType == DOWN) {
392: returnCoordinate = placement.moveDown(fragment);
393: } else if (iMoveType == CARTESIAN) {
394: String sx = getActionParameter(requestContext, X);
395: String sy = getActionParameter(requestContext, Y);
396: String sz = getActionParameter(requestContext, Z);
397: String sWidth = getActionParameter(requestContext, WIDTH);
398: String sHeight = getActionParameter(requestContext, HEIGHT);
399: if (sx != null) {
400: oldX = fragment.getLayoutX();
401: x = Float.parseFloat(sx);
402: fragment.setLayoutX(x);
403: }
404: if (sy != null) {
405: oldY = fragment.getLayoutY();
406: y = Float.parseFloat(sy);
407: fragment.setLayoutY(y);
408: }
409: if (sz != null) {
410: oldZ = fragment.getLayoutZ();
411: z = Float.parseFloat(sz);
412: fragment.setLayoutZ(z);
413: }
414: if (sWidth != null) {
415: oldWidth = fragment.getLayoutWidth();
416: width = Float.parseFloat(sWidth);
417: fragment.setLayoutWidth(width);
418: }
419: if (sHeight != null) {
420: oldHeight = fragment.getLayoutHeight();
421: height = Float.parseFloat(sHeight);
422: fragment.setLayoutHeight(height);
423: }
424: }
425:
426: // synchronize back to the page layout root fragment
427: Page page = placement.syncPageFragments();
428:
429: if (placeInLayoutFragment != null) {
430: placeInLayoutFragment.getFragments().add(fragment);
431: }
432:
433: if (pageManager != null && !batch) {
434: pageManager.updatePage(page);
435: }
436:
437: if (iMoveType == CARTESIAN) {
438: putCartesianResult(resultMap, x, oldX, X, OLD_X);
439: putCartesianResult(resultMap, y, oldY, Y, OLD_Y);
440: putCartesianResult(resultMap, z, oldZ, Z, OLD_Z);
441: putCartesianResult(resultMap, width, oldWidth, WIDTH,
442: OLD_WIDTH);
443: putCartesianResult(resultMap, height, oldHeight, HEIGHT,
444: OLD_HEIGHT);
445: } else {
446: // Need to determine what the old col and row were
447: resultMap.put(OLDCOL, String.valueOf(returnCoordinate
448: .getOldCol()));
449: resultMap.put(OLDROW, String.valueOf(returnCoordinate
450: .getOldRow()));
451: // Need to determine what the new col and row were
452: resultMap.put(NEWCOL, String.valueOf(returnCoordinate
453: .getNewCol()));
454: resultMap.put(NEWROW, String.valueOf(returnCoordinate
455: .getNewRow()));
456: if (absHeightChanged) {
457: putCartesianResult(resultMap, height, oldHeight,
458: HEIGHT, OLD_HEIGHT);
459: }
460: }
461:
462: resultMap.put(FRAGMENTID, moveFragmentId);
463:
464: return success;
465: }
466:
467: protected boolean moveToOtherLayoutFragment(
468: RequestContext requestContext, boolean batch,
469: Map resultMap, String moveFragmentId,
470: Fragment moveToLayoutFragment,
471: Fragment removeFromLayoutFragment)
472: throws PortletPlacementException, NodeException,
473: AJAXException {
474: boolean success = true;
475: Fragment placeFragment = null;
476: if (removeFromLayoutFragment != null) {
477: Page page = requestContext.getPage();
478: PortletPlacementContext placement = new PortletPlacementContextImpl(
479: page, registry, removeFromLayoutFragment);
480:
481: placeFragment = placement.getFragmentById(moveFragmentId);
482: if (placeFragment == null) {
483: success = false;
484: resultMap.put(REASON,
485: "Failed to find fragment to move to another layout for fragment id: "
486: + moveFragmentId);
487: return success;
488: }
489: placement.remove(placeFragment);
490: page = placement.syncPageFragments();
491: page.removeFragmentById(moveFragmentId);
492: }
493: if (placeFragment != null) {
494: return placeFragment(requestContext, batch, resultMap,
495: placeFragment, moveToLayoutFragment);
496: }
497: return success;
498: }
499:
500: protected boolean placeFragment(RequestContext requestContext,
501: boolean batch, Map resultMap, Fragment placeFragment,
502: Fragment placeInLayoutFragment)
503: throws PortletPlacementException, NodeException,
504: AJAXException {
505: boolean success = true;
506: if (placeFragment == null) {
507: success = false;
508: return success;
509: }
510:
511: // add fragment
512: Page page = requestContext.getPage();
513: PortletPlacementContext placement = new PortletPlacementContextImpl(
514: page, registry, placeInLayoutFragment);
515: //placement.add( placeFragment, getCoordinateFromParams( requestContext ) );
516:
517: success = moveInFragment(requestContext, placement,
518: placeFragment, placeInLayoutFragment, resultMap, batch);
519:
520: return success;
521: }
522:
523: protected Coordinate getCoordinateFromParams(
524: RequestContext requestContext) {
525: String a_sCol = getActionParameter(requestContext, COL);
526: String a_sRow = getActionParameter(requestContext, ROW);
527:
528: int a_iCol = 0;
529: int a_iRow = 0;
530:
531: // Convert the col and row into integers
532: if (a_sCol != null) {
533: a_iCol = Integer.parseInt(a_sCol);
534: }
535: if (a_sRow != null) {
536: a_iRow = Integer.parseInt(a_sRow);
537: }
538:
539: Coordinate a_oCoordinate = new CoordinateImpl(0, 0, a_iCol,
540: a_iRow);
541: return a_oCoordinate;
542: }
543:
544: protected void putCartesianResult(Map resultMap, float value,
545: float oldValue, String name, String oldName) {
546: if (value != -1F) {
547: resultMap.put(oldName, new Float(oldValue));
548: resultMap.put(name, new Float(value));
549: }
550: }
551:
552: protected PortletRegistry getPortletRegistry() {
553: return this.registry;
554: }
555: }
|