Skip to content

Commit 5d1b51e

Browse files
static factory methods are now on the generator classes instead of the builder classes
1 parent 9cb7bc1 commit 5d1b51e

File tree

7 files changed

+109
-125
lines changed

7 files changed

+109
-125
lines changed

README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,23 @@ The following features are supported:
3030
<dependency>
3131
<groupId>com.github.bastiaanjansen</groupId>
3232
<artifactId>otp-java</artifactId>
33-
<version>1.2.4</version>
33+
<version>1.3.0</version>
3434
</dependency>
3535
```
3636

3737
### Gradle
3838
```gradle
39-
implementation 'com.github.bastiaanjansen:otp-java:1.2.4'
39+
implementation 'com.github.bastiaanjansen:otp-java:1.3.0'
4040
```
4141

4242
### Scala SBT
4343
```scala
44-
libraryDependencies += "com.github.bastiaanjansen" % "otp-java" % "1.2.4"
44+
libraryDependencies += "com.github.bastiaanjansen" % "otp-java" % "1.3.0"
4545
```
4646

4747
### Apache Ivy
4848
```xml
49-
<dependency org="com.github.bastiaanjansen" name="otp-java" rev="1.2.4" />
49+
<dependency org="com.github.bastiaanjansen" name="otp-java" rev="1.3.0" />
5050
```
5151

5252
Or you can download the source from the [GitHub releases page](https://github.com/BastiaanJansen/OTP-Java/releases).
@@ -83,7 +83,7 @@ byte[] secret = SecretGenerator.generate(512);
8383
It is also possible to create a HOTPGenerator instance based on an OTPAuth URI. When algorithm or digits are not specified, the default values will be used.
8484
```java
8585
URI uri = new URI("otpauth://hotp/issuer?secret=ABCDEFGHIJKLMNOP&algorithm=SHA1&digits=6&counter=8237");
86-
HOTPGenerator hotp = HOTPGenerator.Builder.fromURI(uri);
86+
HOTPGenerator hotp = HOTPGenerator.fromURI(uri);
8787
```
8888

8989
Get information about the generator:
@@ -131,7 +131,7 @@ TOTPGenerator totp = builder.build();
131131
Or create a `TOTPGenerator` instance from an OTPAuth URI:
132132
```java
133133
URI uri = new URI("otpauth://totp/issuer?secret=ABCDEFGHIJKLMNOP&algorithm=SHA1&digits=6&period=30");
134-
TOTPGenerator totp = TOTPGenerator.Builder.fromURI(uri);
134+
TOTPGenerator totp = TOTPGenerator.fromURI(uri);
135135
```
136136

137137
Get information about the generator:

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
<groupId>com.github.bastiaanjansen</groupId>
1212
<artifactId>otp-java</artifactId>
13-
<version>1.2.4</version>
13+
<version>1.3.0</version>
1414

1515
<name>OTP-Java</name>
1616
<description>A small and easy-to-use one-time password generator for Java according to RFC 4226 (HOTP) and RFC 6238 (TOTP).</description>

src/main/java/com/bastiaanjansen/otp/HOTPGenerator.java

+44-26
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
import java.net.URI;
66
import java.net.URISyntaxException;
7+
import java.time.Duration;
78
import java.util.HashMap;
89
import java.util.Map;
10+
import java.util.Optional;
911

1012
/**
1113
* Generates counter-based one-time passwords
@@ -20,6 +22,47 @@ private HOTPGenerator(final HOTPGenerator.Builder builder) {
2022
super(builder);
2123
}
2224

25+
/**
26+
* Build a TOTPGenerator from an OTPAuth URI
27+
*
28+
* @param uri OTPAuth URI
29+
* @return HOTPGenerator
30+
* @throws URISyntaxException when URI cannot be parsed
31+
*/
32+
public static HOTPGenerator fromURI(final URI uri) throws URISyntaxException {
33+
Map<String, String> query = URIHelper.queryItems(uri);
34+
35+
byte[] secret = Optional.ofNullable(query.get(URIHelper.SECRET))
36+
.map(String::getBytes)
37+
.orElseThrow(() -> new IllegalArgumentException("Secret query parameter must be set"));
38+
39+
Builder builder = new Builder(secret);
40+
41+
try {
42+
Optional.ofNullable(query.get(URIHelper.DIGITS))
43+
.map(Integer::valueOf)
44+
.ifPresent(builder::withPasswordLength);
45+
Optional.ofNullable(query.get(URIHelper.ALGORITHM))
46+
.map(String::toUpperCase)
47+
.map(HMACAlgorithm::valueOf)
48+
.ifPresent(builder::withAlgorithm);
49+
} catch (Exception e) {
50+
throw new URISyntaxException(uri.toString(), "URI could not be parsed");
51+
}
52+
53+
return builder.build();
54+
}
55+
56+
/**
57+
* Create a HOTPGenerator with default values
58+
*
59+
* @param secret used to generate hash
60+
* @return a HOTPGenerator with default values
61+
*/
62+
public static HOTPGenerator withDefaultValues(final byte[] secret) {
63+
return new HOTPGenerator.Builder(secret).build();
64+
}
65+
2366
/**
2467
* Generate a counter-based one-time password
2568
* @param counter how many times time interval has passed since 1970
@@ -62,15 +105,11 @@ public URI getURI(final int counter, final String issuer, final String account)
62105
* @author Bastiaan Jansen
63106
* @see HOTPGenerator
64107
*/
65-
public static class Builder extends OTPGenerator.Builder<Builder, HOTPGenerator> {
108+
public static class Builder extends OTPGenerator.Builder<HOTPGenerator, Builder> {
66109
public Builder(final byte[] secret) {
67110
super(secret);
68111
}
69112

70-
private Builder(final URI uri) throws URISyntaxException {
71-
super(uri);
72-
}
73-
74113
@Override
75114
protected Builder getBuilder() {
76115
return this;
@@ -85,26 +124,5 @@ protected Builder getBuilder() {
85124
public HOTPGenerator build() {
86125
return new HOTPGenerator(this);
87126
}
88-
89-
/**
90-
* Build a TOTPGenerator from an OTPAuth URI
91-
*
92-
* @param uri OTPAuth URI
93-
* @return HOTPGenerator
94-
* @throws URISyntaxException when URI cannot be parsed
95-
*/
96-
public static HOTPGenerator fromURI(final URI uri) throws URISyntaxException {
97-
return new HOTPGenerator.Builder(uri).build();
98-
}
99-
100-
/**
101-
* Create a HOTPGenerator with default values
102-
*
103-
* @param secret used to generate hash
104-
* @return a HOTPGenerator with default values
105-
*/
106-
public static HOTPGenerator withDefaultValues(final byte[] secret) {
107-
return new HOTPGenerator.Builder(secret).build();
108-
}
109127
}
110128
}

src/main/java/com/bastiaanjansen/otp/OTPGenerator.java

+3-42
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.nio.charset.StandardCharsets;
1111
import java.security.InvalidKeyException;
1212
import java.security.NoSuchAlgorithmException;
13+
import java.time.Duration;
1314
import java.util.Map;
1415
import java.util.Optional;
1516

@@ -71,26 +72,6 @@ protected OTPGenerator(final Builder<?, ?> builder) {
7172
this(builder.passwordLength, builder.algorithm, builder.secret);
7273
}
7374

74-
protected OTPGenerator(final URI uri) throws URISyntaxException {
75-
Map<String, String> query = URIHelper.queryItems(uri);
76-
77-
this.secret = Optional.ofNullable(query.get(URIHelper.SECRET))
78-
.map(String::getBytes)
79-
.orElseThrow(() -> new IllegalArgumentException("Secret query parameter must be set"));
80-
81-
try {
82-
this.passwordLength = Optional.ofNullable(query.get(URIHelper.DIGITS))
83-
.map(Integer::valueOf)
84-
.orElse(DEFAULT_PASSWORD_LENGTH);
85-
this.algorithm = Optional.ofNullable(query.get(URIHelper.ALGORITHM))
86-
.map(String::toUpperCase)
87-
.map(HMACAlgorithm::valueOf)
88-
.orElse(DEFAULT_HMAC_ALGORITHM);
89-
} catch (Exception e) {
90-
throw new URISyntaxException(uri.toString(), "URI could not be parsed");
91-
}
92-
}
93-
9475
public int getPasswordLength() {
9576
return passwordLength;
9677
}
@@ -278,7 +259,7 @@ private boolean validatePasswordLength(final int passwordLength) {
278259
* @author Bastiaan Jansen
279260
* @param <B> concrete builder class
280261
*/
281-
protected abstract static class Builder<B, G> {
262+
protected abstract static class Builder<T extends OTPGenerator, B extends Builder<T, B>> {
282263
/**
283264
* Number of digits for generated code in range 6...8, defaults to 6
284265
*/
@@ -300,26 +281,6 @@ public Builder(final byte[] secret) {
300281
this.algorithm = DEFAULT_HMAC_ALGORITHM;
301282
}
302283

303-
public Builder(final URI uri) throws URISyntaxException {
304-
Map<String, String> query = URIHelper.queryItems(uri);
305-
306-
this.secret = Optional.ofNullable(query.get(URIHelper.SECRET))
307-
.map(String::getBytes)
308-
.orElseThrow(() -> new IllegalArgumentException("Secret query parameter must be set"));
309-
310-
try {
311-
this.passwordLength = Optional.ofNullable(query.get(URIHelper.DIGITS))
312-
.map(Integer::valueOf)
313-
.orElse(DEFAULT_PASSWORD_LENGTH);
314-
this.algorithm = Optional.ofNullable(query.get(URIHelper.ALGORITHM))
315-
.map(String::toUpperCase)
316-
.map(HMACAlgorithm::valueOf)
317-
.orElse(DEFAULT_HMAC_ALGORITHM);
318-
} catch (Exception e) {
319-
throw new URISyntaxException(uri.toString(), "URI could not be parsed");
320-
}
321-
}
322-
323284
/**
324285
* Change password length of code
325286
*
@@ -344,6 +305,6 @@ public B withAlgorithm(final HMACAlgorithm algorithm) {
344305

345306
protected abstract B getBuilder();
346307

347-
public abstract G build();
308+
public abstract T build();
348309
}
349310
}

src/main/java/com/bastiaanjansen/otp/TOTPGenerator.java

+37-31
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,54 @@ public final class TOTPGenerator extends OTPGenerator {
3131
*/
3232
private final Duration period;
3333

34-
private TOTPGenerator(final TOTPGenerator.Builder builder) {
34+
private TOTPGenerator(final Builder builder) {
3535
super(builder);
3636
this.period = builder.period;
3737
}
3838

39-
private TOTPGenerator(final URI uri) throws URISyntaxException {
40-
super(uri);
39+
/**
40+
* Build a TOTPGenerator from an OTPAuth URI
41+
*
42+
* @param uri OTPAuth URI
43+
* @return TOTPGenerator
44+
* @throws URISyntaxException when URI cannot be parsed
45+
*/
46+
public static TOTPGenerator fromURI(URI uri) throws URISyntaxException {
4147
Map<String, String> query = URIHelper.queryItems(uri);
4248

43-
try {
44-
this.period = Optional.ofNullable(query.get(URIHelper.PERIOD))
45-
.map(Long::parseLong).map(Duration::ofSeconds)
46-
.orElse(DEFAULT_PERIOD);
49+
byte[] secret = Optional.ofNullable(query.get(URIHelper.SECRET))
50+
.map(String::getBytes)
51+
.orElseThrow(() -> new IllegalArgumentException("Secret query parameter must be set"));
52+
53+
Builder builder = new Builder(secret);
4754

55+
try {
56+
Optional.ofNullable(query.get(URIHelper.PERIOD))
57+
.map(Long::parseLong)
58+
.map(Duration::ofSeconds)
59+
.ifPresent(builder::withPeriod);
60+
Optional.ofNullable(query.get(URIHelper.DIGITS))
61+
.map(Integer::valueOf)
62+
.ifPresent(builder::withPasswordLength);
63+
Optional.ofNullable(query.get(URIHelper.ALGORITHM))
64+
.map(String::toUpperCase)
65+
.map(HMACAlgorithm::valueOf)
66+
.ifPresent(builder::withAlgorithm);
4867
} catch (Exception e) {
4968
throw new URISyntaxException(uri.toString(), "URI could not be parsed");
5069
}
70+
71+
return builder.build();
5172
}
5273

53-
public static TOTPGenerator fromURI(URI uri) throws URISyntaxException {
54-
return new TOTPGenerator(uri);
74+
/**
75+
* Create a TOTPGenerator with default values
76+
*
77+
* @param secret used to generate hash
78+
* @return a TOTPGenerator with default values
79+
*/
80+
public static TOTPGenerator withDefaultValues(final byte[] secret) {
81+
return new TOTPGenerator.Builder(secret).build();
5582
}
5683

5784
/**
@@ -192,7 +219,7 @@ private boolean validateTime(final long time) {
192219
* @author Bastiaan Jansen
193220
* @see TOTPGenerator
194221
*/
195-
public static class Builder extends OTPGenerator.Builder<Builder, TOTPGenerator> {
222+
public static class Builder extends OTPGenerator.Builder<TOTPGenerator, Builder> {
196223
/**
197224
* Time interval between new codes
198225
*/
@@ -234,26 +261,5 @@ public TOTPGenerator build() {
234261
protected Builder getBuilder() {
235262
return this;
236263
}
237-
238-
/**
239-
* Build a TOTPGenerator from an OTPAuth URI
240-
*
241-
* @param uri OTPAuth URI
242-
* @return TOTPGenerator
243-
* @throws URISyntaxException when URI cannot be parsed
244-
*/
245-
// public static TOTPGenerator fromURI(final URI uri) throws URISyntaxException {
246-
// return new TOTPGenerator.Builder(uri).build();
247-
// }
248-
249-
/**
250-
* Create a TOTPGenerator with default values
251-
*
252-
* @param secret used to generate hash
253-
* @return a TOTPGenerator with default values
254-
*/
255-
public static TOTPGenerator withDefaultValues(final byte[] secret) {
256-
return new TOTPGenerator.Builder(secret).build();
257-
}
258264
}
259265
}

0 commit comments

Comments
 (0)