org.teiid.spring.autoconfigure.TeiidPostProcessor Maven / Gradle / Ivy
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed 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.teiid.spring.autoconfigure;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.jdbc.XADataSourceWrapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.teiid.PreParser;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.spring.data.BaseConnectionFactory;
import org.teiid.spring.identity.SpringSecurityHelper;
import org.teiid.translator.ExecutionFactory;
/**
* {@link BeanPostProcessor} used to fire {@link TeiidInitializedEvent}s. Should
* only be registered via the inner {@link Registrar} class.
*
* Code as template taken from {@link DataSourceInitializerPostProcessor}
*/
class TeiidPostProcessor implements BeanPostProcessor, Ordered, ApplicationListener {
private static final Log logger = LogFactory.getLog(TeiidPostProcessor.class);
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Autowired
private BeanFactory beanFactory;
@Autowired
private ApplicationContext context;
@Autowired(required = false)
private XADataSourceWrapper xaWrapper;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DataSource) {
this.beanFactory.getBean("teiid", TeiidServer.class);
}
return bean;
}
@SuppressWarnings("rawtypes")
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof TeiidServer) {
// force initialization of this bean as soon as we see a TeiidServer
this.beanFactory.getBean(TeiidInitializer.class);
} else if ((bean instanceof DataSource || bean instanceof XADataSource) && !beanName.equals("dataSource")) {
TeiidServer server = this.beanFactory.getBean(TeiidServer.class);
VDBMetaData vdb = this.beanFactory.getBean(VDBMetaData.class);
DataSource ds = null;
if (bean instanceof XADataSource) {
try {
if (this.xaWrapper == null) {
throw new IllegalStateException("XA data source is configured, however no JTA "
+ "transaction manager is defined in the pom.xml as dependency to this project");
}
ds = xaWrapper.wrapDataSource((XADataSource) bean);
} catch (Exception e) {
throw new IllegalStateException(e);
}
} else {
// only add the data source to transaction adapter when source is non-xa, in xa
// case the sources
// should auto enlist themselves.
ds = (DataSource) bean;
server.getPlatformTransactionManagerAdapter().addDataSource(ds);
}
// initialize databases if any
new MultiDataSourceInitializer(ds, beanName, context).init();
server.addDataSource(vdb, beanName, ds, context);
logger.info("Datasource added to Teiid = " + beanName);
} else if (bean instanceof BaseConnectionFactory) {
TeiidServer server = this.beanFactory.getBean(TeiidServer.class);
VDBMetaData vdb = this.beanFactory.getBean(VDBMetaData.class);
server.addDataSource(vdb, beanName, bean, context);
logger.info("Non JDBC Datasource added to Teiid = " + beanName);
server.getPlatformTransactionManagerAdapter().addDataSource((BaseConnectionFactory) bean);
} else if (bean instanceof PlatformTransactionManager) {
TeiidServer server = this.beanFactory.getBean(TeiidServer.class);
server.getPlatformTransactionManagerAdapter()
.setPlatformTransactionManager((PlatformTransactionManager) bean);
} else if (bean instanceof ExecutionFactory) {
TeiidServer server = this.beanFactory.getBean(TeiidServer.class);
server.addTranslator(beanName, (ExecutionFactory)bean);
} else if (bean instanceof PreParser) {
TeiidServer server = this.beanFactory.getBean(TeiidServer.class);
server.setPreParser((PreParser)bean);
} else if (bean instanceof AuthenticationManager) {
SpringSecurityHelper springSecurityHelper = this.beanFactory.getBean(SpringSecurityHelper.class);
if (springSecurityHelper != null) {
springSecurityHelper.setAuthenticationManager((AuthenticationManager)bean);
}
}
return bean;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
boolean deploy = true;
VDBMetaData vdb = this.beanFactory.getBean(VDBMetaData.class);
TeiidServer server = this.beanFactory.getBean(TeiidServer.class);
if (Boolean.valueOf(vdb.getPropertyValue(TeiidAutoConfiguration.IMPLICIT_VDB))) {
PhysicalNamingStrategy namingStrategy = this.beanFactory.getBean(PhysicalNamingStrategy.class);
deploy = server.findAndConfigureViews(vdb, event.getApplicationContext(), namingStrategy);
}
if (deploy) {
// Deploy at the end when all the data sources are configured
server.undeployVDB(TeiidConstants.VDBNAME);
server.undeployVDB(vdb.getName(), vdb.getVersion());
server.deployVDB(vdb, true, this.context);
}
}
/**
* {@link ImportBeanDefinitionRegistrar} to register the
* {@link TeiidPostProcessor} without causing early bean instantiation issues.
*/
static class Registrar implements ImportBeanDefinitionRegistrar {
private static final String BEAN_NAME = "teiidInitializerPostProcessor";
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(BEAN_NAME)) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(TeiidPostProcessor.class);
beanDefinition.setRole(BeanDefinition.ROLE_APPLICATION);
// We don't need this one to be post processed otherwise it can cause a
// cascade of bean instantiation that we would rather avoid.
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
}
}
}
}