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