blob: 754f3263207fee6b8ffc7219a23c8fe4c72ab3c2 [file] [log] [blame]
/**
* Copyright (c) 2015 Codetrails GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.epp.logging.aeri.core.util;
import static com.google.common.base.Preconditions.*;
import static org.eclipse.core.runtime.IStatus.ERROR;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.text.MessageFormat;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.epp.logging.aeri.core.SystemControl;
import org.eclipse.epp.logging.aeri.core.l10n.LogMessages;
import org.eclipse.jdt.annotation.Nullable;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
public class Logs {
public interface ILogMessage {
/**
* The severity of a log message. One of {@link IStatus#ERROR}, {@link IStatus#WARNING}, {@link IStatus#INFO}, {@link IStatus#OK},
* {@link IStatus#CANCEL}
*/
int severity();
/**
* The error or log code of this log message.
*/
int code();
/**
* A message string that may contain {@link MessageFormat} compatible placeholders (e.g., {0}).
*/
String message();
/**
* The bundle the log message is defined by.
*/
Bundle bundle();
}
public abstract static class DefaultLogMessage implements ILogMessage {
private int severity;
private int code;
private String message;
public DefaultLogMessage(int severity, int code, String message) {
checkArgument(code > 0, "The error code cannot be '0'");
checkNotNull(message);
this.severity = severity;
this.code = code;
this.message = message;
}
@Override
public int severity() {
return severity;
}
@Override
public int code() {
return code;
}
@Override
public String message() {
return message;
}
@Override
public abstract Bundle bundle();
}
public static IStatus toStatus(ILogMessage msg, Object... args) {
return toStatus(msg, null, args);
}
public static IStatus toStatus(ILogMessage msg, @Nullable Throwable t, @Nullable Object... args) {
checkNotNull(msg);
String message = null;
try {
message = MessageFormat.format(msg.message(), args);
} catch (Exception e) {
// in case of an error, do a bullet proof error logging and continue
// working as if almost nothing happened:
message = msg.message();
Bundle bundle = FrameworkUtil.getBundle(Logs.class);
if (bundle != null) {
ILog log = Platform.getLog(bundle);
if (log != null) {
String format = MessageFormat.format("Failed to format '{0}': {1}", msg.message(), e.getMessage());
Status error = new Status(ERROR, bundle.getSymbolicName(), format, e);
log.log(error);
}
}
}
return new Status(msg.severity(), msg.bundle().getSymbolicName(), msg.code(), message, t);
}
public static void log(ILogMessage msg) {
log(msg, (Object[]) null);
}
public static void log(ILogMessage msg, Throwable t) {
log(msg, t, (Object[]) null);
}
public static void log(ILogMessage msg, @Nullable Object... args) {
log(msg, LogTraceException.newTrace(), args);
}
public static void log(ILogMessage msg, Throwable t, @Nullable Object... args) {
try {
IStatus status = toStatus(msg, t, args);
Bundle bundle = msg.bundle();
ILog log = Platform.getLog(bundle);
log.log(status);
} catch (Exception e) {
// swallow this one...
// we are likely in a test case that does not run inside an
// OSGI/Eclipse runtime.
}
}
public static Bundle getBundle(Class<?> bundleClazz) {
Bundle res = FrameworkUtil.getBundle(bundleClazz);
if (res != null) {
return res;
}
String fakeSymbolicName = bundleClazz.getPackage().getName();
return new FakeBundle(fakeSymbolicName);
}
public static ILog getLog(@Nullable Bundle bundle) {
if (bundle == null) {
return new SystemOutLog();
}
return Platform.getLog(bundle);
}
public static String toString(final IStatus status) {
final StringBuilder sb = new StringBuilder();
appendSeverityAndMessage(status, sb);
appendException(status, sb);
if (status.isMultiStatus()) {
appendChildren(status, sb);
}
return sb.toString();
}
private static void appendSeverityAndMessage(final IStatus status, final StringBuilder sb) {
sb.append(toSeverity(status)).append(':').append(' ').append(status.getMessage());
}
private static String toSeverity(final IStatus status) {
switch (status.getSeverity()) {
case IStatus.CANCEL:
return "CANCEL";
case IStatus.ERROR:
return "ERROR";
case IStatus.WARNING:
return "WARNING";
case IStatus.INFO:
return "INFO";
case IStatus.OK:
return "OK";
default:
throw new RuntimeException("Unreachable");
}
}
private static void appendException(final IStatus status, final StringBuilder sb) {
if (status.getException() != null) {
sb.append(' ').append(status.getException());
}
}
private static void appendChildren(final IStatus status, final StringBuilder sb) {
for (final IStatus child : status.getChildren()) {
sb.append('\n').append(toString(child));
}
}
private static final class SystemOutLog implements ILog {
@Override
public void removeLogListener(ILogListener listener) {
}
@Override
public void log(IStatus status) {
System.out.println(status);
}
@Override
public Bundle getBundle() {
return null;
}
@Override
public void addLogListener(ILogListener listener) {
}
}
@SuppressWarnings("null")
private static final class FakeBundle implements Bundle {
private String symbolicName;
public FakeBundle(String fakeBundleId) {
this.symbolicName = fakeBundleId;
}
@Override
public int compareTo(Bundle arg0) {
return 0;
}
@Override
public void update(InputStream input) throws BundleException {
}
@Override
public void update() throws BundleException {
}
@Override
public void uninstall() throws BundleException {
}
@Override
public void stop(int options) throws BundleException {
}
@Override
public void stop() throws BundleException {
}
@Override
public void start(int options) throws BundleException {
}
@Override
public void start() throws BundleException {
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return null;
}
@Override
public boolean hasPermission(Object permission) {
return false;
}
@Override
public Version getVersion() {
return null;
}
@Override
public String getSymbolicName() {
return symbolicName;
}
@Override
public int getState() {
return 0;
}
@Override
public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
return null;
}
@Override
public ServiceReference<?>[] getServicesInUse() {
return null;
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
return null;
}
@Override
public URL getResource(String name) {
return null;
}
@Override
public ServiceReference<?>[] getRegisteredServices() {
return null;
}
@Override
public String getLocation() {
return null;
}
@Override
public long getLastModified() {
return 0;
}
@Override
public Dictionary<String, String> getHeaders(String locale) {
return null;
}
@Override
public Dictionary<String, String> getHeaders() {
return null;
}
@Override
public Enumeration<String> getEntryPaths(String path) {
return null;
}
@Override
public URL getEntry(String path) {
return null;
}
@Override
public File getDataFile(String filename) {
return null;
}
@Override
public long getBundleId() {
return 0;
}
@Override
public BundleContext getBundleContext() {
return null;
}
@Override
public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
return null;
}
@Override
public <A> A adapt(Class<A> type) {
return null;
}
}
private static final class LogTraceException extends RuntimeException {
private static final long serialVersionUID = 1L;
static LogTraceException newTrace() {
LogTraceException res = new LogTraceException();
res.fillInStackTrace();
return res;
}
}
public static void debug(String message, Object... args) {
debug(message, null, args);
}
public static void debug(String message, Throwable throwable, Object... args) {
if (SystemControl.isDebug()) {
LogMessages log = new LogMessages(IStatus.INFO, 404, message);
log(log, throwable, args);
}
}
public static void warn(String message, Object... args) {
warn(message, null, args);
}
public static void warn(String message, Throwable throwable, Object... args) {
LogMessages log = new LogMessages(IStatus.WARNING, 404, message);
log(log, throwable, args);
}
}