001/* 002 * JGrapes Event Driven Framework 003 * Copyright (C) 2022, 2023 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 Affero 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 Affero General Public 013 * License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along 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.Event; 027import org.jgrapes.core.annotation.Handler; 028import org.jgrapes.io.util.ConnectionManager; 029import org.jgrapes.util.Password; 030import org.jgrapes.util.events.ConfigurationUpdate; 031 032/** 033 * Provides a base class for mail components using connections. 034 * 035 * @param <O> the type of the open event 036 * @param <C> the type of the channel 037 */ 038public abstract class MailConnectionManager< 039 C extends MailConnectionManager<C, O>.AbstractMailChannel, 040 O extends Event<?>> extends ConnectionManager<C> { 041 042 protected final Properties mailProps = new Properties(); 043 private Password password; 044 045 /** 046 * Creates a new server using the given channel. 047 * 048 * @param componentChannel the component's channel 049 */ 050 public MailConnectionManager(Channel componentChannel) { 051 super(componentChannel); 052 } 053 054 /** 055 * Sets the mail properties. See 056 * [the Jakarta Mail](https://jakarta.ee/specifications/mail/2.0/apidocs/jakarta.mail/jakarta/mail/package-summary.html) 057 * documentation for available settings. The given properties are 058 * merged with the already existing properties. 059 * 060 * @param props the props 061 * @return the mail monitor 062 */ 063 public MailConnectionManager<C, O> 064 setMailProperties(Map<String, String> props) { 065 mailProps.putAll(props); 066 return this; 067 } 068 069 /** 070 * Sets the password. 071 * 072 * @param password the new password 073 */ 074 public MailConnectionManager<C, O> setPassword(Password password) { 075 this.password = password; 076 return this; 077 } 078 079 /** 080 * Return the password. 081 * 082 * @return the optional password 083 */ 084 protected Optional<Password> password() { 085 return Optional.ofNullable(password); 086 } 087 088 /** 089 * Configure the component. Attempts to access all paths specified 090 * in the package description in sequence as described in 091 * {@link org.jgrapes.mail}. For each path, merges the 092 * `mail` properties and invokes {@link #configureComponent} 093 * with the available key/value pairs. 094 * 095 * @param event the event 096 */ 097 @Handler 098 @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") 099 public void onConfigUpdate(ConfigurationUpdate event) { 100 for (var path : List.of("/org.jgrapes.mail/Component", 101 "/org.jgrapes.mail/" + getClass().getSimpleName(), 102 "/org_jgrapes_mail/Component", 103 "/org_jgrapes_mail/" + getClass().getSimpleName(), 104 componentPath())) { 105 event.values(path + "/mail").ifPresent(c -> { 106 for (var e : c.entrySet()) { 107 mailProps.put("mail." + e.getKey(), e.getValue()); 108 } 109 }); 110 event.values(path).ifPresent(v -> { 111 Optional.ofNullable(v.get("password")) 112 .ifPresent(p -> setPassword(new Password(p.toCharArray()))); 113 configureComponent(v); 114 }); 115 } 116 } 117 118 /** 119 * Configure the component specific values. 120 * 121 * @param values the values 122 */ 123 protected abstract void configureComponent(Map<String, String> values); 124 125 /** 126 * A sub-channel for mail connections. 127 */ 128 protected abstract class AbstractMailChannel 129 extends ConnectionManager<C>.Connection implements MailChannel { 130 131 private final O openEvent; 132 133 /** 134 * Instantiates a new mail channel instance. 135 * 136 * @param event the main channel 137 */ 138 public AbstractMailChannel(O event, Channel channel) { 139 super(channel); 140 openEvent = event; 141 } 142 143 /** 144 * Returns the event that caused this connection to be opened. 145 * 146 * @return the event 147 */ 148 public O openEvent() { 149 return openEvent; 150 } 151 152 } 153}