1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.layout.impl;
18
19 import java.security.Principal;
20 import java.util.Map;
21 import java.util.Iterator;
22
23 import javax.security.auth.Subject;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.jetspeed.JetspeedActions;
28 import org.apache.jetspeed.administration.PortalConfiguration;
29 import org.apache.jetspeed.ajax.AJAXException;
30 import org.apache.jetspeed.ajax.AjaxAction;
31 import org.apache.jetspeed.ajax.AjaxBuilder;
32 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
33 import org.apache.jetspeed.layout.Coordinate;
34 import org.apache.jetspeed.layout.PortletActionSecurityBehavior;
35 import org.apache.jetspeed.layout.PortletPlacementException;
36 import org.apache.jetspeed.layout.PortletPlacementContext;
37 import org.apache.jetspeed.om.page.Fragment;
38 import org.apache.jetspeed.om.page.Page;
39 import org.apache.jetspeed.page.PageManager;
40 import org.apache.jetspeed.page.document.NodeException;
41 import org.apache.jetspeed.portalsite.PortalSiteRequestContext;
42 import org.apache.jetspeed.profiler.impl.ProfilerValveImpl;
43 import org.apache.jetspeed.request.RequestContext;
44 import org.apache.jetspeed.security.RolePrincipal;
45 import org.apache.jetspeed.security.impl.RolePrincipalImpl;
46 import org.apache.jetspeed.Jetspeed;
47
48 /***
49 * Move Portlet portlet placement action
50 *
51 * AJAX Parameters:
52 * id = the fragment id of the portlet to move
53 * page = (implied in the URL)
54 * Additional Absolute Parameters:
55 * row = the new row to move to
56 * col = the new column to move to
57 * Additional Relative Parameters: (move left, right, up, down)
58 * none
59 *
60 * @author <a>David Gurney</a>
61 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
62 * @version $Id: $
63 */
64 public class MovePortletAction
65 extends BasePortletAction
66 implements AjaxAction, AjaxBuilder, Constants
67 {
68 protected static final Log log = LogFactory.getLog(MovePortletAction.class);
69 protected static final String eol = System.getProperty( "line.separator" );
70
71 private PortletRegistry registry;
72 private int iMoveType = -1;
73 private String sMoveType = null;
74
75 public MovePortletAction( String template,
76 String errorTemplate,
77 PortletRegistry registry,
78 String sMoveType )
79 throws AJAXException
80 {
81 this( template, errorTemplate, registry, sMoveType, null, null );
82 }
83
84 public MovePortletAction( String template,
85 String errorTemplate,
86 PortletRegistry registry,
87 PageManager pageManager,
88 PortletActionSecurityBehavior securityBehavior )
89 throws AJAXException
90 {
91 this( template, errorTemplate, registry, "moveabs", pageManager, securityBehavior );
92 }
93
94 public MovePortletAction( String template,
95 String errorTemplate,
96 PortletRegistry registry,
97 String sMoveType,
98 PageManager pageManager,
99 PortletActionSecurityBehavior securityBehavior )
100 throws AJAXException
101 {
102 super( template, errorTemplate, pageManager, securityBehavior );
103 setMoveType( sMoveType );
104 this.registry = registry;
105 }
106
107
108 public void setMoveType(String p_sMoveType) throws AJAXException
109 {
110 sMoveType = p_sMoveType;
111
112 if (p_sMoveType.equalsIgnoreCase("moveabs"))
113 {
114 iMoveType = ABS;
115 }
116 else if (p_sMoveType.equalsIgnoreCase("moveup"))
117 {
118 iMoveType = UP;
119 }
120 else if (p_sMoveType.equalsIgnoreCase("movedown"))
121 {
122 iMoveType = DOWN;
123 }
124 else if (p_sMoveType.equalsIgnoreCase("moveleft"))
125 {
126 iMoveType = LEFT;
127 }
128 else if (p_sMoveType.equalsIgnoreCase("moveright"))
129 {
130 iMoveType = RIGHT;
131 }
132 else if (p_sMoveType.equalsIgnoreCase("move"))
133 {
134 iMoveType = CARTESIAN;
135 }
136 else
137 {
138 throw new AJAXException("invalid move type of:" + p_sMoveType);
139 }
140 }
141
142 public boolean runBatch(RequestContext requestContext, Map resultMap) throws AJAXException
143 {
144 return runAction(requestContext, resultMap, true);
145 }
146
147 public boolean run(RequestContext requestContext, Map resultMap)
148 throws AJAXException
149 {
150 return runAction(requestContext, resultMap, false);
151 }
152
153 protected boolean runAction( RequestContext requestContext, Map resultMap, boolean batch ) throws AJAXException
154 {
155 boolean success = true;
156 String status = "success";
157 try
158 {
159 resultMap.put(ACTION, sMoveType);
160
161 String moveFragmentId = getActionParameter(requestContext, FRAGMENTID);
162 String layoutId = getActionParameter(requestContext, LAYOUTID);
163 if ( moveFragmentId == null )
164 {
165 throw new Exception( FRAGMENTID + " not provided; must specify portlet or layout id" );
166 }
167 resultMap.put(FRAGMENTID, moveFragmentId);
168
169 Fragment currentLayoutFragment = null;
170 Fragment moveToLayoutFragment = null;
171
172 if ( layoutId != null && layoutId.length() > 0 && iMoveType != CARTESIAN )
173 {
174 Page page = requestContext.getPage();
175 currentLayoutFragment = page.getFragmentById( layoutId );
176 if ( currentLayoutFragment == null )
177 {
178 throw new Exception("layout id not found: " + layoutId );
179 }
180 else
181 {
182
183 moveToLayoutFragment = currentLayoutFragment;
184 Iterator layoutChildIter = moveToLayoutFragment.getFragments().iterator();
185 while ( layoutChildIter.hasNext() )
186 {
187 Fragment childFrag = (Fragment)layoutChildIter.next();
188 if ( childFrag != null )
189 {
190 if ( moveFragmentId.equals( childFrag.getId() ) )
191 {
192 moveToLayoutFragment = null;
193 break;
194 }
195 }
196 }
197 if ( moveToLayoutFragment != null )
198 {
199
200
201 Fragment root = requestContext.getPage().getRootFragment();
202 currentLayoutFragment = getParentFragmentById( moveFragmentId, root );
203 }
204 }
205 if ( currentLayoutFragment == null )
206 {
207
208 throw new Exception("parent layout id not found for portlet id:" + moveFragmentId );
209 }
210 }
211
212 if ( false == checkAccess( requestContext, JetspeedActions.EDIT ) )
213 {
214 if ( ! isPageQualifiedForCreateNewPageOnEdit( requestContext ) )
215 {
216 success = false;
217 resultMap.put(REASON, "Page is not qualified for create-new-page-on-edit");
218 return success;
219 }
220
221 Page page = requestContext.getPage();
222 Fragment fragment = page.getFragmentById( moveFragmentId );
223 if ( fragment == null )
224 {
225 success = false;
226 resultMap.put(REASON, "Fragment not found");
227 return success;
228 }
229 NestedFragmentContext moveFragmentContext = null;
230 NestedFragmentContext moveToFragmentContext = null;
231 try
232 {
233 moveFragmentContext = new NestedFragmentContext( fragment, page, registry );
234
235 if ( moveToLayoutFragment != null )
236 {
237 moveToFragmentContext = new NestedFragmentContext( moveToLayoutFragment, page, registry );
238
239 }
240 }
241 catch ( Exception ex )
242 {
243 log.error( "Failure to construct nested context for fragment " + moveFragmentId, ex );
244 success = false;
245 resultMap.put( REASON, "Cannot construct nested context for fragment" );
246 return success;
247 }
248
249
250 if ( ! createNewPageOnEdit( requestContext ) )
251 {
252 success = false;
253 resultMap.put(REASON, "Insufficient access to edit page");
254 return success;
255 }
256 status = "refresh";
257
258 Page newPage = requestContext.getPage();
259
260 Fragment newPageRootFragment = newPage.getRootFragment();
261
262
263 Fragment newFragment = null;
264 try
265 {
266 newFragment = moveFragmentContext.getFragmentOnNewPage( newPage, registry );
267
268 }
269 catch ( Exception ex )
270 {
271 log.error( "Failure to locate copy of fragment " + moveFragmentId, ex );
272 success = false;
273 resultMap.put( REASON, "Failed to find new fragment for portlet id: " + moveFragmentId );
274 return success;
275 }
276
277 moveFragmentId = newFragment.getId();
278 currentLayoutFragment = getParentFragmentById( moveFragmentId, newPageRootFragment );
279 if ( currentLayoutFragment == null )
280 {
281 success = false;
282 resultMap.put( REASON, "Failed to find parent layout for copied fragment " + moveFragmentId );
283 return success;
284 }
285
286 if ( moveToLayoutFragment != null )
287 {
288 Fragment newMoveToFragment = null;
289 try
290 {
291 newMoveToFragment = moveToFragmentContext.getFragmentOnNewPage( newPage, registry );
292
293 }
294 catch ( Exception ex )
295 {
296 log.error( "Failure to locate copy of destination fragment " + moveToLayoutFragment.getId(), ex );
297 success = false;
298 resultMap.put( REASON, "Failed to find copy of destination fragment" );
299 return success;
300 }
301 moveToLayoutFragment = newMoveToFragment;
302 }
303 }
304
305 if ( moveToLayoutFragment != null )
306 {
307 success = moveToOtherLayoutFragment( requestContext,
308 batch,
309 resultMap,
310 moveFragmentId,
311 moveToLayoutFragment,
312 currentLayoutFragment ) ;
313 }
314 else
315 {
316 PortletPlacementContext placement = null;
317 Page page = requestContext.getPage();
318
319 if ( currentLayoutFragment == null )
320 currentLayoutFragment = getParentFragmentById( moveFragmentId, page.getRootFragment() );
321
322 if ( currentLayoutFragment != null )
323 placement = new PortletPlacementContextImpl( page, registry, currentLayoutFragment );
324 else
325 placement = new PortletPlacementContextImpl( page, registry );
326
327 Fragment fragment = placement.getFragmentById(moveFragmentId);
328 if ( fragment == null )
329 {
330 success = false;
331 resultMap.put( REASON, "Failed to find fragment for portlet id: " + moveFragmentId );
332 return success;
333 }
334
335 success = moveInFragment( requestContext, placement, fragment, null, resultMap, batch );
336 }
337 if ( success )
338 {
339 resultMap.put( STATUS, status );
340 }
341 }
342 catch ( Exception e )
343 {
344
345 log.error( "exception while moving a portlet", e );
346 resultMap.put( REASON, e.toString() );
347
348 success = false;
349 }
350
351 return success;
352 }
353
354 protected boolean moveInFragment( RequestContext requestContext, PortletPlacementContext placement, Fragment fragment, Fragment placeInLayoutFragment, Map resultMap, boolean batch )
355 throws PortletPlacementException, NodeException, AJAXException
356 {
357 boolean success = true;
358
359 String moveFragmentId = fragment.getId();
360 boolean addFragment = (placeInLayoutFragment != null);
361 Coordinate returnCoordinate = null;
362 float oldX = 0f, oldY = 0f, oldZ = 0f, oldWidth = 0f, oldHeight = 0f;
363 float x = -1f, y = -1f, z = -1f, width = -1f, height = -1f;
364 boolean absHeightChanged = false;
365
366
367 String posExtended = getActionParameter( requestContext, DESKTOP_EXTENDED );
368 if ( posExtended != null )
369 {
370 Map fragmentProperties = fragment.getProperties();
371 if ( fragmentProperties == null )
372 {
373 success = false;
374 resultMap.put(REASON, "Failed to acquire fragment properties map for portlet id: " + moveFragmentId );
375 return success;
376 }
377 String oldDeskExt = (String)fragmentProperties.get( DESKTOP_EXTENDED );
378 resultMap.put( OLD_DESKTOP_EXTENDED, ( (oldDeskExt != null) ? oldDeskExt : "" ) );
379 fragmentProperties.put( DESKTOP_EXTENDED, posExtended );
380 }
381
382
383 if ( iMoveType == ABS )
384 {
385 Coordinate newCoordinate = getCoordinateFromParams( requestContext );
386 returnCoordinate = placement.moveAbsolute( fragment, newCoordinate, addFragment );
387 String sHeight = getActionParameter( requestContext, HEIGHT );
388 if ( sHeight != null && sHeight.length() > 0 )
389 {
390 oldHeight = fragment.getLayoutHeight();
391 height = Float.parseFloat( sHeight );
392 fragment.setLayoutHeight( height );
393 absHeightChanged = true;
394 }
395 }
396 else if ( iMoveType == LEFT )
397 {
398 returnCoordinate = placement.moveLeft( fragment );
399 }
400 else if ( iMoveType == RIGHT )
401 {
402 returnCoordinate = placement.moveRight( fragment );
403 }
404 else if ( iMoveType == UP )
405 {
406 returnCoordinate = placement.moveUp( fragment );
407 }
408 else if ( iMoveType == DOWN )
409 {
410 returnCoordinate = placement.moveDown( fragment );
411 }
412 else if ( iMoveType == CARTESIAN )
413 {
414 String sx = getActionParameter( requestContext, X );
415 String sy = getActionParameter( requestContext, Y );
416 String sz = getActionParameter( requestContext, Z );
417 String sWidth = getActionParameter( requestContext, WIDTH );
418 String sHeight = getActionParameter( requestContext, HEIGHT );
419 if ( sx != null )
420 {
421 oldX = fragment.getLayoutX();
422 x = Float.parseFloat( sx );
423 fragment.setLayoutX( x );
424 }
425 if ( sy != null )
426 {
427 oldY = fragment.getLayoutY();
428 y = Float.parseFloat( sy );
429 fragment.setLayoutY( y );
430 }
431 if ( sz != null )
432 {
433 oldZ = fragment.getLayoutZ();
434 z = Float.parseFloat( sz );
435 fragment.setLayoutZ( z );
436 }
437 if ( sWidth != null )
438 {
439 oldWidth = fragment.getLayoutWidth();
440 width = Float.parseFloat( sWidth );
441 fragment.setLayoutWidth( width );
442 }
443 if ( sHeight != null )
444 {
445 oldHeight = fragment.getLayoutHeight();
446 height = Float.parseFloat( sHeight );
447 fragment.setLayoutHeight( height );
448 }
449 }
450
451
452 Page page = placement.syncPageFragments();
453
454 if ( placeInLayoutFragment != null )
455 {
456 placeInLayoutFragment.getFragments().add( fragment );
457 }
458
459 if ( pageManager != null && ! batch )
460 {
461 pageManager.updatePage( page );
462 }
463
464 if ( iMoveType == CARTESIAN )
465 {
466 putCartesianResult( resultMap, x, oldX, X, OLD_X );
467 putCartesianResult( resultMap, y, oldY, Y, OLD_Y );
468 putCartesianResult( resultMap, z, oldZ, Z, OLD_Z );
469 putCartesianResult( resultMap, width, oldWidth, WIDTH, OLD_WIDTH );
470 putCartesianResult( resultMap, height, oldHeight, HEIGHT, OLD_HEIGHT );
471 }
472 else
473 {
474
475 resultMap.put( OLDCOL, String.valueOf( returnCoordinate.getOldCol() ) );
476 resultMap.put( OLDROW, String.valueOf( returnCoordinate.getOldRow() ) );
477
478 resultMap.put( NEWCOL, String.valueOf( returnCoordinate.getNewCol() ) );
479 resultMap.put( NEWROW, String.valueOf( returnCoordinate.getNewRow() ) );
480 if ( absHeightChanged )
481 {
482 putCartesianResult( resultMap, height, oldHeight, HEIGHT, OLD_HEIGHT );
483 }
484 }
485
486 resultMap.put( FRAGMENTID, moveFragmentId );
487
488 return success;
489 }
490
491 protected boolean moveToOtherLayoutFragment( RequestContext requestContext,
492 boolean batch,
493 Map resultMap,
494 String moveFragmentId,
495 Fragment moveToLayoutFragment,
496 Fragment removeFromLayoutFragment )
497 throws PortletPlacementException, NodeException, AJAXException
498 {
499 boolean success = true;
500 Fragment placeFragment = null;
501 if ( removeFromLayoutFragment != null )
502 {
503 Page page = requestContext.getPage();
504 PortletPlacementContext placement = new PortletPlacementContextImpl( page, registry, removeFromLayoutFragment );
505
506 placeFragment = placement.getFragmentById( moveFragmentId );
507 if ( placeFragment == null )
508 {
509 success = false;
510 resultMap.put( REASON, "Failed to find fragment to move to another layout for fragment id: " + moveFragmentId );
511 return success;
512 }
513 placement.remove( placeFragment );
514 page = placement.syncPageFragments();
515 page.removeFragmentById( moveFragmentId );
516 }
517 if ( placeFragment != null )
518 {
519 return placeFragment( requestContext,
520 batch,
521 resultMap,
522 placeFragment,
523 moveToLayoutFragment );
524 }
525 return success;
526 }
527
528 protected boolean placeFragment( RequestContext requestContext,
529 boolean batch,
530 Map resultMap,
531 Fragment placeFragment,
532 Fragment placeInLayoutFragment )
533 throws PortletPlacementException, NodeException, AJAXException
534 {
535 boolean success = true;
536 if ( placeFragment == null )
537 {
538 success = false;
539 return success;
540 }
541
542
543 Page page = requestContext.getPage();
544 PortletPlacementContext placement = new PortletPlacementContextImpl( page, registry, placeInLayoutFragment );
545
546
547 success = moveInFragment( requestContext, placement, placeFragment, placeInLayoutFragment, resultMap, batch );
548
549 return success;
550 }
551
552 protected Coordinate getCoordinateFromParams(RequestContext requestContext)
553 {
554 String a_sCol = getActionParameter( requestContext, COL );
555 String a_sRow = getActionParameter( requestContext, ROW );
556
557 int a_iCol = 0;
558 int a_iRow = 0;
559
560
561 if ( a_sCol != null )
562 {
563 a_iCol = Integer.parseInt( a_sCol );
564 }
565 if ( a_sRow != null )
566 {
567 a_iRow = Integer.parseInt( a_sRow );
568 }
569
570 Coordinate a_oCoordinate = new CoordinateImpl( 0, 0, a_iCol, a_iRow );
571 return a_oCoordinate;
572 }
573
574 protected void putCartesianResult(Map resultMap, float value, float oldValue, String name, String oldName)
575 {
576 if (value != -1F)
577 {
578 resultMap.put(oldName, new Float(oldValue));
579 resultMap.put(name, new Float(value));
580 }
581 }
582
583 protected PortletRegistry getPortletRegistry()
584 {
585 return this.registry;
586 }
587 }