001package com.nimbusds.oauth2.sdk.id; 002 003 004import java.security.SecureRandom; 005 006import org.apache.commons.lang3.StringUtils; 007 008import org.apache.commons.codec.binary.Base64; 009 010import net.minidev.json.JSONAware; 011import net.minidev.json.JSONValue; 012 013 014/** 015 * The base abstract class for representing identifiers and identities. 016 * Provides constructors that generate Base64URL-encoded secure random 017 * identifier values. 018 * 019 * <p>Extending classes must override the {@link #equals} method. 020 */ 021public abstract class Identifier implements Comparable<Identifier>, JSONAware { 022 023 024 /** 025 * The default byte length of generated identifiers. 026 */ 027 public static final int DEFAULT_BYTE_LENGTH = 32; 028 029 030 /** 031 * The secure random generator. 032 */ 033 private static final SecureRandom secureRandom = new SecureRandom(); 034 035 036 /** 037 * The identifier value. 038 */ 039 private final String value; 040 041 042 /** 043 * Creates a new identifier with the specified value. 044 * 045 * @param value The identifier value. Must not be {@code null} or empty 046 * string. 047 */ 048 public Identifier(final String value) { 049 050 if (StringUtils.isBlank(value)) 051 throw new IllegalArgumentException("The value must not be null or empty string"); 052 053 this.value = value; 054 } 055 056 057 /** 058 * Creates a new identifier with a randomly generated value of the 059 * specified byte length, Base64URL-encoded. 060 * 061 * @param byteLength The byte length of the value to generate. Must be 062 * greater than one. 063 */ 064 public Identifier(final int byteLength) { 065 066 if (byteLength < 1) 067 throw new IllegalArgumentException("The byte length must be a positive integer"); 068 069 byte[] n = new byte[byteLength]; 070 071 secureRandom.nextBytes(n); 072 073 value = Base64.encodeBase64URLSafeString(n); 074 } 075 076 077 /** 078 * Creates a new identifier with a randomly generated 256-bit 079 * (32-byte) value, Base64URL-encoded. 080 */ 081 public Identifier() { 082 083 this(DEFAULT_BYTE_LENGTH); 084 } 085 086 087 /** 088 * Returns the value of this identifier. 089 * 090 * @return The value. 091 */ 092 public String getValue() { 093 094 return value; 095 } 096 097 098 /** 099 * Returns the JSON string representation of this identifier. 100 * 101 * @return The JSON string. 102 */ 103 @Override 104 public String toJSONString() { 105 106 StringBuilder sb = new StringBuilder("\""); 107 sb.append(JSONValue.escape(value)); 108 sb.append('"'); 109 return sb.toString(); 110 } 111 112 113 /** 114 * @see #getValue 115 */ 116 @Override 117 public String toString() { 118 119 return getValue(); 120 } 121 122 123 @Override 124 public int compareTo(final Identifier other) { 125 126 return getValue().compareTo(other.getValue()); 127 } 128 129 130 /** 131 * Overrides {@code Object.hashCode()}. 132 * 133 * @return The object hash code. 134 */ 135 @Override 136 public int hashCode() { 137 138 return value.hashCode(); 139 } 140 141 142 /** 143 * Overrides {@code Object.equals()}. 144 * 145 * @param object The object to compare to. 146 * 147 * @return {@code true} if the objects have the same value, otherwise 148 * {@code false}. 149 */ 150 @Override 151 public abstract boolean equals(final Object object); 152}