Bug 571866 - Add possibility to register fragments and processors via DS
Change-Id: If7e0800558122d0a9144cb4484353f2626689d7b
Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.ui/+/179582
Tested-by: Platform Bot <platform-bot@eclipse.org>
Reviewed-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
index 3c5f0ce..0059180 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
@@ -165,7 +165,7 @@
E4XMIResource applicationResource = (E4XMIResource) ((EObject) application).eResource();
ResourceSet resourceSet = applicationResource.getResourceSet();
if (attrURI == null) {
- log(LogLevel.WARN, "Unable to find location for the model extension \"{0}\"", bundleName); //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to find location for the model extension {}", bundleName); //$NON-NLS-1$
return;
}
@@ -179,7 +179,7 @@
uri = URI.createPlatformPluginURI(path, false);
}
} catch (RuntimeException e) {
- log(LogLevel.WARN, "Invalid location \"{0}\" of model extension \"\"", attrURI, bundleName, //$NON-NLS-1$
+ log(LogLevel.WARN, "Invalid location {} of model extension {}", attrURI, bundleName, //$NON-NLS-1$
e);
return;
}
@@ -188,7 +188,7 @@
Resource resource = resourceSet.getResource(uri, true);
resource.unload();
} catch (RuntimeException e) {
- log(LogLevel.WARN, "Unable to read model extension from \"{0}\" of \"{1}\"", uri, //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to read model extension from {} of {}", uri, //$NON-NLS-1$
bundleName);
}
}
@@ -276,7 +276,7 @@
try {
ContextInjectionFactory.invoke(service, PreDestroy.class, context);
} catch (Exception e) {
- log(LogLevel.WARN, "Could not run PreDestroy on processor {0}: {1}", contrib.getClass().getName(), //$NON-NLS-1$
+ log(LogLevel.WARN, "Could not run PreDestroy on processor {}: {}", contrib.getClass().getName(), //$NON-NLS-1$
e);
}
});
@@ -389,7 +389,7 @@
// check if the value for apply is valid
if (!ALWAYS.equals(apply) && !INITIAL.equals(apply) && !NOTEXISTS.equals(apply)) {
- log(LogLevel.WARN, "Model-Fragment header apply attribute \"{0}\" is invalid, falling back to always", //$NON-NLS-1$
+ log(LogLevel.WARN, "Model-Fragment header apply attribute {} is invalid, falling back to always", //$NON-NLS-1$
apply);
apply = ALWAYS;
}
@@ -405,7 +405,7 @@
}
}
} else {
- log(LogLevel.ERROR, "Model-Fragment header value \"{0}\" in bundle \\\"{1}\\\" is invalid", //$NON-NLS-1$
+ log(LogLevel.ERROR, "Model-Fragment header value {} in bundle {} is invalid", //$NON-NLS-1$
fragmentHeader, bundle.getSymbolicName());
}
@@ -515,7 +515,7 @@
int severity = validationResult.getSeverity();
if (severity == Diagnostic.ERROR) {
log(LogLevel.ERROR,
- "Fragment from \"{0}\" of \"{1}\" could not be validated and was not merged: " //$NON-NLS-1$
+ "Fragment from {} of {} could not be validated and was not merged: " //$NON-NLS-1$
+ fragment, contributorURI, contributorName);
}
@@ -524,7 +524,7 @@
evalImports = true;
addedElements.addAll(merged);
} else {
- log(LogLevel.DEBUG, "Nothing to merge for fragment \"{0}\" of \"{1}\"", contributorURI, //$NON-NLS-1$
+ log(LogLevel.DEBUG, "Nothing to merge for fragment {} of {}", contributorURI, //$NON-NLS-1$
contributorName);
}
if (evalImports && fragmentsContainer.getImports().size() > 0) {
@@ -536,7 +536,7 @@
E4XMIResource applicationResource = (E4XMIResource) ((EObject) application).eResource();
ResourceSet resourceSet = applicationResource.getResourceSet();
if (attrURI == null) {
- log(LogLevel.WARN, "Unable to find location for the model extension \"{0}\"", bundleName); //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to find location for the model extension {}", bundleName); //$NON-NLS-1$
return null;
}
@@ -550,7 +550,7 @@
uri = URI.createPlatformPluginURI(path, false);
}
} catch (RuntimeException e) {
- log(LogLevel.WARN, "Invalid location \"{0}\" of model extension \"\"", attrURI, bundleName, e); //$NON-NLS-1$
+ log(LogLevel.WARN, "Invalid location {} of model extension {}", attrURI, bundleName, e); //$NON-NLS-1$
return null;
}
@@ -558,7 +558,7 @@
try {
resource = resourceSet.getResource(uri, true);
} catch (RuntimeException e) {
- log(LogLevel.WARN, "Unable to read model extension from \"{0}\" of \"{1}\"", uri, bundleName); //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to read model extension from {} of {}", uri, bundleName); //$NON-NLS-1$
return null;
}
@@ -570,7 +570,7 @@
Object extensionRoot = contents.get(0);
if (!(extensionRoot instanceof MModelFragments)) {
- log(LogLevel.WARN, "Unable to create model extension \"{0}\"", bundleName); //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to create model extension {}", bundleName); //$NON-NLS-1$
return null;
}
return (MModelFragments) extensionRoot;
@@ -670,7 +670,7 @@
// check if the value for apply is valid
if (!ALWAYS.equals(apply) && !INITIAL.equals(apply)) {
log(LogLevel.WARN,
- "IModelProcessorContribution apply property value \"{0}\" is invalid, falling back to always", //$NON-NLS-1$
+ "IModelProcessorContribution apply property value {} is invalid, falling back to always", //$NON-NLS-1$
apply);
apply = IModelProcessorContribution.APPLY_ALWAYS;
}
@@ -699,7 +699,7 @@
MApplicationElement el = ModelUtils.findElementById(application, id);
if (el == null) {
- log(LogLevel.WARN, "Could not find element with id '{0}'", id); //$NON-NLS-1$
+ log(LogLevel.WARN, "Could not find element with id {}", id); //$NON-NLS-1$
}
localContext.set(key, el);
}
@@ -708,14 +708,14 @@
Object o = factory.create("bundleclass://" + ce.getContributor().getName() + "/" + ce.getAttribute("class"), //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
context, localContext);
if (o == null) {
- log(LogLevel.WARN, "Unable to create processor {0} from {1}", //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to create processor {} from {}", //$NON-NLS-1$
ce.getAttribute("class"), //$NON-NLS-1$
ce.getContributor().getName());
} else {
ContextInjectionFactory.invoke(o, Execute.class, context, localContext, null);
}
} catch (Exception e) {
- log(LogLevel.WARN, "Could not run processor: {0}", e); //$NON-NLS-1$
+ log(LogLevel.WARN, "Could not run processor: {}", e); //$NON-NLS-1$
}
}
@@ -737,7 +737,7 @@
MApplicationElement el = ModelUtils.findElementById(application, id);
if (el == null) {
- log(LogLevel.WARN, "Could not find element with id '{0}'", id); //$NON-NLS-1$
+ log(LogLevel.WARN, "Could not find element with id {}", id); //$NON-NLS-1$
}
localContext.set(key, el);
}
@@ -750,14 +750,14 @@
o = processor;
}
if (o == null) {
- log(LogLevel.WARN, "Unable to create processor {0} from {1}", //$NON-NLS-1$
+ log(LogLevel.WARN, "Unable to create processor {} from {}", //$NON-NLS-1$
processor.getProcessorClass().getName(),
FrameworkUtil.getBundle(processor.getProcessorClass()).getSymbolicName());
} else {
ContextInjectionFactory.invoke(o, Execute.class, context, localContext, null);
}
} catch (Exception e) {
- log(LogLevel.WARN, "Could not run processor: {0}", e); //$NON-NLS-1$
+ log(LogLevel.WARN, "Could not run processor: {}", e); //$NON-NLS-1$
}
}
@@ -799,7 +799,7 @@
el = importMaps.get((MApplicationElement) importObject);
if (el == null) {
- log(LogLevel.WARN, "Could not resolve import for {0}", //$NON-NLS-1$
+ log(LogLevel.WARN, "Could not resolve import for {}", //$NON-NLS-1$
((MApplicationElement) importObject).getElementId());
}
}
@@ -812,7 +812,7 @@
commands.add(() -> {
if (internalFeature.isMany()) {
log(LogLevel.ERROR, MessageFormat.format(
- "Replacing in {0}.\n\nFeature={1}.\n\nInternalElement={2} contributed by {3}.\n\nImportObject={4}", //$NON-NLS-1$
+ "Replacing in {}.\n\nFeature={}.\n\nInternalElement={} contributed by {}.\n\nImportObject={}", //$NON-NLS-1$
interalTarget, internalFeature.getName(), internalElement.getElementId(),
internalElement.getContributorURI(), internalImportObject));
@SuppressWarnings("unchecked")
diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
index 1d78e74..19b3738 100644
--- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
+++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/workbench/ModelAssemblerTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2020 EclipseSource Muenchen GmbH and others.
+ * Copyright (c) 2016, 2021 EclipseSource Muenchen GmbH and others.
*
*
* This program and the accompanying materials
@@ -18,15 +18,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import org.eclipse.core.internal.registry.ExtensionRegistry;
import org.eclipse.core.runtime.ContributorFactorySimple;
@@ -63,13 +62,15 @@
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.equinox.log.ExtendedLogReaderService;
+import org.eclipse.equinox.log.LogFilter;
import org.eclipse.swt.widgets.Display;
+import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
-import org.mockito.ArgumentMatchers;
-import org.osgi.service.log.Logger;
-import org.osgi.service.log.LoggerFactory;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
@SuppressWarnings("nls")
public class ModelAssemblerTests {
@@ -82,9 +83,26 @@
private ResourceSetImpl resourceSet;
private E4XMIResource appResource;
private ModelAssembler assembler;
- private Logger logger;
private EModelService modelService;
+ private static final int COUNTDOWN_TIMEOUT = 10_000;
+ private ArrayDeque<String> logMessages;
+ private ModelAssemblerTestLogListener logListener;
+
+ class ModelAssemblerTestLogListener implements LogListener {
+
+ CountDownLatch countDownLatch;
+
+ @Override
+ public void logged(LogEntry entry) {
+ logMessages.add(entry.getMessage());
+ if (countDownLatch != null) {
+ countDownLatch.countDown();
+ }
+ }
+
+ }
+
@Before
public void setup() {
appContext = E4Application.createDefaultContext();
@@ -92,10 +110,6 @@
application.setElementId(APPLICATION_ID);
application.setContext(appContext);
- logger = mock(Logger.class);
- LoggerFactory logFactory = mock(LoggerFactory.class);
- when(logFactory.getLogger((Class<?>) ArgumentMatchers.any())).thenReturn(logger);
-
appContext.set(MApplication.class, application);
appContext.set(UISynchronize.class, new DisplayUISynchronize(Display.getDefault()));
@@ -105,14 +119,29 @@
resourceSet.getResources().add(appResource);
appResource.getContents().add((EObject) application);
- assembler = new ModelAssembler();
+ assembler = appContext.get(ModelAssembler.class);
+ assembler.init(application, appContext, new DisplayUISynchronize(Display.getDefault()));
ContextInjectionFactory.invoke(assembler, PostConstruct.class, appContext);
- assembler.setLogger(logFactory);
+ logMessages = new ArrayDeque<>();
+ logListener = new ModelAssemblerTestLogListener();
+
+ ExtendedLogReaderService log = appContext.get(ExtendedLogReaderService.class);
+ LogFilter logFilter = (bundle, loggerName, logLevel) -> {
+ return "org.eclipse.e4.ui.internal.workbench.ModelAssembler".equals(loggerName);
+ };
+
+ log.addLogListener(logListener, logFilter);
modelService = application.getContext().get(EModelService.class);
}
+ @After
+ public void tearDown() {
+ ExtendedLogReaderService log = appContext.get(ExtendedLogReaderService.class);
+ log.removeLogListener(logListener);
+ }
+
/**
* Test the handling of a fragment contribution with no elements to merge.
*
@@ -131,7 +160,7 @@
&& element.getContributorURI().equals(contributorURI));
assertTrue(modelElements.isEmpty());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -170,9 +199,7 @@
assertEquals(window, found);
assertEquals(fragmentParentId, found.getParent().getElementId());
- verifyZeroInteractions(logger);
-
-
+ assertEquals(0, logMessages.size());
}
@Test
@@ -214,7 +241,7 @@
MUIElement found = modelService.find(contributedElementId, application);
assertEquals(window1, found);
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -258,7 +285,7 @@
assertEquals(found, window2);
assertEquals(contributorID, found.getContributorURI());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/** Tests that correctly configured imports are correctly handled. */
@@ -284,12 +311,13 @@
assembler.resolveImports(imports, addedElements);
assertEquals(realWindow1, placeholder.getRef());
- verifyZeroInteractions(logger);
+
+ assertEquals(0, logMessages.size());
}
/** Tests the processing of an import with a null/incorrect element id. */
@Test
- public void testImports_noImportElementId() {
+ public void testImports_noImportElementId() throws Exception {
List<MApplicationElement> imports = new ArrayList<>();
List<MApplicationElement> addedElements = new ArrayList<>();
@@ -306,10 +334,17 @@
placeholder.setRef(importWindow1);
addedElements.add(placeholder);
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ this.logListener.countDownLatch = countDownLatch;
+
assembler.resolveImports(imports, addedElements);
assertEquals(null, placeholder.getRef());
- verify(logger).warn("Could not resolve import for {0}", new Object[] { null });
- verifyZeroInteractions(logger);
+
+ boolean completed = countDownLatch.await(COUNTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Timeout - no event received", completed);
+
+ assertEquals(1, logMessages.size());
+ assertEquals("Could not resolve import for null", logMessages.poll());
}
/**
@@ -356,7 +391,7 @@
// the testing was done in the post-processor; if we didn't fail there,
// everything went fine.
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -370,7 +405,7 @@
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", true, false);
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.pre", application.getDescriptors().get(0).getElementId());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -384,7 +419,7 @@
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", false, false);
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.pre", application.getDescriptors().get(0).getElementId());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -398,7 +433,7 @@
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", true, false);
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.pre", application.getDescriptors().get(0).getElementId());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -411,7 +446,7 @@
public void testPreProcessor_persistedState_initial() throws Exception {
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", false, false);
assertEquals(0, application.getDescriptors().size());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -425,7 +460,7 @@
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", false, true);
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -439,7 +474,7 @@
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_always.xml", true, true);
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -453,7 +488,7 @@
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", true, true);
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -466,7 +501,7 @@
public void testPostProcessor_persistedState_initial() throws Exception {
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", false, true);
assertEquals(0, application.getDescriptors().size());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -477,11 +512,18 @@
*/
@Test
public void testProcessor_noProcessor() throws Exception {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ this.logListener.countDownLatch = countDownLatch;
+
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processor_null.xml", true, false);
- verify(logger).warn("Unable to create processor {0} from {1}",
- new Object[] { null, "org.eclipse.e4.ui.tests" });
+ boolean completed = countDownLatch.await(COUNTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Timeout - no event received", completed);
+
+ assertEquals(1, logMessages.size());
+ assertEquals("Unable to create processor null from org.eclipse.e4.ui.tests", logMessages.poll());
+
assertEquals(0, application.getDescriptors().size());
- verifyZeroInteractions(logger);
+ assertEquals(0, logMessages.size());
}
/**
@@ -492,14 +534,21 @@
*/
@Test
public void testProcessor_processorNotFound() throws Exception {
- testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml", true, false);
- verify(logger).warn("Unable to create processor {0} from {1}",
- new Object[] { "org.eclipse.e4.ui.tests.workbench.SimplePreProcessor_NotFound",
- "org.eclipse.e4.ui.tests" });
- assertEquals(0, application.getDescriptors().size());
- verifyZeroInteractions(logger);
- }
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ this.logListener.countDownLatch = countDownLatch;
+ testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processor_wrongProcessorClass.xml", true, false);
+ boolean completed = countDownLatch.await(COUNTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Timeout - no event received", completed);
+
+ assertEquals(1, logMessages.size());
+ assertEquals(
+ "Unable to create processor org.eclipse.e4.ui.tests.workbench.SimplePreProcessor_NotFound from org.eclipse.e4.ui.tests",
+ logMessages.poll());
+
+ assertEquals(0, application.getDescriptors().size());
+ assertEquals(0, logMessages.size());
+ }
/**
* Tests a processor contribution that adds to the context an element with
@@ -510,11 +559,18 @@
*/
@Test
public void testProcessor_wrongAppId() throws Exception {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ this.logListener.countDownLatch = countDownLatch;
+
application.setElementId("newID");
testProcessor("org.eclipse.e4.ui.tests/data/ModelAssembler/processors_initial.xml", true, true);
- verify(logger).warn("Could not find element with id '{0}'",
- new Object[] { "org.eclipse.e4.ui.tests.modelassembler.app" });
- verifyZeroInteractions(logger);
+ boolean completed = countDownLatch.await(COUNTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);
+ assertTrue("Timeout - no event received", completed);
+
+ assertEquals(1, logMessages.size());
+ assertEquals("Could not find element with id org.eclipse.e4.ui.tests.modelassembler.app", logMessages.poll());
+
+ assertEquals(0, logMessages.size());
assertEquals(1, application.getDescriptors().size());
assertEquals("simpleprocessor.post", application.getDescriptors().get(0).getElementId());
}