weaver 2004/01/12 14:50:32
Modified: portal/src/java/org/apache/jetspeed/velocity
JetspeedPowerTool.java
Log:
Now supports smart decorators and decorator folders. Smart
decorators are single template as opposed to a -top and a -bottom.
Revision Changes Path
1.3 +191 -115
jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/velocity/JetspeedPowerTool.java
Index: JetspeedPowerTool.java
===================================================================
RCS file:
/home/cvs/jakarta-jetspeed-2/portal/src/java/org/apache/jetspeed/velocity/JetspeedPowerTool.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- JetspeedPowerTool.java 12 Jan 2004 19:25:43 -0000 1.2
+++ JetspeedPowerTool.java 12 Jan 2004 22:50:32 -0000 1.3
@@ -55,13 +55,18 @@
import java.io.IOException;
import java.util.List;
+import java.util.Stack;
import javax.portlet.PortletConfig;
+import javax.portlet.PortletException;
import javax.portlet.PortletRequest;
+import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletResponse;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jetspeed.aggregator.ContentDispatcher;
@@ -120,6 +125,10 @@
public static final String FRAGMENT_ATTR = "fragment";
public static final String HIDDEN = "hidden";
+ public static final String LAYOUT_TEMPLATE_TYPE = "layout";
+ public static final String DECORATOR_TEMPLATE_TYPE = "decorator";
+ public static final String GENERIC_TEMPLATE_TYPE = "generic";
+
private RenderRequest renderRequest;
private RenderResponse renderResponse;
@@ -128,6 +137,8 @@
private ViewContext viewCtx;
+ private Stack fragmentStack;
+
private static final Log log = LogFactory.getLog(JetspeedPowerTool.class);
/**
@@ -151,6 +162,7 @@
renderRequest = request;
renderResponse = resp;
portletConfig = config;
+ fragmentStack = new Stack();
}
/**
@@ -168,7 +180,7 @@
}
else if (obj instanceof PortletRequest)
{
- RenderRequest request = (RenderRequest) obj;
+ RenderRequest request = (RenderRequest) obj;
ctx = (Context)
request.getAttribute(JetspeedVelocityViewServlet.VELOCITY_CONTEXT_ATTR);
setRequest(request);
}
@@ -180,6 +192,7 @@
renderRequest = (RenderRequest) ctx.get(Constants.PORTLET_REQUEST);
renderResponse = (RenderResponse) ctx.get(Constants.PORTLET_RESPONSE);
portletConfig = (PortletConfig) ctx.get(Constants.PORTLET_CONFIG);
+ fragmentStack = new Stack();
}
@@ -190,44 +203,44 @@
{
this.renderRequest = request;
}
-
- /**
- *
- * @return
- */
+
+ /**
+ *
+ * @return
+ */
public Fragment getCurrentFragment()
{
- checkState();
+ checkState();
return (Fragment) renderRequest.getAttribute(FRAGMENT_ATTR);
}
-
- /**
- *
- * @param f
- */
+
+ /**
+ *
+ * @param f
+ */
public void setCurrentFragment(Fragment f)
{
- checkState();
+ checkState();
renderRequest.setAttribute(FRAGMENT_ATTR, f);
}
-
- /**
- *
- * @return
- */
+
+ /**
+ *
+ * @return
+ */
public Page getPage()
{
- checkState();
+ checkState();
return (Page) renderRequest.getAttribute(PAGE_ATTR);
}
-
- /**
- *
- * @return
- */
+
+ /**
+ *
+ * @return
+ */
public List[] getColumns()
{
- checkState();
+ checkState();
return (List[]) renderRequest.getAttribute(COLUMNS_ATTR);
}
@@ -237,8 +250,9 @@
*/
public PortletEntity getCurrentPortletEntity()
{
- PortletEntity portletEntity =
-
PortletEntityAccess.getEntity(JetspeedObjectID.createFromString(getCurrentFragment().getId()));
+ String fragmentId = getCurrentFragment().getId();
+ JetspeedObjectID peid = JetspeedObjectID.createFromString(fragmentId);
+ PortletEntity portletEntity = PortletEntityAccess.getEntity(peid);
return portletEntity;
}
@@ -252,60 +266,63 @@
PortletEntity portletEntity =
PortletEntityAccess.getEntity(JetspeedObjectID.createFromString(f.getId()));
return portletEntity;
}
-
- /**
- * This method is synonymous with the following code:
- * <p>
- * <code>
- * ContentDispatcher dispatcher = (ContentDispatcher)
renderRequest.getAttribute("dispatcher");<br />
- * </code>
- * </p>
- * @see org.apache.jetspeed.aggregator.ContentDispatcher
- * <strong>BEST PRACTICE:</strong> Use this method in templates instead of
- * directly using the equivalent code defined above.
- * @return ContentDispatcher for the RenderRequest
- */
+
+ /**
+ * This method is synonymous with the following code:
+ * <p>
+ * <code>
+ * ContentDispatcher dispatcher = (ContentDispatcher)
renderRequest.getAttribute("dispatcher");<br />
+ * </code>
+ * </p>
+ * @see org.apache.jetspeed.aggregator.ContentDispatcher
+ * <strong>BEST PRACTICE:</strong> Use this method in templates instead of
+ * directly using the equivalent code defined above.
+ * @return ContentDispatcher for the RenderRequest
+ */
public ContentDispatcher getContentDispatcher()
{
- checkState();
+ checkState();
return (ContentDispatcher) renderRequest.getAttribute(DISPATCHER_ATTR);
}
-
-
- /**
- * Checks the the visibilty of this fragment with respect to the current
RenderReqeust.
- * @param f Fragment
- * @return whether or not the Fragment in question should be considered
visible during rendering.
- */
+
+ /**
+ * Checks the the visibilty of this fragment with respect to the current
RenderReqeust.
+ * @param f Fragment
+ * @return whether or not the Fragment in question should be considered visible
during rendering.
+ */
public boolean isHidden(Fragment f)
{
- checkState();
+ checkState();
if (f == null)
{
throw new IllegalArgumentException("Fragment cannot be null for
isHidden(Fragment)");
}
return f.getState() != null && f.getState().equals(HIDDEN);
}
-
-
- /**
- * Retreives a template using Jetspeed's @see
org.apache.jetspeed.cps.template.TemplateLocatorService
- *
- *
- * @param path Expected to the template. This may actually be changed by the
TL service
- * based the capability and localization information provided by the client.
- * @return Template object containng the pertinent information required to
inlcude the
- * request template path in the current response
- * @throws TemplateLocatorException if the <code>path</code> does not exist.
- */
- public Template getTemplate(String path) throws TemplateLocatorException
+
+ /**
+ * Retreives a template using Jetspeed's @see
org.apache.jetspeed.cps.template.TemplateLocatorService
+ *
+ *
+ * @param path Expected to the template. This may actually be changed by the
TL service
+ * based the capability and localization information provided by the client.
+ * @param templateType Type off template we are interested in.
+ * @return Template object containng the pertinent information required to
inlcude the
+ * request template path in the current response
+ * @throws TemplateLocatorException if the <code>path</code> does not exist.
+ */
+ public Template getTemplate(String path, String templateType) throws
TemplateLocatorException
{
- checkState();
+ checkState();
+ if (templateType == null)
+ {
+ templateType = GENERIC_TEMPLATE_TYPE;
+ }
try
{
TemplateLocatorService tls =
(TemplateLocatorService)
CommonPortletServices.getPortalService(TemplateLocatorService.SERVICE_NAME);
- TemplateLocator locator = tls.createLocator("layout");
+ TemplateLocator locator = tls.createLocator(templateType);
locator.setName(path);
Template template = tls.locateTemplate(locator);
return template;
@@ -318,60 +335,116 @@
}
}
-
- /**
- * Includes a portal Fragment into the current <code>RenderResponse.</code>
- * This is the same as calling:
- * <p>
- * <code>
- * ContentDispatcher dispatcher = (ContentDispatcher)
renderRequest.getAttribute("dispatcher");<br />
- * dispatcher.include(fragment, renderRequest, renderResponse);<br />
- * </code>
- * </p>
- * <strong>BEST PRACTICE:</strong> Use this method in templates instead of
- * directly using the equivalent code defined above.
- * @param f Fragment to include.
- * @throws IOException
- */
+
+ /**
+ * Includes a portal Fragment into the current <code>RenderResponse.</code>
+ * This is the same as calling:
+ * <p>
+ * <code>
+ * ContentDispatcher dispatcher = (ContentDispatcher)
renderRequest.getAttribute("dispatcher");<br />
+ * dispatcher.include(fragment, renderRequest, renderResponse);<br />
+ * </code>
+ * </p>
+ * <strong>BEST PRACTICE:</strong> Use this method in templates instead of
+ * directly using the equivalent code defined above.
+ * @param f Fragment to include.
+ * @throws IOException
+ */
public void include(Fragment f) throws IOException
{
- checkState();
+ checkState();
+
// We need to flush so that content gets render in the correct place
- if(viewCtx != null)
+ flush();
+ getContentDispatcher().include(f, renderRequest, renderResponse);
+
+ }
+
+ /**
+ *
+ */
+ public void flush() throws IOException
+ {
+ checkState();
+ if (viewCtx != null)
{
- VelocityWriter vw = (VelocityWriter)
viewCtx.getVelocityContext().get(JetspeedVelocityViewServlet.VELOCITY_WRITER_ATTR);
- vw.flush();
+ VelocityWriter vw = (VelocityWriter)
viewCtx.getVelocityContext().get(JetspeedVelocityViewServlet.VELOCITY_WRITER_ATTR);
+ vw.flush();
}
- getContentDispatcher().include(f, renderRequest, renderResponse);
}
- // public String include(String template) throws IOException
- // {
- //
- // // RequestDispatcher dispatcher =
viewCtx.getRequest().getRequestDispatcher(template);
- // StringWriter buf = new StringWriter();
- // try
- // {
- // Velocity.mergeTemplate(template, "UTF-8",
viewCtx.getVelocityContext(), buf);
- // }
- // catch (Exception e)
- // {
- // // TODO Auto-generated catch block
- // e.printStackTrace();
- // }
-
- // }
-
- /**
- *
- */
- public void flush() throws IOException
+ /**
+ * <p>
+ * This does not actaully "include()" as per the ContentDispatcher, instead,
+ * it locates the decorator for this Fragment or, if none has been defined the
+ * default decorator for this Fragment type from the parent Page.
+ * </p>
+ * <p>
+ * The decorator template itself is responsible for inlcluding the content
+ * of the target Fragment which is easily acheived like so:
+ * <br />
+ * in Velocity:
+ * <pre>
+ * <code>
+ * $jetspeed.include($jetspeed.currentFragment)
+ * </code>
+ * </pre>
+ * In JSP:
+ * <pre>
+ * <code>
+ * <%
+ * JetspeedPowerTool jetspeed = new JetspeedPowerTool(renderRequest,
renderResponse, portletConfig);
+ * jetspeed.include(jetspeed.getCurrentFragment());
+ * %>
+ * </code>
+ * </pre>
+ *
+ *
+ * @param f Fragment to "decorate"
+ * @throws IOException
+ * @throws TemplateLocatorException
+ */
+ public void decorateAndInclude(Fragment f) throws TemplateLocatorException,
PortletException, IOException
{
- checkState();
- // ((RenderResponse)renderResponse ).flushBuffer();
- viewCtx.getResponse().getWriter().flush();
+ // makes sure that any previous content has been written to
+ // preserve natural HTML rendering order
+ flush();
+ String decorator = f.getDecorator();
+ // Fallback to the default decorator if the current fragment is not
+ // specifically decorated
+ if (decorator == null)
+ {
+ decorator = getPage().getDefaultDecorator(f.getType());
+ }
+
+ Template propsTemp = getTemplate(decorator + "/" + DECORATOR_TEMPLATE_TYPE
+ ".properties", DECORATOR_TEMPLATE_TYPE);
+
+ Configuration decoConf = new
PropertiesConfiguration(propsTemp.getAbsolutePath());
+ String ext = decoConf.getString("template.extension");
+
+ // Set this fragment as the current fragment, making sure
+ // the last currentFragment goes on to the fragmentStack
+ if (getCurrentFragment() != null)
+ {
+ fragmentStack.push(getCurrentFragment());
+ }
+ setCurrentFragment(f);
+
+ String decoratorPath = decorator + "/" + DECORATOR_TEMPLATE_TYPE + ext;
+ Template template = getTemplate(decoratorPath, DECORATOR_TEMPLATE_TYPE);
+ PortletRequestDispatcher prd =
portletConfig.getPortletContext().getRequestDispatcher(template.getAppRelativePath());
+ prd.include(renderRequest, renderResponse);
+
+ // Now that were are done with this fragment reset to the last "current"
fragment
+ Fragment lastFragment = (Fragment) fragmentStack.pop();
+ if (lastFragment != null)
+ {
+ setCurrentFragment(lastFragment);
+ }
}
-
+
+
+
/**
*
*
@@ -380,11 +453,14 @@
*/
private void checkState()
{
- if(portletConfig == null || renderRequest == null || renderResponse == null)
- {
- throw new IllegalStateException("JetspeedPowerTool has not been
properly initialized. "+ "" +
"The
JetspeedPowerTool generally only usuable during the rendering phase of "+
- "internal
portlet applications.");
- }
+ if (portletConfig == null || renderRequest == null || renderResponse ==
null)
+ {
+ throw new IllegalStateException(
+ "JetspeedPowerTool has not been properly initialized. "
+ + ""
+ + "The JetspeedPowerTool generally only usuable during the
rendering phase of "
+ + "internal portlet applications.");
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]