View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.layout.impl;
18  
19  import java.util.List;
20  import java.util.Map;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.jetspeed.JetspeedActions;
25  import org.apache.jetspeed.ajax.AJAXException;
26  import org.apache.jetspeed.ajax.AjaxAction;
27  import org.apache.jetspeed.ajax.AjaxBuilder;
28  import org.apache.jetspeed.layout.PortletActionSecurityBehavior;
29  import org.apache.jetspeed.om.page.Fragment;
30  import org.apache.jetspeed.om.page.Page;
31  import org.apache.jetspeed.page.PageManager;
32  import org.apache.jetspeed.request.RequestContext;
33  
34  
35  /***
36   * Add Portlet portlet placement action
37   * 
38   * AJAX Parameters: 
39   *    id = portlet full name (pa::portletName) to be added
40   *    page = (implied in the URL)
41   * Optional Parameters:  
42   *    row = the new row to move to
43   *    col = the new column to move to
44   *    
45   * @author <a>David Gurney </a>
46   * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
47   * @version $Id: $
48   */
49  public class AddPortletAction 
50      extends MovePortletAction 
51      implements AjaxAction, AjaxBuilder, Constants
52  {
53      protected Log log = LogFactory.getLog(AddPortletAction.class);
54      protected GetPortletsAction getPortletsAction = null;
55      protected boolean allowDuplicatePortlets = true;
56  
57      public AddPortletAction(String template, String errorTemplate, GetPortletsAction getPortletsAction)
58          throws AJAXException
59      {
60          this(template, errorTemplate, null, null, getPortletsAction, true);
61      }
62  
63      public AddPortletAction(String template, 
64                              String errorTemplate, 
65                              PageManager pageManager,
66                              PortletActionSecurityBehavior securityBehavior,
67                              GetPortletsAction getPortletsAction)
68          throws AJAXException
69      {
70          this(template, errorTemplate, pageManager, securityBehavior, getPortletsAction, true);
71      }
72  
73      public AddPortletAction(String template, 
74                              String errorTemplate, 
75                              PageManager pageManager,
76                              PortletActionSecurityBehavior securityBehavior,
77                              GetPortletsAction getPortletsAction,
78                              boolean allowDuplicatePortlets)
79          throws AJAXException
80      {
81          super(template, errorTemplate, pageManager, securityBehavior); 
82          this.getPortletsAction = getPortletsAction;
83          this.allowDuplicatePortlets = allowDuplicatePortlets;
84      }
85      
86      protected boolean runAction( RequestContext requestContext, Map resultMap, boolean batch ) throws AJAXException
87      {
88          boolean success = true;
89          String status = "success";
90          try
91          {
92              resultMap.put(ACTION, "add");
93              // Get the necessary parameters off of the request
94              String portletId = getActionParameter(requestContext, PORTLETID);
95              if (portletId == null) 
96              { 
97                  throw new RuntimeException("portlet id not provided"); 
98              }
99              resultMap.put(PORTLETID, portletId);
100             
101             // Verify that the specified portlet id is valid and accessible
102             // If the portletid is not valid an exception will be thrown
103             verifyPortletId(requestContext, portletId);
104             
105             if(allowDuplicatePortlets == false) {
106             	// Check to see if this portlet has already been added to the page
107             	checkForDuplicatePortlet(requestContext, resultMap, portletId);
108             }
109             
110             if (false == checkAccess(requestContext, JetspeedActions.EDIT))
111             {
112                 if (!createNewPageOnEdit(requestContext))
113                 {
114                     success = false;
115                     resultMap.put(REASON, "Insufficient access to edit page");                
116                     return success;
117                 }
118                 status = "refresh";
119             }           
120             
121             Page page = requestContext.getPage();
122             String layoutId = getActionParameter(requestContext, LAYOUTID);
123             Fragment fragment = pageManager.newFragment();
124             fragment.setType(Fragment.PORTLET);
125             fragment.setName(portletId);
126             //fragment.setLayoutColumn(iCol);
127             //fragment.setLayoutRow(iRow);
128             
129             Fragment placeInLayoutFragment = null;
130             if ( layoutId != null && layoutId.length() > 0 )
131             {
132                 placeInLayoutFragment = page.getFragmentById( layoutId );
133                 if ( placeInLayoutFragment == null )
134                 {
135                     throw new Exception( "layout id not found: " + layoutId );
136                 }
137             }
138             else
139             {
140                 placeInLayoutFragment = page.getRootFragment();
141             }
142 
143             success = placeFragment( requestContext,
144                                      pageManager,
145                                      batch,
146                                      resultMap,
147                                      fragment,
148                                      placeInLayoutFragment ) ;
149 
150             resultMap.put(STATUS, status);
151             resultMap.put(PORTLETENTITY, fragment.getId());            
152         } 
153         catch (Exception e)
154         {
155             // Log the exception
156             log.error("exception while adding a portlet", e);
157             resultMap.put(REASON, e.toString());
158 
159             // Return a failure indicator
160             success = false;
161         }
162 
163         return success;
164     }
165     
166     protected void verifyPortletId(RequestContext requestContext, String portletId) throws Exception
167     {
168     	// Get the list of valid portlets from the getPortletAction
169     	List portletList = getPortletsAction.retrievePortlets(requestContext, null);
170     	if(portletList != null) {
171     		for(int i = 0; i < portletList.size(); i++) {
172     			PortletInfo portletInfo = (PortletInfo)portletList.get(i);
173     			if(portletInfo != null) {
174     				if(portletInfo.getName().equalsIgnoreCase(portletId)) {
175     					// A match was found there is no need to continue
176     					return;
177     				}
178     			}
179     		}
180     	}
181     	// If we got here, then no match was found
182     	throw new Exception(portletId + " is not a valid portlet or not allowed for this user");
183     }
184     
185     protected void checkForDuplicatePortlet(RequestContext requestContext, Map resultMap, String portletId)
186     throws AJAXException
187     {
188     	// Look at each portlet currently on the page
189     	Page page = requestContext.getPage();
190     	
191     	boolean duplicateFound = isDuplicateFragment(page.getRootFragment(), portletId);
192     	
193     	// Throw an exception if a duplicate is found
194     	if(duplicateFound == true) {
195     		throw new AJAXException(portletId + " is already on the page, duplicates are not allowed");
196     	}
197     }
198 
199     protected boolean isDuplicateFragment(Fragment fragment, String portletId) {
200     	if(fragment != null) {
201 	    	// Get the name of this fragment
202 	    	String fragmentName = fragment.getName();
203 	    	if(fragmentName.equals(portletId)) {
204 	    		// Duplicate was found
205 	    		return true;
206 	    	} else {
207 	    		// Process the child fragments if found
208 	    		List childFragments = fragment.getFragments();
209 	    		if(childFragments != null) {
210 	    			for(int i = 0; i < childFragments.size(); i++) {
211 	    				// Recursively call this method again to process the child fragments
212 	    				if(isDuplicateFragment((Fragment)childFragments.get(i),portletId) == true) {
213 	    					// No need to continue to loop if a duplicate was found
214 	    					return true;
215 	    				}
216 	    			}
217 	    		}
218 	    	}
219     	}
220     	// We will only get here if no duplicates were found
221     	return false;
222     }
223 }