Bug 559036 - [log] add configuration to avoid capturing log entry
location

Change-Id: Id605511bca7f6a00cbcab26c27cbf851fce36ff0
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/TestListener.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/TestListener.java
index bb9cb89..1feb04e 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/TestListener.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/equinox/log/test/TestListener.java
@@ -1,26 +1,25 @@
 /*******************************************************************************
-n
-n 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
+ * Copyright (c) 2020 Cognos Incorporated, 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
- *******************************************************************************/
+ ******************************************************************************/
 package org.eclipse.equinox.log.test;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.LinkedList;
 import org.eclipse.equinox.log.ExtendedLogEntry;
 import org.eclipse.osgi.tests.OSGiTestsActivator;
 import org.junit.Assert;
 import org.osgi.service.log.LogEntry;
 import org.osgi.service.log.LogListener;
 
-class TestListener implements LogListener {
+public class TestListener implements LogListener {
 	private final String testBundleLoc;
-	private List<LogEntry> logs = new ArrayList<>();
+	private LinkedList<LogEntry> logs = new LinkedList<>();
 
 	public TestListener() {
 		this(null);
@@ -45,11 +44,11 @@
 	public synchronized ExtendedLogEntry getEntryX(long timeToWait) throws InterruptedException {
 		LogEntry logEntry;
 		long startTime = System.currentTimeMillis();
-		if (logs.size() == 0 && timeToWait > 0) {
+		if (logs.isEmpty() && timeToWait > 0) {
 			this.wait(timeToWait);
 			timeToWait = timeToWait - (System.currentTimeMillis() - startTime);
 		}
-		logEntry = logs.size() == 0 ? null : logs.remove(0);
+		logEntry = logs.isEmpty() ? null : logs.removeFirst();
 		if (logEntry == null) {
 			Assert.fail("No log entry logged.");
 		}
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
index ceb80c2..f09cc59 100755
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2018 IBM Corporation and others.
+ * Copyright (c) 2008, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -68,6 +68,7 @@
 import org.eclipse.core.runtime.adaptor.EclipseStarter;
 import org.eclipse.equinox.log.ExtendedLogReaderService;
 import org.eclipse.equinox.log.ExtendedLogService;
+import org.eclipse.equinox.log.test.TestListener;
 import org.eclipse.equinox.log.test.TestListener2;
 import org.eclipse.osgi.container.Module;
 import org.eclipse.osgi.framework.util.FilePath;
@@ -116,6 +117,7 @@
 import org.osgi.service.log.LogEntry;
 import org.osgi.service.log.LogLevel;
 import org.osgi.service.log.LogReaderService;
+import org.osgi.service.log.LogService;
 import org.osgi.service.packageadmin.ExportedPackage;
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.service.startlevel.StartLevel;
@@ -1136,7 +1138,7 @@
 		for (File testBundle : testBundles) {
 			try {
 				systemContext.installBundle("reference:file:///" + testBundle.getAbsolutePath()); //$NON-NLS-1$
-			}catch (BundleException e) {
+			} catch (BundleException e) {
 				fail("Unexpected install error", e); //$NON-NLS-1$
 			}
 		}
@@ -3279,7 +3281,7 @@
 		}
 	}
 
-	public static void doLoggingOnMultipleListeners(Equinox equinox) throws InterruptedException {
+	static void doLoggingOnMultipleListeners(Equinox equinox) throws InterruptedException {
 		int listenersSize = 100;
 		int logSize = 10000;
 		BundleContext bc = equinox.getBundleContext();
@@ -3312,6 +3314,46 @@
 		}
 	}
 
+	public void testCaptureLogEntryLocation() throws BundleException, InterruptedException {
+		doTestCaptureLogEntryLocation(true);
+		doTestCaptureLogEntryLocation(false);
+	}
+
+	private void doTestCaptureLogEntryLocation(boolean captureLocation) throws BundleException, InterruptedException {
+		File config = OSGiTestsActivator.getContext().getDataFile(getName()); //$NON-NLS-1$
+		Map configuration = new HashMap();
+		configuration.put(Constants.FRAMEWORK_STORAGE, config.getAbsolutePath());
+		if (!captureLocation) {
+			// the default is true; only set for false
+			configuration.put(EquinoxConfiguration.PROP_LOG_CAPTURE_ENTRY_LOCATION, Boolean.toString(captureLocation));
+		}
+		Equinox equinox = new Equinox(configuration);
+		try {
+			equinox.start();
+
+			BundleContext bc = equinox.getBundleContext();
+			LogReaderService logReader = bc.getService(bc.getServiceReference(LogReaderService.class));
+			LogService logService = bc.getService(bc.getServiceReference(LogService.class));
+
+			TestListener listener = new TestListener(Constants.SYSTEM_BUNDLE_LOCATION);
+			logReader.addLogListener(listener);
+
+			final String testMsg = "TEST MESSAGE";
+			logService.getLogger(this.getClass()).error(testMsg);
+
+			LogEntry logEntry = listener.getEntryX();
+			assertEquals("Wrong message.", testMsg, logEntry.getMessage());
+			if (captureLocation) {
+				assertNotNull("No location found.", logEntry.getLocation());
+			} else {
+				assertNull("Found location.", logEntry.getLocation());
+			}
+		} finally {
+			equinox.stop();
+			equinox.waitForStop(1000);
+		}
+	}
+
 	public void testSystemCapabilitiesBug522125() throws URISyntaxException, FileNotFoundException, IOException, BundleException, InterruptedException {
 		String frameworkLocation = OSGiTestsActivator.getContext().getProperty(EquinoxConfiguration.PROP_FRAMEWORK);
 		URI uri = new URI(frameworkLocation);
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
index c08e800..da2fb2d 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2003, 2019 IBM Corporation and others.
+ * Copyright (c) 2003, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -223,6 +223,7 @@
 	public static final String PROP_MODULE_AUTO_START_ON_RESOLVE = "osgi.module.auto.start.on.resolve"; //$NON-NLS-1$
 	public static final String PROP_ALLOW_RESTRICTED_PROVIDES = "osgi.equinox.allow.restricted.provides"; //$NON-NLS-1$
 	public static final String PROP_LOG_HISTORY_MAX = "equinox.log.history.max"; //$NON-NLS-1$
+	public static final String PROP_LOG_CAPTURE_ENTRY_LOCATION = "equinox.log.capture.entry.location"; //$NON-NLS-1$
 
 	@Deprecated
 	public static final String PROP_RESOLVER_THREAD_COUNT = "equinox.resolver.thead.count"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
index 32ed552..8040f90 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/EquinoxLogServices.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2017 IBM Corporation and others.
+ * Copyright (c) 2006, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -101,7 +101,8 @@
 			//ignore and use LogLevel.WARN
 		}
 
-		logServiceManager = new LogServiceManager(logHistoryMax, defaultLevel, logWriter, perfWriter);
+		boolean captureLogEntryLocation = "true".equals(environmentInfo.getConfiguration(EquinoxConfiguration.PROP_LOG_CAPTURE_ENTRY_LOCATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
+		logServiceManager = new LogServiceManager(logHistoryMax, defaultLevel, captureLogEntryLocation, logWriter, perfWriter);
 		eclipseLogFactory = new EquinoxLogFactory(logWriter, logServiceManager);
 		rootFrameworkLog = eclipseLogFactory.createFrameworkLog(null, logWriter);
 
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java
index 75e2d9d..a6c3987 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/ExtendedLogServiceFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2018 Cognos Incorporated, IBM Corporation and others
+ * Copyright (c) 2006, 2020 Cognos Incorporated, IBM Corporation and others
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0 which
@@ -37,10 +37,15 @@
 	private final Permission logPermission = new LogPermission("*", LogPermission.LOG); //$NON-NLS-1$
 	final ExtendedLogReaderServiceFactory logReaderServiceFactory;
 	private final LoggerAdmin loggerAdmin = new EquinoxLoggerAdmin();
+	private final boolean captureLogEntryLocation;
 
-	public ExtendedLogServiceFactory(ExtendedLogReaderServiceFactory logReaderServiceFactory) {
+	public ExtendedLogServiceFactory(ExtendedLogReaderServiceFactory logReaderServiceFactory, boolean captureLogEntryLocation) {
 		this.logReaderServiceFactory = logReaderServiceFactory;
+		this.captureLogEntryLocation = captureLogEntryLocation;
+	}
 
+	boolean captureLogEntryLocation() {
+		return captureLogEntryLocation;
 	}
 
 	@Override
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java
index 38bdb07..a569484 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LogServiceManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2018 Cognos Incorporated, IBM Corporation and others
+ * Copyright (c) 2006, 2020 Cognos Incorporated, IBM Corporation and others
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0 which
@@ -61,9 +61,9 @@
 	private EventAdminAdapter eventAdminAdapter;
 	private ConfigAdminListener configAdminListener;
 
-	public LogServiceManager(int maxHistory, LogLevel defaultLevel, LogListener... systemListeners) {
+	public LogServiceManager(int maxHistory, LogLevel defaultLevel, boolean captureLogEntryLocation, LogListener... systemListeners) {
 		logReaderServiceFactory = new ExtendedLogReaderServiceFactory(maxHistory, defaultLevel);
-		logServiceFactory = new ExtendedLogServiceFactory(logReaderServiceFactory);
+		logServiceFactory = new ExtendedLogServiceFactory(logReaderServiceFactory, captureLogEntryLocation);
 		systemBundleLog = logServiceFactory.getLogService(new MockSystemBundle());
 		for (LogListener logListener : systemListeners) {
 			if (logListener instanceof LogFilter)
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java
index dafdcdc..710d5ee 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/log/LoggerImpl.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2018 Cognos Incorporated, IBM Corporation and others
+ * Copyright (c) 2006, 2020 Cognos Incorporated, IBM Corporation and others
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0 which
@@ -298,6 +298,9 @@
 	}
 
 	private StackTraceElement getLocation() {
+		if (!logServiceImpl.getFactory().captureLogEntryLocation()) {
+			return null;
+		}
 		StackTraceElement[] elements = Thread.currentThread().getStackTrace();
 		if (elements.length == 0) {
 			return null;