Package org.apache.jetspeed.factory

Source Code of org.apache.jetspeed.factory.JetspeedPortletFactory

/*
* 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.jetspeed.factory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.portlet.Portlet;
import javax.portlet.PortletException;
import javax.portlet.PortletURLGenerationListener;
import javax.portlet.PreferencesValidator;
import javax.portlet.UnavailableException;
import javax.portlet.filter.PortletFilter;
import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.jetspeed.PortalContext;
import org.apache.jetspeed.container.ContainerInfo;
import org.apache.jetspeed.container.JetspeedPortletConfig;
import org.apache.jetspeed.container.JetspeedPortletConfigImpl;
import org.apache.jetspeed.container.JetspeedPortletContext;
import org.apache.jetspeed.container.JetspeedPortletContextImpl;
import org.apache.jetspeed.container.JetspeedServletContextProviderImpl;
import org.apache.jetspeed.om.portlet.Filter;
import org.apache.jetspeed.om.portlet.Language;
import org.apache.jetspeed.om.portlet.Listener;
import org.apache.jetspeed.om.portlet.PortletApplication;
import org.apache.jetspeed.om.portlet.PortletDefinition;
import org.apache.pluto.container.RequestDispatcherService;
import org.apache.portals.bridges.common.ServletContextProvider;

/**
* <p>
* JetspeedPortletFactory
* </p>
* <p>
*
* </p>
*
* @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
* @version $Id: JetspeedPortletFactory.java 771327 2009-05-04 15:02:23Z ate $
*
*/
public class JetspeedPortletFactory implements PortletFactory
{
    private static final Logger log = LoggerFactory.getLogger(JetspeedPortletFactory.class);
   
    private Map<String, Map<String, PortletInstance>> portletCache;
    private Map<String, Map<String, PreferencesValidator>> validatorCache;
    private Map<String, Map<String, PortletFilterInstance>> portletFilterCache;
    private Map<String, List<PortletURLGenerationListener>> portletListenerCache;
    private Map<String, Map<Locale, ResourceBundle>> applicationResourceBundleCache;
    private Map<String, Map<String, Map<Locale, ResourceBundle>>> portletsResourceBundleCache;
    private final Map<String, ClassLoader> classLoaderMap;
    private PortalContext portalContext;
    private RequestDispatcherService rdService;
    private ServletContextProvider servletContextProvider;  

    /**
     * Flag whether this factory will create proxy instances for actual portlet
     * instances or not.
     */
    private boolean portletProxyUsed;

    /**
     * Flag whether the instantiated proxy will switch edit_defaults mode to
     * edit mode automatically or not.
     */
    private boolean autoSwitchEditDefaultsModeToEditMode;

    /**
     * Flag whether the instantiated proxy will switch config mode to built-in
     * config edit page or not.
     */
    private boolean autoSwitchConfigMode;

    private String customConfigModePortletUniqueName;

    public JetspeedPortletFactory(RequestDispatcherService rdService)
    {
        this(rdService, false, false);
    }
   
    public JetspeedPortletFactory(RequestDispatcherService rdService, boolean autoSwitchConfigMode, boolean autoSwitchEditDefaultsModeToEditMode)
    {
        this.rdService = rdService;
        this.portletCache = Collections.synchronizedMap(new HashMap<String, Map<String, PortletInstance>>());
        this.validatorCache = Collections.synchronizedMap(new HashMap<String, Map<String, PreferencesValidator>>());
        this.classLoaderMap = Collections.synchronizedMap(new HashMap<String, ClassLoader>());
        this.portletFilterCache = Collections.synchronizedMap(new HashMap<String, Map<String, PortletFilterInstance>>());
        this.portletListenerCache = Collections.synchronizedMap(new HashMap<String, List<PortletURLGenerationListener>>());
        this.applicationResourceBundleCache = Collections.synchronizedMap(new HashMap<String, Map<Locale, ResourceBundle>>());
        this.portletsResourceBundleCache = Collections.synchronizedMap(new HashMap<String, Map<String, Map<Locale, ResourceBundle>>>());
        this.autoSwitchConfigMode = autoSwitchConfigMode;
        this.autoSwitchEditDefaultsModeToEditMode = autoSwitchEditDefaultsModeToEditMode;
        this.portletProxyUsed = (this.autoSwitchConfigMode || this.autoSwitchEditDefaultsModeToEditMode);
        this.servletContextProvider = new JetspeedServletContextProviderImpl(rdService);
    }
   
