All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.etlunit.feature.database.DatabaseFeatureModule Maven / Gradle / Ivy

There is a newer version: 1.6.9
Show newest version
package org.etlunit.feature.database;

import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Module;
import org.codehaus.jackson.JsonNode;
import org.etlunit.*;
import org.etlunit.feature.AbstractFeature;
import org.etlunit.feature.FeatureModule;
import org.etlunit.feature.RuntimeOption;
import org.etlunit.feature.assertion.AssertionFeatureModule;
import org.etlunit.feature.database.util.DimensionalHashMap;
import org.etlunit.feature.database.util.DimensionalMap;
import org.etlunit.feature.execute.ExecuteFeatureModule;
import org.etlunit.io.FileBuilder;
import org.etlunit.json.validator.JsonUtils;
import org.etlunit.parser.*;
import org.etlunit.util.IOUtils;

import javax.inject.Inject;
import javax.inject.Named;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;

@FeatureModule
public class DatabaseFeatureModule extends AbstractFeature
{
	private RuntimeSupport runtimeSupport;
	private DatabaseRuntimeSupport databaseRuntimeSupport;

	private static final List prerequisites = Arrays.asList("logging", "execute", "assertion", "file");
	private ExecuteFeatureModule executeFeatureModule;
	private AssertionFeatureModule assertionFeatureModule;

	private final Map implementationMap = new HashMap();
	protected final DimensionalMap initializedDbs = new DimensionalHashMap();

	private DatabaseConfiguration databaseConfiguration;
	private DatabaseClassListener classListener;
	private JDBCClientImpl jdbcClient;

	public void addDatabaseImplementation(DatabaseImplementation impl)
	{
		if (implementationMap.containsKey(impl.getImplementationId()))
		{
			throw new IllegalArgumentException("Database Implementation " + impl.getImplementationId() + " already installed");
		}

		implementationMap.put(impl.getImplementationId(), impl);
	}

	@Inject
	public void setExecuteFeature(ExecuteFeatureModule f)
	{
		executeFeatureModule = f;
	}

	@Inject
	public void setAssertionFeature(AssertionFeatureModule f)
	{
		assertionFeatureModule = f;
	}

	@Inject
	public void setRuntimeSupport(RuntimeSupport runtimeSupport)
	{
		this.runtimeSupport = runtimeSupport;
	}

	@Override
	protected Injector preCreateSub(Injector inj)
	{
		this.databaseRuntimeSupport = postCreate(new DatabaseRuntimeSupportImpl());
		jdbcClient = postCreate(new JDBCClientImpl());

		Injector childInjector = inj.createChildInjector(new Module()
		{
			public void configure(Binder binder)
			{
				binder.bind(DatabaseRuntimeSupport.class).toInstance(databaseRuntimeSupport);
				binder.bind(JDBCClient.class).toInstance(jdbcClient);
			}
		});

		return childInjector;
	}

	@Override
	public void initialize(Injector inj)
	{
		if (featureConfiguration != null)
		{
			databaseConfiguration = new DatabaseConfiguration(
				featureConfiguration,
				runtimeSupport.getProjectName(),
				runtimeSupport.getProjectVersion(),
				runtimeSupport.getProjectUser(),
				runtimeSupport.getProjectUID()
			);

			classListener = new DatabaseClassListener(this, databaseConfiguration);
			inj.injectMembers(classListener);
		}

		DbOperationsExecutor object = new DbOperationsExecutor(this);
		inj.injectMembers(object);
		executeFeatureModule.extend(object);

		DbAssertExtender object1 = new DbAssertExtender(this);
		inj.injectMembers(object1);
		assertionFeatureModule.extend(object1);
	}

	@Override
	public List getPrerequisites()
	{
		return prerequisites;
	}

	public String getFeatureName()
	{
		return "database";
	}

	@Override
	public ClassListener getListener()
	{
		return classListener;
	}

	public SQLAggregator resolveSQLRef(String ddlRef, DatabaseConnection databaseConnection, SQLAggregator.SQLLocator locator) throws IOException, TestExecutionError
	{
		String text = locator.locate(ddlRef, databaseConnection);

		SQLAggregatorImpl ddlAgg = new SQLAggregatorImpl(ddlRef, locator, databaseConnection);

		return ddlAgg;
	}

	public SQLAggregator resolveSQLRef(String text) throws IOException, TestExecutionError
	{
		SQLAggregatorImpl ddlAgg = new SQLAggregatorImpl(text);

		return ddlAgg;
	}

	public SQLAggregator resolveDDLRef(final String ddlRef, DatabaseConnection databaseConnection) throws IOException, TestExecutionError
	{
		SQLAggregatorImpl ddlAgg = new SQLAggregatorImpl(ddlRef, new SQLAggregator.SQLLocator()
		{
			public String locate(String ref, DatabaseConnection connection) throws IOException, TestExecutionError
			{
				return getDDLText(ref, connection);
			}
		}, databaseConnection);

		File output = new FileBuilder(databaseRuntimeSupport.getGeneratedSourceDirectory(databaseConnection, null)).name("GENERATED_" + ddlRef.replace('/', '_')).file();

		IOUtils.writeBufferToFile(output, new StringBuffer(ddlAgg.getText()));

		return ddlAgg;
	}

