Skip to content

Instantly share code, notes, and snippets.

View runeflobakk's full-sized avatar

Rune Flobakk runeflobakk

View GitHub Profile
@runeflobakk
runeflobakk / InterfacesAndImplementors.java
Last active September 24, 2021 10:02
Use ArchUnit to inspect interfaces and their subclasses
import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import org.junit.jupiter.api.Test;
import static java.util.function.Function.identity;
import static java.util.function.Predicate.not;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toMap;
class InterfacesAndImplementors {
@runeflobakk
runeflobakk / EqualConsecutiveItemsCounts.java
Last active February 7, 2021 01:28
Terrible oh-so-functional Java
record Count<T>(T item, int count) {
List<Count<T>> sumIf(BiPredicate<? super T, ? super T> shouldSum, Count<T> other) {
return shouldSum.test(item, other.item) ? List.of(new Count<>(item, count + other.count)) : List.of(this, other);
}
@Override
public String toString() {
return "(\"" + item + "\"," + count + ")";
}
}

Tids-APIet f.o.m. Java 8 har konseptet Clock som gjør at man kan styre tidspunkter som resolves "fra miljøet/systemklokka" i tester. JodaTime gjør dette ved at man kaller på noen statiske metoder som globalt styrer hvordan JodaTime resolver tidspunkt hver gang man typisk ber om DateTime.now() eller tilsvarende. I Java Time API bruker man i stedet en instans av Clock. Jeg er mest fan av Java sin approach, selv om den kan virke mer tungvinn hvis man er vandt med "umiddelbarheten" ved å bare kalle på en statisk utility som overstyrer klokka globalt.

Grunner til at jeg foretrekker klokke-instans fremfor static metode for global styring er:

  • man ser tydeligere at en klasse faktisk har en avhengighet til tiden, siden den må ha et eget Clock-felt, ev ta det inn i en metode.
  • dersom det føles rart å ta inn en Clocker det ofte også feil, og man bør ta inn en spesifikk tidsverdi som er resolvet utenfra. Det er ikke like le
@runeflobakk
runeflobakk / gist:1326485
Created October 30, 2011 21:44
Snippet: Dersom det ikke finnes ConfigAttributes som støttes av SecurityLevelVoter, returner ACCESS_ABSTAIN. Java 8 Project Lambda-syntaks.
Collection<ConfigAttribute> supportedAttributes =
select(attributes, attr -> this.supports(attr));
if (supportedAttributes.isEmpty()) {
return ACCESS_ABSTAIN;
}
@runeflobakk
runeflobakk / SecurityLevelVoter#vote.java
Created October 30, 2011 20:48
Hele vote-metoden hvor implementasjonen reflekterer bedre slik vi ville forklart forrutsetningene for brukertilgang.
public int vote(Authentication authentication,
Object object,
Collection<ConfigAttribute> attributes) {
Collection<ConfigAttribute> supportedAttributes =
select(attributes, new SupportedBy(this));
if (supportedAttributes.isEmpty()) {
return ACCESS_ABSTAIN;
}
@runeflobakk
runeflobakk / gist:1326397
Created October 30, 2011 20:36
Vi har en eller flere støttede ConfigAttributes, og sjekker om det finnes en som aksepterer sikkerhetsnivået til principalen.
Object p = authentication.getPrincipal();
if (p instanceof MyPrincipal
&& exists(supportedAttributes, new AcceptingSecurityLevelOf((MyPrincipal) p))) {
return ACCESS_GRANTED;
} else {
return ACCESS_DENIED;
}
@runeflobakk
runeflobakk / AcceptingSecurityLevelOf.java
Created October 30, 2011 20:24
Funksjon for å avgjøre om MyPrincipal sitt sikkerhetsnivå er høyt nok for det som kreves av ConfigAttributes
public class SecurityLevelVoter implements AccessDecisionVoter {
private String securityLevelPrefix = "SECURITY_LEVEL_";
//...snip...
private class AcceptingSecurityLevelOf implements Predicate<ConfigAttribute> {
private final int principalSecurityLevel;
public AcceptingSecurityLevelOf(MyPrincipal principal) {
principalSecurityLevel = toInt(principal.getSecurityLevel(), Integer.MIN_VALUE);
@runeflobakk
runeflobakk / gist:1296896
Created October 18, 2011 22:14
Snippet: Dersom det ikke finnes ConfigAttributes som støttes av SecurityLevelVoter, returner ACCESS_ABSTAIN
Collection<ConfigAttribute> supportedAttributes = select(attributes, new SupportedBy(this));
if (supportedAttributes.isEmpty()) {
return ACCESS_ABSTAIN;
}
@runeflobakk
runeflobakk / SupportedBy.java
Created October 18, 2011 22:06
Funksjon som sjekker om ConfigAttributes støttes av en AccessDecisionVoter.
public class SupportedBy implements Predicate<ConfigAttribute> {
private final AccessDecisionVoter voter;
public SupportedBy(AccessDecisionVoter voter) {
this.voter = voter;
}
public boolean evaluate(ConfigAttribute attribute) {
return voter.supports(attribute);
public class SecurityLevelVoter implements AccessDecisionVoter {
private String securityLevelPrefix = "SECURITY_LEVEL_";
public int vote(Authentication authentication,
Object object,
Collection<ConfigAttribute> attributes) {
int result = ACCESS_ABSTAIN;
Object principal = authentication.getPrincipal();