001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/ds/resource/legal-notices/cddl.txt
011     * or http://www.opensource.org/licenses/cddl1.php.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/ds/resource/legal-notices/cddl.txt.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2010-2014 UnboundID Corp.
026     */
027    package com.unboundid.directory.sdk.broker.types;
028    
029    import com.unboundid.util.Mutable;
030    import com.unboundid.util.NotExtensible;
031    import com.unboundid.util.ThreadSafety;
032    import com.unboundid.util.ThreadSafetyLevel;
033    import com.unboundid.util.Validator;
034    
035    import java.util.Collections;
036    import java.util.Date;
037    import java.util.Iterator;
038    import java.util.Set;
039    
040    /**
041     * This class provides a data structure for working with OAuth2 access tokens.
042     */
043    @NotExtensible()
044    @Mutable()
045    @ThreadSafety(level= ThreadSafetyLevel.COMPLETELY_THREADSAFE)
046    public final class AccessToken extends Token
047    {
048      // The user ID associated with this token.
049      private final String userId;
050    
051      // The set of scope IDs for which the application has requested or authorized.
052      private final Set<String> scopeIds;
053    
054      // The refresh token associated with this access token.
055      private volatile RefreshToken refreshToken;
056    
057      /**
058       * Construct a new access token instance.
059       *
060       * @param userId The user ID of the resource owner this access token is
061       *                 associated with or the application ID if resource owner
062       *                 authentication was not performed.
063       * @param applicationId The application ID with which this token is
064       *                      associated. Must not be null.
065       * @param generateTimestamp The time that this token was generated. Must not
066       *                          be null.
067       * @param maxValiditySeconds The maximum length of time in seconds that this
068       *                           token will be considered valid. Must not be null
069       *                           and must not be negative.
070       * @param scopeIds The set of scopes for which the client has been authorized.
071       *                 Must not be null.
072       */
073      public AccessToken(final String userId, final String applicationId,
074                         final Date generateTimestamp,
075                         final long maxValiditySeconds, final Set<String> scopeIds)
076      {
077        super(applicationId, scopeIds, generateTimestamp, maxValiditySeconds);
078        this.userId = userId;
079        this.scopeIds = Collections.unmodifiableSet(scopeIds);
080      }
081    
082      /**
083       * Retrieves the user ID of the resource owner this access token is
084       * associated with. Some grant types don't require resource owner involvement
085       * (ie. client_credentials), the userId may be equal to the application ID in
086       * such cases.
087       *
088       * @return The user ID of the resource owner this access token is associated
089       *         with or equal to the application ID if resource owner
090       *         authentication was not performed.
091       */
092      public String getUserId()
093      {
094        return userId;
095      }
096    
097      /**
098       * Retrieves the refresh token associated with this access token.
099       *
100       * @return The refresh token associated with this access token or {@code null}
101       *         if there is no associated refresh token.
102       */
103      public RefreshToken getRefreshToken()
104      {
105        return refreshToken;
106      }
107    
108      /**
109       * Sets the refresh token associated with this access token.
110       *
111       * @param refreshToken The refresh token associated with this access token.
112       */
113      public void setRefreshToken(final RefreshToken refreshToken)
114      {
115        Validator.ensureNotNull(refreshToken);
116        this.refreshToken = refreshToken;
117      }
118    
119      /**
120       * Retrieves a hash code for this access token.
121       *
122       * @return  A hash code for this access token.
123       */
124      @Override
125      public int hashCode()
126      {
127        final int prime = 31;
128        int result = super.hashCode();
129        result = prime * result + (userId != null ? userId.hashCode() : 0);
130        result = prime * result + (scopeIds != null ? scopeIds.hashCode() : 0);
131        return result;
132      }
133    
134      /**
135       * Indicates whether the provided object is equal to this access token.
136       *
137       * @param  o  The object for which to make the determination.
138       *
139       * @return  {@code true} if the provided object is equal to this authorization
140       *          code, or {@code false} if not.
141       */
142      @Override
143      public boolean equals(final Object o)
144      {
145        if (this == o)
146        {
147          return true;
148        }
149        if (o == null || getClass() != o.getClass())
150        {
151          return false;
152        }
153    
154        AccessToken that = (AccessToken) o;
155    
156        if (scopeIds != null ?
157            !scopeIds.equals(that.scopeIds) :
158            that.scopeIds != null)
159        {
160          return false;
161        }
162        if (userId != null ?
163            !userId.equals(that.userId) :
164            that.userId != null)
165        {
166          return false;
167        }
168        if (refreshToken != null ?
169            !refreshToken.equals(that.refreshToken) :
170            that.refreshToken != null)
171        {
172          return false;
173        }
174    
175        return super.equals(o);
176      }
177    
178      /**
179       * Appends a string representation of this access token to the provided
180       * buffer.
181       *
182       * @param  buffer  The buffer to which the string representation should be
183       *                 appended.
184       */
185      protected void toString(final StringBuilder buffer)
186      {
187        buffer.append("AccessToken(userId='");
188        buffer.append(userId);
189        buffer.append("', appID=");
190        buffer.append(getApplicationId());
191        buffer.append(", generateTimestamp=");
192        buffer.append(getGenerateTimestamp());
193        buffer.append("', maxValiditySeconds=");
194        buffer.append(getMaxValiditySeconds());
195        buffer.append(", value=");
196        buffer.append(getValue());
197    
198        if (! scopeIds.isEmpty())
199        {
200          buffer.append(", scopes={");
201    
202          final Iterator<String> iterator = scopeIds.iterator();
203          while (iterator.hasNext())
204          {
205            buffer.append(iterator.next());
206            if (iterator.hasNext())
207            {
208              buffer.append(", ");
209            }
210          }
211    
212          buffer.append('}');
213        }
214    
215        buffer.append("')");
216      }
217    }