keepass2android/src/java/JavaFileStorage/app/src/main/java/com/microsoft/live/LiveConnectSession.java

312 lines
9.1 KiB
Java

//------------------------------------------------------------------------------
// Copyright (c) 2012 Microsoft Corporation. All rights reserved.
//
// Description: See the class level JavaDoc comments.
//------------------------------------------------------------------------------
package com.microsoft.live;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* Represents a Live Connect session.
*/
public class LiveConnectSession {
private String accessToken;
private String authenticationToken;
/** Keeps track of all the listeners, and fires the property change events */
private final PropertyChangeSupport changeSupport;
/**
* The LiveAuthClient that created this object.
* This is needed in order to perform a refresh request.
* There is a one-to-one relationship between the LiveConnectSession and LiveAuthClient.
*/
private final LiveAuthClient creator;
private Date expiresIn;
private String refreshToken;
private Set<String> scopes;
private String tokenType;
/**
* Constructors a new LiveConnectSession, and sets its creator to the passed in
* LiveAuthClient. All other member variables are left uninitialized.
*
* @param creator
*/
LiveConnectSession(LiveAuthClient creator) {
assert creator != null;
this.creator = creator;
this.changeSupport = new PropertyChangeSupport(this);
}
/**
* Adds a {@link PropertyChangeListener} to the session that receives notification when any
* property is changed.
*
* @param listener
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
if (listener == null) {
return;
}
this.changeSupport.addPropertyChangeListener(listener);
}
/**
* Adds a {@link PropertyChangeListener} to the session that receives notification when a
* specific property is changed.
*
* @param propertyName
* @param listener
*/
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
if (listener == null) {
return;
}
this.changeSupport.addPropertyChangeListener(propertyName, listener);
}
/**
* @return The access token for the signed-in, connected user.
*/
public String getAccessToken() {
return this.accessToken;
}
/**
* @return A user-specific token that provides information to an app so that it can validate
* the user.
*/
public String getAuthenticationToken() {
return this.authenticationToken;
}
/**
* @return The exact time when a session expires.
*/
public Date getExpiresIn() {
// Defensive copy
return new Date(this.expiresIn.getTime());
}
/**
* @return An array of all PropertyChangeListeners for this session.
*/
public PropertyChangeListener[] getPropertyChangeListeners() {
return this.changeSupport.getPropertyChangeListeners();
}
/**
* @param propertyName
* @return An array of all PropertyChangeListeners for a specific property for this session.
*/
public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
return this.changeSupport.getPropertyChangeListeners(propertyName);
}
/**
* @return A user-specific refresh token that the app can use to refresh the access token.
*/
public String getRefreshToken() {
return this.refreshToken;
}
/**
* @return The scopes that the user has consented to.
*/
public Iterable<String> getScopes() {
// Defensive copy is not necessary, because this.scopes is an unmodifiableSet
return this.scopes;
}
/**
* @return The type of token.
*/
public String getTokenType() {
return this.tokenType;
}
/**
* @return {@code true} if the session is expired.
*/
public boolean isExpired() {
if (this.expiresIn == null) {
return true;
}
final Date now = new Date();
return now.after(this.expiresIn);
}
/**
* Removes a PropertyChangeListeners on a session.
* @param listener
*/
public void removePropertyChangeListener(PropertyChangeListener listener) {
if (listener == null) {
return;
}
this.changeSupport.removePropertyChangeListener(listener);
}
/**
* Removes a PropertyChangeListener for a specific property on a session.
* @param propertyName
* @param listener
*/
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener == null) {
return;
}
this.changeSupport.removePropertyChangeListener(propertyName, listener);
}
@Override
public String toString() {
return String.format("LiveConnectSession [accessToken=%s, authenticationToken=%s, expiresIn=%s, refreshToken=%s, scopes=%s, tokenType=%s]",
this.accessToken,
this.authenticationToken,
this.expiresIn,
this.refreshToken,
this.scopes,
this.tokenType);
}
boolean contains(Iterable<String> scopes) {
if (scopes == null) {
return true;
} else if (this.scopes == null) {
return false;
}
for (String scope : scopes) {
if (!this.scopes.contains(scope)) {
return false;
}
}
return true;
}
/**
* Fills in the LiveConnectSession with the OAuthResponse.
* WARNING: The OAuthResponse must not contain OAuth.ERROR.
*
* @param response to load from
*/
void loadFromOAuthResponse(OAuthSuccessfulResponse response) {
this.accessToken = response.getAccessToken();
this.tokenType = response.getTokenType().toString().toLowerCase();
if (response.hasAuthenticationToken()) {
this.authenticationToken = response.getAuthenticationToken();
}
if (response.hasExpiresIn()) {
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, response.getExpiresIn());
this.setExpiresIn(calendar.getTime());
}
if (response.hasRefreshToken()) {
this.refreshToken = response.getRefreshToken();
}
if (response.hasScope()) {
final String scopeString = response.getScope();
this.setScopes(Arrays.asList(scopeString.split(OAuth.SCOPE_DELIMITER)));
}
}
/**
* Refreshes this LiveConnectSession
*
* @return true if it was able to refresh the refresh token.
*/
boolean refresh() {
return this.creator.refresh();
}
void setAccessToken(String accessToken) {
final String oldValue = this.accessToken;
this.accessToken = accessToken;
this.changeSupport.firePropertyChange("accessToken", oldValue, this.accessToken);
}
void setAuthenticationToken(String authenticationToken) {
final String oldValue = this.authenticationToken;
this.authenticationToken = authenticationToken;
this.changeSupport.firePropertyChange("authenticationToken",
oldValue,
this.authenticationToken);
}
void setExpiresIn(Date expiresIn) {
final Date oldValue = this.expiresIn;
this.expiresIn = new Date(expiresIn.getTime());
this.changeSupport.firePropertyChange("expiresIn", oldValue, this.expiresIn);
}
void setRefreshToken(String refreshToken) {
final String oldValue = this.refreshToken;
this.refreshToken = refreshToken;
this.changeSupport.firePropertyChange("refreshToken", oldValue, this.refreshToken);
}
void setScopes(Iterable<String> scopes) {
final Iterable<String> oldValue = this.scopes;
// Defensive copy
this.scopes = new HashSet<String>();
if (scopes != null) {
for (String scope : scopes) {
this.scopes.add(scope);
}
}
this.scopes = Collections.unmodifiableSet(this.scopes);
this.changeSupport.firePropertyChange("scopes", oldValue, this.scopes);
}
void setTokenType(String tokenType) {
final String oldValue = this.tokenType;
this.tokenType = tokenType;
this.changeSupport.firePropertyChange("tokenType", oldValue, this.tokenType);
}
boolean willExpireInSecs(int secs) {
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, secs);
final Date future = calendar.getTime();
// if add secs seconds to the current time and it is after the expired time
// then it is almost expired.
return future.after(this.expiresIn);
}
}