/*
* 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.deployers;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.teiid.adminapi.VDB.Status;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.client.util.ResultsFuture;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.dqp.internal.process.DQPCore;
import org.teiid.dqp.internal.process.DataTierManagerImpl;
import org.teiid.events.EventDistributor;
import org.teiid.events.EventListener;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.AbstractMetadataRecord;
import org.teiid.metadata.Column;
import org.teiid.metadata.ColumnStats;
import org.teiid.metadata.Procedure;
import org.teiid.metadata.Schema;
import org.teiid.metadata.Table;
import org.teiid.metadata.Table.TriggerEvent;
import org.teiid.metadata.TableStats;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.SourceTriggerActionPlanner.SourceEventCommand;
import org.teiid.query.optimizer.relational.RelationalPlanner;
import org.teiid.query.processor.DdlPlan;
import org.teiid.query.tempdata.GlobalTableStore;
import org.teiid.runtime.RuntimePlugin;
public abstract class EventDistributorImpl implements EventDistributor {
private Set<EventListener> listeners = Collections.newSetFromMap(new ConcurrentHashMap<EventListener, Boolean>());
public abstract VDBRepository getVdbRepository();
public abstract DQPCore getDQPCore();
public EventDistributorImpl() {
getVdbRepository().addListener(new VDBLifeCycleListener() {
@Override
public void removed(String name, CompositeVDB vdb) {
for(EventListener el:EventDistributorImpl.this.listeners) {
try {
el.vdbUndeployed(name, vdb.getVDB().getVersion());
} catch (Exception e) {
LogManager.logError(LogConstants.CTX_RUNTIME, e, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40148, "undeployed", vdb.getVDBKey())); //$NON-NLS-1$
}
}
}
@Override
public void finishedDeployment(String name, CompositeVDB vdb) {
for(EventListener el:EventDistributorImpl.this.listeners) {
try {
if (vdb.getVDB().getStatus().equals(Status.ACTIVE)) {
el.vdbLoaded(vdb.getVDB());
}
else {
el.vdbLoadFailed(vdb.getVDB());
}
} catch (Exception e) {
LogManager.logError(LogConstants.CTX_RUNTIME, e, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40148, "finished deployment", vdb.getVDBKey())); //$NON-NLS-1$
}
}
}
@Override
public void added(String name, CompositeVDB vdb) {
for(EventListener el:EventDistributorImpl.this.listeners) {
try {
el.vdbDeployed(name, vdb.getVDB().getVersion());
} catch (Exception e) {
LogManager.logError(LogConstants.CTX_RUNTIME, e, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40148, "deployed", vdb.getVDBKey())); //$NON-NLS-1$
}
}
}
@Override
public void beforeRemove(String name, CompositeVDB vdb) {
}
});
}
@Override
public void updateMatViewRow(String vdbName, int vdbVersion, String schema,
String viewName, List<?> tuple, boolean delete) {
updateMatViewRow(vdbName, String.valueOf(vdbVersion), schema, viewName, tuple, delete);
}
@Override
public void updateMatViewRow(String vdbName, String vdbVersion, String schema,
String viewName, List<?> tuple, boolean delete) {
VDBMetaData metadata = getVdbRepository().getLiveVDB(vdbName, vdbVersion);
if (metadata != null) {
GlobalTableStore gts = metadata.getAttachment(GlobalTableStore.class);
if (gts != null) {
try {
gts.updateMatViewRow((RelationalPlanner.MAT_PREFIX + schema + '.' + viewName).toUpperCase(), tuple, delete);
} catch (TeiidComponentException e) {
LogManager.logError(LogConstants.CTX_RUNTIME, e, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40013, "updateMatViewRow")); //$NON-NLS-1$
}
}
}
}
@Override
public void dataModification(String vdbName, int vdbVersion, String schema,
String... tableNames) {
dataModification(vdbName, String.valueOf(vdbVersion), schema, tableNames);
}
@Override
public void dataModification(String vdbName, String vdbVersion, String schema, String... tableNames) {
updateModified(true, vdbName, vdbVersion, schema, tableNames);
}
private void updateModified(boolean data, String vdbName, String vdbVersion, String schema,
String... objectNames) {
Schema s = getSchema(vdbName, vdbVersion, schema);
if (s == null) {
return;
}
long ts = System.currentTimeMillis();
for (String name:objectNames) {
Table table = s.getTables().get(name);
if (table == null) {
continue;
}
if (data) {
table.setLastDataModification(ts);
} else {
table.setLastModified(ts);
}
}
}
@Override
public void setColumnStats(String vdbName, int vdbVersion,
String schemaName, String tableName, String columnName,
ColumnStats stats) {
setColumnStats(vdbName, String.valueOf(vdbVersion), schemaName, tableName, columnName, stats);
}
@Override
public void setColumnStats(String vdbName, String vdbVersion,
String schemaName, String tableName, String columnName,
ColumnStats stats) {
VDBMetaData vdb = getVdbRepository().getLiveVDB(vdbName, vdbVersion);
Table t = getTable(vdbName, vdbVersion, schemaName, tableName);
if (t == null) {
return;
}
Column c = t.getColumnByName(columnName);
if (c != null) {
DdlPlan.setColumnStats(vdb, c, stats);
}
}
@Override
public void setTableStats(String vdbName, int vdbVersion,
String schemaName, String tableName, TableStats stats) {
setTableStats(vdbName, String.valueOf(vdbVersion), schemaName, tableName, stats);
}
@Override
public void setTableStats(String vdbName, String vdbVersion,
String schemaName, String tableName, TableStats stats) {
VDBMetaData vdb = getVdbRepository().getLiveVDB(vdbName, vdbVersion);
Table t = getTable(vdbName, vdbVersion, schemaName, tableName);
if (t == null) {
return;
}
DdlPlan.setTableStats(vdb, t, stats);
}
private Table getTable(String vdbName, String vdbVersion, String schemaName,
String tableName) {
Schema s = getSchema(vdbName, vdbVersion, schemaName);
if (s == null) {
return null;
}
return s.getTables().get(tableName);
}
private Schema getSchema(String vdbName, String vdbVersion, String schemaName) {
VDBMetaData vdb = getVdbRepository().getLiveVDB(vdbName, vdbVersion);
if (vdb == null) {
return null;
}
TransformationMetadata tm = vdb.getAttachment(TransformationMetadata.class);
if (tm == null) {
return null;
}
return tm.getMetadataStore().getSchemas().get(schemaName);
}
@Override
public void setInsteadOfTriggerDefinition(String vdbName, int vdbVersion,
String schema, String viewName, TriggerEvent triggerEvent,
String triggerDefinition, Boolean enabled) {
setInsteadOfTriggerDefinition(vdbName, String.valueOf(vdbVersion), schema, viewName, triggerEvent, triggerDefinition, enabled);
}
@Override
public void setInsteadOfTriggerDefinition(String vdbName, String vdbVersion,
String schema, String viewName, TriggerEvent triggerEvent,
String triggerDefinition, Boolean enabled) {
Table t = getTable(vdbName, vdbVersion, schema, viewName);
if (t == null) {
return;
}
DdlPlan.alterInsteadOfTrigger(getVdbRepository().getLiveVDB(vdbName, vdbVersion), t, triggerDefinition, enabled, triggerEvent, true);
}
@Override
public void setProcedureDefinition(String vdbName, int vdbVersion,
String schema, String procName, String definition) {
setProcedureDefinition(vdbName, String.valueOf(vdbVersion), schema, procName, definition);
}
@Override
public void setProcedureDefinition(String vdbName, String vdbVersion,String schema, String procName, String definition) {
Schema s = getSchema(vdbName, vdbVersion, schema);
if (s == null) {
return;
}
Procedure p = s.getProcedures().get(procName);
if (p == null) {
return;
}
DdlPlan.alterProcedureDefinition(getVdbRepository().getLiveVDB(vdbName, vdbVersion), p, definition, true);
}
@Override
public void setViewDefinition(String vdbName, int vdbVersion,
String schema, String viewName, String definition) {
setViewDefinition(vdbName, String.valueOf(vdbVersion), schema, viewName, definition);
}
@Override
public void setViewDefinition(String vdbName, String vdbVersion, String schema, String viewName, String definition) {
Table t = getTable(vdbName, vdbVersion, schema, viewName);
if (t == null) {
return;
}
DdlPlan.alterView(getVdbRepository().getLiveVDB(vdbName, vdbVersion), t, definition, true);
}
@Override
public void setProperty(String vdbName, int vdbVersion, String uuid,
String name, String value) {
setProperty(vdbName, String.valueOf(vdbVersion), uuid, name, value);
}
@Override
public void setProperty(String vdbName, String vdbVersion, String uuid,
String name, String value) {
VDBMetaData vdb = getVdbRepository().getLiveVDB(vdbName, vdbVersion);
if (vdb == null) {
return;
}
TransformationMetadata tm = vdb.getAttachment(TransformationMetadata.class);
if (tm == null) {
return;
}
AbstractMetadataRecord record = DataTierManagerImpl.getByUuid(tm.getMetadataStore(), uuid);
if (record != null) {
DdlPlan.setProperty(vdb, record, name, value);
}
}
@Override
public ResultsFuture<?> dataModification(String vdbName, String vdbVersion,
String schema, String tableName, Object[] oldValues, Object[] newValues,
String[] columnNames) {
VDBMetaData vdb = getVdbRepository().getLiveVDB(vdbName, vdbVersion);
if (vdb == null) {
return null;
}
TransformationMetadata tm = vdb.getAttachment(TransformationMetadata.class);
if (tm == null) {
return null;
}
//lookup, call triggers
Table t = getTable(vdbName, vdbVersion, schema, tableName);
if (t == null) {
return null;
}
//notify of just the table modification
dataModification(vdbName, vdbVersion, schema, tableName);
if (oldValues == null && newValues == null) {
return null;
}
if (!t.getTriggers().isEmpty()) {
if (columnNames != null) {
if ((oldValues != null && oldValues.length != columnNames.length)
|| (newValues != null && newValues.length != columnNames.length)) {
throw new IllegalArgumentException(RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40162));
}
} else {
if ((oldValues != null && oldValues.length != t.getColumns().size())
|| (newValues != null && newValues.length != t.getColumns().size())) {
throw new IllegalArgumentException(RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40163));
}
}
//create command
SourceEventCommand sec = new SourceEventCommand(t, oldValues, newValues, columnNames);
try {
return DQPCore.executeQuery(sec, vdb, "admin", "event-distributor", -1, getDQPCore(), new DQPCore.ResultsListener() { //$NON-NLS-1$ //$NON-NLS-2$
@Override
public void onResults(List<String> columns, List<? extends List<?>> results) throws Exception {
//no result
}
});
} catch (Throwable throwable) {
throw new TeiidRuntimeException(throwable);
}
}
return null;
}
@Override
public void register(EventListener listener) {
this.listeners.add(listener);
}
@Override
public void unregister(EventListener listener) {
this.listeners.remove(listener);
}
}