Package juzu.impl.bridge.spi.portlet

Source Code of juzu.impl.bridge.spi.portlet.PortletRequestBridge

/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package juzu.impl.bridge.spi.portlet;

import juzu.PropertyMap;
import juzu.PropertyType;
import juzu.Response;
import juzu.Scope;
import juzu.asset.AssetLocation;
import juzu.impl.asset.Asset;
import juzu.impl.bridge.Bridge;
import juzu.impl.bridge.spi.servlet.ServletScopedContext;
import juzu.impl.common.JUL;
import juzu.impl.common.Logger;
import juzu.impl.common.RunMode;
import juzu.impl.inject.spi.InjectorProvider;
import juzu.impl.request.ControllerHandler;
import juzu.io.UndeclaredIOException;
import juzu.request.ClientContext;
import juzu.request.RequestParameter;
import juzu.request.ResponseParameter;
import juzu.impl.bridge.spi.DispatchBridge;
import juzu.impl.common.MimeType;
import juzu.impl.common.MethodHandle;
import juzu.impl.common.Tools;
import juzu.impl.plugin.controller.ControllerService;
import juzu.impl.plugin.controller.ControllerResolver;
import juzu.impl.bridge.spi.ScopedContext;
import juzu.impl.request.Request;
import juzu.impl.bridge.spi.RequestBridge;
import juzu.bridge.portlet.JuzuPortlet;
import juzu.request.ApplicationContext;
import juzu.request.HttpContext;
import juzu.request.Phase;
import juzu.request.SecurityContext;
import juzu.request.UserContext;
import juzu.request.WindowContext;

