1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.portal;
18
19
20 import java.util.Vector;
21 import java.util.Enumeration;
22
23
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
38 import org.apache.turbine.services.localization.Localization;
39 import org.apache.turbine.util.RunData;
40
41
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
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
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
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
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
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
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
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
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
744 }
745
746
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
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 }