1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.portlets.layout;
18
19 import java.io.IOException;
20 import java.util.HashMap;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.StringTokenizer;
24
25 import javax.portlet.ActionRequest;
26 import javax.portlet.ActionResponse;
27 import javax.portlet.PortletConfig;
28 import javax.portlet.PortletException;
29 import javax.portlet.PortletPreferences;
30 import javax.portlet.RenderRequest;
31 import javax.portlet.RenderResponse;
32
33 import org.apache.commons.configuration.Configuration;
34 import org.apache.commons.configuration.ConfigurationException;
35 import org.apache.commons.configuration.PropertiesConfiguration;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.jetspeed.CommonPortletServices;
39 import org.apache.jetspeed.JetspeedActions;
40 import org.apache.jetspeed.PortalReservedParameters;
41 import org.apache.jetspeed.capabilities.CapabilityMap;
42 import org.apache.jetspeed.components.portletentity.PortletEntityAccessComponent;
43 import org.apache.jetspeed.components.portletregistry.PortletRegistry;
44 import org.apache.jetspeed.container.window.PortletWindowAccessor;
45 import org.apache.jetspeed.layout.JetspeedPowerTool;
46 import org.apache.jetspeed.locator.LocatorDescriptor;
47 import org.apache.jetspeed.locator.TemplateDescriptor;
48 import org.apache.jetspeed.locator.TemplateLocator;
49 import org.apache.jetspeed.locator.TemplateLocatorException;
50 import org.apache.jetspeed.om.page.Fragment;
51 import org.apache.jetspeed.om.page.Page;
52 import org.apache.jetspeed.page.PageManager;
53 import org.apache.jetspeed.request.RequestContext;
54 import org.apache.jetspeed.velocity.JetspeedPowerToolFactory;
55 import org.apache.pluto.om.window.PortletWindow;
56
57 /***
58 */
59 public class LayoutPortlet extends org.apache.portals.bridges.common.GenericServletPortlet
60 {
61 public static final String GENERIC_TEMPLATE_TYPE = "generic";
62
63 public static final String FRAGMENT_PROCESSING_ERROR_PREFIX = "fragment.processing.error.";
64
65 public static final String FRAGMENT_ATTR = "fragment";
66
67 public static final String LAYOUT_ATTR = "layout";
68
69 public static final String HIDDEN = "hidden";
70
71 public static final String LAYOUT_TEMPLATE_TYPE = "layout";
72
73 public static final String DECORATOR_TYPE = "decorator";
74
75 public static final String PARAM_SOLO_PAGE = "SoloPage";
76
77
78 /*** Commons logging */
79 protected final static Log log = LogFactory.getLog(LayoutPortlet.class);
80
81 protected PortletRegistry registry;
82 protected PageManager pageManager;
83 protected JetspeedPowerToolFactory jptFactory;
84 protected TemplateLocator templateLocator;
85 protected PortletEntityAccessComponent entityAccess;
86 protected PortletWindowAccessor windowAccess;
87 protected TemplateLocator decorationLocator;
88
89
90 private Map layoutTemplateProperties = new HashMap();
91 public static final String DEFAULT_TEMPLATE_EXT = ".vm";
92 public static final String TEMPLATE_EXTENSION_KEY = "template.extension";
93 public static final String DEFAULT_TEMPLATE_TYPE = "velocity";
94 public static final String TEMPLATE_TYPE_KEY = "template.type";
95
96
97 public void init( PortletConfig config ) throws PortletException
98 {
99 super.init(config);
100
101 registry = (PortletRegistry)getPortletContext().getAttribute(CommonPortletServices.CPS_REGISTRY_COMPONENT);
102 if (null == registry)
103 {
104 throw new PortletException("Failed to find the Portlet Registry on portlet initialization");
105 }
106 pageManager = (PageManager)getPortletContext().getAttribute(CommonPortletServices.CPS_PAGE_MANAGER_COMPONENT);
107 if (null == pageManager)
108 {
109 throw new PortletException("Failed to find the Page Manager on portlet initialization");
110 }
111 jptFactory = (JetspeedPowerToolFactory)getPortletContext().getAttribute(CommonPortletServices.CPS_JETSPEED_POWERTOOL_FACTORY);
112 if (null == jptFactory)
113 {
114 throw new PortletException("Failed to find the JPT Factory on portlet initialization");
115 }
116
117 entityAccess = (PortletEntityAccessComponent) getPortletContext().getAttribute(CommonPortletServices.CPS_ENTITY_ACCESS_COMPONENT);
118 if (null == entityAccess)
119 {
120 throw new PortletException("Failed to find the Entity Access on portlet initialization");
121 }
122
123 windowAccess = (PortletWindowAccessor) getPortletContext().getAttribute(CommonPortletServices.CPS_WINDOW_ACCESS_COMPONENT);
124 if (null == windowAccess)
125 {
126 throw new PortletException("Failed to find the Window Access on portlet initialization");
127 }
128
129 templateLocator = (TemplateLocator) getPortletContext().getAttribute("TemplateLocator");
130 decorationLocator = (TemplateLocator) getPortletContext().getAttribute("DecorationLocator");
131 }
132
133 public void doHelp( RenderRequest request, RenderResponse response ) throws PortletException, IOException
134 {
135 response.setContentType("text/html");
136 JetspeedPowerTool jpt = getJetspeedPowerTool(request);
137
138 String absHelpPage = "";
139
140
141
142
143 try
144 {
145 String helpPage = (String)request.getPortletSession().getAttribute(PortalReservedParameters.PAGE_LAYOUT_HELP);
146 if (helpPage == null)
147 {
148 PortletPreferences prefs = request.getPreferences();
149 helpPage = prefs.getValue(PARAM_HELP_PAGE, null);
150 if (helpPage == null)
151 {
152 helpPage = this.getInitParameter(PARAM_HELP_PAGE);
153 if (helpPage == null)
154 helpPage = "columns";
155 }
156 request.getPortletSession().setAttribute(PortalReservedParameters.PAGE_LAYOUT_HELP, helpPage);
157 }
158
159
160 Configuration props = getConfiguration(request, helpPage);
161 String ext = (String) props.getString(TEMPLATE_EXTENSION_KEY);
162 absHelpPage = jpt.getTemplate(helpPage + "/" + JetspeedPowerTool.LAYOUT_TEMPLATE_TYPE + "-help" + ext,
163 JetspeedPowerTool.LAYOUT_TEMPLATE_TYPE).getAppRelativePath();
164 log.debug("Path to help page for LayoutPortlet " + absHelpPage);
165 request.setAttribute(PARAM_VIEW_PAGE, absHelpPage);
166 }
167 catch (TemplateLocatorException e)
168 {
169 throw new PortletException("Unable to locate view page " + absHelpPage, e);
170 }
171 super.doView(request, response);
172
173 }
174
175 /***
176 *
177 */
178 public void doView( RenderRequest request, RenderResponse response ) throws PortletException, IOException
179 {
180 response.setContentType("text/html");
181 RequestContext context = getRequestContext(request);
182 PortletWindow window = context.getPortalURL().getNavigationalState().getMaximizedWindow();
183 boolean maximized = (window != null);
184 boolean solo = false;
185
186 if (maximized)
187 {
188 request.setAttribute("layout", getMaximizedLayout(request));
189 solo = JetspeedActions.SOLO_STATE.equals(context.getPortalURL().getNavigationalState().getMappedState(window));
190 if ( solo )
191 {
192 maximized = false;
193 }
194 }
195 else
196 {
197 request.setAttribute("layout", getFragment(request, false));
198 }
199 String viewPage = null;
200 String absViewPage = null;
201 try
202 {
203 JetspeedPowerTool jpt = getJetspeedPowerTool(request);
204 if (maximized)
205 {
206 viewPage = (String)request.getPortletSession().getAttribute(PortalReservedParameters.PAGE_LAYOUT_MAX);
207 if (viewPage == null)
208 {
209 PortletPreferences prefs = request.getPreferences();
210 viewPage = prefs.getValue(PARAM_MAX_PAGE, null);
211 if (viewPage == null)
212 {
213 viewPage = this.getInitParameter(PARAM_MAX_PAGE);
214 if (viewPage == null)
215 viewPage = "maximized";
216 }
217 request.getPortletSession().setAttribute(PortalReservedParameters.PAGE_LAYOUT_MAX, viewPage);
218 }
219 }
220 else if (solo)
221 {
222 viewPage = (String)request.getPortletSession().getAttribute(PortalReservedParameters.PAGE_LAYOUT_SOLO);
223 if (viewPage == null)
224 {
225 PortletPreferences prefs = request.getPreferences();
226 viewPage = prefs.getValue(PARAM_SOLO_PAGE, null);
227 if (viewPage == null)
228 {
229 viewPage = this.getInitParameter(PARAM_SOLO_PAGE);
230 if (viewPage == null)
231 {
232 viewPage = "solo";
233 }
234 }
235 request.getPortletSession().setAttribute(PortalReservedParameters.PAGE_LAYOUT_SOLO, viewPage);
236 }
237 }
238 else
239 {
240 viewPage = (String)request.getPortletSession().getAttribute(PortalReservedParameters.PAGE_LAYOUT_VIEW);
241 if (viewPage == null)
242 {
243 PortletPreferences prefs = request.getPreferences();
244 viewPage = prefs.getValue(PARAM_VIEW_PAGE, null);
245 if (viewPage == null)
246 {
247 viewPage = this.getInitParameter(PARAM_VIEW_PAGE);
248 if (viewPage == null)
249 viewPage = "columns";
250 }
251 request.getPortletSession().setAttribute(PortalReservedParameters.PAGE_LAYOUT_VIEW, viewPage);
252 }
253 }
254
255
256 Configuration props = getConfiguration(request, viewPage);
257 String ext = (String) props.getString(TEMPLATE_EXTENSION_KEY);
258
259
260 absViewPage = jpt.getTemplate(viewPage + "/" + JetspeedPowerTool.LAYOUT_TEMPLATE_TYPE + ext,
261 JetspeedPowerTool.LAYOUT_TEMPLATE_TYPE).getAppRelativePath();
262 log.debug("Path to view page for LayoutPortlet " + absViewPage);
263 request.setAttribute(PARAM_VIEW_PAGE, absViewPage);
264 }
265 catch (TemplateLocatorException e)
266 {
267 throw new PortletException("Unable to locate view page " + absViewPage, e);
268 }
269 super.doView(request, response);
270
271 request.removeAttribute(PortalReservedParameters.PAGE_ATTRIBUTE);
272 request.removeAttribute("fragment");
273 request.removeAttribute("layout");
274 request.removeAttribute("dispatcher");
275 }
276
277 public void processAction(ActionRequest request, ActionResponse response)
278 throws PortletException, IOException
279 {
280 String page = request.getParameter("page");
281 String deleteFragmentId = request.getParameter("deleteId");
282 String portlets = request.getParameter("portlets");
283 if (deleteFragmentId != null && deleteFragmentId.length() > 0)
284 {
285 removeFragment(page, deleteFragmentId);
286 }
287 else if (portlets != null && portlets.length() > 0)
288 {
289 int count = 0;
290 StringTokenizer tokenizer = new StringTokenizer(portlets, ",");
291 while (tokenizer.hasMoreTokens())
292 {
293 String portlet = tokenizer.nextToken();
294 try
295 {
296 if (portlet.startsWith("box_"))
297 {
298 portlet = portlet.substring("box_".length());
299 addPortletToPage(page, portlet);
300 count++;
301 }
302 }
303 catch (Exception e)
304 {
305 log.error("failed to add portlet to page: " + portlet);
306 }
307 }
308
309 }
310 }
311
312 protected void removeFragment(String pageId, String fragmentId)
313 {
314 Page page = null;
315 try
316 {
317 page = pageManager.getPage(pageId);
318
319 }
320 catch (Exception e)
321 {
322 log.error("failed to remove portlet " + fragmentId + " from page: " + pageId, e);
323 }
324 removeFragment(page,page.getRootFragment(), fragmentId);
325 }
326
327 protected void removeFragment(Page page, Fragment root, String fragmentId)
328 {
329 try
330 {
331 Fragment f = page.getFragmentById(fragmentId);
332 if ( f == null )
333 {
334
335 return;
336 }
337 root.getFragments().remove(f);
338 pageManager.updatePage(page);
339 }
340 catch (Exception e)
341 {
342 log.error("failed to remove portlet " + fragmentId + " from page: " + page, e);
343 }
344 }
345
346 protected void addPortletToPage(String pageId, String portletId)
347 {
348 Page page = null;
349 try
350 {
351 page = pageManager.getContentPage(pageId);
352 }
353 catch (Exception e)
354 {
355 log.error("failed to add portlet " + portletId + " to page: " + pageId, e);
356 }
357 addPortletToPage(page, page.getRootFragment(), portletId);
358 }
359
360 protected void addPortletToPage(Page page, Fragment root, String portletId)
361 {
362 try
363 {
364 Fragment fragment = pageManager.newFragment();
365 fragment.setType(Fragment.PORTLET);
366 fragment.setName(portletId);
367
368 root.getFragments().add(fragment);
369 pageManager.updatePage(page);
370 }
371 catch (Exception e)
372 {
373 log.error("failed to add portlet " + portletId + " to page: " + page, e);
374 }
375 }
376
377 /***
378 * <p>
379 * initJetspeedPowerTool
380 * </p>
381 *
382 * @param request
383 * @param response
384 * @return
385 * @throws PortletException
386 */
387 protected JetspeedPowerTool getJetspeedPowerTool( RenderRequest request ) throws PortletException
388 {
389 JetspeedPowerTool tool = (JetspeedPowerTool) request.getAttribute(PortalReservedParameters.JETSPEED_POWER_TOOL_REQ_ATTRIBUTE);
390 RequestContext requestContext = (RequestContext) request.getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
391
392 if (tool == null)
393 {
394
395 try
396 {
397 if (requestContext == null)
398 {
399 throw new IllegalStateException(
400 "LayoutPortlet unable to handle request because there is no RequestContext in "
401 + "the HttpServletRequest.");
402 }
403
404 tool = this.jptFactory.getJetspeedPowerTool(requestContext);
405 request.setAttribute(PortalReservedParameters.JETSPEED_POWER_TOOL_REQ_ATTRIBUTE, tool);
406 }
407
408 catch (Exception e1)
409 {
410 throw new PortletException("Unable to init JetspeedPowerTool: " + e1.toString(), e1);
411 }
412 }
413
414 return tool;
415 }
416
417 /***
418 *
419 * @param request
420 * @param maximized
421 * @return
422 */
423 protected Fragment getFragment( RenderRequest request, boolean maximized )
424 {
425 String attribute = (maximized)
426 ? PortalReservedParameters.MAXIMIZED_FRAGMENT_ATTRIBUTE
427 : PortalReservedParameters.FRAGMENT_ATTRIBUTE;
428 return (Fragment) request.getAttribute(attribute);
429 }
430
431 /***
432 *
433 * @param request
434 * @return
435 */
436 protected Fragment getMaximizedLayout( RenderRequest request )
437 {
438 return (Fragment) request.getAttribute(PortalReservedParameters.MAXIMIZED_LAYOUT_ATTRIBUTE);
439 }
440
441 /***
442 *
443 * @param request
444 * @return
445 */
446 protected RequestContext getRequestContext( RenderRequest request )
447 {
448 RequestContext requestContext = (RequestContext) request
449 .getAttribute(PortalReservedParameters.REQUEST_CONTEXT_ATTRIBUTE);
450 if (requestContext != null)
451 {
452 return requestContext;
453 }
454 else
455 {
456 throw new IllegalStateException(
457 "getRequestContext() failed as it appears that no RenderRequest is available within the RenderRequest");
458 }
459 }
460
461 /***
462 * <p>
463 * doEdit
464 * </p>
465 *
466 * @see javax.portlet.GenericPortlet#doEdit(javax.portlet.RenderRequest,
467 * javax.portlet.RenderResponse)
468 * @param request
469 * @param response
470 * @throws PortletException
471 * @throws IOException
472 */
473 public void doEdit( RenderRequest request, RenderResponse response ) throws PortletException, IOException
474 {
475 doView(request, response);
476 }
477
478 /***
479 *
480 * @param request
481 * @return
482 * @throws TemplateLocatorException
483 */
484 protected LocatorDescriptor getTemplateLocatorDescriptor(RenderRequest request) throws TemplateLocatorException
485 {
486 RequestContext requestContext = getRequestContext(request);
487 CapabilityMap capabilityMap = requestContext.getCapabilityMap();
488 Locale locale = requestContext.getLocale();
489
490 LocatorDescriptor templateLocatorDescriptor = templateLocator.createLocatorDescriptor(null);
491 templateLocatorDescriptor.setMediaType(capabilityMap.getPreferredMediaType().getName());
492 templateLocatorDescriptor.setCountry(locale.getCountry());
493 templateLocatorDescriptor.setLanguage(locale.getLanguage());
494 return templateLocatorDescriptor;
495 }
496
497
498 /***
499 *
500 * @param request
501 * @return
502 * @throws TemplateLocatorException
503 */
504 protected LocatorDescriptor getDecoratorLocatorDescriptor(RenderRequest request) throws TemplateLocatorException
505 {
506 RequestContext requestContext = getRequestContext(request);
507 CapabilityMap capabilityMap = requestContext.getCapabilityMap();
508 Locale locale = requestContext.getLocale();
509
510 LocatorDescriptor decorationLocatorDescriptor = decorationLocator.createLocatorDescriptor(null);
511 decorationLocatorDescriptor.setMediaType(capabilityMap.getPreferredMediaType().getName());
512 decorationLocatorDescriptor.setCountry(locale.getCountry());
513 decorationLocatorDescriptor.setLanguage(locale.getLanguage());
514
515 return decorationLocatorDescriptor;
516 }
517
518 /***
519 *
520 * @param request
521 * @param fragment
522 * @param page
523 * @return
524 * @throws TemplateLocatorException
525 * @throws ConfigurationException
526 */
527 public String decorateAndInclude(RenderRequest request, Fragment fragment, Page page) throws TemplateLocatorException, ConfigurationException
528 {
529 String fragmentType = fragment.getType();
530 String decorator = fragment.getDecorator();
531 LocatorDescriptor decorationLocatorDescriptor = getDecoratorLocatorDescriptor(request);
532 if (decorator == null)
533 {
534 decorator = page.getEffectiveDefaultDecorator(fragmentType);
535 }
536
537
538 TemplateDescriptor propsTemp = getTemplate(decorator + "/" + DECORATOR_TYPE + ".properties", fragmentType,
539 decorationLocator, decorationLocatorDescriptor);
540 if (propsTemp == null)
541 {
542 fragmentType = GENERIC_TEMPLATE_TYPE;
543 propsTemp = getTemplate(decorator + "/" + DECORATOR_TYPE + ".properties", fragmentType, decorationLocator,
544 decorationLocatorDescriptor);
545 }
546
547
548 Configuration decoConf = new PropertiesConfiguration(propsTemp.getAbsolutePath());
549 String ext = decoConf.getString("template.extension");
550 String decoratorPath = decorator + "/" + DECORATOR_TYPE + ext;
551 TemplateDescriptor template = null;
552 try
553 {
554 template = getDecoration(request, decoratorPath, fragmentType);
555 }
556 catch (TemplateLocatorException e)
557 {
558 String parent = decoConf.getString("extends");
559 if (parent != null)
560 {
561 template = getDecoration(request, parent + "/" + DECORATOR_TYPE + ext, fragmentType);
562 }
563 }
564
565 return template.getAppRelativePath();
566 }
567
568 /***
569 *
570 * @param request
571 * @param path
572 * @param templateType
573 * @return
574 * @throws TemplateLocatorException
575 */
576 protected TemplateDescriptor getDecoration( RenderRequest request, String path, String templateType ) throws TemplateLocatorException
577 {
578 return getTemplate(path, templateType, decorationLocator, getDecoratorLocatorDescriptor(request));
579 }
580
581 /***
582 *
583 * @param path
584 * @param templateType
585 * @param locator
586 * @param descriptor
587 * @return
588 * @throws TemplateLocatorException
589 */
590 protected TemplateDescriptor getTemplate( String path, String templateType, TemplateLocator locator,
591 LocatorDescriptor descriptor ) throws TemplateLocatorException
592 {
593
594 if (templateType == null)
595 {
596 templateType = GENERIC_TEMPLATE_TYPE;
597 }
598 try
599 {
600
601 descriptor.setName(path);
602 descriptor.setType(templateType);
603
604 TemplateDescriptor template = locator.locateTemplate(descriptor);
605 return template;
606 }
607 catch (TemplateLocatorException e)
608 {
609 log.error("Unable to locate template: " + path, e);
610
611 throw e;
612 }
613 }
614
615 /***
616 * Gets the configuration (layout.properties) object for the decoration.
617 * @param name Name of the Decoration.
618 * @return <code>java.util.Properties</code> representing the configuration
619 * object.
620 */
621 protected Configuration getConfiguration( RenderRequest request, String name )
622 {
623 Configuration props = null;
624 JetspeedPowerTool jpt = null;
625 String templatePropertiesPath = null;
626 String key = name;
627 try
628 {
629 jpt = getJetspeedPowerTool(request);
630 templatePropertiesPath = jpt.getTemplate(name + "/" + JetspeedPowerTool.LAYOUT_TEMPLATE_TYPE + ".properties",
631 JetspeedPowerTool.LAYOUT_TEMPLATE_TYPE).getAbsolutePath();
632 }
633 catch (PortletException e)
634 {
635 log.warn("Could not acquire JetspeedPowerTool from request",e);
636 }
637 catch (TemplateLocatorException e)
638 {
639 log.warn("Could not find templatePorpertiesPath",e);
640 }
641 catch (Exception e)
642 {
643 log.warn("Could not determine Layout template properties file",e);
644 }
645
646 if (null == templatePropertiesPath)
647 {
648 key = "default";
649 }
650 else
651 {
652 key = templatePropertiesPath;
653 }
654 props = (Configuration)this.layoutTemplateProperties.get(key);
655
656 if ( props != null )
657 {
658 return props;
659 }
660 if (log.isDebugEnabled()){
661 log.debug(
662 "Template descriptor path:<" + templatePropertiesPath + ">"
663 );
664 }
665
666
667 try
668 {
669 props = new PropertiesConfiguration(templatePropertiesPath);
670 if (log.isDebugEnabled())
671 log.debug("Successfully read in: <" + templatePropertiesPath + "> ");
672 }
673 catch (Exception e)
674 {
675 props = new PropertiesConfiguration();
676 log.warn( "Could not locate the " + templatePropertiesPath + " file for layout template \"" + name + "\". This layout template may not exist.",e );
677 props.setProperty( "id", name );
678 props.setProperty( TEMPLATE_TYPE_KEY, DEFAULT_TEMPLATE_TYPE );
679 props.setProperty( TEMPLATE_EXTENSION_KEY, DEFAULT_TEMPLATE_EXT);
680 }
681 finally
682 {
683 String templateIdPropVal = (String) props.getProperty( "id" );
684 String templateNamePropVal = (String) props.getProperty( TEMPLATE_TYPE_KEY );
685 String templateExtPropVal = (String) props.getProperty(TEMPLATE_EXTENSION_KEY);
686
687 if ( templateIdPropVal == null )
688 {
689 templateIdPropVal = name;
690 props.setProperty( "id", templateIdPropVal );
691 }
692
693 if ( templateNamePropVal == null )
694 {
695 props.setProperty( TEMPLATE_TYPE_KEY, DEFAULT_TEMPLATE_TYPE );
696 }
697 if ( templateExtPropVal == null )
698 {
699 props.setProperty( TEMPLATE_EXTENSION_KEY, DEFAULT_TEMPLATE_EXT );
700 }
701 }
702
703 this.layoutTemplateProperties.put(key, props);
704 if (log.isDebugEnabled())
705 {
706 log.debug("Template layout.properties extension is:<" + props.getString(TEMPLATE_EXTENSION_KEY));
707 }
708 return props;
709 }
710
711 }