import javax.portlet.BaseURL;
import javax.portlet.MimeResponse;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletModeException;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.PortletURL;
import javax.portlet.WindowState;
import javax.portlet.WindowStateException;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public abstract class PortletRequestBridge<Rq extends PortletRequest, Rs extends PortletResponse> implements RequestBridge {

  /** . */
  protected final Bridge bridge;

  /** . */
  protected final Rq req;

  /** . */
  protected final Rs resp;

  /** . */
  protected final ControllerHandler<?> target;

  /** . */
  protected  final Map<String ,RequestParameter> requestParameters;

  /** . */
  protected final PortletHttpContext httpContext;

  /** . */
  protected final PortletSecurityContext securityContext;

  /** . */
  protected final PortletWindowContext windowContext;

  /** . */
  protected final PortletUserContext userContext;

  /** . */
  protected final PortletApplicationContext applicationContext;

  /** . */
  private final Phase phase;

  /** . */
  protected Request request;

  /** . */
  protected Response response;

  PortletRequestBridge(Bridge bridge, Phase phase, Rq req, Rs resp, PortletConfig config) {
    String methodId = null;
    Map<String, String[]> parameters = new HashMap<String, String[]>(req.getParameterMap());
    Map<String ,RequestParameter> requestParameters = Collections.emptyMap();
    for (Iterator<Map.Entry<String, String[]>> i = parameters.entrySet().iterator();i.hasNext();) {
      Map.Entry<String, String[]> parameter = i.next();
      String name = parameter.getKey();
      if (name.startsWith("juzu.")) {
        if (name.equals("juzu.op")) {
          methodId = parameter.getValue()[0];
        }
        i.remove();
      } else {
        if (requestParameters.isEmpty()) {
          requestParameters = new HashMap<String, RequestParameter>();
        }
        requestParameters.put(name, RequestParameter.create(parameter));
      }
    }

    //
    ControllerResolver<ControllerHandler> resolver = bridge.getApplication().resolveBean(ControllerService.class).getResolver();
    ControllerHandler<?> target;
    if (methodId != null) {
      target = resolver.resolveMethod(phase, methodId, parameters.keySet());
    } else {
      target = resolver.resolve(phase, parameters.keySet());
    }

    //
    this.bridge = bridge;
    this.req = req;
    this.resp = resp;
    this.target = target;
    this.httpContext = new PortletHttpContext(req);
    this.securityContext = new PortletSecurityContext(req);
    this.windowContext = new PortletWindowContext(this);
    this.userContext = new PortletUserContext(req);
    this.applicationContext = new PortletApplicationContext(config);
    this.requestParameters = requestParameters;
    this.phase = phase;
  }

  PortletRequestBridge(Bridge bridge,  Phase phase, Rq req, Rs resp, PortletConfig config, ControllerHandler<?> target, Map<String, String[]> parameters) {

    //
    Map<String, RequestParameter> requestParameters = Collections.emptyMap();
    for (Map.Entry<String, String[]> parameter : parameters.entrySet()) {
      if (requestParameters.isEmpty()) {
        requestParameters = new HashMap<String, RequestParameter>();
      }
      RequestParameter.create(parameter).appendTo(requestParameters);
    }

    //
    this.phase = phase;
    this.bridge = bridge;
    this.req = req;
    this.resp = resp;
    this.target = target;
    this.requestParameters = requestParameters;
    this.httpContext = new PortletHttpContext(req);
    this.securityContext = new PortletSecurityContext(req);
    this.windowContext = new PortletWindowContext(this);
    this.userContext = new PortletUserContext(req);
    this.applicationContext = new PortletApplicationContext(config);
  }

  @Override
  public Charset getDefaultRequestEncoding() {
    return bridge.getConfig().requestEncoding;
  }

  @Override
  public ClientContext getClientContext() {
    return null;
  }

  @Override
  public RunMode getRunMode() {
    return bridge.getRunMode();
  }

  public final Logger getLogger(String name) {
    return JUL.getLogger(name);
  }

  public final Phase getPhase() {
    return phase;
  }

  public Map<String, RequestParameter> getRequestArguments() {
    return requestParameters;
  }

  public <T> T getProperty(PropertyType<T> propertyType) {
    Object propertyValue = null;
    if (JuzuPortlet.PORTLET_MODE.equals(propertyType)) {
      propertyValue = req.getPortletMode();
    }
    else if (JuzuPortlet.WINDOW_STATE.equals(propertyType)) {
      propertyValue = req.getWindowState();
    }
    if (RunMode.PROPERTY.equals(propertyType)) {
      propertyValue = bridge.getRunMode();
    } else if (InjectorProvider.PROPERTY.equals(propertyType)) {
      return propertyType.cast(bridge.getConfig().injectorProvider);
    }
    return propertyValue == null ? null : propertyType.cast(propertyValue);
  }

  public MethodHandle getTarget() {
    return target.getHandle();
  }

  public final HttpContext getHttpContext() {
    return httpContext;
  }

  public final SecurityContext getSecurityContext() {
    return securityContext;
  }

  public final WindowContext getWindowContext() {
    return windowContext;
  }

  public final UserContext getUserContext() {
    return userContext;
  }

  public final ApplicationContext getApplicationContext() {
    return applicationContext;
  }

  public void execute(Runnable runnable) throws RejectedExecutionException {
    throw new RejectedExecutionException();
  }

  public void close() {
  }

  public final ScopedContext getScopedContext(Scope scope, boolean create) {
    Logger log = bridge.context.getLogger(ServletScopedContext.class.getName());
    ScopedContext context;
    switch (scope) {
      case REQUEST:
        context = (ScopedContext)req.getAttribute("juzu.request_scope");
        if (context == null && create) {
          req.setAttribute("juzu.request_scope", context = new ServletScopedContext(log));
        }
        break;
      case FLASH:
        PortletSession session = req.getPortletSession(create);
        if (session != null) {
          context = (ScopedContext)session.getAttribute("juzu.flash_scope");
          if (context == null && create) {
            session.setAttribute("juzu.flash_scope", context = new ServletScopedContext(log));
          }
        } else {
          context = null;
        }
        break;
      case SESSION:
        session = req.getPortletSession(create);
        if (session != null) {
          context = (ScopedContext)session.getAttribute("juzu.session_scope");
          if (context == null && create) {
            session.setAttribute("juzu.session_scope", context = new ServletScopedContext(log));
          }
        } else {
          context = null;
        }
        break;
      default:
        throw new UnsupportedOperationException("Unsupported scope " + scope);
    }
    return context;
  }

  public final void setResponse(Response response) throws IllegalArgumentException, IOException {
    this.response = response;
  }

  public void begin(Request request) {
    this.request = request;
  }

  public void end() {
    this.request = null;
  }

  public void invoke() throws Exception {
    try {
      bridge.getApplication().resolveBean(ControllerService.class).invoke(this);
    } finally {
      Tools.safeClose(this);
    }
  }

  public abstract void send() throws IOException, PortletException;

  private <T> String _checkPropertyValidity(Phase phase, PropertyType<T> propertyType, T propertyValue) {
    if (propertyType == JuzuPortlet.PORTLET_MODE) {
      if (phase == Phase.RESOURCE) {
        return "Resource URL don't have portlet modes";
      }
      PortletMode portletMode = (PortletMode)propertyValue;
      for (Enumeration<PortletMode> e = req.getPortalContext().getSupportedPortletModes();e.hasMoreElements();) {
        PortletMode next = e.nextElement();
        if (next.equals(portletMode)) {
          return null;
        }
      }
      return "Unsupported portlet mode " + portletMode;
    }
    else if (propertyType == JuzuPortlet.WINDOW_STATE) {
      if (phase == Phase.RESOURCE) {
        return "Resource URL don't have windwo state";
      }
      WindowState windowState = (WindowState)propertyValue;
      for (Enumeration<WindowState> e = req.getPortalContext().getSupportedWindowStates();e.hasMoreElements();) {
        WindowState next = e.nextElement();
        if (next.equals(windowState)) {
          return null;
        }
      }
      return "Unsupported window state " + windowState;
    }
    else {
      // For now we ignore other properties
      return null;
    }
  }

  public DispatchBridge createDispatch(final Phase phase, final MethodHandle target, final Map<String, ResponseParameter> parameters) throws NullPointerException, IllegalArgumentException {
    return new DispatchBridge() {

      public MethodHandle getTarget() {
        return target;
      }

      public Map<String, ResponseParameter> getParameters() {
        return parameters;
      }

      public <T> String checkPropertyValidity(PropertyType<T> propertyType, T propertyValue) {
        return _checkPropertyValidity(phase, propertyType, propertyValue);
      }

      public void renderURL(PropertyMap properties, MimeType mimeType, Appendable appendable) throws IOException {

        if (resp instanceof MimeResponse) {
          MimeResponse mimeResp = (MimeResponse)resp;

          //
          ControllerHandler handler = bridge.getApplication().resolveBean(ControllerService.class).getDescriptor().getMethodByHandle(target);

          //
          BaseURL url;
          if (handler.getPhase() == Phase.ACTION) {
            url = mimeResp.createActionURL();
          } else if (handler.getPhase() == Phase.VIEW) {
            url = mimeResp.createRenderURL();
          } else if (handler.getPhase() == Phase.RESOURCE) {
            url = mimeResp.createResourceURL();
          } else {
            throw new AssertionError();
          }

          // Set generic parameters
          for (ResponseParameter parameter : parameters.values()) {
            url.setParameter(parameter.getName(), parameter.toArray());
          }

          //
          boolean escapeXML = false;
          if (properties != null) {
            Boolean escapeXMLProperty = properties.getValue(PropertyType.ESCAPE_XML);
            if (escapeXMLProperty != null && Boolean.TRUE.equals(escapeXMLProperty)) {
              escapeXML = true;
            }

            // Handle portlet mode
            PortletMode portletModeProperty = properties.getValue(JuzuPortlet.PORTLET_MODE);
            if (portletModeProperty != null) {
              if (url instanceof PortletURL) {
                try {
                  ((PortletURL)url).setPortletMode(portletModeProperty);
                }
                catch (PortletModeException e) {
                  throw new IllegalArgumentException(e);
                }
              }
              else {
                throw new IllegalArgumentException();
              }
            }

            // Handle window state
            WindowState windowStateProperty = properties.getValue(JuzuPortlet.WINDOW_STATE);
            if (windowStateProperty != null) {
              if (url instanceof PortletURL) {
                try {
                  ((PortletURL)url).setWindowState(windowStateProperty);
                }
                catch (WindowStateException e) {
                  throw new IllegalArgumentException(e);
                }
              }
              else {
                throw new IllegalArgumentException();
              }
            }

            // Set method id
            url.setParameter("juzu.op", handler.getId());
          }

          //
          if (escapeXML) {
            StringWriter writer = new StringWriter();
            url.write(writer, true);
            appendable.append(writer.toString());
          }
          else {
            appendable.append(url.toString());
          }
        } else {
          throw new IllegalStateException("Cannot render an URL during phase " + phase);
        }
      }
    };
  }
  public PortletRequest getPortletRequest() {
    return req;
  }

  public PortletResponse getPortletResponse() {
    return resp;
  }

  public void renderAssetURL(AssetLocation location, String uri, Appendable appendable) throws NullPointerException, UnsupportedOperationException, IOException {
    switch (location) {
      case SERVER:
        if (!uri.startsWith("/")) {
          appendable.append(req.getContextPath());
          appendable.append('/');
        }
        appendable.append(uri);
        break;
      case APPLICATION:
        appendable.append(req.getContextPath()).append("/assets");
        if (!uri.startsWith("/")) {
          appendable.append('/');
          appendable.append(bridge.getApplication().getDescriptor().getPackageName().replace('.', '/'));
          appendable.append("/assets/");
        }
        appendable.append(uri);
        break;
      case URL:
        appendable.append(uri);
        break;
      default:
        throw new AssertionError();
    }
  }

  String getAssetURL(Asset asset) {
    StringBuilder sb = new StringBuilder();
    try {
      renderAssetURL(asset.getLocation(), asset.resolveURI(bridge.getRunMode().getMinifyAssets()), sb);
    }
    catch (IOException e) {
      // Should not happen
      throw new UndeclaredIOException(e);
    }
    return sb.toString();
  }
}
TOP

Related Classes of juzu.impl.bridge.spi.portlet.PortletRequestBridge

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.