Author: anil.saldhana(a)jboss.com
Date: 2011-09-22 14:54:06 -0400 (Thu, 22 Sep 2011)
New Revision: 1246
Added:
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookProcessor.java
Modified:
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookAuthenticator.java
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookLoginModule.java
Log:
refactor and clean fb integration
Modified:
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookAuthenticator.java
===================================================================
---
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookAuthenticator.java 2011-09-22
05:19:29 UTC (rev 1245)
+++
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookAuthenticator.java 2011-09-22
18:54:06 UTC (rev 1246)
@@ -22,18 +22,9 @@
package org.picketlink.social.facebook;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLDecoder;
-import java.net.URLEncoder;
import java.security.Principal;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
@@ -46,10 +37,7 @@
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.LoginConfig;
-import org.apache.catalina.realm.GenericPrincipal;
import org.apache.log4j.Logger;
-import org.json.JSONException;
-import org.json.JSONObject;
/**
* Component for sending login requests to Facebook.
@@ -63,24 +51,19 @@
protected static Logger log = Logger.getLogger(FacebookAuthenticator.class);
protected boolean trace = log.isTraceEnabled();
- public static ThreadLocal<Principal> cachedPrincipal = new
ThreadLocal<Principal>();
-
- public static ThreadLocal<List<String>> cachedRoles = new
ThreadLocal<List<String>>();
-
- protected FacebookUtil util = new FacebookUtil(FacebookConstants.SERVICE_URL);
protected String returnURL;
protected String clientID;
protected String clientSecret;
- protected String scope;
+ protected String scope = "email";
protected List<String> roles = new ArrayList<String>();
//Whether the authenticator has to to save and restore request
protected boolean saveRestoreRequest = true;
- public static String EMPTY_PASSWORD = "EMPTY";
-
private enum STATES { AUTH, AUTHZ, FINISH};
+
+ protected FacebookProcessor processor;
public void setReturnURL(String returnURL)
{
@@ -140,12 +123,14 @@
throw new IOException("Not of type Catalina response");
return authenticate((Request)request, (Response)response, loginConfig);
}
-
- @Override
+
public boolean authenticate(Request request, Response response, LoginConfig
loginConfig) throws IOException
{
if(trace) log.trace("authenticate");
+ if(processor == null)
+ processor = new FacebookProcessor(clientID, clientSecret, scope, returnURL,
roles);
+
HttpSession session = request.getSession();
String state = (String) session.getAttribute("STATE");
@@ -160,55 +145,24 @@
{
this.saveRequest(request, request.getSessionInternal());
}
- Map<String, String> params = new HashMap<String, String>();
- params.put(OAuthConstants.REDIRECT_URI_PARAMETER, this.returnURL);
- params.put(OAuthConstants.CLIENT_ID_PARAMETER, this.clientID);
- if (scope != null)
- {
- params.put(OAuthConstants.SCOPE_PARAMETER, scope);
- }
- String location = new
StringBuilder(FacebookConstants.SERVICE_URL).append("?").append(
- util.createQueryString(params)).toString();
- try
- {
- session.setAttribute("STATE", STATES.AUTH.name());
- if(trace) log.trace("Redirect:"+location);
- response.sendRedirect(location);
- return false;
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
+ return processor.initialInteraction(request, response);
}
//We have sent an auth request
if( state.equals(STATES.AUTH.name()))
{
- return handleAuthStage(request, response);
-
+ return processor.handleAuthStage(request, response);
}
- Principal facebookPrincipal = null;
+ //Principal facebookPrincipal = null;
if( state.equals(STATES.AUTHZ.name()))
- {
- Principal principal = null;
- facebookPrincipal = handleAuthenticationResponse(request, response);
+ {
+ Principal principal = processor.getPrincipal(request, response,
context.getRealm());
- request.getSession().setAttribute("principal", facebookPrincipal);
- cachedPrincipal.set(facebookPrincipal);
+ if(principal == null)
+ throw new RuntimeException("Principal was null. Maybe login modules need
to be configured properly.");
+ String userName = principal.getName();
- if(isJBossEnv())
- {
- cachedRoles.set(roles);
- principal = context.getRealm().authenticate(facebookPrincipal.getName(),
EMPTY_PASSWORD);
- }
- else
- {
- //Create a Tomcat Generic Principal
- principal = new GenericPrincipal(getContainer().getRealm(),
facebookPrincipal.getName(), null, roles, facebookPrincipal);
- }
-
- request.getSessionInternal().setNote(Constants.SESS_USERNAME_NOTE,
facebookPrincipal.getName());
+ request.getSessionInternal().setNote(Constants.SESS_USERNAME_NOTE, userName);
request.getSessionInternal().setNote(Constants.SESS_PASSWORD_NOTE,
"");
request.setUserPrincipal(principal);
@@ -216,208 +170,11 @@
{
this.restoreRequest(request, request.getSessionInternal());
}
- register(request, response, principal, Constants.FORM_METHOD,
facebookPrincipal.getName(), "");
+ register(request, response, principal, Constants.FORM_METHOD, userName,
"");
request.getSession().setAttribute("STATE", STATES.FINISH.name());
return true;
}
return false;
}
-
- protected void sendAuthorizeRequest(String returnUrl, HttpServletResponse response)
- {
- //String returnUri = util.getReturnUri(returnUrl);
- String returnUri = returnUrl;
-
- Map<String, String> params = new HashMap<String, String>();
- params.put(OAuthConstants.REDIRECT_URI_PARAMETER, returnUri);
- params.put(OAuthConstants.CLIENT_ID_PARAMETER, clientID);
- if (scope != null)
- {
- params.put(OAuthConstants.SCOPE_PARAMETER, scope);
- }
- String location = new
StringBuilder(FacebookConstants.AUTHENTICATION_ENDPOINT_URL).append("?").append(
- util.createQueryString(params)).toString();
- try
- {
- response.sendRedirect(location);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
- protected URLConnection sendAccessTokenRequest(String returnUrl, String
authorizationCode, HttpServletResponse response)
- {
- String returnUri = returnURL;
-
- Map<String, String> params = new HashMap<String, String>();
- params.put(OAuthConstants.REDIRECT_URI_PARAMETER, returnUri);
- params.put(OAuthConstants.CLIENT_ID_PARAMETER, clientID);
- params.put(OAuthConstants.CLIENT_SECRET_PARAMETER, clientSecret);
- params.put(OAuthConstants.CODE_PARAMETER, authorizationCode);
-
- String location = new
StringBuilder(FacebookConstants.ACCESS_TOKEN_ENDPOINT_URL).append("?").append(
- util.createQueryString(params)).toString();
-
- try
- {
- if(trace) log.trace("AccessToken Request="+location);
- URL url = new URL(location);
- URLConnection connection = url.openConnection();
- return connection;
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- }
-
-
-
- protected Principal handleAuthenticationResponse(HttpServletRequest request,
HttpServletResponse response)
- {
- String error = request.getParameter(OAuthConstants.ERROR_PARAMETER);
- if (error != null)
- {
- throw new RuntimeException("error:" + error);
- }
- else
- {
- String returnUrl = returnURL;
- String authorizationCode = request.getParameter(OAuthConstants.CODE_PARAMETER);
- if (authorizationCode == null)
- {
- throw new RuntimeException("Authorization code parameter not
found");
- }
-
- URLConnection connection = sendAccessTokenRequest(returnUrl, authorizationCode,
response);
-
- Map<String, String> params = formUrlDecode(readUrlContent(connection));
- String accessToken = params.get(OAuthConstants.ACCESS_TOKEN_PARAMETER);
- String expires = params.get(FacebookConstants.EXPIRES);
-
- if(trace) log.trace("Access Token=" + accessToken + " ::
Expires=" + expires);
-
- if (accessToken == null)
- {
- throw new RuntimeException("No access token found");
- }
-
- return readInIdentity(request, response, accessToken, returnUrl);
- }
- }
-
- private boolean handleAuthStage(HttpServletRequest request, HttpServletResponse
response)
- {
- request.getSession().setAttribute("STATE",STATES.AUTHZ.name());
- sendAuthorizeRequest(this.returnURL, response);
- return false;
- }
-
-
- private boolean isJBossEnv()
- {
- ClassLoader tcl = SecurityActions.getContextClassLoader();
- Class<?> clazz = null;
- try
- {
- clazz = tcl.loadClass("org.jboss.system.Service");
- }
- catch (ClassNotFoundException e)
- {
- }
- if( clazz != null )
- return true;
- return false;
- }
-
- private Principal readInIdentity(HttpServletRequest request, HttpServletResponse
response, String accessToken, String returnUrl)
- {
- FacebookPrincipal facebookPrincipal = null;
- try
- {
- String urlString = new
StringBuilder(FacebookConstants.PROFILE_ENDPOINT_URL).append("?access_token=").append(
- URLEncoder.encode(accessToken, "UTF-8")).toString();
- if(trace) log.trace("Profile read:"+urlString);
-
- URL profileUrl = new URL(urlString);
- String profileContent = readUrlContent(profileUrl.openConnection());
- JSONObject jsonObject = new JSONObject(profileContent);
-
- facebookPrincipal = new FacebookPrincipal();
- facebookPrincipal.setAccessToken(accessToken);
- facebookPrincipal.setId(jsonObject.getString("id"));
- facebookPrincipal.setName(jsonObject.getString("name"));
- facebookPrincipal.setFirstName(jsonObject.getString("first_name"));
- facebookPrincipal.setLastName(jsonObject.getString("last_name"));
- facebookPrincipal.setGender(jsonObject.getString("gender"));
- facebookPrincipal.setTimezone(jsonObject.getString("timezone"));
- facebookPrincipal.setLocale(jsonObject.getString("locale"));
- if (jsonObject.getString("email") != null)
- {
- facebookPrincipal.setEmail(jsonObject.getString("email"));
- }
- }
- catch (JSONException e)
- {
- throw new RuntimeException(e);
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
-
- return facebookPrincipal;
- }
-
- private String readUrlContent(URLConnection connection)
- {
- StringBuilder result = new StringBuilder();
- try
- {
- Reader reader = new InputStreamReader(connection.getInputStream());
- char[] buffer = new char[50];
- int nrOfChars;
- while ((nrOfChars = reader.read(buffer)) != -1)
- {
- result.append(buffer, 0, nrOfChars);
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException(e);
- }
- return result.toString();
- }
-
- private Map<String, String> formUrlDecode(String encodedData)
- {
- Map<String, String> params = new HashMap<String, String>();
- String[] elements = encodedData.split("&");
- for (String element : elements)
- {
- String[] pair = element.split("=");
- if (pair.length == 2)
- {
- String paramName = pair[0];
- String paramValue;
- try
- {
- paramValue = URLDecoder.decode(pair[1], "UTF-8");
- }
- catch (UnsupportedEncodingException e)
- {
- throw new RuntimeException(e);
- }
- params.put(paramName, paramValue);
- }
- else
- {
- throw new RuntimeException("Unexpected name-value pair in response:
" + element);
- }
- }
- return params;
- }
}
\ No newline at end of file
Modified:
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookLoginModule.java
===================================================================
---
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookLoginModule.java 2011-09-22
05:19:29 UTC (rev 1245)
+++
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookLoginModule.java 2011-09-22
18:54:06 UTC (rev 1246)
@@ -33,7 +33,7 @@
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
/**
- * A {@link LoginModule} for JBoss environment
+ * A {@link LoginModule} for JBoss environment to support facebook authentication
* @author Anil Saldhana
* @since May 19, 2011
*/
@@ -42,13 +42,13 @@
@Override
protected Principal getIdentity()
{
- return FacebookAuthenticator.cachedPrincipal.get();
+ return FacebookProcessor.cachedPrincipal.get();
}
@Override
protected String getUsersPassword() throws LoginException
{
- return FacebookAuthenticator.EMPTY_PASSWORD;
+ return FacebookProcessor.EMPTY_PASSWORD;
}
@Override
@@ -56,7 +56,7 @@
{
Group group = new SimpleGroup("Roles");
- List<String> roles = FacebookAuthenticator.cachedRoles.get();
+ List<String> roles = FacebookProcessor.cachedRoles.get();
if(roles != null)
{
Added:
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookProcessor.java
===================================================================
---
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookProcessor.java
(rev 0)
+++
social/trunk/facebook/src/main/java/org/picketlink/social/facebook/FacebookProcessor.java 2011-09-22
18:54:06 UTC (rev 1246)
@@ -0,0 +1,338 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2011, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.social.facebook;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.Realm;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.log4j.Logger;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Processor to perform Facebook interaction
+ * @author Anil Saldhana
+ * @since Sep 22, 2011
+ */
+public class FacebookProcessor
+{
+ protected static Logger log = Logger.getLogger(FacebookProcessor.class);
+ protected boolean trace = log.isTraceEnabled();
+
+ protected FacebookUtil util = new FacebookUtil(FacebookConstants.SERVICE_URL);
+
+ public static ThreadLocal<Principal> cachedPrincipal = new
ThreadLocal<Principal>();
+
+ public static ThreadLocal<List<String>> cachedRoles = new
ThreadLocal<List<String>>();
+ public static String EMPTY_PASSWORD = "EMPTY";
+
+ protected List<String> roles = new ArrayList<String>();
+
+ public enum STATES { AUTH, AUTHZ, FINISH};
+
+ protected String clientID;
+ protected String clientSecret;
+ protected String scope;
+ private String returnURL;
+
+ public FacebookProcessor(String clientID, String clientSecret, String scope, String
returnURL, List<String> requiredRoles)
+ {
+ super();
+ this.clientID = clientID;
+ this.clientSecret = clientSecret;
+ this.scope = scope;
+ this.returnURL = returnURL;
+ this.roles.addAll(requiredRoles);
+ }
+
+ public void setRoleString(String roleStr)
+ {
+ if(roleStr == null)
+ throw new RuntimeException("Role String is null in configuration");
+ StringTokenizer st = new StringTokenizer(roleStr, ",");
+ while(st.hasMoreElements())
+ {
+ roles.add(st.nextToken());
+ }
+ }
+
+ public boolean initialInteraction(Request request, Response response) throws
IOException
+ {
+ HttpSession session = request.getSession();
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(OAuthConstants.REDIRECT_URI_PARAMETER, returnURL);
+ params.put(OAuthConstants.CLIENT_ID_PARAMETER, clientID);
+
+ if (scope != null)
+ {
+ params.put(OAuthConstants.SCOPE_PARAMETER, scope);
+ }
+
+ String location = new
StringBuilder(FacebookConstants.SERVICE_URL).append("?").append(
+ util.createQueryString(params)).toString();
+ try
+ {
+ session.setAttribute("STATE", STATES.AUTH.name());
+ if(trace) log.trace("Redirect:"+location);
+ response.sendRedirect(location);
+ return false;
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean handleAuthStage(HttpServletRequest request, HttpServletResponse
response)
+ {
+ request.getSession().setAttribute("STATE",STATES.AUTHZ.name());
+ sendAuthorizeRequest(this.returnURL, response);
+ return false;
+ }
+
+ protected void sendAuthorizeRequest(String returnUrl, HttpServletResponse response)
+ {
+ String returnUri = returnUrl;
+
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(OAuthConstants.REDIRECT_URI_PARAMETER, returnUri);
+ params.put(OAuthConstants.CLIENT_ID_PARAMETER, clientID);
+ if (scope != null)
+ {
+ params.put(OAuthConstants.SCOPE_PARAMETER, scope);
+ }
+ String location = new
StringBuilder(FacebookConstants.AUTHENTICATION_ENDPOINT_URL).append("?").append(
+ util.createQueryString(params)).toString();
+ try
+ {
+ response.sendRedirect(location);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Principal getPrincipal(Request request, Response response, Realm realm)
+ {
+ Principal principal = null;
+ Principal facebookPrincipal = handleAuthenticationResponse(request, response);
+
+ request.getSession().setAttribute("principal", facebookPrincipal);
+ cachedPrincipal.set(facebookPrincipal);
+
+ if(isJBossEnv())
+ {
+ cachedRoles.set(roles);
+ principal = realm.authenticate(facebookPrincipal.getName(), EMPTY_PASSWORD);
+ }
+ else
+ {
+ //Create a Tomcat Generic Principal
+ principal = new GenericPrincipal(realm, facebookPrincipal.getName(), null,
roles, facebookPrincipal);
+ }
+ return principal;
+ }
+
+ protected Principal handleAuthenticationResponse(HttpServletRequest request,
HttpServletResponse response)
+ {
+ String error = request.getParameter(OAuthConstants.ERROR_PARAMETER);
+ if (error != null)
+ {
+ throw new RuntimeException("error:" + error);
+ }
+ else
+ {
+ String returnUrl = returnURL;
+ String authorizationCode = request.getParameter(OAuthConstants.CODE_PARAMETER);
+ if (authorizationCode == null)
+ {
+ throw new RuntimeException("Authorization code parameter not
found");
+ }
+
+ URLConnection connection = sendAccessTokenRequest(returnUrl, authorizationCode,
response);
+
+ Map<String, String> params = formUrlDecode(readUrlContent(connection));
+ String accessToken = params.get(OAuthConstants.ACCESS_TOKEN_PARAMETER);
+ String expires = params.get(FacebookConstants.EXPIRES);
+
+ if(trace) log.trace("Access Token=" + accessToken + " ::
Expires=" + expires);
+
+ if (accessToken == null)
+ {
+ throw new RuntimeException("No access token found");
+ }
+
+ return readInIdentity(request, response, accessToken, returnUrl);
+ }
+ }
+
+ protected URLConnection sendAccessTokenRequest(String returnUrl, String
authorizationCode, HttpServletResponse response)
+ {
+ String returnUri = returnURL;
+
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(OAuthConstants.REDIRECT_URI_PARAMETER, returnUri);
+ params.put(OAuthConstants.CLIENT_ID_PARAMETER, clientID);
+ params.put(OAuthConstants.CLIENT_SECRET_PARAMETER, clientSecret);
+ params.put(OAuthConstants.CODE_PARAMETER, authorizationCode);
+
+ String location = new
StringBuilder(FacebookConstants.ACCESS_TOKEN_ENDPOINT_URL).append("?").append(
+ util.createQueryString(params)).toString();
+
+ try
+ {
+ if(trace) log.trace("AccessToken Request="+location);
+ URL url = new URL(location);
+ URLConnection connection = url.openConnection();
+ return connection;
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private boolean isJBossEnv()
+ {
+ ClassLoader tcl = SecurityActions.getContextClassLoader();
+ Class<?> clazz = null;
+ try
+ {
+ clazz = tcl.loadClass("org.jboss.system.Service");
+ }
+ catch (ClassNotFoundException e)
+ {
+ }
+ if( clazz != null )
+ return true;
+ return false;
+ }
+
+ private Principal readInIdentity(HttpServletRequest request, HttpServletResponse
response, String accessToken, String returnUrl)
+ {
+ FacebookPrincipal facebookPrincipal = null;
+ try
+ {
+ String urlString = new
StringBuilder(FacebookConstants.PROFILE_ENDPOINT_URL).append("?access_token=").append(
+ URLEncoder.encode(accessToken, "UTF-8")).toString();
+ if(trace) log.trace("Profile read:"+urlString);
+
+ URL profileUrl = new URL(urlString);
+ String profileContent = readUrlContent(profileUrl.openConnection());
+ JSONObject jsonObject = new JSONObject(profileContent);
+
+ facebookPrincipal = new FacebookPrincipal();
+ facebookPrincipal.setAccessToken(accessToken);
+ facebookPrincipal.setId(jsonObject.getString("id"));
+ facebookPrincipal.setName(jsonObject.getString("name"));
+ facebookPrincipal.setFirstName(jsonObject.getString("first_name"));
+ facebookPrincipal.setLastName(jsonObject.getString("last_name"));
+ facebookPrincipal.setGender(jsonObject.getString("gender"));
+ facebookPrincipal.setTimezone(jsonObject.getString("timezone"));
+ facebookPrincipal.setLocale(jsonObject.getString("locale"));
+ if (jsonObject.getString("email") != null)
+ {
+ facebookPrincipal.setEmail(jsonObject.getString("email"));
+ }
+ }
+ catch (JSONException e)
+ {
+ throw new RuntimeException(e);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ return facebookPrincipal;
+ }
+
+ private String readUrlContent(URLConnection connection)
+ {
+ StringBuilder result = new StringBuilder();
+ try
+ {
+ Reader reader = new InputStreamReader(connection.getInputStream());
+ char[] buffer = new char[50];
+ int nrOfChars;
+ while ((nrOfChars = reader.read(buffer)) != -1)
+ {
+ result.append(buffer, 0, nrOfChars);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ return result.toString();
+ }
+
+ private Map<String, String> formUrlDecode(String encodedData)
+ {
+ Map<String, String> params = new HashMap<String, String>();
+ String[] elements = encodedData.split("&");
+ for (String element : elements)
+ {
+ String[] pair = element.split("=");
+ if (pair.length == 2)
+ {
+ String paramName = pair[0];
+ String paramValue;
+ try
+ {
+ paramValue = URLDecoder.decode(pair[1], "UTF-8");
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ params.put(paramName, paramValue);
+ }
+ else
+ {
+ throw new RuntimeException("Unexpected name-value pair in response:
" + element);
+ }
+ }
+ return params;
+ }
+}
\ No newline at end of file