/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* 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 com.qualogy.qafe.business.resource.rdb;
import java.io.File;
import java.net.URI;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.springframework.jdbc.datasource.DataSourceUtils;
import com.qualogy.qafe.bind.core.application.ApplicationContext;
import com.qualogy.qafe.bind.core.application.Configuration;
import com.qualogy.qafe.bind.io.FileLocation;
import com.qualogy.qafe.bind.io.Reader;
import com.qualogy.qafe.bind.resource.BindResource;
import com.qualogy.qafe.bind.resource.DatasourceBindResource;
import com.qualogy.qafe.bind.resource.query.Query;
import com.qualogy.qafe.bind.resource.query.QueryContainer;
import com.qualogy.qafe.business.resource.Resource;
import com.qualogy.qafe.business.resource.rdb.query.enhancer.EnhancementManager;
import com.qualogy.qafe.business.resource.rdb.statement.dialect.Dialect;
import com.qualogy.qafe.business.transaction.SupportsLocalTransactions;
public abstract class RDBDatasource extends Resource implements SupportsLocalTransactions {
private static final Logger LOG = Logger.getLogger(RDBDatasource.class.getName());
private Dialect dialect;
private DataSource dataSource;
/**
* Holder for {@link Query}. The {@link Query} are read and bound from a file and contained in an
* {@link QueryContainer}.
*/
private QueryContainer queryContainer;
public QueryContainer getQueryContainer() {
return queryContainer;
}
public void setQueryContainer(QueryContainer queryContainer) {
this.queryContainer = queryContainer;
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public DatasourceBindResource getResource() {
return (DatasourceBindResource) super.get();
}
public RDBDatasource(BindResource resource) {
super(resource);
}
public boolean isEqualTo(Resource otherResource) {
return false;
}
public void init() {
setDialect(((DatasourceBindResource) getBindResource()).getDialect());
}
public String toLogString() {
return ToStringBuilder.reflectionToString(dataSource);
}
public Query get(String queryName) {
return (Query) queryContainer.get(queryName);
}
public void put(Query query) {
queryContainer.put(query);
}
public Dialect getDialect() {
return dialect;
}
public void setDialect(String dialect) {
this.dialect = Dialect.create(dialect);
}
/**
* @deprecated move to dialect
* @param namedParametersSupported
*/
public void setNamedParametersSupported(boolean namedParametersSupported) {
if (dialect != null)
this.dialect.setNamedParametersSupported(namedParametersSupported);
}
public void destroy(ApplicationContext context) {
if (dataSource != null) {
try {
DataSourceUtils.releaseConnection(dataSource.getConnection(), dataSource);
} catch (SQLException e) {
LOG.log(Level.WARNING, "Problem releasing db connection", e);
}
// if (!dataSource.getConnection().isClosed()){
// // You call close() on the Connection object when you're done. Note that this doesn't really
// close the connection - it just returns it to the pool.
// dataSource.getConnection().close();
// }
}
}
private List<FileLocation> getFileLocations(final ApplicationContext context) {
final List<FileLocation> fileLocations = new ArrayList<FileLocation>();
final FileLocation stmtFileNameTemp = getResource().getStatementsFileUrl();
if (stmtFileNameTemp != null) {
if (stmtFileNameTemp.getLocation().contains(",")) {
final String[] stmtFiles = getResource().getStatementsFileUrl().getLocation().split(",");
for (final String stmtFile : stmtFiles) {
String root = stmtFileNameTemp.getRoot();
final FileLocation fileLocation;
if (root == null && stmtFile.startsWith(FileLocation.SCHEME_FILE)) {
fileLocation = new FileLocation(stmtFile);
} else {
root = context.getRoot();
fileLocation = new FileLocation(StringUtils.trim(root), StringUtils.trim(stmtFile));
}
fileLocations.add(fileLocation);
}
} else {
fileLocations.add(getResource().getStatementsFileUrl());
}
}
return fileLocations;
}
private URI fileLocationToURI(final ApplicationContext context, final FileLocation stmtFileName) {
URI uri = null;
final String stmtFileLocation = stmtFileName.getLocation();
if ((stmtFileLocation.startsWith(FileLocation.SCHEME_HTTP + FileLocation.COMMON_SCHEME_DELIM))
|| (stmtFileLocation.startsWith(FileLocation.SCHEME_FILE))) {
uri = stmtFileName.toURI();
} else {
LOG.info(" Statement [" + stmtFileName
+ "] file could not be found. Now iterating the filelocations in the applicationmapping");
final List<FileLocation> list = context.getMappingFileLocations();
if (list != null) {
for (FileLocation fileLocation : list) {
LOG.info("Trying Statement ["
+ fileLocation.getLocation()
+ File.separator
+ stmtFileName
+ "] file could not be found. Now iterating the filelocations in the applicationmapping");
final String baseLocation;
if (FilenameUtils.indexOfExtension(fileLocation.getLocation()) == -1) {
baseLocation = fileLocation.getLocation();
} else {
baseLocation = FilenameUtils.getPath(fileLocation.getLocation());
}
final FileLocation fileLoc =
new FileLocation(context.getRoot(), baseLocation + File.separator
+ stmtFileName.getLocation());
uri = fileLoc.toURI();
if (uri != null) {
break;
}
}
} else {
uri = stmtFileName.toURI();
}
}
return uri;
}
final void postInit(final ApplicationContext context) {
QueryContainer container = null;
final boolean validating =
Boolean.valueOf(context.getConfigurationItem(Configuration.QAFE_XML_VALIDATION)).booleanValue();
for (final FileLocation stmtFileName : getFileLocations(context)) {
if (stmtFileName == null) {
throw new IllegalArgumentException("DBSTATEMENTS_FILE_URL property not set");
}
final URI uri = fileLocationToURI(context, stmtFileName);
LOG.info("loading from [" + ((uri != null) ? uri.toString() : "<empty URI>") + "]");
if (uri == null) {
throw new IllegalArgumentException("DBSTATEMENTS_FILE_URL statements not found "
+ stmtFileName.getLocation());
}
if (container == null) {
container = (QueryContainer) new Reader(QueryContainer.class, validating).read(uri);
} else {
final QueryContainer containerTemp =
(QueryContainer) new Reader(QueryContainer.class, validating).read(uri);
final Collection<Query> queries = containerTemp.values();
for (Query query : queries) {
container.put(query);
}
}
}
container = EnhancementManager.enhance(container, this);
setQueryContainer(container);
validate();
}
}