/**
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.organization.idm;
import org.exoplatform.container.configuration.ConfigurationManager;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.ValueParam;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.database.HibernateService;
import org.exoplatform.services.naming.InitialContextInitializer;
import org.jboss.cache.Cache;
import org.jboss.cache.CacheFactory;
import org.jboss.cache.DefaultCacheFactory;
import org.jgroups.JChannelFactory;
import org.picketlink.idm.api.IdentitySession;
import org.picketlink.idm.api.IdentitySessionFactory;
import org.picketlink.idm.api.cfg.IdentityConfiguration;
import org.picketlink.idm.common.exception.IdentityConfigurationException;
import org.picketlink.idm.impl.cache.JBossCacheAPICacheProviderImpl;
import org.picketlink.idm.impl.cache.JBossCacheIdentityStoreCacheProviderImpl;
import org.picketlink.idm.impl.configuration.IdentityConfigurationImpl;
import org.picketlink.idm.impl.configuration.jaxb2.JAXB2IdentityConfiguration;
import org.picketlink.idm.spi.configuration.metadata.IdentityConfigurationMetaData;
import org.picocontainer.Startable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.naming.InitialContext;
/*
* @author <a href="mailto:boleslaw.dawidowicz at redhat.com">Boleslaw Dawidowicz</a>
*/
public class PicketLinkIDMServiceImpl implements PicketLinkIDMService, Startable
{
private static Log log = ExoLogger.getLogger(PicketLinkIDMServiceImpl.class);
public static final String PARAM_CONFIG_OPTION = "config";
public static final String PARAM_HIBERNATE_PROPS = "hibernate.properties";
public static final String PARAM_HIBERNATE_MAPPINGS = "hibernate.mappings";
public static final String PARAM_HIBERNATE_ANNOTATIONS = "hibernate.annotations";
public static final String PARAM_JNDI_NAME_OPTION = "jndiName";
public static final String REALM_NAME_OPTION = "portalRealm";
public static final String CACHE_CONFIG_API_OPTION = "apiCacheConfig";
public static final String CACHE_CONFIG_STORE_OPTION = "storeCacheConfig";
public static final String JGROUPS_CONFIG = "jgroups-configuration";
public static final String JGROUPS_MUX_ENABLED = "jgroups-multiplexer-stack";
public static final String CACHE_EXPIRATION = "cacheExpiration";
private IdentitySessionFactory identitySessionFactory;
private String config;
private String realmName = "idm_realm";
private IdentityConfiguration identityConfiguration;
private IntegrationCache integrationCache;
private static final JChannelFactory CHANNEL_FACTORY = new JChannelFactory();
private HibernateService hibernateService;
private PicketLinkIDMServiceImpl()
{
}
public PicketLinkIDMServiceImpl(
InitParams initParams,
HibernateService hibernateService,
ConfigurationManager confManager,
PicketLinkIDMCacheService picketLinkIDMCache,
InitialContextInitializer dependency) throws Exception
{
ValueParam config = initParams.getValueParam(PARAM_CONFIG_OPTION);
ValueParam jndiName = initParams.getValueParam(PARAM_JNDI_NAME_OPTION);
ValueParam realmName = initParams.getValueParam(REALM_NAME_OPTION);
ValueParam apiCacheConfig = initParams.getValueParam(CACHE_CONFIG_API_OPTION);
ValueParam storeCacheConfig = initParams.getValueParam(CACHE_CONFIG_STORE_OPTION);
ValueParam jgroupsStack = initParams.getValueParam(JGROUPS_MUX_ENABLED);
ValueParam jgroupsConfig = initParams.getValueParam(JGROUPS_CONFIG);
ValueParam cacheExpirationParam = initParams.getValueParam(CACHE_EXPIRATION);
this.hibernateService = hibernateService;
if (config == null && jndiName == null)
{
throw new IllegalStateException("Either '" + PARAM_CONFIG_OPTION + "' or '" + PARAM_JNDI_NAME_OPTION
+ "' parameter must " + "be specified");
}
if (realmName != null)
{
this.realmName = realmName.getValue();
}
if (config != null)
{
this.config = config.getValue();
URL configURL = confManager.getURL(this.config);
if (configURL == null)
{
throw new IllegalStateException("Cannot fine resource: " + this.config);
}
IdentityConfigurationMetaData configMD =
JAXB2IdentityConfiguration.createConfigurationMetaData(confManager.getInputStream(this.config));
identityConfiguration = new IdentityConfigurationImpl().configure(configMD);
identityConfiguration.getIdentityConfigurationRegistry().register(hibernateService.getSessionFactory(), "hibernateSessionFactory");
int expiration = -1;
if (cacheExpirationParam != null &&
cacheExpirationParam.getValue() != null &&
cacheExpirationParam.getValue().length() > 0)
{
expiration = Integer.decode(cacheExpirationParam.getValue());
}
if (apiCacheConfig != null)
{
InputStream configStream = confManager.getInputStream(apiCacheConfig.getValue());
CacheFactory factory = new DefaultCacheFactory();
if (configStream == null)
{
throw new IllegalArgumentException("JBoss Cache configuration InputStream is null");
}
Cache cache = factory.createCache(configStream);
applyJGroupsConfig(cache, confManager, jgroupsStack, jgroupsConfig);
cache.create();
cache.start();
configStream.close();
// PLIDM API cache
JBossCacheAPICacheProviderImpl apiCacheProvider = new JBossCacheAPICacheProviderImpl();
apiCacheProvider.setExpiration(expiration);
apiCacheProvider.initialize(cache);
picketLinkIDMCache.register(apiCacheProvider);
identityConfiguration.getIdentityConfigurationRegistry().register(apiCacheProvider, "apiCacheProvider");
//Integration cache
integrationCache = new IntegrationCache();
integrationCache.setExpiration(expiration);
integrationCache.initialize(cache);
picketLinkIDMCache.register(integrationCache);
}
if (storeCacheConfig != null)
{
InputStream configStream = confManager.getInputStream(storeCacheConfig.getValue());
CacheFactory factory = new DefaultCacheFactory();
if (configStream == null)
{
throw new IllegalArgumentException("JBoss Cache configuration InputStream is null");
}
Cache cache = factory.createCache(configStream);
applyJGroupsConfig(cache, confManager, jgroupsStack, jgroupsConfig);
cache.create();
cache.start();
configStream.close();
JBossCacheIdentityStoreCacheProviderImpl storeCacheProvider = new JBossCacheIdentityStoreCacheProviderImpl();
storeCacheProvider.setExpiration(expiration);
storeCacheProvider.initialize(cache);
picketLinkIDMCache.register(storeCacheProvider);
identityConfiguration.getIdentityConfigurationRegistry().register(storeCacheProvider, "storeCacheProvider");
configStream.close();
}
}
else
{
identitySessionFactory = (IdentitySessionFactory)new InitialContext().lookup(jndiName.getValue());
}
}
public void start()
{
if (identitySessionFactory == null)
{
try
{
identitySessionFactory = identityConfiguration.buildIdentitySessionFactory();
}
catch (IdentityConfigurationException e)
{
throw new RuntimeException(e);
}
}
}
public void stop()
{
}
public IdentitySessionFactory getIdentitySessionFactory()
{
return identitySessionFactory; //To change body of implemented methods use File | Settings | File Templates.
}
public IdentitySession getIdentitySession() throws Exception
{
return getIdentitySessionFactory().getCurrentIdentitySession(realmName);
}
public IdentitySession getIdentitySession(String realm) throws Exception
{
if (realm == null)
{
throw new IllegalArgumentException("Realm name cannot be null");
}
return getIdentitySessionFactory().getCurrentIdentitySession(realm);
}
public IntegrationCache getIntegrationCache()
{
return integrationCache;
}
public String getRealmName()
{
return realmName;
}
/**
* Applying JGroups configuration for JBossCache.
* Code forked from org.exoplatform.services.jcr.jbosscacheExoJBossCacheFactory
*
* @param cache
* @param configurationManager
* @param jgroupsEnabledParam
* @param jgroupsConfigurationParam
*/
private void applyJGroupsConfig(Cache cache,
ConfigurationManager configurationManager,
ValueParam jgroupsEnabledParam,
ValueParam jgroupsConfigurationParam)
{
String jgroupsEnabled = jgroupsEnabledParam != null ? jgroupsEnabledParam.getValue() : null;
String jgroupsConfiguration = jgroupsConfigurationParam != null ? jgroupsConfigurationParam.getValue() : null;
// JGroups multiplexer configuration if enabled
if (jgroupsEnabled != null && jgroupsEnabled.equalsIgnoreCase("true"))
{
try
{
if (jgroupsConfiguration != null)
{
// Create and inject multiplexer factory
CHANNEL_FACTORY.setMultiplexerConfig(configurationManager.getResource(jgroupsConfiguration));
cache.getConfiguration().getRuntimeConfig().setMuxChannelFactory(CHANNEL_FACTORY);
log.info("Multiplexer stack successfully enabled for the cache.");
}
}
catch (Exception e)
{
// exception occurred setting mux factory
throw new IllegalStateException("Error setting multiplexer configuration.", e);
}
}
else
{
// Multiplexer is not enabled. If jGroups configuration preset it is applied
if (jgroupsConfiguration != null)
{
try
{
cache.getConfiguration().setJgroupsConfigFile(
configurationManager.getResource(jgroupsConfiguration));
log.info("Custom JGroups configuration set:"
+ configurationManager.getResource(jgroupsConfiguration));
}
catch (Exception e)
{
throw new IllegalStateException("Error setting JGroups configuration.", e);
}
}
}
}
public HibernateService getHibernateService()
{
return hibernateService;
}
}