    protected ResourceBundle loadResourceBundle( Locale locale, String bundleName, ClassLoader cl )
    {
        ResourceBundle resourceBundle = null;
        try
        {
            resourceBundle = ResourceBundle.getBundle(bundleName, locale, cl);
        }
        catch (MissingResourceException x)
        {
            return null;
        }
        return resourceBundle;
    }
   
   
    public void setPortalContext(PortalContext portalContext)
    {
        this.portalContext = portalContext;
    }

    public void setPortletProxyUsed(boolean portletProxyUsed)
    {
        this.portletProxyUsed = portletProxyUsed;
    }

    public boolean getPortletProxyUsed()
    {
        return this.portletProxyUsed;
    }

    public void setCustomConfigModePortletUniqueName(String customConfigModePortletUniqueName)
    {
        this.customConfigModePortletUniqueName = customConfigModePortletUniqueName;
    }

    public String getCustomConfigModePortletUniqueName()
    {
        return this.customConfigModePortletUniqueName;
    }
   
    public void registerPortletApplication(PortletApplication pa, ClassLoader cl)
    {
        synchronized (classLoaderMap)
        {
            unregisterPortletApplication(pa);           
            classLoaderMap.put(pa.getName(), cl);
        }
    }

    public void unregisterPortletApplication(PortletApplication pa)
    {
        String paName = pa.getName();
        ClassLoader paCl = this.classLoaderMap.remove(paName);
       
        if (paCl != null)
        {
            applicationResourceBundleCache.remove(paName);
            portletsResourceBundleCache.remove(paName);
            Map<String, PortletInstance> portletInstanceCache = this.portletCache.remove(paName);
            Map<String, PortletFilterInstance> portletFilterInstanceCache = this.portletFilterCache.remove(paName);
           
            ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
           
            try
            {
                Thread.currentThread().setContextClassLoader(paCl);

                if (portletInstanceCache != null && !portletInstanceCache.isEmpty())
                {
                    synchronized (portletInstanceCache)
                    {
                        for (PortletInstance portlet : portletInstanceCache.values())
                        {
                            try
                            {
                                portlet.destroy();
                            }
                            catch (Exception e)
                            {
                                String msg = "Exception occurred during destroying portlet " + portlet.getClass();
                                log.error(msg, e);
                            }
                        }
                    }
                }
               
                if (portletFilterInstanceCache != null && !portletFilterInstanceCache.isEmpty())
                {
                    synchronized (portletFilterInstanceCache)
                    {
                        for (PortletFilterInstance portletFilter : portletFilterInstanceCache.values())
                        {
                            try
                            {
                                portletFilter.destroy();
                            }
                            catch (Exception e)
                            {
                                String msg = "Exception occurred during destroying portlet " + portletFilter.getClass();
                                log.error(msg, e);
                            }
                        }
                    }
                }
            }
            finally
            {
                Thread.currentThread().setContextClassLoader(currentContextClassLoader);
            }
           
            this.validatorCache.remove(paName);
            this.portletListenerCache.remove(paName);
        }
    }

    public PreferencesValidator getPreferencesValidator(PortletDefinition pd)
    {
        PreferencesValidator validator = null;
       
        try
        {
            String paName = pd.getApplication().getName();
            String pdName = pd.getPortletName();
           
            Map<String, PreferencesValidator> instanceCache = this.validatorCache.get(paName);
            validator = (instanceCache != null) ? instanceCache.get(pdName) : null;
           
            if (validator == null)
            {
                String className = pd.getPreferenceValidatorClassname();
               
                if (className != null)
                {
                    ClassLoader paCl = classLoaderMap.get(paName);
                    if (paCl == null)
                    {
                        throw new UnavailableException("Portlet Application " + paName + " not available");
                    }
                   
                    try
                    {
                        Class<?> clazz = paCl.loadClass(className);
                        validator = (PreferencesValidator) clazz.newInstance();
                       
                        if (instanceCache == null)
                        {
                            instanceCache = Collections.synchronizedMap(new HashMap<String, PreferencesValidator>());
                            this.validatorCache.put(paName, instanceCache);
                        }
                       
                        instanceCache.put(pdName, validator);
                    }
                    catch (Exception e)
                    {
                        String msg = "Cannot create PreferencesValidator instance "+className+" for Portlet "+pdName;
                        log.error(msg, e);
                    }
                }
            }
        }
        catch (Exception e)
        {
            log.error(e.getMessage(),e);
        }
       
        return validator;
    }
   
