{
11 | String defaultMessage;
12 |
13 | public void initialize(MatchSymbolPrefix constraintAnnotation) {
14 | defaultMessage = constraintAnnotation.message();
15 | }
16 |
17 | public boolean isValid(Datacentre datacentre, ConstraintValidatorContext context) {
18 | String datacentreSymbol = datacentre.getSymbol();
19 | String allocatorSymbol = datacentre.getAllocator().getSymbol();
20 |
21 | ValidationUtils.addConstraintViolation(context, defaultMessage, "symbol");
22 |
23 | return datacentreSymbol.startsWith(allocatorSymbol + ".");
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/service/impl/PasswordEncoderImpl.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.service.impl;
2 |
3 | import org.apache.log4j.Logger;
4 | import org.springframework.beans.factory.annotation.Value;
5 | import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
6 | import org.springframework.stereotype.Service;
7 |
8 | @Service
9 | public class PasswordEncoderImpl extends ShaPasswordEncoder {
10 |
11 | Logger log4j = Logger.getLogger(PasswordEncoderImpl.class);
12 |
13 | @Value("${salt.password}") String salt;
14 |
15 | public PasswordEncoderImpl() {
16 | super(256); // SHA-256
17 | }
18 |
19 | @Override
20 | public String encodePassword(String rawPass, Object salt) {
21 | // use system-wide salt
22 | log4j.debug("encodePassword (salt=" + this.salt + ")");
23 | return super.encodePassword(rawPass, this.salt);
24 | }
25 |
26 | @Override
27 | public boolean isPasswordValid(String encPass, String rawPass, Object salt) {
28 | // use system-wide salt
29 | return super.isPasswordValid(encPass, rawPass, this.salt);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/ListOfDomains.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 |
12 | import org.datacite.mds.validation.constraints.impl.ListOfDomainsValidator;
13 |
14 | /**
15 | * This annotation is used for a String containing a comma separated list of
16 | * domains (e.g. "datacite.org,datacite.org.uk")
17 | */
18 | @Documented
19 | @Constraint(validatedBy = ListOfDomainsValidator.class)
20 | @Target( { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
21 | @Retention(RetentionPolicy.RUNTIME)
22 | public @interface ListOfDomains {
23 | String message() default "{org.datacite.mds.validation.constraints.ListOfDomains.message}";
24 |
25 | String wildCard() default "*";
26 |
27 | Class>[] groups() default {};
28 |
29 | Class extends Payload>[] payload() default {};
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/MatchPrefixes.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 |
12 | import org.datacite.mds.validation.constraints.impl.MatchPrefixesValidator;
13 |
14 | /**
15 | * This annotation has to be placed on type level and is only applicable for a
16 | * Datacentre.
17 | *
18 | * It checks if list of prefixes is a subset of allocator's prefixes
19 | */
20 | @Documented
21 | @Constraint(validatedBy = MatchPrefixesValidator.class)
22 | @Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
23 | @Retention(RetentionPolicy.RUNTIME)
24 | public @interface MatchPrefixes {
25 | String message() default "{org.datacite.mds.validation.constraints.MatchPrefixes.message}";
26 |
27 | Class>[] groups() default {};
28 |
29 | Class extends Payload>[] payload() default {};
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/web/ui/model/ChangePasswordModel.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.web.ui.model;
2 |
3 | import javax.validation.constraints.AssertTrue;
4 | import javax.validation.constraints.NotNull;
5 | import javax.validation.constraints.Size;
6 |
7 | public class ChangePasswordModel {
8 | @NotNull
9 | @Size(min = 8, max = 30)
10 | String first;
11 | String second;
12 |
13 | String symbol;
14 |
15 | @AssertTrue(message = "{org.datacite.mds.validation.other.FieldEquals.message}")
16 | public boolean isEqual() {
17 | return getFirst().equals(getSecond());
18 | }
19 |
20 | public String getFirst() {
21 | return first;
22 | }
23 |
24 | public void setFirst(String first) {
25 | this.first = first;
26 | }
27 |
28 | public String getSecond() {
29 | return second;
30 | }
31 |
32 | public void setSecond(String second) {
33 | this.second = second;
34 | }
35 |
36 | public String getSymbol() {
37 | return symbol;
38 | }
39 |
40 | public void setSymbol(String symbol) {
41 | this.symbol = symbol;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/views/datasets/views.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/MediaType.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 | import javax.validation.constraints.Size;
12 |
13 | import org.datacite.mds.validation.constraints.impl.MediaTypeValidator;
14 |
15 | /**
16 | * This annotation is used for a String containing a Internet Media Type (aka
17 | * MIME type). It checks if the media type is well-formed.
18 | */
19 | @Documented
20 | @Constraint(validatedBy = MediaTypeValidator.class)
21 | @Size(max = 80)
22 | @Target( { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
23 | @Retention(RetentionPolicy.RUNTIME)
24 | public @interface MediaType {
25 | String message() default "{org.datacite.mds.validation.constraints.MediaType.message}";
26 |
27 | Class>[] groups() default {};
28 |
29 | Class extends Payload>[] payload() default {};
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/views/prefixes/views.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/views/metadatas/views.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/web/ui/UsernamePasswordAuthenticationRequireCookiesFilter.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.web.ui;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 | import javax.servlet.http.HttpSession;
6 |
7 | import org.springframework.security.authentication.AuthenticationServiceException;
8 | import org.springframework.security.core.Authentication;
9 | import org.springframework.security.core.AuthenticationException;
10 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
11 |
12 | public class UsernamePasswordAuthenticationRequireCookiesFilter extends UsernamePasswordAuthenticationFilter {
13 |
14 | @Override
15 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
16 | throws AuthenticationException {
17 | HttpSession session = request.getSession(false);
18 | if (session == null)
19 | throw new AuthenticationServiceException("Cannot create session. Cookies disabled?");
20 | return super.attemptAuthentication(request, response);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/views/password/change/success.jspx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ${fn:escapeXml(title)}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/util/FilterPredicates.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.util;
2 |
3 | import org.apache.commons.collections.Predicate;
4 | import org.datacite.mds.domain.AllocatorOrDatacentre;
5 | import org.datacite.mds.domain.Prefix;
6 |
7 | public class FilterPredicates {
8 |
9 | public static Predicate getAllocatorOrDatacentreContainsPrefixPredicate(final Prefix prefix) {
10 | return new Predicate() {
11 | @Override
12 | public boolean evaluate(Object object) {
13 | AllocatorOrDatacentre user = (AllocatorOrDatacentre) object;
14 | return user.getPrefixes().contains(prefix);
15 | }
16 | };
17 | }
18 |
19 | public static Predicate getAllocatorOrDatacentreIsInferiorOfPredicate(final AllocatorOrDatacentre superior) {
20 | return new Predicate() {
21 | @Override
22 | public boolean evaluate(Object object) {
23 | AllocatorOrDatacentre inferior = (AllocatorOrDatacentre) object;
24 | return SecurityUtils.isUserSuperiorTo(superior, inferior);
25 | }
26 | };
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/views/metadatas/update.jspx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/impl/ListOfDomainsValidator.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints.impl;
2 |
3 | import javax.validation.ConstraintValidator;
4 | import javax.validation.ConstraintValidatorContext;
5 |
6 | import org.apache.commons.lang.StringUtils;
7 | import org.datacite.mds.util.Utils;
8 | import org.datacite.mds.util.ValidationUtils;
9 | import org.datacite.mds.validation.constraints.ListOfDomains;
10 |
11 | public class ListOfDomainsValidator implements ConstraintValidator {
12 |
13 | String wildCard;
14 |
15 | public void initialize(ListOfDomains constraintAnnotation) {
16 | this.wildCard = constraintAnnotation.wildCard();
17 | }
18 |
19 | public boolean isValid(String domains, ConstraintValidatorContext context) {
20 | for (String domain : Utils.csvToList(domains)) {
21 | boolean containsWildcard = StringUtils.contains(domain, wildCard);
22 | boolean isHostName = ValidationUtils.isHostname(domain);
23 | if (! containsWildcard && ! isHostName) {
24 | return false;
25 | }
26 | }
27 | return true;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/MatchSymbolPrefix.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 |
12 | import org.datacite.mds.validation.constraints.impl.MatchSymbolPrefixValidator;
13 |
14 | /**
15 | * This annotation has to be placed on type level and is only applicable for a
16 | * Datacentre.
17 | *
18 | * It checks if prefix of the specified symbol begins with the symbol of the
19 | * assigned allocator
20 | *
21 | */
22 |
23 | @Documented
24 | @Constraint(validatedBy = MatchSymbolPrefixValidator.class)
25 | @Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
26 | @Retention(RetentionPolicy.RUNTIME)
27 | public @interface MatchSymbolPrefix {
28 | String message() default "{org.datacite.mds.validation.constraints.MatchSymbolPrefix.message}";
29 |
30 | Class>[] groups() default {};
31 |
32 | Class extends Payload>[] payload() default {};
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/layouts/default.jspx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/test/java/org/datacite/mds/validation/constraints/ListOfDomainsTest.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import static org.junit.Assert.assertFalse;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import org.junit.Test;
7 |
8 | public class ListOfDomainsTest extends AbstractContraintsTest {
9 | @ListOfDomains(wildCard = "#")
10 | String domains;
11 |
12 | @Test
13 | public void test() {
14 | assertTrue(isValid(null));
15 | assertFalse(isValid("com"));
16 | assertFalse(isValid("example.o"));
17 | assertFalse(isValid("com,example.com"));
18 | assertFalse(isValid("example.org;example.com"));
19 | assertFalse(isValid("example.com/path"));
20 | assertFalse(isValid("http://example.com"));
21 | assertTrue(isValid("example.org,foo.bar.org,a.b.c.de"));
22 |
23 | assertTrue(isValid("#"));
24 | assertTrue(isValid("#.com"));
25 | assertTrue(isValid("example.com,#.org"));
26 | assertFalse(isValid("example.com,#.org,net"));
27 | }
28 |
29 | boolean isValid(String domains) {
30 | this.domains = domains;
31 | return super.isValid(this, "domains");
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/MatchDoiPrefix.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 |
12 | import org.datacite.mds.validation.constraints.impl.MatchDoiPrefixValidator;
13 |
14 | /**
15 | * This annotation has to be placed on type level and is only applicable for a
16 | * Dataset.
17 | *
18 | * It checks if prefix of the specified DOI is in the list of the allowed
19 | * prefixes of the datacentre.
20 | *
21 | * @see org.datacite.mds.domain.Dataset
22 | */
23 | @Documented
24 | @Constraint(validatedBy = MatchDoiPrefixValidator.class)
25 | @Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
26 | @Retention(RetentionPolicy.RUNTIME)
27 | public @interface MatchDoiPrefix {
28 | String message() default "{org.datacite.mds.validation.constraints.MatchDoiPrefix.message}";
29 |
30 | Class>[] groups() default {};
31 |
32 | Class extends Payload>[] payload() default {};
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/ValidXML.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 | import javax.validation.ReportAsSingleViolation;
12 |
13 | import org.datacite.mds.validation.constraints.impl.ValidXMLValidator;
14 |
15 | /**
16 | * This annotation is used for XML content (byte[]) that should be validate to a
17 | * xml schema.
18 | *
19 | * Example usage:
20 | *
21 | *
22 | * @ValidXML
23 | * private byte[] xml;
24 | *
25 | */
26 | @Documented
27 | @Constraint(validatedBy = ValidXMLValidator.class)
28 | @Target( { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
29 | @Retention(RetentionPolicy.RUNTIME)
30 | @ReportAsSingleViolation
31 | public @interface ValidXML {
32 |
33 | String message() default "{org.datacite.mds.validation.constraints.ValidXML.message}";
34 |
35 | Class>[] groups() default {};
36 |
37 | Class extends Payload>[] payload() default {};
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/service/HandleService.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.service;
2 |
3 | import org.datacite.mds.web.api.NotFoundException;
4 |
5 | /**
6 | * An interface to access Handle System
7 | */
8 | public interface HandleService {
9 |
10 | /**
11 | * Resolve a DOI
12 | * @param doi name to be resolved
13 | * @return url of DOI
14 | * @throws NotFoundException if DOI does not exist or does not have a URL
15 | * @throws HandleException wraps exception from the server
16 | */
17 | String resolve(String doi) throws HandleException, NotFoundException;
18 |
19 | /**
20 | * Mints a new DOI
21 | * @param doi name to be minted
22 | * @param url location to be resolved
23 | * @throws HandleException wraps exception from the server
24 | */
25 | void create(String doi, String url) throws HandleException;
26 |
27 | /**
28 | * Updates an existing DOI
29 | * @param doi name to be updated
30 | * @param newUrl a new location to be resolved
31 | * @throws HandleException wraps exception from the server
32 | */
33 | void update(String doi, String newUrl) throws HandleException;
34 |
35 | void ping() throws HandleException;
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/service/userdetails/AllocatorMasterUserDetailsServiceImpl.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2010 DataCite
3 | *
4 | * All rights reserved. This program and the accompanying
5 | * materials are made available under the terms of the
6 | * Apache License, Version 2.0 which accompanies
7 | * this distribution, and is available at
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | *******************************************************************************/
11 |
12 | package org.datacite.mds.service.userdetails;
13 |
14 | import org.datacite.mds.util.Utils;
15 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
16 |
17 | /**
18 | * accept allocator of a datacentre as master user
19 | */
20 | public class AllocatorMasterUserDetailsServiceImpl extends BaseMasterUserDetailsService {
21 |
22 | @Override
23 | public String getMasterUsername(String username) {
24 | String mastername = Utils.getAllocatorFromDatacentreSymbol(username);
25 | if (mastername == null) {
26 | throw new UsernameNotFoundException("cannot parse allocator symbol");
27 | }
28 | return mastername;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/validation/constraints/URL.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.validation.constraints;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import javax.validation.Constraint;
10 | import javax.validation.Payload;
11 | import javax.validation.constraints.Pattern;
12 | import javax.validation.constraints.Size;
13 |
14 | /**
15 | * This annotation is used for a String containing a URL. It checks if the URL
16 | * is well-formed and have one of http, https and ftp as protocol. Null is a
17 | * valid URL (use @NotNull annotation if you don't want this).
18 | */
19 | @Documented
20 | @Size(max = 2048)
21 | @org.hibernate.validator.constraints.URL
22 | @Pattern(regexp = "(https?|ftp)://.*|\\s*", message = "{org.datacite.mds.validation.constraints.URL.protocol.message}")
23 | @Target( { ElementType.FIELD, ElementType.ANNOTATION_TYPE })
24 | @Retention(RetentionPolicy.RUNTIME)
25 | @Constraint(validatedBy = {})
26 | public @interface URL {
27 | String message() default "";
28 |
29 | Class>[] groups() default {};
30 |
31 | Class extends Payload>[] payload() default {};
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/web/api/controller/StatusController.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.web.api.controller;
2 |
3 | import javax.persistence.EntityManager;
4 | import javax.persistence.PersistenceContext;
5 |
6 | import org.datacite.mds.service.HandleException;
7 | import org.datacite.mds.service.HandleService;
8 | import org.datacite.mds.web.api.ApiController;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseEntity;
12 | import org.springframework.stereotype.Controller;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 |
15 | @Controller
16 | public class StatusController implements ApiController {
17 |
18 | @PersistenceContext
19 | EntityManager em;
20 |
21 | @Autowired
22 | HandleService handleService;
23 |
24 | @RequestMapping(value = "/status")
25 | public ResponseEntity status() throws HandleException {
26 | checkDatabaseConnection();
27 | handleService.ping();
28 | return new ResponseEntity("OK", null, HttpStatus.OK);
29 | }
30 |
31 | private void checkDatabaseConnection() {
32 | em.createNativeQuery("SELECT 1").getSingleResult();
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/datacite/mds/service/impl/MailServiceImpl.java:
--------------------------------------------------------------------------------
1 | package org.datacite.mds.service.impl;
2 |
3 | import java.util.concurrent.Future;
4 |
5 | import org.apache.log4j.Logger;
6 | import org.datacite.mds.mail.MailMessage;
7 | import org.datacite.mds.service.MailService;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.mail.MailException;
10 | import org.springframework.mail.MailSender;
11 | import org.springframework.scheduling.annotation.Async;
12 | import org.springframework.scheduling.annotation.AsyncResult;
13 | import org.springframework.stereotype.Service;
14 |
15 | @Service
16 | public class MailServiceImpl implements MailService {
17 |
18 | Logger log4j = Logger.getLogger(MailServiceImpl.class);
19 |
20 | @Autowired
21 | MailSender mailSender;
22 |
23 | public void send(MailMessage mail) {
24 | log4j.info("Sending mail: " + mail);
25 | try {
26 | mailSender.send(mail);
27 | } catch (MailException e) {
28 | log4j.warn(e.getMessage());
29 | throw e;
30 | }
31 | }
32 |
33 | @Async
34 | public Future