Skip to content
This repository has been archived by the owner on Apr 8, 2019. It is now read-only.

Commit

Permalink
Decouple the page controller from the portlet by introducing a conten…
Browse files Browse the repository at this point in the history
…t provider abstraction
  • Loading branch information
vietj committed Jun 24, 2013
1 parent 5d68626 commit 3bde517
Show file tree
Hide file tree
Showing 15 changed files with 970 additions and 604 deletions.
2 changes: 2 additions & 0 deletions portal/web/src/main/java/org/gatein/portal/package-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@Binding(NavigationService.class),
@Binding(SiteService.class),
@Binding(SimpleLayoutFactory.class),
@Binding(PortletContentProvider.class),
@Binding(KernelFilter.class)})
@Assets(stylesheets = @Stylesheet(src = "bootstrap-2.3.1.min.css"))
package org.gatein.portal;
Expand All @@ -28,4 +29,5 @@
import org.gatein.portal.mop.navigation.NavigationService;
import org.gatein.portal.mop.page.PageService;
import org.gatein.portal.mop.site.SiteService;
import org.gatein.portal.page.spi.portlet.PortletContentProvider;
import org.gatein.portal.portlet.PortletAppManager;
142 changes: 20 additions & 122 deletions portal/web/src/main/java/org/gatein/portal/page/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,24 @@

package org.gatein.portal.page;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.portlet.ResourceResponse;
import javax.xml.namespace.QName;

import juzu.Param;
import juzu.Path;
import juzu.PropertyType;
import juzu.Response;
import juzu.Route;
import juzu.View;
import juzu.impl.common.Tools;
import juzu.request.RenderContext;
import juzu.request.RequestParameter;
import juzu.template.Template;
import org.exoplatform.container.PortalContainer;
import org.gatein.common.util.MultiValuedPropertyMap;
import org.gatein.pc.api.Mode;
import org.gatein.pc.api.ParametersStateString;
import org.gatein.pc.api.invocation.response.ContentResponse;
import org.gatein.pc.api.invocation.response.PortletInvocationResponse;
import org.gatein.pc.api.invocation.response.ResponseProperties;
import org.gatein.pc.api.invocation.response.UpdateNavigationalStateResponse;
import org.gatein.portal.layout.Layout;
import org.gatein.portal.layout.ZoneLayoutFactory;
import org.gatein.portal.mop.customization.CustomizationService;
Expand All @@ -63,7 +52,8 @@
import org.gatein.portal.mop.site.SiteContext;
import org.gatein.portal.mop.site.SiteKey;
import org.gatein.portal.mop.site.SiteService;
import org.gatein.portal.portlet.PortletAppManager;
import org.gatein.portal.page.spi.WindowContent;
import org.gatein.portal.page.spi.portlet.PortletContentProvider;

/**
* The controller for aggregation.
Expand All @@ -75,12 +65,6 @@ public class Controller {
/** . */
private static final Map<String, String[]> NO_PARAMETERS = Collections.emptyMap();

@Inject
PortalContainer current;

@Inject
PortletAppManager manager;

@Inject
SiteService siteService;

