forked from aispl/ais-commons-domain
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
819afce
commit aee6550
Showing
5 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
src/main/java/pl/ais/commons/domain/security/CryptographicService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package pl.ais.commons.domain.security; | ||
|
||
import java.io.Serializable; | ||
|
||
import javax.annotation.Nonnull; | ||
|
||
/** | ||
* Defines the API contract for the cryptographic service. | ||
* | ||
* @param <T> defines the type of unencrypted value | ||
* @author Warlock, AIS.PL | ||
* @since 1.0.2 | ||
*/ | ||
public interface CryptographicService<T> extends Serializable { | ||
|
||
/** | ||
* Decrypts the value. | ||
* | ||
* @param value the value to decrypt | ||
* @return decrypted value | ||
*/ | ||
@Nonnull | ||
T decrypt(@Nonnull DecryptableValue<T> value); | ||
|
||
/** | ||
* Encrypts given value. | ||
* | ||
* @param value the value to encrypt | ||
* @return encrypted value | ||
*/ | ||
@Nonnull | ||
DecryptableValue<T> encrypt(@Nonnull T value); | ||
|
||
} |
97 changes: 97 additions & 0 deletions
97
src/main/java/pl/ais/commons/domain/security/DecryptableValue.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package pl.ais.commons.domain.security; | ||
|
||
import java.io.Serializable; | ||
import java.util.Arrays; | ||
|
||
import javax.annotation.Nonnull; | ||
|
||
import org.apache.commons.lang3.builder.EqualsBuilder; | ||
import org.apache.commons.lang3.builder.HashCodeBuilder; | ||
import org.apache.commons.lang3.builder.ToStringBuilder; | ||
|
||
import pl.ais.commons.domain.stereotype.ValueObject; | ||
|
||
/** | ||
* Decryptable value. | ||
* | ||
* @param <T> defines the type of unencrypted value | ||
* @author Warlock, AIS.PL | ||
* @since 1.0.2 | ||
*/ | ||
@ValueObject | ||
public final class DecryptableValue<T> implements Serializable { | ||
|
||
private transient T decryptedValue; | ||
|
||
private final CryptographicService<T> decryptor; | ||
|
||
private final byte[] encryptedValue; | ||
|
||
/** | ||
* Constructs new instance. | ||
* | ||
* @param decryptor decryptor which will be used to decrypt value | ||
* @param encryptedValue encrypted value, which will be enclosed by the created instance | ||
*/ | ||
public DecryptableValue(@Nonnull final CryptographicService<T> decryptor, @Nonnull final byte[] encryptedValue) { | ||
super(); | ||
if ((null == decryptor) || (null == encryptedValue)) { | ||
throw new IllegalArgumentException("Both decryptor and encrypted value cannot be null."); | ||
} | ||
this.decryptor = decryptor; | ||
this.encryptedValue = Arrays.copyOf(encryptedValue, encryptedValue.length); | ||
} | ||
|
||
/** | ||
* Decrypts the value. | ||
* | ||
* @return decrypted value | ||
*/ | ||
@Nonnull | ||
public T decrypt() { | ||
if (null == decryptedValue) { | ||
decryptedValue = decryptor.decrypt(this); | ||
} | ||
return decryptedValue; | ||
} | ||
|
||
/** | ||
* @see java.lang.Object#equals(java.lang.Object) | ||
*/ | ||
@SuppressWarnings("rawtypes") | ||
@Override | ||
public boolean equals(final Object object) { | ||
boolean result = (this == object); | ||
if (!result && (null != object) && (getClass() == object.getClass())) { | ||
final DecryptableValue other = (DecryptableValue) object; | ||
result = new EqualsBuilder().append(decryptor, other.decryptor) | ||
.append(encryptedValue, other.encryptedValue).isEquals(); | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* @return the encrypted value | ||
*/ | ||
@Nonnull | ||
public byte[] getEncryptedValue() { | ||
return Arrays.copyOf(encryptedValue, encryptedValue.length); | ||
} | ||
|
||
/** | ||
* @see java.lang.Object#hashCode() | ||
*/ | ||
@Override | ||
public int hashCode() { | ||
return new HashCodeBuilder().append(decryptor).append(encryptedValue).toHashCode(); | ||
} | ||
|
||
/** | ||
* @see java.lang.Object#toString() | ||
*/ | ||
@Override | ||
public String toString() { | ||
return new ToStringBuilder(this).append("decryptor", decryptor).build(); | ||
} | ||
|
||
} |
103 changes: 103 additions & 0 deletions
103
src/main/java/pl/ais/commons/domain/security/PassThroughCryptographicService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package pl.ais.commons.domain.security; | ||
|
||
import java.nio.charset.Charset; | ||
|
||
import javax.annotation.Nonnull; | ||
import javax.annotation.concurrent.ThreadSafe; | ||
|
||
import org.apache.commons.lang3.builder.HashCodeBuilder; | ||
import org.apache.commons.lang3.builder.ToStringBuilder; | ||
|
||
import pl.ais.commons.domain.stereotype.DomainService; | ||
|
||
/** | ||
* Pass-through implementation of cryptographic service. | ||
* | ||
* <p> | ||
* This implementation in fact doesn't perform any encryption. Returned {@link DecryptableValue} holds | ||
* the unencrypted data passed through. | ||
* </p> | ||
* | ||
* @author Warlock, AIS.PL | ||
* @since 1.0.2 | ||
*/ | ||
@ThreadSafe | ||
@DomainService | ||
public final class PassThroughCryptographicService implements CryptographicService<String> { | ||
|
||
private final String charsetName; | ||
|
||
/** | ||
* Constructs new instance using default charset of this JVM for the string conversions. | ||
*/ | ||
public PassThroughCryptographicService() { | ||
this(Charset.defaultCharset()); | ||
} | ||
|
||
/** | ||
* Constructs new instance. | ||
* | ||
* @param charset the charset which should be used for the string conversions | ||
*/ | ||
public PassThroughCryptographicService(@Nonnull final Charset charset) { | ||
super(); | ||
if (null == charset) { | ||
throw new IllegalArgumentException("Charset cannot be null."); | ||
} | ||
this.charsetName = charset.name(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
@Nonnull | ||
public String decrypt(@Nonnull final DecryptableValue<String> value) { | ||
if (null == value) { | ||
throw new IllegalArgumentException(); | ||
} | ||
return new String(value.getEncryptedValue(), Charset.forName(charsetName)); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
@Override | ||
@Nonnull | ||
public DecryptableValue<String> encrypt(@Nonnull final String value) { | ||
if (null == value) { | ||
throw new IllegalArgumentException(); | ||
} | ||
return new DecryptableValue<>(this, value.getBytes(Charset.forName(charsetName))); | ||
} | ||
|
||
/** | ||
* @see java.lang.Object#equals(java.lang.Object) | ||
*/ | ||
@Override | ||
public boolean equals(final Object object) { | ||
boolean result = (this == object); | ||
if (!result && (null != object) && (getClass() == object.getClass())) { | ||
final PassThroughCryptographicService other = (PassThroughCryptographicService) object; | ||
result = charsetName.equals(other.charsetName); | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* @see java.lang.Object#hashCode() | ||
*/ | ||
@Override | ||
public int hashCode() { | ||
return new HashCodeBuilder().append(charsetName).toHashCode(); | ||
} | ||
|
||
/** | ||
* @see java.lang.Object#toString() | ||
*/ | ||
@Override | ||
public String toString() { | ||
return new ToStringBuilder(this).append("charsetName", charsetName).build(); | ||
} | ||
|
||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/pl/ais/commons/domain/stereotype/DomainService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package pl.ais.commons.domain.stereotype; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
import org.springframework.context.annotation.Scope; | ||
import org.springframework.context.annotation.ScopedProxyMode; | ||
import org.springframework.stereotype.Service; | ||
|
||
/** | ||
* Indicates that an annotated class is a Domain Service. | ||
* | ||
* @author Warlock, AIS.PL | ||
* @since 1.0.2 | ||
*/ | ||
@Documented | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.TYPE}) | ||
@Service | ||
@Scope(proxyMode = ScopedProxyMode.INTERFACES) | ||
public @interface DomainService { | ||
|
||
/** | ||
* The value may indicate a suggestion for a logical component name, | ||
* to be turned into a Spring bean in case of an autodetected component. | ||
* | ||
* @return the suggested component name, if any | ||
*/ | ||
String value() default ""; | ||
|
||
} |
28 changes: 28 additions & 0 deletions
28
src/main/java/pl/ais/commons/domain/stereotype/ValueObject.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package pl.ais.commons.domain.stereotype; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
import javax.annotation.concurrent.Immutable; | ||
|
||
/** | ||
* Indicates that an annotated class is a Value Object. | ||
* | ||
* @see <a href="http://martinfowler.com/eaaCatalog/valueObject.html">Value Object (Patterns of Enterprise Application Architecture)</a> | ||
* @see <a href="http://en.wikipedia.org/wiki/Value_object">Value Object (Wikipedia)</a> | ||
* | ||
* @author Warlock, AIS.PL | ||
* @since 1.0.2 | ||
*/ | ||
@Documented | ||
@Immutable | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.TYPE) | ||
public @interface ValueObject { | ||
|
||
// Empty by design ... | ||
|
||
} |