org.semispace.google.space.address.FetchAddress.java Source code

Java tutorial

Introduction

Here is the source code for org.semispace.google.space.address.FetchAddress.java

Source

/*
 * ============================================================================
 *
 *  File:     FetchAddress.java
 *----------------------------------------------------------------------------
 *
 * Copyright 2008 Erlend Nossum
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 *
 *  Description:  See javadoc below
 *
 *  Created:      Oct 4, 2008
 * ============================================================================ 
 */

package org.semispace.google.space.address;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.semispace.SemiSpace;
import org.semispace.SemiSpaceInterface;
import org.semispace.google.transport.AddressQuery;
import org.semispace.google.transport.GoogleAddress;
import org.semispace.google.webapp.beans.GoogleKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FetchAddress implements Runnable {
    private static final Logger log = LoggerFactory.getLogger(FetchAddress.class);
    private static final long MAX_SEMAPHORE_WAIT_MS = 10000;
    private SemiSpaceInterface space;

    public FetchAddress(SemiSpaceInterface space) {
        this.space = space;
    }

    public void run() {
        AddressQuery query = (AddressQuery) space.takeIfExists(new AddressQuery());
        if (query == null) {
            log.warn("Could not get address query even when space flagged availability. Just returning.");
            return;
        }
        log.info("Read query OK in thread.");
        GoogleAddress ga = new GoogleAddress();
        ga.setAddress(query.getAddress());
        if (space.readIfExists(ga) != null) {
            log.info("I alreay have a cached instance of the query for address, and will not query again: "
                    + ga.getAddress());
            return;
        }

        AddressLookupSemaphore semaphore = (AddressLookupSemaphore) space.take(new AddressLookupSemaphore(),
                MAX_SEMAPHORE_WAIT_MS);
        if (semaphore == null) {
            log.warn("Service seems to be saturated. Did not get semaphore.");
            return;
        }
        try {
            GoogleKey key = (GoogleKey) space.readIfExists(new GoogleKey());
            if (key == null) {
                log.warn("Google key is null. You need to supply a valid key.");
                ga = new GoogleAddress();
                ga.setAccuracy("-2");
                ga.setAddress("-- missing google key on server --");
                // Caching missing key an hour:
                space.write(ga, 1000 * 3600);
            } else {
                ga = resolveAddress(query.getAddress(), key);
                // Caching lookup a day. This implies that results with an 
                // incorrect key is cached a day as well.
                space.write(ga, SemiSpace.ONE_DAY);
                log.debug("Resolving " + ga.getAddress() + " resulted in status code " + ga.getStatusCode()
                        + " and accuracy " + ga.getAccuracy());
            }
        } finally {
            // Putting semaphore back
            space.write(semaphore, GoogleAddressFetcher.TEN_YEARS);
        }
    }

    public GoogleAddress resolveAddress(String address, GoogleKey key) {
        GoogleAddress result = new GoogleAddress();
        String url = encodeAddressAsHttpParameter(address, key);
        log.debug("Query url: " + url);
        HttpMethod method = new GetMethod(url);
        try {
            result.setAddress(address);
            HttpClient client = new HttpClient();
            method.setFollowRedirects(false);
            method.setDoAuthentication(false);
            client.executeMethod(method);
            byte[] buffer = method.getResponseBody();
            fillResponseInAddress(result, new String(buffer));
        } catch (IOException e) {
            result.setStatusCode("-1");
            log.error("Got exception", e);
        } finally {
            method.releaseConnection();
        }
        return result;
    }

    private void fillResponseInAddress(GoogleAddress result, String csv) {
        log.debug("CSV from google: " + csv);
        String values[] = csv.split(",");
        result.setStatusCode(values[0]);
        result.setAccuracy(values[1]);
        result.setLatitude(values[2]);
        result.setLongitude(values[3]);
    }

    private String encodeAddressAsHttpParameter(String address, GoogleKey key) {
        StringBuilder sb = new StringBuilder();
        sb.append("http://maps.google.com/maps/geo?q=");

        try {
            sb.append(URLEncoder.encode(address, "UTF8"));
        } catch (UnsupportedEncodingException e) {
            log.error("Got exception", e);
        }
        sb.append("&gl=no&output=csv&");
        sb.append("key=" + key.getKey());
        return sb.toString();
    }
}