/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.sun.lwuit.io.util;
import com.sun.lwuit.Component;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.html.AsyncDocumentRequestHandler.IOCallback;
import com.sun.lwuit.html.DocumentInfo;
import com.sun.lwuit.html.HTMLComponent;
import com.sun.lwuit.io.ConnectionRequest;
import com.sun.lwuit.io.html.AsyncDocumentRequestHandlerImpl;
import com.sun.lwuit.layouts.BorderLayout;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* This is a utility class that allows Oauth2 authentication
* This utility uses the LWUIT XHTML Component to display the authentication
* pages.
* http://tools.ietf.org/pdf/draft-ietf-oauth-v2-12.pdf
*
* @author Chen Fishbein
*/
public class Oauth2 {
public static final String TOKEN = "access_token";
private String token;
private String clientId;
private String redirectURI;
private String scope;
private String OauthURL;
private Hashtable additionalParams;
private IOException error;
/**
* Simple constructor
*
* @param OauthURL the authentication url of the service
* @param clientId the client id that would like to use the service
* @param redirectURI the redirect uri
* @param scope the authentication scope
*/
public Oauth2(String OauthURL, String clientId, String redirectURI, String scope) {
this(OauthURL, clientId, redirectURI, scope, null);
}
/**
* Simple constructor
*
* @param OauthURL the authentication url of the service
* @param clientId the client id that would like to use the service
* @param redirectURI the redirect uri
* @param scope the authentication scope
* @param additionalParams hashtable of additional parameters to the
* authentication request
*/
public Oauth2(String OauthURL, String clientId, String redirectURI, String scope, Hashtable additionalParams) {
this.OauthURL = OauthURL;
this.redirectURI = redirectURI;
this.clientId = clientId;
this.scope = scope;
this.additionalParams = additionalParams;
}
/**
* This method preforms the actual authentication, this method is a blocking
* method that will display the user the html authentication pages.
*
* @return the method if passes authentication will return the access token
* or null if authentication failed.
*
* @throws IOException the method will throw an IOException if something went
* wrong in the communication.
*/
public String authenticate() throws IOException{
if (token == null) {
final Form current = Display.getInstance().getCurrent();
final boolean[] loginFlag = new boolean[1];
error = null;
Form login = new Form();
login.setLayout(new BorderLayout());
login.setScrollable(false);
Component html = createLoginComponent(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
loginFlag[0] = true;
}
});
login.addComponent(BorderLayout.CENTER, html);
login.show();
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
while (!loginFlag[0]) {
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
if (current != null) {
current.show();
}
}
});
if(error != null){
throw error;
}
}
return token;
}
private Component createLoginComponent(final ActionListener loginCallback) {
String URL = OauthURL + "?client_id=" + clientId
+ "&redirect_uri=" + Util.encodeUrl(redirectURI) + "&scope=" + scope + "&response_type=token";
if (additionalParams != null) {
Enumeration e = additionalParams.keys();
while(e.hasMoreElements()){
String key = (String) e.nextElement();
String val = additionalParams.get(key).toString();
URL += "&" + key + "=" + val;
}
}
HTMLComponent c = new HTMLComponent(new AsyncDocumentRequestHandlerImpl() {
protected ConnectionRequest createConnectionRequest(final DocumentInfo docInfo, final IOCallback callback, final Object[] response) {
return new ConnectionRequest() {
protected void buildRequestBody(OutputStream os) throws IOException {
if (isPost()) {
if (docInfo.getParams() != null) {
OutputStreamWriter w = new OutputStreamWriter(os, docInfo.getEncoding());
w.write(docInfo.getParams());
}
}
}
protected void handleIOException(IOException err) {
if (callback == null) {
response[0] = err;
}
error = err;
loginCallback.actionPerformed(null);
}
protected boolean shouldAutoCloseResponse() {
return callback != null;
}
protected void readResponse(InputStream input) throws IOException {
BufferedInputStream i;
if (input instanceof BufferedInputStream) {
i = (BufferedInputStream) input;
} else {
i = new BufferedInputStream(input);
}
i.setYield(-1);
if (callback != null) {
callback.streamReady(input, docInfo);
} else {
response[0] = input;
synchronized (LOCK) {
LOCK.notify();
}
}
}
public boolean onRedirect(String url) {
if ((url.startsWith(redirectURI))){
boolean success = url.indexOf("#") > -1;
if(success){
String accessToken = url.substring(url.indexOf("#") + 1);
token = accessToken.substring(accessToken.indexOf("=") + 1, accessToken.indexOf("&"));
}
loginCallback.actionPerformed(null);
return true;
}
return false;
}
};
}
});
c.setPage(URL);
c.getDocumentInfo().setPostRequest(true);
c.setIgnoreCSS(true);
c.getDocumentInfo().setEncoding("UTF-8");
return c;
}
}