From: vasary.daniel Date: Fri, 4 Mar 2022 15:19:24 +0000 (+0000) Subject: git-tfs-id: [http://tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube... X-Git-Url: http://git.useribm.hu/?a=commitdiff_plain;h=6275f0ef83b354c4b7893a2a7fe60f0d3911baa8;p=mediacube.git git-tfs-id: [tfs.userrendszerhaz.hu:8080/tfs/DefaultCollection]$/MediaCube;C33016 --- diff --git a/server/user.jobengine.log4j/.classpath b/server/user.jobengine.log4j/.classpath new file mode 100644 index 00000000..4d79cc51 --- /dev/null +++ b/server/user.jobengine.log4j/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/server/user.jobengine.log4j/.project b/server/user.jobengine.log4j/.project new file mode 100644 index 00000000..d074e0e4 --- /dev/null +++ b/server/user.jobengine.log4j/.project @@ -0,0 +1,28 @@ + + + user.jobengine.log4j + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/server/user.jobengine.log4j/.settings/org.eclipse.jdt.core.prefs b/server/user.jobengine.log4j/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..e2860e99 --- /dev/null +++ b/server/user.jobengine.log4j/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/server/user.jobengine.log4j/.settings/org.eclipse.pde.core.prefs b/server/user.jobengine.log4j/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 00000000..b7e72d01 --- /dev/null +++ b/server/user.jobengine.log4j/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/server/user.jobengine.log4j/META-INF/MANIFEST.MF b/server/user.jobengine.log4j/META-INF/MANIFEST.MF new file mode 100644 index 00000000..e9bb79b9 --- /dev/null +++ b/server/user.jobengine.log4j/META-INF/MANIFEST.MF @@ -0,0 +1,78 @@ +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" diff --git a/server/user.jobengine.log4j/build.properties b/server/user.jobengine.log4j/build.properties new file mode 100644 index 00000000..4a34f797 --- /dev/null +++ b/server/user.jobengine.log4j/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + lib/log4j-api-2.17.2.jar,\ + lib/log4j-core-2.17.2.jar,\ + lib/log4j-slf4j-impl-2.17.2.jar diff --git a/server/user.jobengine.log4j/lib/log4j-api-2.17.2.jar b/server/user.jobengine.log4j/lib/log4j-api-2.17.2.jar new file mode 100644 index 00000000..16d9061d Binary files /dev/null and b/server/user.jobengine.log4j/lib/log4j-api-2.17.2.jar differ diff --git a/server/user.jobengine.log4j/lib/log4j-core-2.17.2.jar b/server/user.jobengine.log4j/lib/log4j-core-2.17.2.jar new file mode 100644 index 00000000..0fd00514 Binary files /dev/null and b/server/user.jobengine.log4j/lib/log4j-core-2.17.2.jar differ diff --git a/server/user.jobengine.log4j/lib/log4j-slf4j-impl-2.17.2.jar b/server/user.jobengine.log4j/lib/log4j-slf4j-impl-2.17.2.jar new file mode 100644 index 00000000..a5cc3961 Binary files /dev/null and b/server/user.jobengine.log4j/lib/log4j-slf4j-impl-2.17.2.jar differ diff --git a/server/user.jobengine.log4j/src/user/commons/log4j2/appender/HTMLMailAppender.java b/server/user.jobengine.log4j/src/user/commons/log4j2/appender/HTMLMailAppender.java new file mode 100644 index 00000000..e957186f --- /dev/null +++ b/server/user.jobengine.log4j/src/user/commons/log4j2/appender/HTMLMailAppender.java @@ -0,0 +1,163 @@ +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. + * + *

+ * The number of logging events delivered in this e-mail depend on the value of BufferSize option. The SmtpAppender keeps only the last + * BufferSize 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 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 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; + } +} diff --git a/server/user.jobengine.log4j/src/user/commons/log4j2/appender/SmtpManager.java b/server/user.jobengine.log4j/src/user/commons/log4j2/appender/SmtpManager.java new file mode 100644 index 00000000..72d87be2 --- /dev/null +++ b/server/user.jobengine.log4j/src/user/commons/log4j2/appender/SmtpManager.java @@ -0,0 +1,469 @@ +/* + * 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 { + + 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> 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 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 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 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 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 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 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 events, final Layout layout, final OutputStream out) + throws IOException { + out.write("".getBytes()); + out.write("".getBytes()); + + out.write("".getBytes()); + for (final LogEvent priorEvent : events) { + out.write("".getBytes()); + } + out.write("
".getBytes()); + final byte[] bytes = layout.toByteArray(priorEvent); + out.write(bytes); + out.write("
".getBytes()); + out.write("".getBytes()); + out.write("".getBytes()); + } + + private void writeContent(final List 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); + } + } +} diff --git a/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeFinishMarker.java b/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeFinishMarker.java new file mode 100644 index 00000000..2f6170cc --- /dev/null +++ b/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeFinishMarker.java @@ -0,0 +1,20 @@ +package user.commons.log4j2.marker; + +@SuppressWarnings("serial") +public class MediaCubeFinishMarker extends MediaCubeMarker { + + public MediaCubeFinishMarker(MediaCubeMarker parent) { + setSessionID(parent.getSessionID()); + setSessionName(parent.getSessionName()); + setTo(parent.getTo()); + setUseSessionLog(parent.isUseSessionLog()); + setParents(parent); + } + + public MediaCubeFinishMarker(MediaCubeMarker parent, String to) { + super(to); + setSessionID(parent.getSessionID()); + setSessionName(parent.getSessionName()); + setParents(parent); + } +} diff --git a/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeMarker.java b/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeMarker.java new file mode 100644 index 00000000..2f4e618e --- /dev/null +++ b/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeMarker.java @@ -0,0 +1,78 @@ +package user.commons.log4j2.marker; + +import org.apache.logging.log4j.MarkerManager.Log4jMarker; + +@SuppressWarnings("serial") +public class MediaCubeMarker extends Log4jMarker { + private static final String MEDIACUBE = "MEDIACUBE"; + private String to; + private String subject; + private String sessionID; + private String sessionName; + private boolean useSessionLog; + + public MediaCubeMarker() { + super(MEDIACUBE); + } + + public MediaCubeMarker(String to) { + super(MEDIACUBE); + this.to = to; + } + + public MediaCubeMarker(String to, String subject) { + super(MEDIACUBE); + this.to = to; + this.subject = subject; + } + + public String getSessionID() { + return sessionID; + } + + public String getSessionName() { + return sessionName; + } + + public String getSubject() { + return subject; + } + + public String getTo() { + return to; + } + + public boolean isUseSessionLog() { + return useSessionLog; + } + + public void setSessionID(String sessionID) { + this.sessionID = sessionID; + } + + public void setSessionName(String sessionName) { + this.sessionName = sessionName; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public void setTo(String to) { + this.to = to; + } + + public void setUseSessionLog(boolean useSessionLog) { + this.useSessionLog = useSessionLog; + } + + // @Override + // public boolean equals(Object o) { + // if (o == null || !o.getClass().equals(MediaCubeMarker.class)) + // return false; + // + // + // return true; + // } + +} diff --git a/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeUndoMarker.java b/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeUndoMarker.java new file mode 100644 index 00000000..2b2ffbda --- /dev/null +++ b/server/user.jobengine.log4j/src/user/commons/log4j2/marker/MediaCubeUndoMarker.java @@ -0,0 +1,8 @@ +package user.commons.log4j2.marker; + +@SuppressWarnings("serial") +public class MediaCubeUndoMarker extends MediaCubeMarker { + public MediaCubeUndoMarker(String sessionID) { + setSessionID(sessionID); + } +}