001/* 002 * JGrapes Event Driven Framework 003 * Copyright (C) 2022 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License as published by 007 * the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jgrapes.mail; 020 021import java.util.List; 022import java.util.Map; 023import java.util.Optional; 024import java.util.Properties; 025import org.jgrapes.core.Channel; 026import org.jgrapes.core.Component; 027import org.jgrapes.core.Components; 028import org.jgrapes.core.Event; 029import org.jgrapes.core.Manager; 030import org.jgrapes.core.annotation.Handler; 031import org.jgrapes.core.annotation.HandlerDefinition.ChannelReplacements; 032import org.jgrapes.util.Password; 033import org.jgrapes.util.events.ConfigurationUpdate; 034 035/** 036 * A base class for mail handling components. 037 */ 038public abstract class MailComponent extends Component { 039 040 protected final Properties mailProps = new Properties(); 041 private Password password; 042 043 /** 044 * Creates a new component with its channel set to itself. 045 */ 046 public MailComponent() { 047 // Nothing to do. 048 } 049 050 /** 051 * Creates a new component base with its channel set to the given 052 * channel. As a special case {@link Channel#SELF} can be 053 * passed to the constructor to make the component use itself 054 * as channel. The special value is necessary as you 055 * obviously cannot pass an object to be constructed to its 056 * constructor. 057 * 058 * @param componentChannel the channel that the component's 059 * handlers listen on by default and that 060 * {@link Manager#fire(Event, Channel...)} sends the event to 061 */ 062 public MailComponent(Channel componentChannel) { 063 super(componentChannel); 064 } 065 066 /** 067 * Creates a new component base like {@link #MailComponent(Channel)} 068 * but with channel mappings for {@link Handler} annotations. 069 * 070 * @param componentChannel the channel that the component's 071 * handlers listen on by default and that 072 * {@link Manager#fire(Event, Channel...)} sends the event to 073 * @param channelReplacements the channel replacements to apply 074 * to the `channels` elements of the {@link Handler} annotations 075 */ 076 public MailComponent(Channel componentChannel, 077 ChannelReplacements channelReplacements) { 078 super(componentChannel, channelReplacements); 079 } 080 081 /** 082 * Sets the mail properties. See 083 * [the Jakarta Mail](https://jakarta.ee/specifications/mail/2.0/apidocs/jakarta.mail/jakarta/mail/package-summary.html) 084 * documentation for available settings. The given properties are 085 * merged with the already existing properties. 086 * 087 * @param props the props 088 * @return the mail monitor 089 */ 090 public MailComponent setMailProperties(Map<String, String> props) { 091 mailProps.putAll(props); 092 return this; 093 } 094 095 /** 096 * Sets the password. 097 * 098 * @param password the new password 099 */ 100 public MailComponent setPassword(Password password) { 101 this.password = password; 102 return this; 103 } 104 105 /** 106 * Return the password. 107 * 108 * @return the optional password 109 */ 110 protected Optional<Password> password() { 111 return Optional.ofNullable(password); 112 } 113 114 /** 115 * Configure the component. Attempts to access all paths specified 116 * in the package description in sequence as described in 117 * {@link org.jgrapes.mail}. For each path, merges the 118 * `mail` properties and invokes {@link #configureComponent} 119 * with the available key/value pairs. 120 * 121 * @param event the event 122 */ 123 @Handler 124 @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") 125 public void onConfigUpdate(ConfigurationUpdate event) { 126 for (var path : List.of("/org.jgrapes.mail/Component", 127 "/org.jgrapes.mail/" + getClass().getSimpleName(), 128 "/org_jgrapes_mail/Component", 129 "/org_jgrapes_mail/" + getClass().getSimpleName(), 130 componentPath())) { 131 event.values(path + "/mail").ifPresent(c -> { 132 for (var e : c.entrySet()) { 133 mailProps.put("mail." + e.getKey(), e.getValue()); 134 } 135 }); 136 event.values(path).ifPresent(v -> { 137 Optional.ofNullable(v.get("password")) 138 .ifPresent(p -> setPassword(new Password(p.toCharArray()))); 139 configureComponent(v); 140 }); 141 } 142 } 143 144 /** 145 * Configure the component specific values. 146 * 147 * @param values the values 148 */ 149 protected abstract void configureComponent(Map<String, String> values); 150 151 /* 152 * (non-Javadoc) 153 * 154 * @see java.lang.Object#toString() 155 */ 156 @Override 157 public String toString() { 158 return Components.objectName(this); 159 } 160}