centralize the bundle identifier construction
The ready marker logic is created to hide the real usage. The ready marker uses an "identifier" that is not specific or limited to bundles. Currently the bundle symbolic name is used as bundle identifier. That "convention" needs to be known at several different places. There should be one method that created an identifier for a bundle and "no one" needs to care about the implementation details. Another point is that the bundle symbolic name that has been used is optional. It may be null e.g. for bundles that has been installed by the synthetic bundle installer mechanism etc. The runtime assigns a bundle ID to an installed bundle that remains the same for the bundle (see JavaDoc). The bundle ID is present all the time. The implementation of the "get identifier for bundle" has been choosen to use the BSN -- if available -- (as before) but fallback to a custom one using also the bundle ID (to be unique). So we can provide always a non null identifier for a bundle. It should be easily to change the identifier creation now if there is every any need for. Signed-off-by: Markus Rathgeb <maggu2810@gmail.com>pull/543/head
parent
92b71f1712
commit
fd95b86b36
|
@ -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<T> extends BundleTracker<Bundle> {
|
|||
XmlDocumentProvider<T> 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<T> extends BundleTracker<Bundle> {
|
|||
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<T> extends BundleTracker<Bundle> {
|
|||
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<T> extends BundleTracker<Bundle> {
|
|||
|
||||
@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<T> extends BundleTracker<Bundle> {
|
|||
private void parseDocuments(Bundle bundle, Collection<URL> 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<T> extends BundleTracker<Bundle> {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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() + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue