| /******************************************************************************* |
| * 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(); |
| } |
| } |