    public ResourceBundle getResourceBundle(PortletApplication pa, Locale locale)
    {
        ResourceBundle bundle = null;
       
        try
        {
            if (locale != null && pa.getResourceBundle() != null)
            {
                String paName = pa.getName();
                Map<Locale, ResourceBundle> bundleCache = applicationResourceBundleCache.get(paName);
                if (bundleCache == null)
                {
                    bundleCache = Collections.synchronizedMap(new HashMap<Locale, ResourceBundle>());
                    applicationResourceBundleCache.put(paName, bundleCache);
                }
                bundle = bundleCache.get(locale);
                // check if the bundle doesn't contain the key (as a null value might be stored before)
                if (!bundleCache.containsKey(locale) )
                {
                    ClassLoader paCl = classLoaderMap.get(paName);
                   
                    if (paCl == null)
                    {
                        throw new UnavailableException("Portlet Application " + paName + " not available");
                    }
                    bundle = loadResourceBundle(locale, pa.getResourceBundle(), paCl);
                    // even if bundle isn't found, store a null value in the HashMap so we don't need to go
                    // look for it again
                    bundleCache.put(locale, bundle);
                }
            }
        }
        catch (Exception e)
        {
            log.error(e.getMessage(),e);
        }
        return bundle;
    }
   
    public ResourceBundle getResourceBundle(PortletDefinition pd, Locale locale)
    {
        ResourceBundle bundle = null;
       
        try
        {
            String paName = pd.getApplication().getName();
            String pdName = pd.getPortletName();
           
            Map<String, Map<Locale, ResourceBundle>> portletResourceBundleCache = portletsResourceBundleCache.get(paName);
            if (portletResourceBundleCache == null)
            {
                portletResourceBundleCache = Collections.synchronizedMap(new HashMap<String, Map<Locale, ResourceBundle>>());
                portletsResourceBundleCache.put(paName, portletResourceBundleCache);
            }
            Map<Locale, ResourceBundle> bundleCache = portletResourceBundleCache.get(pdName);
            if (bundleCache == null)
            {
                bundleCache = Collections.synchronizedMap(new HashMap<Locale, ResourceBundle>());
            }
            bundle = bundleCache.get(locale);
            if (bundle == null)
            {
                Language l = pd.getLanguage(locale);
                if (pd.getResourceBundle() == null)
                {
                    bundle = new InlinePortletResourceBundle(l.getTitle(), l.getShortTitle(), l.getKeywords());
                }
                else
                {
                    ClassLoader paCl = classLoaderMap.get(paName);
                   
                    if (paCl == null)
                    {
                        throw new UnavailableException("Portlet Application " + paName + " not available");
                    }
                    ResourceBundle loadedBundle = loadResourceBundle(l.getLocale(), pd.getResourceBundle(), paCl);
                    if (loadedBundle != null)
                    {
                        bundle = new InlinePortletResourceBundle(l.getTitle(), l.getShortTitle(), l.getKeywords(), loadedBundle);
                    }
                    else
                    {
                        bundle = new InlinePortletResourceBundle(l.getTitle(), l.getShortTitle(), l.getKeywords());
                    }
                }
                bundleCache.put(locale, bundle);
            }
        }
        catch (Exception e)
        {
            log.error(e.getMessage(),e);
        }
        return bundle;
    }

    /**
     * Gets a portlet by either creating it or returning a handle to it from the
     * portlet 'cache'
     *
     * @param portletDefinition
     *            The definition of the portlet
     * @return PortletInstance
     * @throws PortletException
     */
    public PortletInstance getPortletInstance(ServletContext servletContext, PortletDefinition pd) throws PortletException
    {
        return getPortletInstance(servletContext, pd, this.portletProxyUsed);
    }
   
