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 * 021 * @author Vladimir Dzhuvinov 022 */ 023public abstract class Identifier implements JSONAware { 024 025 026 /** 027 * The default byte length of generated identifiers. 028 */ 029 public static final int DEFAULT_BYTE_LENGTH = 32; 030 031 032 /** 033 * The secure random generator. 034 */ 035 private static final SecureRandom secureRandom = new SecureRandom(); 036 037 038 /** 039 * The identifier value. 040 */ 041 private final String value; 042 043 044 /** 045 * Creates a new identifier with the specified value. 046 * 047 * @param value The identifier value. Must not be {@code null} or empty 048 * string. 049 */ 050 public Identifier(final String value) { 051 052 if (StringUtils.isBlank(value)) 053 throw new IllegalArgumentException("The value must not be null or empty string"); 054 055 this.value = value; 056 } 057 058 059 /** 060 * Creates a new identifier with a randomly generated value of the 061 * specified byte length, Base64URL-encoded. 062 * 063 * @param byteLength The byte length of the value to generate. Must be 064 * greater than one. 065 */ 066 public Identifier(final int byteLength) { 067 068 if (byteLength < 1) 069 throw new IllegalArgumentException("The byte length must be a positive integer"); 070 071 byte[] n = new byte[byteLength]; 072 073 secureRandom.nextBytes(n); 074 075 value = Base64.encodeBase64URLSafeString(n); 076 } 077 078 079 /** 080 * Creates a new identifier with a randomly generated 256-bit 081 * (32-byte) value, Base64URL-encoded. 082 */ 083 public Identifier() { 084 085 this(DEFAULT_BYTE_LENGTH); 086 } 087 088 089 /** 090 * Returns the value of this identifier. 091 * 092 * @return The value. 093 */ 094 public String getValue() { 095 096 return value; 097 } 098 099 100 /** 101 * Returns the JSON string representation of this identifier. 102 * 103 * @return The JSON string. 104 */ 105 @Override 106 public String toJSONString() { 107 108 StringBuilder sb = new StringBuilder("\""); 109 sb.append(JSONValue.escape(value)); 110 sb.append('"'); 111 return sb.toString(); 112 } 113 114 115 /** 116 * @see #getValue 117 */ 118 @Override 119 public String toString() { 120 121 return getValue(); 122 } 123 124 125 /** 126 * Overrides {@code Object.hashCode()}. 127 * 128 * @return The object hash code. 129 */ 130 @Override 131 public int hashCode() { 132 133 return value.hashCode(); 134 } 135 136 137 /** 138 * Overrides {@code Object.equals()}. 139 * 140 * @param object The object to compare to. 141 * 142 * @return {@code true} if the objects have the same value, otherwise 143 * {@code false}. 144 */ 145 @Override 146 public abstract boolean equals(final Object object); 147}