diff --git a/bundles/org.openhab.core.config.xml/src/main/java/org/eclipse/smarthome/config/xml/osgi/XmlDocumentBundleTracker.java b/bundles/org.openhab.core.config.xml/src/main/java/org/eclipse/smarthome/config/xml/osgi/XmlDocumentBundleTracker.java index 0aad3b4c9b..8934a256cc 100644 --- a/bundles/org.openhab.core.config.xml/src/main/java/org/eclipse/smarthome/config/xml/osgi/XmlDocumentBundleTracker.java +++ b/bundles/org.openhab.core.config.xml/src/main/java/org/eclipse/smarthome/config/xml/osgi/XmlDocumentBundleTracker.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import org.eclipse.smarthome.config.xml.util.XmlDocumentReader; import org.eclipse.smarthome.core.common.ThreadPoolManager; import org.eclipse.smarthome.core.service.ReadyMarker; +import org.eclipse.smarthome.core.service.ReadyMarkerUtils; import org.eclipse.smarthome.core.service.ReadyService; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; @@ -223,7 +224,8 @@ public class XmlDocumentBundleTracker extends BundleTracker { XmlDocumentProvider xmlDocumentProvider = bundleDocumentProviderMap.get(bundle); if (xmlDocumentProvider == null) { xmlDocumentProvider = xmlDocumentProviderFactory.createDocumentProvider(bundle); - logger.trace("Create an empty XmlDocumentProvider for the module '{}'.", bundle.getSymbolicName()); + logger.trace("Create an empty XmlDocumentProvider for the module '{}'.", + ReadyMarkerUtils.getIdentifier(bundle)); bundleDocumentProviderMap.put(bundle, xmlDocumentProvider); } return xmlDocumentProvider; @@ -238,10 +240,11 @@ public class XmlDocumentBundleTracker extends BundleTracker { return; } try { - logger.debug("Releasing the XmlDocumentProvider for module '{}'.", bundle.getSymbolicName()); + logger.debug("Releasing the XmlDocumentProvider for module '{}'.", ReadyMarkerUtils.getIdentifier(bundle)); xmlDocumentProvider.release(); } catch (Exception e) { - logger.error("Could not release the XmlDocumentProvider for '{}'!", bundle.getSymbolicName(), e); + logger.error("Could not release the XmlDocumentProvider for '{}'!", ReadyMarkerUtils.getIdentifier(bundle), + e); } bundleDocumentProviderMap.remove(bundle); } @@ -261,7 +264,8 @@ public class XmlDocumentBundleTracker extends BundleTracker { try { xmlDocumentProvider.addingFinished(); } catch (Exception ex) { - logger.error("Could not send adding finished event for the module '{}'!", bundle.getSymbolicName(), ex); + logger.error("Could not send adding finished event for the module '{}'!", + ReadyMarkerUtils.getIdentifier(bundle), ex); } } @@ -273,7 +277,7 @@ public class XmlDocumentBundleTracker extends BundleTracker { @Override public final synchronized void removedBundle(Bundle bundle, BundleEvent event, Bundle object) { - logger.trace("Removing the XML related objects from module '{}'...", bundle.getSymbolicName()); + logger.trace("Removing the XML related objects from module '{}'...", ReadyMarkerUtils.getIdentifier(bundle)); finishedBundles.remove(bundle); Future future = queue.remove(bundle); if (future != null) { @@ -400,7 +404,7 @@ public class XmlDocumentBundleTracker extends BundleTracker { private void parseDocuments(Bundle bundle, Collection filteredPaths) { int numberOfParsedXmlDocuments = 0; for (URL xmlDocumentURL : filteredPaths) { - String moduleName = bundle.getSymbolicName(); + String moduleName = ReadyMarkerUtils.getIdentifier(bundle); String xmlDocumentFile = xmlDocumentURL.getFile(); logger.debug("Reading the XML document '{}' in module '{}'...", xmlDocumentFile, moduleName); try { @@ -422,23 +426,19 @@ public class XmlDocumentBundleTracker extends BundleTracker { } private void registerReadyMarker(Bundle bundle) { - final String bsn = bundle.getSymbolicName(); - if (bsn != null) { - if (!bundleReadyMarkerRegistrations.containsKey(bsn)) { - ReadyMarker readyMarker = new ReadyMarker(readyMarkerKey, bsn); - readyService.markReady(readyMarker); - bundleReadyMarkerRegistrations.put(bsn, readyMarker); - } + final String identifier = ReadyMarkerUtils.getIdentifier(bundle); + if (!bundleReadyMarkerRegistrations.containsKey(identifier)) { + ReadyMarker readyMarker = new ReadyMarker(readyMarkerKey, identifier); + readyService.markReady(readyMarker); + bundleReadyMarkerRegistrations.put(identifier, readyMarker); } } private void unregisterReadyMarker(Bundle bundle) { - final String bsn = bundle.getSymbolicName(); - if (bsn != null) { - ReadyMarker readyMarker = bundleReadyMarkerRegistrations.remove(bsn); - if (readyMarker != null) { - readyService.unmarkReady(readyMarker); - } + final String identifier = ReadyMarkerUtils.getIdentifier(bundle); + ReadyMarker readyMarker = bundleReadyMarkerRegistrations.remove(identifier); + if (readyMarker != null) { + readyService.unmarkReady(readyMarker); } } diff --git a/bundles/org.openhab.core.test/src/main/java/org/eclipse/smarthome/test/SyntheticBundleInstaller.java b/bundles/org.openhab.core.test/src/main/java/org/eclipse/smarthome/test/SyntheticBundleInstaller.java index 34061dbbe4..3f38ea4bc2 100644 --- a/bundles/org.openhab.core.test/src/main/java/org/eclipse/smarthome/test/SyntheticBundleInstaller.java +++ b/bundles/org.openhab.core.test/src/main/java/org/eclipse/smarthome/test/SyntheticBundleInstaller.java @@ -36,6 +36,7 @@ import java.util.zip.ZipEntry; import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.service.ReadyMarker; +import org.eclipse.smarthome.core.service.ReadyMarkerUtils; import org.eclipse.smarthome.core.service.ReadyService; import org.junit.Assert; import org.osgi.framework.Bundle; @@ -291,17 +292,14 @@ public class SyntheticBundleInstaller { if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) { return; } - final String bsn = bundle.getSymbolicName(); - if (bsn == null) { - return; - } + final String identifier = ReadyMarkerUtils.getIdentifier(bundle); long startTime = System.nanoTime(); ServiceReference readyServiceRef = context.getServiceReference(ReadyService.class.getName()); ReadyService readyService = (ReadyService) context.getService(readyServiceRef); - ReadyMarker expected = new ReadyMarker(marker, bsn); + ReadyMarker expected = new ReadyMarker(marker, identifier); while (!readyService.isReady(expected)) { if (System.nanoTime() - startTime > TimeUnit.SECONDS.toNanos(WAIT_TIMOUT)) { - Assert.fail(MessageFormat.format("Timout waiting for marker {0} at bundle {1}", marker, bsn)); + Assert.fail(MessageFormat.format("Timout waiting for marker {0} at bundle {1}", marker, identifier)); } try { Thread.sleep(100); diff --git a/bundles/org.openhab.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerImpl.java b/bundles/org.openhab.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerImpl.java index 521b00bf16..f415ff51cb 100644 --- a/bundles/org.openhab.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerImpl.java +++ b/bundles/org.openhab.core.thing/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerImpl.java @@ -34,7 +34,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; -import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.core.ConfigDescription; import org.eclipse.smarthome.config.core.ConfigDescriptionParameter; import org.eclipse.smarthome.config.core.ConfigDescriptionRegistry; @@ -48,6 +47,7 @@ import org.eclipse.smarthome.core.common.registry.Provider; import org.eclipse.smarthome.core.events.EventPublisher; import org.eclipse.smarthome.core.service.ReadyMarker; import org.eclipse.smarthome.core.service.ReadyMarkerFilter; +import org.eclipse.smarthome.core.service.ReadyMarkerUtils; import org.eclipse.smarthome.core.service.ReadyService; import org.eclipse.smarthome.core.storage.Storage; import org.eclipse.smarthome.core.storage.StorageService; @@ -1009,10 +1009,7 @@ public class ThingManagerImpl protected synchronized void activate(ComponentContext componentContext) { readyService.registerTracker(this, new ReadyMarkerFilter().withType(XML_THING_TYPE)); for (ThingHandlerFactory factory : thingHandlerFactories) { - final String bsn = getBundleName(factory); - if (bsn != null) { - handleThingHandlerFactoryAddition(bsn); - } + handleThingHandlerFactoryAddition(getBundleIdentifier(factory)); } thingRegistry.addThingTracker(this); active = true; @@ -1023,10 +1020,7 @@ public class ThingManagerImpl logger.debug("Thing handler factory '{}' added", thingHandlerFactory.getClass().getSimpleName()); thingHandlerFactories.add(thingHandlerFactory); if (active) { - final String bsn = getBundleName(thingHandlerFactory); - if (bsn != null) { - handleThingHandlerFactoryAddition(getBundleName(thingHandlerFactory)); - } + handleThingHandlerFactoryAddition(getBundleIdentifier(thingHandlerFactory)); } } @@ -1041,20 +1035,20 @@ public class ThingManagerImpl @Override public void onReadyMarkerAdded(ReadyMarker readyMarker) { - String bsn = readyMarker.getIdentifier(); - loadedXmlThingTypes.add(bsn); - handleThingHandlerFactoryAddition(bsn); + String identifier = readyMarker.getIdentifier(); + loadedXmlThingTypes.add(identifier); + handleThingHandlerFactoryAddition(identifier); } @Override public void onReadyMarkerRemoved(ReadyMarker readyMarker) { - String bsn = readyMarker.getIdentifier(); - loadedXmlThingTypes.remove(bsn); + String identifier = readyMarker.getIdentifier(); + loadedXmlThingTypes.remove(identifier); } - private void handleThingHandlerFactoryAddition(String bsn) { + private void handleThingHandlerFactoryAddition(String bundleIdentifier) { thingHandlerFactories.stream().filter(it -> { - return bsn.equals(getBundleName(it)); + return bundleIdentifier.equals(getBundleIdentifier(it)); }).forEach(thingHandlerFactory -> { things.forEach(thing -> { if (thingHandlerFactory.supportsThingType(thing.getThingTypeUID())) { @@ -1068,22 +1062,20 @@ public class ThingManagerImpl }); } - private @Nullable String getBundleName(ThingHandlerFactory thingHandlerFactory) { - return bundleResolver.resolveBundle(thingHandlerFactory.getClass()).getSymbolicName(); + private String getBundleIdentifier(ThingHandlerFactory thingHandlerFactory) { + return ReadyMarkerUtils.getIdentifier(bundleResolver.resolveBundle(thingHandlerFactory.getClass())); } private void registerAndInitializeHandler(final Thing thing, final ThingHandlerFactory thingHandlerFactory) { if (thingHandlerFactory != null) { - final String bsn = getBundleName(thingHandlerFactory); - if (bsn != null) { - if (loadedXmlThingTypes.contains(bsn)) { - registerHandler(thing, thingHandlerFactory); - initializeHandler(thing); - } else { - logger.debug( - "Not registering a handler at this point. The thing types of bundle {} are not fully loaded yet.", - bsn); - } + final String identifier = getBundleIdentifier(thingHandlerFactory); + if (loadedXmlThingTypes.contains(identifier)) { + registerHandler(thing, thingHandlerFactory); + initializeHandler(thing); + } else { + logger.debug( + "Not registering a handler at this point. The thing types of bundle {} are not fully loaded yet.", + identifier); } } else { logger.debug("Not registering a handler at this point. No handler factory for thing '{}' found.", diff --git a/bundles/org.openhab.core/src/main/java/org/eclipse/smarthome/core/service/ReadyMarkerUtils.java b/bundles/org.openhab.core/src/main/java/org/eclipse/smarthome/core/service/ReadyMarkerUtils.java new file mode 100644 index 0000000000..3a4957c4ac --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/eclipse/smarthome/core/service/ReadyMarkerUtils.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2014,2019 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.smarthome.core.service; + +import java.util.Arrays; + +import org.osgi.framework.Bundle; + +/** + * Utilities for the ready maker usage. + * + * @author Markus Rathgeb - Initial contribution and API + */ +public class ReadyMarkerUtils { + + /** + * Gets an identifier for a bundle. + * + * @param bundle the bundle + * @return an identifier + */ + public static String getIdentifier(final Bundle bundle) { + final String bsn = bundle.getSymbolicName(); + if (bsn != null) { + return bsn; + } else { + return String.format("@bundleId@0x%x", bundle.getBundleId()); + } + } + + /** + * Provides a string to debug bundle information. + * + * @param bundle the bundle + * @return a debug string + */ + public static String debugString(final Bundle bundle) { + return "Bundle [getState()=" + bundle.getState() + ", getHeaders()=" + bundle.getHeaders() + ", getBundleId()=" + + bundle.getBundleId() + ", getLocation()=" + bundle.getLocation() + ", getRegisteredServices()=" + + Arrays.toString(bundle.getRegisteredServices()) + ", getServicesInUse()=" + + Arrays.toString(bundle.getServicesInUse()) + ", getSymbolicName()=" + bundle.getSymbolicName() + + ", getLastModified()=" + bundle.getLastModified() + ", getBundleContext()=" + + bundle.getBundleContext() + ", getVersion()=" + bundle.getVersion() + "]"; + } + +} diff --git a/itests/org.openhab.core.thing.tests/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerOSGiTest.java b/itests/org.openhab.core.thing.tests/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerOSGiTest.java index 524a97afe3..084f99e922 100644 --- a/itests/org.openhab.core.thing.tests/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerOSGiTest.java +++ b/itests/org.openhab.core.thing.tests/src/main/java/org/eclipse/smarthome/core/thing/internal/ThingManagerOSGiTest.java @@ -51,6 +51,7 @@ import org.eclipse.smarthome.core.library.items.StringItem; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.service.ReadyMarker; +import org.eclipse.smarthome.core.service.ReadyMarkerUtils; import org.eclipse.smarthome.core.service.ReadyService; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -1523,10 +1524,10 @@ public class ThingManagerOSGiTest extends JavaOSGiTest { registerService(thingHandlerFactory); + final ReadyMarker marker = new ReadyMarker(ThingManagerImpl.XML_THING_TYPE, + ReadyMarkerUtils.getIdentifier(FrameworkUtil.getBundle(this.getClass()))); waitForAssert(() -> { // wait for the XML processing to be finished, then remove the ready marker again - ReadyMarker marker = new ReadyMarker(ThingManagerImpl.XML_THING_TYPE, - FrameworkUtil.getBundle(this.getClass()).getSymbolicName()); assertThat(readyService.isReady(marker), is(true)); readyService.unmarkReady(marker); }); @@ -1542,8 +1543,7 @@ public class ThingManagerOSGiTest extends JavaOSGiTest { verify(thingHandler, never()).initialize(); assertThat(thing.getStatusInfo(), is(uninitializedNone)); - readyService.markReady(new ReadyMarker(ThingManagerImpl.XML_THING_TYPE, - FrameworkUtil.getBundle(this.getClass()).getSymbolicName())); + readyService.markReady(marker); // ThingHandler.initialize() called, thing status is INITIALIZING.NONE ThingStatusInfo initializingNone = ThingStatusInfoBuilder