001/**
002 * Copyright 2014 Tampere University of Technology, Pori Department
003 * 
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * 
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 * 
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package service.tut.pori.users.google;
017
018import java.lang.reflect.Type;
019import java.util.Date;
020
021import org.apache.commons.lang3.StringUtils;
022import org.apache.log4j.Logger;
023
024import com.google.gson.Gson;
025import com.google.gson.GsonBuilder;
026import com.google.gson.JsonDeserializationContext;
027import com.google.gson.JsonDeserializer;
028import com.google.gson.JsonElement;
029import com.google.gson.JsonParseException;
030import com.google.gson.JsonPrimitive;
031import com.google.gson.JsonSerializationContext;
032import com.google.gson.JsonSerializer;
033import com.google.gson.annotations.SerializedName;
034
035
036/**
037 * OAuth2 Token
038 */
039public class OAuth2Token {
040  private static final Logger LOGGER = Logger.getLogger(OAuth2Token.class);
041  @SerializedName(value=Definitions.JSON_NAME_OAUTH2_ACCESS_TOKEN)
042  private String _accessToken = null;
043  @SerializedName(value=Definitions.JSON_NAME_OAUTH2_EXPIRES_IN)
044  private Date _expires = null;
045  @SerializedName(value=Definitions.JSON_NAME_OAUTH2_REFRESH_TOKEN)
046  private String _refreshToken = null;
047  @SerializedName(value=Definitions.JSON_NAME_OAUTH2_TOKEN_TYPE)
048  private String _type = null;
049  
050  /**
051   * 
052   * @return serializer capable of properly serializing an OAuth2Token
053   */
054  public static Gson getTokenGSONSerializer(){
055    GsonBuilder builder = new GsonBuilder();
056    builder.setPrettyPrinting();
057    
058    JsonSerializer<Date> dateSerializer = new JsonSerializer<Date>() {  
059
060      @Override
061      public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
062        return (src == null ? null : new JsonPrimitive(toExpiresIn(src)));
063      }
064    };  
065    builder.registerTypeAdapter(Date.class, dateSerializer);
066      
067    builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {  // register custom adapter for Dates
068      
069      @Override
070      public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
071        return (json == null ? null : fromExpiresIn(json.getAsLong()));
072      }
073    });
074    return builder.create();
075  }
076  
077  /**
078   * 
079   * @param expiresIn in seconds
080   * @return the expiration date based on the given expiresIn or null if null value was passed
081   */
082  public static Date fromExpiresIn(Long expiresIn){
083    if(expiresIn == null){
084      return null;
085    }
086    return new Date(System.currentTimeMillis()+expiresIn*1000);
087  }
088  
089  /**
090   * 
091   * @param expirationDate
092   * @return seconds to the expiration date (always at least 0) as designated b the expirationDate or null if null passed
093   */
094  public static Long toExpiresIn(Date expirationDate){
095    if(expirationDate == null){
096      return null;
097    }
098    long milliSecondsTo = expirationDate.getTime()-System.currentTimeMillis();  // expiration time somewhere in the future, so unix time is greater
099    if(milliSecondsTo <= 0){  // the expiration time has passed
100      return 0L;
101    }else{
102      return milliSecondsTo/1000; // convert to seconds truncating if necessary
103    }
104  }
105  
106  /**
107   * Note: if you want to know if this token has expired, use isExpired() instead
108   * 
109   * Note: this does not validate the token stricly as defined by the OAuth2 spec
110   * (e.g. http://tools.ietf.org/html/draft-ietf-oauth-v2-31#section-4.2.2),
111   * This is generally because the draft seems to change ~7 times a year, and because
112   * there is an ambiguity on what to do on missing expires_in field. This class
113   * should be subclassed to provide a more accurate (provider specific) implementation
114   * if one is needed.
115   * 
116   * @return true if:
117   *  - the token contains an accessToken, which is NOT expired OR
118   *  - ...the token contains an refreshToken
119   */
120  public boolean isValid(){
121    if(!StringUtils.isEmpty(_refreshToken)){
122      return true;
123    }else if(StringUtils.isEmpty(_accessToken)){
124      return false;
125    }else{
126      return !(isExpired());
127    }
128  }
129  
130  /**
131   * Same as calling expiresIn(0)
132   * @see #expiresIn(long)
133   * 
134   * @return true if this token has expired
135   */
136  public boolean isExpired(){
137    return expiresIn(0);
138  }
139  
140  /**
141   * This returns true if the token has already expired, expires in the the given timeframe or does not have a valid
142   * expiration time
143   * 
144   * @param time the timeframe in ms
145   * @return true if the token expires in the given timeframe
146   */
147  public boolean expiresIn(long time){
148    if(_expires == null){
149      LOGGER.debug("No expiration date given.");
150      return true;
151    }else if(_expires.getTime() <= (System.currentTimeMillis()+time)){
152      return true;
153    }else{
154      return false;
155    }
156  }
157
158  /**
159   * @return the accessToken
160   */
161  public String getAccessToken() {
162    return _accessToken;
163  }
164
165  /**
166   * @param accessToken the accessToken to set
167   */
168  public void setAccessToken(String accessToken) {
169    _accessToken = accessToken;
170  }
171
172  /**
173   * @return the refreshToken
174   */
175  public String getRefreshToken() {
176    return _refreshToken;
177  }
178
179  /**
180   * @param refreshToken the refreshToken to set
181   */
182  public void setRefreshToken(String refreshToken) {
183    _refreshToken = refreshToken;
184  }
185
186  /**
187   * @return the expires
188   */
189  public Date getExpires() {
190    return _expires;
191  }
192
193  /**
194   * @param expires the expires to set
195   */
196  public void setExpires(Date expires) {
197    _expires = expires;
198  }
199  
200  /**
201   * 
202   * @param expiresIn (in seconds)
203   */
204  public void setExpiresIn(Long expiresIn){
205    _expires = fromExpiresIn(expiresIn);
206  }
207
208  /**
209   * @return the type
210   */
211  public String getType() {
212    return _type;
213  }
214
215  /**
216   * @param type the type to set
217   */
218  public void setType(String type) {
219    _type = type;
220  }
221}