/*
* 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.actions;
import static org.teiid.designer.extension.ui.UiConstants.UTIL;
import static org.teiid.designer.ui.UiConstants.Util;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.extension.ExtensionPlugin;
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.UiConstants;
import org.teiid.designer.ui.common.viewsupport.UiBusyIndicator;
/**
* RegistryDeploymentValidator - has static methods for checking whether a ModelExtensionDefinition can safely be deployed to the
* extension registry.
*/
public class RegistryDeploymentValidator {
/**
* Determine if the supplied IFile has any outstanding problem markers. If markers are found, dialogs are displayed.
*
* @param mxdFile the file containing the extension definition
* @return <code>true</code> if problems were found
*/
private static boolean checkProblemMarkers( IFile mxdFile ) {
IMarker[] markers = null;
boolean errorOccurred = false;
try {
markers = mxdFile.findMarkers(UiConstants.ExtensionIds.PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
} catch (CoreException ex) {
Util.log(ex);
errorOccurred = true;
}
// Notify user if error getting markers
if (errorOccurred) {
MessageDialog.openError(getShell(), Messages.checkMedProblemMarkersErrorTitle, Messages.checkMedProblemMarkersErrorMsg);
return true;
}
if (markers.length > 0) {
MessageDialog.openError(getShell(), Messages.checkMedProblemMarkersHasErrorsTitle,
Messages.checkMedProblemMarkersHasErrorsMsg);
return true;
}
return false;
}
/**
* Find Open Editor for the currently selected ModelExtensionDefinition
*
* @param selectedMedFile the mxd file to check
* @return the currently open editor or <code>null</code> if none open
*/
private static IEditorPart getOpenEditor( IFile selectedMedFile ) {
final IWorkbenchWindow window = Activator.getDefault().getCurrentWorkbenchWindow();
if (window != null) {
final IWorkbenchPage page = window.getActivePage();
if (page != null) {
// look through the open editors and see if there is one available for this model file.
IEditorReference[] editors = page.getEditorReferences();
for (int i = 0; i < editors.length; ++i) {
IEditorPart editor = editors[i].getEditor(false);
if (editor != null) {
IEditorInput input = editor.getEditorInput();
if (input instanceof IFileEditorInput) {
if ((selectedMedFile != null) && selectedMedFile.equals(((IFileEditorInput)input).getFile())) {
return editor;
}
}
}
}
}
}
return null;
}
/**
* Determine if the supplied File contains a valid ModelExtensionDefinition. 'valid' meaning that the file contents are parsable
* against the MED schema. If the contents are not valid, a dialog is displayed.
*
* @param mxdContents the file contents of the extension definition
* @param showInfoDialog flag indicates whether info dialog should be shown to user
* @return the ModelExtensionDefinition, null if invalid
*/
public static ModelExtensionDefinition parseMed( InputStream mxdContents,
boolean showInfoDialog ) {
ModelExtensionDefinition med = null;
try {
med = ExtensionPlugin.getInstance().parse(mxdContents);
} catch (Exception e) {
UTIL.log(Messages.medFileParseErrorMsg);
}
// Notify user if parse fails
if (med == null && showInfoDialog) {
showMedNotValidDialog();
}
return med;
}
/**
* Get the ModelExtensionDefinition with the specified NS Prefix from the registry.
*
* @param registry the extension registry
* @param nsPrefix the ModelExtensionDefinition Namespace Prefix
* @return the ModelExtensionDefinition, null if not found
*/
public static ModelExtensionDefinition getRegisteredMedWithNSPrefix( ModelExtensionRegistry registry,
String nsPrefix ) {
return registry.getDefinition(nsPrefix);
}
/**
* Get the ModelExtensionDefinition with the specified NS URI from the registry.
*
* @param registry the extension registry
* @param nsUri the ModelExtensionDefinition Namespace URI
* @return the ModelExtensionDefinition, null if not found
*/
public static ModelExtensionDefinition getRegisteredMedWithNSUri( ModelExtensionRegistry registry,
String nsUri ) {
return registry.getDefinitionWithNSUri(nsUri);
}
/**
* Show the 'MED not parsable' info dialog
*/
private static void showMedNotValidDialog() {
MessageDialog.openInformation(getShell(), Messages.registerMedActionInvalidMedTitle,
Messages.registerMedActionInvalidMedMsg);
}
/**
* Show the 'MED with same NS prefix already registered' info dialog
*/
private static void showMedNSPrefixAlreadyRegisteredDialog() {
MessageDialog.openInformation(getShell(), Messages.registerMedActionNamespacePrefixRegisteredTitle,
Messages.registerMedActionNamespacePrefixRegisteredMsg);
}
/**
* Show the 'MED with same NS prefix already registered' confirmation dialog. This will ask user if they want to update the
* registered MED.
*/
private static boolean showMedNSPrefixAlreadyRegisteredDoUpdateDialog() {
return MessageDialog.openConfirm(getShell(), Messages.registerMedActionNamespacePrefixRegisteredTitle,
Messages.registerMedActionNamespacePrefixRegisteredDoUpdateMsg);
}
/**
* Show the 'MED with same NS URI already registered' info dialog
*/
private static void showMedNSUriAlreadyRegisteredDialog() {
MessageDialog.openInformation(getShell(), Messages.registerMedActionNamespaceUriRegisteredTitle,
Messages.registerMedActionNamespaceUriRegisteredMsg);
}
/**
* Show the 'MED NSUri conflicts with Built-In' info dialog
*/
private static void showMedNSUriConflictsWBuiltInDialog() {
MessageDialog.openInformation(getShell(), Messages.registerMedActionNamespaceUriConflictsWBuiltInTitle,
Messages.registerMedActionNamespaceUriConflictsWBuiltInMsg);
}
/**
* Show the 'MED NSPrefix conflicts with Built-In' info dialog
*/
private static void showMedNSPrefixConflictsWBuiltInDialog() {
MessageDialog.openInformation(getShell(), Messages.registerMedActionNamespacePrefixConflictsWBuiltInTitle,
Messages.registerMedActionNamespacePrefixConflictsWBuiltInMsg);
}
public static void deploy( final IFile medToDeploy ) {
CoreArgCheck.isNotNull(medToDeploy, "medToDeploy is null"); //$NON-NLS-1$
// Check whether there is currently an open editor for the selected Med
IEditorPart editor = getOpenEditor(medToDeploy);
// If editor is open and dirty, ask user whether to save
if ((editor != null) && editor.isDirty()) {
if (!MessageDialog.openQuestion(getShell(), Messages.updateMedInRegistryMedDirtyTitle,
Messages.updateMedInRegistryMedDirtyMsg)) {
return;
}
editor.doSave(new NullProgressMonitor());
}
// If the file has any error markers, user is informed to fix them first
if (RegistryDeploymentValidator.checkProblemMarkers(medToDeploy)) {
return;
}
ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
InputStream fileContents = null;
try {
fileContents = medToDeploy.getContents();
} catch (CoreException e) {
UTIL.log(IStatus.ERROR, e, NLS.bind(Messages.medFileGetContentsErrorMsg, medToDeploy.getName()));
}
if (fileContents != null) {
// Parse file contents to get the MED. Show info dialog if parse errors.
ModelExtensionDefinition med = null;
try {
ModelExtensionDefinitionParser parser = new ModelExtensionDefinitionParser(ExtensionPlugin.getInstance()
.getMedSchema());
med = parser.parse(fileContents, ExtensionPlugin.getInstance().createDefaultModelObjectExtensionAssistant());
if (!parser.getErrors().isEmpty()) {
MessageDialog.openError(getShell(), Messages.registerMedActionFailedTitle,
NLS.bind(Messages.medFileParseErrorMsg, medToDeploy.getName()));
fileContents.close();
return;
}
} catch (Exception e) {
UTIL.log(e);
MessageDialog.openError(getShell(), Messages.registerMedActionFailedTitle, Messages.registerMedActionFailedMsg);
try {
fileContents.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return;
}
try {
fileContents.close();
} catch (IOException e1) {
e1.printStackTrace();
}
// Continue checks on parsable MED
if (med != null) {
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
UiBusyIndicator.showWhile(Display.getDefault(), new Runnable() {
@Override
public void run() {
internalRun(medToDeploy, false);
}
});
// If the NS Prefix conflicts with a Built-in, prompt user to fix
} else if (nsPrefixConflictMedBuiltIn) {
RegistryDeploymentValidator.showMedNSPrefixConflictsWBuiltInDialog();
// If the NS URI conflicts with a Built-in, prompt user to fix
} else if (nsUriConflictMedBuiltIn) {
RegistryDeploymentValidator.showMedNSUriConflictsWBuiltInDialog();
// 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)) {
RegistryDeploymentValidator.showMedNSPrefixAlreadyRegisteredDialog();
} else {
boolean doUpdate = RegistryDeploymentValidator.showMedNSPrefixAlreadyRegisteredDoUpdateDialog();
if (doUpdate) {
// Add the selected Med
UiBusyIndicator.showWhile(Display.getDefault(), new Runnable() {
@Override
public void run() {
internalRun(medToDeploy, true);
}
});
}
}
// If there is a NS URI Conflict, prompt user to fix it
} else if (nsUriConflict) {
RegistryDeploymentValidator.showMedNSUriAlreadyRegisteredDialog();
}
}
}
}
static void internalRun( IFile medToRegister,
boolean isUpdate ) {
boolean wasAdded = true;
try {
if (isUpdate) {
updateExtensionInRegistry(medToRegister);
} else {
addExtensionToRegistry(medToRegister);
}
} catch (Exception e) {
wasAdded = false;
UTIL.log(IStatus.ERROR, e, NLS.bind(Messages.medRegistryAddErrorMsg, medToRegister.getName()));
MessageDialog.openInformation(getShell(), Messages.registerMedActionFailedTitle, Messages.registerMedActionFailedMsg);
}
if (wasAdded) {
MessageDialog.openInformation(getShell(), Messages.registerMedActionSuccessTitle, Messages.registerMedActionSuccessMsg);
}
}
/**
* Add a ModelExtensionDefinition to the Extension Registry
*
* @param medFile the file containing the med definition
* @throws Exception throws exception if the add operation failed
*/
private static void addExtensionToRegistry( IFile medFile ) throws Exception {
ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
registry.addDefinition(medFile.getContents(), ExtensionPlugin.getInstance().createDefaultModelObjectExtensionAssistant());
}
/**
* If a MED with the same NS Prefix is already registered, it will be removed and replaced with the supplied MED
*
* @param medFile the file containing the med definition
* @throws Exception throws exception if the add operation failed
*/
private static void updateExtensionInRegistry( IFile medFile ) throws Exception {
ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry();
// If MED with this prefix is registered, remove it first
ModelExtensionDefinition med = RegistryDeploymentValidator.parseMed(medFile.getContents(), false);
if (registry.isNamespacePrefixRegistered(med.getNamespacePrefix())) {
registry.removeDefinition(med.getNamespacePrefix());
}
// Add the supplied MED
addExtensionToRegistry(medFile);
}
private static Shell getShell() {
return Activator.getDefault().getCurrentWorkbenchWindow().getShell();
}
}