/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library 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 library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.metadatastore;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.teiid.adminapi.Admin;
import org.teiid.adminapi.AdminException;
import org.teiid.adminapi.AdminProcessingException;
import org.teiid.adminapi.PropertyDefinition;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.adminapi.impl.VDBMetadataParser;
import org.teiid.core.util.FileUtils;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.jdbc.TeiidDriver;
import org.teiid.metadata.MetadataRepository;
import org.teiid.runtime.EmbeddedAdminImpl;
import org.teiid.runtime.EmbeddedConfiguration;
import org.teiid.runtime.EmbeddedServer;
import org.teiid.runtime.EmbeddedServer.ConnectionFactoryProvider;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.runtime.TestEmbeddedServer;
import org.teiid.runtime.util.ConvertVDB;
import org.teiid.security.Credentials;
import org.teiid.security.GSSResult;
import org.teiid.security.SecurityHelper;
import org.teiid.translator.ExecutionFactory;
import org.teiid.translator.file.FileExecutionFactory;
@SuppressWarnings("nls")
public class TestDDLMetadataStore {
static ExtendedEmbeddedServer es;
@Before
public void setup() {
FileUtils.removeDirectoryAndChildren(new File(UnitTestUtil.getTestScratchPath()));
es = new ExtendedEmbeddedServer();
}
@After
public void teardown() {
if (es != null) {
es.stop();
}
}
static final class ExtendedEmbeddedServer extends EmbeddedServer {
@Override
public Admin getAdmin() {
return new DatasourceAwareEmbeddedAdmin(this);
}
}
private static class DatasourceAwareEmbeddedAdmin extends EmbeddedAdminImpl {
HashSet<String> datasourceNames = new HashSet<String>();
public DatasourceAwareEmbeddedAdmin(EmbeddedServer embeddedServer) {
super(embeddedServer);
}
@Override
public void createDataSource(String deploymentName, String templateName, Properties properties)
throws AdminException {
if (deploymentName.equals("z") && templateName.equals("custom")) { // custom name comes from ddl
final AtomicInteger counter = new AtomicInteger();
ConnectionFactoryProvider<AtomicInteger> cfp =
new EmbeddedServer.SimpleConnectionFactoryProvider<AtomicInteger>(counter);
es.addConnectionFactoryProvider(deploymentName, cfp);
datasourceNames.add(deploymentName);
}
}
@Override
public Collection<? extends PropertyDefinition> getTemplatePropertyDefinitions(String templateName)
throws AdminException {
return Collections.emptyList();
}
@Override
public Properties getDataSource(String deployedName) throws AdminException {
throw new AdminProcessingException(RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40137, "getDataSource")); //$NON-NLS-1$
}
@Override
public void deleteDataSource(String deployedName) throws AdminException {
if (deployedName.equals("z")) {
// TODO: no remove on method on server
datasourceNames.remove(deployedName);
}
}
@Override
public Collection<String> getDataSourceNames() throws AdminException {
return this.datasourceNames;
}
@Override
public Set<String> getDataSourceTemplateNames() throws AdminException {
HashSet<String> names = new HashSet<String>();
names.add("custom");
return names;
}
}
public static class ThreadLocalSecurityHelper implements SecurityHelper {
private static ThreadLocal<Subject> threadLocalContext = new ThreadLocal<Subject>();
@Override
public Object associateSecurityContext(Object context) {
Object previous = threadLocalContext.get();
threadLocalContext.set((Subject)context);
return previous;
}
@Override
public Object getSecurityContext() {
return threadLocalContext.get();
}
@Override
public void clearSecurityContext() {
threadLocalContext.remove();
}
@Override
public Subject getSubjectInContext(String securityDomain) {
return threadLocalContext.get();
}
@Override
public Object authenticate(String securityDomain,
String baseUserName, Credentials credentials,
String applicationName) throws LoginException {
Subject subject = new Subject();
subject.getPrincipals().add(new SimpleGroup("superuser"));
SimpleGroup rolesGroup = new SimpleGroup("Roles");
rolesGroup.addMember(new SimplePrincipal("superuser"));
rolesGroup.addMember(new SimplePrincipal("admin"));
subject.getPrincipals().add(rolesGroup);
return subject;
}
@Override
public Subject getSubjectInContext(Object context) {
return (Subject)context;
}
@Override
public GSSResult negotiateGssLogin(String securityDomain,
byte[] serviceTicket) throws LoginException {
return null;
}
}
@Test
public void testVDBExport() throws Exception {
EmbeddedConfiguration ec = new EmbeddedConfiguration();
ec.setUseDisk(false);
ec.setSecurityHelper(new ThreadLocalSecurityHelper());
es.addTranslator("y", new TestEmbeddedServer.FakeTranslator(false));
es.start(ec);
final AtomicInteger counter = new AtomicInteger();
ConnectionFactoryProvider<AtomicInteger> cfp = new EmbeddedServer.SimpleConnectionFactoryProvider<AtomicInteger>(counter);
es.addConnectionFactoryProvider("z", cfp);
es.addMetadataRepository("myrepo", Mockito.mock(MetadataRepository.class));
es.deployVDB(new FileInputStream(UnitTestUtil.getTestDataPath()+"/first-db.ddl"), true);
Admin admin = es.getAdmin();
VDBMetaData vdb = (VDBMetaData)admin.getVDB("empty", "2");
ByteArrayOutputStream out = new ByteArrayOutputStream();
VDBMetadataParser.marshell(vdb, out);
String expected = ObjectConverterUtil
.convertFileToString(new File(UnitTestUtil.getTestDataPath() + "/" + "first-vdb.xml"));
assertEquals(expected, new String(out.toByteArray()));
}
@Test
public void testRoles() throws Exception {
EmbeddedConfiguration ec = new EmbeddedConfiguration();
ec.setUseDisk(false);
ec.setSecurityHelper(new ThreadLocalSecurityHelper());
es.addTranslator("y", new TestEmbeddedServer.FakeTranslator(false));
es.addTranslator("y2", new TestEmbeddedServer.FakeTranslator(false));
final AtomicInteger counter = new AtomicInteger();
ConnectionFactoryProvider<AtomicInteger> cfp =
new EmbeddedServer.SimpleConnectionFactoryProvider<AtomicInteger>(counter);
es.addConnectionFactoryProvider("z", cfp);
es.start(ec);
es.addMetadataRepository("myrepo", Mockito.mock(MetadataRepository.class));
es.deployVDB(new FileInputStream(UnitTestUtil.getTestDataPath()+"/first-db.ddl"), true);
TeiidDriver td = es.getDriver();
Connection c = td.connect("jdbc:teiid:empty", null);
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("select * from mytable");
assertFalse(rs.next());
assertEquals("my-column", rs.getMetaData().getColumnLabel(1));
s.execute("update mytable set \"my-column\" = 'a'");
assertEquals(2, s.getUpdateCount());
try {
s.execute("delete from mytable where \"my-column\" = 'a'");
fail("should have stopped by roles");
} catch(Exception e) {
//pass
}
}
@Test
public void testConvertVDBXML() throws Exception {
EmbeddedConfiguration ec = new EmbeddedConfiguration();
ec.setUseDisk(false);
es.addTranslator("file", new FileExecutionFactory());
es.addTranslator("h2", new ExecutionFactory<>());
es.start(ec);
FileInputStream vdb = new FileInputStream(UnitTestUtil.getTestDataPath() + "/" + "portfolio-vdb.xml");
es.deployVDB(vdb);
String content = ConvertVDB.convert(new File(UnitTestUtil.getTestDataPath() + "/" + "portfolio-vdb.xml"));
es.undeployVDB("Portfolio");
/*
FileWriter fw = new FileWriter(new File(UnitTestUtil.getTestDataPath() + "/" + "portfolio-vdb.ddl"));
fw.write(content);
fw.close();
*/
String expected = ObjectConverterUtil
.convertFileToString(new File(UnitTestUtil.getTestDataPath() + "/" + "portfolio-vdb.ddl"));
assertEquals(expected, content);
//make sure the output is valid
es.deployVDB(new ByteArrayInputStream(content.getBytes("UTF-8")), true);
}
@Test
public void testMigrateVDBXML() throws Exception {
File vdb = new File(UnitTestUtil.getTestDataPath() + "/" + "portfolio-vdb.xml");
String content = ConvertVDB.convert(vdb);
/*
FileWriter fw = new FileWriter(new File(UnitTestUtil.getTestDataPath() + "/" + "portfolio-converted-vdb.ddl"));
fw.write(content);
fw.close();
*/
String expected = ObjectConverterUtil
.convertFileToString(new File(UnitTestUtil.getTestDataPath() + "/" + "portfolio-converted-vdb.ddl"));
assertEquals(expected, content);
}
@Test
public void testOverideTranslator() throws Exception {
File vdb = new File(UnitTestUtil.getTestDataPath() + "/" + "override-vdb.xml");
String content = ConvertVDB.convert(vdb);
/*
FileWriter fw = new FileWriter(new File(UnitTestUtil.getTestDataPath() + "/" + "override-vdb.ddl"));
fw.write(content);
fw.close();
*/
String expected = ObjectConverterUtil
.convertFileToString(new File(UnitTestUtil.getTestDataPath() + "/" + "override-vdb.ddl"));
assertEquals(expected, content);
}
@Test
public void testMultiSource() throws Exception {
EmbeddedConfiguration ec = new EmbeddedConfiguration();
ec.setUseDisk(false);
es.start(ec);
es.addTranslator(FileExecutionFactory.class);
es.deployVDB(new FileInputStream(UnitTestUtil.getTestDataPath() + "/" + "multisource-vdb.ddl"), true);
es.getAdmin().addSource("multisource", "1", "MarketData", "x", "file", "z");
Connection c = es.getDriver().connect("jdbc:teiid:multisource", null);
DatabaseMetaData dmd = c.getMetaData();
ResultSet rs = dmd.getProcedureColumns(null, null, "deleteFile", null);
int count = 0;
while (rs.next()) {
count++;
}
assertEquals(2, count);
}
}