org.wildfly.security.auth.client.MatchRule Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wildfly.security.auth.client;
import static org.wildfly.security.auth.client._private.ElytronMessages.log;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
import org.wildfly.common.net.CidrAddress;
import org.wildfly.common.net.Inet;
/**
* A rule used for deciding which authentication configuration to use.
*
* @author David M. Lloyd
*/
public abstract class MatchRule {
private final MatchRule parent;
/**
* The root rule which matches all URIs.
*/
public static final MatchRule ALL = new MatchRule(null) {
@Override
MatchRule reparent(final MatchRule newParent) {
return this;
}
@Override
public boolean isProtocolMatched() {
return false;
}
@Override
public boolean isTypeMatched() {
return false;
}
@Override
public boolean isTypeAuthorityMatched() {
return false;
}
@Override
public String getMatchProtocol() {
return null;
}
@Override
public String getMatchAbstractType() {
return null;
}
@Override
public String getMatchAbstractTypeAuthority() {
return null;
}
@Override
public boolean isHostMatched() {
return false;
}
@Override
public String getMatchHost() {
return null;
}
@Override
public boolean isPathMatched() {
return false;
}
@Override
public String getMatchPath() {
return null;
}
@Override
public boolean isPortMatched() {
return false;
}
@Override
public int getMatchPort() {
return 0;
}
@Override
public boolean isUserMatched() {
return true;
}
@Override
public String getMatchUser() {
return null;
}
@Override
public boolean isUrnNameMatched() {
return false;
}
@Override
public String getMatchUrnName() {
return null;
}
@Override
public boolean matches(final URI uri, final String abstractType, final String abstractTypeAuthority) {
return true;
}
@Override
MatchRule without(final Class extends MatchRule> clazz) {
return this;
}
@Override
boolean halfEqual(final MatchRule other) {
return true;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
StringBuilder asString(final StringBuilder b) {
return b;
}
};
MatchRule(final MatchRule parent) {
this.parent = parent;
}
abstract MatchRule reparent(MatchRule newParent);
/**
* Determine whether this rule is equal to another object. Two rules are equal if they match the same conditions.
*
* @param other the other object
* @return {@code true} if they are equal, {@code false} otherwise
*/
public final boolean equals(final Object other) {
return other instanceof MatchRule && equals((MatchRule) other);
}
/**
* Determine whether this rule is equal to another. Two rules are equal if they match the same conditions.
*
* @param other the other object
* @return {@code true} if they are equal, {@code false} otherwise
*/
public final boolean equals(MatchRule other) {
return hashCode() == other.hashCode() && halfEqual(other) && other.halfEqual(this);
}
abstract boolean halfEqual(MatchRule other);
final boolean parentHalfEqual(MatchRule other) {
return parent.halfEqual(other);
}
/**
* Get the hash code of this rule.
*
* @return the hash code
*/
public abstract int hashCode();
final int parentHashCode() {
return parent.hashCode();
}
MatchRule without(Class extends MatchRule> clazz) {
if (clazz.isInstance(this)) return parent;
MatchRule newParent = parent.without(clazz);
if (parent == newParent) return this;
return reparent(newParent);
}
/**
* Determine if this rule matches the given URI.
*
* @param uri the URI to test
* @return {@code true} if the rule matches, {@code false} otherwise
*/
public final boolean matches(URI uri) {
return matches(uri, null, null);
}
/**
* Determine if this rule matches the given URI, and type.
*
* @param uri the URI to test
* @param abstractType the abstract type of the connection (may be {@code null})
* @param abstractTypeAuthority the authority name of the abstract type (may be {@code null})
* @return {@code true} if the rule matches, {@code false} otherwise
*/
public boolean matches(URI uri, final String abstractType, final String abstractTypeAuthority) {
return parent.matches(uri, abstractType, abstractTypeAuthority);
}
// protocol (scheme)
/**
* Determine whether this rule matches based on URI protocol (scheme).
*
* @return {@code true} if the rule matches based on URI protocol, {@code false} otherwise
*/
public boolean isProtocolMatched() {
return parent.isProtocolMatched();
}
/**
* Get the protocol (scheme) that this rule matches, or {@code null} if this rule does not match by protocol.
*
* @return the protocol, or {@code null} if there is none
*/
public String getMatchProtocol() {
return parent.getMatchProtocol();
}
/**
* Determine whether this rule matches based on abstract type.
*
* @return {@code true} if the rule matches based on type, {@code false} otherwise
*/
public boolean isTypeMatched() {
return parent.isTypeMatched();
}
/**
* Determine whether this rule matches based on abstract type.
*
* @return {@code true} if the rule matches based on type, {@code false} otherwise
*/
public boolean isTypeAuthorityMatched() {
return parent.isTypeAuthorityMatched();
}
/**
* Get the abstract type that this rule matches, or {@code null} if this rule does not match by abstract type.
*
* @return the abstract type, or {@code null} if there is none
*/
public String getMatchAbstractType() {
return parent.getMatchAbstractType();
}
/**
* Get the abstract type authority that this rule matches, or {@code null} if this rule does not match by abstract type authority.
*
* @return the abstract type, or {@code null} if there is none
*/
public String getMatchAbstractTypeAuthority() {
return parent.getMatchAbstractTypeAuthority();
}
/**
* Create a new rule which is the same as this rule, but also matches the given protocol (scheme) name.
*
* @param protoName the protocol name to match
* @return the new rule
*/
public final MatchRule matchProtocol(String protoName) {
if (protoName == null || protoName.equals("*")) {
return without(MatchSchemeRule.class);
}
return new MatchSchemeRule(this, protoName);
}
/**
* Create a new rule which is the same as this rule, but also matches the given abstract type and type authority.
*
* @param typeName the type to match
* @param authorityName the type authority name to match
* @return the new rule
*/
public final MatchRule matchAbstractType(String typeName, String authorityName) {
MatchRule baseRule;
if (typeName == null || typeName.equals("*")) {
baseRule = without(MatchAbstractTypeRule.class);
} else {
baseRule = new MatchAbstractTypeRule(this, typeName);
}
if (authorityName == null || authorityName.equals("*")) {
return baseRule.without(MatchAbstractTypeAuthorityRule.class);
} else {
return new MatchAbstractTypeAuthorityRule(baseRule, authorityName);
}
}
// host
/**
* Determine whether this rule matches based on host name.
*
* @return {@code true} if the rule matches based on host name, {@code false} otherwise
*/
public boolean isHostMatched() {
return parent.isHostMatched();
}
/**
* Get the host name that this rule matches, or {@code null} if this rule does not match by host.
*
* @return the host name, or {@code null} if there is none
*/
public String getMatchHost() {
return parent.getMatchHost();
}
/**
* Determine whether this rule matches based on network.
*
* @return {@code true} if the rule matches based on network, {@code false} otherwise
*/
public boolean isNetworkMatched() {
return parent.isNetworkMatched();
}
/**
* Get the network that this rule matches, or {@code null} if this rule does not match by network.
*
* @return the network that this rule matches, or {@code null} if there is none
*/
public CidrAddress getMatchNetwork() {
return parent.getMatchNetwork();
}
/**
* Create a new rule which is the same as this rule, but also matches the given host name. If the given string
* appears to be an IP address or a CIDR network specification, then it is treated as such.
*
* @param hostSpec the host name to match
* @return the new rule
*/
public final MatchRule matchHost(String hostSpec) {
if (hostSpec == null || hostSpec.equals("*")) {
return without(MatchHostRule.class).without(MatchNetworkRule.class);
}
final CidrAddress cidrAddress = Inet.parseCidrAddress(hostSpec);
if (cidrAddress != null) {
return new MatchNetworkRule(this, cidrAddress);
}
final InetAddress inetAddress = Inet.parseInetAddress(hostSpec);
if (inetAddress != null) {
return new MatchNetworkRule(this, CidrAddress.create(inetAddress, inetAddress instanceof Inet6Address ? 128 : 32));
}
return new MatchHostRule(this, hostSpec);
}
/**
* Create a new rule which is the same as this rule, but also matches the given Internet address.
*
* @param inetAddress the address to match
* @return the new rule
*/
public final MatchRule matchAddress(InetAddress inetAddress) {
if (inetAddress == null) {
return without(MatchHostRule.class).without(MatchNetworkRule.class);
} else {
return new MatchNetworkRule(this, CidrAddress.create(inetAddress, inetAddress instanceof Inet6Address ? 128 : 32));
}
}
/**
* Create a new rule which is the same as this rule, but also matches the given Internet network address.
*
* @param cidrAddress the network to match
* @return the new rule
*/
public final MatchRule matchNetwork(CidrAddress cidrAddress) {
if (cidrAddress == null) {
return without(MatchHostRule.class).without(MatchNetworkRule.class);
} else {
return new MatchNetworkRule(this, cidrAddress);
}
}
// path
/**
* Determine whether this rule matches based on path name.
*
* @return {@code true} if the rule matches based on path name, {@code false} otherwise
*/
public boolean isPathMatched() {
return parent.isPathMatched();
}
/**
* Get the path name that this rule matches, or {@code null} if this rule does not match by path.
*
* @return the path name, or {@code null} if there is none
*/
public String getMatchPath() {
return parent.getMatchPath();
}
/**
* Create a new rule which is the same as this rule, but also matches the given path name.
*
* @param pathSpec the path name to match
* @return the new rule
*/
public final MatchRule matchPath(String pathSpec) {
if (pathSpec == null || pathSpec.equals("**") || pathSpec.equals("/**")) {
return without(MatchPathRule.class);
}
return new MatchPathRule(this, pathSpec);
}
// port
/**
* Determine whether this rule matches based on port.
*
* @return {@code true} if the rule matches based on port, {@code false} otherwise
*/
public boolean isPortMatched() {
return parent.isPortMatched();
}
/**
* Get the port number that this rule matches, or 0 if this rule does not match by port.
*
* @return the port number, or 0 if there is none
*/
public int getMatchPort() {
return parent.getMatchPort();
}
/**
* Create a new rule which is the same as this rule, but also matches the given port number. The port number must
* be between 1 and 65535 (inclusive).
*
* @param port the port to match
* @return the new rule
*/
public final MatchRule matchPort(int port) {
if (port <= 0 || port > 65535) {
throw log.invalidPortNumber(port);
}
return new MatchPortRule(this, port);
}
// user
// internal builder operations
/**
* Determine whether this rule matches based on non-empty URI user info.
*
* @return {@code true} if the rule matches based on non-empty user info, {@code false} otherwise
*/
public boolean isUserMatched() {
return parent.isUserMatched();
}
/**
* Get the URI user info that this rule matches, or {@code null} if this rule only matches empty URI user info.
*
* @return the user info, or {@code null} if there is none
*/
public String getMatchUser() {
return parent.getMatchUser();
}
/**
* Create a new rule which is the same as this rule, but also matches the given URI user info.
*
* @param userSpec the user info to match
* @return the new rule
*/
public final MatchRule matchUser(String userSpec) {
return userSpec == null ? matchNoUser() : new MatchUserRule(this, userSpec);
}
/**
* Create a new rule which is the same as this rule, but only matches URIs with no user info.
*
* @return the new rule
*/
public final MatchRule matchNoUser() {
return new MatchNoUserRule(this);
}
/**
* Create a new rule which is the same as this rule, but matches URIs with or without user info.
*
* @return the new rule
*/
public final MatchRule matchAnyUser() {
return without(MatchUserRule.class).without(MatchNoUserRule.class);
}
// URN
/**
* Determine whether this rule matches based on URN name.
*
* @return {@code true} if the rule matches based on URN name, {@code false} otherwise
*/
public boolean isUrnNameMatched() {
return parent.isUrnNameMatched();
}
/**
* Get the URN name that this rule matches, or {@code null} if this rule does not match by URN.
*
* @return the URN name, or {@code null} if there is none
*/
public String getMatchUrnName() {
return parent.getMatchUrnName();
}
/**
* Create a new rule which is the same as this rule, but also matches the given URN name.
*
* @param name the URN name to match
* @return the new rule
*/
public final MatchRule matchUrnName(String name) {
return name == null ? without(MatchSchemeSpecificPartRule.class) : new MatchSchemeSpecificPartRule(this, name);
}
/**
* Create a new rule which is the same as this rule, but also matches the given security domain.
*
* @param name the security domain name to match
* @return the new rule
*/
public final MatchRule matchLocalSecurityDomain(String name) {
return name == null ? matchProtocol(null).matchUrnName(null) : matchProtocol("domain").matchUrnName(name);
}
// string
/**
* Get the string representation of this rule.
*
* @return the string representation of this rule
*/
public final String toString() {
final StringBuilder b = new StringBuilder();
asString(b);
if (b.length() > 1) {
b.setLength(b.length() - 1);
}
return b.toString();
}
final StringBuilder parentAsString(StringBuilder b) {
return parent.asString(b);
}
abstract StringBuilder asString(StringBuilder b);
}