PLUTO-619 Fix parsing of escapeXml container runtime option
git-svn-id: https://svn.apache.org/repos/asf/portals/pluto/branches/2.1-spi-cleanup@1377088 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
index 56eca34..161bf27 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletInvokerService.java
@@ -69,53 +69,59 @@
* container to the underlying <code>PortletRquest</code>.
*/
String METHOD_ID = "org.apache.pluto.core.method";
-
+
/**
- * The unique method identifier for render requests. Render requests are
- * requested through a call to the {@link PortletContainer#doRender(org.apache.pluto.container.PortletWindow,
- * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
- * method.
+ * Describes the set of methods that can be invoked by the container
*/
- Integer METHOD_RENDER = new Integer(1);
+ public enum Method {
- /**
- * The unique method identifier for render requests. Render requests are
- * requested through a call to the {@link PortletContainer#doAction(org.apache.pluto.container.PortletWindow,
- * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
- * method.
- */
- Integer METHOD_ACTION = new Integer(3);
+ /**
+ * The unique method identifier for render requests. Render requests are
+ * requested through a call to the {@link PortletContainer#doRender(org.apache.pluto.container.PortletWindow,
+ * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method.
+ */
+ RENDER,
- /**
- * The unique method identifier for load requests. Load requests are
- * requested through a call to the {@link PortletContainer#doLoad(org.apache.pluto.container.PortletWindow,
- * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
- * method.
- */
- Integer METHOD_LOAD = new Integer(5);
+ /**
+ * The unique method identifier for render requests. Render requests are
+ * requested through a call to the {@link PortletContainer#doAction(org.apache.pluto.container.PortletWindow,
+ * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method.
+ */
+ ACTION,
- /**
- * The unique method identifier for resource Serving requests. Resource requests are
- * requested through a call to the {@link PortletContainer#doServeResource(PortletWindow,
- * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
- * method.
- */
- Integer METHOD_RESOURCE = new Integer(7);
+ /**
+ * The unique method identifier for load requests. Load requests are
+ * requested through a call to the {@link PortletContainer#doLoad(org.apache.pluto.container.PortletWindow,
+ * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method.
+ */
+ LOAD,
- /**
- * The unique method identifier for render requests. Render requests are
- * requested through a call to the {@link PortletContainer#doEvent(org.apache.pluto.container.PortletWindow,
- * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.portlet.Event)}
- * method.
- */
- Integer METHOD_EVENT = new Integer(9);
+ /**
+ * The unique method identifier for resource Serving requests. Resource requests are
+ * requested through a call to the {@link PortletContainer#doServeResource(PortletWindow,
+ * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method.
+ */
+ RESOURCE,
- /**
- * The unique method identifier for admin requests. Admin requests
- * are requested through a call to the {@link PortletContainer#doAdmin(PortletWindow, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
- * method.
- */
- Integer METHOD_ADMIN = new Integer(11);
+ /**
+ * The unique method identifier for render requests. Render requests are
+ * requested through a call to the {@link PortletContainer#doEvent(org.apache.pluto.container.PortletWindow,
+ * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.portlet.Event)}
+ * method.
+ */
+ EVENT,
+
+ /**
+ * The unique method identifier for admin requests. Admin requests
+ * are requested through a call to the {@link PortletContainer#doAdmin(PortletWindow, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
+ * method.
+ */
+ ADMIN
+ }
/**
* The public key, to store the FilterManager in the request.
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PlutoServices.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PlutoServices.java
deleted file mode 100644
index dda84e1..0000000
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PlutoServices.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 org.apache.pluto.container.driver;
-
-import javax.portlet.PortalContext;
-
-import org.apache.pluto.container.CCPPProfileService;
-import org.apache.pluto.container.EventCoordinationService;
-import org.apache.pluto.container.FilterManagerService;
-import org.apache.pluto.container.NamespaceMapper;
-import org.apache.pluto.container.PortletEnvironmentService;
-import org.apache.pluto.container.PortletInvokerService;
-import org.apache.pluto.container.PortletPreferencesService;
-import org.apache.pluto.container.PortletRequestContextService;
-import org.apache.pluto.container.PortletURLListenerService;
-import org.apache.pluto.container.RequestDispatcherService;
-import org.apache.pluto.container.UserInfoService;
-
-
-public class PlutoServices implements PortalDriverServices
-{
- private PortalDriverServices driverServices;
-
- private static PlutoServices singleton;
-
- public static PlutoServices getServices()
- {
- return singleton;
- }
-
- public PlutoServices(PortalDriverServices driverServices)
- {
- singleton = this;
- this.driverServices = driverServices;
- }
-
- public CCPPProfileService getCCPPProfileService()
- {
- return driverServices.getCCPPProfileService();
- }
-
- public PortalContext getPortalContext()
- {
- return driverServices.getPortalContext();
- }
-
- public NamespaceMapper getNamespaceMapper()
- {
- return driverServices.getNamespaceMapper();
- }
-
- public PortalAdministrationService getPortalAdministrationService()
- {
- return driverServices.getPortalAdministrationService();
- }
-
- public PortletEnvironmentService getPortletEnvironmentService()
- {
- return driverServices.getPortletEnvironmentService();
- }
-
- public PortletInvokerService getPortletInvokerService()
- {
- return driverServices.getPortletInvokerService();
- }
-
- public PortletPreferencesService getPortletPreferencesService()
- {
- return driverServices.getPortletPreferencesService();
- }
-
- public PortletRegistryService getPortletRegistryService()
- {
- return driverServices.getPortletRegistryService();
- }
-
- public UserInfoService getUserInfoService()
- {
- return driverServices.getUserInfoService();
- }
-
- public PortletContextService getPortletContextService()
- {
- return driverServices.getPortletContextService();
- }
-
- public PortletRequestContextService getPortletRequestContextService()
- {
- return driverServices.getPortletRequestContextService();
- }
-
- public EventCoordinationService getEventCoordinationService()
- {
- return driverServices.getEventCoordinationService();
- }
-
- public FilterManagerService getFilterManagerService()
- {
- return driverServices.getFilterManagerService();
- }
-
- public PortletURLListenerService getPortletURLListenerService()
- {
- return driverServices.getPortletURLListenerService();
- }
-
- public RequestDispatcherService getRequestDispatcherService()
- {
- return driverServices.getRequestDispatcherService();
- }
-}
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PlutoServicesRegistry.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PlutoServicesRegistry.java
new file mode 100644
index 0000000..f1640ba
--- /dev/null
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PlutoServicesRegistry.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.pluto.container.driver;
+
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.pluto.container.PortletContainerException;
+
+/**
+ * Static registry used by the {@link PortletServlet} and {@link PortalDriverServices} implementations to
+ * coordinate registration lifecycle
+ *
+ * @author Eric Dalquist
+ */
+public final class PlutoServicesRegistry {
+ //Using a weak map keyed on ServletConfig, this should result in the map not causing memory leaks as applications are redpeloyed
+ private static final Map<ServletConfig, RegistrationData> REGISTERED_PORTLETS = new WeakHashMap<ServletConfig, RegistrationData>();
+ private static volatile PortalDriverServices portalDriverServices;
+
+ /**
+ * Called by the portlet container when it initializes to register the {@link PortalDriverServices} implementation
+ */
+ public static void registerPortalDriverServices(PortalDriverServices portalDriverServices) {
+ if (portalDriverServices == null) {
+ throw new IllegalArgumentException("Cannot register a null PortalDriverServices");
+ }
+
+ synchronized (REGISTERED_PORTLETS) {
+ if (PlutoServicesRegistry.portalDriverServices != null) {
+ throw new IllegalStateException("Cannot register PortalDriverServices, there is already one registered\n" +
+ "existing: " + PlutoServicesRegistry.portalDriverServices + "\n" +
+ " new: " + portalDriverServices);
+ }
+
+ PlutoServicesRegistry.portalDriverServices = portalDriverServices;
+
+ //Just registered the driver services, notify it about all portlets that have already called register
+ if (PlutoServicesRegistry.portalDriverServices != null) {
+ final PortletContextService portletContextService = portalDriverServices.getPortletContextService();
+
+ for (final Map.Entry<ServletConfig, RegistrationData> registeredPortletEntry : REGISTERED_PORTLETS.entrySet()) {
+ final ServletConfig config = registeredPortletEntry.getKey();
+ final RegistrationData registrationData = registeredPortletEntry.getValue();
+ registerPortlet(portletContextService, config, registrationData);
+ }
+ }
+ }
+ }
+
+ /**
+ * Called by the portlet container when it is destroyed to remove the {@link PortalDriverServices} registration
+ */
+ public static void unregisterPortalDriverServices(PortalDriverServices portalDriverServices) {
+ if (portalDriverServices == null) {
+ throw new IllegalArgumentException("Cannot unregister a null PortalDriverServices");
+ }
+
+ synchronized (REGISTERED_PORTLETS) {
+ if (PlutoServicesRegistry.portalDriverServices != portalDriverServices) {
+ throw new IllegalStateException("Cannot unregister PortalDriverServices, the provided service does not match the existing registered service\n" +
+ "existing: " + PlutoServicesRegistry.portalDriverServices + "\n" +
+ "provided: " + portalDriverServices);
+ }
+
+ //Just unregistered the driver services, notify each portlet by calling unregister
+ for (final Map.Entry<ServletConfig, RegistrationData> registeredPortletEntry : REGISTERED_PORTLETS.entrySet()) {
+ final RegistrationData registrationData = registeredPortletEntry.getValue();
+
+ try {
+ registrationData.lifecycleCallback.unregistered();
+ }
+ catch (Throwable t) {
+ final ServletConfig config = registeredPortletEntry.getKey();
+ config.getServletContext().log("Failed to unregister portlet " + config.getInitParameter("portlet-name") + " in " + config.getServletContext().getServletContextName(), t);
+ }
+ }
+
+ //Clear the services reference
+ PlutoServicesRegistry.portalDriverServices = null;
+ }
+
+ }
+
+ /**
+ * Called by the {@link PortletServlet} when it initializes, notifies the portlet container that the portlet needs to be registered
+ *
+ * @param config The {@link ServletConfig} for the {@link PortletServlet} that is being initialized
+ * @param classLoader The portlet application's {@link ClassLoader}
+ * @param lifecycleCallback The callback the portlet container should call when registering the portlet
+ */
+ public static void register(String portletName, ServletConfig config, ClassLoader classLoader, PortletServletLifecycleCallback lifecycleCallback) {
+ synchronized (REGISTERED_PORTLETS) {
+ final RegistrationData registrationData = new RegistrationData(portletName, classLoader, lifecycleCallback);
+ REGISTERED_PORTLETS.put(config, registrationData);
+
+ //Driver services exist, notify them of the registration
+ if (portalDriverServices != null) {
+ final PortletContextService portletContextService = portalDriverServices.getPortletContextService();
+ registerPortlet(portletContextService, config, registrationData);
+ }
+ }
+ }
+
+ /**
+ * Called by the {@link PortletServlet} when it is destroyed, notifies the portlet container that the portlet needs to be unregistered
+ *
+ * @param config The {@link ServletConfig} for the {@link PortletServlet} that is being destroyed
+ * @param classLoader The portlet application's {@link ClassLoader}
+ * @param lifecycleCallback The callback the portlet container should call when unregistering the portlet
+ */
+ public static void unregister(ServletConfig config, DriverPortletContext portletAppContext, DriverPortletConfig portletContext, PortletServletLifecycleCallback lifecycleCallback) {
+ synchronized (REGISTERED_PORTLETS) {
+ REGISTERED_PORTLETS.remove(config);
+
+ //Driver services exist, notify them of the de-registration
+ if (portalDriverServices != null) {
+ final PortletContextService portletContextService = portalDriverServices.getPortletContextService();
+ portletContextService.unregister(portletAppContext, portletContext, lifecycleCallback);
+ }
+ else {
+ //Run the unregistered callback immediately since there is no portal to notify
+ lifecycleCallback.unregistered();
+ }
+ }
+ }
+
+ private static void registerPortlet(final PortletContextService portletContextService, final ServletConfig config,
+ final RegistrationData registrationData) {
+
+ try {
+ portletContextService.register(registrationData.portletName, config, registrationData.classLoader, registrationData.lifecycleCallback);
+ }
+ catch (PortletContainerException e) {
+ final ServletContext context = config.getServletContext();
+ context.log(e.getMessage(), e);
+ }
+ }
+
+ private static final class RegistrationData {
+ private final String portletName;
+ private final ClassLoader classLoader;
+ private final PortletServletLifecycleCallback lifecycleCallback;
+
+ public RegistrationData(String portletName, ClassLoader classLoader, PortletServletLifecycleCallback lifecycleCallback) {
+ this.portletName = portletName;
+ this.classLoader = classLoader;
+ this.lifecycleCallback = lifecycleCallback;
+ }
+ }
+}
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
index 82d268c..d5a87a5 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletContextService.java
@@ -83,16 +83,17 @@
/**
* Register a portlet application
*
- * @param config
- * @return
+ * @param config the portlet's config
+ * @param classLoader the portlet's classloader
+ * @param registrationCallback A callback to execute when registration is complete
* @throws PortletContainerException
*/
- String register(ServletConfig config) throws PortletContainerException;
+ void register(String portletName, ServletConfig config, ClassLoader classLoader, PortletServletLifecycleCallback registrationCallback) throws PortletContainerException;
/**
* Unregister a portlet application
*
* @param context
*/
- void unregister(DriverPortletContext context);
+ void unregister(DriverPortletContext portletContext, DriverPortletConfig portletConfig, PortletServletLifecycleCallback lifecycleCallback);
}
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletInvocationEvent.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletInvocationEvent.java
index d701085..50114e2 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletInvocationEvent.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletInvocationEvent.java
@@ -18,27 +18,19 @@
import javax.portlet.PortletRequest;
-import org.apache.pluto.container.PortletInvokerService;
+import org.apache.pluto.container.PortletInvokerService.Method;
import org.apache.pluto.container.PortletWindow;
public class PortletInvocationEvent {
- public static int LOAD = PortletInvokerService.METHOD_LOAD.intValue();
+ private final PortletRequest portletRequest;
- public static int ACTION = PortletInvokerService.METHOD_ACTION.intValue();
+ private final PortletWindow portletWindow;
- public static int RENDER = PortletInvokerService.METHOD_RENDER.intValue();
+ private final Method invocationMethod;
- public static int ADMIN = PortletInvokerService.METHOD_ADMIN.intValue();
-
- private PortletRequest portletRequest;
-
- private PortletWindow portletWindow;
-
- private int invocationMethod;
-
- public PortletInvocationEvent(PortletRequest portletRequest, PortletWindow portletWindow, int invocationMethod) {
+ public PortletInvocationEvent(PortletRequest portletRequest, PortletWindow portletWindow, Method invocationMethod) {
this.portletRequest = portletRequest;
this.portletWindow = portletWindow;
this.invocationMethod = invocationMethod;
@@ -48,7 +40,7 @@
return portletRequest;
}
- public int getInvocationMethod() {
+ public Method getInvocationMethod() {
return invocationMethod;
}
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet.java
index 3962977..b20cc56 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet.java
@@ -17,8 +17,6 @@
package org.apache.pluto.container.driver;
import java.io.IOException;
-import java.util.Timer;
-import java.util.TimerTask;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
@@ -44,7 +42,6 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.pluto.container.FilterManager;
-import org.apache.pluto.container.PortletContainerException;
import org.apache.pluto.container.PortletInvokerService;
import org.apache.pluto.container.PortletRequestContext;
import org.apache.pluto.container.PortletResponseContext;
@@ -58,10 +55,15 @@
* @version 1.1
* @since 09/22/2004
*/
-public class PortletServlet extends HttpServlet
+public class PortletServlet extends HttpServlet implements PortletServletLifecycleCallback
{
private static final long serialVersionUID = -5096339022539360365L;
+ private static final String CLASSLOADER_CONTEXT_KEY = PortletServlet.class.getName() + ".WEBAPP_CLASSLOADER";
+ private static final Object REGISTRATION_MUTEX = new Object(){};
+ /**
+ * Used to support portlets that don't handle event or resource requests
+ */
static class NullPortlet implements EventPortlet, ResourceServingPortlet, Portlet
{
public void processEvent(EventRequest arg0, EventResponse arg1)
@@ -102,31 +104,30 @@
/**
* The portlet instance wrapped by this servlet.
*/
- private Portlet portlet;
+ private volatile Portlet portlet;
+ /**
+ * The Event Portlet instance (the same object as portlet) wrapped by this servlet.
+ */
+ private volatile EventPortlet eventPortlet;
+ /**
+ * The Resource Portlet instance (the same object as portlet) wrapped by this servlet.
+ */
+ private volatile ResourceServingPortlet resourceServingPortlet;
/**
* The internal portlet context instance.
*/
- private DriverPortletContext portletContext;
-
+ private volatile DriverPortletContext portletAppContext;
/**
* The internal portlet config instance.
*/
- private DriverPortletConfig portletConfig;
-
+ private volatile DriverPortletConfig portletContext;
/**
- * The Event Portlet instance (the same object as portlet) wrapped by this
- * servlet.
+ * Reference to the portal provided services API
*/
- private EventPortlet eventPortlet;
+ private volatile PortalDriverContainerServices portalDriverServices;
- /** The resource serving portlet instance wrapped by this servlet. */
- private ResourceServingPortlet resourceServingPortlet;
-
- private PortletContextService contextService;
-
- private boolean started = false;
- Timer startTimer;
+ private volatile boolean started = false;
// HttpServlet Impl --------------------------------------------------------
@@ -141,137 +142,133 @@
* @throws ServletException
* if an error occurs while loading portlet.
*/
- public void init(ServletConfig config) throws ServletException
+ public void init(final ServletConfig config) throws ServletException
{
-
+ started = false;
+
// Call the super initialization method.
super.init(config);
// Retrieve portlet name as defined as an initialization parameter.
portletName = getInitParameter("portlet-name");
-
- started = false;
-
- startTimer = new Timer(true);
- final ServletContext servletContext = getServletContext();
+
+ //Grab a reference to the portlet's classloader and store it in the servlet context
final ClassLoader paClassLoader = Thread.currentThread().getContextClassLoader();
- startTimer.schedule(new TimerTask()
- {
- public void run()
- {
- synchronized(servletContext)
- {
- if (startTimer != null)
- {
- if (attemptRegistration(servletContext, paClassLoader ))
- {
- startTimer.cancel();
- startTimer = null;
- }
- }
- }
- }
- }, 1, 10000);
+ final ServletContext servletContext = config.getServletContext();
+ servletContext.setAttribute(CLASSLOADER_CONTEXT_KEY, paClassLoader);
+
+ PlutoServicesRegistry.register(portletName, config, paClassLoader, this);
}
-
- protected boolean attemptRegistration(ServletContext context, ClassLoader paClassLoader)
- {
- if (PlutoServices.getServices() != null)
- {
- contextService = PlutoServices.getServices().getPortletContextService();
- try
- {
- ServletConfig sConfig = getServletConfig();
- if (sConfig == null)
- {
- String msg = "Problem obtaining servlet configuration(getServletConfig() returns null).";
- context.log(msg);
- return true;
+
+ public void registered(PortalDriverContainerServices portalDriverServices, DriverPortletContext portletContext, DriverPortletConfig portletConfig) {
+ //sync is to make sure that modification of the portlet/portal references is atomic
+ synchronized (REGISTRATION_MUTEX) {
+ //Get references to pluto services and portlet configuration data
+ this.portalDriverServices = portalDriverServices;
+ this.portletAppContext = portletContext;
+ this.portletContext = portletConfig;
+
+ final PortletDefinition portletDD = portletConfig.getPortletDefinition();
+ this.portlet = loadPortlet(portletDD.getPortletClass());
+ if (this.portlet != null) {
+ try {
+ portlet.init(portletConfig);
+
+ //Init event and resource portlet references
+ initializeEventPortlet();
+ initializeResourceServingPortlet();
}
-
- String applicationName = contextService.register(sConfig);
- started = true;
- portletContext = contextService.getPortletContext(applicationName);
- portletConfig = contextService.getPortletConfig(applicationName, portletName);
-
+ catch (PortletException e) {
+ final ServletContext servletContext = this.getServletContext();
+ servletContext.log("Failed to initialize portlet '" + this.portletName + "' in web application " + this.getServletContext().getServletContextName(), e);
+
+ //failed to init portlet class, do cleanup
+ unregistered();
+ }
}
- catch (PortletContainerException ex)
- {
- context.log(ex.getMessage(),ex);
- return true;
+ else {
+ //failed to load portlet class, do cleanup
+ unregistered();
}
-
- PortletDefinition portletDD = portletConfig.getPortletDefinition();
-
- // Create and initialize the portlet wrapped in the servlet.
- try
- {
- Class<?> clazz = paClassLoader.loadClass((portletDD.getPortletClass()));
- portlet = (Portlet) clazz.newInstance();
- portlet.init(portletConfig);
- initializeEventPortlet();
- initializeResourceServingPortlet();
- return true;
- }
- catch (Exception ex)
- {
- context.log(ex.getMessage(),ex);
- // take out of service
- portlet = null;
- portletConfig = null;
- return true;
- }
+
+ //Mark the portlet as started
+ this.started = true;
}
- return false;
+ }
+
+ protected Portlet loadPortlet(String portletClass) {
+ final ServletContext servletContext = this.getServletContext();
+ final ClassLoader paClassLoader = (ClassLoader)servletContext.getAttribute(CLASSLOADER_CONTEXT_KEY);
+ final Class<?> clazz;
+ try {
+ clazz = paClassLoader.loadClass(portletClass);
+ }
+ catch (ClassNotFoundException e) {
+ servletContext.log("Failed to load portlet-class '" + portletClass + "' for " + getPortletNameForLogging(), e);
+ return null;
+ }
+
+ try {
+ return (Portlet) clazz.newInstance();
+ }
+ catch (InstantiationException e) {
+ servletContext.log("Failed to instantiate portlet-class '" + portletClass + "' for " + getPortletNameForLogging(), e);
+ return null;
+ }
+ catch (IllegalAccessException e) {
+ servletContext.log("Failed to instantiate portlet-class '" + portletClass + "' for " + getPortletNameForLogging(), e);
+ return null;
+ }
}
public void destroy()
{
- synchronized(getServletContext())
- {
- if ( startTimer != null )
- {
- startTimer.cancel();
- startTimer = null;
+ this.started = false;
+
+ final ServletConfig servletConfig = this.getServletConfig();
+ PlutoServicesRegistry.unregister(servletConfig, this.portletAppContext, this.portletContext, this);
+ }
+
+ public void unregistered() {
+ //sync is to make sure that modification of the portlet/portal references is atomic
+ synchronized (REGISTRATION_MUTEX) {
+ this.started = false;
+
+ try {
+ portlet.destroy();
}
- else if ( started && portletContext != null)
- {
- started = false;
- contextService.unregister(portletContext);
- if (portlet != null)
- {
- try
- {
- portlet.destroy();
- }
- catch (Exception e)
- {
- // ignore
- }
- portlet = null;
- }
+ catch (Throwable th) {
+ // Don't care for Exception
+ this.getServletContext().log("Error destroying " + getPortletNameForLogging(), th);
}
+
+ this.portalDriverServices = null;
+ this.portletAppContext = null;
+ this.portletContext = null;
+ this.portlet = null;
+ this.resourceServingPortlet = null;
+ this.eventPortlet = null;
+
super.destroy();
}
}
+
+ protected String getPortletNameForLogging() {
+ return "portlet '" + this.portletName + "' in web application " + this.getServletContext().getServletContextName();
+ }
- protected void doGet(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException
- {
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
dispatch(request, response);
- }
+ }
- protected void doPost(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException
- {
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
+ IOException {
dispatch(request, response);
- }
+ }
- protected void doPut(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException
- {
+ protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
dispatch(request, response);
- }
+ }
// Private Methods ---------------------------------------------------------
@@ -295,13 +292,15 @@
private void dispatch(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
- if (portlet == null)
- {
- throw new javax.servlet.UnavailableException("Portlet "+portletName+" unavailable");
+ if (!started) {
+ throw new javax.servlet.UnavailableException(getPortletNameForLogging() + " has not been initialized", 5);
+ }
+ if (portlet == null) {
+ throw new javax.servlet.UnavailableException(getPortletNameForLogging() + " is unavailable, there was a problem during initialization check the container logs for more details");
}
// Retrieve attributes from the servlet request.
- Integer methodId = (Integer) request.getAttribute(PortletInvokerService.METHOD_ID);
+ PortletInvokerService.Method method = (PortletInvokerService.Method) request.getAttribute(PortletInvokerService.METHOD_ID);
final PortletRequest portletRequest = (PortletRequest)request.getAttribute(PortletInvokerService.PORTLET_REQUEST);
@@ -317,12 +316,12 @@
request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
- requestContext.init(portletConfig, getServletContext(), request, response);
+ requestContext.init(portletContext, getServletContext(), request, response);
responseContext.init(request, response);
PortletWindow window = requestContext.getPortletWindow();
- PortletInvocationEvent event = new PortletInvocationEvent(portletRequest, window, methodId.intValue());
+ PortletInvocationEvent event = new PortletInvocationEvent(portletRequest, window, method);
notify(event, true, null);
@@ -331,100 +330,87 @@
try
{
-
- // The requested method is RENDER: call Portlet.render(..)
- if (methodId == PortletInvokerService.METHOD_RENDER)
- {
- RenderRequest renderRequest = (RenderRequest) portletRequest;
- RenderResponse renderResponse = (RenderResponse) portletResponse;
- filterManager.processFilter(renderRequest, renderResponse,
- portlet, portletContext);
- }
-
- // The requested method is RESOURCE: call
- // ResourceServingPortlet.serveResource(..)
- else if (methodId == PortletInvokerService.METHOD_RESOURCE)
- {
- ResourceRequest resourceRequest = (ResourceRequest) portletRequest;
- ResourceResponse resourceResponse = (ResourceResponse) portletResponse;
- filterManager.processFilter(resourceRequest, resourceResponse,
- resourceServingPortlet, portletContext);
- }
-
- // The requested method is ACTION: call Portlet.processAction(..)
- else if (methodId == PortletInvokerService.METHOD_ACTION)
- {
- ActionRequest actionRequest = (ActionRequest) portletRequest;
- ActionResponse actionResponse = (ActionResponse) portletResponse;
- filterManager.processFilter(actionRequest, actionResponse,
- portlet, portletContext);
- }
-
- // The request methode is Event: call Portlet.processEvent(..)
- else if (methodId == PortletInvokerService.METHOD_EVENT)
- {
- EventRequest eventRequest = (EventRequest) portletRequest;
- EventResponse eventResponse = (EventResponse) portletResponse;
- filterManager.processFilter(eventRequest, eventResponse,
- eventPortlet, portletContext);
- }
- // The requested method is ADMIN: call handlers.
- else if (methodId == PortletInvokerService.METHOD_ADMIN)
- {
- PortalAdministrationService pas = PlutoServices.getServices().getPortalAdministrationService();
-
- for (AdministrativeRequestListener l : pas.getAdministrativeRequestListeners())
- {
- l.administer(portletRequest, portletResponse);
+ switch (method) {
+ // The requested method is RENDER: call Portlet.render(..)
+ case RENDER: {
+ RenderRequest renderRequest = (RenderRequest) portletRequest;
+ RenderResponse renderResponse = (RenderResponse) portletResponse;
+ filterManager.processFilter(renderRequest, renderResponse, portlet, portletAppContext);
+ break;
}
- }
+ // The requested method is RESOURCE: call
+ // ResourceServingPortlet.serveResource(..)
+ case RESOURCE: {
+ ResourceRequest resourceRequest = (ResourceRequest) portletRequest;
+ ResourceResponse resourceResponse = (ResourceResponse) portletResponse;
+ filterManager.processFilter(resourceRequest, resourceResponse,
+ resourceServingPortlet, portletAppContext);
+ break;
+ }
+ // The requested method is ACTION: call Portlet.processAction(..)
+ case ACTION: {
+ ActionRequest actionRequest = (ActionRequest) portletRequest;
+ ActionResponse actionResponse = (ActionResponse) portletResponse;
+ filterManager.processFilter(actionRequest, actionResponse,
+ portlet, portletAppContext);
+ break;
+ }
+ // The request methode is Event: call Portlet.processEvent(..)
+ case EVENT: {
+ EventRequest eventRequest = (EventRequest) portletRequest;
+ EventResponse eventResponse = (EventResponse) portletResponse;
+ filterManager.processFilter(eventRequest, eventResponse,
+ eventPortlet, portletAppContext);
+ break;
+ }
+ // The requested method is ADMIN: call handlers.
+ case ADMIN: {
+ PortalAdministrationService pas = this.portalDriverServices.getPortalAdministrationService();
- // The requested method is LOAD: do nothing.
- else if (methodId == PortletInvokerService.METHOD_LOAD)
- {
- // Do nothing.
+ for (AdministrativeRequestListener l : pas.getAdministrativeRequestListeners())
+ {
+ l.administer(portletRequest, portletResponse);
+ }
+ break;
+ }
+ // The requested method is LOAD: do nothing.
+ case LOAD: {
+ // Nothing to do
+ }
}
notify(event, false, null);
}
- catch (UnavailableException ex)
+ catch (UnavailableException e)
{
- //
- // if (e.isPermanent()) { throw new
- // UnavailableException(e.getMessage()); } else { throw new
- // UnavailableException(e.getMessage(), e.getUnavailableSeconds());
- // }
- //
-
- // Portlet.destroy() isn't called by Tomcat, so we have to fix it.
- try
- {
- portlet.destroy();
+ if (e.isPermanent()) {
+ this.destroy();
+ this.getServletContext().log(getPortletNameForLogging() + " threw a permanent UnavailableException, taking the portlet out of service", e);
+ final javax.servlet.UnavailableException se = new javax.servlet.UnavailableException(e.getMessage());
+ se.initCause(e); //make sure we don't lose the original stack trace
+ throw se;
}
- catch (Throwable th)
- {
- // Don't care for Exception
- this.getServletContext().log("Error during portlet destroy.", th);
- }
- // take portlet out of service
- portlet = null;
-
- // TODO: Handle everything as permanently for now.
- throw new javax.servlet.UnavailableException(ex.getMessage());
+
+ //not permanent, mark the portlet unavailable for the specified time period
+
+ //Note when the unavailable time ends
+ final javax.servlet.UnavailableException se = new javax.servlet.UnavailableException(e.getMessage(), e.getUnavailableSeconds());
+ se.initCause(e); //make sure we don't lose the original stack trace
+ throw se;
}
catch (PortletException ex)
{
notify(event, false, ex);
- throw new ServletException(ex);
+ throw new ServletException(getPortletNameForLogging() + " threw an exception when processing a " + method + " request", ex);
}
- }
+ }
protected void notify(PortletInvocationEvent event, boolean pre, Throwable e)
{
- PortalAdministrationService pas = PlutoServices.getServices().getPortalAdministrationService();
+ PortalAdministrationService pas = this.portalDriverServices.getPortalAdministrationService();
for (PortletInvocationListener listener : pas.getPortletInvocationListeners())
{
@@ -449,10 +435,14 @@
{
eventPortlet = (EventPortlet) portlet;
}
- else
+ else if (portlet != null)
{
eventPortlet = new NullPortlet();
}
+ else
+ {
+ eventPortlet = null;
+ }
}
private void initializeResourceServingPortlet()
@@ -461,9 +451,13 @@
{
resourceServingPortlet = (ResourceServingPortlet) portlet;
}
- else
+ else if (portlet != null)
{
resourceServingPortlet = new NullPortlet();
}
+ else
+ {
+ resourceServingPortlet = null;
+ }
}
}
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServletLifecycleCallback.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServletLifecycleCallback.java
new file mode 100644
index 0000000..208f738
--- /dev/null
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServletLifecycleCallback.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.pluto.container.driver;
+
+/**
+ * Used to inform a {@link PortletServlet} that registration has been completed
+ *
+ * @author Eric Dalquist
+ */
+public interface PortletServletLifecycleCallback {
+ /**
+ * Called after the container has completely registered the portlet. This may be called in a different thread than called
+ * {@link PlutoServicesRegistry#register(javax.servlet.ServletConfig, ClassLoader, PortletRegistrationCallback)} meaning
+ * implementations and data structures they modify need to be thread-safe
+ */
+ void registered(PortalDriverContainerServices portalDriverServices, DriverPortletContext portletContext, DriverPortletConfig portletConfig);
+
+ /**
+ * Called after the container has completely registered the portlet. This may be called in a different thread than called
+ * {@link PlutoServicesRegistry#unregister(javax.servlet.ServletConfig, DriverPortletContext)} meaning implementations and
+ * data structures they modify need to be thread-safe
+ */
+ void unregistered();
+}
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
index 1be78a3..abc67e2 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletStateAwareResponseContextImpl.java
@@ -31,7 +31,7 @@
import org.apache.pluto.container.PortletStateAwareResponseContext;
import org.apache.pluto.container.PortletURLProvider;
import org.apache.pluto.container.PortletWindow;
-import org.apache.pluto.container.driver.PlutoServices;
+import org.apache.pluto.container.driver.PortalDriverServices;
import org.apache.pluto.container.impl.PortletURLImpl;
import org.apache.pluto.driver.core.PortalRequestContext;
import org.apache.pluto.driver.url.PortalURL;
@@ -129,6 +129,7 @@
public EventProvider getEventProvider()
{
- return isClosed() ? null : new EventProviderImpl(getPortletWindow(), PlutoServices.getServices().getPortletRegistryService());
+ //TODO fix method for getting reference to PortletRegistryService
+ return isClosed() ? null : new EventProviderImpl(getPortletWindow(), ((PortalDriverServices)super.getContainer().getContainerServices()).getPortletRegistryService());
}
}
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultOptionalContainerServices.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultOptionalContainerServices.java
index 83331e9..0419721 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultOptionalContainerServices.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultOptionalContainerServices.java
@@ -27,6 +27,7 @@
import org.apache.pluto.container.driver.OptionalContainerServices;
import org.apache.pluto.container.driver.PortalAdministrationService;
import org.apache.pluto.container.driver.PortalDriverContainerServices;
+import org.apache.pluto.container.driver.PortalDriverServices;
import org.apache.pluto.container.driver.PortletContextService;
import org.apache.pluto.container.driver.PortletRegistryService;
import org.apache.pluto.container.impl.PortletEnvironmentServiceImpl;
@@ -57,10 +58,10 @@
* Constructs an instance using the default portlet preferences service
* implementation.
*/
- public DefaultOptionalContainerServices() {
+ public DefaultOptionalContainerServices(PortalDriverServices portalDriverServices) {
rdService = new RequestDispatcherServiceImpl();
portletPreferencesService = new DefaultPortletPreferencesService();
- portletRegistryService = new PortletContextManager(rdService, new PortletAppDescriptorServiceImpl());
+ portletRegistryService = new PortletContextManager(portalDriverServices, new PortletAppDescriptorServiceImpl());
portletContextService = (PortletContextManager)portletRegistryService;
portletInvokerService = new DefaultPortletInvokerService(portletContextService);
portletEnvironmentService = new PortletEnvironmentServiceImpl();
@@ -77,8 +78,8 @@
* be used. Otherwise, the default portlet preferences service will be used.
* @param root the root optional container services implementation.
*/
- public DefaultOptionalContainerServices(OptionalContainerServices root, PortalDriverContainerServices driverServices) {
- this();
+ public DefaultOptionalContainerServices(OptionalContainerServices root, PortalDriverServices driverServices) {
+ this(driverServices);
if (root.getPortletPreferencesService() != null) {
portletPreferencesService = root.getPortletPreferencesService();
}
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
index 44d7619..c14fa74 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/DefaultPortletInvokerService.java
@@ -34,8 +34,6 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.pluto.container.FilterManager;
import org.apache.pluto.container.PortletContainerException;
import org.apache.pluto.container.PortletInvokerService;
@@ -44,6 +42,8 @@
import org.apache.pluto.container.driver.PortletContextService;
import org.apache.pluto.container.driver.PortletServlet;
import org.apache.pluto.container.util.StringManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Used internally to invoke/dispatch requests from the container to
@@ -98,7 +98,7 @@
if (LOG.isDebugEnabled()) {
LOG.debug("Performing Action Invocation");
}
- invoke(context, request, response, filterManager, PortletInvokerService.METHOD_ACTION);
+ invoke(context, request, response, filterManager, Method.ACTION);
}
/**
@@ -114,7 +114,7 @@
if (LOG.isDebugEnabled()) {
LOG.debug("Performing Render Invocation");
}
- invoke(context, request, response, filterManager, PortletInvokerService.METHOD_RENDER);
+ invoke(context, request, response, filterManager, Method.RENDER);
}
/**
@@ -130,7 +130,7 @@
if (LOG.isDebugEnabled()) {
LOG.debug("Performing Render Invocation");
}
- invoke(context, request, response, filterManager, PortletInvokerService.METHOD_EVENT);
+ invoke(context, request, response, filterManager, Method.EVENT);
}
/**
@@ -146,7 +146,7 @@
if (LOG.isDebugEnabled()) {
LOG.debug("Performing Resource Invocation");
}
- invoke(context, request, response, filterManager, PortletInvokerService.METHOD_RESOURCE);
+ invoke(context, request, response, filterManager, Method.RESOURCE);
}
/**
@@ -161,7 +161,7 @@
if (LOG.isDebugEnabled()) {
LOG.debug("Performing Load Invocation.");
}
- invoke(context, request, response, PortletInvokerService.METHOD_LOAD);
+ invoke(context, request, response, Method.LOAD);
}
public void admin(PortletRequestContext context, PortletRequest request, PortletResponse response)
@@ -170,7 +170,7 @@
LOG.debug("Performing Admin Invocation.");
}
- invoke(context, request, response, PortletInvokerService.METHOD_ADMIN);
+ invoke(context, request, response, Method.ADMIN);
}
// Private Invoke Method ---------------------------------------------------
@@ -178,10 +178,10 @@
private final void invoke(PortletRequestContext context,
PortletRequest request,
PortletResponse response,
- Integer methodID)
+ Method method)
throws PortletException, IOException, PortletContainerException {
- invoke(context, request, response, null, methodID);
+ invoke(context, request, response, null, method);
}
/**
@@ -198,7 +198,7 @@
PortletRequest request,
PortletResponse response,
FilterManager filterManager,
- Integer methodID)
+ Method method)
throws PortletException, IOException, PortletContainerException {
PortletWindow portletWindow = context.getPortletWindow();
@@ -219,20 +219,20 @@
try {
- containerRequest.setAttribute(PortletInvokerService.METHOD_ID, methodID);
+ containerRequest.setAttribute(PortletInvokerService.METHOD_ID, method);
containerRequest.setAttribute(PortletInvokerService.PORTLET_REQUEST, request);
containerRequest.setAttribute(PortletInvokerService.PORTLET_RESPONSE, response);
containerRequest.setAttribute(PortletInvokerService.FILTER_MANAGER, filterManager);
- if (methodID.equals(PortletInvokerService.METHOD_RESOURCE))
- {
- dispatcher.forward(containerRequest, containerResponse);
+ switch (method) {
+ case RESOURCE: {
+ dispatcher.forward(containerRequest, containerResponse);
+ break;
+ }
+ default: {
+ dispatcher.include(containerRequest, containerResponse);
+ }
}
- else
- {
- dispatcher.include(containerRequest, containerResponse);
- }
-
} catch (javax.servlet.UnavailableException ex) {
int seconds = ex.isPermanent() ? -1 : ex.getUnavailableSeconds();
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PlutoServicesRegistryBean.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PlutoServicesRegistryBean.java
new file mode 100644
index 0000000..c5adafb
--- /dev/null
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PlutoServicesRegistryBean.java
@@ -0,0 +1,22 @@
+package org.apache.pluto.driver.container;
+
+import org.apache.pluto.container.driver.PlutoServicesRegistry;
+import org.apache.pluto.container.driver.PortalDriverServices;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+
+public class PlutoServicesRegistryBean implements InitializingBean, DisposableBean {
+ private PortalDriverServices portalDriverServices;
+
+ public PlutoServicesRegistryBean(PortalDriverServices portalDriverServices) {
+ this.portalDriverServices = portalDriverServices;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ PlutoServicesRegistry.registerPortalDriverServices(portalDriverServices);
+ }
+
+ public void destroy() throws Exception {
+ PlutoServicesRegistry.unregisterPortalDriverServices(portalDriverServices);
+ }
+}
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortalDriverServicesImpl.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortalDriverServicesImpl.java
index b569191..594261c 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortalDriverServicesImpl.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortalDriverServicesImpl.java
@@ -35,9 +35,9 @@
import org.apache.pluto.container.driver.PortletContextService;
import org.apache.pluto.container.driver.PortletRegistryService;
import org.apache.pluto.container.driver.RequiredContainerServices;
+import org.apache.pluto.container.impl.PortletAppDescriptorServiceImpl;
import org.apache.pluto.container.impl.PortletEnvironmentServiceImpl;
import org.apache.pluto.container.impl.RequestDispatcherServiceImpl;
-import org.apache.pluto.container.impl.PortletAppDescriptorServiceImpl;
public class PortalDriverServicesImpl implements RequiredContainerServices, OptionalContainerServices, PortalDriverServices
@@ -166,7 +166,7 @@
protected void createDefaultServicesIfNeeded()
{
rdService = rdService == null ? new RequestDispatcherServiceImpl() : rdService;
- portletRegistryService = portletRegistryService == null ? new PortletContextManager(rdService, new PortletAppDescriptorServiceImpl()) : portletRegistryService;
+ portletRegistryService = portletRegistryService == null ? new PortletContextManager(this, new PortletAppDescriptorServiceImpl()) : portletRegistryService;
portletContextService = portletContextService == null ? (PortletContextManager)portletRegistryService : portletContextService;
portalAdministrationService = portalAdministrationService == null ? new DefaultPortalAdministrationService() : portalAdministrationService;
ccppProfileService = ccppProfileService == null ? new DummyCCPPProfileServiceImpl() : ccppProfileService;
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
index 9e6cf05..5b893d6 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/container/PortletContextManager.java
@@ -28,21 +28,23 @@
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.pluto.container.PortletAppDescriptorService;
import org.apache.pluto.container.PortletContainerException;
import org.apache.pluto.container.PortletWindow;
import org.apache.pluto.container.RequestDispatcherService;
-import org.apache.pluto.container.PortletAppDescriptorService;
import org.apache.pluto.container.driver.DriverPortletConfig;
import org.apache.pluto.container.driver.DriverPortletContext;
+import org.apache.pluto.container.driver.PortalDriverServices;
import org.apache.pluto.container.driver.PortletContextService;
import org.apache.pluto.container.driver.PortletRegistryEvent;
import org.apache.pluto.container.driver.PortletRegistryListener;
import org.apache.pluto.container.driver.PortletRegistryService;
+import org.apache.pluto.container.driver.PortletServletLifecycleCallback;
import org.apache.pluto.container.om.portlet.PortletApplicationDefinition;
import org.apache.pluto.container.om.portlet.PortletDefinition;
import org.apache.pluto.container.util.ClasspathScanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Manager used to cache the portlet configurations which have
@@ -59,16 +61,16 @@
private static final Logger LOG = LoggerFactory.getLogger(PortletContextManager.class);
/**
- * The PortletContext cache map: key is servlet context, and value is the
- * associated portlet context.
- */
- private Map<String,DriverPortletContext> portletContexts = new HashMap<String,DriverPortletContext>();
-
- /**
* List of application id resolvers. *
*/
private static final List<ApplicationIdResolver> APP_ID_RESOLVERS = new ArrayList<ApplicationIdResolver>();
+ /**
+ * The PortletContext cache map: key is servlet context, and value is the
+ * associated portlet context.
+ */
+ private final Map<String,DriverPortletContextHolder> portletContexts = new HashMap<String,DriverPortletContextHolder>();
+
// Private Member Variables ------------------------------------------------
@@ -90,18 +92,27 @@
*/
private final Map<String,ClassLoader> classLoaders = new HashMap<String,ClassLoader>();
- private final RequestDispatcherService rdService;
+ private final PortalDriverServices portalDriverServices;
private final PortletDescriptorRegistry portletRegistry;
// Constructor -------------------------------------------------------------
- public PortletContextManager(RequestDispatcherService rdService, PortletAppDescriptorService portletAppDescriptorService) {
- this.rdService = rdService;
+ public PortletContextManager(PortalDriverServices portalDriverServices, PortletAppDescriptorService portletAppDescriptorService) {
+ this.portalDriverServices = portalDriverServices;
portletRegistry = new PortletDescriptorRegistry(portletAppDescriptorService);
}
// Public Methods ----------------------------------------------------------
+
+ private static final class DriverPortletContextHolder {
+ private final DriverPortletContext portletAppContext;
+ private int portletCount = 0;
+
+ public DriverPortletContextHolder(DriverPortletContext portletAppContext) {
+ this.portletAppContext = portletAppContext;
+ }
+ }
/**
* Retrieves the PortletContext associated with the given ServletContext.
@@ -111,58 +122,93 @@
* @return the InternalPortletContext associated with the ServletContext.
* @throws PortletContainerException
*/
- public String register(ServletConfig config) throws PortletContainerException {
- ServletContext servletContext = config.getServletContext();
- String contextPath = getContextPath(servletContext);
- if (!portletContexts.containsKey(contextPath)) {
+ public synchronized void register(String portletName, ServletConfig config, ClassLoader classLoader,
+ PortletServletLifecycleCallback registrationCallback) throws PortletContainerException {
+
+ final ServletContext servletContext = config.getServletContext();
+ final String contextPath = getContextPath(servletContext);
+
+ //Get or register the portlet application
+ DriverPortletContextHolder portletAppContextHolder = portletContexts.get(contextPath);
+ if (portletAppContextHolder == null) {
+ final PortletApplicationDefinition portletApp = portletRegistry.getPortletAppDD(servletContext, contextPath, contextPath);
+ final RequestDispatcherService requestDispatcherService = this.portalDriverServices.getRequestDispatcherService();
+ final DriverPortletContextImpl portletAppContext = new DriverPortletContextImpl(servletContext, portletApp, requestDispatcherService);
+
+ //Verify the app loaded correctly
+ final String appName = portletAppContext.getApplicationName();
+ if (appName == null) {
+ throw new PortletContainerException(
+ "Portlet application name was null when trying to register portlet '" + portletName
+ + "' from webapp " + contextPath);
+ }
+
+ portletAppContextHolder = new DriverPortletContextHolder(portletAppContext);
- PortletApplicationDefinition portletApp = portletRegistry.getPortletAppDD(servletContext, contextPath, contextPath);
-
- DriverPortletContext portletContext = new DriverPortletContextImpl(servletContext, portletApp, rdService);
-
- portletContexts.put(contextPath, portletContext);
-
- fireRegistered(portletContext);
+ portletContexts.put(contextPath, portletAppContextHolder);
+ classLoaders.put(portletApp.getName(), classLoader);
+
+ fireRegistered(portletAppContext);
if (LOG.isInfoEnabled()) {
LOG.info("Registered portlet application for context '" + contextPath + "'");
-
- LOG.info("Registering "+portletApp.getPortlets().size()+" portlets for context /"+portletContext.getApplicationName());
- }
-
- classLoaders.put(portletApp.getName(), Thread.currentThread().getContextClassLoader());
- for (PortletDefinition portlet: portletApp.getPortlets()) {
- String appName = portletContext.getApplicationName();
- if (appName == null) {
- throw new PortletContainerException("Portlet application name should not be null.");
- }
- portletConfigs.put(
- portletContext.getApplicationName() + "/" + portlet.getPortletName(),
- new DriverPortletConfigImpl(portletContext, portlet)
- );
- }
- } else {
- if (LOG.isInfoEnabled()) {
- LOG.info("Portlet application for context '" + contextPath + "' already registered.");
}
}
- return contextPath;
+
+
+ //register the portlet
+ final DriverPortletContext portletAppContext = portletAppContextHolder.portletAppContext;
+ final PortletApplicationDefinition portletApp = portletAppContext.getPortletApplicationDefinition();
+
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Portlet application for context '" + contextPath
+ + "' already registered, incrementing portlet count");
+ }
+
+ final PortletDefinition portlet = portletApp.getPortlet(portletName);
+
+ final DriverPortletConfigImpl portletContext = new DriverPortletConfigImpl(portletAppContext, portlet);
+ final String portletAppKey = portletAppContext.getApplicationName() + "/" + portlet.getPortletName();
+ portletConfigs.put(portletAppKey, portletContext);
+
+ //Notify the portlet it has been registered
+ try {
+ registrationCallback.registered(portalDriverServices, portletAppContext, portletContext);
+ portletAppContextHolder.portletCount++;
+ }
+ catch (Throwable t) {
+ //registration failed, cleanup
+ portletConfigs.remove(portletAppKey);
+
+ throw new PortletContainerException("Failed to register portlet " + portlet.getPortletName() + " from context " + portletAppContext.getApplicationName(), t);
+ }
+
+ //TODO fireRegistered(portletContext);
+
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Registered portlet " + portlet.getPortletName() + " from context " + portletAppContext.getApplicationName() + " which now has " + portletAppContextHolder.portletCount + " registered portlets");
+ }
}
- /**
- * @see org.apache.pluto.container.driver.PortletContextService#unregister(org.apache.pluto.container.driver.DriverPortletContext)
- */
- public void unregister(DriverPortletContext context) {
- portletContexts.remove(context.getApplicationName());
- classLoaders.remove(context.getApplicationName());
- Iterator<String> configs = portletConfigs.keySet().iterator();
- while (configs.hasNext()) {
- String key = configs.next();
- if (key.startsWith(context.getApplicationName() + "/")) {
- configs.remove();
+
+ public synchronized void unregister(DriverPortletContext portletAppContext, DriverPortletConfig portletContext, PortletServletLifecycleCallback lifecycleCallback) {
+ lifecycleCallback.unregistered();
+
+ final String portletAppKey = portletAppContext.getApplicationName() + "/" + portletContext.getPortletName();
+
+ if (portletConfigs.remove(portletAppKey) != null) {
+ //only bother with unregistration work if the was successfully registered in the first place
+
+ //TODO fireRemoved(portletAppContext);
+
+ final DriverPortletContextHolder driverPortletContextHolder = portletContexts.get(portletAppContext.getApplicationName());
+ driverPortletContextHolder.portletCount--;
+
+ //Last portlet unregistered, remove the app
+ if (driverPortletContextHolder.portletCount == 0) {
+ fireRemoved(portletAppContext);
}
}
- fireRemoved(context);
}
/**
@@ -175,22 +221,32 @@
/**
* @see org.apache.pluto.container.driver.PortletContextService#getPortletContexts()
*/
- public Iterator<DriverPortletContext> getPortletContexts() {
- return new HashSet<DriverPortletContext>(portletContexts.values()).iterator();
+ public synchronized Iterator<DriverPortletContext> getPortletContexts() {
+ final List<DriverPortletContext> portletContextsList = new ArrayList<DriverPortletContext>(portletContexts.size());
+
+ for (final DriverPortletContextHolder portletContextHolder : portletContexts.values()) {
+ portletContextsList.add(portletContextHolder.portletAppContext);
+ }
+
+ return portletContextsList.iterator();
}
/**
* @see org.apache.pluto.container.driver.PortletContextService#getPortletContext(java.lang.String)
*/
public DriverPortletContext getPortletContext(String applicationName) {
- return portletContexts.get(applicationName);
+ final DriverPortletContextHolder driverPortletContextHolder = portletContexts.get(applicationName);
+ if (driverPortletContextHolder == null) {
+ return null;
+ }
+ return driverPortletContextHolder.portletAppContext;
}
/**
* @see org.apache.pluto.container.driver.PortletContextService#getPortletContext(org.apache.pluto.container.PortletWindow)
*/
public DriverPortletContext getPortletContext(PortletWindow portletWindow) throws PortletContainerException {
- return portletContexts.get(portletWindow.getPortletDefinition().getApplication().getName());
+ return getPortletContext(portletWindow.getPortletDefinition().getApplication().getName());
}
@@ -224,9 +280,12 @@
* @see org.apache.pluto.container.driver.PortletRegistryService#getPortletApplication(java.lang.String)
*/
public PortletApplicationDefinition getPortletApplication(String applicationName) throws PortletContainerException {
- DriverPortletContext ipc = portletContexts.get(applicationName);
- if (ipc != null) {
- return ipc.getPortletApplicationDefinition();
+ final DriverPortletContextHolder driverPortletContextHolder = portletContexts.get(applicationName);
+ if (driverPortletContextHolder != null) {
+ DriverPortletContext ipc = driverPortletContextHolder.portletAppContext;
+ if (ipc != null) {
+ return ipc.getPortletApplicationDefinition();
+ }
}
String msg = "Unable to retrieve portlet application: '"+applicationName+"'";
LOG.warn(msg);
@@ -255,6 +314,7 @@
}
private void fireRegistered(DriverPortletContext context) {
+ //TODO differentiate between portlet app and portlet events
PortletRegistryEvent event = new PortletRegistryEvent();
event.setPortletApplication(context.getPortletApplicationDefinition());
@@ -265,6 +325,7 @@
}
private void fireRemoved(DriverPortletContext context) {
+ //TODO differentiate between portlet app and portlet events
PortletRegistryEvent event = new PortletRegistryEvent();
event.setPortletApplication(context.getPortletApplicationDefinition());
diff --git a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/core/PortletWindowImpl.java b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/core/PortletWindowImpl.java
index a67056a..4f3354f 100644
--- a/pluto-portal-driver/src/main/java/org/apache/pluto/driver/core/PortletWindowImpl.java
+++ b/pluto-portal-driver/src/main/java/org/apache/pluto/driver/core/PortletWindowImpl.java
@@ -19,16 +19,16 @@
import javax.portlet.PortletMode;
import javax.portlet.WindowState;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.apache.pluto.container.PortletContainer;
import org.apache.pluto.container.PortletContainerException;
import org.apache.pluto.container.PortletWindow;
import org.apache.pluto.container.PortletWindowID;
-import org.apache.pluto.container.driver.PlutoServices;
+import org.apache.pluto.container.driver.PortalDriverServices;
import org.apache.pluto.container.om.portlet.PortletDefinition;
import org.apache.pluto.driver.services.portal.PortletWindowConfig;
import org.apache.pluto.driver.url.PortalURL;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Implementation of <code>PortletWindow</code> interface.
@@ -59,7 +59,8 @@
try
{
String applicationName = config.getContextPath();
- this.portlet = PlutoServices.getServices().getPortletRegistryService().getPortlet(applicationName, config.getPortletName());
+ //TODO need better way to get reference to PortletRegistryService
+ this.portlet = ((PortalDriverServices)container).getPortletRegistryService().getPortlet(applicationName, config.getPortletName());
}
catch (PortletContainerException ex)
{
diff --git a/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml b/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml
index 6b45907..0530df4 100644
--- a/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml
+++ b/pluto-portal/src/main/webapp/WEB-INF/pluto-portal-driver-services-config.xml
@@ -55,13 +55,9 @@
<ref bean="PortalDriverServices"/>
</constructor-arg>
</bean>
-
- <bean id="PlutoServices"
- class="org.apache.pluto.container.driver.PlutoServices"
- singleton="true">
- <constructor-arg>
- <ref bean="PortalDriverServices"/>
- </constructor-arg>
+
+ <bean class="org.apache.pluto.driver.container.PlutoServicesRegistryBean">
+ <constructor-arg ref="PortalDriverServices" />
</bean>
<bean id="PortalDriverServices"
@@ -224,7 +220,7 @@
<bean id="PortletContextService"
class="org.apache.pluto.driver.container.PortletContextManager">
<constructor-arg>
- <ref bean="RequestDispatcherService"/>
+ <ref bean="PortalDriverServices"/>
</constructor-arg>
<constructor-arg>
<bean class="org.apache.pluto.container.impl.PortletAppDescriptorServiceImpl"/>