/*
* 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.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
import org.teiid.adminapi.AdminProcessingException;
import org.teiid.adminapi.VDB.Status;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.ModelMetaData.Message.Severity;
import org.teiid.adminapi.impl.SourceMappingMetadata;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.core.TeiidException;
import org.teiid.dqp.internal.datamgr.ConnectorManager;
import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.runtime.RuntimePlugin;
import org.teiid.vdb.runtime.VDBKey;
public abstract class VDBStatusChecker {
private static final String JAVA_CONTEXT = "java:/"; //$NON-NLS-1$
/**
* @param translatorName
*/
public void translatorAdded(String translatorName) {
}
/**
* @param translatorName
*/
public void translatorRemoved(String translatorName) {
}
public void dataSourceAdded(String dataSourceName, VDBKey vdbKey) {
dataSourceName = stripContext(dataSourceName);
if (vdbKey == null) {
//scan all
resourceAdded(dataSourceName);
} else {
CompositeVDB cvdb = getVDBRepository().getCompositeVDB(vdbKey);
if (cvdb == null) {
return;
}
VDBMetaData vdb = cvdb.getVDB();
resourceAdded(dataSourceName, new LinkedList<Runnable>(), vdb);
}
}
public static String stripContext(String dataSourceName) {
if (dataSourceName == null) {
return null;
}
if (dataSourceName.startsWith(JAVA_CONTEXT)) {
dataSourceName = dataSourceName.substring(5);
}
return dataSourceName;
}
/**
*
* @param dataSourceName
* @param vdbKey which cannot be null
*/
public void dataSourceRemoved(String dataSourceName, VDBKey vdbKey) {
dataSourceName = stripContext(dataSourceName);
CompositeVDB cvdb = getVDBRepository().getCompositeVDB(vdbKey);
if (cvdb == null) {
return;
}
VDBMetaData vdb = cvdb.getVDB();
if (vdb.getStatus() == Status.FAILED) {
return;
}
synchronized (vdb) {
ConnectorManagerRepository cmr = vdb.getAttachment(ConnectorManagerRepository.class);
for (ModelMetaData model:vdb.getModelMetaDatas().values()) {
String sourceName = getSourceName(dataSourceName, model);
if (sourceName == null) {
continue;
}
Severity severity = Severity.WARNING;
ConnectorManager cm = cmr.getConnectorManager(sourceName);
if (cm.getExecutionFactory().isSourceRequired() && vdb.getStatus() == Status.ACTIVE) {
severity = Severity.ERROR;
}
String msg = RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40012, vdb.getName(), vdb.getVersion(), dataSourceName);
model.addRuntimeMessage(severity, msg);
LogManager.logInfo(LogConstants.CTX_RUNTIME, msg);
}
}
}
public boolean dataSourceReplaced(String vdbName, String vdbVersion,
String modelName, String sourceName, String translatorName,
String dsName) throws AdminProcessingException {
return updateSource(vdbName, vdbVersion, new SourceMappingMetadata(sourceName, translatorName, dsName), true);
}
/**
* @return true if the datasource is new to the vdb
* @throws AdminProcessingException
*/
public boolean updateSource(String vdbName, String vdbVersion, SourceMappingMetadata mapping, boolean replace) throws AdminProcessingException {
String dsName = stripContext(mapping.getConnectionJndiName());
VDBMetaData vdb = getVDBRepository().getLiveVDB(vdbName, vdbVersion);
if (vdb == null || vdb.getStatus() == Status.FAILED) {
return false;
}
synchronized (vdb) {
ConnectorManagerRepository cmr = vdb.getAttachment(ConnectorManagerRepository.class);
ConnectorManager existing = cmr.getConnectorManager(mapping.getName());
try {
cmr.createConnectorManager(vdb, cmr.getProvider(), mapping, replace);
} catch (TeiidException e) {
throw new AdminProcessingException(RuntimePlugin.Event.TEIID40033, e);
}
if (mapping.getConnectionJndiName() != null && (existing == null || !dsName.equals(existing.getConnectionName()))) {
List<Runnable> runnables = new ArrayList<Runnable>();
resourceAdded(dsName, runnables, vdb);
return true;
}
return false;
}
}
void resourceAdded(String resourceName) {
List<Runnable> runnables = new ArrayList<Runnable>();
for (CompositeVDB cvdb:getVDBRepository().getCompositeVDBs()) {
VDBMetaData vdb = cvdb.getVDB();
if (vdb.getStatus() == Status.FAILED) {
continue;
}
resourceAdded(resourceName, runnables, vdb);
}
}
private void resourceAdded(String resourceName, List<Runnable> runnables,
VDBMetaData vdb) {
synchronized (vdb) {
ConnectorManagerRepository cmr = vdb.getAttachment(ConnectorManagerRepository.class);
boolean usesResourse = false;
for (ModelMetaData model:vdb.getModelMetaDatas().values()) {
if (!model.hasRuntimeMessages()) {
continue;
}
String sourceName = getSourceName(resourceName, model);
if (sourceName == null) {
continue;
}
usesResourse = true;
ConnectorManager cm = cmr.getConnectorManager(sourceName);
checkStatus(runnables, vdb, model, cm);
}
if (usesResourse) {
updateVDB(runnables, vdb);
}
}
}
private void updateVDB(List<Runnable> runnables, VDBMetaData vdb) {
if (!runnables.isEmpty()) {
//the task themselves will set the status on completion/failure
for (Runnable runnable : runnables) {
getExecutor().execute(runnable);
}
runnables.clear();
} else if (vdb.hasErrors()) {
LogManager.logInfo(LogConstants.CTX_RUNTIME, RuntimePlugin.Util.gs(RuntimePlugin.Event.TEIID40003,vdb.getName(), vdb.getVersion(), vdb.getStatus()));
}
}
private void checkStatus(List<Runnable> runnables, VDBMetaData vdb,
ModelMetaData model, ConnectorManager cm) {
//get the pending metadata load
model.removeAttachment(VDBStatusChecker.class);
Runnable r = model.removeAttachment(Runnable.class);
if (r != null) {
runnables.add(r);
} else {
String status = cm.getStausMessage();
if (status != null && status.length() > 0) {
Severity severity = vdb.getStatus() == Status.LOADING?Severity.WARNING:Severity.ERROR;
model.addRuntimeMessage(severity, status);
LogManager.logInfo(LogConstants.CTX_RUNTIME, status);
} else if (vdb.getStatus() != Status.LOADING){
model.clearRuntimeMessages();
} else {
//mark the model to indicate that it should be reloaded if it
//is currently failing a load
model.addAttchment(VDBStatusChecker.class, this);
}
}
}
private String getSourceName(String factoryName, ModelMetaData model) {
for (SourceMappingMetadata source:model.getSources().values()) {
String jndiName = source.getConnectionJndiName();
if (jndiName == null) {
continue;
}
jndiName = stripContext(jndiName);
if (factoryName.equals(jndiName)) {
return source.getName();
}
}
return null;
}
public abstract Executor getExecutor();
public abstract VDBRepository getVDBRepository();
}