replace(/[^0-9//-//.]/g, "");
The expression will strip out any of the non-numeric characters not allowed in normal decimal arithmetic.
Example of use:
alert("$100,000.00".replace(/[^0-9//-//.]/g, ""));
produces an alert box displaying 100000.00
replace(/[^0-9//-//.]/g, "");
The expression will strip out any of the non-numeric characters not allowed in normal decimal arithmetic.
Example of use:
alert("$100,000.00".replace(/[^0-9//-//.]/g, ""));
produces an alert box displaying 100000.00
In the final part of this series, we'll examine how to use the PGP class in our custom TAI.
Updated code:
package test.security.tai;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ibm.websphere.security.CustomRegistryException;
import com.ibm.websphere.security.EntryNotFoundException;
import com.ibm.websphere.security.UserRegistry;
import com.ibm.websphere.security.WebTrustAssociationException;
import com.ibm.websphere.security.WebTrustAssociationFailedException;
import com.ibm.wsspi.security.tai.TAIResult;
import com.ibm.wsspi.security.tai.TrustAssociationInterceptor;
import com.security.pgp.PGPSSOUtil
/**
* Custom Login Module
*
* Project imports the jar wssec.jar for development purposes.
* Found in the server runtime lib directory ($irad_home$\runtimes\base_v6\)
*
*
**/
public class CustomPortalTAI implements TrustAssociationInterceptor
{
private static final String VERSION = "Custom TAI version 1.0 \n Author: SirCrofty \n " + "Last Updated: March 1, 2008";
private static final String TYPE = "--- Custom TAI --- \n Custom Trust Assocation Interceptor for WebSphere Portal Application";
HashMap sharedState = null;
/**
* Constructor
*
**/
public CustomPortalTAI()
{
sharedState = new HashMap();
}
/**
* (non-Javadoc)
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#initialize(java.util.Properties)
* @param arg0
* @return
* @throws com.ibm.websphere.security.WebTrustAssociationFailedException
*
**/
public int initialize(Properties props) throws WebTrustAssociationFailedException
{
return 0;
}
/**
* (non-Javadoc)
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#isTargetInterceptor(javax.servlet.http.HttpServletRequest)
* @param arg0
* @return
* @throws com.ibm.websphere.security.WebTrustAssociationException
*
**/
public boolean isTargetInterceptor(HttpServletRequest req) throws WebTrustAssociationException
{
System.out.println("*********** Custom TAI ******************");
System.out.println("Determining if this TAI should handle the incoming request...");
if (req.getParameter("customUser") != null)
{
System.out.println("Custom TAI is being used to establish trust!");
return true;
}
System.out.println("Bypassing Custom TAI, did not find a user ID in the request");
return false;
}
/**
* (non-Javadoc)
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#negotiateValidateandEstablishTrust(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
* @param arg0
* @param arg1
* @return
* @throws com.ibm.websphere.security.WebTrustAssociationFailedException
*
**/
public TAIResult negotiateValidateandEstablishTrust(HttpServletRequest req, HttpServletResponse resp)
throws WebTrustAssociationFailedException
{
String encryptId = req.getParameter("customUser");
try
{
PGPSSOUtil util = new PGPSSOUtil();
// assume the user id has been encrypted and then converted to Hex encoding
byte[] unHexBytes = util.convertHexStringToByteArray(encryptId);
// use the keys referenced in PGPSSOUtil to decrypt the userId
userId = util.decryptId(unHexBytes);
}
catch (Exception e)
{
return TAIResult.create(HttpServletResponse.SC_FORBIDDEN, userId);
}
return TAIResult.create(HttpServletResponse.SC_OK, userId);
}
/**
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#cleanup()
*
*
**/
public void cleanup()
{
sharedState = null;
}
/**
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#getType()
* @return
*
**/
public String getType()
{
return TYPE + " \n " + this.getClass().getName();
}
/**
*
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#getVersion()
* @return
*
**/
public String getVersion()
{
return VERSION;
}
}
The parts of interest here are the changes to the negotiateValidateandEstablishTrust method.
We've replaced the conditional that checks the user name value against a constant to instead use the encrypted user id passed in the request. Assuming the id decrypts correctly (userId = util.decryptId(unHexBytes);), we'll pass the userId along to the Portal itself for authorization. If the user name does not encrypt correctly, than the decryption will fail, an exception will be thrown, and a Forbidden access message will be displayed. In this way, we use the security and access controls already built into WebSphere Portal to handle the rest of the job once we have an acceptable user id.
The only other thing to note is the decoding of the hashed user id from Hex. This is done to because we are assuming the user id has been hex encoded so that it can be passed around while avoiding a bunch of special characters.
This series should hopefully give you a jump on how to create a simple SSO solution for WebSphere Portal. For production purposes, there would be other considerations, such as the storage of the PGP key files and how to determine the location of the trusted sender, but this should get you started in the right direction.
/*
* PGP Decryption Utility
*
*/
package com.security.pgp;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Iterator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
public class PGPSSOUtil
{
private static final String PROVIDER_SHORT = "BC";
private static final String KEY_PHRASE = "MySecretPhrase123";
private static final String DECRYPTION_KEY_FILE = "C:\\PGP\\PGP60.pkr";
private static final String PRIVATE_KEY_FILE = "C:\\PGP\\PGP60.skr";
private static PGPPublicKey pubKey;
private static PGPPrivateKey privateKey;
static
{
// adds the BouncyCastle Security Provider to the Java Security Providers
// list
Security.addProvider(new BouncyCastleProvider());
}
/**
* Constructor
*
* Initializes PGPPublicKey and PGPPrivateKey objects
*
* @throws Exception
*
**/
public PGPSSOUtil() throws Exception
{
// get the PGPPublicKey object
if (pubKey == null)
{
FileInputStream fis = new FileInputStream(DECRYPTION_KEY_FILE);
pubKey = readPublicKeyFromCol(fis);
fis.close();
}
// get the PGPPrivateKey object
if (privateKey == null)
{
FileInputStream fis = new FileInputStream(PRIVATE_KEY_FILE);
privateKey = findSecretKey(fis, pubKey.getKeyID(), KEY_PHRASE.toCharArray());
fis.close();
}
}
/**
* Given an encypted hex byte array, decrypt the data and return a user id to the caller
*
* @param encryptHex Byte Array, containing the encypted user id
* @return a valid SW1 user id, or whatever else is contained in the ecrypted data
*
**/
public String decryptId(byte[] encryptHex)
{
String id = null;
if (encryptHex == null encryptHex.length == 0)
return id;
try
{
// get the decrypted data
byte[] decryptedData = decrypt(privateKey, encryptHex);
// return a String translation of the Byte Array
if (decryptedData != null)
id = new String(decryptedData);
}
catch (Exception e)
{
e.printStackTrace();
}
return id;
}
/**
* Decrypt the given data using the BouncyCastle PGP provider
*
* @param privKey PGPPrivateKey object to decrypt the data with
* @param input Byte Array to decrypt
* @return Byte Array of decypted data
* @throws Exception
*
**/
private byte[] decrypt(PGPPrivateKey privKey, byte[] input) throws Exception
{
byte[] decrypted = null;
try
{
int bufferSize = 1024;
InputStream in = new ByteArrayInputStream(input);
in = PGPUtil.getDecoderStream(in);
PGPObjectFactory pgpObjectFactory = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object pgpObject = pgpObjectFactory.nextObject();
if (pgpObject instanceof PGPEncryptedDataList)
{
enc = (PGPEncryptedDataList) pgpObject;
}
else
{
enc = (PGPEncryptedDataList) pgpObjectFactory.nextObject();
}
Iterator it = enc.getEncryptedDataObjects();
PGPPublicKeyEncryptedData pbe = null;
while (it.hasNext())
{
pbe = (PGPPublicKeyEncryptedData) it.next();
}
if (pbe == null)
{
return decrypted;
}
InputStream clear = pbe.getDataStream(privateKey, PROVIDER_SHORT);
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
PGPCompressedData cData = (PGPCompressedData)
plainFact.nextObject();
InputStream compressedStream = cData.getDataStream();
if (!(compressedStream instanceof BufferedInputStream))
{
compressedStream = new BufferedInputStream(compressedStream, bufferSize);
}
PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream);
Object message = pgpFact.nextObject();
if (message instanceof PGPLiteralData)
{
PGPLiteralData literalData = (PGPLiteralData) message;
ByteArrayOutputStream fOut = new ByteArrayOutputStream();
BufferedInputStream unc = new
BufferedInputStream(literalData.getInputStream(), bufferSize);
byte[] buffer = new byte[bufferSize];
int bytesRead;
while ((bytesRead = unc.read(buffer)) != -1)
{
fOut.write(buffer, 0, bytesRead);
fOut.flush();
}
decrypted = fOut.toByteArray();
fOut.close();
in.close();
}
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
return decrypted;
}
/**
* Find the public key using the BouncyCastle Provider.
*
* @param in InputStream A InputStream created from the PGP Public Key file
* @return PGPPublicKey object used for encrypting and decypting data
* @throws Exception
*
**/
private PGPPublicKey readPublicKeyFromCol(InputStream in) throws Exception
{
PGPPublicKeyRing pkRing = null;
// get the Public Key Rings from the given Public Key File
PGPPublicKeyRingCollection pkCol = new PGPPublicKeyRingCollection(in);
Iterator it = pkCol.getKeyRings();
while (it.hasNext()) // loop over the key rings
{
pkRing = (PGPPublicKeyRing) it.next();
Iterator pkIt = pkRing.getPublicKeys();
while (pkIt.hasNext())
{
PGPPublicKey key = (PGPPublicKey) pkIt.next();
// check if it's the encryption key, this is the one we want to decrypt files with
if (key.isEncryptionKey())
{
return key;
}
}
}
return null;
}
/**
* Find the PGP Private Key from the Private Key file, using BouncyCastle
*
* @param keyIn InputStream created from the PrivateKey File location
* @param keyID The Key Id from the Public Key File
* @param pass The Passphrase used to extract the private key
* @return PGPPrivateKey representing the private key to decrypt with
* @throws IOException
* @throws PGPException
* @throws NoSuchProviderException
*
**/
private static PGPPrivateKey findSecretKey(InputStream keyIn, long keyID, char[] pass) throws IOException, PGPException, NoSuchProviderException
{
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(keyIn));
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null)
{
return null;
}
return pgpSecKey.extractPrivateKey(pass, PROVIDER_SHORT);
}
/**
* Converts a Hex String back to a Byte Array. Courtesy Bouncy Castle
*
* @param hexStr Hex String to convert back to a normal byte array
* @return normally encoded byte array
*
**/
public byte[] convertHexStringToByteArray(String hexStr)
{
byte bArray[] = new byte[hexStr.length()/2];
for(int i=0; i<(hexStr.length()/2); i++)
{
byte firstNibble = Byte.parseByte(hexStr.substring(2*i,2*i+1),16);
byte secondNibble = Byte.parseByte(hexStr.substring(2*i+1,2*i+2),16);
int finalByte = (secondNibble) | (firstNibble << 4 );
bArray[i] = (byte) finalByte;
}
return bArray;
}
/**
* Converts a Byte Array to Hex String. Got this online from Bouncy Castle
*
* @param in byte[] array normally encoded
* @return String in Hex format
*
**/
public String convertByteArrayToHexString(byte in[])
{
byte ch = 0x00;
int i = 0;
if (in == null || in.length <= 0)
{
return null;
}
String pseudo[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8","9", "A", "B", "C", "D", "E", "F"};
StringBuffer out = new StringBuffer(in.length * 2);
while (i < in.length)
{
ch = (byte) (in[i] & 0xF0);
ch = (byte) (ch >>> 4);
ch = (byte) (ch & 0x0F);
out.append(pseudo[ (int) ch]);
ch = (byte) (in[i] & 0x0F);
out.append(pseudo[ (int) ch]);
i++;
}
String rslt = new String(out);
return rslt;
}
}
package test.security.tai;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ibm.websphere.security.CustomRegistryException;
import com.ibm.websphere.security.EntryNotFoundException;
import com.ibm.websphere.security.UserRegistry;
import com.ibm.websphere.security.WebTrustAssociationException;
import com.ibm.websphere.security.WebTrustAssociationFailedException;
import com.ibm.wsspi.security.tai.TAIResult;
import com.ibm.wsspi.security.tai.TrustAssociationInterceptor;
/**
* Custom Login Module
*
* Project imports the jar wssec.jar for development purposes.
* Found in the server runtime lib directory ($irad_home$\runtimes\base_v6\)
*
*
**/
public class CustomPortalTAI implements TrustAssociationInterceptor
{
private static final String VERSION = "Custom TAI version 1.0 \n Author: SirCrofty \n " + "Last Updated: March 1, 2008";
private static final String TYPE = "--- Custom TAI --- \n Custom Trust Assocation Interceptor for WebSphere Portal Application";
HashMap sharedState = null;
/**
* Constructor
*
**/
public CustomPortalTAI()
{
sharedState = new HashMap();
}
/**
* (non-Javadoc)
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#initialize(java.util.Properties)
* @param arg0
* @return
* @throws com.ibm.websphere.security.WebTrustAssociationFailedException
*
**/
public int initialize(Properties props) throws WebTrustAssociationFailedException
{
return 0;
}
/**
* (non-Javadoc)
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#isTargetInterceptor(javax.servlet.http.HttpServletRequest)
* @param arg0
* @return
* @throws com.ibm.websphere.security.WebTrustAssociationException
*
**/
public boolean isTargetInterceptor(HttpServletRequest req) throws WebTrustAssociationException
{
System.out.println("*********** Custom TAI ******************");
System.out.println("Determining if this TAI should handle the incoming request...");
if (req.getParameter("customUser") != null)
{
System.out.println("Custom TAI is being used to establish trust!");
return true;
}
System.out.println("Bypassing Custom TAI, did not find a user ID in the request");
return false;
}
/**
* (non-Javadoc)
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#negotiateValidateandEstablishTrust(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
* @param arg0
* @param arg1
* @return
* @throws com.ibm.websphere.security.WebTrustAssociationFailedException
*
**/
public TAIResult negotiateValidateandEstablishTrust(HttpServletRequest req, HttpServletResponse resp)
throws WebTrustAssociationFailedException
{
String userId = req.getParameter("customUser");
if (userId.equals("portalUser"))
{
System.out.println("*********** CustomTAI *****************");
System.out.println("UserID = " + userId);
return TAIResult.create(HttpServletResponse.SC_OK, userId);
}
else
{
return TAIResult.create(HttpServletResponse.SC_FORBIDDEN, userId);
}
}
/**
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#cleanup()
*
*
**/
public void cleanup()
{
sharedState = null;
}
/**
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#getType()
* @return
*
**/
public String getType()
{
return TYPE + " \n " + this.getClass().getName();
}
/**
*
* @see com.ibm.wsspi.security.tai.TrustAssociationInterceptor#getVersion()
* @return
*
**/
public String getVersion()
{
return VERSION;
}
}
The Property object is the pojo representing the element to be mapped. It comes from the data source with latitude and longitude information, but if it's empty, that's where the Geocoding service comes in:
public synchronized void load()
{
PropertyDAO propDao = new PropertyDAOImpl(conn);
List<Property> propList = null;
try
{
// get the properties from growth right now
propList = propDao.getPropertiesGeoInfo();
}
catch (SQLException e)
{
e.printStackTrace();
}
if (propList != null)
{
// get the property cache
CacheManager manager = CacheManager.getInstance();
Cache propCache = manager.getCache("myCache");
// for each property, check if it has latitude and longitude, fill in if it doesn't and put in the list
for (Property prop : propList)
{
// check to see if there is a latitude and longitude
if (prop.getLatitudeNbr() == 0 || prop.getLongitudeNbr() == 0)
{
lookupGeoInfo(prop);
}
// add it to the cache
propCache.put(new Element(prop.getFacilityNbr(), prop));
}
}
}
Here we create a Restlet Request and set it's endpoint to Google's Geocoding endpoint. Once we've established where the request is going, we set the parameters Google expects (handled by mapParams). Note the format of the response - in this case, I just want the latitude and longitude, so I request the response to come back as csv format and parse it according to it's positions. There are other formats available, check the Geocoding Responses section for more info.
private void lookupGeoInfo(Property prop)
{
// create a new restlet request
Request request = new Request();
Reference ref = new Reference("http://maps.google.com/maps/geo");
// map the parameters to the geocoding service
mapParams(ref, prop);
request.setResourceRef(ref);
request.setMethod(Method.GET);
Client client = new Client(Protocol.HTTP);
// call Google and get the response back
Response response = client.handle(request);
if (response != null)
{
Representation rep = response.getEntity();
try
{
/***
* split the tokens of the response.
* The format is 4 tokens:
* 200,6,42.7,-73.69
* Status code, accuracy, latitude, longitude
*
**/
String[] tokens = rep.getText().split(",");
// if the response code is success, get the lat and long and set it on the prop object
if ("200".equalsIgnoreCase(tokens[0]))
{
prop.setLatitudeNbr(Double.parseDouble(tokens[2]));
prop.setLongitudeNbr(Double.parseDouble(tokens[3]));
}
}
catch (IOException ie)
{
ie.printStackTrace();
}
}
// explicitly close the call
request.release();
}
The Reference.addQueryParameter method adds a query string parameter to your outgoing Restlet Request, allowing you to set to set parameters more elegantly than building the whole url in a StringBuilder/StringBuffer. The method attempts to build the address line off of the Property object fields, and then sets all other parameters for the geocoding service appropriately. Note that you'll need a key from Google to perform this call, same as you would with Google Maps.
private void mapParams(Reference ref, Property prop)
{
// flag to know whether to add a comma or not
boolean first = true;
StringBuilder sb = new StringBuilder();
// add address line one if it's there
if (!nullOrEmpty(prop.getAddrLn1Txt()))
first = formatForParam(prop.getAddrLn1Txt(), first, sb);
if (!nullOrEmpty(prop.getAddrLn2Txt()))
first = formatForParam(prop.getAddrLn2Txt(), first, sb);
if (!nullOrEmpty(prop.getCityName()))
formatForParam(prop.getCityName(), first, sb);
if (!nullOrEmpty(prop.getStateCd()))
formatForParam(prop.getStateCd(), first, sb);
if (!nullOrEmpty(prop.getPostalCd()))
formatForParam(prop.getPostalCd(), first, sb);
if (!nullOrEmpty(prop.getCountryName()))
formatForParam(prop.getCountryName(), first, sb);
// now the address parameter built from the prop object
ref.addQueryParameter("q", sb.toString());
// add the sensor param (true for a gps device)
ref.addQueryParameter("sensor", "false");
// the desired output - all we need is the csv, we don't care about other data they send back
ref.addQueryParameter("output", "csv");
// the encoding the response is coming back in
ref.addQueryParameter("oe", "utf8");
// add the key to geo code request
ref.addQueryParameter("key", geoCodeKey);
}
public class PropertyCacheLoad
{
private Connection conn = null;
private String geoCodeKey = null;
public PropertyCacheLoad(Connection conn, String geoCodeKey)
{
this.conn = conn;
this.geoCodeKey = geoCodeKey;
}
/*
*
*/
public void configure(String configFile)
{
CacheManager.create(configFile);
}
/*
*
*/
public synchronized void load()
{
PropertyDAO propDao = new PropertyDAOImpl(conn);
List<property:gt; propList = null;
try
{
// get the properties from growth right now
propList = propDao.getPropertiesGeoInfo();
}
catch (SQLException e)
{
e.printStackTrace();
}
if (propList != null)
{
// get the property cache
CacheManager manager = CacheManager.getInstance();
Cache propCache = manager.getCache("myCache");
// for each property, check if it has latitude and longitude, fill in if it doesn't and put in the list
for (Property prop : propList)
{
// check to see if there is a latitude and longitude
if (prop.getLatitudeNbr() == 0 || prop.getLongitudeNbr() == 0)
{
lookupGeoInfo(prop);
}
// add it to the cache
propCache.put(new Element(prop.getFacilityNbr(), prop));
}
}
}
/**
* @param prop
*/
private void lookupGeoInfo(Property prop)
{
// create a new restlet request
Request request = new Request();
Reference ref = new Reference("http://maps.google.com/maps/geo");
// map the parameters to the geocoding service
mapParams(ref, prop);
request.setResourceRef(ref);
request.setMethod(Method.GET);
Client client = new Client(Protocol.HTTP);
// call Google and get the response back
Response response = client.handle(request);
if (response != null)
{
Representation rep = response.getEntity();
try
{
/***
* split the tokens of the response.
* The format is 4 tokens:
* 200,6,42.7,-73.69
* Status code, accuracy, latitude, longitude
*
**/
String[] tokens = rep.getText().split(",");
// if the response code is success, get the lat and long and set it on the prop object
if ("200".equalsIgnoreCase(tokens[0]))
{
prop.setLatitudeNbr(Double.parseDouble(tokens[2]));
prop.setLongitudeNbr(Double.parseDouble(tokens[3]));
}
}
catch (IOException ie)
{
ie.printStackTrace();
}
}
// explicitly close the call
request.release();
}
/**
* @param ref
* @param prop
*/
private void mapParams(Reference ref, Property prop)
{
// flag to know whether to add a comma or not
boolean first = true;
StringBuilder sb = new StringBuilder();
if (!nullOrEmpty(prop.getAddrLn1Txt()))
first = formatForParam(prop.getAddrLn1Txt(), first, sb);
if (!nullOrEmpty(prop.getAddrLn2Txt()))
first = formatForParam(prop.getAddrLn2Txt(), first, sb);
if (!nullOrEmpty(prop.getCityName()))
formatForParam(prop.getCityName(), first, sb);
if (!nullOrEmpty(prop.getStateCd()))
formatForParam(prop.getStateCd(), first, sb);
if (!nullOrEmpty(prop.getPostalCd()))
formatForParam(prop.getPostalCd(), first, sb);
if (!nullOrEmpty(prop.getCountryName()))
formatForParam(prop.getCountryName(), first, sb);
// now the address parameter built from the prop object
ref.addQueryParameter("q", sb.toString());
// add the sensor param (true for a gps device)
ref.addQueryParameter("sensor", "false");
// the desired output - all we need is the csv, we don't care about other data they send back
ref.addQueryParameter("output", "csv");
// the encoding the response is coming back in
ref.addQueryParameter("oe", "utf8");
// add the key to geo code request
ref.addQueryParameter("key", geoCodeKey);
}
/**
* @param s
* @return
*/
private boolean nullOrEmpty(String s)
{
return (s == null || s.trim().length() == 0);
}
/**
* @param s
* @param first
* @param sb
* @return
*/
private boolean formatForParam(String s, boolean first, StringBuilder sb)
{
if (first)
sb.append(s);
else
sb.append(", " + s);
return false;
}
}