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;
18  
19  // standard java stuff
20  import java.util.Vector;
21  import java.util.Enumeration;
22  
23  // Jetspeed stuff
24  import org.apache.jetspeed.om.security.JetspeedUser;
25  import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
26  import org.apache.jetspeed.services.logging.JetspeedLogger;
27  import org.apache.jetspeed.services.persistence.PersistenceManager;
28  import org.apache.jetspeed.services.persistence.PortalPersistenceException;
29  import org.apache.jetspeed.services.rundata.JetspeedRunData;
30  import org.apache.jetspeed.services.security.PortalResource;
31  import org.apache.jetspeed.services.JetspeedSecurity;
32  import org.apache.jetspeed.util.template.JetspeedLink;
33  import org.apache.jetspeed.util.template.JetspeedLinkFactory;
34  import org.apache.jetspeed.util.MetaData;
35  import org.apache.jetspeed.util.MimeType;
36  
37  // turbine stuff
38  import org.apache.turbine.services.localization.Localization;
39  import org.apache.turbine.util.RunData;
40  
41  // ECS stuff
42  import org.apache.ecs.ConcreteElement;
43  import org.apache.ecs.StringElement;
44  
45  /***
46   * The PortletSet is basically a wrapper around an array of portlets. It provides
47   * runtime context for a set of portlets.
48   * A portlet can get its current set by calling via its PortletConfig
49   *
50   * @author <a href="mailto:raphael@apache.org">Raphaël Luta</a>
51   * @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
52   * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
53   * @author <a href="mailto:morciuch@apache.org">Mark Orciuch</a>
54   * @version $Id: BasePortletSet.java,v 1.35 2004/03/29 21:38:42 taylor Exp $
55   */
56  public class BasePortletSet implements PortletSet, Portlet, PortletState
57  {
58  
59      /***
60       * Static initialization of the logger for this class
61       */    
62      private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(BasePortletSet.class.getName());    
63      
64      /***
65      Is this set sorted
66      */
67      private boolean dirty = false;
68  
69      /***
70      The PortletConfig of this set
71      */
72      private PortletConfig pc = null;
73  
74      /***
75      Provide a name for this set
76      */
77      private String name = null;
78  
79      /***
80      Storage for the portlets assigned to this set
81      */
82      private Vector portlets = null;
83  
84      /***
85      Controller which will layout the set
86      */
87      private PortletController controller = null;
88      
89      /***
90      The time this portlet was created.
91      */
92      private long creationTime;
93      
94      /*** 
95      The name of the portlet displaying info
96      */
97      private String info;
98  
99      /*** 
100     The portletset id
101     */
102     private String id = null;
103 
104     /***
105     Builds a new empty set for storing portlets
106     */
107     public BasePortletSet()
108     {
109         portlets = new Vector();
110         try
111         {
112             init();
113         }
114         catch (PortletException e)
115         {
116             logger.error("Exception", e);
117         }
118     }
119 
120     /***
121     Builds a new empty set for storing portlets with a default controller
122     */
123     public BasePortletSet(PortletController controller)
124     {
125             portlets = new Vector();
126             setController(controller);
127     }
128 
129     /***
130     */
131     public void init() throws PortletException
132     {            
133         if (getPortletConfig() == null)
134         {
135             setPortletConfig(new BasePortletConfig());
136         }
137     }
138 
139     // Set manipulation methods
140 
141     /***
142     Returns the number of portlets currently stored in this set
143     */
144     public int size()
145     {
146         return portlets.size();
147     }
148 
149     /***
150     Returns the portlet set as an array.
151     */
152     public Portlet[] toArray()
153     {
154         sortPortletSet();
155         Portlet[] p = new Portlet[portlets.size()];
156         portlets.copyInto(p);
157 
158         return p;
159     }
160 
161     /***
162     Returns the Portlet at position pos
163     */
164     public Portlet getPortletAt(int pos)
165     {
166         sortPortletSet();
167         return (Portlet) portlets.elementAt(pos);
168     }
169 
170     /***
171     Returns the Portlet with the given id
172     */
173     public Portlet getPortletByID(String id)
174     {
175         if (portlets == null)
176         {
177             return null;
178         }
179 
180         Portlet portlet = null;
181         for (int ix = 0; ix < portlets.size(); ix++)
182         {
183             portlet = (Portlet) portlets.elementAt(ix);
184             if (portlet.getID().equals(id))
185             {
186                 return portlet;
187             }
188         }
189         return null;
190     }
191 
192     /***
193     Returns the Portlet with the given name
194     */
195     public Portlet getPortletByName(String name)
196     {
197         if (portlets == null)
198         {
199             return null;
200         }
201 
202         Portlet portlet = null;
203         for (int ix = 0; ix < portlets.size(); ix++)
204         {
205             portlet = (Portlet) portlets.elementAt(ix);
206             if (portlet.getName().equals(name))
207             {
208                 return portlet;
209             }
210         }
211         return null;
212     }
213 
214     /***
215     Returns the portlet set as an Enumeration
216     */
217     public Enumeration getPortlets()
218     {
219         sortPortletSet();
220         return portlets.elements();
221     }
222 
223 
224     // set content manipulation methods
225 
226     /***
227     Add a portlet to this set.It updates its config to modify the current set
228     */
229     public void addPortlet(Portlet portlet)
230     {
231         addPortlet(portlet, null, -1);
232     }
233 
234     /***
235     Add a portlet to this set.It updates its config to modify the current set
236     */
237     public void addPortlet(Portlet portlet, int position)
238     {
239         addPortlet(portlet, null, position);
240     }
241 
242     /***
243     Add a portlet to this set.It updates its config to modify the current set
244     */
245     public void addPortlet(Portlet portlet, PortletSet.Constraints constraints)
246     {
247         addPortlet(portlet, constraints, -1);
248     }
249 
250     /***
251     Add a portlet to this set.It updates its config to modify the current set
252     */
253     public void addPortlet(Portlet portlet, PortletSet.Constraints constraints, int position)
254     {
255         synchronized (portlets)
256         {
257             portlets.addElement(portlet);
258             PortletConfig pc = portlet.getPortletConfig();
259             if (pc != null)
260             {
261                 pc.setPortletSet(this);
262                 if (constraints != null)
263                 {
264                     pc.setConstraints(constraints);
265                 }
266                 if (position >= 0)
267                 {
268                     pc.setPosition(position);
269                     if (position < (portlets.size() - 1))
270                     {
271                         this.dirty = true;
272                     }
273                 }
274             }
275         }
276     }
277 
278     // set properties setters/getters
279 
280     /***
281     Return the current controller for this set
282     */
283     public PortletController getController()
284     {
285         return this.controller;
286     }
287 
288     /***
289     Set the controller for this set
290     */
291     public synchronized void setController(PortletController controller)
292     {
293         this.controller = controller;
294         controller.setPortlets(this);
295     }
296 
297 
298     // portlet interface implementation
299 
300     /***
301     */
302     public ConcreteElement getContent(RunData rundata)
303     {
304         ConcreteElement content = null; 
305         PortletController controller = getController();
306         PortalResource portalResource = new PortalResource(this);
307 
308         try
309         {
310             JetspeedLink jsLink = JetspeedLinkFactory.getInstance(rundata);
311             portalResource.setOwner(jsLink.getUserName());
312             JetspeedLinkFactory.putInstance(jsLink);
313         }
314         catch (Exception e)
315         {
316             logger.warn(e.toString(), e);
317             portalResource.setOwner(null);
318         }
319 
320         if (!JetspeedSecurity.checkPermission((JetspeedUser) rundata.getUser(),  
321                   portalResource, JetspeedSecurity.PERMISSION_VIEW))
322         {   
323             if ( logger.isDebugEnabled() )
324             {
325                 logger.debug("Unauthorized access by user \"" + rundata.getUser().getUserName() + "\"");
326             }
327             // Clear any portlets that exist in this set
328             if (this.portlets != null)
329             {
330                 this.portlets.clear();
331             }
332             return new StringElement(Localization.getString(rundata, "SECURITY_NO_ACCESS"));
333         }
334         else
335         {
336             if ( logger.isDebugEnabled() )
337             {
338                 logger.debug("User \"" + rundata.getUser().getUserName() + "\" is authorized to portlet set " + getID());
339             }
340         }
341             
342         if (controller == null)
343         {
344             Portlet p = getPortletAt(0);
345     
346             if (p != null)
347             {
348                 content = p.getContent(rundata);
349             }
350         }
351         else
352         {
353             content = controller.getContent(rundata);
354         }
355 
356         if (content == null)
357         {
358             content = new ConcreteElement();
359         }
360         
361         return content;
362     }
363 
364     /***
365     */
366     public String getName()
367     {
368         if (name == null)
369         {
370             return this.getClass().getName();
371         }
372 
373         return name;
374     }
375 
376     /***
377     */
378     public void setName(String name)
379     {
380         this.name = name;
381     }
382 
383     /***
384     */
385     public PortletConfig getPortletConfig()
386     {
387         return this.pc;
388     }
389 
390     /***
391     */
392     public void setPortletConfig(PortletConfig pc)
393     {
394         this.pc = pc;
395     }
396 
397     /***
398     */
399     public String getDescription()
400     {
401         if (getPortletConfig() != null)
402         {
403             if (getPortletConfig().getMetainfo() != null)
404             {
405                 return getPortletConfig().getMetainfo().getDescription();
406             }
407         }
408 
409         return null;
410     }
411 
412     /***
413      * Getter for property description.
414      * @return Name of portlet description.
415      */
416     public String getDescription(String instanceDescription)
417     {
418       if (instanceDescription != null)
419       {
420           return instanceDescription;
421       }
422       return getDescription();
423     }
424 
425     /***
426     */
427     public void setDescription(String description)
428     {
429         PortletConfig pc = getPortletConfig();
430         if (pc == null)
431         {
432             pc = new BasePortletConfig();
433             setPortletConfig(pc);
434         }
435 
436         MetaData meta = pc.getMetainfo();
437         if (meta == null)
438         {
439             meta = new MetaData();
440             pc.setMetainfo(meta);
441         }
442 
443         meta.setDescription(description);
444     }
445 
446     /***
447      * Setter for property image.
448      */
449     public void setImage(String instanceImage)
450     {
451     }    
452      
453     /***
454     */
455     public String getImage()
456     {
457         if (getPortletConfig() != null)
458         {
459             if (getPortletConfig().getMetainfo() != null)
460             {
461                 return getPortletConfig().getMetainfo().getImage();
462             }
463         }
464 
465         return null;
466     }
467     
468     /***
469      * Getter for property image.
470      * @return Name of portlet image, icon.  The name is expected to be in the form of a URL.
471      */
472     public String getImage(String instanceImage)
473     {
474       if (instanceImage != null)
475       {
476           return instanceImage;
477       }
478       return getImage();
479     }
480 
481     /***
482     */
483     public String getTitle()
484     {
485         if (getPortletConfig() != null)
486         {
487             if (getPortletConfig().getMetainfo() != null)
488             {
489                 return getPortletConfig().getMetainfo().getTitle();
490             }
491         }
492 
493         return null;
494     }
495     
496 
497     /*** Get a title for this instance of the portlet.  This method is called
498      * from the context variable portlet_instance and from PortletInstance
499      *
500      * If you wish to append to the title, then you code should look like
501      *    getTitle( String instanceTitle)
502      *    {
503      *      return super.getTitle( instanceTitle) + " - Appened title text";
504      *    }
505      *
506      * @param instanceTitle Title from PSML
507      */
508     public String getTitle(String instanceTitle)
509     {
510         if (instanceTitle != null)
511         {
512             return instanceTitle;
513         }
514         return getTitle();
515     }
516 
517     /***
518     */
519     public void setTitle(String title)
520     {
521 
522         PortletConfig pc = getPortletConfig();
523         if (pc == null)
524         {
525             pc = new BasePortletConfig();
526             setPortletConfig(pc);
527         }
528 
529         MetaData meta = pc.getMetainfo();
530         if (meta == null)
531         {
532             meta = new MetaData();
533             pc.setMetainfo(meta);
534         }
535 
536         meta.setTitle(title);
537     }
538 
539     /***
540     */
541     public boolean getAllowEdit(RunData rundata)
542     {
543         return true;
544     }
545 
546     /***
547      */
548      public boolean getAllowView(RunData rundata)
549      {
550          return true;
551      }
552     
553     /***
554     */
555     public boolean getAllowMaximize(RunData rundata)
556     {
557         return false;
558     }
559 
560     // private util methods
561 
562     /***
563      * Sort the portlets according to Layout position
564      */
565     public final void sortPortletSet()    
566     {
567         if (!this.dirty)
568         {
569             return;
570         }
571         
572         synchronized (portlets)
573         {
574             for (int i = 0; i < portlets.size(); i++)
575             {
576                 
577                 Portlet p = (Portlet) portlets.elementAt(i);
578                 int pos = p.getPortletConfig().getPosition();
579                 if ((pos >= 0) && (pos != i) && pos < portlets.size())
580                 {
581                     portlets.removeElementAt(i);
582                     portlets.insertElementAt(p, pos);
583                 }
584             }
585                     
586             this.dirty = false;   
587         }        
588     }
589 
590     /***
591     @see Portlet#getCreationTime()
592     */
593     public long getCreationTime()
594     {
595         return this.creationTime;
596     }
597     
598     /***
599     @see Portlet#setCreationTime
600     */
601     public void setCreationTime(long creationTime)
602     {
603         this.creationTime = creationTime;
604     }
605     
606     /***
607      Method retruns true if at least one of the portlets of the portletset
608      fits the requested MimeTyp. Otherwise it retruns false. 
609     */
610     public boolean supportsType(MimeType mimeType)
611     {
612         Enumeration portlets = this.getPortlets();
613         while (portlets.hasMoreElements())
614         {
615             Portlet p = (Portlet) portlets.nextElement();
616             if (p.supportsType(mimeType))
617             {
618                 return true;
619             }
620         }
621 
622         return false;
623     }
624 
625     // PortletState Interface implementation
626     
627     /***
628      * Implements the default close behavior: any authenticated user may
629      * remove a portlet from his page
630      *
631      * @param rundata the RunData object for the current request
632      */
633     public boolean allowClose(RunData rundata)
634     {
635         return false;
636     }
637 
638     /***
639      * Returns true if this portlet is currently closed
640      */
641     public boolean isClosed(RunData data)
642     {
643         return false;
644     }
645 
646     /***
647      * Toggles the portlet state between closed and normal
648      *
649      * @param minimized the new portlet state
650      * @param data the RunData for this request
651      */
652     public void setClosed(boolean close, RunData data)
653     {
654         // empty
655     }
656 
657     /***
658      * Implements the default info behavior: any authenticated user may
659      * get information on a portlet
660      *
661      * @param rundata the RunData object for the current request
662      */
663     public boolean allowInfo(RunData rundata)
664     {
665         return false;
666     }
667 
668     /***
669      * Implements the default print friendly format behavior: not
670      * available for the portlet set
671      *
672      * @param rundata the RunData object for the current request
673      */
674     public boolean allowPrintFriendly(RunData rundata)
675     {
676         return false;
677     }
678 
679     /***
680      * Implements the default customize behavior: any authenticated user may
681      * customize a portlet
682      *
683      * @param rundata the RunData object for the current request
684      */
685     public boolean allowCustomize(RunData rundata)
686     {
687         PortalResource portalResource = new PortalResource(this);
688         try
689         {
690             JetspeedLink jsLink = JetspeedLinkFactory.getInstance(rundata);
691             portalResource.setOwner(jsLink.getUserName());
692             JetspeedLinkFactory.putInstance(jsLink);
693         }
694         catch (Exception e)
695         {
696             logger.warn(e.toString(), e);
697             portalResource.setOwner(null);
698         }
699         JetspeedRunData jdata = (JetspeedRunData) rundata;
700         return JetspeedSecurity.checkPermission((JetspeedUser) jdata.getUser(),
701                                                 portalResource,
702                                                 JetspeedSecurity.PERMISSION_CUSTOMIZE);
703     }
704 
705     /***
706      * Implements the default maximize behavior: any authenticated user may
707      * maximize a portlet
708      *
709      * @param rundata the RunData object for the current request
710      */
711     public boolean allowMaximize(RunData rundata)
712     {
713         return false;
714     }
715 
716     /***
717      * Implements the default info behavior: any authenticated user may
718      * minimize a portlet
719      *
720      * @param rundata the RunData object for the current request
721      */
722     public boolean allowMinimize(RunData rundata)
723     {
724         return false;
725     }
726 
727     /***
728      * Returns true if this portlet is currently minimized
729      */
730     public boolean isMinimized(RunData rundata)
731     {
732         return false;
733     }
734 
735     /***
736     Change the portlet visibility state ( minimized <-> normal )
737 
738     @param minimize True if the portlet change to minimized
739     @param rundata A RunData object
740     */
741     public void setMinimized(boolean minimize, RunData rundata)
742     {
743         // empty
744     }
745 
746     //Portlet interface
747 
748    /***
749      * Retrieve a portlet attribute from persistent storage
750      *
751      * @param attrName The attribute to retrieve
752      * @param attrDefValue The value if the attr doesn't exists
753      * @param rundata The RunData object for the current request
754      * @return The attribute value
755      */
756     public String getAttribute(String attrName, String attrDefValue, RunData rundata)
757     {
758         // return attrDefValue;
759         
760         String attrValue = null ;
761 
762         PortletInstance instance = PersistenceManager.getInstance(this, rundata);
763         attrValue = instance.getAttribute(attrName, attrDefValue);
764 
765         return attrValue;
766         
767     }
768 
769     /***
770      * Stores a portlet attribute in persistent storage
771      *
772      * @param attrName The attribute to retrieve
773      * @paarm attrValue The value to store
774      * @param rundata The RunData object for the current request
775      */
776     public void setAttribute(String attrName, String attrValue, RunData rundata)
777     {
778         try
779         {
780             PortletInstance instance = PersistenceManager.getInstance(this, rundata);
781             instance.setAttribute(attrName, attrValue);
782             PersistenceManager.store(instance);
783         }
784         catch (PortalPersistenceException e)
785         {
786             logger.error("Exception while setting attribute " + attrName + " for portlet " + getName(), e);
787         }
788     }
789 
790     /***
791      * Gets the portlet instance associated with this portlet.
792      *
793      * @return PortletInstance
794      */
795     public PortletInstance getInstance(RunData rundata)
796     {
797        return PersistenceManager.getInstance(this, rundata);
798     }
799 
800 
801     public String getID()
802     {
803         return id;
804     }
805 
806     public void setID(String id)
807     {
808         this.id = id;
809     }
810 
811     /***
812     * @return true if the portlet does its own customization
813     */
814     public boolean providesCustomization()
815     {
816         return false;
817     }
818     
819     /*** Returns TRUE if the title bar in should be displayed. The title bar includes
820      * the portlet title and action buttons.  This
821      *
822      * @param rundata The RunData object for the current request
823      */
824     public boolean isShowTitleBar(RunData rundata)
825     {
826         return true;
827     }
828 }