Package juzu.bridge.portlet

Source Code of juzu.bridge.portlet.JuzuPortlet

/*
* 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.bridge.portlet;

import juzu.Consumes;
import juzu.PropertyType;
import juzu.impl.asset.AssetServer;
import juzu.impl.bridge.Bridge;
import juzu.impl.bridge.BridgeConfig;
import juzu.impl.bridge.BridgeContext;
import juzu.impl.bridge.module.ApplicationBridge;
import juzu.impl.bridge.module.ModuleContextImpl;
import juzu.impl.bridge.provided.ProvidedBridge;
import juzu.impl.bridge.spi.portlet.PortletEventBridge;
import juzu.impl.bridge.spi.portlet.PortletViewBridge;
import juzu.impl.bridge.spi.servlet.AbstractBridgeContext;
import juzu.impl.common.JUL;
import juzu.impl.fs.spi.ReadFileSystem;
import juzu.impl.fs.spi.war.WarFileSystem;
import juzu.impl.bridge.spi.portlet.PortletActionBridge;
import juzu.impl.bridge.spi.portlet.PortletResourceBridge;
import juzu.impl.common.Logger;
import juzu.impl.common.SimpleMap;
import juzu.impl.common.Tools;
import juzu.impl.inject.spi.Injector;
import juzu.impl.inject.spi.InjectorProvider;
import juzu.impl.inject.spi.spring.SpringInjector;
import juzu.impl.plugin.controller.ControllerService;
import juzu.impl.plugin.controller.ControllerResolver;
import juzu.impl.request.ControllerHandler;
import juzu.impl.resource.ResourceResolver;
import juzu.request.Phase;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventPortlet;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.ResourceServingPortlet;
import javax.portlet.UnavailableException;
import javax.portlet.WindowState;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class JuzuPortlet implements Portlet, ResourceServingPortlet, EventPortlet {

  /** . */
  public static final PropertyType<PortletMode> PORTLET_MODE = new PropertyType<PortletMode>(){};

  /** . */
  public static final PropertyType<WindowState> WINDOW_STATE = new PropertyType<WindowState>(){};

  /** . */
  private Bridge bridge;

  /** . */
  private PortletConfig config;

  public void init(final PortletConfig config) throws PortletException {

    //
    final PortletContext context = config.getPortletContext();

    //
    AssetServer server = (AssetServer)context.getAttribute("asset.server");
    if (server == null) {
      server = new AssetServer();
      context.setAttribute("asset.server", server);
    }

    // The portlet logger
    Logger portletLogger = JUL.getLogger(JuzuPortlet.class.getName() + "." + config.getPortletName());

    //
    BridgeConfig bridgeConfig;
    try {
      bridgeConfig = new BridgeConfig(portletLogger, new SimpleMap<String, String>() {
        @Override
        protected Iterator<String> keys() {
          return BridgeConfig.NAMES.iterator();
        }

        @Override
        public String get(Object key) {
          if (BridgeConfig.APP_NAME.equals(key)) {
            return getApplicationName(config);
          } else if (BridgeConfig.INJECT.equals(key)) {
            // Cascade:
            // 1/ portlet init param
            // 2/ servket context init param
            String inject = config.getInitParameter((String)key);
            if (inject == null) {
              inject = context.getInitParameter((String)key);
            }
            return inject;
          } else if (BridgeConfig.NAMES.contains(key)) {
            return config.getInitParameter((String)key);
          } else {
            return null;
          }
        }
      });
    }
    catch (Exception e) {
      String msg = "Could not find an application to start";
      if (e instanceof PortletException) {
        String nested = e.getMessage();
        if (nested != null) {
          msg += ":" + nested;
        }
        throw Tools.initCause(new UnavailableException(msg), e.getCause());
      } else {
        throw new PortletException(msg, e);
      }
    }

    //
    final BridgeContext bridgeContext = new AbstractBridgeContext() {
      final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      final ResourceResolver resolver = new ResourceResolver() {
        public URL resolve(String uri) {
          try {
            return context.getResource(uri);
          }
          catch (MalformedURLException e) {
            return null;
          }
        }
      };
      public ReadFileSystem<?> getResourcePath() {
        return WarFileSystem.create(context, "/WEB-INF/");
      }
      public ReadFileSystem<?> getClassPath() {
        return WarFileSystem.create(context, "/WEB-INF/classes/");
      }
      public ClassLoader getClassLoader() {
        return classLoader;
      }
      public String getInitParameter(String name) {
        return context.getInitParameter(name);
      }
      public ResourceResolver getResolver() {
        return resolver;
      }
      public Object getAttribute(String key) {
        return context.getAttribute(key);
      }
      public void setAttribute(String key, Object value) {
        context.setAttribute(key, value);
      }
    };

    //
    InjectorProvider injectorProvider = bridgeConfig.injectorProvider;
    if (injectorProvider == null) {
      throw new UnavailableException("No inject implementation selected");
    } else {
      portletLogger.info("Using inject implementation " + injectorProvider.getValue());
    }

    //
    Injector injector = injectorProvider.get();
    if (injector instanceof SpringInjector) {
      SpringInjector springInjector = (SpringInjector)injector;
      Object parent = context.getAttribute("org.springframework.web.context.WebApplicationContext.ROOT");
      if (parent != null) {
        springInjector.setParent(parent);
      }
    }

    //
    ResourceResolver resolver = new ResourceResolver() {
      public URL resolve(String uri) {
        try {
          return context.getResource(uri);
        }
        catch (MalformedURLException e) {
          return null;
        }
      }
    };

    //
    ModuleContextImpl module = (ModuleContextImpl)context.getAttribute("juzu.module");
    if (module == null) {
      context.setAttribute("juzu.module", module = new ModuleContextImpl(portletLogger, bridgeContext, resolver));
    }

    //
    Bridge bridge;
    if (injector.isProvided()) {
      bridge = new ProvidedBridge(bridgeContext, bridgeConfig, server, resolver, injector);
    } else {
      bridge = new ApplicationBridge(module, bridgeContext, bridgeConfig, server, resolver, injector);
    }

    //
    this.config = config;
    this.bridge = bridge;
  }

  /**
   * Returns the application name to use using the <code>juzu.app_name</code> init parameter of the portlet deployment
   * descriptor. Subclass can override it to provide a custom application name.
   *
   * @param config the portlet config
   * @return the application name
   */
  protected String getApplicationName(PortletConfig config) {
    return config.getInitParameter(BridgeConfig.APP_NAME);
  }

  private void rethrow(Throwable e) throws PortletException, IOException {
    if (e instanceof PortletException) {
      throw (PortletException)e;
    } else if (e instanceof IOException) {
      throw (IOException)e;
    } else {
      throw new PortletException(e);
    }
  }

  public void processAction(ActionRequest req, ActionResponse resp) throws PortletException, IOException {
    try {
      PortletActionBridge requestBridge = new PortletActionBridge(bridge, req, resp, config);
      requestBridge.invoke();
      requestBridge.send();
    }
    catch (Throwable e) {
      rethrow(e);
    }
  }

  public void processEvent(EventRequest request, EventResponse response) throws PortletException, IOException {
    ControllerResolver<ControllerHandler> resolver = bridge.getApplication().resolveBean(ControllerService.class).getDescriptor().getResolver();
    List<ControllerHandler> handlers = resolver.resolveMethods(Phase.EVENT, null, request.getParameterMap().keySet());

    //
    ControllerHandler target = null;
    for (ControllerHandler handler : handlers) {
      Consumes consumes = handler.getMethod().getAnnotation(Consumes.class);
      if (consumes.value().equals("")) {
        target = handler;
        // we don't break here on purpose because having empty match is less important
        // than an explicit match
      } else if (consumes.value().equals(request.getEvent().getName())) {
        target = handler;
        break;
      }
    }

    //
    if (target != null) {
      try {
        PortletEventBridge requestBridge = new PortletEventBridge(
            bridge,
            request,
            response,
            config,
            target,
            request.getParameterMap());
        requestBridge.invoke();
        requestBridge.send();
      }
      catch (Throwable e) {
        rethrow(e);
      }
    } else {
      // We just don't dispatch however we keep the same render parameters
      response.setRenderParameters(request);
    }
  }

  private boolean initialized = false;

  public void render(final RenderRequest req, final RenderResponse resp) throws PortletException, IOException {

    // THIS CODE SHOULD BE REMOVED
    // BECAUSE IT DOES NOT BEHAVE CORRECTLY WHEN USED IN PRETTY FAIL MODE
    // AND IT IS ALSO HANDLED IN THE REQUEST BRIDGE
    if (!initialized) {
      try {
        bridge.refresh();
        initialized = true;
      }
      catch (Exception e) {
        String msg = "Could not initialize application";
        if (e instanceof PortletException) {
          String nested = e.getMessage();
          if (nested != null) {
            msg += ":" + nested;
          }
          throw new PortletException(msg, e.getCause());
        } else {
          throw new PortletException(msg, e);
        }
      }
    }

    //
    try {
      PortletViewBridge requestBridge = new PortletViewBridge(bridge, req, resp, config);
      requestBridge.invoke();
      requestBridge.send();
    }
    catch (Throwable e) {
      rethrow(e);
    }
  }

  public void serveResource(final ResourceRequest req, final ResourceResponse resp) throws PortletException, IOException {

    // THIS CODE SHOULD BE REMOVED
    // BECAUSE IT DOES NOT BEHAVE CORRECTLY WHEN USED IN PRETTY FAIL MODE
    // AND IT IS ALSO HANDLED IN THE REQUEST BRIDGE
    if (!initialized) {
      try {
        bridge.refresh();
        initialized = true;
      }
      catch (Exception e) {
        String msg = "Could not initialize application";
        if (e instanceof PortletException) {
          String nested = e.getMessage();
          if (nested != null) {
            msg += ":" + nested;
          }
          throw new PortletException(msg, e.getCause());
        } else {
          throw new PortletException(msg, e);
        }
      }
    }

    //
    try {
      PortletResourceBridge requestBridge = new PortletResourceBridge(bridge, req, resp, config);
      requestBridge.invoke();
      requestBridge.send();
    }
    catch (Throwable throwable) {
      rethrow(throwable);
    }
  }

  public void destroy() {
    Tools.safeClose(bridge);
  }
}
TOP

Related Classes of juzu.bridge.portlet.JuzuPortlet

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.