refactor: Optimsed codes.

Move private and protected methods or fields to the last of java files.
This commit is contained in:
Zihlu Wang
2024-03-31 18:34:01 +08:00
parent cb537a6844
commit 5895557368
16 changed files with 200 additions and 152 deletions
Vendored Regular → Executable
View File
@@ -32,36 +32,6 @@ import java.util.Random;
*/ */
public final class SecretCreator { public final class SecretCreator {
/**
* Private constructor to prevent instantiation
*/
private SecretCreator() {
}
/**
* The string containing all lowercase characters that can be used to
* generate the secret.
*/
private static final String LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
/**
* The string containing all uppercase characters that can be used to
* generate the secret.
*/
private static final String UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* The string containing all digit characters that can be used to generate
* the secret.
*/
private static final String DIGITS = "0123456789";
/**
* The string containing all special sign characters that can be used to
* generate the secret.
*/
private static final String SPECIAL_SIGNS = "!@#$%^&,*()_+-=,[]{}|;:,'\",.<>/?";
/** /**
* Generates a secure secret with the specified length and character sets. * Generates a secure secret with the specified length and character sets.
* *
@@ -153,4 +123,33 @@ public final class SecretCreator {
return createSecret(length, false, false, false); return createSecret(length, false, false, false);
} }
/**
* Private constructor will protect this class from being instantiated.
*/
private SecretCreator() {
}
/**
* The string containing all lowercase characters that can be used to
* generate the secret.
*/
private static final String LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
/**
* The string containing all uppercase characters that can be used to
* generate the secret.
*/
private static final String UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* The string containing all digit characters that can be used to generate
* the secret.
*/
private static final String DIGITS = "0123456789";
/**
* The string containing all special sign characters that can be used to
* generate the secret.
*/
private static final String SPECIAL_SIGNS = "!@#$%^&,*()_+-=,[]{}|;:,'\",.<>/?";
} }
@@ -88,11 +88,7 @@ public final class PredefinedKeys {
public static final List<String> KEYS = List.of(ISSUER, SUBJECT, AUDIENCE, EXPIRATION_TIME, NOT_BEFORE, ISSUED_AT, JWT_ID); public static final List<String> KEYS = List.of(ISSUER, SUBJECT, AUDIENCE, EXPIRATION_TIME, NOT_BEFORE, ISSUED_AT, JWT_ID);
/** /**
* Private constructor to prevent instantiation of the * Private constructor will protect this class from being instantiated.
* {@code PredefinedKeys} class.
* <p>
* This class is intended to be used as a utility class with only static
* constants and methods.
*/ */
private PredefinedKeys() { private PredefinedKeys() {
} }
@@ -63,6 +63,9 @@ public enum TokenDataType {
*/ */
private final Class<?> mappedClass; private final Class<?> mappedClass;
/**
* Create a TokenDataType with a mapped class.
*/
TokenDataType(Class<?> mappedClass) { TokenDataType(Class<?> mappedClass) {
this.mappedClass = mappedClass; this.mappedClass = mappedClass;
} }
@@ -98,16 +98,6 @@ import java.util.*;
@Slf4j @Slf4j
public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> { public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
private final GuidCreator<?> jtiCreator;
private final SecureDigestAlgorithm<SecretKey, SecretKey> algorithm;
private final String issuer;
private final SecretKey key;
private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance();
/** /**
* Create a resolver with specified algorithm, issuer, secret and guid strategy. * Create a resolver with specified algorithm, issuer, secret and guid strategy.
* *
@@ -432,6 +422,15 @@ public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
return renew(oldToken, Duration.ofMinutes(30), payload); return renew(oldToken, Duration.ofMinutes(30), payload);
} }
/**
* Build a new token with specified data.
*
* @param expireAfter the validity time of the token
* @param audience the audience of the token
* @param subject the subject of the token
* @param claims the data to be included in the token
* @return the built token
*/
private String buildToken(Duration expireAfter, String audience, String subject, Map<String, Object> claims) { private String buildToken(Duration expireAfter, String audience, String subject, Map<String, Object> claims) {
var now = LocalDateTime.now(); var now = LocalDateTime.now();
var builder = Jwts.builder() var builder = Jwts.builder()
@@ -453,4 +452,29 @@ public class JjwtTokenResolver implements TokenResolver<Jws<Claims>> {
return builder.signWith(key, algorithm) return builder.signWith(key, algorithm)
.compact(); .compact();
} }
/**
* The ID creator for creating unique JWT IDs.
*/
private final GuidCreator<?> jtiCreator;
/**
* The algorithm to sign this token.
*/
private final SecureDigestAlgorithm<SecretKey, SecretKey> algorithm;
/**
* The issuer of this token.
*/
private final String issuer;
/**
* The signature key of this token.
*/
private final SecretKey key;
/**
* The config of this token resolver.
*/
private final JjwtTokenResolverConfig config = JjwtTokenResolverConfig.getInstance();
} }
@@ -63,17 +63,6 @@ import java.util.Map;
*/ */
public final class JjwtTokenResolverConfig implements TokenResolverConfig<SecureDigestAlgorithm<SecretKey, SecretKey>> { public final class JjwtTokenResolverConfig implements TokenResolverConfig<SecureDigestAlgorithm<SecretKey, SecretKey>> {
private JjwtTokenResolverConfig() {
}
private static final Map<TokenAlgorithm, SecureDigestAlgorithm<SecretKey, SecretKey>> SUPPORTED_ALGORITHMS = new HashMap<>() {{
put(TokenAlgorithm.HS256, Jwts.SIG.HS256);
put(TokenAlgorithm.HS384, Jwts.SIG.HS384);
put(TokenAlgorithm.HS512, Jwts.SIG.HS512);
}};
private static JjwtTokenResolverConfig instance;
public static JjwtTokenResolverConfig getInstance() { public static JjwtTokenResolverConfig getInstance() {
if (instance == null) { if (instance == null) {
instance = new JjwtTokenResolverConfig(); instance = new JjwtTokenResolverConfig();
@@ -106,4 +95,25 @@ public final class JjwtTokenResolverConfig implements TokenResolverConfig<Secure
} }
return SUPPORTED_ALGORITHMS.get(algorithm); return SUPPORTED_ALGORITHMS.get(algorithm);
} }
/**
* Private constructor will protect this class from being instantiated.
*/
private JjwtTokenResolverConfig() {
}
/**
* A {@code Map} to map a {@link TokenAlgorithm} to {@link SecureDigestAlgorithm}.
*/
private static final Map<TokenAlgorithm, SecureDigestAlgorithm<SecretKey, SecretKey>> SUPPORTED_ALGORITHMS = new HashMap<>() {{
put(TokenAlgorithm.HS256, Jwts.SIG.HS256);
put(TokenAlgorithm.HS384, Jwts.SIG.HS384);
put(TokenAlgorithm.HS512, Jwts.SIG.HS512);
}};
/**
* The instance of this config class.
*/
private static JjwtTokenResolverConfig instance;
} }
@@ -65,19 +65,6 @@ import org.springframework.context.annotation.Bean;
@AutoConfigureAfter(value = GuidAutoConfiguration.class) @AutoConfigureAfter(value = GuidAutoConfiguration.class)
public class AuthzeroTokenResolverAutoConfiguration { public class AuthzeroTokenResolverAutoConfiguration {
/**
* The GuidCreator instance to be used for generating JWT IDs (JTI).
*/
private final GuidCreator<?> jtiCreator;
/**
* The {@code SimpleJwtProperties} instance containing the configuration
* properties for Simple JWT.
*/
private final SimpleJwtProperties simpleJwtProperties;
private final ObjectMapper objectMapper;
/** /**
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the * Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
* provided SimpleJwtProperties. * provided SimpleJwtProperties.
@@ -112,4 +99,17 @@ public class AuthzeroTokenResolverAutoConfiguration {
); );
} }
/**
* The GuidCreator instance to be used for generating JWT IDs (JTI).
*/
private final GuidCreator<?> jtiCreator;
/**
* The {@code SimpleJwtProperties} instance containing the configuration
* properties for Simple JWT.
*/
private final SimpleJwtProperties simpleJwtProperties;
private final ObjectMapper objectMapper;
} }
@@ -39,6 +39,11 @@ import java.util.UUID;
@AutoConfiguration @AutoConfiguration
public class GuidAutoConfiguration { public class GuidAutoConfiguration {
/**
* Create a default {@code jtiCreator} with UUID.
*
* @return UUID creator
*/
@Bean(name = "jtiCreator") @Bean(name = "jtiCreator")
@Conditional(GuidCreatorCondition.class) @Conditional(GuidCreatorCondition.class)
public GuidCreator<?> jtiCreator() { public GuidCreator<?> jtiCreator() {
@@ -65,17 +65,6 @@ import org.springframework.context.annotation.Bean;
@AutoConfigureAfter(value = GuidAutoConfiguration.class) @AutoConfigureAfter(value = GuidAutoConfiguration.class)
public class JjwtTokenResolverAutoConfiguration { public class JjwtTokenResolverAutoConfiguration {
/**
* The GuidCreator instance to be used for generating JWT IDs (JTI).
*/
private final GuidCreator<?> jtiCreator;
/**
* The {@code SimpleJwtProperties} instance containing the configuration
* properties for Simple JWT.
*/
private final SimpleJwtProperties simpleJwtProperties;
/** /**
* Constructs a new {@code SimpleJwtAutoConfiguration} instance with the * Constructs a new {@code SimpleJwtAutoConfiguration} instance with the
* provided SimpleJwtProperties. * provided SimpleJwtProperties.
@@ -107,4 +96,15 @@ public class JjwtTokenResolverAutoConfiguration {
); );
} }
/**
* The GuidCreator instance to be used for generating JWT IDs (JTI).
*/
private final GuidCreator<?> jtiCreator;
/**
* The {@code SimpleJwtProperties} instance containing the configuration
* properties for Simple JWT.
*/
private final SimpleJwtProperties simpleJwtProperties;
} }
@@ -17,6 +17,18 @@ import java.util.Objects;
*/ */
@Slf4j @Slf4j
public class GuidCreatorCondition implements Condition { public class GuidCreatorCondition implements Condition {
/**
* The condition to create bean {@code jtiCreator}.
* <p>
* If Spring does not have a bean of type
* {@link cn.org.codecrafters.guid.GuidCreator} named {@code jtiCreator}
* in the application context, then create {@code jtiCreator}.
*
* @param context the spring application context
* @param metadata the metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked
*/
@Override @Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
final var beanFactory = Objects.requireNonNull(context.getBeanFactory()); final var beanFactory = Objects.requireNonNull(context.getBeanFactory());
@@ -17,6 +17,8 @@
package cn.org.codecrafters.webcal; package cn.org.codecrafters.webcal;
import cn.org.codecrafters.webcal.impl.WebCalendarEvent;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -50,55 +52,6 @@ import java.util.Objects;
*/ */
public final class WebCalendar { public final class WebCalendar {
/**
* The {@code VCALENDAR} tag for iCalendar format
*/
private final static String TAG = "VCALENDAR";
/**
* The name of this calendar.
*/
private String name;
/**
* The company who produces this calendar.
* <p>
* This property will be used in {@code PRODID}.
*/
private String companyName;
/**
* The product name.
* <p>
* This property will be used in {@code PRODID}
*/
private String productName;
/**
* The producer's domain name.
*/
private String domainName;
/**
* Scale of this calendar.
*/
private final String scale = "GREGORIAN";
/**
* The method of this calendar.
*/
private String method;
/**
* The version of this calendar.
*/
private final String version = "2.0";
/**
* List of calendar components and events
*/
private final List<WebCalendarNode> nodes;
/** /**
* Constructor for WebCalendar class, initializes the list of calendar * Constructor for WebCalendar class, initializes the list of calendar
* components and events. * components and events.
@@ -209,5 +162,54 @@ public final class WebCalendar {
"END:" + TAG; "END:" + TAG;
} }
/**
* The {@code VCALENDAR} tag for iCalendar format
*/
private final static String TAG = "VCALENDAR";
/**
* The name of this calendar.
*/
private String name;
/**
* The company who produces this calendar.
* <p>
* This property will be used in {@code PRODID}.
*/
private String companyName;
/**
* The product name.
* <p>
* This property will be used in {@code PRODID}
*/
private String productName;
/**
* The producer's domain name.
*/
private String domainName;
/**
* Scale of this calendar.
*/
private final String scale = "GREGORIAN";
/**
* The method of this calendar.
*/
private String method;
/**
* The version of this calendar.
*/
private final String version = "2.0";
/**
* List of calendar components and events
*/
private final List<WebCalendarNode> nodes;
} }
@@ -18,6 +18,7 @@
package cn.org.codecrafters.webcal; package cn.org.codecrafters.webcal;
import cn.org.codecrafters.webcal.config.Classification; import cn.org.codecrafters.webcal.config.Classification;
import cn.org.codecrafters.webcal.impl.WebCalendarEvent;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -37,8 +38,7 @@ import java.util.List;
* @version 1.1.0 * @version 1.1.0
* @since 1.0.0 * @since 1.0.0
*/ */
public abstract sealed class WebCalendarNode public abstract class WebCalendarNode {
permits WebCalendarEvent {
// Common properties for all calendar components and events // Common properties for all calendar components and events
protected List<String> categories; protected List<String> categories;
@@ -22,13 +22,19 @@ import java.time.format.DateTimeFormatter;
import java.util.Objects; import java.util.Objects;
/** /**
* DatetimeFormatters * A formatter to format {@link java.time.LocalDateTime}.
* *
* @author Zihlu Wang * @author Zihlu Wang
* @since 21 Sept, 2023
*/ */
public final class Formatter { public final class DateAndTimeFormatter {
/**
* Get the {@link java.time.format.DateTimeFormatter datetime formatter}
* with UTC pattern and timezone.
*
* @return the {@link java.time.format.DateTimeFormatter datetime formatter}
* with UTC pattern and timezone
*/
public static DateTimeFormatter getUtcDatetimeFormatter() { public static DateTimeFormatter getUtcDatetimeFormatter() {
if (Objects.isNull(utcDateTimeFormatter)) { if (Objects.isNull(utcDateTimeFormatter)) {
utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC); utcDateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'").withZone(ZoneOffset.UTC);
@@ -37,16 +43,6 @@ public final class Formatter {
return utcDateTimeFormatter; return utcDateTimeFormatter;
} }
// public static DateTimeFormatter getLocalDatetimeFormatter() {
// if (Objects.isNull(localDatetimeFormatter)) {
// localDatetimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss");
// }
//
// return localDatetimeFormatter;
// }
private static DateTimeFormatter utcDateTimeFormatter; private static DateTimeFormatter utcDateTimeFormatter;
// private static DateTimeFormatter localDatetimeFormatter;
} }
@@ -15,10 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.org.codecrafters.webcal; package cn.org.codecrafters.webcal.impl;
import cn.org.codecrafters.webcal.WebCalendarNode;
import cn.org.codecrafters.webcal.config.Classification; import cn.org.codecrafters.webcal.config.Classification;
import cn.org.codecrafters.webcal.config.Formatter; import cn.org.codecrafters.webcal.config.DateAndTimeFormatter;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.time.Duration; import java.time.Duration;
@@ -47,8 +48,6 @@ import java.util.UUID;
*/ */
public final class WebCalendarEvent extends WebCalendarNode { public final class WebCalendarEvent extends WebCalendarNode {
private final static String TAG = "VEVENT";
/** /**
* Add categories to the event. * Add categories to the event.
* *
@@ -270,8 +269,8 @@ public final class WebCalendarEvent extends WebCalendarNode {
END:{0}""", END:{0}""",
TAG, // 0 - tag TAG, // 0 - tag
Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName, // 1 - uid Optional.ofNullable(uid).orElse(UUID.randomUUID().toString()) + "@" + domainName, // 1 - uid
now.format(Formatter.getUtcDatetimeFormatter()), // 2 - dtstamp now.format(DateAndTimeFormatter.getUtcDatetimeFormatter()), // 2 - dtstamp
start.atZone(ZoneId.systemDefault()).format(Formatter.getUtcDatetimeFormatter()), // 3 - start time start.atZone(ZoneId.systemDefault()).format(DateAndTimeFormatter.getUtcDatetimeFormatter()), // 3 - start time
Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""), // 4 - summary Optional.ofNullable(summary).map((item) -> "\nSUMMARY:" + item).orElse(""), // 4 - summary
Optional.ofNullable(categories) Optional.ofNullable(categories)
.map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""), // 5 - categories .map((item) -> !item.isEmpty() ? "\nCATEGORIES:" + resolveCategories() : null).orElse(""), // 5 - categories
@@ -289,4 +288,6 @@ public final class WebCalendarEvent extends WebCalendarNode {
); );
} }
private final static String TAG = "VEVENT";
} }
@@ -27,7 +27,7 @@
* generating web calendars with customisable settings and events. * generating web calendars with customisable settings and events.
* </li> * </li>
* <li> * <li>
* {@link cn.org.codecrafters.webcal.WebCalendarEvent}: A class * {@link cn.org.codecrafters.webcal.impl.WebCalendarEvent}: A class
* representing a single event in a web calendar with various * representing a single event in a web calendar with various
* attributes and options. * attributes and options.
* </li> * </li>
@@ -18,7 +18,7 @@
package cn.org.codecrafters.webcal.test; package cn.org.codecrafters.webcal.test;
import cn.org.codecrafters.webcal.WebCalendar; import cn.org.codecrafters.webcal.WebCalendar;
import cn.org.codecrafters.webcal.WebCalendarEvent; import cn.org.codecrafters.webcal.impl.WebCalendarEvent;
import cn.org.codecrafters.webcal.config.Classification; import cn.org.codecrafters.webcal.config.Classification;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;