blob: 2f6c0f83226d2cba98ad5142a56b7dcb488adcc2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.osgi.internal.log.ExtendedLogServiceFactory.EquinoxLoggerContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.Version;
import org.osgi.service.log.admin.LoggerContext;
public class LoggerContextTargetMap {
private final Map<Bundle, ExtendedLogServiceImpl> logServices = new HashMap<>();
private final Map<String, EquinoxLoggerContext> loggerContexts = new HashMap<>();
private final Map<Bundle, List<String>> targetToQualifiedNames = new HashMap<>();
private final Map<String, Collection<Bundle>> qualifiedNameToTargets = new HashMap<>();
List<String> add(Bundle b) {
String bsn = b.getSymbolicName();
if (bsn == null) {
bsn = ""; //$NON-NLS-1$
}
Version v = b.getVersion();
String version = v == null ? "" : v.toString(); //$NON-NLS-1$
String location = ExtendedLogServiceFactory.secureAction.getLocation(b);
List<String> result = new ArrayList<>(3);
StringBuilder sb = new StringBuilder(bsn);
getTargetsInternal(bsn).add(b);
sb.append('|').append(version);
String bsnVersion = sb.toString();
getTargetsInternal(bsnVersion).add(b);
sb.append('|').append(location);
String bsnVersionLocation = sb.toString();
getTargetsInternal(bsnVersionLocation).add(b);
result.add(bsnVersionLocation);
result.add(bsnVersion);
result.add(bsn);
List<String> unmodifiable = Collections.unmodifiableList(result);
targetToQualifiedNames.put(b, unmodifiable);
return unmodifiable;
}
void remove(Bundle b) {
List<String> qualifiedNames = targetToQualifiedNames.remove(b);
if (qualifiedNames != null) {
for (String qualifiedName : qualifiedNames) {
Collection<Bundle> targets = qualifiedNameToTargets.get(qualifiedName);
if (targets != null) {
targets.remove(b);
if (targets.isEmpty()) {
qualifiedNameToTargets.remove(qualifiedName);
}
}
}
}
logServices.remove(b);
}
private Collection<Bundle> getTargetsInternal(String pid) {
Collection<Bundle> targets = qualifiedNameToTargets.get(pid);
if (targets == null) {
targets = new ArrayList<>(1);
qualifiedNameToTargets.put(pid, targets);
}
return targets;
}
ExtendedLogServiceImpl getLogService(Bundle bundle, ExtendedLogServiceFactory factory) {
ExtendedLogServiceImpl logService = logServices.get(bundle);
if (logService == null) {
// add bundle to target maps before constructing
add(bundle);
logService = new ExtendedLogServiceImpl(factory, bundle);
if (bundle != null && bundle.getState() != Bundle.UNINSTALLED)
logServices.put(bundle, logService);
}
return logService;
}
void replaceSystemBundleLogService(Bundle previousBundle, Bundle currentBundle) {
ExtendedLogServiceImpl existing = logServices.get(previousBundle);
if (existing != null) {
remove(previousBundle);
add(currentBundle);
logServices.put(currentBundle, existing);
existing.applyLogLevels(getEffectiveLoggerContext(currentBundle));
}
}
void clear() {
logServices.clear();
qualifiedNameToTargets.clear();
targetToQualifiedNames.clear();
loggerContexts.clear();
}
LoggerContext createLoggerContext(String name, ExtendedLogServiceFactory factory) {
EquinoxLoggerContext loggerContext = loggerContexts.get(name);
if (loggerContext == null) {
loggerContext = factory.createEquinoxLoggerContext(name);
loggerContexts.put(name, loggerContext);
}
return loggerContext;
}
EquinoxLoggerContext getRootLoggerContext() {
return loggerContexts.get(null);
}
void applyLogLevels(EquinoxLoggerContext loggerContext) {
Collection<Bundle> matching;
boolean isRoot = loggerContext.getName() == null;
if (isRoot) {
// root applies to all loggers
matching = logServices.keySet();
} else {
matching = qualifiedNameToTargets.get(loggerContext.getName());
}
if (matching == null) {
return;
}
for (Bundle bundle : matching) {
ExtendedLogServiceImpl logService = logServices.get(bundle);
if (logService != null) {
// Always apply the effective log context.
// This may be more costly but it is more simple than checking
// if the changed context overrides the existing settings
logService.applyLogLevels(getEffectiveLoggerContext(bundle));
}
}
}
EquinoxLoggerContext getEffectiveLoggerContext(Bundle bundle) {
List<String> qualifiedNames = targetToQualifiedNames.get(bundle);
if (qualifiedNames != null) {
for (String qualifiedName : qualifiedNames) {
EquinoxLoggerContext loggerContext = loggerContexts.get(qualifiedName);
if (loggerContext != null && !loggerContext.isEmpty()) {
return loggerContext;
}
}
}
return getRootLoggerContext();
}
}