001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.oauth2.sdk.id;
019
020
021import java.io.Serializable;
022import java.security.SecureRandom;
023
024import com.nimbusds.jose.util.Base64URL;
025import com.nimbusds.oauth2.sdk.util.StringUtils;
026import net.minidev.json.JSONAware;
027import net.minidev.json.JSONValue;
028
029
030/**
031 * The base class for representing identifiers and identities. Provides
032 * constructors that generate Base64URL-encoded secure random identifier
033 * values.
034 *
035 * <p>Extending classes must override the {@link #equals} method.
036 */
037public class Identifier implements Serializable, Comparable<Identifier>, JSONAware {
038        
039        
040        /**
041         * The default byte length of generated identifiers.
042         */
043        public static final int DEFAULT_BYTE_LENGTH = 32;
044        
045        
046        /**
047         * The secure random generator.
048         */
049        private static final SecureRandom secureRandom = new SecureRandom();
050
051
052        /**
053         * The identifier value.
054         */
055        private final String value;
056
057
058        /**
059         * Creates a new identifier with the specified value.
060         *
061         * @param value The identifier value. Must not be {@code null} or empty
062         *              string.
063         */
064        public Identifier(final String value) {
065
066                if (StringUtils.isBlank(value))
067                        throw new IllegalArgumentException("The value must not be null or empty string");
068
069                this.value = value;
070        }
071
072
073        /**
074         * Creates a new identifier with a randomly generated value of the 
075         * specified byte length, Base64URL-encoded.
076         *
077         * @param byteLength The byte length of the value to generate. Must be
078         *                   greater than one.
079         */
080        public Identifier(final int byteLength) {
081                
082                if (byteLength < 1)
083                        throw new IllegalArgumentException("The byte length must be a positive integer");
084                
085                byte[] n = new byte[byteLength];
086                
087                secureRandom.nextBytes(n);
088
089                value = Base64URL.encode(n).toString();
090        }
091        
092        
093        /**
094         * Creates a new identifier with a randomly generated 256-bit 
095         * (32-byte) value, Base64URL-encoded.
096         */
097        public Identifier() {
098
099                this(DEFAULT_BYTE_LENGTH);
100        }
101
102
103        /**
104         * Returns the value of this identifier.
105         *
106         * @return The value.
107         */
108        public String getValue() {
109
110                return value;
111        }
112
113
114        /**
115         * Returns the JSON string representation of this identifier.
116         *
117         * @return The JSON string.
118         */
119        @Override
120        public String toJSONString() {
121                
122                return  "\"" + JSONValue.escape(value) + '"';
123        }
124        
125        
126        /**
127         * @see #getValue
128         */
129        @Override
130        public String toString() {
131        
132                return getValue();
133        }
134
135
136        @Override
137        public int compareTo(final Identifier other) {
138
139                return getValue().compareTo(other.getValue());
140        }
141
142
143        @Override
144        public boolean equals(final Object o) {
145                if (this == o) return true;
146                if (o == null || getClass() != o.getClass()) return false;
147
148                Identifier that = (Identifier) o;
149
150                return getValue() != null ? getValue().equals(that.getValue()) : that.getValue() == null;
151
152        }
153
154
155        @Override
156        public int hashCode() {
157                return getValue() != null ? getValue().hashCode() : 0;
158        }
159}