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