	protected String getDDLText(final String ddlRef, DatabaseConnection databaseConnection) throws IOException, TestExecutionError
	{
		// Enhance this to look at the classpath if the file isn't found
		File ddl = new FileBuilder(runtimeSupport.getFeatureSourceDirectory(databaseConnection.getImplementationId())).subdir(databaseConnection.getId()).mkdirs().name(ddlRef).file();

		String text = null;

		if (ddl.exists())
		{
			text = IOUtils.readFileToString(ddl);
		}
		else
		{
			// check for a classpath reference
			String name = databaseConnection.getImplementationId() + "/" + databaseConnection.getId() + "/" + ddlRef;
			URL ref = getClass().getClassLoader().getResource(name);

			if (ref == null)
			{
				applicationLog.info("Unable to find ddl for reference: " + name + ", trying without the connection ID");

				// try one more time, this time without the connection id
				name = databaseConnection.getImplementationId() + "/" + ddlRef;
				ref = getClass().getClassLoader().getResource(name);

				// foul
				if (ref == null)
				{
					throw new TestExecutionError("Error resolving ddl ref: " + name, DatabaseConstants.ERR_MISSSING_DDL);
				}
			}

			text = IOUtils.readURLToString(ref);
		}

		return text;
	}

	protected void updateDatabaseFlag(String mode, DatabaseConnection databaseConnection)
	{
		JsonNode configNode = databaseConnection.getDatabaseConfiguration().getJsonNode();

		File flagFile = getFlagFile(mode, databaseConnection);

		try
		{
			IOUtils.writeBufferToFile(flagFile, new StringBuffer(configNode.toString()));

			for (String script : databaseConnection.getSchemaScripts())
			{
				File ref = getDDLFlagFile(script, mode, databaseConnection);

				StringBuilder bui = new StringBuilder();

				SQLAggregator SQLAggregator = resolveDDLRef(script, databaseConnection);
				bui.append(SQLAggregator.getText());
				long crc = IOUtils.checkSumStream(new ByteArrayInputStream(bui.toString().getBytes())).getValue();

				IOUtils.writeBufferToFile(ref, new StringBuffer("{\"checksum\": " + crc + "}"));
			}
		}
		catch (Exception e)
		{
			throw new IllegalArgumentException("", e);
		}
	}

	private File getDDLFlagFile(String ref, String mode, DatabaseConnection databaseConnection)
	{
		return runtimeSupport.createGeneratedSourceFile(databaseConnection.getImplementationId(), "ddl." + ref + "." + databaseConnection.getId() + "." + mode + "." + runtimeSupport.getProjectUID() + ".chk");
	}

	private File getFlagFile(String mode, DatabaseConnection databaseConnection)
	{
		return runtimeSupport.createGeneratedSourceFile(databaseConnection.getImplementationId(), "database." + databaseConnection.getId() + "." + mode + "." + runtimeSupport.getProjectUID() + ".tag");
	}

	protected boolean databaseOutOfDate(String mode, DatabaseConnection databaseConnection)
	{
		File flagFile = getFlagFile(mode, databaseConnection);

		JsonNode configNode = databaseConnection.getDatabaseConfiguration().getJsonNode();

		try
		{
			if (flagFile.exists())
			{
				JsonNode flgNode = JsonUtils.loadJson(flagFile);

				if (flgNode.equals(configNode))
				{
					for (String script : databaseConnection.getSchemaScripts())
					{
						File ref = getDDLFlagFile(script, mode, databaseConnection);

						if (!ref.exists())
						{
							return true;
						}

						StringBuilder bui = new StringBuilder();

						SQLAggregator SQLAggregator = resolveDDLRef(script, databaseConnection);
						bui.append(SQLAggregator.getText());

						long crc = IOUtils.checkSumStream(new ByteArrayInputStream(bui.toString().getBytes())).getValue();

						JsonNode node = JsonUtils.loadJson(ref);

						if (node.get("checksum").asLong() != crc)
						{
							return true;
						}
					}

					return false;
				}
			}
		}
		catch (Exception e)
		{
			throw new IllegalArgumentException("", e);
		}

		return true;
	}

	protected void propogateProperties(ETLTestValueObjectBuilder builder, DatabaseConnection databaseConnection, String mode)
	{
		builder.key("database-name").value(databaseConnection.getDatabaseName(mode));
		builder.key("login-name").value(databaseConnection.getLoginName(mode));
		builder.key("password").value(databaseConnection.getPassword(mode));
		builder.key("server-name").value(databaseConnection.getServerName());
	}

	DatabaseImplementation getImplementation(String connectionId)
	{
		DatabaseConnection conn = databaseConfiguration.getDatabaseConnection(connectionId);

		return implementationMap.get(conn.getImplementationId());
	}

	public DatabaseConfiguration getDatabaseConfiguration()
	{
		return databaseConfiguration;
	}

	@Override
	public void dispose()
	{
		for (Map.Entry entry : implementationMap.entrySet())
		{
			entry.getValue().dispose();
		}
	}

	@Override
	protected List getSupportedFolderNamesSub()
	{
		return Arrays.asList("data", "sql");
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy