View Javadoc

1   /*
2    * Copyright 2000-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.jetspeed.portal.controls;
18  
19  // Turbine stuff
20  import org.apache.turbine.services.velocity.TurbineVelocity;
21  import org.apache.turbine.services.pull.TurbinePull;
22  import org.apache.turbine.util.RunData;
23  
24  // Jetspeed stuff
25  import org.apache.jetspeed.portal.Portlet;
26  import org.apache.jetspeed.portal.PortletState;
27  import org.apache.jetspeed.portal.security.portlets.PortletWrapper;
28  import org.apache.jetspeed.services.TemplateLocator;
29  import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
30  import org.apache.jetspeed.services.logging.JetspeedLogger;
31  import org.apache.jetspeed.services.persistence.PersistenceManager;
32  import org.apache.jetspeed.services.resources.JetspeedResources;
33  import org.apache.jetspeed.services.rundata.JetspeedRunData;
34  import org.apache.jetspeed.util.template.JetspeedTool;
35  import org.apache.jetspeed.util.template.JetspeedLink;
36  import org.apache.jetspeed.util.template.JetspeedLinkFactory;
37  import org.apache.jetspeed.services.JetspeedSecurity;
38  import org.apache.jetspeed.om.security.JetspeedUser;
39  
40  // Ecs stuff
41  import org.apache.ecs.ConcreteElement;
42  import org.apache.ecs.StringElement;
43  
44  // Velocity Stuff
45  import org.apache.velocity.context.Context;
46  
47  // Java stuff
48  import java.util.List;
49  import java.util.Vector;
50  import java.util.Iterator;
51  
52  /***
53   * A Velocity based portlet control which implements all PortletState action
54   *
55   * <p>To use this control you need to define in your registry the following
56   * entry or similar:</p>
57   * <pre>
58   *   <portlet-control-entry name="TitlePortletControl">
59   *     <classname>org.apache.jetspeed.portal.controls.VelocityPortletControl</classname>
60   *     <parameter name="theme" value="default.vm"/>
61   *     <meta-info>
62   *       <title>TitleControl</title>
63   *       <description>The standard Jetspeed boxed control</description>
64   *       <image>url of image (icon)</description>
65   *     </meta-info>
66   *     <media-type ref="html"/>
67   *   </portlet-control-entry>
68   * </pre>
69   *
70   * 
71   * @author <a href="mailto:re_carrasco@bco011.sonda.cl">Roberto Carrasco</a>
72   * @author <a href="mailto:raphael@apache.org">Raphaël Luta</a>
73   * @author <a href="mailto:morciuch@apache.org">Mark Orciuch</a> 
74   *
75   * @version $Id: VelocityPortletControl.java,v 1.30 2004/03/29 21:38:42 taylor Exp $
76   *
77   */
78  public class VelocityPortletControl extends AbstractPortletControl
79  {
80  
81      /***
82       * Static initialization of the logger for this class
83       */    
84      private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(VelocityPortletControl.class.getName());    
85      
86      /*** Disable content caching */
87      public boolean isCacheable()
88      {
89          return false;
90      }
91      
92      /***
93       * Handles the content generation for this control using Velocity
94       */
95      public ConcreteElement getContent( RunData rundata )
96      {
97          Portlet portlet = getPortlet();
98          JetspeedRunData jdata = (JetspeedRunData)rundata;
99          
100         // Check to see if the portlet allows view
101         // If the current security context disallows view,
102         // do not display the portlet OR the control decorator
103         if (portlet instanceof PortletWrapper)
104         {
105             PortletWrapper wrapper = (PortletWrapper)portlet;
106             if (!wrapper.getAllowView(rundata))
107             {
108                 if (JetspeedResources.getBoolean("defaultportletcontrol.hide.decorator", true))
109                 {                
110                     return new StringElement("");
111                 }
112             }
113         }
114 
115         // Create a new Velocity context and load default 
116         // application pull tools
117         Context context = TurbineVelocity.getContext();
118         
119         context.put("data", rundata );
120         context.put("actions", buildActionList( rundata, portlet ) );
121         context.put("conf", getConfig() );
122         context.put("skin", portlet.getPortletConfig().getPortletSkin() );
123 
124         // Put the request and session based contexts
125         TurbinePull.populateContext(context, rundata);
126         
127         if ( portlet.getName().equals(jdata.getCustomized())
128              && (!portlet.providesCustomization()) )
129         {            
130             context.put("portlet",JetspeedTool.getCustomizer(portlet));
131             context.put("portlet_instance",JetspeedTool.getCustomizer(portlet));
132         }
133         else
134         {
135             context.put("portlet", portlet );
136             if (PersistenceManager.getInstance(portlet, jdata) == null)
137             {
138               context.put("portlet_instance", portlet );
139             }
140             else
141             {
142               context.put("portlet_instance", PersistenceManager.getInstance(portlet, jdata) );
143             }
144         }
145             
146         // allow subclasses to add elements to the context
147         buildContext( rundata, context );
148         
149         String theme = getConfig().getInitParameter("theme","default.vm");
150 
151         String s = "";
152         try 
153         {
154             String template = TemplateLocator.locateControlTemplate(rundata,theme);
155             TurbineVelocity.handleRequest(context, template, rundata.getOut());
156         }
157         catch( Exception e )
158         {
159             logger.error( "Exception while creating content ", e );
160             s = e.toString();
161         }
162 
163         TurbineVelocity.requestFinished(context);
164 
165         return new StringElement( s );
166     }
167     
168     /***
169      * This method allows subclasses of the VelocityPortletControl
170      * to populate the context of this control before rendering by
171      * the template engine.
172      *
173      * @param rundata the RunData object for this request
174      * @param context the Context used by the template
175      */
176     public void buildContext( RunData rundata, Context context )
177     {
178         // empty, used by subclasses to populate the context
179     }
180     
181     /*** Builds a list of possible window actions for this portlet
182      *  instance. For best results, the portlet should also implement the
183      *  PortletState interface.
184      *
185      * @param rundata the request RunData
186      * @param the portlet instance managed by this control
187      * @return a list of ordered PortletAction objects describing the
188      * the actions available for this portlet
189      */
190     protected List buildActionList( RunData rundata, Portlet portlet )
191     {
192         List actions = new Vector();
193         JetspeedLink jsLink = null;
194         JetspeedRunData jdata = (JetspeedRunData)rundata;
195 
196         // disable actions option
197         if (JetspeedSecurity.areActionsDisabledForAllUsers())
198         {
199             return actions;
200         }
201         JetspeedUser user = jdata.getJetspeedUser();
202         if (JetspeedSecurity.areActionsDisabledForAnon() && false == user.hasLoggedIn())
203         {
204             return actions;
205         }
206 
207 
208         // list the available actiosn for this portlet
209         if (portlet instanceof PortletState)
210         {            
211             // the portlet is state aware
212             PortletState state = (PortletState)portlet;
213             boolean customized = (jdata.getMode()==JetspeedRunData.CUSTOMIZE);
214             boolean maximized = customized||(jdata.getMode()==JetspeedRunData.MAXIMIZE);
215             boolean infoAdded = false;
216                     
217             if ( state.allowCustomize( rundata ) )
218             {
219                 if (! customized )
220                 {
221                     actions.add( new PortletAction("customize", "Customize") );
222                 }
223             }
224             else
225             {
226                 if ( state.allowInfo( rundata ) )
227                 {
228                     actions.add( new PortletAction("info", "Information") );
229                     infoAdded = true;
230                 }
231             }
232 
233             if ( (!customized) &&  state.allowPrintFriendly( rundata ) )
234             {
235                 actions.add( new PortletAction("print", "Print Friendly Format") );
236             }
237 
238             if ( (!customized) &&  state.allowInfo( rundata ) && (!infoAdded) )
239             {
240                 actions.add( new PortletAction("info", "Information") );
241             }
242                        
243             if ( (!customized) && (!maximized) && state.allowClose( rundata ) )
244             {
245                 actions.add( new PortletAction("close", "Close") );
246             }
247             
248             if ( state.isMinimized( rundata ) || maximized )
249             {
250                 actions.add( new PortletAction("restore", "Restore") );
251             }
252             else
253             {
254                 if ( state.allowMinimize( rundata ) )
255                 {
256                     actions.add( new PortletAction("minimize", "Minimize") );
257                 }
258 
259                 if ( state.allowMaximize( rundata ) )
260                 {
261                     actions.add( new PortletAction("maximize", "Maximize") );
262                 }
263             }
264         }
265         else
266         {
267             // the portlet only knows about edit and maximize
268             if ( portlet.getAllowEdit( rundata ) )
269             {
270                 actions.add( new PortletAction("info", "Information") );
271             }
272         
273             if ( portlet.getAllowMaximize( rundata ) )
274             {
275                 actions.add( new PortletAction("maximize", "Maximize") );
276             }
277         }
278         
279         // Now that we know which actions should be displayed,
280         // build the links and put it in the context
281         Iterator i = actions.iterator();
282                 
283         while( i.hasNext() )
284         {
285             PortletAction action = (PortletAction)i.next();
286 
287             try
288             {
289                 jsLink = JetspeedLinkFactory.getInstance(rundata);
290             }
291             catch( Exception e)
292             {
293                logger.error( "Exception in buildActionList", e );
294             }
295 //            action.setLink( jsLink.setPortletById(portlet.getID())
296 //                                 .addQueryData("action", getAction( action.getName()))
297 //                                 .toString());
298             action.setLink( jsLink.setAction( getAction( action.getName()), portlet).toString());
299             JetspeedLinkFactory.putInstance(jsLink);
300             jsLink=null;
301         }
302         
303         return actions;
304     }
305     
306     /*** Transforms an Action name in Turbine valid action name, by
307      *  adding a controls package prefix and capitalizing the first
308      *  letter of the name.
309      */
310     protected static String getAction( String name )
311     {
312         StringBuffer buffer = new StringBuffer( "controls." );
313         
314         buffer.append( name.substring(0,1).toUpperCase() );
315         buffer.append( name.substring(1, name.length() ) );
316         
317         return buffer.toString();
318     }
319     
320     /*** This utility class is used to give information about the actions 
321      *  available in a control theme template
322      */
323     public class PortletAction
324     {
325         String name = null;
326         String link = null;
327         String alt = null;
328     
329         /***
330          * Constructor
331          * 
332          * @param name   Name of the action
333          * @param alt    Alternative text description (localized)
334          */
335         protected PortletAction( String name, String alt )
336         {
337             this.name = name;
338             this.alt = alt;
339         }
340         
341         public String getName()
342         {
343             return this.name;
344         }
345         
346         public String getLink()
347         {
348             return this.link;
349         }
350         
351         public void setLink(String link)
352         {
353             this.link = link;
354         }
355 
356         public String getAlt()
357         {
358             return this.alt;
359         }
360 
361     }
362 }
363