Expand All @@ -99,6 +83,9 @@ public class Controller {
@Inject
ZoneLayoutFactory layoutFactory;

@Inject
PortletContentProvider contentProvider;

@Inject
@Path("not_found.gtmpl")
Template notFound;
Expand Down Expand Up @@ -147,7 +134,7 @@ public Response index(
} else {

// Page builder
PageContext.Builder pageBuilder = new PageContext.Builder(path);
PageContext.Builder pageBuilder = new PageContext.Builder(contentProvider, customizationService, path);

// Load site windows
SiteContext site = siteService.loadSite(SiteKey.portal("classic"));
Expand All @@ -173,22 +160,21 @@ public Response index(
pageBuilder.setParameters(prp);
} else if (name.startsWith("javax.portlet.p.")) {
String id = name.substring("javax.portlet.p.".length());
Decoder decoder = new Decoder(parameter.getRaw(0));
WindowData window = pageBuilder.getWindow(id);
WindowContent window = pageBuilder.getWindow(id);
if (window != null) {
window.parameters = decoder.decode().getParameters();
window.setParameters(parameter.getRaw(0));
}
} else if (name.startsWith("javax.portlet.w.")) {
String id = name.substring("javax.portlet.w.".length());
WindowData window = pageBuilder.getWindow(id);
WindowContent window = pageBuilder.getWindow(id);
if (window != null) {
window.windowState = org.gatein.pc.api.WindowState.create(parameter.getValue());
window.setWindowState(parameter.getValue());
}
} else if (name.startsWith("javax.portlet.m.")) {
String id = name.substring("javax.portlet.m.".length());
WindowData window = pageBuilder.getWindow(id);
WindowContent window = pageBuilder.getWindow(id);
if (window != null) {
window.mode = org.gatein.pc.api.Mode.create(parameter.getValue());
window.setMode(parameter.getValue());
}
}
} else {
Expand All @@ -203,7 +189,7 @@ public Response index(
if (phase != null) {

//
PageContext pageContext = pageBuilder.build(customizationService, manager);
PageContext pageContext = pageBuilder.build();

// Going to invoke process action
if (target != null) {
Expand All @@ -213,37 +199,17 @@ public Response index(
if ("action".equals(phase)) {

//
org.gatein.pc.api.WindowState windowState = window.state.windowState;
String windowState = window.state.getWindowState();
if (targetWindowState != null) {
windowState = org.gatein.pc.api.WindowState.create(targetWindowState);
windowState = targetWindowState;
}
Mode mode = window.state.mode;
String mode = window.state.getMode();
if (targetMode != null) {
mode = org.gatein.pc.api.Mode.create(targetMode);
mode = targetMode;
}

//
PortletInvocationResponse response = window.processAction(windowState, mode, parameters);
if (response instanceof UpdateNavigationalStateResponse) {
UpdateNavigationalStateResponse update = (UpdateNavigationalStateResponse) response;
PageContext.Builder clone = pageContext.builder();
WindowData windowClone = clone.getWindow(window.state.name);
ParametersStateString s = (ParametersStateString) update.getNavigationalState();
windowClone.parameters = s.getParameters();
if (update.getWindowState() != null) {
windowClone.windowState = update.getWindowState();
}
if (update.getMode() != null) {
windowClone.mode = update.getMode();
}
Map<String, String[]> changes = update.getPublicNavigationalStateUpdates();
if (changes != null && changes.size() > 0) {
clone.apply(window.getPublicParametersChanges(changes));
}
return clone.build(customizationService, manager).getDispatch().with(PropertyType.REDIRECT_AFTER_ACTION);
} else {
throw new UnsupportedOperationException("Not yet handled " + response);
}
return window.processAction(windowState, mode, parameters);
} else if ("resource".equals(phase)) {

//
Expand All @@ -256,59 +222,7 @@ public Response index(
}

//
PortletInvocationResponse response = window.serveResource(id, parameters);

//
if (response instanceof ContentResponse) {
ContentResponse content = (ContentResponse) response;

//
int code = 200;
ResponseProperties properties = content.getProperties();
MultiValuedPropertyMap<String> headers = properties != null ? properties.getTransportHeaders() : null;
if (headers != null) {
String value = headers.getValue(ResourceResponse.HTTP_STATUS_CODE);
if (value != null) {
try {
code = Integer.parseInt(value);
} catch (NumberFormatException e) {
// throw new ServletException("Bad " + ResourceResponse.HTTP_STATUS_CODE + "=" + value +
// " resource value", e);
}
}
}

// Create response
Response.Status status = Response.status(code);

// Headers
sendHttpHeaders(headers, status);

// Charset
String encoding = content.getEncoding();
if (encoding != null) {
Charset charset = Charset.forName(encoding);
status.with(PropertyType.CHARSET, charset);
}

// Mime type
String contentType = content.getContentType();
if (contentType != null) {
status.with(PropertyType.MIME_TYPE, contentType);
}

//
if (content.getBytes() != null) {
status = status.body(content.getBytes());
} else if (content.getChars() != null) {
status = status.body(content.getChars());
}

//
return status;
} else {
throw new UnsupportedOperationException("No yet handled " + response);
}
return window.serveResource(id, parameters);
} else {
throw new AssertionError("should not be here");
}
Expand All @@ -328,7 +242,7 @@ public Response index(
pageBuilder.setParameters(prp);

// Build page
PageContext pageContext = pageBuilder.build(customizationService, manager);
PageContext pageContext = pageBuilder.build();

// Render page
String layoutId = page.getState().getFactoryId();
Expand All @@ -349,20 +263,4 @@ public Response index(
return Response.notFound("Page for navigation " + path + " could not be located");
}
}

private static void sendHttpHeaders(ResponseProperties properties, Response.Status resp) {
if (properties != null) {
sendHttpHeaders(properties.getTransportHeaders(), resp);
}
}

private static void sendHttpHeaders(MultiValuedPropertyMap<String> httpHeaders, Response.Status resp) {
if (httpHeaders != null) {
for (String headerName : httpHeaders.keySet()) {
if (!headerName.equals(ResourceResponse.HTTP_STATUS_CODE)) {
resp.withHeader(headerName, httpHeaders.getValue(headerName));
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public class NodeState {

/** . */
final NodeContext<NodeState, ElementState> context;
public final NodeContext<NodeState, ElementState> context;

public NodeState(NodeContext<NodeState, ElementState> context) {
this.context = context;
Expand Down
45 changes: 30 additions & 15 deletions portal/web/src/main/java/org/gatein/portal/page/PageContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@
import javax.xml.namespace.QName;

import juzu.request.Phase;
import org.exoplatform.portal.pom.spi.portlet.Portlet;
import org.gatein.portal.mop.customization.CustomizationContext;
import org.gatein.portal.mop.customization.CustomizationService;
import org.gatein.portal.mop.hierarchy.NodeContext;
import org.gatein.portal.mop.hierarchy.NodeModel;
import org.gatein.portal.mop.layout.ElementState;
import org.gatein.portal.portlet.PortletAppManager;
import org.gatein.portal.page.spi.ContentProvider;
import org.gatein.portal.page.spi.WindowContent;

/**
* Encapsulate state and operations on a page.
Expand All @@ -44,21 +47,31 @@ public class PageContext implements Iterable<Map.Entry<String, WindowContext>> {
*/
public static class Builder implements NodeModel<NodeState, ElementState> {

public Builder(String path) {
/** . */
private final ContentProvider contentProvider;

/** . */
private final CustomizationService customizationService;

public Builder(ContentProvider contentProvider, CustomizationService customizationService, String path) {
this.contentProvider = contentProvider;
this.customizationService = customizationService;
this.state = new PageData(path);
}

public Builder(PageData state) {
public Builder(ContentProvider contentProvider, CustomizationService customizationService, PageData state) {
this.contentProvider = contentProvider;
this.customizationService = customizationService;
this.state = state;
}

/** . */
private PageData state;

/** A map of name -> window. */
private final HashMap<String, WindowData> windows = new LinkedHashMap<String, WindowData>();
private final HashMap<String, WindowContent> windows = new LinkedHashMap<String, WindowContent>();

public WindowData getWindow(String name) {
public WindowContent getWindow(String name) {
return windows.get(name);
}

Expand All @@ -78,22 +91,24 @@ public void setParameters(Map<QName, String[]> parameters) {
@Override
public NodeState create(NodeContext<NodeState, ElementState> context) {
if (context.getState() instanceof ElementState.Window) {
CustomizationContext<Portlet> portletCustomization = customizationService.loadCustomization(context.getId());
String contentId = portletCustomization.getContentId();
NodeState window = new NodeState(context);
WindowData windowState = new WindowData(window);
windows.put(windowState.name, windowState);
WindowContent windowState = contentProvider.getContent(contentId, window);
windows.put(windowState.getName(), windowState);
return window;
} else {
return new NodeState(context);
}
}

public PageContext build(CustomizationService customizationService, PortletAppManager portletManager) {
return new PageContext(this, customizationService, portletManager);
public PageContext build() {
return new PageContext(this, customizationService, contentProvider);
}
}

/** . */
final PortletAppManager portletManager;
final ContentProvider portletManager;

/** . */
final CustomizationService customizationService;
Expand All @@ -110,12 +125,12 @@ public PageContext build(CustomizationService customizationService, PortletAppMa
public PageContext(
Builder builder,
CustomizationService customizationService,
PortletAppManager portletManager) {
ContentProvider portletManager) {

//
LinkedHashMap<String, WindowContext> a = new LinkedHashMap<String, WindowContext>(builder.windows.size());
for (WindowData state : builder.windows.values()) {
a.put(state.name, new WindowContext(state, this));
for (WindowContent state : builder.windows.values()) {
a.put(state.getName(), new WindowContext(state, this));
}

//
Expand All @@ -128,12 +143,12 @@ public PageContext(

public Builder builder() {

Builder builder = new Builder(new PageData(state));
Builder builder = new Builder(portletManager, customizationService, new PageData(state));

// Clone the windows
for (Map.Entry<String, WindowContext> entry : windowMap.entrySet()) {
WindowContext window = entry.getValue();
builder.windows.put(window.state.name, new WindowData(window.state));
builder.windows.put(window.state.getName(), window.state.copy());
}

//
Expand Down

0 comments on commit 3bde517

Please sign in to comment.