org.jboss.jca.deployers.fungal.DsXmlDeployer Maven / Gradle / Ivy
The newest version!
/*
* IronJacamar, a Java EE Connector Architecture implementation
* Copyright 2008-2010, Red Hat Inc, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* 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.jboss.jca.deployers.fungal;
import org.jboss.jca.common.api.metadata.common.Credential;
import org.jboss.jca.common.api.metadata.ds.DataSource;
import org.jboss.jca.common.api.metadata.ds.DataSources;
import org.jboss.jca.common.api.metadata.ds.Driver;
import org.jboss.jca.common.api.metadata.ds.XaDataSource;
import org.jboss.jca.common.api.metadata.spec.ConfigProperty;
import org.jboss.jca.common.api.metadata.spec.ConnectionDefinition;
import org.jboss.jca.common.api.metadata.spec.Connector;
import org.jboss.jca.common.api.metadata.spec.ResourceAdapter;
import org.jboss.jca.common.metadata.ds.DatasourcesImpl;
import org.jboss.jca.common.metadata.ds.DsParser;
import org.jboss.jca.common.metadata.merge.Merger;
import org.jboss.jca.core.naming.ExplicitJndiStrategy;
import org.jboss.jca.core.spi.mdr.MetadataRepository;
import org.jboss.jca.core.spi.mdr.NotFoundException;
import org.jboss.jca.core.spi.naming.JndiStrategy;
import org.jboss.jca.core.spi.rar.ResourceAdapterRepository;
import org.jboss.jca.core.spi.security.SubjectFactory;
import org.jboss.jca.deployers.DeployersLogger;
import org.jboss.jca.deployers.common.AbstractDsDeployer;
import org.jboss.jca.deployers.common.CommonDeployment;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.DynamicMBean;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import jakarta.resource.spi.ManagedConnectionFactory;
import org.jboss.logging.Logger;
import com.github.fungal.api.Kernel;
import com.github.fungal.api.util.Injection;
import com.github.fungal.api.util.JMX;
import com.github.fungal.spi.deployers.Context;
import com.github.fungal.spi.deployers.DeployException;
import com.github.fungal.spi.deployers.Deployer;
import com.github.fungal.spi.deployers.Deployment;
/**
* The -ds.xml deployer for JCA/SJC
* @author Jesper Pedersen
*/
public class DsXmlDeployer extends AbstractDsDeployer implements Deployer
{
/** The logger */
private static DeployersLogger log = Logger.getMessageLogger(DeployersLogger.class, DsXmlDeployer.class.getName());
/** jdbcLocal **/
private String jdbcLocal;
/** jdbcXA **/
private String jdbcXA;
/** The kernel */
private Kernel kernel;
/** Metadata repository */
private MetadataRepository mdr;
/** ResourceAdapter repository */
private ResourceAdapterRepository resourceAdapterRepository;
/** Driver registry */
private DriverRegistry driverRegistry;
/**
* Constructor
*/
public DsXmlDeployer()
{
this.kernel = null;
this.jdbcLocal = null;
this.jdbcXA = null;
this.mdr = null;
this.resourceAdapterRepository = null;
this.driverRegistry = null;
}
/**
* Set the name for the JDBC Local resource adapter
* @param value The value
*/
public void setJDBCLocal(String value)
{
jdbcLocal = value;
}
/**
* Get the name for the JDBC Local resource adapter
* @return The value
*/
public String getJDBCLocal()
{
return jdbcLocal;
}
/**
* Set the name for the JDBC XA resource adapter
* @param value The value
*/
public void setJDBCXA(String value)
{
jdbcXA = value;
}
/**
* Get the name for the JDBC Xa resource adapter
* @return The value
*/
public String getJDBCXA()
{
return jdbcXA;
}
/**
* {@inheritDoc}
*/
protected DeployersLogger getLogger()
{
return log;
}
/**
* Set the driver registry
* @param value The value
*/
public void setDriverRegistry(DriverRegistry value)
{
driverRegistry = value;
}
/**
* {@inheritDoc}
*/
public boolean accepts(URL url)
{
if (url == null || url.toExternalForm().startsWith("jar") || !(url.toExternalForm().endsWith("-ds.xml")))
return false;
return true;
}
/**
* {@inheritDoc}
*/
public int getOrder()
{
return Constants.DSXML_DEPLOYER;
}
/**
* {@inheritDoc}
*/
public synchronized Deployment deploy(URL url, Context context, ClassLoader parent) throws DeployException
{
if (log.isDebugEnabled())
{
log.debug("Deploying: " + url.toExternalForm());
}
ClassLoader oldTCCL = SecurityActions.getThreadContextClassLoader();
InputStream is = null;
try
{
File f = getFileFromUrl(url);
if (!f.exists())
throw new IOException("Deployment " + url.toExternalForm() + " doesnt exists");
is = new FileInputStream(f);
DsParser dsParser = new DsParser();
DataSources dataSources = dsParser.parse(is);
String deploymentName = f.getName();
Set raDeployments = mdr.getResourceAdapters();
String uniqueJdbcLocalId = null;
String uniqueJdbcXAId = null;
for (String s : raDeployments)
{
if (s.endsWith(jdbcLocal))
{
URL urlJdbcLocal = new URL(s);
uniqueJdbcLocalId = urlJdbcLocal.toExternalForm();
}
else if (s.endsWith(jdbcXA))
{
URL urlJdbcXA = new URL(s);
uniqueJdbcXAId = urlJdbcXA.toExternalForm();
}
}
kernel = context.getKernel();
if (numberOfDataSources(dataSources) == 1 || verifyTypes(dataSources))
{
CommonDeployment c = createObjectsAndInjectValue(url, deploymentName,
uniqueJdbcLocalId, uniqueJdbcXAId,
dataSources, parent);
List onames = registerManagementView(c.getDataSources(),
kernel.getMBeanServer(),
kernel.getName());
return new DsXmlDeployment(c.getURL(), c.getDeploymentName(),
c.getResourceAdapter(), c.getResourceAdapterKey(),
c.getBootstrapContextIdentifier(),
resourceAdapterRepository,
c.getCfs(), c.getCfJndiNames(), c.getConnectionManagers(),
c.getRecovery(), getXAResourceRecoveryRegistry(),
c.getDataSources(), getManagementRepository(),
onames, kernel.getMBeanServer(),
c.getCl());
}
else
{
List deployments = new ArrayList();
Map driversMap = new HashMap();
for (Driver driver : dataSources.getDrivers())
{
driversMap.put(driver.getName(), driver);
}
for (DataSource ds : dataSources.getDataSource())
{
DataSources dsD = new DatasourcesImpl(Arrays.asList(ds), null, driversMap);
CommonDeployment c = createObjectsAndInjectValue(url, deploymentName,
uniqueJdbcLocalId, null,
dsD, parent);
List onames = registerManagementView(c.getDataSources(),
kernel.getMBeanServer(),
kernel.getName());
deployments.add(new DsXmlDeployment(c.getURL(), c.getDeploymentName(),
c.getResourceAdapter(), c.getResourceAdapterKey(),
c.getBootstrapContextIdentifier(),
resourceAdapterRepository,
c.getCfs(), c.getCfJndiNames(), c.getConnectionManagers(),
c.getRecovery(), getXAResourceRecoveryRegistry(),
c.getDataSources(), getManagementRepository(),
onames, kernel.getMBeanServer(),
c.getCl()));
}
for (XaDataSource xads : dataSources.getXaDataSource())
{
DataSources dsD = new DatasourcesImpl(null, Arrays.asList(xads), driversMap);
CommonDeployment c = createObjectsAndInjectValue(url, deploymentName,
null, uniqueJdbcXAId,
dsD, parent);
List onames = registerManagementView(c.getDataSources(),
kernel.getMBeanServer(),
kernel.getName());
deployments.add(new DsXmlDeployment(c.getURL(), c.getDeploymentName(),
c.getResourceAdapter(), c.getResourceAdapterKey(),
c.getBootstrapContextIdentifier(),
resourceAdapterRepository,
c.getCfs(), c.getCfJndiNames(), c.getConnectionManagers(),
c.getRecovery(), getXAResourceRecoveryRegistry(),
c.getDataSources(), getManagementRepository(),
onames, kernel.getMBeanServer(),
c.getCl()));
}
return new DsXmlDeployments(url, deployments, deployments.get(0).getClassLoader());
}
}
catch (DeployException de)
{
// Just rethrow
throw de;
}
catch (Throwable t)
{
throw new DeployException("Deployment " + url.toExternalForm() + " failed", t);
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException ioe)
{
// Ignore
}
}
cleanTemporaryFiles(url);
SecurityActions.setThreadContextClassLoader(oldTCCL);
}
}
/**
* Get File object of URL who locate xml resource
* @param url url of the archive
* @return a File object pointing of xml resource
* @throws URISyntaxException Thrown if the resource adapter cant be found
* @throws IOException Thrown if the resource adapter cant be accessible
*/
protected File getFileFromUrl(URL url) throws URISyntaxException, IOException
{
return new File(url.toURI());
}
/**
* Get IronJacamar Home directory
* @return a String object
*/
protected String getIronJacamarHome()
{
return SecurityActions.getSystemProperty("iron.jacamar.home");
}
/**
* Clean all potential temporary files
* @param url url of the archive
* @throws DeployException Thrown if the resource cant be cleaned
*/
protected void cleanTemporaryFiles(URL url) throws DeployException
{
}
/**
* Initialize and inject configuration properties
* @param className The fully qualified class name
* @param configs The configuration properties
* @param cl The class loader
* @return The object
* @throws org.jboss.jca.deployers.common.DeployException Thrown if the object cant be initialized
*/
@Override
public Object initAndInject(String className, List extends ConfigProperty> configs, ClassLoader cl)
throws org.jboss.jca.deployers.common.DeployException
{
try
{
Class clz = Class.forName(className, true, cl);
Object o = clz.newInstance();
if (configs != null)
{
Injection injector = new Injection();
for (ConfigProperty cpmd : configs)
{
if (cpmd.isValueSet())
injector.inject(o, cpmd.getConfigPropertyName().getValue(),
cpmd.getConfigPropertyValue().getValue(), cpmd.getConfigPropertyType().getValue());
}
}
return o;
}
catch (Throwable t)
{
throw new org.jboss.jca.deployers.common.DeployException("Deployment " + className + " failed", t);
}
}
/**
* Bind connection factory into JNDI
* @param deployment The deployment name
* @param jndi The JNDI name
* @param cf The connection factory
* @return The JNDI names bound
* @throws Throwable thrown if an error occurs
*/
@Override
protected String[] bindConnectionFactory(String deployment, String jndi, Object cf) throws Throwable
{
JndiStrategy js = new ExplicitJndiStrategy();
String[] result = js.bindConnectionFactories(deployment, new Object[]{cf}, new String[]{jndi});
log.infof("Bound data source at: %s", jndi);
return result;
}
/**
* Get the driver
* @param driverName The name of the driver
* @param moduleId The id of the module
* @return The driver class name; or null
if not found
*/
@Override
protected String getDriver(String driverName, String moduleId)
{
String driver = driverRegistry.getDriver(driverName);
if (driver == null)
driver = driverRegistry.getDriver(moduleId);
return driver;
}
/**
* Start
*/
public void start()
{
if (transactionIntegration == null)
throw new IllegalStateException("TransactionIntegration not defined");
if (mdr == null)
throw new IllegalStateException("MetadataRepository not defined");
if (resourceAdapterRepository == null)
throw new IllegalStateException("ResourceAdapterRepository not defined");
if (jdbcLocal == null)
throw new IllegalStateException("JDBCLocal not defined");
if (jdbcXA == null)
throw new IllegalStateException("JDBCXA not defined");
if (getCachedConnectionManager() == null)
throw new IllegalStateException("CachedConnectionManager not defined");
}
@Override
protected ClassLoader getDeploymentClassLoader(String uniqueId)
{
try
{
URL urlJdbc = new URL(uniqueId);
List deployments = kernel.getDeployments(urlJdbc);
Deployment deployment = null;
if (deployments != null && deployments.size() > 0)
{
for (int i = 0; deployment == null && i < deployments.size(); i++)
{
deployment = deployments.get(i);
}
return deployment.getClassLoader();
}
}
catch (Throwable t)
{
throw new RuntimeException(t.getMessage(), t);
}
throw new RuntimeException("No classloader was found for: " + uniqueId);
}
@Override
protected SubjectFactory getSubjectFactory(Credential credential, String jndiName)
throws org.jboss.jca.deployers.common.DeployException
{
log.tracef("getSubjectFactory(%s)", credential);
if (credential == null || credential.getSecurityDomain() == null ||
credential.getSecurityDomain().trim().equals(""))
return null;
try
{
return kernel.getBean(credential.getSecurityDomain(), SubjectFactory.class);
}
catch (Throwable t)
{
throw new org.jboss.jca.deployers.common.DeployException("Error during loookup of security domain: " +
credential.getSecurityDomain(), t);
}
}
/**
* Register management view of datasources in JMX
* @param mgtDses The management view of the datasources
* @param server The MBeanServer instance
* @param domain The management domain
* @return The ObjectName's generated for these datasources
* @exception JMException Thrown in case of an error
*/
private List registerManagementView(org.jboss.jca.core.api.management.DataSource[] mgtDses,
MBeanServer server, String domain)
throws JMException
{
List ons = null;
if (mgtDses != null)
{
if (server != null)
{
ons = new ArrayList();
for (org.jboss.jca.core.api.management.DataSource mgtDs : mgtDses)
{
String jndiName = mgtDs.getJndiName();
if (jndiName.indexOf("/") != -1)
jndiName = jndiName.substring(jndiName.lastIndexOf("/") + 1);
String baseName = domain + ":deployment=" + jndiName;
if (mgtDs.getPoolConfiguration() != null)
{
String dsPCName = baseName + ",type=PoolConfigutation";
DynamicMBean dsPCDMB = JMX.createMBean(mgtDs.getPoolConfiguration(), "Pool configuration");
ObjectName dsPCON = new ObjectName(dsPCName);
server.registerMBean(dsPCDMB, dsPCON);
ons.add(dsPCON);
}
if (mgtDs.getPool() != null)
{
String dsPName = baseName + ",type=Pool";
DynamicMBean dsPDMB = JMX.createMBean(mgtDs.getPool(), "Pool");
ObjectName dsPON = new ObjectName(dsPName);
server.registerMBean(dsPDMB, dsPON);
ons.add(dsPON);
if (mgtDs.getPool().getStatistics() != null)
{
String dsPSName = baseName + ",type=PoolStatistics";
Set writeAttributes = new HashSet();
writeAttributes.add("Enabled");
Set excludeAttributes = new HashSet();
Set excludeOperations = new HashSet();
excludeOperations.add("delta(.)*");
DynamicMBean dsPSDMB = JMX.createMBean(mgtDs.getPool().getStatistics(), "PoolStatistics",
writeAttributes, null,
excludeAttributes, excludeOperations);
ObjectName dsPSON = new ObjectName(dsPSName);
server.registerMBean(dsPSDMB, dsPSON);
ons.add(dsPSON);
}
}
if (mgtDs.getStatistics() != null)
{
String dsSName = baseName + ",type=Statistics";
Set writeAttributes = new HashSet();
writeAttributes.add("Enabled");
Set excludeAttributes = new HashSet();
Set excludeOperations = new HashSet();
excludeOperations.add("delta(.)*");
DynamicMBean dsSDMB = JMX.createMBean(mgtDs.getStatistics(), "Statistics",
writeAttributes, null, excludeAttributes, excludeOperations);
ObjectName dsSON = new ObjectName(dsSName);
server.registerMBean(dsSDMB, dsSON);
ons.add(dsSON);
}
}
}
}
return ons;
}
@Override
protected jakarta.resource.spi.ResourceAdapter createRa(String uniqueId, ClassLoader cl)
throws NotFoundException, Exception, DeployException
{
Connector md = mdr.getResourceAdapter(uniqueId);
ResourceAdapter ra = md.getResourceadapter();
List extends ConfigProperty> l = new ArrayList();
jakarta.resource.spi.ResourceAdapter rar =
(jakarta.resource.spi.ResourceAdapter)initAndInject(ra.getResourceadapterClass(), l, cl);
return rar;
}
@Override
protected String registerResourceAdapterToResourceAdapterRepository(jakarta.resource.spi.ResourceAdapter instance)
{
return getResourceAdapterRepository().registerResourceAdapter(instance);
}
@Override
protected ManagedConnectionFactory createMcf(XaDataSource ds, String uniqueId, ClassLoader cl)
throws NotFoundException, Exception, DeployException
{
Merger merger = new Merger();
Connector md = mdr.getResourceAdapter(uniqueId);
md = merger.mergeConnectorAndDs(ds, md);
// Get the first connection definition as there is only one
ResourceAdapter ra = md.getResourceadapter();
List cds = ra.getOutboundResourceadapter().getConnectionDefinitions();
ConnectionDefinition cd = cds.get(0);
// ManagedConnectionFactory
ManagedConnectionFactory mcf = (ManagedConnectionFactory) initAndInject(cd.getManagedConnectionFactoryClass()
.getValue(), cd.getConfigProperties(), cl);
initAndInjectClassLoaderPlugin(mcf, ds);
return mcf;
}
@Override
protected ManagedConnectionFactory createMcf(DataSource ds, String uniqueId, ClassLoader cl)
throws NotFoundException, Exception, DeployException
{
Merger merger = new Merger();
Connector md = mdr.getResourceAdapter(uniqueId);
md = merger.mergeConnectorAndDs(ds, md);
// Get the first connection definition as there is only one
ResourceAdapter ra = md.getResourceadapter();
List cds = ra.getOutboundResourceadapter().getConnectionDefinitions();
ConnectionDefinition cd = cds.get(0);
// ManagedConnectionFactory
ManagedConnectionFactory mcf = (ManagedConnectionFactory) initAndInject(cd.getManagedConnectionFactoryClass()
.getValue(), cd.getConfigProperties(), cl);
initAndInjectClassLoaderPlugin(mcf, ds);
return mcf;
}
/**
* Set the metadata repository
* @param value The value
*/
public void setMetadataRepository(MetadataRepository value)
{
mdr = value;
}
/**
* Get the metadata repository
* @return The handle
*/
public MetadataRepository getMetadataRepository()
{
return mdr;
}
/**
* Set the resource adapter repository
* @param value The value
*/
public void setResourceAdapterRepository(ResourceAdapterRepository value)
{
resourceAdapterRepository = value;
}
/**
* Get the resource adapter repository
* @return The handle
*/
public ResourceAdapterRepository getResourceAdapterRepository()
{
return resourceAdapterRepository;
}
}