/**
* Copyright © 2001 The JA-SIG Collaborative. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the JA-SIG Collaborative
* (http://www.jasig.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE JA-SIG COLLABORATIVE "AS IS" AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JA-SIG COLLABORATIVE OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package org.jasig.portal;
import java.util.Map;
import org.jasig.portal.car.CarResources;
import org.jasig.portal.layout.IUserLayoutChannelDescription;
import org.jasig.portal.layout.IUserLayoutManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* A factory class that produces IChannel
instances.
*
* @author Peter Kharchenko
* @version $Revision: 1.16 $
*/
public class ChannelFactory {
private static final Log log = LogFactory.getLog(ChannelFactory.class);
public static final int CHANNEL_MANAGER_ID = PropertiesManager.getPropertyAsInt("org.jasig.portal.ChannelFactory.channel_manager_id");
// table of multithreaded channels
public static final java.util.Hashtable staticChannels=new java.util.Hashtable();
// create a CAR class loader object for loading channel classes from CARs
// Note that the current class loader is passed as the parent and is
// searched before CARs are. So if a class exists in the VM classpath
// _and_ in a CAR the one on the classpath will be found first.
private static ClassLoader classLoader = CarResources.getInstance()
.getClassLoader();
/**
* Instantiate a channel from information supplied by the user layout manager.
*
* @param channelSubscribeId a String
value
* @param ulm an IUserLayoutManager
value
* @param sessionId a String
HTTP session Id value
* @return an IChannel
instance
* @exception PortalException if an error occurs
*/
public static IChannel instantiateLayoutChannel(String channelSubscribeId, IUserLayoutManager ulm, String sessionId) throws PortalException {
// get channel information from the user layout manager
IUserLayoutChannelDescription channel=(IUserLayoutChannelDescription) ulm.getNode(channelSubscribeId);
if(channel!=null) {
String className=channel.getClassName();
String channelPublishId=channel.getChannelPublishId();
long timeOut=channel.getTimeout();
try {
return instantiateChannel(channelSubscribeId,channelPublishId, className,timeOut,channel.getParameterMap(),sessionId);
} catch (Exception ex) {
log.error("ChannelManager::instantiateChannel() : unable to instantiate channel class \""+className+"\". "+ex);
return null;
}
} else return null;
}
/**
* Construct channel instance based on a channel description object.
*
* @param description an IUserLayoutChannelDescription
value
* @param sessionId a String
HTTP session Id value
* @return an IChannel
value
*/
public static IChannel instantiateLayoutChannel(IUserLayoutChannelDescription description, String sessionId) throws PortalException {
return instantiateChannel(description.getChannelSubscribeId(),description.getChannelPublishId(), description.getClassName(),description.getTimeout(),description.getParameterMap(),sessionId);
}
private static IChannel instantiateChannel(String channelSubscribeId, String channelPublishId, String className, long timeOut, Map params, String sessionId) throws PortalException {
String uid = sessionId + "/" + channelSubscribeId;
return instantiateChannel(className, uid);
}
/**
* Produce an IChannel based on a java class name. If the java class
* specified implements a channel interface other than
* org.jasig.portal.IChannel
, it will be wrapped by an
* appropriate adapter class that does implement IChannel.
* @param className the channel's java class name
* @param uid a unique ID for use with multithreaded channels
* @return an IChannel
object
*/
public static IChannel instantiateChannel(String className, String uid) throws PortalException {
IChannel ch = null;
boolean exists = false;
// Avoid instantiating a multithreaded channel more than once
// by storing it in a staticChannels table.
Object cobj = staticChannels.get(className);
if (cobj != null) {
exists = true;
} else {
Class channelClass = null;
try {
// Load the class using the CAR class loader which uses
// the default class loader before looking into the CARs
channelClass = classLoader.loadClass(className);
} catch (Exception e) {
throw new PortalException("Unable to load class '" + className + "'", e);
}
try {
cobj = channelClass.newInstance();
} catch (Throwable t) {
throw new PortalException("Unable to instantiate class '" + className + "'", new Exception(t.getMessage()));
}
}
// determine what kind of a channel it is.
// (perhaps, later this all could be moved to JNDI factories, so everything would be transparent)
if (cobj instanceof IMultithreadedCharacterChannel) {
if (cobj instanceof IMultithreadedCacheable) {
if (cobj instanceof IMultithreadedPrivileged) {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedPrivilegedCacheableMimeResponseCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
} else if (cobj instanceof IMultithreadedDirectResponse) {
// cacheable, privileged and direct response
ch = new MultithreadedPrivilegedCacheableDirectResponseCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
} else {
// both cacheable and privileged
ch = new MultithreadedPrivilegedCacheableCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
}
} else {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedCacheableMimeResponseCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
} else {
// just cacheable
ch = new MultithreadedCacheableCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
}
}
} else if (cobj instanceof IMultithreadedPrivileged) {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedPrivilegedMimeResponseCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
} else {
ch = new MultithreadedPrivilegedCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
}
} else {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedMimeResponseCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
} else {
// plain multithreaded
ch = new MultithreadedCharacterChannelAdapter((IMultithreadedCharacterChannel)cobj, uid);
}
}
// see if we need to add the instance to the staticChannels
if (!exists) {
staticChannels.put(className, cobj);
}
} else if (cobj instanceof IMultithreadedChannel) {
if (cobj instanceof IMultithreadedCacheable) {
if (cobj instanceof IMultithreadedPrivileged) {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedPrivilegedCacheableMimeResponseChannelAdapter((IMultithreadedChannel)cobj, uid);
} else {
// both cacheable and privileged
ch = new MultithreadedPrivilegedCacheableChannelAdapter((IMultithreadedChannel)cobj, uid);
}
} else {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedCacheableMimeResponseChannelAdapter((IMultithreadedChannel)cobj, uid);
} else {
// just cacheable
ch = new MultithreadedCacheableChannelAdapter((IMultithreadedChannel)cobj, uid);
}
}
} else if (cobj instanceof IMultithreadedPrivileged) {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedPrivilegedMimeResponseChannelAdapter((IMultithreadedChannel)cobj, uid);
} else {
ch = new MultithreadedPrivilegedChannelAdapter((IMultithreadedChannel)cobj, uid);
}
} else {
if (cobj instanceof IMultithreadedMimeResponse) {
ch = new MultithreadedMimeResponseChannelAdapter((IMultithreadedChannel)cobj, uid);
} else {
// plain multithreaded
ch = new MultithreadedChannelAdapter((IMultithreadedChannel)cobj, uid);
}
}
// see if we need to add the instance to the staticChannels
if (!exists) {
staticChannels.put(className, cobj);
}
} else {
// vanilla IChannel
ch = (IChannel)cobj;
}
return ch;
}
}