/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.extension.ui.server;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.osgi.util.NLS;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.StringConstants;
import org.teiid.designer.extension.ExtensionPlugin;
import org.teiid.designer.extension.convertor.MxdConvertor;
import org.teiid.designer.extension.definition.ModelExtensionDefinition;
import org.teiid.designer.extension.definition.ModelExtensionDefinitionParser;
import org.teiid.designer.extension.registry.ModelExtensionRegistry;
import org.teiid.designer.extension.ui.Activator;
import org.teiid.designer.extension.ui.Messages;
import org.teiid.designer.extension.ui.actions.RegistryDeploymentValidator;
import org.teiid.designer.runtime.spi.ExecutionConfigurationEvent;
import org.teiid.designer.runtime.spi.IExecutionConfigurationListener;
import org.teiid.designer.runtime.spi.ITeiidServer;
import org.teiid.designer.runtime.spi.ITeiidTranslator;
/**
*
*/
public class TeiidInstanceMedListener implements IExecutionConfigurationListener {
private static TeiidInstanceMedListener instance;
private ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
private IStatus result = null;
/**
* @return singleton instance
*/
public static TeiidInstanceMedListener getInstance() {
if(instance == null)
instance = new TeiidInstanceMedListener();
return instance;
}
private TeiidInstanceMedListener() {}
private void addStatus(final int severity, final String msg, final Exception e) {
if(result == null) {
result = new MultiStatus(Activator.PLUGIN_ID, -1, Messages.translatorExtensionConversionResult, null);
}
((MultiStatus) result).add(new Status(severity, Activator.PLUGIN_ID, -1, msg, e) );
}
private void internalRun( File medToRegister, boolean isUpdate ) throws Exception {
if (isUpdate) {
// If MED with this prefix is registered, remove it first
FileInputStream inputStream = new FileInputStream(medToRegister);
try {
ModelExtensionDefinition med = RegistryDeploymentValidator.parseMed(inputStream, false);
if (registry.isNamespacePrefixRegistered(med.getNamespacePrefix())) {
registry.removeDefinition(med.getNamespacePrefix());
}
} finally {
try {
inputStream.close();
} catch(Exception ex) {
// Do nothing
}
}
}
// Add the supplied MED
FileInputStream inputStream = new FileInputStream(medToRegister);
try {
ModelExtensionDefinition definition = registry.addDefinition(inputStream, ExtensionPlugin.getInstance().createDefaultModelObjectExtensionAssistant());
if (definition != null)
definition.markAsImported();
} finally {
try {
inputStream.close();
} catch(Exception ex) {
// Do nothing
}
}
}
private void deploy(File fileInput) throws Exception {
CoreArgCheck.isNotNull(fileInput);
// Parse file contents to get the MED. Show info dialog if parse errors.
ModelExtensionDefinition med = null;
ModelExtensionDefinitionParser parser = new ModelExtensionDefinitionParser(ExtensionPlugin.getInstance()
.getMedSchema());
FileInputStream inputStream = new FileInputStream(fileInput);
try {
med = parser.parse(inputStream, ExtensionPlugin.getInstance().createDefaultModelObjectExtensionAssistant());
} finally {
try {
inputStream.close();
} catch(Exception ex) {
// Do nothing
}
}
if (med == null || !parser.getErrors().isEmpty()) {
String name = med != null ? med.getNamespacePrefix() : Messages.teiidGeneratedMed;
StringBuffer errorMsg = new StringBuffer(NLS.bind(Messages.medFileParseErrorMsg, name));
errorMsg.append(StringConstants.NEW_LINE);
for (String err : parser.getErrors()) {
errorMsg.append(Messages.parsingError);
errorMsg.append(err);
errorMsg.append(StringConstants.NEW_LINE);
}
throw new Exception(errorMsg.toString());
}
// Continue checks on parsable MED
ModelExtensionDefinition medNSPrefixMatch = RegistryDeploymentValidator.getRegisteredMedWithNSPrefix(registry,
med.getNamespacePrefix());
ModelExtensionDefinition medNSUriMatch = RegistryDeploymentValidator.getRegisteredMedWithNSUri(registry,
med.getNamespaceUri());
boolean nsPrefixConflict = false;
boolean nsUriConflict = false;
boolean nsPrefixAndUriConflictSameMed = false;
boolean nsPrefixConflictMedBuiltIn = false;
boolean nsUriConflictMedBuiltIn = false;
if (medNSPrefixMatch != null) {
nsPrefixConflict = true;
nsPrefixConflictMedBuiltIn = medNSPrefixMatch.isBuiltIn();
}
if (medNSUriMatch != null) {
nsUriConflict = true;
nsUriConflictMedBuiltIn = medNSUriMatch.isBuiltIn();
}
if (nsPrefixConflict && nsUriConflict && medNSPrefixMatch.equals(medNSUriMatch))
nsPrefixAndUriConflictSameMed = true;
// No conflicts - add it to the registry
if (!nsPrefixConflict && !nsUriConflict) {
// Add the selected Med
internalRun(fileInput, false);
// If the NS Prefix conflicts with a Built-in, then return
} else if (nsPrefixConflictMedBuiltIn) {
// FIXME check version of med and teiid instance and register version-specific versions
return;
// If the NS URI conflicts with a Built-in, then return
} else if (nsUriConflictMedBuiltIn) {
// FIXME check version of med and teiid instance and register version-specific versions
return;
// If there is (1) just a NS Prefix Conflict or (2) NS Prefix AND URI, but they are same MED, prompt user
// whether to update
} else if (nsPrefixConflict && (!nsUriConflict || (nsUriConflict && nsPrefixAndUriConflictSameMed))) {
// Do not re-deploy the same MED
if (med.equals(medNSPrefixMatch)) {
// Already registered so return
return;
} else {
// Add the selected Med
internalRun(fileInput, true);
}
// If there is a NS URI Conflict, throw exception to that effect
} else if (nsUriConflict) {
throw new Exception(Messages.registerMedActionNamespacePrefixRegisteredDoUpdateMsg);
}
}
/**
* @param teiidInstance
*
*/
private IStatus analyseTranslators(ITeiidServer teiidInstance) {
CoreArgCheck.isNotNull(teiidInstance, "teiid instance"); //$NON-NLS-1$
FileOutputStream output = null;
result = null;
Collection<ITeiidTranslator> translators = Collections.emptyList();
try {
translators = teiidInstance.getTranslators();
} catch (Exception ex) {
addStatus(IStatus.ERROR, Messages.failureToReceiveTranslators, ex);
return result;
}
if (translators == null || translators.isEmpty()) {
// Nothing to do
return Status.OK_STATUS;
}
MxdConvertor convertor = MxdConvertor.getInstance();
for (ITeiidTranslator translator : translators) {
try {
// Create temp file to store convertor's resulting xml
File outputFile = File.createTempFile(this.getClass().getSimpleName(),
StringConstants.DOT + StringConstants.XML);
outputFile.deleteOnExit();
// Output stream for convertor
output = new FileOutputStream(outputFile);
boolean conversion = convertor.convert(translator, output);
if (!conversion)
continue;
deploy(outputFile);
} catch (Exception ex) {
addStatus(IStatus.ERROR,
NLS.bind(Messages.errorOccurredAnalysingTranslators, translator.getName(), ex.getLocalizedMessage()),
ex);
} finally {
if (output != null) {
try {
output.close();
} catch (IOException ex) {
// Ignore close failures
}
}
}
}
return result != null ? result : Status.OK_STATUS;
}
@Override
public void configurationChanged(final ExecutionConfigurationEvent event) {
switch(event.getEventType()) {
case CONNECTED:
Job job = new Job(Messages.analyseTranslatorsJob) {
@Override
protected IStatus run(IProgressMonitor monitor) {
return analyseTranslators(event.getServer());
}
};
job.setPriority(Job.LONG);
job.setSystem(true);
job.setUser(false);
job.schedule();
break;
default:
// Don't care about other event types
}
}
}