1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.util.template;
18
19 import org.apache.ecs.ConcreteElement;
20 import org.apache.ecs.StringElement;
21
22 import org.apache.turbine.util.RunData;
23 import org.apache.turbine.services.pull.ApplicationTool;
24 import org.apache.turbine.services.localization.Localization;
25
26 import org.apache.jetspeed.portal.Portlet;
27 import org.apache.jetspeed.portal.PortletSet;
28 import org.apache.jetspeed.portal.PortletControl;
29 import org.apache.jetspeed.services.PortalToolkit;
30 import org.apache.jetspeed.services.PortletFactory;
31 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
32 import org.apache.jetspeed.services.logging.JetspeedLogger;
33 import org.apache.jetspeed.services.resources.JetspeedResources;
34 import org.apache.jetspeed.services.Profiler;
35 import org.apache.jetspeed.services.rundata.JetspeedRunData;
36 import org.apache.jetspeed.om.SecurityReference;
37 import org.apache.jetspeed.om.profile.PSMLDocument;
38 import org.apache.jetspeed.om.profile.Profile;
39 import org.apache.jetspeed.om.profile.ProfileException;
40 import org.apache.jetspeed.om.profile.Entry;
41 import org.apache.jetspeed.modules.ParameterLoader;
42 import org.apache.jetspeed.services.security.PortalResource;
43 import org.apache.jetspeed.om.registry.Parameter;
44 import org.apache.jetspeed.om.registry.PortletEntry;
45 import org.apache.jetspeed.om.security.JetspeedUser;
46 import org.apache.jetspeed.services.Registry;
47 import org.apache.jetspeed.services.JetspeedSecurity;
48 import org.apache.jetspeed.portal.security.portlets.PortletWrapper;
49 import org.apache.jetspeed.util.JetspeedClearElement;
50
51 import java.util.Enumeration;
52 import java.util.Stack;
53 import java.util.Map;
54 import java.util.Hashtable;
55 import java.util.StringTokenizer;
56
57 /***
58 * Utility class for accessing Jetspeed in a "pull" mode
59 *
60 * <strong>Since the tool stores a RunData object, it may not be
61 * shared between threads and/or requests</strong>
62 *
63 * @author <a href="mailto:raphael@apache.org">Raphaël Luta</a>
64 * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
65 * @author <a href="mark_orciuch@ngsltd.com">Mark Orciuch</a>
66 * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
67 *
68 * @version $Id: JetspeedTool.java,v 1.38 2004/03/29 21:38:43 taylor Exp $
69 */
70 public class JetspeedTool implements ApplicationTool
71 {
72 /***
73 * Static initialization of the logger for this class
74 */
75 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedTool.class.getName());
76
77 /*** RunData object for this request */
78 protected JetspeedRunData rundata = null;
79
80 /*** Empty constructor used by introspection
81 */
82 public JetspeedTool()
83 {
84 }
85
86 /*** The Tool constructor
87 *
88 * @param data the RunData object for the current request
89 */
90 public JetspeedTool(RunData data)
91 {
92 this.rundata = (JetspeedRunData)data;
93 }
94
95 /***
96 * This will initialise a JetspeedTool object that was
97 * constructed with the default constructor (ApplicationTool
98 * method).
99 *
100 * @param data assumed to be a RunData object
101 */
102 public void init(Object data)
103 {
104 this.rundata = (JetspeedRunData)data;
105 }
106
107 /***
108 * Refresh method - does nothing
109 */
110 public void refresh()
111 {
112
113 }
114
115 /***
116 * Returns the portlet content customized for the current user.
117 * Currently, the layout engine does not handle panes, so the
118 * panes are mapped to real PSML files.
119 * If the pane name is null or "default", the profiler will automatically
120 * chose the PSML content, else the tool will try to load the PSML
121 * file with the specified name
122 *
123 * @param name the name of the pane to render
124 * @return the rendered content of the pane
125 */
126 public ConcreteElement getPane(String name)
127 {
128 ConcreteElement result = null;
129 String msg = "";
130
131 if (null != rundata)
132 {
133 Profile profile = rundata.getProfile();
134 try
135 {
136 if (null == profile)
137 {
138 profile = Profiler.getProfile(rundata);
139 if (profile == null)
140 {
141 throw new ProfileException("Profile not found.");
142 }
143 rundata.setProfile(profile);
144 }
145
146 if ((name == null) || Profiler.DEFAULT_PROFILE.equals(name) || "".equals(name))
147 ;
148 else
149 profile.setName(name);
150
151 PSMLDocument doc = profile.getDocument();
152 if (null != doc)
153 {
154 result = PortalToolkit.getSet(doc.getPortlets()).getContent(rundata);
155 }
156 }
157 catch (Exception e)
158 {
159 logger.warn("JetspeedTool.getPane: problem getting: "
160 + name + " from current request's profile: " + e.toString());
161 msg = e.getMessage();
162 }
163
164 }
165
166 if (result == null)
167 {
168 result = new StringElement("Error retrieving Portal Page: " + msg);
169 }
170
171 return result;
172 }
173
174 /***
175 * Return the content of a named portlet. This portlet is sought in
176 * the current PSML resource.
177 *
178 * If a control is attached to the portlet description, returns the defined
179 * portlet and control, otherwise use the default control.
180 *
181 * Note: This will return the FIRST portlet with a name = name. Use getPortletById().
182 *
183 * @param name the name of the portlet to render
184 * @return the rendered content of the portlet
185 *
186 * @deprecated Use getPortletById()
187 */
188 public ConcreteElement getPortlet(String name)
189 {
190 ConcreteElement result = null;
191 Portlet found = null;
192 Stack sets = new Stack();
193 sets.push(rundata.getProfile().getRootSet());
194
195 while ((sets.size() > 0) && (found==null))
196 {
197 PortletSet set = (PortletSet)sets.pop();
198
199 if (set.getName().equals(name))
200 {
201 found = set;
202 }
203 else
204 {
205 Enumeration en = set.getPortlets();
206 while((found==null) && en.hasMoreElements())
207 {
208 Portlet p = (Portlet)en.nextElement();
209
210
211 Portlet real = p;
212 while (real instanceof PortletControl)
213 {
214 real = ((PortletControl)p).getPortlet();
215 }
216
217 if (real instanceof PortletSet)
218 {
219
220 sets.push(real);
221 }
222 else if (p.getName().equals(name))
223 {
224 found = p;
225 }
226 }
227 }
228 }
229
230 if (found!=null)
231 {
232 result = found.getContent(rundata);
233 }
234
235 if (result==null)
236 {
237
238 result = new ConcreteElement();
239 }
240
241 return result;
242 }
243
244 /*** This method retrieves the appropriate customizer portlet for the
245 * current portlet
246 *
247 * @param p the portlet to customize
248 * @param data the RunData for this request
249 * @return the portlet object of the appropriate customizer
250 */
251 public static Portlet getCustomizer(Portlet p)
252 {
253 Portlet customizer = p;
254
255 while (p instanceof PortletControl)
256 {
257 p = ((PortletControl)p).getPortlet();
258 }
259
260
261 if ( !p.providesCustomization() )
262 {
263
264
265
266
267 String name = p.getPortletConfig().getInitParameter("_customizer");
268
269 if (name == null)
270 {
271 String key = (p instanceof PortletSet)?"PortletSet":"Portlet";
272
273 name = JetspeedResources.getString("customizer."+key,key+"Customizer");
274 }
275
276 try
277 {
278 customizer = PortletFactory.getPortlet(name, p.getID()+"customize");
279 customizer.getPortletConfig()
280 .setPortletSkin(p.getPortletConfig().getPortletSkin());
281 PortletControl control = PortalToolkit.getControl((String)null);
282 if (control!=null)
283 {
284 control.setPortlet(customizer);
285 control.init();
286 return control;
287 }
288 }
289 catch (Exception e)
290 {
291 logger.error("Exception", e);
292 }
293 }
294
295 return customizer;
296 }
297
298 /*** This method retrieves the appropriate information portlet for the
299 * current portlet
300 *
301 * @param p the portlet to display information about
302 * @param data the RunData for this request
303 * @return the portlet object of the appropriate customizer
304 */
305 public static Portlet getPortletInfoPortlet(RunData data)
306 {
307 Portlet info = null;
308
309 String name = JetspeedResources.getString("PortletInfoPortlet.name", "PortletInfoPortlet");
310
311 try {
312
313 if (null != data)
314 {
315 JetspeedRunData jdata = (JetspeedRunData)data;
316 Profile profile = jdata.getProfile();
317
318 if (null == profile)
319 {
320 logger.warn("JetspeedTool: profile is null");
321 profile = Profiler.getProfile(jdata);
322 jdata.setProfile(profile);
323 }
324
325 Portlet source = findPortlet(data);
326 if (source != null) {
327 jdata.setPortlet(source.getName());
328 info = PortletFactory.getPortlet(name, "PortletInfoPortlet");
329 info.getPortletConfig().setPortletSkin(source.getPortletConfig().getPortletSkin());
330 PortletControl control = PortalToolkit.getControl((String)null);
331 if (control != null)
332 {
333 control.setPortlet(info);
334 control.init();
335 return control;
336 }
337 }
338 }
339 } catch (Exception e) {
340 logger.error("Exception", e);
341 }
342
343 return info;
344 }
345
346 /***
347 * Finds portlet identified by js_peid in the current user's profile
348 *
349 * @param rundata for this request
350 * @return portlet identified by js_peid
351 */
352 private static Portlet findPortlet(RunData rundata) {
353
354 Portlet found = null;
355 JetspeedRunData jdata = (JetspeedRunData)rundata;
356 String peid = jdata.getJs_peid();
357 if (peid != null)
358 {
359 Stack sets = new Stack();
360 sets.push(jdata.getProfile().getRootSet());
361
362 while ((found==null) && (sets.size() > 0))
363 {
364 PortletSet set = (PortletSet)sets.pop();
365
366 if (set.getID().equals(peid))
367 {
368 found = set;
369 }
370 else
371 {
372 Enumeration en = set.getPortlets();
373 while((found==null) && en.hasMoreElements())
374 {
375 Portlet p = (Portlet)en.nextElement();
376
377
378 Portlet real = p;
379 while (real instanceof PortletControl)
380 {
381 real = ((PortletControl)p).getPortlet();
382 }
383
384 if (real instanceof PortletSet)
385 {
386 if (real.getID().equals(peid))
387 {
388 found=real;
389 }
390 else
391 {
392
393 sets.push(real);
394 }
395 }
396 else if (p.getID().equals(peid))
397 {
398 found = p;
399 }
400 }
401 }
402 }
403 }
404
405 return found;
406 }
407
408
409 /***
410 * Return the content of a portal element given the id of the element.
411 *
412 * @param id The portlet id
413 * @return the rendered content of the portlet
414 */
415 public ConcreteElement getPortalElement(String id)
416 {
417 ConcreteElement result = null;
418
419 if (null != rundata)
420 {
421 Profile profile = rundata.getProfile();
422 try
423 {
424 if (null == profile)
425 {
426 System.out.println("profile is null");
427 profile = Profiler.getProfile(rundata);
428 rundata.setProfile(profile);
429 }
430
431 PSMLDocument doc = profile.getDocument();
432 if (null != doc)
433 {
434 Entry entry = doc.getEntryById(id);
435 if (null == entry)
436 {
437
438
439 result = new StringElement("not implemented - PortletElement");
440 }
441 else
442 {
443 Portlet p = PortletFactory.getPortlet( entry );
444 if (p != null)
445 {
446 result = p.getContent(rundata);
447 }
448 else
449 result = new StringElement("Error retrieving PortletElement");
450
451 }
452 }
453 }
454 catch (Exception e)
455 {
456 logger.error("Exception", e);
457 }
458 }
459
460 if (result == null)
461 {
462 result = new StringElement("Error fetching pane");
463 }
464
465 return result;
466
467 }
468
469 /***
470 * Return the content of a portlet using the portlet's id (PEID). This portlet is sought in
471 * the current PSML resource.
472 *
473 * If a control is attached to the portlet description, returns the defined
474 * portlet and control, otherwise use the default control.
475 *
476 * @param peid the peid of the portlet to render
477 * @return the rendered content of the portlet
478 */
479 public ConcreteElement getPortletById(String peid)
480 {
481 ConcreteElement result = null;
482 Portlet found = null;
483 Stack sets = new Stack();
484 sets.push(rundata.getProfile().getRootSet());
485
486 while ((sets.size() > 0) && (found==null))
487 {
488 PortletSet set = (PortletSet)sets.pop();
489
490 if (set.getID().equals(peid))
491 {
492 found = set;
493 }
494 else
495 {
496 Enumeration en = set.getPortlets();
497 while((found==null) && en.hasMoreElements())
498 {
499 Portlet p = (Portlet)en.nextElement();
500
501
502 Portlet real = p;
503 while (real instanceof PortletControl)
504 {
505 real = ((PortletControl)p).getPortlet();
506 }
507
508 if (real instanceof PortletSet)
509 {
510
511 sets.push(real);
512 }
513 else if (p.getID().equals(peid))
514 {
515 found = p;
516 }
517 }
518 }
519 }
520
521 if (found!=null)
522 {
523
524 result = PortletWrapper.wrap(found).getContent(rundata);
525 }
526
527 if (result==null)
528 {
529
530 result = new ConcreteElement();
531 }
532
533 return result;
534 }
535
536 /***
537 * Return the content of a portlet using the portlet's name. This portlet is sought in
538 * the registry. This is useful when you want to get portlet's content without
539 * actually having the portlet in user's profile (for example, to preview a portlet
540 * before adding it to the profile).
541 * <P>
542 * If a control name is specified to the portlet description, returns the defined
543 * portlet and control, otherwise use the default control.
544 * <P>
545 * Issues to resolve:
546 * <UL>
547 * <LI>is new portlet instance created everytime someone previews the same portlet?</LI>
548 * <LI>should use the same skin as the current pane</LI>
549 * <LI>if TitlePortletControl is used, the action icons (max, min, etc) are not functional.
550 * Also, customize icon should not be present.</LI>
551 * <LI> interactive portlets (such as DatabaseBrowser) lose functionality (such as sorting
552 * in DatabaseBrowser).</LI>
553 * </UL>
554 *
555 * @param portletName
556 * Name of the portlet as defined in registry
557 * @param controlName
558 * Optional control name to use in displaying the portlet
559 * @return the rendered content of the portlet
560 */
561 public ConcreteElement getPortletFromRegistry(RunData data)
562 {
563
564 ConcreteElement result = null;
565 Portlet p = null;
566 String portletName = data.getParameters().getString("p");
567 String controlName = data.getParameters().getString("c");
568
569 try
570 {
571
572
573 PortletEntry entry = (PortletEntry) Registry.getEntry(Registry.PORTLET, portletName);
574
575
576 boolean canAccess = JetspeedSecurity.checkPermission((JetspeedUser) data.getUser(),
577 new PortalResource(entry),
578 JetspeedSecurity.PERMISSION_CUSTOMIZE);
579
580 if (canAccess)
581 {
582
583
584 p = PortletFactory.getPortlet(portletName, "preview");
585 PortletControl control = controlName == null ? PortalToolkit.getControl((String) null)
586 : PortalToolkit.getControl(controlName);
587 if (control != null)
588 {
589 JetspeedRunData jdata = (JetspeedRunData) rundata;
590
591 p.getPortletConfig().setPortletSkin(PortalToolkit.getSkin(jdata.getProfile().getDocument().getPortlets().getSkin()));
592 control.setPortlet(p);
593 control.init();
594 result = control.getContent(rundata);
595 }
596 else if (p != null)
597 {
598 result = p.getContent(rundata);
599 }
600 }
601 else
602 {
603 result = new JetspeedClearElement(Localization.getString(data, "SECURITY_NO_ACCESS_TO_PORTLET"));
604 }
605 }
606 catch (Exception e)
607 {
608 logger.error("Exception", e);
609 result = new ConcreteElement();
610 }
611
612 if (result == null)
613 {
614
615 result = new ConcreteElement();
616 }
617
618 return result;
619 }
620
621 /***
622 * Return the content of a portlet using the portlet's name. This portlet is sought in
623 * the registry. This is useful when you want to get portlet's content without
624 * actually having the portlet in user's profile (for example, to preview a portlet
625 * before adding it to the profile).
626 * <P>
627 * If a control name is specified to the portlet description, returns the defined
628 * portlet and control, otherwise use the default control.
629 * <P>
630 * Issues to resolve:
631 * <UL>
632 * <LI>is new portlet instance created everytime someone previews the same portlet?</LI>
633 * <LI>should use the same skin as the current pane</LI>
634 * <LI>if TitlePortletControl is used, the action icons (max, min, etc) are not functional.
635 * Also, customize icon should not be present.</LI>
636 * <LI> interactive portlets (such as DatabaseBrowser) lose functionality (such as sorting
637 * in DatabaseBrowser).</LI>
638 * </UL>
639 *
640 * @param portletName
641 * Name of the portlet as defined in registry
642 * @param controlName
643 * Optional control name to use in displaying the portlet
644 * @return the rendered content of the portlet
645 * @deprecated Do not use this method because it's not secure. It will be removed after Beta 5.
646 */
647 public ConcreteElement getPortletFromRegistry(String portletName, String controlName)
648 {
649
650 ConcreteElement result = null;
651 Portlet p = null;
652
653 try
654 {
655
656
657 p = PortletFactory.getPortlet(portletName, "preview");
658 PortletControl control = controlName == null ? PortalToolkit.getControl((String) null)
659 : PortalToolkit.getControl(controlName);
660 if (control != null)
661 {
662 JetspeedRunData jdata = (JetspeedRunData) rundata;
663
664 p.getPortletConfig().setPortletSkin(PortalToolkit.getSkin(jdata.getProfile().getDocument().getPortlets().getSkin()));
665 control.setPortlet(p);
666 control.init();
667 result = control.getContent(rundata);
668 }
669 else if (p != null)
670 {
671 result = p.getContent(rundata);
672 }
673 }
674 catch (Exception e)
675 {
676 logger.error("Exception", e);
677 result = new ConcreteElement();
678 }
679
680 if (result == null)
681 {
682
683 result = new ConcreteElement();
684 }
685
686 return result;
687 }
688
689 /***
690 * Returns a parameter in its defined parameter style
691 *
692 * @param data for this request
693 * @param portlet portlet instance
694 * @param parmName parameter name
695 * @return current parameter value using specified presentation style
696 */
697 public static String getPortletParameter(RunData data, Portlet portlet, String parmName)
698 {
699
700 if (portlet != null && parmName != null)
701 {
702 String parmValue = portlet.getPortletConfig().getInitParameter(parmName, "");
703 return getPortletParameter(data, portlet, parmName, parmValue);
704 }
705
706 return "";
707 }
708
709 /***
710 * Returns a parameter in its defined parameter style
711 *
712 * @param data for this request
713 * @param portlet portlet instance
714 * @param parmName parameter name
715 * @param parmValue current parameter value
716 * @return current parameter value using specified presentation style
717 */
718 public static String getPortletParameter(RunData data, Portlet portlet, String parmName, String parmValue)
719 {
720 String result = null;
721 try
722 {
723 if (portlet != null && parmName != null)
724 {
725
726 PortletEntry entry = (PortletEntry) Registry.getEntry(Registry.PORTLET, portlet.getName());
727 Parameter param = entry.getParameter(parmName);
728
729
730 boolean canAccess = JetspeedSecurity.checkPermission((JetspeedUser) data.getUser(),
731 new PortalResource(entry, param),
732 JetspeedSecurity.PERMISSION_CUSTOMIZE);
733 Map portletParms = portlet.getPortletConfig().getInitParameters();
734 String parmStyle = portlet.getPortletConfig().getInitParameter(parmName + ".style");
735
736
737 portletParms.put(parmName.concat(".style.portlet"), portlet);
738
739 if (canAccess)
740 {
741 if (parmStyle != null)
742 {
743 result = ParameterLoader.getInstance().eval(data,
744 parmStyle,
745 parmName,
746 parmValue,
747 portletParms);
748 }
749 else
750 {
751 result = "<input type=\"text\" name=\"" + parmName + "\" value=\"" + parmValue + "\"";
752 }
753 }
754 else
755 {
756
757 String parmNameNoAccess = portlet.getPortletConfig().getInitParameter(parmName + ".style.no-access");
758 if (parmNameNoAccess != null)
759 {
760 if (logger.isDebugEnabled())
761 {
762 logger.debug("JetspeedTool: access to parm [" + parmName + "] disallowed, redirecting to parm [" +
763 parmNameNoAccess + "]");
764 }
765 String parmStyleNoAccess = portlet.getPortletConfig().getInitParameter(parmNameNoAccess + ".style");
766 result = ParameterLoader.getInstance().eval(data,
767 parmStyleNoAccess,
768 parmNameNoAccess,
769 parmValue,
770 portletParms);
771 }
772 }
773 }
774 }
775 catch (Exception e)
776 {
777 logger.error("Exception", e);
778 }
779
780 return result;
781 }
782
783 /***
784 * Returns a parameter rendered in specific parameter style
785 *
786 * @param data for this request
787 * @param parmStyle parameter style
788 * @param parmName parameter name
789 * @param parmValue current parameter value
790 * @param options optional style parameters in delimited format (option1=value1;option2=value2)
791 * @return current parameter value using specified presentation style
792 */
793 public static String getParameter(RunData data, String parmStyle, String parmName, String parmValue, String parmOptions)
794 {
795 String result = null;
796 try
797 {
798 if (parmName != null)
799 {
800 if (parmStyle != null)
801 {
802 Map options = null;
803 if (parmOptions != null && parmOptions.length() > 0)
804 {
805 options = new Hashtable();
806
807 StringTokenizer st = new StringTokenizer(parmOptions, ";");
808 String prefix = parmName + ".style.";
809 while (st.hasMoreTokens())
810 {
811 StringTokenizer pair = new StringTokenizer(st.nextToken(), "=");
812 if (pair.countTokens() == 2)
813 {
814 options.put(prefix + pair.nextToken().trim(), pair.nextToken().trim());
815 }
816 }
817
818 }
819 result = ParameterLoader.getInstance().eval(data,
820 parmStyle,
821 parmName,
822 parmValue,
823 options);
824 }
825 else
826 {
827 result = "<input type=\"text\" name=\"" + parmName + "\" value=\"" + parmValue + "\"";
828 }
829 }
830 }
831 catch (Exception e)
832 {
833 logger.error("Exception", e);
834 result = "<input type=\"text\" name=\"" + parmName + "\" value=\"" + parmValue + "\"";
835 }
836
837 return result;
838 }
839
840 /***
841 * Retreives the correct SecurityReference for the portlet based on the current
842 * profile and the request.
843 */
844 public SecurityReference getSecurityReference(Entry entry)
845 {
846 return JetspeedSecurity.getSecurityReference(entry, rundata);
847 }
848
849 public int getSecuritySource(Entry entry)
850 {
851 return JetspeedSecurity.getSecuritySource(entry, rundata);
852 }
853
854 /***
855 * Retreives the Entry object for current portlet based on the
856 * "js_peid" parameter
857 */
858 public Entry getEntryFromRequest() throws Exception
859 {
860 String jsPeid = rundata.getParameters().getString("js_peid");
861 Profile profile = Profiler.getProfile(rundata);
862 PSMLDocument doc = profile.getDocument();
863 return doc.getEntryById(jsPeid);
864 }
865
866 }