You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/07/31 14:49:20 UTC
[1/2] syncope git commit: [SYNCOPE-1180] Allowing more flexible SMTP
configuration, fixing mail debug option, improving docs with examples;
side effect: fixing properties file lookup for Encryptor
Repository: syncope
Updated Branches:
refs/heads/2_0_X 4d7dab2f7 -> e95f373cd
refs/heads/master aa85d9900 -> 7ad5d19b9
[SYNCOPE-1180] Allowing more flexible SMTP configuration, fixing mail debug option, improving docs with examples; side effect: fixing properties file lookup for Encryptor
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/e95f373c
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/e95f373c
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/e95f373c
Branch: refs/heads/2_0_X
Commit: e95f373cd5ba24f3cc0fcef33f920b44ca598dc2
Parents: 4d7dab2
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Jul 31 16:48:59 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Jul 31 16:48:59 2017 +0200
----------------------------------------------------------------------
.../console/SyncopeConsoleApplication.java | 21 +--
.../enduser/SyncopeEnduserApplication.java | 17 +--
.../syncope/common/lib/LogOutputStream.java | 141 +++++++++++++++++++
.../syncope/common/lib/PropertyUtils.java | 64 +++++++++
.../notification/NotificationJobDelegate.java | 50 +++++--
.../src/main/resources/mail.properties | 10 +-
.../src/main/resources/provisioningContext.xml | 7 -
.../syncope/core/spring/security/Encryptor.java | 14 +-
.../src/main/resources/security.properties | 2 +
.../ext/saml2lsp/agent/SAML2SPAgentSetup.java | 19 +--
.../syncope/core/logic/init/SAML2SPLoader.java | 26 +---
.../src/main/resources/log4j2.xml | 10 ++
.../src/main/resources/mail.properties | 10 +-
.../fit/core/NotificationTaskITCase.java | 4 +-
.../emailconfiguration.adoc | 60 +++++++-
15 files changed, 343 insertions(+), 112 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
index 1798dda..bd8ec60 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
@@ -22,8 +22,6 @@ import de.agilecoders.wicket.core.Bootstrap;
import de.agilecoders.wicket.core.settings.BootstrapSettings;
import de.agilecoders.wicket.core.settings.IBootstrapSettings;
import de.agilecoders.wicket.core.settings.SingleThemeProvider;
-import java.io.File;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -35,7 +33,6 @@ import java.util.Map;
import java.util.Properties;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
@@ -53,12 +50,12 @@ import org.apache.syncope.client.console.themes.AdminLTE;
import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.DomainTO;
import org.apache.syncope.common.lib.types.StandardEntitlement;
import org.apache.syncope.common.rest.api.service.DomainService;
import org.apache.wicket.Page;
-import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
@@ -142,20 +139,8 @@ public class SyncopeConsoleApplication extends AuthenticatedWebApplication {
super.init();
// read console.properties
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + CONSOLE_PROPERTIES)) {
- props.load(is);
- File consoleDir = new File(props.getProperty("console.directory"));
- if (consoleDir.exists() && consoleDir.canRead() && consoleDir.isDirectory()) {
- File consoleDirProps = FileUtils.getFile(consoleDir, CONSOLE_PROPERTIES);
- if (consoleDirProps.exists() && consoleDirProps.canRead() && consoleDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(consoleDirProps));
- }
- }
- } catch (Exception e) {
- throw new WicketRuntimeException("Could not read " + CONSOLE_PROPERTIES, e);
- }
+ Properties props = PropertyUtils.read(getClass(), CONSOLE_PROPERTIES, "console.directory").getLeft();
+
version = props.getProperty("version");
Args.notNull(version, "<version>");
site = props.getProperty("site");
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
index fc0d730..5e42000 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
@@ -42,6 +42,7 @@ import org.apache.syncope.client.enduser.init.EnduserInitializer;
import org.apache.syncope.client.enduser.model.CustomAttributesInfo;
import org.apache.syncope.client.enduser.resources.CaptchaResource;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
@@ -99,20 +100,8 @@ public class SyncopeEnduserApplication extends WebApplication implements Seriali
super.init();
// read enduser.properties
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + ENDUSER_PROPERTIES)) {
- props.load(is);
- File enduserDir = new File(props.getProperty("enduser.directory"));
- if (enduserDir.exists() && enduserDir.canRead() && enduserDir.isDirectory()) {
- File enduserDirProps = FileUtils.getFile(enduserDir, ENDUSER_PROPERTIES);
- if (enduserDirProps.exists() && enduserDirProps.canRead() && enduserDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(enduserDirProps));
- }
- }
- } catch (Exception e) {
- throw new WicketRuntimeException("Could not read " + ENDUSER_PROPERTIES, e);
- }
+ Properties props = PropertyUtils.read(getClass(), ENDUSER_PROPERTIES, "enduser.directory").getLeft();
+
version = props.getProperty("version");
Args.notNull(version, "<version>");
site = props.getProperty("site");
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java b/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java
new file mode 100644
index 0000000..5087f95
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java
@@ -0,0 +1,141 @@
+/*
+ * 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 org.apache.syncope.common.lib;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.slf4j.Logger;
+
+/**
+ * Delegates output stream writing onto an SLF4J logger.
+ * Inspired by {@code}org.apache.commons.exec.LogOutputStream{@code}
+ */
+public class LogOutputStream extends OutputStream {
+
+ /** Initial buffer size. */
+ private static final int INTIAL_SIZE = 132;
+
+ /** Carriage return. */
+ private static final int CR = 0x0d;
+
+ /** Linefeed. */
+ private static final int LF = 0x0a;
+
+ /** The internal buffer. */
+ private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(INTIAL_SIZE);
+
+ /**
+ * The delegate logger.
+ */
+ private final Logger logger;
+
+ private boolean skip = false;
+
+ public LogOutputStream(final Logger logger) {
+ this.logger = logger;
+ }
+
+ /**
+ * Write the data to the buffer and flush the buffer, if a line separator is
+ * detected.
+ *
+ * @param cc data to log (byte).
+ * @see java.io.OutputStream#write(int)
+ */
+ @Override
+ public void write(final int cc) {
+ final byte c = (byte) cc;
+ if (c == '\n' || c == '\r') {
+ if (!skip) {
+ processBuffer();
+ }
+ } else {
+ buffer.write(cc);
+ }
+ skip = c == '\r';
+ }
+
+ /**
+ * Flush this log stream.
+ *
+ * @see java.io.OutputStream#flush()
+ */
+ @Override
+ public void flush() {
+ if (buffer.size() > 0) {
+ processBuffer();
+ }
+ }
+
+ /**
+ * Writes all remaining data from the buffer.
+ *
+ * @throws java.io.IOException
+ * @see java.io.OutputStream#close()
+ */
+ @Override
+ public void close() throws IOException {
+ if (buffer.size() > 0) {
+ processBuffer();
+ }
+ super.close();
+ }
+
+ /**
+ * Write a block of characters to the output stream
+ *
+ * @param b the array containing the data
+ * @param off the offset into the array where data starts
+ * @param len the length of block
+ * @see java.io.OutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(final byte[] b, final int off, final int len) {
+ // find the line breaks and pass other chars through in blocks
+ int offset = off;
+ int blockStartOffset = offset;
+ int remaining = len;
+ while (remaining > 0) {
+ while (remaining > 0 && b[offset] != LF && b[offset] != CR) {
+ offset++;
+ remaining--;
+ }
+ // either end of buffer or a line separator char
+ final int blockLength = offset - blockStartOffset;
+ if (blockLength > 0) {
+ buffer.write(b, blockStartOffset, blockLength);
+ }
+ while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) {
+ write(b[offset]);
+ offset++;
+ remaining--;
+ }
+ blockStartOffset = offset;
+ }
+ }
+
+ /**
+ * Converts the buffer to a string and sends it to internal logger.
+ */
+ private void processBuffer() {
+ logger.debug(buffer.toString());
+ buffer.reset();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java b/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java
new file mode 100644
index 0000000..1dd9066
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.apache.syncope.common.lib;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * Utility class for manipulating properties files.
+ */
+public final class PropertyUtils {
+
+ public static Pair<Properties, String> read(
+ final Class<?> clazz, final String propertiesFileName, final String confDirProp) {
+
+ Properties props = new Properties();
+ String confDirName = null;
+
+ try (InputStream is = clazz.getResourceAsStream("/" + propertiesFileName)) {
+ props.load(is);
+
+ confDirName = props.getProperty(confDirProp);
+ if (confDirName != null) {
+ File confDir = new File(confDirName);
+ if (confDir.exists() && confDir.canRead() && confDir.isDirectory()) {
+ File confDirProps = new File(confDir, propertiesFileName);
+ if (confDirProps.exists() && confDirProps.canRead() && confDirProps.isFile()) {
+ props.clear();
+ props.load(new FileInputStream(confDirProps));
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Could not read " + propertiesFileName, e);
+ }
+
+ return Pair.of(props, confDirName);
+ }
+
+ /**
+ * Private default constructor, for static-only classes.
+ */
+ private PropertyUtils() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
index 3ef734b..c019639 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
@@ -18,10 +18,16 @@
*/
package org.apache.syncope.core.provisioning.java.job.notification;
+import java.io.PrintStream;
import java.util.Date;
+import java.util.Enumeration;
import java.util.Properties;
+import javax.mail.Session;
import javax.mail.internet.MimeMessage;
+import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.LogOutputStream;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.lib.types.TraceLevel;
@@ -32,9 +38,11 @@ import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
import org.apache.syncope.core.provisioning.api.AuditManager;
import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
+import org.apache.syncope.core.spring.security.Encryptor;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
@@ -43,7 +51,7 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
-public class NotificationJobDelegate {
+public class NotificationJobDelegate implements InitializingBean {
private static final Logger LOG = LoggerFactory.getLogger(NotificationJobDelegate.class);
@@ -62,24 +70,38 @@ public class NotificationJobDelegate {
@Autowired
private NotificationManager notificationManager;
- private long maxRetries;
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (mailSender instanceof JavaMailSenderImpl) {
+ JavaMailSenderImpl javaMailSender = (JavaMailSenderImpl) mailSender;
- private void init() {
- maxRetries = notificationManager.getMaxRetries();
+ Properties javaMailProperties = javaMailSender.getJavaMailProperties();
- if (mailSender instanceof JavaMailSenderImpl
- && StringUtils.isNotBlank(((JavaMailSenderImpl) mailSender).getUsername())) {
+ Properties props = PropertyUtils.read(Encryptor.class, "mail.properties", "conf.directory").getLeft();
+ for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) {
+ String prop = (String) e.nextElement();
+ if (prop.startsWith("mail.smtp.")) {
+ javaMailProperties.setProperty(prop, props.getProperty(prop));
+ }
+ }
+
+ if (StringUtils.isNotBlank(javaMailSender.getUsername())) {
+ javaMailProperties.setProperty("mail.smtp.auth", "true");
+ }
- Properties javaMailProperties = ((JavaMailSenderImpl) mailSender).getJavaMailProperties();
- javaMailProperties.setProperty("mail.smtp.auth", "true");
- ((JavaMailSenderImpl) mailSender).setJavaMailProperties(javaMailProperties);
+ javaMailSender.setJavaMailProperties(javaMailProperties);
+
+ String mailDebug = props.getProperty("mail.debug", "false");
+ if (BooleanUtils.toBoolean(mailDebug)) {
+ Session session = javaMailSender.getSession();
+ session.setDebug(true);
+ session.setDebugOut(new PrintStream(new LogOutputStream(LOG)));
+ }
}
}
@Transactional
public TaskExec executeSingle(final NotificationTask task) {
- init();
-
TaskExec execution = entityFactory.newEntity(TaskExec.class);
execution.setTask(task);
execution.setStart(new Date());
@@ -216,16 +238,16 @@ public class NotificationJobDelegate {
}
private void handleRetries(final TaskExec execution) {
- if (maxRetries <= 0) {
+ if (notificationManager.getMaxRetries() <= 0) {
return;
}
long failedExecutionsCount = notificationManager.countExecutionsWithStatus(
execution.getTask().getKey(), NotificationJob.Status.NOT_SENT.name());
- if (failedExecutionsCount <= maxRetries) {
+ if (failedExecutionsCount <= notificationManager.getMaxRetries()) {
LOG.debug("Execution of notification task {} will be retried [{}/{}]",
- execution.getTask(), failedExecutionsCount, maxRetries);
+ execution.getTask(), failedExecutionsCount, notificationManager.getMaxRetries());
notificationManager.setTaskExecuted(execution.getTask().getKey(), false);
auditManager.audit(
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/core/provisioning-java/src/main/resources/mail.properties
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/resources/mail.properties b/core/provisioning-java/src/main/resources/mail.properties
index 7a6653e..e0cb1b0 100644
--- a/core/provisioning-java/src/main/resources/mail.properties
+++ b/core/provisioning-java/src/main/resources/mail.properties
@@ -14,11 +14,17 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+conf.directory=${conf.directory}
+
smtpHost=none.syncope.apache.org
smtpPort=25
smtpUser=
smtpPassword=
smtpProtocol=smtp
smtpEncoding=UTF-8
-smtpConnectionTimeout=3000
-mailDebug=false
+mail.debug=false
+
+# Add more properties starting with mail.smtp.* from
+# https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=false
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/core/provisioning-java/src/main/resources/provisioningContext.xml
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/resources/provisioningContext.xml b/core/provisioning-java/src/main/resources/provisioningContext.xml
index fab7099..023d234 100644
--- a/core/provisioning-java/src/main/resources/provisioningContext.xml
+++ b/core/provisioning-java/src/main/resources/provisioningContext.xml
@@ -104,13 +104,6 @@ under the License.
<property name="username" value="${smtpUser}"/>
<property name="password" value="${smtpPassword}"/>
<property name="protocol" value="${smtpProtocol}"/>
-
- <property name="javaMailProperties">
- <props>
- <prop key="mail.smtp.connectiontimeout">${smtpConnectionTimeout}</prop>
- <prop key="mail.debug">${mailDebug}</prop>
- </props>
- </property>
</bean>
<bean class="org.apache.syncope.core.provisioning.java.propagation.PropagationManagerImpl"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
----------------------------------------------------------------------
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
index a97094a..91cf40a 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
@@ -18,7 +18,6 @@
*/
package org.apache.syncope.core.spring.security;
-import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
@@ -31,9 +30,9 @@ import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
import org.jasypt.commons.CommonUtils;
import org.jasypt.digest.StandardStringDigester;
@@ -88,11 +87,8 @@ public final class Encryptor {
private static Boolean ULSSC;
static {
- InputStream propStream = null;
try {
- propStream = Encryptor.class.getResourceAsStream("/security.properties");
- Properties props = new Properties();
- props.load(propStream);
+ Properties props = PropertyUtils.read(Encryptor.class, "security.properties", "conf.directory").getLeft();
SECRET_KEY = props.getProperty("secretKey");
SALT_ITERATIONS = Integer.valueOf(props.getProperty("digester.saltIterations"));
@@ -102,8 +98,6 @@ public final class Encryptor {
ULSSC = Boolean.valueOf(props.getProperty("digester.useLenientSaltSizeCheck"));
} catch (Exception e) {
LOG.error("Could not read security parameters", e);
- } finally {
- IOUtils.closeQuietly(propStream);
}
if (SECRET_KEY == null) {
@@ -160,8 +154,8 @@ public final class Encryptor {
actualKeyPadding.append(randomChars);
actualKey = actualKeyPadding.toString();
LOG.warn("The secret key is too short (< 16), adding some random characters. "
- + "Passwords encrypted with AES and this key will not be recoverable "
- + "as a result if the container is restarted.");
+ + "Passwords encrypted with AES and this key will not be recoverable "
+ + "as a result if the container is restarted.");
}
try {
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/core/spring/src/main/resources/security.properties
----------------------------------------------------------------------
diff --git a/core/spring/src/main/resources/security.properties b/core/spring/src/main/resources/security.properties
index 5c39d1e..2c8b442 100644
--- a/core/spring/src/main/resources/security.properties
+++ b/core/spring/src/main/resources/security.properties
@@ -14,6 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+conf.directory=${conf.directory}
+
adminUser=${adminUser}
adminPassword=${adminPassword}
adminPasswordAlgorithm=SHA1
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
index e42d438..870f4b6 100644
--- a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
+++ b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
@@ -18,16 +18,14 @@
*/
package org.apache.syncope.ext.saml2lsp.agent;
-import java.io.File;
-import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.PropertyUtils;
@WebListener
public class SAML2SPAgentSetup implements ServletContextListener {
@@ -44,20 +42,7 @@ public class SAML2SPAgentSetup implements ServletContextListener {
@Override
public void contextInitialized(final ServletContextEvent sce) {
// read saml2spagent.properties
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + SAML2SP_AGENT_PROPERTIES)) {
- props.load(is);
- File confDir = new File(props.getProperty("conf.directory"));
- if (confDir.exists() && confDir.canRead() && confDir.isDirectory()) {
- File consoleDirProps = FileUtils.getFile(confDir, SAML2SP_AGENT_PROPERTIES);
- if (consoleDirProps.exists() && consoleDirProps.canRead() && consoleDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(consoleDirProps));
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("Could not read " + SAML2SP_AGENT_PROPERTIES, e);
- }
+ Properties props = PropertyUtils.read(getClass(), SAML2SP_AGENT_PROPERTIES, "conf.directory").getLeft();
String anonymousUser = props.getProperty("anonymousUser");
assertNotNull(anonymousUser, "<anonymousUser>");
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
index f9a5eec..a4230b2 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
@@ -18,15 +18,15 @@
*/
package org.apache.syncope.core.logic.init;
-import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.core.persistence.api.SyncopeLoader;
import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
import org.apache.syncope.common.lib.types.SAML2SPEntitlement;
@@ -80,25 +80,9 @@ public class SAML2SPLoader implements SyncopeLoader {
public void load() {
EntitlementsHolder.getInstance().init(SAML2SPEntitlement.values());
- String confDirectory = null;
-
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + SAML2SP_LOGIC_PROPERTIES)) {
- props.load(is);
- confDirectory = props.getProperty("conf.directory");
-
- File confDir = new File(confDirectory);
- if (confDir.exists() && confDir.canRead() && confDir.isDirectory()) {
- File confDirProps = FileUtils.getFile(confDir, SAML2SP_LOGIC_PROPERTIES);
- if (confDirProps.exists() && confDirProps.canRead() && confDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(confDirProps));
- confDirectory = props.getProperty("conf.directory");
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("Could not read " + SAML2SP_LOGIC_PROPERTIES, e);
- }
+ Pair<Properties, String> init = PropertyUtils.read(getClass(), SAML2SP_LOGIC_PROPERTIES, "conf.directory");
+ Properties props = init.getLeft();
+ String confDirectory = init.getRight();
assertNotNull(confDirectory, "<conf.directory>");
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/fit/core-reference/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/log4j2.xml b/fit/core-reference/src/main/resources/log4j2.xml
index 4c9684f..5dde70c 100644
--- a/fit/core-reference/src/main/resources/log4j2.xml
+++ b/fit/core-reference/src/main/resources/log4j2.xml
@@ -189,6 +189,16 @@ under the License.
<appender-ref ref="main"/>
</asyncLogger>
+ <!-- To enable when setting 'mail.debug=true' in mail.properties -->
+ <!--<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification" additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+ </asyncLogger>
+ <asyncLogger name="javax.mail" additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+ </asyncLogger>-->
+
<root level="INFO">
<appender-ref ref="mainFile"/>
<appender-ref ref="main"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/fit/core-reference/src/main/resources/mail.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/mail.properties b/fit/core-reference/src/main/resources/mail.properties
index e8b9a5f..f8e1c05 100644
--- a/fit/core-reference/src/main/resources/mail.properties
+++ b/fit/core-reference/src/main/resources/mail.properties
@@ -14,11 +14,17 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+conf.directory=${conf.directory}
+
smtpHost=localhost
smtpPort=2525
smtpUser=
smtpPassword=
smtpProtocol=smtp
smtpEncoding=UTF-8
-smtpConnectionTimeout=3000
-mailDebug=false
+mail.debug=false
+
+# Add more properties starting with mail.smtp.* from
+# https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=false
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
index 2f568b5..a4ca1f4 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
@@ -103,7 +103,7 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
NotificationTaskTO taskTO = findNotificationTask(created.getLeft(), 50);
assertNotNull(taskTO);
assertNotNull(taskTO.getNotification());
- assertTrue(taskTO.getExecutions().isEmpty());
+ int preExecs = taskTO.getExecutions().size();
// 4. verify notification could not be delivered
execTask(taskService, taskTO.getKey(), NotificationJob.Status.NOT_SENT.name(), 5, false);
@@ -111,7 +111,7 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
taskTO = taskService.read(taskTO.getKey(), true);
assertNotNull(taskTO);
assertFalse(taskTO.isExecuted());
- assertFalse(taskTO.getExecutions().isEmpty());
+ assertTrue(preExecs <= taskTO.getExecutions().size());
for (ExecTO exec : taskTO.getExecutions()) {
assertEquals(NotificationJob.Status.NOT_SENT.name(), exec.getStatus());
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/e95f373c/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
index 6863f6d..9787dc3 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
@@ -18,8 +18,8 @@
//
==== E-mail Configuration
-The `mail.properties` holds the configuration options to enable the effective delivery of <<notifications,notification>>
-e-mails:
+The `mail.properties` file holds the configuration options to enable the effective delivery of
+<<notifications,notification>> e-mails:
* `smtpHost` - the mail server host, typically an SMTP host;
* `smtpPort` - the mail server port;
@@ -27,9 +27,59 @@ e-mails:
* `smtpPassword` - (optional) the password for the account at the mail host;
* `smtpProtocol` - the mail protocol;
* `smtpEncoding` - the default encoding to use for MIME messages;
-* `smtpConnectionTimeout` - the connection timeout value in milliseconds, to the mail host;
-* `mailDebug` - when `true`, enable the debugging of email, including the handshake, authentication, delivery and
-disconnection.
+* `mail.smtp.starttls.enable` - when `true`, enable the use of the `STARTTLS` command to switch the connection to a
+TLS-protected connection before issuing any login commands;
+* `mail.smtp.connectiontimeout` - the connection timeout value in milliseconds, to the mail host;
+* `mail.debug` - when `true`, enable the debugging of email processing including the handshake, authentication, delivery
+ and disconnection; in order for this setting to be effective, it is also required to add the following elements to the
+`log4j2.xml` configuration file:
+[source,xml]
+<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification"
+ additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+</asyncLogger>
+<asyncLogger name="javax.mail" additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+</asyncLogger>
+
+All the https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties[JavaMail(TM) properties^]
+are available for usage.
+
+.Basic configuration, no authentication
+====
+....
+conf.directory=${conf.directory}
+
+smtpHost=your.local.smtp.server
+smtpPort=25
+smtpUser=
+smtpPassword=
+smtpProtocol=smtp
+smtpEncoding=UTF-8
+mail.debug=false
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=false
+....
+====
+
+.STARTTLS configuration, with authentication
+====
+....
+conf.directory=${conf.directory}
+
+smtpHost=smtp.gmail.com
+smtpPort=587
+smtpUser=your_username@gmail.com
+smtpPassword=your_password
+smtpProtocol=smtp
+smtpEncoding=UTF-8
+mail.debug=false
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=true
+....
+====
[NOTE]
In order to make the changes to `mail.properties` effective, the Java EE container needs to be restarted.
[2/2] syncope git commit: [SYNCOPE-1180] Allowing more flexible SMTP
configuration, fixing mail debug option, improving docs with examples;
side effect: fixing properties file lookup for Encryptor
Posted by il...@apache.org.
[SYNCOPE-1180] Allowing more flexible SMTP configuration, fixing mail debug option, improving docs with examples; side effect: fixing properties file lookup for Encryptor
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/7ad5d19b
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/7ad5d19b
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/7ad5d19b
Branch: refs/heads/master
Commit: 7ad5d19b91e01544f076b980c1b26deae0184a79
Parents: aa85d99
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Mon Jul 31 16:48:59 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Mon Jul 31 16:49:10 2017 +0200
----------------------------------------------------------------------
.../console/SyncopeConsoleApplication.java | 21 +--
.../enduser/SyncopeEnduserApplication.java | 17 +--
.../syncope/common/lib/LogOutputStream.java | 141 +++++++++++++++++++
.../syncope/common/lib/PropertyUtils.java | 64 +++++++++
.../notification/NotificationJobDelegate.java | 50 +++++--
.../src/main/resources/mail.properties | 10 +-
.../src/main/resources/provisioningContext.xml | 7 -
.../syncope/core/spring/security/Encryptor.java | 14 +-
.../src/main/resources/security.properties | 2 +
.../ext/saml2lsp/agent/SAML2SPAgentSetup.java | 19 +--
.../syncope/core/logic/init/SAML2SPLoader.java | 26 +---
.../src/main/resources/log4j2.xml | 10 ++
.../src/main/resources/mail.properties | 10 +-
.../fit/core/NotificationTaskITCase.java | 4 +-
.../emailconfiguration.adoc | 60 +++++++-
15 files changed, 343 insertions(+), 112 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
index 4c44802..427e364 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleApplication.java
@@ -22,8 +22,6 @@ import de.agilecoders.wicket.core.Bootstrap;
import de.agilecoders.wicket.core.settings.BootstrapSettings;
import de.agilecoders.wicket.core.settings.IBootstrapSettings;
import de.agilecoders.wicket.core.settings.SingleThemeProvider;
-import java.io.File;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -35,7 +33,6 @@ import java.util.Map;
import java.util.Properties;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
@@ -52,12 +49,12 @@ import org.apache.syncope.client.console.themes.AdminLTE;
import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.to.DomainTO;
import org.apache.syncope.common.lib.types.StandardEntitlement;
import org.apache.syncope.common.rest.api.service.DomainService;
import org.apache.wicket.Page;
-import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.authroles.authentication.AbstractAuthenticatedWebSession;
import org.apache.wicket.authroles.authentication.AuthenticatedWebApplication;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
@@ -141,20 +138,8 @@ public class SyncopeConsoleApplication extends AuthenticatedWebApplication {
super.init();
// read console.properties
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + CONSOLE_PROPERTIES)) {
- props.load(is);
- File consoleDir = new File(props.getProperty("console.directory"));
- if (consoleDir.exists() && consoleDir.canRead() && consoleDir.isDirectory()) {
- File consoleDirProps = FileUtils.getFile(consoleDir, CONSOLE_PROPERTIES);
- if (consoleDirProps.exists() && consoleDirProps.canRead() && consoleDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(consoleDirProps));
- }
- }
- } catch (Exception e) {
- throw new WicketRuntimeException("Could not read " + CONSOLE_PROPERTIES, e);
- }
+ Properties props = PropertyUtils.read(getClass(), CONSOLE_PROPERTIES, "console.directory").getLeft();
+
version = props.getProperty("version");
Args.notNull(version, "<version>");
site = props.getProperty("site");
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
index fc0d730..5e42000 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserApplication.java
@@ -42,6 +42,7 @@ import org.apache.syncope.client.enduser.init.EnduserInitializer;
import org.apache.syncope.client.enduser.model.CustomAttributesInfo;
import org.apache.syncope.client.enduser.resources.CaptchaResource;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
@@ -99,20 +100,8 @@ public class SyncopeEnduserApplication extends WebApplication implements Seriali
super.init();
// read enduser.properties
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + ENDUSER_PROPERTIES)) {
- props.load(is);
- File enduserDir = new File(props.getProperty("enduser.directory"));
- if (enduserDir.exists() && enduserDir.canRead() && enduserDir.isDirectory()) {
- File enduserDirProps = FileUtils.getFile(enduserDir, ENDUSER_PROPERTIES);
- if (enduserDirProps.exists() && enduserDirProps.canRead() && enduserDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(enduserDirProps));
- }
- }
- } catch (Exception e) {
- throw new WicketRuntimeException("Could not read " + ENDUSER_PROPERTIES, e);
- }
+ Properties props = PropertyUtils.read(getClass(), ENDUSER_PROPERTIES, "enduser.directory").getLeft();
+
version = props.getProperty("version");
Args.notNull(version, "<version>");
site = props.getProperty("site");
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java b/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java
new file mode 100644
index 0000000..5087f95
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/LogOutputStream.java
@@ -0,0 +1,141 @@
+/*
+ * 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 org.apache.syncope.common.lib;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.slf4j.Logger;
+
+/**
+ * Delegates output stream writing onto an SLF4J logger.
+ * Inspired by {@code}org.apache.commons.exec.LogOutputStream{@code}
+ */
+public class LogOutputStream extends OutputStream {
+
+ /** Initial buffer size. */
+ private static final int INTIAL_SIZE = 132;
+
+ /** Carriage return. */
+ private static final int CR = 0x0d;
+
+ /** Linefeed. */
+ private static final int LF = 0x0a;
+
+ /** The internal buffer. */
+ private final ByteArrayOutputStream buffer = new ByteArrayOutputStream(INTIAL_SIZE);
+
+ /**
+ * The delegate logger.
+ */
+ private final Logger logger;
+
+ private boolean skip = false;
+
+ public LogOutputStream(final Logger logger) {
+ this.logger = logger;
+ }
+
+ /**
+ * Write the data to the buffer and flush the buffer, if a line separator is
+ * detected.
+ *
+ * @param cc data to log (byte).
+ * @see java.io.OutputStream#write(int)
+ */
+ @Override
+ public void write(final int cc) {
+ final byte c = (byte) cc;
+ if (c == '\n' || c == '\r') {
+ if (!skip) {
+ processBuffer();
+ }
+ } else {
+ buffer.write(cc);
+ }
+ skip = c == '\r';
+ }
+
+ /**
+ * Flush this log stream.
+ *
+ * @see java.io.OutputStream#flush()
+ */
+ @Override
+ public void flush() {
+ if (buffer.size() > 0) {
+ processBuffer();
+ }
+ }
+
+ /**
+ * Writes all remaining data from the buffer.
+ *
+ * @throws java.io.IOException
+ * @see java.io.OutputStream#close()
+ */
+ @Override
+ public void close() throws IOException {
+ if (buffer.size() > 0) {
+ processBuffer();
+ }
+ super.close();
+ }
+
+ /**
+ * Write a block of characters to the output stream
+ *
+ * @param b the array containing the data
+ * @param off the offset into the array where data starts
+ * @param len the length of block
+ * @see java.io.OutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(final byte[] b, final int off, final int len) {
+ // find the line breaks and pass other chars through in blocks
+ int offset = off;
+ int blockStartOffset = offset;
+ int remaining = len;
+ while (remaining > 0) {
+ while (remaining > 0 && b[offset] != LF && b[offset] != CR) {
+ offset++;
+ remaining--;
+ }
+ // either end of buffer or a line separator char
+ final int blockLength = offset - blockStartOffset;
+ if (blockLength > 0) {
+ buffer.write(b, blockStartOffset, blockLength);
+ }
+ while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) {
+ write(b[offset]);
+ offset++;
+ remaining--;
+ }
+ blockStartOffset = offset;
+ }
+ }
+
+ /**
+ * Converts the buffer to a string and sends it to internal logger.
+ */
+ private void processBuffer() {
+ logger.debug(buffer.toString());
+ buffer.reset();
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java b/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java
new file mode 100644
index 0000000..1dd9066
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/PropertyUtils.java
@@ -0,0 +1,64 @@
+/*
+ * 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 org.apache.syncope.common.lib;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Properties;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * Utility class for manipulating properties files.
+ */
+public final class PropertyUtils {
+
+ public static Pair<Properties, String> read(
+ final Class<?> clazz, final String propertiesFileName, final String confDirProp) {
+
+ Properties props = new Properties();
+ String confDirName = null;
+
+ try (InputStream is = clazz.getResourceAsStream("/" + propertiesFileName)) {
+ props.load(is);
+
+ confDirName = props.getProperty(confDirProp);
+ if (confDirName != null) {
+ File confDir = new File(confDirName);
+ if (confDir.exists() && confDir.canRead() && confDir.isDirectory()) {
+ File confDirProps = new File(confDir, propertiesFileName);
+ if (confDirProps.exists() && confDirProps.canRead() && confDirProps.isFile()) {
+ props.clear();
+ props.load(new FileInputStream(confDirProps));
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Could not read " + propertiesFileName, e);
+ }
+
+ return Pair.of(props, confDirName);
+ }
+
+ /**
+ * Private default constructor, for static-only classes.
+ */
+ private PropertyUtils() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
index 3ef734b..c019639 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/notification/NotificationJobDelegate.java
@@ -18,10 +18,16 @@
*/
package org.apache.syncope.core.provisioning.java.job.notification;
+import java.io.PrintStream;
import java.util.Date;
+import java.util.Enumeration;
import java.util.Properties;
+import javax.mail.Session;
import javax.mail.internet.MimeMessage;
+import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.LogOutputStream;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.lib.types.TraceLevel;
@@ -32,9 +38,11 @@ import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
import org.apache.syncope.core.provisioning.api.AuditManager;
import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
+import org.apache.syncope.core.spring.security.Encryptor;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
@@ -43,7 +51,7 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
-public class NotificationJobDelegate {
+public class NotificationJobDelegate implements InitializingBean {
private static final Logger LOG = LoggerFactory.getLogger(NotificationJobDelegate.class);
@@ -62,24 +70,38 @@ public class NotificationJobDelegate {
@Autowired
private NotificationManager notificationManager;
- private long maxRetries;
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (mailSender instanceof JavaMailSenderImpl) {
+ JavaMailSenderImpl javaMailSender = (JavaMailSenderImpl) mailSender;
- private void init() {
- maxRetries = notificationManager.getMaxRetries();
+ Properties javaMailProperties = javaMailSender.getJavaMailProperties();
- if (mailSender instanceof JavaMailSenderImpl
- && StringUtils.isNotBlank(((JavaMailSenderImpl) mailSender).getUsername())) {
+ Properties props = PropertyUtils.read(Encryptor.class, "mail.properties", "conf.directory").getLeft();
+ for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) {
+ String prop = (String) e.nextElement();
+ if (prop.startsWith("mail.smtp.")) {
+ javaMailProperties.setProperty(prop, props.getProperty(prop));
+ }
+ }
+
+ if (StringUtils.isNotBlank(javaMailSender.getUsername())) {
+ javaMailProperties.setProperty("mail.smtp.auth", "true");
+ }
- Properties javaMailProperties = ((JavaMailSenderImpl) mailSender).getJavaMailProperties();
- javaMailProperties.setProperty("mail.smtp.auth", "true");
- ((JavaMailSenderImpl) mailSender).setJavaMailProperties(javaMailProperties);
+ javaMailSender.setJavaMailProperties(javaMailProperties);
+
+ String mailDebug = props.getProperty("mail.debug", "false");
+ if (BooleanUtils.toBoolean(mailDebug)) {
+ Session session = javaMailSender.getSession();
+ session.setDebug(true);
+ session.setDebugOut(new PrintStream(new LogOutputStream(LOG)));
+ }
}
}
@Transactional
public TaskExec executeSingle(final NotificationTask task) {
- init();
-
TaskExec execution = entityFactory.newEntity(TaskExec.class);
execution.setTask(task);
execution.setStart(new Date());
@@ -216,16 +238,16 @@ public class NotificationJobDelegate {
}
private void handleRetries(final TaskExec execution) {
- if (maxRetries <= 0) {
+ if (notificationManager.getMaxRetries() <= 0) {
return;
}
long failedExecutionsCount = notificationManager.countExecutionsWithStatus(
execution.getTask().getKey(), NotificationJob.Status.NOT_SENT.name());
- if (failedExecutionsCount <= maxRetries) {
+ if (failedExecutionsCount <= notificationManager.getMaxRetries()) {
LOG.debug("Execution of notification task {} will be retried [{}/{}]",
- execution.getTask(), failedExecutionsCount, maxRetries);
+ execution.getTask(), failedExecutionsCount, notificationManager.getMaxRetries());
notificationManager.setTaskExecuted(execution.getTask().getKey(), false);
auditManager.audit(
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/core/provisioning-java/src/main/resources/mail.properties
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/resources/mail.properties b/core/provisioning-java/src/main/resources/mail.properties
index 7a6653e..e0cb1b0 100644
--- a/core/provisioning-java/src/main/resources/mail.properties
+++ b/core/provisioning-java/src/main/resources/mail.properties
@@ -14,11 +14,17 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+conf.directory=${conf.directory}
+
smtpHost=none.syncope.apache.org
smtpPort=25
smtpUser=
smtpPassword=
smtpProtocol=smtp
smtpEncoding=UTF-8
-smtpConnectionTimeout=3000
-mailDebug=false
+mail.debug=false
+
+# Add more properties starting with mail.smtp.* from
+# https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=false
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/core/provisioning-java/src/main/resources/provisioningContext.xml
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/resources/provisioningContext.xml b/core/provisioning-java/src/main/resources/provisioningContext.xml
index fab7099..023d234 100644
--- a/core/provisioning-java/src/main/resources/provisioningContext.xml
+++ b/core/provisioning-java/src/main/resources/provisioningContext.xml
@@ -104,13 +104,6 @@ under the License.
<property name="username" value="${smtpUser}"/>
<property name="password" value="${smtpPassword}"/>
<property name="protocol" value="${smtpProtocol}"/>
-
- <property name="javaMailProperties">
- <props>
- <prop key="mail.smtp.connectiontimeout">${smtpConnectionTimeout}</prop>
- <prop key="mail.debug">${mailDebug}</prop>
- </props>
- </property>
</bean>
<bean class="org.apache.syncope.core.provisioning.java.propagation.PropagationManagerImpl"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
----------------------------------------------------------------------
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
index a97094a..91cf40a 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/Encryptor.java
@@ -18,7 +18,6 @@
*/
package org.apache.syncope.core.spring.security;
-import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
@@ -31,9 +30,9 @@ import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.common.lib.types.CipherAlgorithm;
import org.jasypt.commons.CommonUtils;
import org.jasypt.digest.StandardStringDigester;
@@ -88,11 +87,8 @@ public final class Encryptor {
private static Boolean ULSSC;
static {
- InputStream propStream = null;
try {
- propStream = Encryptor.class.getResourceAsStream("/security.properties");
- Properties props = new Properties();
- props.load(propStream);
+ Properties props = PropertyUtils.read(Encryptor.class, "security.properties", "conf.directory").getLeft();
SECRET_KEY = props.getProperty("secretKey");
SALT_ITERATIONS = Integer.valueOf(props.getProperty("digester.saltIterations"));
@@ -102,8 +98,6 @@ public final class Encryptor {
ULSSC = Boolean.valueOf(props.getProperty("digester.useLenientSaltSizeCheck"));
} catch (Exception e) {
LOG.error("Could not read security parameters", e);
- } finally {
- IOUtils.closeQuietly(propStream);
}
if (SECRET_KEY == null) {
@@ -160,8 +154,8 @@ public final class Encryptor {
actualKeyPadding.append(randomChars);
actualKey = actualKeyPadding.toString();
LOG.warn("The secret key is too short (< 16), adding some random characters. "
- + "Passwords encrypted with AES and this key will not be recoverable "
- + "as a result if the container is restarted.");
+ + "Passwords encrypted with AES and this key will not be recoverable "
+ + "as a result if the container is restarted.");
}
try {
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/core/spring/src/main/resources/security.properties
----------------------------------------------------------------------
diff --git a/core/spring/src/main/resources/security.properties b/core/spring/src/main/resources/security.properties
index 3f72ad0..870d853 100644
--- a/core/spring/src/main/resources/security.properties
+++ b/core/spring/src/main/resources/security.properties
@@ -14,6 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+conf.directory=${conf.directory}
+
adminUser=${adminUser}
adminPassword=${adminPassword}
adminPasswordAlgorithm=SSHA256
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
index e42d438..870f4b6 100644
--- a/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
+++ b/ext/saml2sp/agent/src/main/java/org/apache/syncope/ext/saml2lsp/agent/SAML2SPAgentSetup.java
@@ -18,16 +18,14 @@
*/
package org.apache.syncope.ext.saml2lsp.agent;
-import java.io.File;
-import java.io.InputStream;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.lib.PropertyUtils;
@WebListener
public class SAML2SPAgentSetup implements ServletContextListener {
@@ -44,20 +42,7 @@ public class SAML2SPAgentSetup implements ServletContextListener {
@Override
public void contextInitialized(final ServletContextEvent sce) {
// read saml2spagent.properties
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + SAML2SP_AGENT_PROPERTIES)) {
- props.load(is);
- File confDir = new File(props.getProperty("conf.directory"));
- if (confDir.exists() && confDir.canRead() && confDir.isDirectory()) {
- File consoleDirProps = FileUtils.getFile(confDir, SAML2SP_AGENT_PROPERTIES);
- if (consoleDirProps.exists() && consoleDirProps.canRead() && consoleDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(consoleDirProps));
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("Could not read " + SAML2SP_AGENT_PROPERTIES, e);
- }
+ Properties props = PropertyUtils.read(getClass(), SAML2SP_AGENT_PROPERTIES, "conf.directory").getLeft();
String anonymousUser = props.getProperty("anonymousUser");
assertNotNull(anonymousUser, "<anonymousUser>");
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
----------------------------------------------------------------------
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
index f9a5eec..a4230b2 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
@@ -18,15 +18,15 @@
*/
package org.apache.syncope.core.logic.init;
-import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.PropertyUtils;
import org.apache.syncope.core.persistence.api.SyncopeLoader;
import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
import org.apache.syncope.common.lib.types.SAML2SPEntitlement;
@@ -80,25 +80,9 @@ public class SAML2SPLoader implements SyncopeLoader {
public void load() {
EntitlementsHolder.getInstance().init(SAML2SPEntitlement.values());
- String confDirectory = null;
-
- Properties props = new Properties();
- try (InputStream is = getClass().getResourceAsStream("/" + SAML2SP_LOGIC_PROPERTIES)) {
- props.load(is);
- confDirectory = props.getProperty("conf.directory");
-
- File confDir = new File(confDirectory);
- if (confDir.exists() && confDir.canRead() && confDir.isDirectory()) {
- File confDirProps = FileUtils.getFile(confDir, SAML2SP_LOGIC_PROPERTIES);
- if (confDirProps.exists() && confDirProps.canRead() && confDirProps.isFile()) {
- props.clear();
- props.load(FileUtils.openInputStream(confDirProps));
- confDirectory = props.getProperty("conf.directory");
- }
- }
- } catch (Exception e) {
- throw new RuntimeException("Could not read " + SAML2SP_LOGIC_PROPERTIES, e);
- }
+ Pair<Properties, String> init = PropertyUtils.read(getClass(), SAML2SP_LOGIC_PROPERTIES, "conf.directory");
+ Properties props = init.getLeft();
+ String confDirectory = init.getRight();
assertNotNull(confDirectory, "<conf.directory>");
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/fit/core-reference/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/log4j2.xml b/fit/core-reference/src/main/resources/log4j2.xml
index 4c9684f..5dde70c 100644
--- a/fit/core-reference/src/main/resources/log4j2.xml
+++ b/fit/core-reference/src/main/resources/log4j2.xml
@@ -189,6 +189,16 @@ under the License.
<appender-ref ref="main"/>
</asyncLogger>
+ <!-- To enable when setting 'mail.debug=true' in mail.properties -->
+ <!--<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification" additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+ </asyncLogger>
+ <asyncLogger name="javax.mail" additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+ </asyncLogger>-->
+
<root level="INFO">
<appender-ref ref="mainFile"/>
<appender-ref ref="main"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/fit/core-reference/src/main/resources/mail.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/mail.properties b/fit/core-reference/src/main/resources/mail.properties
index e8b9a5f..f8e1c05 100644
--- a/fit/core-reference/src/main/resources/mail.properties
+++ b/fit/core-reference/src/main/resources/mail.properties
@@ -14,11 +14,17 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+conf.directory=${conf.directory}
+
smtpHost=localhost
smtpPort=2525
smtpUser=
smtpPassword=
smtpProtocol=smtp
smtpEncoding=UTF-8
-smtpConnectionTimeout=3000
-mailDebug=false
+mail.debug=false
+
+# Add more properties starting with mail.smtp.* from
+# https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=false
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
index 2f568b5..a4ca1f4 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
@@ -103,7 +103,7 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
NotificationTaskTO taskTO = findNotificationTask(created.getLeft(), 50);
assertNotNull(taskTO);
assertNotNull(taskTO.getNotification());
- assertTrue(taskTO.getExecutions().isEmpty());
+ int preExecs = taskTO.getExecutions().size();
// 4. verify notification could not be delivered
execTask(taskService, taskTO.getKey(), NotificationJob.Status.NOT_SENT.name(), 5, false);
@@ -111,7 +111,7 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
taskTO = taskService.read(taskTO.getKey(), true);
assertNotNull(taskTO);
assertFalse(taskTO.isExecuted());
- assertFalse(taskTO.getExecutions().isEmpty());
+ assertTrue(preExecs <= taskTO.getExecutions().size());
for (ExecTO exec : taskTO.getExecutions()) {
assertEquals(NotificationJob.Status.NOT_SENT.name(), exec.getStatus());
}
http://git-wip-us.apache.org/repos/asf/syncope/blob/7ad5d19b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
----------------------------------------------------------------------
diff --git a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
index 6863f6d..9787dc3 100644
--- a/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
+++ b/src/main/asciidoc/reference-guide/workingwithapachesyncope/systemadministration/emailconfiguration.adoc
@@ -18,8 +18,8 @@
//
==== E-mail Configuration
-The `mail.properties` holds the configuration options to enable the effective delivery of <<notifications,notification>>
-e-mails:
+The `mail.properties` file holds the configuration options to enable the effective delivery of
+<<notifications,notification>> e-mails:
* `smtpHost` - the mail server host, typically an SMTP host;
* `smtpPort` - the mail server port;
@@ -27,9 +27,59 @@ e-mails:
* `smtpPassword` - (optional) the password for the account at the mail host;
* `smtpProtocol` - the mail protocol;
* `smtpEncoding` - the default encoding to use for MIME messages;
-* `smtpConnectionTimeout` - the connection timeout value in milliseconds, to the mail host;
-* `mailDebug` - when `true`, enable the debugging of email, including the handshake, authentication, delivery and
-disconnection.
+* `mail.smtp.starttls.enable` - when `true`, enable the use of the `STARTTLS` command to switch the connection to a
+TLS-protected connection before issuing any login commands;
+* `mail.smtp.connectiontimeout` - the connection timeout value in milliseconds, to the mail host;
+* `mail.debug` - when `true`, enable the debugging of email processing including the handshake, authentication, delivery
+ and disconnection; in order for this setting to be effective, it is also required to add the following elements to the
+`log4j2.xml` configuration file:
+[source,xml]
+<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification"
+ additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+</asyncLogger>
+<asyncLogger name="javax.mail" additivity="false" level="DEBUG">
+ <appender-ref ref="mainFile"/>
+ <appender-ref ref="main"/>
+</asyncLogger>
+
+All the https://javaee.github.io/javamail/docs/api/com/sun/mail/smtp/package-summary.html#properties[JavaMail(TM) properties^]
+are available for usage.
+
+.Basic configuration, no authentication
+====
+....
+conf.directory=${conf.directory}
+
+smtpHost=your.local.smtp.server
+smtpPort=25
+smtpUser=
+smtpPassword=
+smtpProtocol=smtp
+smtpEncoding=UTF-8
+mail.debug=false
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=false
+....
+====
+
+.STARTTLS configuration, with authentication
+====
+....
+conf.directory=${conf.directory}
+
+smtpHost=smtp.gmail.com
+smtpPort=587
+smtpUser=your_username@gmail.com
+smtpPassword=your_password
+smtpProtocol=smtp
+smtpEncoding=UTF-8
+mail.debug=false
+mail.smtp.connectiontimeout=3000
+mail.smtp.starttls.enable=true
+....
+====
[NOTE]
In order to make the changes to `mail.properties` effective, the Java EE container needs to be restarted.