    /**
     * Gets a portlet by either creating it or returning a handle to it from the
     * portlet 'cache'
     *
     * @param portletDefinition
     *            The definition of the portlet
     * @return PortletInstance
     * @throws PortletException
     */
    public PortletInstance getPortletInstance(ServletContext servletContext, PortletDefinition pd, boolean proxyUsed) throws PortletException
    {
        PortletInstance portlet = null;
        PortletApplication pa = pd.getApplication();
        String paName = pa.getName();
        String pdName = pd.getPortletName();
       
        try
        {
            Map<String, PortletInstance> instanceCache = this.portletCache.get(paName);
           
            if (instanceCache != null)
            {
                portlet = instanceCache.get(pdName);
            }
           
            // If the current cached portlet instance is a proxied object as it is not expected,
            // recreate the portlet instance.
            if (portlet != null && this.portletProxyUsed && !proxyUsed && portlet.isProxyInstance())
            {
                portlet = null;
            }
           
            if (portlet == null)
            {
                ClassLoader paCl = classLoaderMap.get(paName);
               
                if (paCl == null)
                {
                    throw new UnavailableException("Portlet Application " + paName + " not available");
                }
               
                ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
               
                try
                {
                    Class<?> clazz = paCl.loadClass(pd.getPortletClass());
                   
                    try
                    {
                        Thread.currentThread().setContextClassLoader(paCl);
                        // wrap new Portlet inside PortletInstance which ensures
                        // the destroy
                        // method will wait for all its invocation threads to
                        // complete
                        // and thereby releasing all its ClassLoader locks as
                        // needed for local portlets.

                        if (proxyUsed)
                        {
                            portlet = new JetspeedPortletProxyInstance(pd
                                    .getPortletName(), (Portlet) clazz
                                    .newInstance(),
                                    this.autoSwitchEditDefaultsModeToEditMode,
                                    this.autoSwitchConfigMode,
                                    this.customConfigModePortletUniqueName);
                        }
                        else
                        {
                            portlet = new JetspeedPortletInstance(pdName, (Portlet)clazz.newInstance());
                        }
                    }
                    finally
                    {
                        Thread.currentThread().setContextClassLoader(currentContextClassLoader);
                    }
                }
                catch (Exception e)
                {
                    String msg = "Cannot create Portlet instance " + pd.getPortletClass() + " for Portlet Application " + paName;                       
                    log.error(msg, e);
                    throw new UnavailableException(msg);
                }
               
                JetspeedPortletContext portletContext = new JetspeedPortletContextImpl(servletContext,
                                                                                       pa,
                                                                                       ContainerInfo.getInfo(),
                                                                                       portalContext.getConfiguration(),
                                                                                       rdService,
                                                                                       servletContextProvider
                                                                                       );
                JetspeedPortletConfig portletConfig = new JetspeedPortletConfigImpl(this, portletContext, pd);
               
                try
                {
                    try
                    {
                        Thread.currentThread().setContextClassLoader(paCl);
                        portlet.init(portletConfig);
                    }
                    finally
                    {
                        Thread.currentThread().setContextClassLoader(currentContextClassLoader);
                    }
                }
                catch (PortletException e1)
                {
                    log.error("Failed to initialize Portlet "+pd.getPortletClass()+" for Portlet Application "+paName, e1);
                    throw e1;
                }
               
                if (instanceCache == null)
                {
                    instanceCache = Collections.synchronizedMap(new HashMap<String, PortletInstance>());
                    this.portletCache.put(paName, instanceCache);
                }
               
                instanceCache.put(pdName, portlet);
            }
        }
        catch (PortletException pe)
        {
            throw pe;
        }
        catch (Throwable e)
        {
            log.error("PortletFactory: Failed to load portlet " + pd.getPortletClass(), e);
            throw new UnavailableException("Failed to load portlet " + pd.getPortletClass() + ": " + e.toString());
        }
       
        return portlet;
    }

    public void updatePortletConfig(PortletDefinition pd)
    {
        if (pd != null)
        {
            Map<String, PortletInstance> instanceCache = portletCache.get(pd.getApplication().getName());
            PortletInstance instance = instanceCache != null ? instanceCache.get(pd.getPortletName()) : null;
           
            if (instance != null)
            {
                JetspeedPortletConfigImpl config = (JetspeedPortletConfigImpl) instance.getConfig();
                config.setPortletDefinition(pd);
            }               
        }
    }

