Prototypes implementation of the JSR286 compatible portlet for serving content items
git-svn-id: https://svn.libreccm.org/ccm/trunk@2739 8810af33-2d31-482b-a856-94f89814c4dfmaster
parent
ea1128367c
commit
435f024233
|
|
@ -18,24 +18,35 @@
|
|||
*/
|
||||
package com.arsdigita.cms.portlet;
|
||||
|
||||
import com.arsdigita.bebop.Page;
|
||||
import com.arsdigita.bebop.PageFactory;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.SimpleComponent;
|
||||
import com.arsdigita.cms.CMS;
|
||||
import com.arsdigita.cms.ContentBundle;
|
||||
import com.arsdigita.cms.ContentItem;
|
||||
import com.arsdigita.cms.ContentPage;
|
||||
import com.arsdigita.cms.ContentSection;
|
||||
import com.arsdigita.cms.ContentSectionCollection;
|
||||
import com.arsdigita.cms.ItemCollection;
|
||||
import com.arsdigita.cms.dispatcher.SimpleXMLGenerator;
|
||||
import com.arsdigita.cms.portlet.utils.HttpServletRequestAdapter;
|
||||
import com.arsdigita.cms.portlet.utils.HttpServletResponseAdapter;
|
||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||
import com.arsdigita.domain.DomainObjectFactory;
|
||||
import com.arsdigita.globalization.GlobalizationHelper;
|
||||
import com.arsdigita.persistence.OID;
|
||||
import com.arsdigita.portal.JSRPortlet;
|
||||
import com.arsdigita.templating.PresentationManager;
|
||||
import com.arsdigita.templating.Templating;
|
||||
import com.arsdigita.xml.Document;
|
||||
import com.arsdigita.xml.Element;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletException;
|
||||
|
|
@ -43,6 +54,9 @@ import javax.portlet.PortletPreferences;
|
|||
import javax.portlet.PortletRequestDispatcher;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
|
@ -83,13 +97,13 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
*/
|
||||
@Override
|
||||
protected void doEdit(final RenderRequest request, final RenderResponse response)
|
||||
throws PortletException, IOException {
|
||||
throws PortletException, IOException {
|
||||
//response.setContentType("text/html");
|
||||
//PrintWriter writer = new PrintWriter(response.getWriter());
|
||||
//writer.println("You're now in Edit mode.");
|
||||
final ContentSectionCollection contentSections = ContentSection.getAllSections();
|
||||
final List<ContentSection> sections = new ArrayList<ContentSection>((int) contentSections
|
||||
.size());
|
||||
.size());
|
||||
|
||||
while (contentSections.next()) {
|
||||
sections.add(contentSections.getContentSection());
|
||||
|
|
@ -101,7 +115,7 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
|
||||
if ((selectedContentSection != null)) {
|
||||
final ContentSection selectedSection = new ContentSection(OID.valueOf(
|
||||
selectedContentSection));
|
||||
selectedContentSection));
|
||||
final ItemCollection items = selectedSection.getItems();
|
||||
items.addFilter(String.format("(lower(name) LIKE lower('%%%s%%'))", search));
|
||||
items.addVersionFilter(true);
|
||||
|
|
@ -119,7 +133,7 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
request.setAttribute("errors", errors);
|
||||
|
||||
final String itemOID = request.getPreferences().getValue(response.getNamespace().concat(
|
||||
PREFS_SELECTED_ITEM), "");
|
||||
PREFS_SELECTED_ITEM), "");
|
||||
if (!itemOID.isEmpty()) {
|
||||
try {
|
||||
final OID oid = OID.valueOf(itemOID);
|
||||
|
|
@ -148,15 +162,15 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
//errors.add(String.format("The OID '%s' set in the preferences is invalid.",
|
||||
// itemOID));
|
||||
errors.add(MessageFormat.format(getResourceBundle(request.getLocale()).getString(
|
||||
"contentItemJSRPortlet.errors.perferences.illegal_oid"),
|
||||
"contentItemJSRPortlet.errors.perferences.illegal_oid"),
|
||||
itemOID));
|
||||
} catch (DataObjectNotFoundException ex) {
|
||||
//errors.add(String.format("The item identified by the OID '%s' does not exist.",
|
||||
// itemOID));
|
||||
errors.add(MessageFormat.format(
|
||||
getResourceBundle(request.getLocale()).getString(
|
||||
"contentItemJSRPortlet.errors.perferences.item_does_not_exist"),
|
||||
itemOID));
|
||||
getResourceBundle(request.getLocale()).getString(
|
||||
"contentItemJSRPortlet.errors.perferences.item_does_not_exist"),
|
||||
itemOID));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,7 +178,7 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
|
||||
//request.setAttribute("helloworld", "Hello World Attribute");
|
||||
final PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher(
|
||||
"/templates/portlets/ContentItemJSRPortletAdmin.jsp");
|
||||
"/templates/portlets/ContentItemJSRPortletAdmin.jsp");
|
||||
dispatcher.include(request, response);
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +192,7 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
*/
|
||||
@Override
|
||||
protected void doHelp(final RenderRequest request, final RenderResponse response)
|
||||
throws PortletException, IOException {
|
||||
throws PortletException, IOException {
|
||||
response.setContentType("text/html");
|
||||
final PrintWriter writer = new PrintWriter(response.getWriter());
|
||||
writer.println("You're now in Help mode.");
|
||||
|
|
@ -194,10 +208,38 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
*/
|
||||
@Override
|
||||
protected void doView(final RenderRequest request, final RenderResponse response)
|
||||
throws PortletException, IOException {
|
||||
response.setContentType("text/html");
|
||||
final PrintWriter writer = new PrintWriter(response.getWriter());
|
||||
writer.println("Hello world! You're in View mode.");
|
||||
throws PortletException, IOException {
|
||||
// response.setContentType("text/html");
|
||||
// final PrintWriter writer = new PrintWriter(response.getWriter());
|
||||
// writer.println("Hello world! You're in View mode.");
|
||||
|
||||
final String itemOID = request.getPreferences().getValue(response.getNamespace().concat(
|
||||
PREFS_SELECTED_ITEM), "");
|
||||
|
||||
if (itemOID.isEmpty()) {
|
||||
final PrintWriter writer = response.getWriter();
|
||||
writer.append("<div>");
|
||||
writer.append(getResourceBundle(request.getLocale()).getString(
|
||||
"contentItemJSRPortlet.no_item_configured"));
|
||||
writer.append("</div>");
|
||||
} else {
|
||||
try {
|
||||
final OID oid = OID.valueOf(itemOID);
|
||||
|
||||
final BigDecimal itemId = (BigDecimal) oid.get("id");
|
||||
final PortletRequestDispatcher dispatcher = getPortletContext().
|
||||
getRequestDispatcher(String.format(
|
||||
"/portlets/content-item-portlet-servlet/items/%s",
|
||||
itemId.toString()));
|
||||
dispatcher.include(request, response);
|
||||
|
||||
} catch (IllegalArgumentException ex) {
|
||||
writeMessage(request,
|
||||
response,
|
||||
"contentItemJSRPortlet.errors.parameters.illegal_oid",
|
||||
itemOID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -233,16 +275,66 @@ public class ContentItemJSRPortlet extends JSRPortlet {
|
|||
|
||||
} catch (IllegalArgumentException ex) {
|
||||
errors.add(MessageFormat.format(getResourceBundle(actionRequest.getLocale()).
|
||||
getString("contentItemJSRPortlet.errors.parameters.illegal_oid"),
|
||||
getString("contentItemJSRPortlet.errors.parameters.illegal_oid"),
|
||||
itemOID));
|
||||
} catch (DataObjectNotFoundException ex) {
|
||||
errors.add(MessageFormat.format(getResourceBundle(actionRequest.getLocale())
|
||||
.getString(
|
||||
"contentItemJSRPortlet.errors.parameters.item_does_not_exist"),
|
||||
.getString(
|
||||
"contentItemJSRPortlet.errors.parameters.item_does_not_exist"),
|
||||
itemOID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeMessage(final RenderRequest request,
|
||||
final RenderResponse response,
|
||||
final String msgKey,
|
||||
final Object... args) throws IOException {
|
||||
final PrintWriter writer = response.getWriter();
|
||||
writer.append("<div>");
|
||||
writer.append(MessageFormat.format(getResourceBundle(request.getLocale()).
|
||||
getString(msgKey), args));
|
||||
writer.append("</div>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Special component to make it possible to use special XSL for the data served by the
|
||||
* PortletDataProvider
|
||||
*
|
||||
*/
|
||||
private class PortletDataItemPanel extends SimpleComponent {
|
||||
|
||||
private final XMLGenerator xmlGenerator;
|
||||
|
||||
public PortletDataItemPanel(final ContentItem item) {
|
||||
super();
|
||||
this.xmlGenerator = new XMLGenerator(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateXML(final PageState state, final Element parent) {
|
||||
final Element content = parent.newChildElement("cms:contentPanel",
|
||||
CMS.CMS_XML_NS);
|
||||
xmlGenerator.generateXML(state, content, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class XMLGenerator extends SimpleXMLGenerator {
|
||||
|
||||
private final ContentItem item;
|
||||
|
||||
public XMLGenerator(final ContentItem item) {
|
||||
super();
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContentItem getContentItem(final PageState state) {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,3 +10,5 @@ contentItemJSRPortlet.edit.contentSectionSelect.label=Content section
|
|||
contentitemJSRPortlet.edit.search.label=Title of the content item
|
||||
|
||||
contentItemJSRPortlet.edit.fieldset.label=Please choose the content item to display
|
||||
contentItemJSRPortlet.no_item_configured=No item to show configured
|
||||
contentItemJSRPortlet.errors.item_is_not_live=The configured is not published yet
|
||||
|
|
|
|||
|
|
@ -7,3 +7,5 @@ contentItemJSRPortlet.errors.parameters.item_does_not_exist=Es gibt kein Item mi
|
|||
contentItemJSRPortlet.edit.contentSectionSelect.label=Content Section
|
||||
contentitemJSRPortlet.edit.search.label=Titel des Content Items
|
||||
contentItemJSRPortlet.edit.fieldset.label=Bitte w\u00e4hlen Sie das anzuzeigende Content Item
|
||||
contentItemJSRPortlet.no_item_configured=Es wurde noch Content Item zum Anzeigen festgelegt.
|
||||
contentItemJSRPortlet.errors.item_is_not_live=Das konfigurierte Content Item ist (noch) nicht publiziert.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,195 @@
|
|||
package com.arsdigita.cms.portlet;
|
||||
|
||||
import com.arsdigita.bebop.Page;
|
||||
import com.arsdigita.bebop.PageFactory;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.SimpleComponent;
|
||||
import com.arsdigita.bebop.page.PageTransformer;
|
||||
import com.arsdigita.cms.CMS;
|
||||
import com.arsdigita.cms.ContentItem;
|
||||
import com.arsdigita.cms.dispatcher.SimpleXMLGenerator;
|
||||
import com.arsdigita.domain.DataObjectNotFoundException;
|
||||
import com.arsdigita.persistence.OID;
|
||||
import com.arsdigita.templating.PresentationManager;
|
||||
import com.arsdigita.templating.Templating;
|
||||
import com.arsdigita.web.Application;
|
||||
import com.arsdigita.web.BaseServlet;
|
||||
import com.arsdigita.xml.Document;
|
||||
import com.arsdigita.xml.Element;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* This servlet is the backend for the the {@link ContentItemJSRPortlet} and provides the view of a
|
||||
* content item. Using a servlet is necessary to include the transformed HTML of the content item.
|
||||
* The {@link PageTransformer} requires a HTTP request but in the Portlet only a
|
||||
* {@link PortletRequest} is available. And a {@link PortletRequest} can't be converted into a
|
||||
* {@link ServletHttpRequest}.
|
||||
*
|
||||
* @author Jens Pelzetter <jens.pelzetter@scientificcms.org>
|
||||
*/
|
||||
public class ContentItemPortletItemProviderServlet extends BaseServlet{ //BaseApplicationServlet {
|
||||
|
||||
private static final String ITEMS = "items";
|
||||
private static final String CATEGORIES = "categories";
|
||||
|
||||
/**
|
||||
* This method is the entry point to the logic of this class. The method analyses the path (from
|
||||
* {@link HttpServletRequest#getPathInfo()}) and delegates to the responsible method of this
|
||||
* class.
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param app
|
||||
* @throws ServletException
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
// protected void doService(final HttpServletRequest request,
|
||||
// final HttpServletResponse response,
|
||||
// final Application app)
|
||||
protected void doService(final HttpServletRequest request,
|
||||
final HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
String path = request.getPathInfo();
|
||||
if (path.charAt(0) == '/') {
|
||||
path = path.substring(1);
|
||||
}
|
||||
final String[] pathTokens = path.split("/");
|
||||
|
||||
if (pathTokens.length == 0) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check the first token of the path and delegate the clal
|
||||
if (ITEMS.equals(pathTokens[0])) {
|
||||
serveContentItem(pathTokens, request, response);
|
||||
} else if (CATEGORIES.equals(pathTokens[0])) {
|
||||
throw new UnsupportedOperationException("Not implemtend yet");
|
||||
} else {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serves an HTML fragment showing the detail view of a specific content item. Will create a
|
||||
* BAD_REQUEST HTTP error if the provided ID/OID is invalid and a NOT_FOUND HTTP error if no
|
||||
* content item with the provided ID/OID is found.
|
||||
*
|
||||
* @param pathTokens The tokens of the path
|
||||
* @param request
|
||||
* @param response
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void serveContentItem(final String[] pathTokens,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws IOException,
|
||||
ServletException {
|
||||
//Retrieve the content item and ensure that we work with the live version of the item.
|
||||
ContentItem item = null;
|
||||
try {
|
||||
final ContentItem tmpItem = retrieveContentItem(pathTokens[1]);
|
||||
if (tmpItem.isLiveVersion()) {
|
||||
item = tmpItem;
|
||||
} else {
|
||||
if (tmpItem.isLive()) {
|
||||
item = tmpItem.getLiveVersion();
|
||||
} else {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND,
|
||||
String.format("Item with ID %d is not published.",
|
||||
pathTokens[1]));
|
||||
}
|
||||
}
|
||||
} catch (DataObjectNotFoundException ex) {
|
||||
//No item with the provided ID/OID found, respond with NOT_FOUND (404).
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND,
|
||||
String.format("Item with ID/PID %d not found.", pathTokens[1]));
|
||||
return;
|
||||
} catch (NumberFormatException ex) {
|
||||
//The provided ID was not a number, respond with bad request error.
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
|
||||
String.format("'%s' is not a valid item id", pathTokens[1]));
|
||||
return;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
//The provided OID is was invalid, respond with bad request error.
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST,
|
||||
String.format("'%s' is not a valid item OID", pathTokens[1]));
|
||||
return;
|
||||
}
|
||||
|
||||
//Create the XML output
|
||||
final Page page = PageFactory.buildPage(
|
||||
"PortletDataProvider",
|
||||
String.format("ContentItem %s", item.getOID().toString()));
|
||||
final PortletDataItemPanel panel = new PortletDataItemPanel(item);
|
||||
page.add(panel);
|
||||
page.lock();
|
||||
|
||||
//Delegate to theming enging
|
||||
final Document document = page.buildDocument(request, response);
|
||||
final PresentationManager presenter = Templating.getPresentationManager();
|
||||
presenter.servePage(document, request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method encapsulating the logic for retrieving a content item. If the first character
|
||||
* of the provided item id is a digit the method assumes that the numeric ID of the item was
|
||||
* provided. Otherwise the method assumes that the OID of the item to serve was provided.
|
||||
*
|
||||
* @param itemId
|
||||
* @return
|
||||
*/
|
||||
private ContentItem retrieveContentItem(final String itemId) {
|
||||
if (Character.isDigit(itemId.charAt(0))) {
|
||||
return new ContentItem(new BigDecimal(itemId));
|
||||
} else {
|
||||
return new ContentItem(OID.valueOf(itemId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special component to make it possible to use special XSL for the data served by the
|
||||
* PortletDataProvider
|
||||
*
|
||||
*/
|
||||
private class PortletDataItemPanel extends SimpleComponent {
|
||||
|
||||
private final XMLGenerator xmlGenerator;
|
||||
|
||||
public PortletDataItemPanel(final ContentItem item) {
|
||||
super();
|
||||
this.xmlGenerator = new XMLGenerator(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateXML(final PageState state, final Element parent) {
|
||||
final Element content = parent.newChildElement("cms:contentPanel",
|
||||
CMS.CMS_XML_NS);
|
||||
xmlGenerator.generateXML(state, content, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class XMLGenerator extends SimpleXMLGenerator {
|
||||
|
||||
private final ContentItem item;
|
||||
|
||||
public XMLGenerator(final ContentItem item) {
|
||||
super();
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContentItem getContentItem(final PageState state) {
|
||||
return item;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,6 +31,11 @@
|
|||
<servlet-name>template-xsl</servlet-name>
|
||||
<servlet-class>com.arsdigita.cms.dispatcher.TemplateXSLServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>content-item-portlet-servlet</servlet-name>
|
||||
<servlet-class>com.arsdigita.cms.portlet.ContentItemPortletItemProviderServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<!--
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
@ -57,5 +62,13 @@
|
|||
<servlet-name>template-xsl</servlet-name>
|
||||
<url-pattern>/themes/servlet/template/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!--
|
||||
Servlets used as backend for Portlets
|
||||
-->
|
||||
<servlet-mapping>
|
||||
<servlet-name>content-item-portlet-servlet</servlet-name>
|
||||
<url-pattern>/portlets/content-item-portlet-servlet/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
|
|
|||
Loading…
Reference in New Issue