--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Log4j
+Bundle-SymbolicName: user.jobengine.log4j
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: user.jobengine.log4j
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ClassPath: .,
+ lib/log4j-api-2.17.2.jar,
+ lib/log4j-core-2.17.2.jar,
+ lib/log4j-slf4j-impl-2.17.2.jar
+Export-Package: org.apache.logging.log4j,
+ org.apache.logging.log4j.core,
+ org.apache.logging.log4j.core.appender,
+ org.apache.logging.log4j.core.appender.db,
+ org.apache.logging.log4j.core.appender.db.jdbc,
+ org.apache.logging.log4j.core.appender.mom,
+ org.apache.logging.log4j.core.appender.mom.jeromq,
+ org.apache.logging.log4j.core.appender.mom.kafka,
+ org.apache.logging.log4j.core.appender.nosql,
+ org.apache.logging.log4j.core.appender.rewrite,
+ org.apache.logging.log4j.core.appender.rolling,
+ org.apache.logging.log4j.core.appender.rolling.action,
+ org.apache.logging.log4j.core.appender.routing,
+ org.apache.logging.log4j.core.async,
+ org.apache.logging.log4j.core.config,
+ org.apache.logging.log4j.core.config.arbiters,
+ org.apache.logging.log4j.core.config.builder.api,
+ org.apache.logging.log4j.core.config.builder.impl,
+ org.apache.logging.log4j.core.config.composite,
+ org.apache.logging.log4j.core.config.json,
+ org.apache.logging.log4j.core.config.plugins,
+ org.apache.logging.log4j.core.config.plugins.convert,
+ org.apache.logging.log4j.core.config.plugins.processor,
+ org.apache.logging.log4j.core.config.plugins.util,
+ org.apache.logging.log4j.core.config.plugins.validation,
+ org.apache.logging.log4j.core.config.plugins.validation.constraints,
+ org.apache.logging.log4j.core.config.plugins.validation.validators,
+ org.apache.logging.log4j.core.config.plugins.visitors,
+ org.apache.logging.log4j.core.config.properties,
+ org.apache.logging.log4j.core.config.status,
+ org.apache.logging.log4j.core.config.xml,
+ org.apache.logging.log4j.core.config.yaml,
+ org.apache.logging.log4j.core.filter,
+ org.apache.logging.log4j.core.impl,
+ org.apache.logging.log4j.core.jackson,
+ org.apache.logging.log4j.core.jmx,
+ org.apache.logging.log4j.core.layout,
+ org.apache.logging.log4j.core.layout.internal,
+ org.apache.logging.log4j.core.lookup,
+ org.apache.logging.log4j.core.message,
+ org.apache.logging.log4j.core.net,
+ org.apache.logging.log4j.core.net.ssl,
+ org.apache.logging.log4j.core.osgi,
+ org.apache.logging.log4j.core.parser,
+ org.apache.logging.log4j.core.pattern,
+ org.apache.logging.log4j.core.script,
+ org.apache.logging.log4j.core.selector,
+ org.apache.logging.log4j.core.time,
+ org.apache.logging.log4j.core.time.internal,
+ org.apache.logging.log4j.core.tools,
+ org.apache.logging.log4j.core.tools.picocli,
+ org.apache.logging.log4j.core.util,
+ org.apache.logging.log4j.core.util.datetime,
+ org.apache.logging.log4j.internal,
+ org.apache.logging.log4j.message,
+ org.apache.logging.log4j.simple,
+ org.apache.logging.log4j.spi,
+ org.apache.logging.log4j.status,
+ org.apache.logging.log4j.util,
+ org.apache.logging.slf4j,
+ org.slf4j.impl,
+ user.commons.log4j2.appender,
+ user.commons.log4j2.marker
+Import-Package: javax.mail;version="1.5.0",
+ javax.mail.internet;version="1.5.0",
+ javax.mail.util;version="1.5.0"
+Require-Bundle: org.eclipse.osgi;bundle-version="3.11.2"
--- /dev/null
+package user.commons.log4j2.appender;
+
+import java.io.Serializable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Core;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.DefaultConfiguration;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
+import org.apache.logging.log4j.core.config.plugins.validation.constraints.ValidPort;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.apache.logging.log4j.core.layout.HtmlLayout;
+import org.apache.logging.log4j.core.util.Booleans;
+
+/**
+ * Send an e-mail when a specific logging event occurs, typically on errors or fatal errors.
+ *
+ * <p>
+ * The number of logging events delivered in this e-mail depend on the value of <b>BufferSize</b> option. The <code>SmtpAppender</code> keeps only the last
+ * <code>BufferSize</code> logging events in its cyclic buffer. This keeps memory requirements at a reasonable level while still delivering useful application
+ * context.
+ *
+ * By default, an email message will formatted as HTML. This can be modified by setting a layout for the appender.
+ *
+ * By default, an email message will be sent when an ERROR or higher severity message is appended. This can be modified by setting a filter for the appender.
+ */
+@Plugin(name = "HTMLMailAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
+public final class HTMLMailAppender extends AbstractAppender {
+
+ private static final int DEFAULT_BUFFER_SIZE = 512;
+
+ private static final int CONCURRENT_MAIL_QUEUES = 1;
+ private static final ExecutorService executor = Executors.newFixedThreadPool(CONCURRENT_MAIL_QUEUES);
+
+ /**
+ * Create a SmtpAppender.
+ *
+ * @param name
+ * The name of the Appender.
+ * @param to
+ * The comma-separated list of recipient email addresses.
+ * @param cc
+ * The comma-separated list of CC email addresses.
+ * @param bcc
+ * The comma-separated list of BCC email addresses.
+ * @param from
+ * The email address of the sender.
+ * @param replyTo
+ * The comma-separated list of reply-to email addresses.
+ * @param subject
+ * The subject of the email message.
+ * @param smtpProtocol
+ * The SMTP transport protocol (such as "smtps", defaults to "smtp").
+ * @param smtpHost
+ * The SMTP hostname to send to.
+ * @param smtpPortStr
+ * The SMTP port to send to.
+ * @param smtpUsername
+ * The username required to authenticate against the SMTP server.
+ * @param smtpPassword
+ * The password required to authenticate against the SMTP server.
+ * @param smtpDebug
+ * Enable mail session debuging on STDOUT.
+ * @param bufferSizeStr
+ * How many log events should be buffered for inclusion in the message?
+ * @param layout
+ * The layout to use (defaults to HtmlLayout).
+ * @param filter
+ * The Filter or null (defaults to ThresholdFilter, level of ERROR).
+ * @param ignore
+ * If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise they are propagated to the caller.
+ * @return The SmtpAppender.
+ */
+ @PluginFactory
+ public static HTMLMailAppender createAppender(@PluginConfiguration final Configuration config, @PluginAttribute("name") @Required final String name,
+ @PluginAttribute("to") final String to, @PluginAttribute("cc") final String cc, @PluginAttribute("bcc") final String bcc,
+ @PluginAttribute("from") final String from, @PluginAttribute("replyTo") final String replyTo, @PluginAttribute("subject") final String subject,
+ @PluginAttribute("smtpProtocol") final String smtpProtocol, @PluginAttribute("smtpHost") final String smtpHost,
+ @PluginAttribute(value = "smtpPort", defaultString = "0") @ValidPort final String smtpPortStr,
+ @PluginAttribute("smtpUsername") final String smtpUsername, @PluginAttribute(value = "smtpPassword", sensitive = true) final String smtpPassword,
+ @PluginAttribute("smtpDebug") final String smtpDebug, @PluginAttribute("bufferSize") final String bufferSizeStr,
+ @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filter") Filter filter,
+ @PluginAttribute("ignoreExceptions") final String ignore) {
+ if (name == null) {
+ LOGGER.error("No name provided for SmtpAppender");
+ return null;
+ }
+
+ final boolean ignoreExceptions = Booleans.parseBoolean(ignore, true);
+ final int smtpPort = AbstractAppender.parseInt(smtpPortStr, 0);
+ final boolean isSmtpDebug = Boolean.parseBoolean(smtpDebug);
+ final int bufferSize = bufferSizeStr == null ? DEFAULT_BUFFER_SIZE : Integer.parseInt(bufferSizeStr);
+
+ if (layout == null) {
+ layout = HtmlLayout.createDefaultLayout();
+ }
+ if (filter == null) {
+ filter = ThresholdFilter.createFilter(null, null, null);
+ }
+ final Configuration configuration = config != null ? config : new DefaultConfiguration();
+
+ final SmtpManager manager = SmtpManager.getSmtpManager(configuration, to, cc, bcc, from, replyTo, subject, smtpProtocol, smtpHost, smtpPort,
+ smtpUsername, smtpPassword, isSmtpDebug, filter.toString(), bufferSize);
+ if (manager == null)
+ return null;
+
+ return new HTMLMailAppender(name, filter, layout, manager, ignoreExceptions);
+ }
+
+ /** The SMTP Manager */
+ private final SmtpManager manager;
+
+ private HTMLMailAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout, final SmtpManager manager,
+ final boolean ignoreExceptions) {
+ super(name, filter, layout, ignoreExceptions);
+ this.manager = manager;
+ }
+
+ /**
+ * Perform SmtpAppender specific appending actions, mainly adding the event to a cyclic buffer and checking if the event triggers an e-mail to be sent.
+ *
+ * @param event
+ * The Log event.
+ */
+ @Override
+ public void append(final LogEvent event) {
+ //System.out.println("append " + event.getMessage().getFormattedMessage());
+ final LogEvent eventToSend = event.toImmutable();
+ executor.submit(() -> {
+ manager.sendEvents(getLayout(), eventToSend);
+ });
+
+ }
+
+ /**
+ * Capture all events in CyclicBuffer.
+ *
+ * @param event
+ * The Log event.
+ * @return true if the event should be filtered.
+ */
+ @Override
+ public boolean isFiltered(final LogEvent event) {
+ final boolean filtered = super.isFiltered(event);
+ // if (filtered) {
+ // manager.add(event);
+ // }
+
+ //System.out.println("isFiltered");
+ return filtered;
+ }
+}
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package user.commons.log4j2.appender;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.activation.CommandMap;
+import javax.activation.DataSource;
+import javax.activation.MailcapCommandMap;
+import javax.mail.Authenticator;
+import javax.mail.Message;
+import javax.mail.Message.RecipientType;
+import javax.mail.MessagingException;
+import javax.mail.PasswordAuthentication;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetHeaders;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+import javax.mail.internet.MimeUtility;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LoggingException;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractManager;
+import org.apache.logging.log4j.core.appender.ManagerFactory;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.core.net.MimeMessageBuilder;
+import org.apache.logging.log4j.core.util.NameUtil;
+import org.apache.logging.log4j.core.util.NetUtils;
+import org.apache.logging.log4j.util.PropertiesUtil;
+import org.apache.logging.log4j.util.Strings;
+
+import user.commons.log4j2.marker.MediaCubeFinishMarker;
+import user.commons.log4j2.marker.MediaCubeMarker;
+import user.commons.log4j2.marker.MediaCubeUndoMarker;
+
+/**
+ * Manager for sending SMTP events.
+ */
+public class SmtpManager extends AbstractManager {
+ /**
+ * Factory data.
+ */
+ private static class FactoryData {
+ private final String to;
+ private final String cc;
+ private final String bcc;
+ private final String from;
+ private final String replyto;
+ private final Serializer subject;
+ private final String protocol;
+ private final String host;
+ private final int port;
+ private final String username;
+ private final String password;
+ private final boolean isDebug;
+ private final int numElements;
+
+ public FactoryData(final String to, final String cc, final String bcc, final String from, final String replyTo,
+ final Serializer subjectSerializer, final String protocol, final String host, final int port,
+ final String username, final String password, final boolean isDebug, final int numElements) {
+ this.to = to;
+ this.cc = cc;
+ this.bcc = bcc;
+ this.from = from;
+ this.replyto = replyTo;
+ this.subject = subjectSerializer;
+ this.protocol = protocol;
+ this.host = host;
+ this.port = port;
+ this.username = username;
+ this.password = password;
+ this.isDebug = isDebug;
+ this.numElements = numElements;
+ }
+ }
+
+ /**
+ * Factory to create the SMTP Manager.
+ */
+ private static class SMTPManagerFactory implements ManagerFactory<SmtpManager, FactoryData> {
+
+ private Authenticator buildAuthenticator(final String username, final String password) {
+ if (null != password && null != username) {
+ return new Authenticator() {
+ private final PasswordAuthentication passwordAuthentication = new PasswordAuthentication(username,
+ password);
+
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return passwordAuthentication;
+ }
+ };
+ }
+ return null;
+ }
+
+ @Override
+ public SmtpManager createManager(final String name, final FactoryData data) {
+ final String prefix = "mail." + data.protocol;
+
+ final Properties properties = PropertiesUtil.getSystemProperties();
+ properties.put("mail.transport.protocol", data.protocol);
+ if (properties.getProperty("mail.host") == null) {
+ // Prevent an UnknownHostException in Java 7
+ properties.put("mail.host", NetUtils.getLocalHostname());
+ }
+
+ if (null != data.host) {
+ properties.put(prefix + ".host", data.host);
+ }
+ if (data.port > 0) {
+ properties.put(prefix + ".port", String.valueOf(data.port));
+ }
+
+ final Authenticator authenticator = buildAuthenticator(data.username, data.password);
+ if (null != authenticator) {
+ properties.put(prefix + ".auth", "true");
+ }
+
+ final Session session = Session.getInstance(properties, authenticator);
+ session.setProtocolForAddress("rfc822", data.protocol);
+ session.setDebug(data.isDebug);
+ return new SmtpManager(name, session, null, data);
+ }
+ }
+
+ private static final SMTPManagerFactory FACTORY = new SMTPManagerFactory();
+ private static Map<String, List<LogEvent>> sessionEvents = new ConcurrentHashMap<>();
+
+ private static MimeMessage createMimeMessage(final FactoryData data, final Session session,
+ final LogEvent appendEvent) throws MessagingException {
+ return new MimeMessageBuilder(session).setFrom(data.from).setReplyTo(data.replyto)
+ .setRecipients(Message.RecipientType.TO, data.to).setRecipients(Message.RecipientType.CC, data.cc)
+ .setRecipients(Message.RecipientType.BCC, data.bcc).setSubject(data.subject.toSerializable(appendEvent))
+ .build();
+ }
+
+ public static SmtpManager getSmtpManager(final Configuration config, final String to, final String cc,
+ final String bcc, final String from, final String replyTo, final String subject, String protocol,
+ final String host, final int port, final String username, final String password, final boolean isDebug,
+ final String filterName, final int numElements) {
+ if (Strings.isEmpty(protocol)) {
+ protocol = "smtp";
+ }
+
+ final StringBuilder sb = new StringBuilder();
+ if (to != null) {
+ sb.append(to);
+ }
+ sb.append(':');
+ if (cc != null) {
+ sb.append(cc);
+ }
+ sb.append(':');
+ if (bcc != null) {
+ sb.append(bcc);
+ }
+ sb.append(':');
+ if (from != null) {
+ sb.append(from);
+ }
+ sb.append(':');
+ if (replyTo != null) {
+ sb.append(replyTo);
+ }
+ sb.append(':');
+ if (subject != null) {
+ sb.append(subject);
+ }
+ sb.append(':');
+ sb.append(protocol).append(':').append(host).append(':').append("port").append(':');
+ if (username != null) {
+ sb.append(username);
+ }
+ sb.append(':');
+ if (password != null) {
+ sb.append(password);
+ }
+ sb.append(isDebug ? ":debug:" : "::");
+ sb.append(filterName);
+
+ final String name = "SMTP:" + NameUtil.md5(sb.toString());
+ final Serializer subjectSerializer = PatternLayout.newSerializerBuilder().setConfiguration(config)
+ .setPattern(subject).build();
+
+ return getManager(name, FACTORY, new FactoryData(to, cc, bcc, from, replyTo, subjectSerializer, protocol, host,
+ port, username, password, isDebug, numElements));
+ }
+
+ private final Session session;
+ private volatile MimeMessage message;
+ private final FactoryData data;
+ private String defaultRecipient;
+ private String defaultSubject;
+
+ protected SmtpManager(final String name, final Session session, final MimeMessage message, final FactoryData data) {
+ super(null, name);
+ this.session = session;
+ this.message = message;
+ this.data = data;
+ this.defaultRecipient = data.to;
+ }
+
+ // public void add(LogEvent event) {
+ // if (event instanceof Log4jLogEvent && event.getMessage() instanceof
+ // ReusableMessage) {
+ // ((Log4jLogEvent) event).makeMessageImmutable();
+ // } else if (event instanceof MutableLogEvent) {
+ // event = ((MutableLogEvent) event).createMemento();
+ // }
+ // }
+
+ private synchronized void connect(final LogEvent appendEvent) {
+ if (message != null) {
+ return;
+ }
+ try {
+ message = createMimeMessage(data, session, appendEvent);
+ this.defaultSubject = message.getSubject();
+ } catch (final MessagingException e) {
+ logError("Could not set SmtpAppender message options", e);
+ message = null;
+ }
+ }
+
+ protected void encodeContent(final byte[] bytes, final String encoding, final ByteArrayOutputStream out)
+ throws MessagingException, IOException {
+ try (final OutputStream encoder = MimeUtility.encode(out, encoding)) {
+ encoder.write(bytes);
+ }
+ }
+
+ protected byte[] encodeContentToBytes(final byte[] rawBytes, final String encoding)
+ throws MessagingException, IOException {
+ final ByteArrayOutputStream encoded = new ByteArrayOutputStream();
+ encodeContent(rawBytes, encoding, encoded);
+ return encoded.toByteArray();
+ }
+
+ protected byte[] formatContentToBytes(final List<LogEvent> events, final Layout<?> layout) throws IOException {
+ final ByteArrayOutputStream raw = new ByteArrayOutputStream();
+ writeContent(events, layout, raw);
+ return raw.toByteArray();
+ }
+
+ protected String getEncoding(final byte[] rawBytes, final String contentType) {
+ final DataSource dataSource = new ByteArrayDataSource(rawBytes, contentType);
+ return MimeUtility.getEncoding(dataSource);
+ }
+
+ protected InternetHeaders getHeaders(final String contentType, final String encoding) {
+ final InternetHeaders headers = new InternetHeaders();
+ headers.setHeader("Content-Type", contentType + "; charset=UTF-8");
+ headers.setHeader("Content-Transfer-Encoding", encoding);
+ return headers;
+ }
+
+ private Level getLowestLevel(final Level level, final List<LogEvent> events) {
+ Level mailLevel = level;
+ if (events != null) {
+ for (LogEvent event : events) {
+ if (event.getLevel().intLevel() < mailLevel.intLevel())
+ mailLevel = event.getLevel();
+ }
+ }
+ return mailLevel;
+ }
+
+ protected MimeMultipart getMimeMultipart(final byte[] encodedBytes, final InternetHeaders headers)
+ throws MessagingException {
+ final MimeMultipart mp = new MimeMultipart();
+ final MimeBodyPart part = new MimeBodyPart(headers, encodedBytes);
+ mp.addBodyPart(part);
+ return mp;
+ }
+
+ private void sendEmail(final String to, final String subject, byte[] content, String contentType) {
+ try {
+ MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
+ mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
+ mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
+ mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
+ mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
+ mc.addMailcap("message/rfc822;; x-java-content- handler=com.sun.mail.handlers.message_rfc822");
+ message.setSubject(subject);
+ message.setRecipients(RecipientType.TO, to);
+ final String encoding = getEncoding(content, contentType);
+ final byte[] encodedBytes = encodeContentToBytes(content, encoding);
+ final InternetHeaders headers = getHeaders(contentType, encoding);
+ final MimeMultipart mp = getMimeMultipart(encodedBytes, headers);
+ sendMultipartMessage(message, mp);
+ } catch (final MessagingException | IOException | RuntimeException e) {
+ logError("Caught exception while sending e-mail notification.", e);
+ throw new LoggingException("Error occurred while sending email", e);
+ }
+ }
+
+ /**
+ * Send the contents of the cyclic buffer as an e-mail message.
+ *
+ * @param layout The layout for formatting the events.
+ * @param appendEvent The event that triggered the send.
+ */
+ public void sendEvents(final Layout<?> layout, final LogEvent appendEvent) {
+ if (message == null)
+ connect(appendEvent);
+
+ // System.out.println(appendEvent.getMarker().getClass().getSimpleName() + " " +
+ // new String(layout.toByteArray(appendEvent)));
+ String to = defaultRecipient;
+ String subject = defaultSubject;
+ if (appendEvent.getMarker() instanceof MediaCubeFinishMarker) {
+ MediaCubeFinishMarker mcm = (MediaCubeFinishMarker) appendEvent.getMarker();
+ storeSessionEvent(mcm, appendEvent);
+ String sessionID = mcm.getSessionID();
+ if (sessionID == null)
+ return;
+
+ List<LogEvent> events = sessionEvents.get(sessionID);
+
+ // ha error, akkor mindenkepp elmegy
+ if (mcm.isUseSessionLog() || getLowestLevel(Level.INFO, events).intLevel() < Level.WARN.intLevel()) {
+ sendSessionEvents(events, mcm, layout, appendEvent.getLevel());
+ }
+
+ }
+
+ if (appendEvent.getMarker() instanceof MediaCubeUndoMarker) {
+ undoSessionEvents((MediaCubeMarker) appendEvent.getMarker());
+ return;
+ }
+
+ if (appendEvent.getMarker() instanceof MediaCubeMarker) {
+ MediaCubeMarker mcm = (MediaCubeMarker) appendEvent.getMarker();
+ if (mcm.getSessionID() == null) {
+ if (mcm.getTo() != null)
+ to = mcm.getTo();
+ if (mcm.getSubject() != null)
+ subject = mcm.getSubject();
+ } else {
+ storeSessionEvent(mcm, appendEvent);
+ return;
+ }
+
+ }
+
+ sendEvents(to, subject, layout, Arrays.asList(appendEvent));
+ }
+
+ private void sendEvents(final String to, final String subject, final Layout<?> layout,
+ final List<LogEvent> events) {
+ try {
+ final byte[] rawBytes = formatContentToBytes(events, layout);
+ // final String contentType = layout.getContentType();
+
+ sendEmail(to, subject, rawBytes, "text/html; charset=utf-8");
+ } catch (Exception e) {
+ logError("Caught exception while sending e-mail notification.", e);
+ throw new LoggingException("Error occurred while sending email", e);
+ }
+ }
+
+ protected void sendMultipartMessage(final MimeMessage msg, final MimeMultipart mp) throws MessagingException {
+ synchronized (msg) {
+ msg.setContent(mp);
+ msg.setSentDate(new Date());
+ Transport.send(msg);
+ }
+ }
+
+ private void sendSessionEvents(final List<LogEvent> events, final MediaCubeMarker mcm, final Layout<?> layout,
+ final Level level) {
+ String sessionID = mcm.getSessionID();
+ if (events == null)
+ return;
+
+ Level mailLevel = getLowestLevel(level, events);
+
+ String to = mcm.getTo() == null ? defaultRecipient : defaultRecipient + "," + mcm.getTo();
+ String subject = mcm.getSessionName() == null ? defaultSubject
+ : String.format("%s: %s #%s", mailLevel, mcm.getSessionName(), sessionID);
+ sendEvents(to, subject, layout, events);
+ sessionEvents.remove(sessionID);
+ }
+
+ private void storeSessionEvent(MediaCubeMarker mcm, LogEvent appendEvent) {
+ String sessionID = mcm.getSessionID();
+ List<LogEvent> events = sessionEvents.get(sessionID);
+ if (events == null) {
+ events = new ArrayList<>();
+ sessionEvents.put(sessionID, events);
+ }
+ events.add(appendEvent);
+ }
+
+ private void undoSessionEvents(final MediaCubeMarker mcm) {
+ String sessionID = mcm.getSessionID();
+ if (sessionID != null && sessionEvents.containsKey(sessionID))
+ sessionEvents.remove(sessionID);
+ }
+
+ protected void writeBuffer(List<LogEvent> events, final Layout<?> layout, final OutputStream out)
+ throws IOException {
+ out.write("<html>".getBytes());
+ out.write("<body>".getBytes());
+
+ out.write("<table>".getBytes());
+ for (final LogEvent priorEvent : events) {
+ out.write("<tr><td>".getBytes());
+ final byte[] bytes = layout.toByteArray(priorEvent);
+ out.write(bytes);
+ out.write("</td></tr>".getBytes());
+ }
+ out.write("</table>".getBytes());
+ out.write("</body>".getBytes());
+ out.write("</html>".getBytes());
+ }
+
+ private void writeContent(final List<LogEvent> events, final Layout<?> layout, final ByteArrayOutputStream out)
+ throws IOException {
+ writeHeader(layout, out);
+ writeBuffer(events, layout, out);
+ writeFooter(layout, out);
+ }
+
+ protected void writeFooter(final Layout<?> layout, final OutputStream out) throws IOException {
+ final byte[] footer = layout.getFooter();
+ if (footer != null) {
+ out.write(footer);
+ }
+ }
+
+ protected void writeHeader(final Layout<?> layout, final OutputStream out) throws IOException {
+ final byte[] header = layout.getHeader();
+ if (header != null) {
+ out.write(header);
+ }
+ }
+}