    public ClassLoader getPortletApplicationClassLoader(PortletApplication pa)
    {
        return pa != null ? classLoaderMap.get(pa.getName()) : null;
    }

    public boolean isPortletApplicationRegistered(PortletApplication pa)
    {
        return getPortletApplicationClassLoader(pa) != null;
    }

    public List<PortletURLGenerationListener> getPortletApplicationListeners(PortletApplication pa) throws PortletException
    {
        String paName = pa.getName();
        List<PortletURLGenerationListener> cacheListeners = this.portletListenerCache.get(paName);
       
        if (cacheListeners == null)
        {
            List<? extends Listener> paListenerList = pa.getListeners();
           
            if (paListenerList != null)
            {
                cacheListeners = new ArrayList<PortletURLGenerationListener>();
                ClassLoader paCl = getPortletApplicationClassLoader(pa);
               
                if (paCl == null)
                {
                    throw new UnavailableException("Portlet Application " + paName + " not available");
                }
               
                for (Listener listener : paListenerList)
                {
                    try
                    {
                        Class<? extends Object> clazz = paCl.loadClass(listener.getListenerClass());
                        PortletURLGenerationListener listenerInstance = (PortletURLGenerationListener) clazz.newInstance();
                        cacheListeners.add(listenerInstance);
                    }
                    catch (ClassNotFoundException e)
                    {
                        String message = "The listener class isn't found: " + listener.getListenerClass();
                        log.error(message);
                    }
                    catch (InstantiationException e)
                    {
                        String message = "The listener class instantiation fail: " + listener.getListenerClass();
                        log.error(message);
                    }
                    catch (IllegalAccessException e)
                    {
                        String message = "IllegalAccessException on the listener class: " + listener.getListenerClass();
                        log.error(message);
                    }
                }
               
                this.portletListenerCache.put(paName, cacheListeners);
            }
        }
       
        if (cacheListeners != null)
        {
            return Collections.unmodifiableList(cacheListeners);
        }
        else
        {
            return Collections.emptyList();
        }
    }
   
    public PortletFilterInstance getPortletFilterInstance(PortletApplication pa, String filterName) throws PortletException
    {
        String paName = pa.getName();
        PortletFilterInstance filterInstance = null;
       
        Map<String, PortletFilterInstance> cacheFilters = this.portletFilterCache.get(paName);
       
        if (cacheFilters != null)
        {
            filterInstance = cacheFilters.get(filterName);
        }
       
        if (filterInstance == null)
        {
            Filter filter = pa.getFilter(filterName);
           
            if (filter != null)
            {
                ClassLoader paCl = classLoaderMap.get(paName);
               
                if (paCl == null)
                {
                    throw new UnavailableException("Portlet Application " + paName + " not available");
                }
               
                try
                {
                    Class<? extends Object> clazz = paCl.loadClass(filter.getFilterClass());
                    PortletFilter portletFilter = (PortletFilter) clazz.newInstance();
                    filterInstance = new JetspeedPortletFilterInstance(filter, portletFilter);
                }
                catch (ClassNotFoundException e)
                {
                    String message = "The filter class isn't found: " + filter.getFilterClass();
                    log.error(message);
                    throw new UnavailableException(message);
                }
                catch (InstantiationException e)
                {
                    String message = "The filter class instantiation fail: " + filter.getFilterClass();
                    log.error(message);
                    throw new UnavailableException(message);
                }
                catch (IllegalAccessException e)
                {
                    String message = "IllegalAccessException on the filter class: " + filter.getFilterClass();
                    log.error(message);
                    throw new UnavailableException(message);
                }
               
                if (cacheFilters == null)
                {
                    cacheFilters = Collections.synchronizedMap(new HashMap<String, PortletFilterInstance>());
                    this.portletFilterCache.put(paName, cacheFilters);
                }

                cacheFilters.put(filterName, filterInstance);
            }
        }
       
        return filterInstance;
    }

}
TOP

Related Classes of org.apache.jetspeed.factory.JetspeedPortletFactory

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.