/*******************************************************************************
* Copyright 2007 Amazon Technologies, Inc.
* 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://aws.amazon.com/apache2.0
* This file 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.
* *****************************************************************************
* __ _ _ ___
* ( )( \/\/ )/ __)
* /__\ \ / \__ \
* (_)(_) \/\/ (___/
*
* Amazon A2S Java Library
* API Version: 2007-10-29
* Generated: Thu Jan 10 05:27:32 PST 2008
*
*/
package com.amazonaws.a2s;
import com.amazonaws.a2s.*;
import com.amazonaws.a2s.model.*;
import java.io.BufferedReader;
import java.util.Map;
import java.util.Iterator;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.JAXBException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.HttpMethodRetryHandler;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NoHttpResponseException;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.InputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.transform.stream.StreamSource;
/**
*
* Amazon Associates Web Service (A2S) is the best way to make money on the Internet.
* Amazon has spent ten years and hundreds of millions of dollars developing a
* world-class web service that millions of customers use every day. As a developer,
* you can build A2S applications that leverage this robust, scalable, and reliable
* technology. You get access to much of the data that is used by Amazon,
* including the items for sale, customer reviews, seller reviews, as well as most
* of the functionality that you see on www.amazon.com, such as finding items,
* finding similar items, displaying customer reviews, and product promotions.
* In short, A2S operations open the doors to Amazon's databases so that you can
* take advantage of Amazon's sophisticated E-commerce data and functionality.
* Build your own web store to sell Amazon items or your own items.
* <br><br>
* Best of all, A2S is free. By signing up to become a A2S developer, you join the
* tens of thousands of developers who are already realizing financial gains by
* creating A2S-driven applications and web stores. In 2006, A2S developers sold well
* over $600 million worth of items. Would you like a percentage of that revenue?
* <br><br>
* E-commerce is the practice of conducting business over the Internet. This guide
* explains in detail how you can use A2S operations to create storefronts in which
* you enable Internet customers to search for your items, see pictures of them, find
* related items, get customer reviews, and purchase items.
* <br><br>
* With e-commerce, the barrier of distance between the shopper and the store goes away:
* the local video store must compete with stores across the country. E-commerce levels
* the playing field: the web site of an individual seller can appear as sophisticated
* and intoxicating as that of a major retailer. A2S is your opportunity to enter the
* world market where patronage is not limited by the size of your storefront, foot traffic
* or locality. Welcome to the world of A2S E-commerce.
*
*
*
* AmazonA2SClient is the implementation of AmazonA2S based on the
* Apache <a href="http://jakarta.apache.org/commons/httpclient/">HttpClient</a>.
*
*/
public class AmazonA2SClient implements AmazonA2S {
private final Log log = LogFactory.getLog(AmazonA2SClient.class);
private String awsAccessKeyId = null;
private String associateTag = null;
private AmazonA2SConfig config = null;
private HttpClient httpClient = null;
private static JAXBContext jaxbContext;
private static ThreadLocal<Unmarshaller> unmarshaller;
/** Initialize JAXBContext and Unmarshaller **/
static {
try {
jaxbContext = JAXBContext.newInstance("com.amazonaws.a2s.model", AmazonA2S.class.getClassLoader());
} catch (JAXBException ex) {
throw new ExceptionInInitializerError(ex);
}
unmarshaller = new ThreadLocal<Unmarshaller>() {
@Override
protected synchronized Unmarshaller initialValue() {
try {
return jaxbContext.createUnmarshaller();
} catch(JAXBException e) {
throw new ExceptionInInitializerError(e);
}
}
};
}
/**
* Constructs AmazonA2SClient with AWS Access Key ID and Accociate Tag
*
* @param awsAccessKeyId
* AWS Access Key ID
* @param associateTag
* Associate Tag
*/
public AmazonA2SClient(String awsAccessKeyId,String associateTag) {
this (awsAccessKeyId, associateTag, AmazonA2SLocale.US);
}
/**
* Constructs AmazonA2SClient with AWS Access Key ID, Associate Tag
* and specific service locale
*
* @param awsAccessKeyId
* AWS Access Key ID
* @param associateTag
* Associate Tag
* @param locale
* Locale you wish to invoke the service call at.
*
* Supported Locales are: US, UK, DE, FR, CA, JP. Note, not all operations
* supported by all locales. Please refer to Amazon A2S documentation for
* more information
*
*/
public AmazonA2SClient(String awsAccessKeyId,String associateTag, AmazonA2SLocale locale) {
this.awsAccessKeyId = awsAccessKeyId;
this.associateTag = associateTag;
this.config = locale.getConfig();
this.httpClient = configureHttpClient();
}
// Public API ------------------------------------------------------------//
/**
* Help Request
*
* <br><br>
* The Help operation provides information about A2S operations and
* response groups. For operations, Help lists required and optional
* request parameters, as well as default and optional response groups the
* operation can use. For response groups, Help lists the operations that can
* use the response group as well as the response tags returned by the
* response group in the XML response.
* <br><br>
* The Help operation is not often used in customer applications. It can, however, be
* used to help the developer in the following ways:
* <br><br>
* <ul>
* <li>Provide contextual help in an interactive development environment (IDE) for developerst</li>
* <li>Automate documentation creation as part of a developer's toolkit. </li>
* </ul>
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>Help</li>
* </ul>
*
* @param request
* Help Request
* @return
* Help Response from the service
*
* @throws AmazonA2SException
*/
public HelpResponse help(HelpRequest... request) throws AmazonA2SException {
Help action = new Help();
return invoke(HelpResponse.class, action.withRequest(request).toMap());
}
/**
* Item Search Request
*
* <br><br>
* The ItemSearch operation returns items that satisfy the search
* criteria, including one or more search indices
* <br><br>
* ItemSearch returns up to ten search results at a time. When condition
* equals "All," ItemSearch returns up to three offers per condition (if they exist),
* for example, three new, three used, three refurbished, and three collectible items.
* Or, for example, if there are no collectible or refurbished offers, ItemSearch
* returns three new and three used offers.
* <br><br>
* Because there are thousands of items in each search index, ItemSearch requires
* that you specify the value for at least one parameter in addition to a search index.
* The additional parameter value must reference items within the specified search index.
* For example, you might specify a browse node (BrowseNode is an ItemSearch parameter),
* Harry Potter Books, within the Books product category. You would not get results,
* for example, if you specified the search index to be Automotive and the browse node
* to be Harry Potter Books. In this case, the parameter value is not associated with
* the search index value.
* <br><br>
* The ItemPage parameter enables you to return a specified page of results. The maximum
* ItemPage number that can be returned is 400. An error is returned if you try to access
* higher numbered pages. If you do not include ItemPage in your request, the first page
* will be returned by default. There can be up to ten items per page.
* <br><br>
* ItemSearch is the operation that is used most often in requests. In general,
* when trying to find an item for sale, you use this operation.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>Small</li>
* <li>Accessories</li>
* <li>BrowseNodes</li>
* <li>EditorialReview</li>
* <li>Images</li>
* <li>ItemAttributes</li>
* <li>ItemIds</li>
* <li>Large</li>
* <li>ListmaniaLists</li>
* <li>Medium</li>
* <li>MerchantItemAttributes</li>
* <li>OfferFull</li>
* <li>Offers</li>
* <li>OfferSummary</li>
* <li>Reviews</li>
* <li>SalesRank</li>
* <li>SearchBins</li>
* <li>Similarities</li>
* <li>Subjects</li>
* <li>Tracks</li>
* <li>TagsSummary</li>
* <li>Tags</li>
* <li>VariationImages</li>
* <li>VariationMinimum</li>
* <li>Variations</li>
* <li>VariationSummary</li>
* </ul>
*
* @param request
* ItemSearch Request
* @return
* ItemSearch Response from the service
*
* @throws AmazonA2SException
*/
public ItemSearchResponse itemSearch(ItemSearchRequest... request) throws AmazonA2SException {
ItemSearch action = new ItemSearch();
return invoke(ItemSearchResponse.class, action.withRequest(request).toMap());
}
/**
* Item Lookup Request
*
* <br><br>
* Given an Item identifier, the ItemLookup operation returns some or all
* of the item attributes, depending on the response group specified in the request.
* By default, ItemLookup returns an item's ASIN, DetailPageURL, Manufacturer,
* ProductGroup, and Title of the item.
* <br><br>
* ItemLookup supports many response groups, so you can retrieve many different
* kinds of product information, called item attributes, including product reviews,
* variations, similar products, pricing, availability, images of products, accessories,
* and other information.
* <br><br>
* To look up more than one item at a time, separate the item identifiers by commas.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>Small</li>
* <li>Accessories</li>
* <li>BrowseNodes</li>
* <li>EditorialReview</li>
* <li>Images</li>
* <li>ItemAttributes</li>
* <li>ItemIds</li>
* <li>Large</li>
* <li>ListmaniaLists</li>
* <li>Medium</li>
* <li>MerchantItemAttributes</li>
* <li>OfferFull</li>
* <li>Offers</li>
* <li>OfferSummary</li>
* <li>Reviews</li>
* <li>SalesRank</li>
* <li>Similarities</li>
* <li>Subjects</li>
* <li>Tracks</li>
* <li>TagsSummary</li>
* <li>Tags</li>
* <li>VariationImages</li>
* <li>VariationMinimum</li>
* <li>Variations</li>
* <li>VariationSummary</li>
* </ul>
*
* @param request
* ItemLookup Request
* @return
* ItemLookup Response from the service
*
* @throws AmazonA2SException
*/
public ItemLookupResponse itemLookup(ItemLookupRequest... request) throws AmazonA2SException {
ItemLookup action = new ItemLookup();
return invoke(ItemLookupResponse.class, action.withRequest(request).toMap());
}
/**
* Browse Node Lookup Request
*
* <br><br>
* Given a browse node ID, BrowseNodeLookup returns the specified browse node's name, children, and ancestors.
* The names and browse node IDs of the children and ancestor browse nodes are also returned.
* BrowseNodeLookup enables you to traverse the browse node hierarchy to find a browse node.
* As you traverse down the hierarchy, you refine your search and limit the number of items returned.
* For example, you might traverse the following hierarchy: DVD Used DVDs Kids and Family,
* to select out of all the DVDs offered by Amazon only those that are appropriate for family viewing.
* Returning the items associated with Kids and Family produces a much more targeted result than a search
* based at the level of Used DVDs.
* <br><br>
* Alternatively, by traversing up the browse node tree, you can determine the root category of an item.
* You might do that, for example, to return the top seller of the root product category using the
* TopSeller response group in an ItemSearch request.
* <br><br>
* You can use BrowseNodeLookup iteratively to navigate through the browse node hierarchy to
* reach the node that most appropriately suits your search. Then you can use the browse node ID in
* an ItemSearch request. This response would be far more targeted than, for example,
* searching through all of the browse nodes in a search index.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>BrowseNodeInfo</li>
* </ul>
*
* @param request
* BrowseNodeLookup Request
* @return
* BrowseNodeLookup Response from the service
*
* @throws AmazonA2SException
*/
public BrowseNodeLookupResponse browseNodeLookup(BrowseNodeLookupRequest... request) throws AmazonA2SException {
BrowseNodeLookup action = new BrowseNodeLookup();
return invoke(BrowseNodeLookupResponse.class, action.withRequest(request).toMap());
}
/**
* List Search Request
*
* <br><br>
* Given a customer name or Email address, the ListSearch operation
* returns the associated list ID(s) but not the list items. To find those,
* use the list ID returned by ListSearch with ListLookup .
* <br><br>
* Specifying a full name or just a first or last name in the request typically
* returns multiple lists belonging to different people. Using Email as the
* identifier produces more filtered results.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>ListInfo</li>
* <li>ListMinimum</li>
* </ul>
*
* @param request
* ListSearch Request
* @return
* ListSearch Response from the service
*
* @throws AmazonA2SException
*/
public ListSearchResponse listSearch(ListSearchRequest... request) throws AmazonA2SException {
ListSearch action = new ListSearch();
return invoke(ListSearchResponse.class, action.withRequest(request).toMap());
}
/**
* List Lookup Request
*
* <br><br>
* The ListLookup operation returns, by default, summary information about a
* list that you specify in the request. The summary information includes the:
* <br><br>
* <ul>
* <li>Creation date of the list</li>
* <li>Name of the list's creator</li>
* </ul>
* <br><br>
* The operation returns up to ten sets of summary information per page.
* <br><br>
* Lists are specified by list type and list ID, which can be found using ListSearch.
* <br><br>
* You cannot lookup more than one list at a time in a single request.
* You can, however, make a batch request to look for more than one list simultaneously.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>ListInfo</li>
* <li>Accessories</li>
* <li>BrowseNodes</li>
* <li>EditorialReview</li>
* <li>Images</li>
* <li>ItemAttributes</li>
* <li>ItemIds</li>
* <li>Large</li>
* <li>ListFull</li>
* <li>ListItems</li>
* <li>ListmaniaLists</li>
* <li>Medium</li>
* <li>Offers</li>
* <li>OfferSummary</li>
* <li>Reviews</li>
* <li>SalesRank</li>
* <li>Similarities</li>
* <li>Small</li>
* <li>Subjects</li>
* <li>Tracks</li>
* <li>VariationMinimum</li>
* <li>Variations</li>
* <li>VariationSummary</li>
* </ul>
*
* @param request
* ListLookup Request
* @return
* ListLookup Response from the service
*
* @throws AmazonA2SException
*/
public ListLookupResponse listLookup(ListLookupRequest... request) throws AmazonA2SException {
ListLookup action = new ListLookup();
return invoke(ListLookupResponse.class, action.withRequest(request).toMap());
}
/**
* Customer Content Search Request
*
* <br><br>
* For a given customer Email address or name, the CustomerContentSearch
* operation returns matching customer IDs, names, nicknames, and residence
* information (city, state, and country). In general, supplying an Email
* address returns unique results whereas supplying a name more often
* returns multiple results.
* <br><br>
* Often you use CustomerContentSearch to find a customer ID that you can
* use in the CustomerContentLookup operation, which returns more
* extensive customer information.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>CustomerInfo</li>
* </ul>
*
* @param request
* CustomerContentSearch Request
* @return
* CustomerContentSearch Response from the service
*
* @throws AmazonA2SException
*/
public CustomerContentSearchResponse customerContentSearch(CustomerContentSearchRequest... request) throws AmazonA2SException {
CustomerContentSearch action = new CustomerContentSearch();
return invoke(CustomerContentSearchResponse.class, action.withRequest(request).toMap());
}
/**
* Customer Content Lookup Request
*
* <br><br>
* For a given customer ID, the CustomerContentLookup operation
* retrieves all of the information a customer has made public about
* themselves on Amazon. Such information includes some or all of the following:
* <br><br>
* <ul>
* <li>AboutMe</li>
* <li>Birthday</li>
* <li>City, State and Country</li>
* <li>Customer Reviews</li>
* <li>Customer ID</li>
* <li>Name</li>
* <li>Nickname</li>
* <li>Wedding Registry</li>
* <li>WishList</li>
* </ul>
* <br><br>
* To find a customer ID, use the CustomerContentSearch operation.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>CustomerInfo</li>
* <li>CustomerReviews</li>
* <li>CustomerLists</li>
* <li>CustomerFull</li>
* <li>TaggedGuides</li>
* <li>TaggedItems</li>
* <li>TaggedListmaniaLists</li>
* <li>TagsSummary</li>
* <li>Tags</li>
* </ul>
*
* @param request
* CustomerContentLookup Request
* @return
* CustomerContentLookup Response from the service
*
* @throws AmazonA2SException
*/
public CustomerContentLookupResponse customerContentLookup(CustomerContentLookupRequest... request) throws AmazonA2SException {
CustomerContentLookup action = new CustomerContentLookup();
return invoke(CustomerContentLookupResponse.class, action.withRequest(request).toMap());
}
/**
* Similarity Lookup Request
*
* <br><br>
* The SimilarityLookup operation returns up to ten products per page that are
* similar to one or more items specified in the request. This operation is
* typically used to pique a customer's interest in buying something similar to what they've already ordered.
* <br><br>
* If you specify more than one item, SimilarityLookup returns the intersection of similar
* items each item would return separately. Alternatively, you can use the SimilarityType
* parameter to return the union of items that are similar to any of the specified items.
* A maximum of ten similar items are returned; the operation does not return additional
* pages of similar items. if there are more than ten similar items, running the same
* request can result in different answers because the ten that are included in the
* response are picked randomly.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>Small</li>
* <li>Accessories</li>
* <li>BrowseNodes</li>
* <li>EditorialReview</li>
* <li>Images</li>
* <li>Large</li>
* <li>ItemAttributes</li>
* <li>ItemIds</li>
* <li>ListmaniaLists</li>
* <li>Medium</li>
* <li>Offers</li>
* <li>OfferSummary</li>
* <li>PromotionDetails</li>
* <li>PromotionSummary</li>
* <li>Reviews</li>
* <li>SalesRank</li>
* <li>Similarities</li>
* <li>Tracks</li>
* <li>VariationMinimum</li>
* <li>Variations</li>
* <li>VariationSummary</li>
* </ul>
*
* @param request
* SimilarityLookup Request
* @return
* SimilarityLookup Response from the service
*
* @throws AmazonA2SException
*/
public SimilarityLookupResponse similarityLookup(SimilarityLookupRequest... request) throws AmazonA2SException {
SimilarityLookup action = new SimilarityLookup();
return invoke(SimilarityLookupResponse.class, action.withRequest(request).toMap());
}
/**
* Seller Lookup Request
*
* <br><br>
* The SellerLookup operation returns detailed information about sellers and,
* in the US locale, merchants. To lookup a seller, you must use their seller ID.
* The information returned includes the seller's name, location, average rating by
* customers, and the first five customer feedback entries. SellerLookup will not,
* however, return the seller's Email or business addresses.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>Seller</li>
* </ul>
*
* @param request
* SellerLookup Request
* @return
* SellerLookup Response from the service
*
* @throws AmazonA2SException
*/
public SellerLookupResponse sellerLookup(SellerLookupRequest... request) throws AmazonA2SException {
SellerLookup action = new SellerLookup();
return invoke(SellerLookupResponse.class, action.withRequest(request).toMap());
}
/**
* Cart Get Request
*
* <br><br>
* The CartGet operation enables you to retrieve the IDs, quantities,
* and prices of all of the items, including SavedForLater items in a
* remote shopping cart.
* <br><br>
* Because the contents of a cart can change for different reasons,
* such as availability, you should not keep a copy of a cart locally.
* Instead, use CartGet to retrieve the items in a remote shopping cart.
* <br><br>
* To retrieve the items in a cart, you must specify the cart using the
* CartId and HMAC values, which are returned in the CartCreate operation.
* A value similar to HMAC, URLEncodedHMAC, is also returned. This value is the
* URL encoded version of the HMAC. This encoding is necessary because some
* characters, such as + and /, cannot be included in a URL. Rather than
* encoding the HMAC yourself, use the URLEncodedHMAC value for the HMAC parameter.
* <br><br>
* CartGet does not work after the customer has used the PurchaseURL to either
* purchase the items or merge them with the items in their Amazon cart.
* <br><br>
* If the associated CartCreate request specified an AssociateTag, all CartGet
* requests must also include a value for AssociateTag otherwise the request will fail.
* <br><br>
* <b>Available Response Groups</b>:
* <ul>
* <li>Request</li>
* <li>Cart</li>
* <li>CartSimilarities</li>
* <li>CartTopSellers</li>
* <li>CartNewReleases</li>
* </ul>
*
* @param request
* CartGet Request
* @return
* CartGet Response from the service
*
* @throws AmazonA2SException
*/
public CartGetResponse cartGet(CartGetRequest... request) throws AmazonA2SException {
CartGet action = new CartGet();
return invoke(CartGetResponse.class, action.withRequest(request).toMap());
}
/**
* Cart Add Request
*
* <br><br>
* The CartAdd operation enables you to add items to an existing remote shopping cart.
* CartAdd can only be used to place a new item in a shopping cart. It cannot be used to increase
|