├── .travis.yml
├── src
├── main
│ ├── resources
│ │ └── props.properties
│ ├── java
│ │ └── threescale
│ │ │ └── v3
│ │ │ └── api
│ │ │ ├── package.html
│ │ │ ├── impl
│ │ │ ├── package.html
│ │ │ ├── ParameterEncoder.java
│ │ │ ├── ServerAccessorDriver.java
│ │ │ └── ServiceApiDriver.java
│ │ │ ├── example
│ │ │ ├── package.html
│ │ │ ├── TestKeys.java
│ │ │ ├── Example.java
│ │ │ └── AllCallsExample.java
│ │ │ ├── ParameterMapType.java
│ │ │ ├── ServerError.java
│ │ │ ├── HttpResponse.java
│ │ │ ├── ServerAccessor.java
│ │ │ ├── ReportResponse.java
│ │ │ ├── ServiceApi.java
│ │ │ ├── UsageReport.java
│ │ │ ├── ParameterMap.java
│ │ │ └── AuthorizeResponse.java
│ └── javadoc
│ │ └── overview.html
└── test
│ └── java
│ └── threescale
│ └── v3
│ └── api
│ ├── impl
│ ├── ServiceAccessorDriverTest.java
│ └── ParameterEncoderTest.java
│ ├── ServiceApiDriverIntegrationTest.java
│ └── ServiceApiDriverTest.java
├── .gitignore
├── LICENSE
├── release.sh
├── pom.xml
└── README.md
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
--------------------------------------------------------------------------------
/src/main/resources/props.properties:
--------------------------------------------------------------------------------
1 | MAVEN_PROJECT_VERSION=${project.version}
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/package.html:
--------------------------------------------------------------------------------
1 |
Threescale Service API.
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | *.iml
3 | .idea
4 | .classpath
5 | .project
6 | .settings
7 | /target/
8 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/impl/package.html:
--------------------------------------------------------------------------------
1 | Implementation Classes
2 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/example/package.html:
--------------------------------------------------------------------------------
1 |
2 | Sample code for using the ServiceApi
3 |
4 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/ParameterMapType.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | /**
4 | * Enum for the type that can be stored in a ParameterMap.
5 | */
6 | public enum ParameterMapType {
7 | STRING, MAP, ARRAY, LONG;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/ServerError.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | /**
4 | * Encapulates error information for a server operation.
5 | */
6 | public class ServerError extends Exception {
7 |
8 | private static final long serialVersionUID = -5900004126517852322L;
9 |
10 | public ServerError(String reason) {
11 | super(reason);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/javadoc/overview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | This jar provides some interface classes for the 3Scale Service Api. Specifically it supports
4 | Authrep, Authorize and Report.
5 |
6 | To use the code you create a ServiceApi object, build a ParameterMap with the values for the api call then call the
7 | appropriate method for the operation.
8 |
9 | Each method call returns a response object that gives success or failure information.
10 |
11 | See @see threescale.v3.api.example.Example for more details
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/example/TestKeys.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.example;
2 |
3 | /**
4 | * Edit this interface and replace the values with your live values to test the calls to the backend.
5 | */
6 | public interface TestKeys {
7 | static String my_provider_key = "";
8 |
9 | //App Id
10 | static String app_id = "";
11 | static String app_key = "";
12 | static String app_id_service_id = "";
13 |
14 | //API Key
15 | static String user_key = "";
16 | static String user_key_service_id = "";
17 |
18 | // OAuth
19 | static String oauth_service_id = "";
20 | static String oauth_app_id = "";
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/HttpResponse.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | /**
4 | * Returns the result of an Http GET / POST
5 | */
6 | public class HttpResponse {
7 |
8 | private int status;
9 | private String body;
10 |
11 | /**
12 | * construct an HtmlResponse from the Http Status and Body Content
13 | *
14 | * @param status Http Status
15 | * @param body Http Body
16 | */
17 | public HttpResponse(int status, String body) {
18 | this.status = status;
19 | this.body = body;
20 | }
21 |
22 | /**
23 | * Return the content
24 | *
25 | * @return body
26 | */
27 | public String getBody() {
28 | return body;
29 | }
30 |
31 | /**
32 | * Get the Status.
33 | *
34 | * @return status.
35 | */
36 | public int getStatus() {
37 | return status;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2010 3scale networks S.L.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/ServerAccessor.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | /**
4 | * Interface to HTML operation between this client and the 3Scale Server
5 | */
6 | public interface ServerAccessor {
7 | String X_3SCALE_USER_CLIENT_HEADER = "X-3scale-User-Agent";
8 | String MAVEN_PROJECT_VERSION = "MAVEN_PROJECT_VERSION";
9 | String X_3SCALE_USER_CLIENT_HEADER_JAVA_PLUGIN = "plugin-java-v";
10 |
11 | /**
12 | * Perform and HTML GET with the provided URL
13 | *
14 | * @param url The URL and parameters to be sent
15 | * @return Status and content as a HtmlResponse
16 | * @throws ServerError If there are problems connection tp the server.
17 | */
18 | public HttpResponse get(String url) throws ServerError;
19 |
20 | /**
21 | * Perform and HTML POST with the provided URL and form data
22 | *
23 | * @param url The URl to contact
24 | * @param data The data to be sent
25 | * @return Status and content as a HtmlResponse
26 | * @throws ServerError If there are problems connection tp the server.
27 | */
28 | public HttpResponse post(String url, String data) throws ServerError;
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/threescale/v3/api/impl/ServiceAccessorDriverTest.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.impl;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | import threescale.v3.api.HttpResponse;
10 | import threescale.v3.api.ServerAccessor;
11 | import threescale.v3.api.ServerError;
12 |
13 | /**
14 | * Unit Test class for the Service Api.
15 | */
16 |
17 | public class ServiceAccessorDriverTest {
18 | private ServerAccessorDriver underTest = new ServerAccessorDriver();;
19 |
20 |
21 | @Before
22 | public void setup() {
23 |
24 | }
25 |
26 | @Test
27 | public void testClientHeader() {
28 | String actualClientHeader = underTest.getPluginHeaderValue();
29 | Assert.assertNotNull(actualClientHeader);
30 | Assert.assertTrue(actualClientHeader.startsWith(ServerAccessor.X_3SCALE_USER_CLIENT_HEADER_JAVA_PLUGIN));
31 | }
32 |
33 | //@Test
34 | public void testGet() throws ServerError {
35 | String testUrl = "http://requestb.in/1k27m9c1"; //inspect the headers at http://requestb.in/1k27m9c1?inspect
36 |
37 | HttpResponse response = underTest.get(testUrl);
38 | int status = response.getStatus();
39 | assertEquals(status, 200);
40 | }
41 |
42 | //@Test
43 | public void testPost() throws ServerError {
44 | String testUrl = "http://requestb.in/1k27m9c1"; //inspect the headers at http://requestb.in/1k27m9c1?inspect
45 |
46 | HttpResponse response = underTest.post(testUrl, "");
47 | int status = response.getStatus();
48 | assertEquals(status, 200);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | echo ""
3 | echo "######################################"
4 | echo " Releasing 3scale Java Plugin"
5 | echo "######################################"
6 | echo ""
7 |
8 | BRANCH=`git rev-parse --abbrev-ref HEAD`
9 |
10 | echo "** Current Branch: $BRANCH **"
11 | echo ""
12 |
13 | RELEASE_VERSION=$1
14 | DEV_VERSION=$2
15 | GPG_PASSPHRASE=$3
16 |
17 | if [ "x$RELEASE_VERSION" = "x" ]
18 | then
19 | read -p "Release Version: " RELEASE_VERSION
20 | fi
21 |
22 | if [ "x$DEV_VERSION" = "x" ]
23 | then
24 | read -p "New Development Version: " DEV_VERSION
25 | fi
26 |
27 | if [ "x$GPG_PASSPHRASE" = "x" ]
28 | then
29 | read -p "GPG Passphrase: " GPG_PASSPHRASE
30 | fi
31 |
32 | echo "######################################"
33 | echo "Release Version: $RELEASE_VERSION"
34 | echo "Dev Version: $DEV_VERSION"
35 | echo "######################################"
36 |
37 | rm -rf ~/.m2/repository/io/3scale
38 | mvn clean install
39 | STATUS=$?
40 | if [ $STATUS -eq 0 ]; then
41 | echo "Build success!"
42 | else
43 | echo "Build failed!"
44 | exit 1
45 | fi
46 |
47 | mvn versions:set -DnewVersion=$RELEASE_VERSION
48 | find . -name '*.versionsBackup' -exec rm -f {} \;
49 | git add .
50 | git commit -m "Prepare for release $RELEASE_VERSION"
51 | git push origin $BRANCH
52 |
53 | mvn clean install
54 |
55 | git tag -a -m "Tagging release $RELEASE_VERSION" v$RELEASE_VERSION
56 | git push origin v$RELEASE_VERSION
57 |
58 | mvn clean deploy -Prelease -Dgpg.passphrase=$GPG_PASSPHRASE
59 |
60 | mvn versions:set -DnewVersion=$DEV_VERSION
61 | find . -name '*.versionsBackup' -exec rm -f {} \;
62 | git add .
63 | git commit -m "Update to next development version: $DEV_VERSION"
64 | git push origin $BRANCH
65 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/example/Example.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.example;
2 |
3 | import threescale.v3.api.AuthorizeResponse;
4 | import threescale.v3.api.ParameterMap;
5 | import threescale.v3.api.ServerError;
6 | import threescale.v3.api.ServiceApi;
7 | import threescale.v3.api.impl.ServiceApiDriver;
8 |
9 | /**
10 | * Simple Example of using the API
11 | */
12 | public class Example {
13 |
14 | public void performAuthRep() {
15 |
16 | ServiceApi serviceApi = new ServiceApiDriver("my_provider_key"); // Create the API object
17 |
18 | ParameterMap params = new ParameterMap(); // Create top level ParameterMap
19 | params.add("app_id", "appid"); // Set the Users App Id
20 |
21 | ParameterMap usage = new ParameterMap(); // Create 1st Level PM for usage
22 | usage.add("hits", "3"); // Add number of hits metric
23 | params.add("usage", usage); // Add 1st level to top level as "usage"
24 |
25 | try {
26 | final AuthorizeResponse response = serviceApi.authrep(params); // Perform the AuthRep and get the response
27 |
28 | if (response.success()) { // Check if the AuthRep succeeded
29 | // Perform your calls there
30 | } else {
31 | // Handle failure here
32 | }
33 | } catch (ServerError serverError) {
34 | // Thrown if there is a communications error with the server.
35 | serverError.printStackTrace();
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/ReportResponse.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | import nu.xom.*;
4 |
5 | import java.io.IOException;
6 |
7 | /**
8 | * The response information from a Report operations.
9 | * success is true if the report succeeded.
10 | * success is false if it failed and the Error Code and Error Message fields will be populated.
11 | */
12 | public class ReportResponse {
13 | private String errorCode = "";
14 | private String errorMessage = "";
15 | private boolean status = false;
16 |
17 | /**
18 | * Create a ReportResponse from an HTML POST
19 | *
20 | * @param response
21 | * @throws ServerError
22 | */
23 | public ReportResponse(HttpResponse response) throws ServerError {
24 | if (response.getStatus() == 200 || response.getStatus() == 202) {
25 | status = true;
26 | } else {
27 | status = false;
28 | parseResponse(response);
29 | }
30 | }
31 |
32 | private void parseResponse(HttpResponse response) throws ServerError {
33 | try {
34 | Builder parser = new Builder();
35 | Document doc = parser.build(response.getBody(), null);
36 | Element root = doc.getRootElement();
37 |
38 | Attribute codeEl = root.getAttribute("code");
39 | errorCode = codeEl.getValue();
40 | errorMessage = root.getValue();
41 | return;
42 | } catch (ParsingException ex) {
43 | throw new ServerError("The xml received was invalid: " + response.getBody());
44 | } catch (IOException ex) {
45 | throw new ServerError("Unable process the XML");
46 | }
47 | }
48 |
49 | /**
50 | * Return the Error Code
51 | *
52 | * @return error code
53 | */
54 | public String getErrorCode() {
55 | return errorCode;
56 | }
57 |
58 | /**
59 | * Return the Error Message
60 | *
61 | * @return message
62 | */
63 | public String getErrorMessage() {
64 | return errorMessage;
65 | }
66 |
67 | /**
68 | * Return success / failure
69 | *
70 | * @return true = success, false = failure
71 | */
72 | public boolean success() {
73 | return status;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/ServiceApi.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | /**
4 | * Service API interface.
5 | */
6 | public interface ServiceApi {
7 | String DEFAULT_HOST = "su1.3scale.net";
8 |
9 | /**
10 | * Performs and AuthRep operation
11 | *
12 | * @param metrics The app_id and metrics for this authrep
13 | * @return Information about the success/failure of the operation and the current metrics
14 | * @throws ServerError Thrown if there is an error communicating with the 3Scale server
15 | */
16 | public AuthorizeResponse authrep(ParameterMap metrics) throws ServerError;
17 | public AuthorizeResponse authrep(String serviceToken, String serviceId, ParameterMap metrics)
18 | throws ServerError;
19 |
20 | /**
21 | * Performs an Authorize
22 | *
23 | * @param parameters App_id etc for the authorize
24 | * @return Information about the success/failure of the operation
25 | * @throws ServerError Thrown if there is an error communicating with the 3Scale server
26 | */
27 | public AuthorizeResponse authorize(ParameterMap parameters) throws ServerError;
28 | public AuthorizeResponse authorize(String serviceToken, String serviceId, ParameterMap parameters)
29 | throws ServerError;
30 |
31 | /**
32 | * Perform an Authorize using OAuth.
33 | *
34 | * @param params Parameters for the authorize
35 | * @return Information about the success/failure of the operation
36 | * @throws ServerError Thrown if there is an error communicating with the 3Scale server
37 | */
38 | public AuthorizeResponse oauth_authorize(ParameterMap params) throws ServerError;
39 | public AuthorizeResponse oauth_authorize(String serviceToken, String serviceId, ParameterMap params)
40 | throws ServerError;
41 |
42 | /**
43 | * Report a set of metrics. Note: report differs from the rest of these methods in that a serviceId is
44 | * an argument. The reason for this is that it does not accept a root level ParameterMap argument, which is
45 | * normally how the serviceId would be passed. Instead, the root level ParameterMap is created by the
46 | * implementation, and so the serviceId cannot be included in it.
47 | *
48 | * @param transactions The metrics to be reported
49 | * @return Information about the success/failure of the operation
50 | * @throws ServerError Thrown if there is an error communicating with the 3Scale server
51 | */
52 | public ReportResponse report(String serviceId, ParameterMap... transactions) throws ServerError;
53 | public ReportResponse report(String serviceToken, String serviceId, ParameterMap... transactions) throws ServerError;
54 |
55 | /**
56 | * Get the URL of the 3scale server
57 | *
58 | * @return Server url
59 | */
60 | public String getHost();
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/UsageReport.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | /**
4 | * Usage information for an AuthRep or Authorize
5 | */
6 | public class UsageReport {
7 |
8 | private String metric = "";
9 | private String period = "";
10 | private String periodStart = "";
11 | private String periodEnd = "";
12 | private String currentValue = "";
13 | private String maxValue = "";
14 | private boolean hasExceeded = false;
15 |
16 | /**
17 | * Create a UsageReport
18 | *
19 | * @param metric
20 | * @param period
21 | * @param periodStart
22 | * @param periodEnd
23 | * @param currentValue
24 | * @param maxValue
25 | * @param hasExceeded
26 | */
27 | public UsageReport(String metric, String period, String periodStart, String periodEnd, String currentValue, String maxValue, String hasExceeded) {
28 | this.metric = metric;
29 | this.period = period;
30 | this.periodStart = periodStart;
31 | this.periodEnd = periodEnd;
32 | this.currentValue = currentValue;
33 | this.maxValue = maxValue;
34 | setHasExceeded(hasExceeded);
35 | }
36 |
37 | private void setHasExceeded(String hasExceeded) {
38 | if (hasExceeded.toLowerCase().equals("true")) {
39 | this.hasExceeded = true;
40 | } else {
41 | this.hasExceeded = false;
42 | }
43 | }
44 |
45 | /**
46 | * Get the Name of the Metric
47 | *
48 | * @return name
49 | */
50 | public String getMetric() {
51 | return metric;
52 | }
53 |
54 | /**
55 | * Get the period of the metric
56 | *
57 | * @return
58 | */
59 | public String getPeriod() {
60 | return period;
61 | }
62 |
63 | /**
64 | * Get the current value of the metric
65 | *
66 | * @return
67 | */
68 | public String getCurrentValue() {
69 | return currentValue;
70 | }
71 |
72 | /**
73 | * Get the maximum value of the metric
74 | *
75 | * @return
76 | */
77 | public String getMaxValue() {
78 | return maxValue;
79 | }
80 |
81 | /**
82 | * Get the start of period as a String
83 | *
84 | * @return YYYY-MM-DD HH:mm:SS +NNNN Year-Month-Day Hour:Minute:second Offset from UTC
85 | */
86 | public String getPeriodStart() {
87 | return periodStart;
88 | }
89 |
90 | /**
91 | * Get the end of period as a String
92 | *
93 | * @return YYYY-MM-DD HH:mm:SS +NNNN Year-Month-Day Hour:Minute:second Offset from UTC
94 | */
95 | public String getPeriodEnd() {
96 | return periodEnd;
97 | }
98 |
99 | /**
100 | * Returns the hasExceeded flag
101 | *
102 | * @return true if the metrics have been exceeded.
103 | */
104 | public boolean hasExceeded() {
105 | return hasExceeded;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/threescale/v3/api/impl/ParameterEncoderTest.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.impl;
2 |
3 | import org.joda.time.DateTime;
4 | import org.joda.time.DateTimeZone;
5 | import org.joda.time.format.DateTimeFormat;
6 | import org.joda.time.format.DateTimeFormatter;
7 |
8 | import org.junit.Before;
9 | import org.junit.Test;
10 | import threescale.v3.api.ParameterMap;
11 |
12 | import static org.junit.Assert.assertEquals;
13 |
14 | /**
15 | * JUnit Test class
16 | */
17 | public class ParameterEncoderTest {
18 |
19 | private ParameterEncoder encoder;
20 | DateTimeFormatter fmt;
21 |
22 | @Before
23 | public void setup() {
24 | encoder = new ParameterEncoder();
25 | fmt = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss Z");
26 | }
27 |
28 | @Test
29 | public void testEncodeOneParameter() throws Exception {
30 | ParameterMap param = new ParameterMap();
31 | param.add("provider_key", "123abc");
32 |
33 | assertEquals("provider_key=123abc", encoder.encode(param));
34 | }
35 |
36 | @Test
37 | public void testEncodeTwoParameters() throws Exception {
38 | ParameterMap param = new ParameterMap();
39 | param.add("provider_key", "123abc");
40 | param.add("app_id", "3456aaa");
41 |
42 | assertEquals("provider_key=123abc&app_id=3456aaa", encoder.encode(param));
43 | }
44 |
45 | @Test
46 | public void testEncodeTwoParametersAndOneMap() throws Exception {
47 | ParameterMap param = new ParameterMap();
48 | param.add("provider_key", "123abc");
49 | param.add("app_id", "3456aaa");
50 |
51 | ParameterMap usage = new ParameterMap();
52 | usage.add("hits", "111");
53 | param.add("usage", usage);
54 |
55 | assertEquals("provider_key=123abc&app_id=3456aaa&usage%5Bhits%5D=111", encoder.encode(param));
56 | }
57 |
58 | @Test
59 | public void testEncodeTwoParametersAndTwoMap() throws Exception {
60 | ParameterMap param = new ParameterMap();
61 | param.add("provider_key", "123abc");
62 | param.add("app_id", "3456aaa");
63 |
64 | ParameterMap usage = new ParameterMap();
65 | usage.add("hits", "111");
66 | usage.add("timestamp", fmt.print(new DateTime(2010, 4, 27, 15, 0, DateTimeZone.UTC)));
67 | param.add("usage", usage);
68 |
69 |
70 | assertEquals(
71 | "provider_key=123abc&app_id=3456aaa&usage%5Bhits%5D=111&usage%5Btimestamp%5D=2010-04-27%2015%3A00%3A00%20+0000",
72 | encoder.encode(param));
73 | }
74 |
75 | @Test
76 | public void testEncodingAnArray() throws Exception {
77 | final String expected =
78 | "provider_key=1234abcd&"
79 | + "transactions%5B0%5D%5Bapp_id%5D=foo&"
80 | + "transactions%5B0%5D%5Btimestamp%5D=2010-04-27%2015%3A42%3A17%200200&"
81 | + "transactions%5B0%5D%5Busage%5D%5Bhits%5D=1&"
82 | + "transactions%5B1%5D%5Bapp_id%5D=bar&"
83 | + "transactions%5B1%5D%5Btimestamp%5D=2010-04-27%2015%3A55%3A12%200200&"
84 | + "transactions%5B1%5D%5Busage%5D%5Bhits%5D=1";
85 |
86 | ParameterMap app1 = new ParameterMap();
87 | app1.add("app_id", "foo");
88 | app1.add("timestamp", "2010-04-27 15:42:17 0200");
89 |
90 | ParameterMap usage1 = new ParameterMap();
91 | usage1.add("hits", "1");
92 | app1.add("usage", usage1);
93 |
94 | ParameterMap app2 = new ParameterMap();
95 | app2.add("app_id", "bar");
96 | app2.add("timestamp", "2010-04-27 15:55:12 0200");
97 |
98 | ParameterMap usage2 = new ParameterMap();
99 | usage2.add("hits", "1");
100 | app2.add("usage", usage2);
101 |
102 | ParameterMap[] transactions = new ParameterMap[2];
103 | transactions[0] = app1;
104 | transactions[1] = app2;
105 |
106 | ParameterMap params = new ParameterMap();
107 | params.add("provider_key", "1234abcd");
108 | params.add("transactions", transactions);
109 |
110 | assertEquals(expected, encoder.encode(params));
111 |
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/ParameterMap.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | import java.util.Arrays;
4 | import java.util.HashMap;
5 | import java.util.LinkedHashMap;
6 | import java.util.Set;
7 |
8 | /**
9 | * Hold a set of parameter and metrics for an AuthRep, Authorize, OAuth Authorize or Report.
10 | *
11 | * Each item consists of a name/value pair, where the value can be a String, An Array of ParameterMaps or another Parameter Map.
12 | *
13 | *
14 | * E.g. For an AuthRep:
15 | *
16 | *
17 | * ParameterMap params = new ParameterMap();
18 | * params.add("app_id", "app_1234");
19 | * ParameterMap usage = new ParameterMap();
20 | * usage.add("hits", "3");
21 | * params.add("usage", usage);
22 | * AuthorizeResponse response = serviceApi.authrep(params);
23 | *
24 | *
25 | * An example for a report might be:
26 | *
27 | *
28 | * ParameterMap params = new ParameterMap();
29 | * params.add("app_id", "foo");
30 | * params.add("timestamp", fmt.print(new DateTime(2010, 4, 27, 15, 0)));
31 | * ParameterMap usage = new ParameterMap();
32 | * usage.add("hits", "1");
33 | * params.add("usage", usage);
34 | * ReportResponse response = serviceApi.report(params);
35 | *
36 | */
37 | public class ParameterMap {
38 |
39 | private HashMap data;
40 |
41 | /**
42 | * Construct and empty ParameterMap
43 | */
44 | public ParameterMap() {
45 | // Note: use a linked hash map for more predictable serialization of the parameters (mostly for testing)
46 | data = new LinkedHashMap();
47 | }
48 |
49 | /**
50 | * Add a string value
51 | *
52 | * @param key
53 | * @param value
54 | */
55 | public void add(String key, String value) {
56 | data.put(key, value);
57 | }
58 |
59 | /**
60 | * Add another ParameterMap
61 | *
62 | * @param key
63 | * @param map
64 | */
65 | public void add(String key, ParameterMap map) {
66 | data.put(key, map);
67 | }
68 |
69 | /**
70 | * Add an array of parameter maps
71 | *
72 | * @param key
73 | * @param array
74 | */
75 | public void add(String key, ParameterMap[] array) {
76 | data.put(key, array);
77 | }
78 |
79 | /**
80 | * Return the keys in a ParameterMap
81 | *
82 | * @return
83 | */
84 | public Set getKeys() {
85 | return data.keySet();
86 | }
87 |
88 | /**
89 | * Get the type of data item associated with the key
90 | *
91 | * @param key
92 | * @return STRING, MAP, ARRAY
93 | */
94 | public ParameterMapType getType(String key) {
95 | Class> clazz = data.get(key).getClass();
96 | if (clazz == String.class) {
97 | return ParameterMapType.STRING;
98 | }
99 | if (clazz == ParameterMap[].class) {
100 | return ParameterMapType.ARRAY;
101 | }
102 | if (clazz == ParameterMap.class) {
103 | return ParameterMapType.MAP;
104 | }
105 | if (clazz == Long.class) {
106 | return ParameterMapType.LONG;
107 | }
108 | throw new RuntimeException("Unknown object in parameters");
109 | }
110 |
111 | /**
112 | * Get the String associated with a key
113 | *
114 | * @param key
115 | * @return
116 | */
117 | public String getStringValue(String key) {
118 | switch (getType(key)) {
119 | case ARRAY:
120 | return Arrays.toString((ParameterMap[]) data.get(key));
121 | case LONG:
122 | return Long.toString((Long) data.get(key));
123 | case MAP:
124 | return ((ParameterMap) data.get(key)).toString(); //
125 | case STRING:
126 | return (String) data.get(key);
127 | }
128 | return null;
129 | }
130 |
131 | /**
132 | * Get the map associated with a key
133 | *
134 | * @param key
135 | * @return
136 | */
137 | public ParameterMap getMapValue(String key) {
138 | return (ParameterMap) data.get(key);
139 | }
140 |
141 | /**
142 | * Get the array associated with a key.
143 | *
144 | * @param key
145 | * @return
146 | */
147 | public ParameterMap[] getArrayValue(String key) {
148 | return (ParameterMap[]) data.get(key);
149 | }
150 | public long getLongValue(String key) {
151 | return (Long) data.get(key);
152 | }
153 | public void setLongValue(String key, long value) {
154 | data.put(key, value);
155 | }
156 |
157 | /**
158 | * Return the number of elements in the map.
159 | *
160 | * @return
161 | */
162 | public int size() {
163 | return data.size();
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/impl/ParameterEncoder.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.impl;
2 |
3 | import threescale.v3.api.ParameterMap;
4 |
5 | /**
6 | * Encodes a ParameterMap as a string suitable for sending as part of an HTML request.
7 | */
8 | public class ParameterEncoder {
9 |
10 | /**
11 | * Takes the parameter map and returns an encoded string.
12 | *
13 | * @param params Parameter map to encode
14 | * @return Encoded string
15 | */
16 | public String encode(ParameterMap params) {
17 | StringBuilder result = new StringBuilder();
18 |
19 | int index = 0;
20 | for (String mapKey : params.getKeys()) {
21 | if (index != 0) result.append("&");
22 | switch (params.getType(mapKey)) {
23 | case STRING:
24 | result.append(emitNormalValue(mapKey, params.getStringValue(mapKey)));
25 | break;
26 | case MAP:
27 | result.append(emitNormalMap(mapKey, params.getMapValue(mapKey)));
28 | break;
29 | case ARRAY:
30 | result.append(emitNormalArray(mapKey, params.getArrayValue(mapKey)));
31 | break;
32 | case LONG:
33 | result.append(emitNormalValue(mapKey, Long.toString(params.getLongValue(mapKey))));
34 | break;
35 | default:
36 | break;
37 | }
38 | index++;
39 | }
40 |
41 | return substituteCharacters(result.toString());
42 | }
43 |
44 | private String emitNormalArray(String mapKey, ParameterMap[] mapValue) {
45 | StringBuilder b = new StringBuilder();
46 | int index = 0;
47 |
48 | for (ParameterMap arrayMap : mapValue) {
49 | if (index != 0) b.append("&");
50 | b.append(emitArray(mapKey, arrayMap, index));
51 | index++;
52 | }
53 | return b.toString();
54 | }
55 |
56 | private String emitArray(String mapKey, ParameterMap arrayMap, int arrayIndex) {
57 | StringBuilder b = new StringBuilder();
58 | int index = 0;
59 |
60 | for (String key : arrayMap.getKeys()) {
61 | switch (arrayMap.getType(key)) {
62 | case STRING:
63 | if (index != 0) b.append("&");
64 | b.append(mapKey).append("[").append(arrayIndex).append("]");
65 | b.append("[").append(key).append("]=").append(arrayMap.getStringValue(key));
66 | index++;
67 | break;
68 | case MAP:
69 | ParameterMap map = arrayMap.getMapValue(key);
70 | for (String itemKey : map.getKeys()) {
71 | if (index != 0) b.append("&");
72 | b.append(emitArrayValue(mapKey, key, itemKey, map.getStringValue(itemKey), arrayIndex));
73 | index++;
74 | }
75 | break;
76 | case ARRAY:
77 | // TODO does ARRAY need to be handled?
78 | break;
79 | case LONG:
80 | break;
81 | default:
82 | break;
83 | }
84 | }
85 | return b.toString();
86 | }
87 |
88 | private String emitArrayValue(String mapKey, String key, String itemKey, String stringValue, int index) {
89 | StringBuilder b = new StringBuilder();
90 | b.append(mapKey).append("[").append(index).append("]");
91 | b.append("[").append(key).append("]");
92 | b.append("[").append(itemKey).append("]=").append(stringValue);
93 | return b.toString();
94 | }
95 |
96 | private String emitNormalMap(String mapKey, ParameterMap mapValue) {
97 | StringBuilder b = new StringBuilder();
98 | int index = 0;
99 | for (String key : mapValue.getKeys()) {
100 | if (index != 0) b.append("&");
101 | switch (mapValue.getType(key)) {
102 | case LONG:
103 | b.append(emitMapValue(mapKey, key, Long.toString(mapValue.getLongValue(key))));
104 | break;
105 | case STRING:
106 | b.append(emitMapValue(mapKey, key, mapValue.getStringValue(key)));
107 | break;
108 | case MAP:
109 | // TODO does MAP need to be handled?
110 | break;
111 | case ARRAY:
112 | // TODO does ARRAY need to be handled?
113 | break;
114 | }
115 | index++;
116 | }
117 | return b.toString();
118 | }
119 |
120 | private String emitMapValue(String mapKey, String key, String stringValue) {
121 | StringBuilder b = new StringBuilder();
122 | b.append(mapKey).append("[").append(key).append("]=").append(stringValue);
123 | return b.toString();
124 | }
125 |
126 | private String emitNormalValue(String key, String value) {
127 | StringBuilder b = new StringBuilder();
128 | b.append(key).append("=").append(value);
129 | return b.toString();
130 | }
131 |
132 | private String substituteCharacters(String input) {
133 | return input.replace(" ", "%20").replace("[", "%5B").replace("]", "%5D").replace("#", "%23").replace(":", "%3A");
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/test/java/threescale/v3/api/ServiceApiDriverIntegrationTest.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import org.joda.time.format.DateTimeFormat;
6 | import org.joda.time.format.DateTimeFormatter;
7 | import org.junit.Before;
8 |
9 | import threescale.v3.api.example.TestKeys;
10 | import threescale.v3.api.impl.ServiceApiDriver;
11 |
12 | /**
13 | * Integration Test class for the ServiceApiDriver. Currently only tests
14 | * the authrep and report methods and assumes your service uses a user_key
15 | * Assumes your API has 2 methods getHello and getGoodbye, with getHello
16 | * mapped under Hits
17 | * Set your 3 data items (TestKeys.my_provider_key, TestKeys.user_key_service_id,
18 | * TestKeys.user_key) before running
19 | * Optional: rename the methods below to your own (necessary if your methods are named/configured differently)
20 | * Run each test individually and examine the Metrics before and after on your
21 | * Services overview page in the admin site
22 |
23 |
24 | TODO add tests for the other ServiceApiDriver methods and test the other authentication methods
25 | */
26 |
27 | public class ServiceApiDriverIntegrationTest {
28 | private final String provider_key = TestKeys.my_provider_key;
29 |
30 | private ServiceApi serviceApi;
31 | // private ServerAccessor htmlServer;
32 |
33 | DateTimeFormatter fmt;
34 | ParameterMap params;
35 |
36 | @Before
37 | public void setup() {
38 | serviceApi = new ServiceApiDriver(provider_key);
39 |
40 | fmt = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss Z");
41 |
42 | params = new ParameterMap();
43 | params.add("service_id", TestKeys.user_key_service_id);
44 | params.add("user_key", TestKeys.user_key);
45 |
46 | }
47 |
48 | //@Test
49 | // URL Pattern: [usage][hits]=1
50 | // Expected: OK results in Hits incrementing by 1
51 | public void testAuthrepNullUsageAndUserKey() throws ServerError {
52 |
53 | AuthorizeResponse auresp = serviceApi.authrep(params);
54 | reportResult(auresp);
55 | }
56 |
57 |
58 |
59 | //@Test
60 | // URL Pattern: [usage][hits]=1
61 | // Expected: OK results in Hits incrementing by 1
62 | public void testAuthrepEmptyUsageAndUserKey() throws ServerError {
63 |
64 | ParameterMap usage = new ParameterMap();
65 | params.add("usage", usage);
66 |
67 | AuthorizeResponse auresp = serviceApi.authrep(params);
68 | reportResult(auresp);
69 | }
70 |
71 |
72 | //@Test
73 | // URL Pattern: [usage][getHello]=2
74 | // EXPECTED: Success; hits +2
75 | public void testAuthrepUsageWithNestedMethodAndUserKey() throws ServerError {
76 | ParameterMap usage = new ParameterMap();
77 | usage.add("getHello", "2");
78 | params.add("usage", usage);
79 |
80 | AuthorizeResponse auresp = serviceApi.authrep(params);
81 | reportResult(auresp);
82 |
83 | }
84 |
85 | //@Test
86 | // URL Pattern: [usage][hits]=3&[usage][getHello]=2
87 | // EXPECTED: Success; hits +5
88 | public void testAuthrepUsageWithNestedMethodAndHitsAndUserKey() throws ServerError {
89 |
90 | ParameterMap usage = new ParameterMap();
91 | usage.add("getHello", "2");
92 | usage.add("hits", "3");
93 | params.add("usage", usage);
94 |
95 | AuthorizeResponse auresp = serviceApi.authrep(params);
96 | reportResult(auresp);
97 |
98 | }
99 |
100 |
101 | //@Test
102 | // URL Pattern: [usage][getGoodbye]=4
103 | // EXPECTED: Success; hits unchanged, getGoodbye +4
104 | public void testAuthrepUsageWithNonNestedMethodAndUserKey() throws ServerError {
105 |
106 | ParameterMap usage = new ParameterMap();
107 | usage.add("getGoodbye", "4");
108 | params.add("usage", usage);
109 |
110 | AuthorizeResponse auresp = serviceApi.authrep(params);
111 | reportResult(auresp);
112 |
113 | }
114 |
115 | //@Test
116 | // URL Pattern: [usage][hits]=1
117 | // Expected: OK results in Hits incrementing by 1
118 | public void test_successful_report() throws ServerError {
119 |
120 |
121 | ParameterMap usage = new ParameterMap();
122 | usage.add("hits", "1");
123 | params.add("usage", usage);
124 |
125 | ReportResponse response = serviceApi.report(TestKeys.user_key_service_id, params);
126 |
127 | assertTrue(response.success());
128 | }
129 |
130 |
131 | //@Test
132 | // Expected: success
133 | public void testAuthorizeWithEternityPeriod() throws ServerError {
134 |
135 | AuthorizeResponse response = serviceApi.authorize(params);
136 |
137 | assertTrue(response.success());
138 |
139 | }
140 |
141 |
142 | //@Test
143 | // URL http://requestb.in/1k27m9c1
144 | // In order to visually examine the request headers in a POST
145 | //
146 | public void testPostToRequestBin() throws ServerError {
147 |
148 | AuthorizeResponse auresp = serviceApi.authrep(params);
149 | reportResult(auresp);
150 | }
151 |
152 |
153 |
154 | //@Test
155 | // URL http://requestb.in/1k27m9c1
156 | // In order to visually examine the request headers in a GET
157 | //
158 | public void testGetToRequestBin() throws ServerError {
159 | //String url = "http://requestb.in/1k27m9c1;
160 |
161 | ServiceApiDriver localServiceApiDriver = new ServiceApiDriver("provider_key", "http://requestb.in");
162 |
163 | localServiceApiDriver.authorize(new ParameterMap());
164 |
165 | //reportResult(auresp);
166 | }
167 |
168 |
169 |
170 |
171 |
172 |
173 | //*******************************************************************
174 | private void reportResult(AuthorizeResponse auresp){
175 | boolean success = auresp.success();
176 | if (success){
177 | System.out.println("Success");
178 | }
179 | else{
180 | System.out.println("Fail: "+auresp.getReason());
181 | }
182 |
183 | };
184 |
185 | }
186 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/impl/ServerAccessorDriver.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.impl;
2 |
3 | import threescale.v3.api.HttpResponse;
4 | import threescale.v3.api.ServerAccessor;
5 | import threescale.v3.api.ServerError;
6 |
7 | import java.io.*;
8 | import java.net.HttpURLConnection;
9 | import java.net.MalformedURLException;
10 | import java.net.URL;
11 |
12 | import java.util.Properties;
13 | /**
14 | * Performs GET's and POST's against the live 3Scale Server
15 | */
16 | public class ServerAccessorDriver implements ServerAccessor {
17 |
18 | private Properties props;
19 | private String pluginHeaderValue;
20 | private String defaultVersion = "3.1";
21 | public ServerAccessorDriver() {
22 |
23 |
24 | props = new Properties();
25 | try {
26 | InputStream in = ServerAccessorDriver.class.getClassLoader().getResourceAsStream("props.properties");
27 | if (in == null) {
28 | System.out.println("props.properties not found");
29 | }
30 | else{
31 | props.load(in);
32 | defaultVersion = props.getProperty(MAVEN_PROJECT_VERSION);
33 | }
34 |
35 |
36 | } catch (Exception e) {
37 | System.out.println(e);
38 | }
39 | pluginHeaderValue = X_3SCALE_USER_CLIENT_HEADER_JAVA_PLUGIN+defaultVersion;
40 |
41 | }
42 |
43 | /**
44 | * @param urlParams url + parameter string
45 | * @return Http Response
46 | * @throws ServerError
47 | * @see ServerAccessor
48 | */
49 | public HttpResponse get(final String urlParams) throws ServerError {
50 | HttpURLConnection connection = null;
51 | URL url;
52 |
53 | try {
54 | url = new URL(urlParams);
55 | } catch (MalformedURLException ex) {
56 | throw new RuntimeException(ex);
57 | }
58 |
59 | try {
60 | connection = (HttpURLConnection) url.openConnection();
61 | connection.setRequestMethod("GET");
62 | connection.setDoOutput(true);
63 | connection.setReadTimeout(10000);
64 | connection.setRequestProperty("Accept-Charset", "UTF-8");
65 | connection.setRequestProperty(X_3SCALE_USER_CLIENT_HEADER, pluginHeaderValue);
66 |
67 | connection.connect();
68 |
69 |
70 | return new HttpResponse(connection.getResponseCode(), getBody(connection.getInputStream()));
71 |
72 | } catch (IOException ex) {
73 | try {
74 | return new HttpResponse(connection.getResponseCode(), getBody(connection.getErrorStream()));
75 | } catch (IOException e) {
76 | throw new ServerError(e.getMessage());
77 | } catch (NullPointerException npe) {
78 | throw new ServerError("NullPointerException thrown ServerAccessorDriver::get, urlParams were "+urlParams);
79 | }
80 | } catch (NullPointerException npe) {
81 | throw new ServerError("NullPointerException thrown ServerAccessorDriver::get, urlParams were "+urlParams);
82 | } finally {
83 | if (connection != null) {
84 | connection.disconnect();
85 | }
86 | }
87 | }
88 |
89 | private String getBody(InputStream content) throws IOException {
90 | BufferedReader rd;
91 | StringBuilder sb;
92 | String line;
93 | rd = new BufferedReader(new InputStreamReader(content));
94 | sb = new StringBuilder();
95 |
96 | while ((line = rd.readLine()) != null) {
97 | sb.append(line + '\n');
98 | }
99 | return sb.toString();
100 | }
101 |
102 | /**
103 | * @param urlParams url to access
104 | * @param data The data to be sent
105 | * @return Response from the server
106 | * @throws ServerError
107 | * @see ServerAccessor
108 | */
109 | public HttpResponse post(final String urlParams,final String data) throws ServerError {
110 | HttpURLConnection connection = null;
111 | OutputStreamWriter wr;
112 | URL url;
113 |
114 | try {
115 | url = new URL(urlParams);
116 | } catch (MalformedURLException ex) {
117 | throw new RuntimeException(ex);
118 | }
119 | try {
120 | connection = (HttpURLConnection) url.openConnection();
121 | connection.setRequestMethod("POST");
122 | connection.setDoOutput(true);
123 | connection.setReadTimeout(10000);
124 | connection.setRequestProperty("Accept", "*/*");
125 | connection.setRequestProperty("Accept-Charset", "UTF-8");
126 | connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
127 | connection.setRequestProperty(X_3SCALE_USER_CLIENT_HEADER, pluginHeaderValue);
128 |
129 |
130 | connection.connect();
131 | wr = new OutputStreamWriter(connection.getOutputStream());
132 | wr.write(data);
133 | wr.flush();
134 |
135 | return new HttpResponse(connection.getResponseCode(), getBody(connection.getInputStream()));
136 | } catch (IOException ex) {
137 | try {
138 | return new HttpResponse(connection.getResponseCode(),
139 | (connection.getErrorStream() == null) ? getBody(connection.getInputStream()) : getBody(connection.getErrorStream()));
140 | } catch (IOException e) {
141 | throw new ServerError(e.getMessage());
142 | } catch (NullPointerException npe) {
143 | throw new ServerError("NullPointerException thrown ServerAccessorDriver::post, urlParams were "+urlParams+", data was "+data);
144 | }
145 | } catch (NullPointerException npe) {
146 | throw new ServerError("NullPointerException thrown ServerAccessorDriver::post, urlParams were "+urlParams+", data was "+data);
147 | }finally {
148 | if (connection != null) {
149 | connection.disconnect();
150 | }
151 | }
152 | }
153 |
154 | public String getPluginHeaderValue() {
155 | return pluginHeaderValue;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | net.3scale
5 | 3scale-api
6 | 3.0.5-SNAPSHOT
7 |
8 | 3scale Java API
9 |
10 | This API is used to encapsulate the communication with the 3scale backend server for validating and
11 | reporting transactions between the user and the provider of a service
12 |
13 | https://www.3scale.net/
14 |
15 |
16 |
17 | MIT
18 | http://creativecommons.org/licenses/MIT/
19 |
20 |
21 |
22 |
23 |
24 | Andrew Mackenzie
25 | andrew@3scale.net
26 | 3scale
27 | http://www.3scale.net
28 |
29 |
30 |
31 |
32 | GitHub
33 | https://github.com/3scale/3scale_ws_api_for_java/issues
34 |
35 |
36 |
37 | https://github.com/3scale/3scale_ws_api_for_java
38 | scm:git:git@github.com:3scale/3scale_ws_api_for_java.git
39 | scm:git:git@github.com:3scale/3scale_ws_api_for_java.git
40 |
41 |
42 |
43 | 1.6
44 | 1.6
45 | UTF-8
46 |
47 |
48 |
49 |
50 |
51 | central
52 | Central Repository
53 | http://repo.maven.apache.org/maven2
54 |
55 | true
56 |
57 |
58 | false
59 |
60 |
61 |
62 | snapshots-repo
63 | https://oss.sonatype.org/content/repositories/snapshots
64 |
65 | false
66 |
67 |
68 | true
69 |
70 |
71 |
72 | jboss-public-repository-group
73 | JBoss Public Repository Group
74 | http://repository.jboss.org/nexus/content/groups/public
75 | default
76 |
77 | true
78 | never
79 |
80 |
81 | true
82 | daily
83 |
84 |
85 |
86 |
87 |
88 |
89 | ossrh
90 | https://oss.sonatype.org/content/repositories/snapshots
91 |
92 |
93 |
94 |
95 |
96 | xom
97 | xom
98 | 1.2.5
99 |
100 |
101 |
102 |
103 | joda-time
104 | joda-time
105 | 2.3
106 | test
107 |
108 |
109 | org.hamcrest
110 | hamcrest-core
111 | 1.2
112 | test
113 |
114 |
115 | org.jmock
116 | jmock-junit4
117 | 2.6.0
118 | test
119 |
120 |
121 | junit
122 | junit
123 | 4.13.1
124 | test
125 |
126 |
127 |
128 |
129 |
130 |
131 | true
132 | src/main/resources
133 |
134 |
135 |
136 |
137 | org.apache.maven.plugins
138 | maven-compiler-plugin
139 | 3.1
140 |
141 | ${maven.compile.source}
142 | ${maven.compile.source}
143 |
144 |
145 |
146 | org.apache.maven.plugins
147 | maven-javadoc-plugin
148 | 2.9.1
149 |
150 |
151 | attach-javadocs
152 |
153 | jar
154 |
155 |
156 |
157 |
158 |
159 | org.apache.maven.plugins
160 | maven-source-plugin
161 | 3.0.1
162 |
163 |
164 | attach-sources
165 |
166 | jar-no-fork
167 |
168 |
169 |
170 |
171 |
172 | org.apache.maven.plugins
173 | maven-surefire-plugin
174 | 2.16
175 |
176 |
177 | org.apache.maven.plugins
178 | maven-surefire-report-plugin
179 | 2.16
180 |
181 |
182 |
183 |
184 |
185 |
186 | release
187 |
188 |
189 |
190 | org.sonatype.plugins
191 | nexus-staging-maven-plugin
192 | 1.6.7
193 | true
194 |
195 | ossrh
196 | https://oss.sonatype.org/
197 | true
198 |
199 |
200 |
201 | org.apache.maven.plugins
202 | maven-gpg-plugin
203 | 1.6
204 |
205 |
206 | sign-artifacts
207 | verify
208 |
209 | sign
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 | java8
219 |
220 | [1.8,)
221 |
222 |
223 |
224 |
225 | org.apache.maven.plugins
226 | maven-javadoc-plugin
227 |
228 | -Xdoclint:none
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/example/AllCallsExample.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.example;
2 |
3 | import threescale.v3.api.*;
4 | import threescale.v3.api.impl.*;
5 |
6 |
7 | /**
8 | * Simple Example of using the API
9 | */
10 | public class AllCallsExample implements TestKeys {
11 |
12 | public static void main(String[] args) {
13 |
14 | runUserKey();
15 | runAppId();
16 | runOAuth();
17 | }
18 |
19 | /**
20 | * Example code for calls on user key (API key) mode
21 | */
22 | private static void runUserKey() {
23 | ServiceApi serviceApi = new ServiceApiDriver(my_provider_key); // Create the API object
24 |
25 | ParameterMap params = new ParameterMap();
26 | params.add("user_key", user_key); // Add keys for authrep or authorize
27 | params.add("service_id", user_key_service_id);
28 |
29 | ParameterMap usage = new ParameterMap(); // Add a metric
30 | usage.add("hits", "1");
31 |
32 | params.add("usage", usage);
33 |
34 | AuthorizeResponse response = null;
35 | // the 'preferred way': authrep
36 | try {
37 | response = serviceApi.authrep(params);
38 | System.out.println("AuthRep on User Key Success: " + response.success());
39 | if (response.success() == false) {
40 | System.out.println("Error: " + response.getErrorCode());
41 | System.out.println("Reason: " + response.getReason());
42 | }
43 | System.out.println("Plan: " + response.getPlan());
44 | } catch (ServerError serverError) {
45 | serverError.printStackTrace();
46 | }
47 |
48 | // the '2 steps way': authorize + report
49 | try {
50 | response = serviceApi.authorize(params);
51 | System.out.println("Authorize on User Key Success: " + response.success());
52 | if (response.success() == false) {
53 | System.out.println("Error: " + response.getErrorCode());
54 | System.out.println("Reason: " + response.getReason());
55 | } else {
56 |
57 | // the API call got authorized, let's do a report
58 | ParameterMap transaction = new ParameterMap();
59 | transaction.add("user_key", user_key);
60 |
61 | ParameterMap transaction_usage = new ParameterMap();
62 | transaction_usage.add("hits", "1");
63 | transaction.add("usage", transaction_usage);
64 |
65 | try {
66 | final ReportResponse report_response = serviceApi.report(user_key_service_id, transaction);
67 |
68 | if (report_response.success()) {
69 | System.out.println("Report on User Key was successful");
70 | } else {
71 | System.out.println("Report on User Key failed");
72 | }
73 | } catch (ServerError serverError) {
74 | serverError.printStackTrace();
75 | }
76 |
77 | }
78 | System.out.println("Plan: " + response.getPlan());
79 |
80 | } catch (ServerError serverError) {
81 | serverError.printStackTrace();
82 | }
83 | }
84 |
85 | /**
86 | * Example code for calls on App Id mode
87 | */
88 | private static void runAppId() {
89 | ServiceApi serviceApi = new ServiceApiDriver(my_provider_key); // Create the API object
90 |
91 | ParameterMap params = new ParameterMap();
92 | params.add("app_id", app_id); // Add app_id for authrep or authorize
93 | params.add("app_key", app_key); // Add key for authrep or authorize
94 | params.add("service_id", app_id_service_id);
95 |
96 | ParameterMap usage = new ParameterMap(); // Add a metric
97 | usage.add("hits", "1");
98 |
99 | params.add("usage", usage);
100 |
101 | AuthorizeResponse response = null;
102 | // the 'preferred way': authrep
103 | try {
104 | response = serviceApi.authrep(params);
105 | System.out.println("AuthRep on App Id Success: " + response.success());
106 | if (response.success() == false) {
107 | System.out.println("Error: " + response.getErrorCode());
108 | System.out.println("Reason: " + response.getReason());
109 | }
110 | System.out.println("Plan: " + response.getPlan());
111 | } catch (ServerError serverError) {
112 | serverError.printStackTrace();
113 | }
114 |
115 | // the '2 steps way': authorize + report
116 | try {
117 | response = serviceApi.authorize(params);
118 | System.out.println("Authorize on App Id Success: " + response.success());
119 | if (response.success() == false) {
120 | System.out.println("Error: " + response.getErrorCode());
121 | System.out.println("Reason: " + response.getReason());
122 | } else {
123 |
124 | // the API call got authorized, let's do a report
125 | ParameterMap transaction = new ParameterMap();
126 | transaction.add("app_id", app_id);
127 |
128 | ParameterMap transaction_usage = new ParameterMap();
129 | transaction_usage.add("hits", "1");
130 | transaction.add("usage", transaction_usage);
131 |
132 | try {
133 | final ReportResponse report_response = serviceApi.report(app_id_service_id, transaction);
134 |
135 | if (report_response.success()) {
136 | System.out.println("Report on App Id was successful");
137 | } else {
138 | System.out.println("Report on App Id failed");
139 | }
140 | } catch (ServerError serverError) {
141 | serverError.printStackTrace();
142 | }
143 |
144 | }
145 | System.out.println("Plan: " + response.getPlan());
146 |
147 | } catch (ServerError serverError) {
148 | serverError.printStackTrace();
149 | }
150 | }
151 |
152 | /**
153 | * Example code for an OAuth authorize
154 | */
155 | private static void runOAuth() {
156 | ServiceApi serviceApi = new ServiceApiDriver(my_provider_key); // Create the API object
157 |
158 | ParameterMap params = new ParameterMap();
159 | params.add("app_id", oauth_app_id);
160 | params.add("service_id", oauth_service_id);
161 |
162 | // for OAuth only the '2 steps way' is available
163 | try {
164 | AuthorizeResponse response = serviceApi.oauth_authorize(params); // Perform OAuth authorize
165 | System.out.println("Authorize on OAuth Success: " + response.success());
166 | if (response.success() == false) {
167 | System.out.println("Error: " + response.getErrorCode());
168 | System.out.println("Reason: " + response.getReason());
169 | } else {
170 |
171 | // you check the client's secret returned
172 | System.out.println("OAuth Client Secret: " + response.getClientSecret());
173 |
174 | // the API call got authorized, let's do a report
175 | ParameterMap transaction = new ParameterMap();
176 | transaction.add("app_id", oauth_app_id);
177 |
178 | ParameterMap transaction_usage = new ParameterMap();
179 | transaction_usage.add("hits", "1");
180 | transaction.add("usage", transaction_usage);
181 |
182 | try {
183 | final ReportResponse report_response = serviceApi.report(oauth_service_id, transaction);
184 |
185 | if (report_response.success()) {
186 | System.out.println("Report on OAuth was successful");
187 | } else {
188 | System.out.println("Report on OAuth failed");
189 | }
190 | } catch (ServerError serverError) {
191 | serverError.printStackTrace();
192 | }
193 |
194 | }
195 | System.out.println("Plan: " + response.getPlan());
196 | } catch (ServerError serverError) {
197 | serverError.printStackTrace();
198 | }
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/AuthorizeResponse.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | import nu.xom.*;
4 |
5 | import java.io.IOException;
6 | import java.util.ArrayList;
7 |
8 | /**
9 | * Provides information about the success or failure of an Authorize operation.
10 | *
11 | * The success response sets:
12 | * the Status (true = success false = exceeded/failed)
13 | * the Reason if failed.
14 | * the Plan
15 | * the ClientSecret
16 | * the redirect URL
17 | * the Usage reports
18 | *
19 | * The failure response sets:
20 | * the ErrorCode
21 | * Reason.
22 | */
23 | public class AuthorizeResponse {
24 |
25 | private boolean status = false;
26 | private String plan = "";
27 | private String clientSecret = "";
28 | private UsageReport[] usageReports = new UsageReport[0];
29 | private String reason = "";
30 | private String errorCode = "";
31 | private String redirectUrl = "";
32 |
33 | /**
34 | * Build an AuthorizeResponse using the status and content of an html get.
35 | *
36 | * @param httpStatus Status value from the GET
37 | * @param httpContent Contents of the GET
38 | * @throws ServerError If the received XML is invalid, or cannot process the XML
39 | */
40 | public AuthorizeResponse(int httpStatus, String httpContent) throws ServerError {
41 | if (httpStatus == 200 || httpStatus == 409) {
42 | createAuthorizedOKOrExceeded(httpContent);
43 | } else {
44 | createAuthorizationFailed(httpContent);
45 | }
46 | }
47 |
48 | /**
49 | * Create a failure response.
50 | *
51 | * @param httpContent
52 | * @throws ServerError
53 | */
54 | private void createAuthorizationFailed(String httpContent) throws ServerError {
55 | try {
56 | Builder parser = new Builder();
57 | Document doc = parser.build(httpContent, null);
58 | Element root = doc.getRootElement();
59 |
60 | final Attribute codeEl = root.getAttribute("code");
61 | setErrorCode(codeEl.getValue());
62 | setReason(root.getValue());
63 | setStatus("false");
64 |
65 | } catch (ParsingException ex) {
66 | throw new ServerError("The xml received was invalid: " + httpContent);
67 | } catch (IOException ex) {
68 | throw new ServerError("Error processing the XML");
69 | }
70 | }
71 |
72 | /**
73 | * Creates a success response
74 | *
75 | * @param httpContent
76 | * @throws ServerError
77 | */
78 | private void createAuthorizedOKOrExceeded(String httpContent) throws ServerError {
79 | try {
80 | Builder parser = new Builder();
81 | Document doc = parser.build(httpContent, null);
82 | Element root = doc.getRootElement();
83 |
84 | Element authorizedEl = root.getFirstChildElement("authorized");
85 | setStatus(authorizedEl.getValue());
86 | if (success() == false) {
87 | Element reasonEl = root.getFirstChildElement("reason");
88 | if (reasonEl != null) {
89 | setReason(reasonEl.getValue());
90 | }
91 | }
92 |
93 | Element planEl = root.getFirstChildElement("plan");
94 | setPlan(planEl.getValue());
95 |
96 | Element applicationEl = root.getFirstChildElement("application");
97 | if (applicationEl != null) {
98 | Element keyEl = applicationEl.getFirstChildElement("key");
99 | if (keyEl != null) {
100 | setClientSecret(keyEl.getValue());
101 | }
102 |
103 | Element redirectUrlEl = applicationEl.getFirstChildElement("redirect_url");
104 | if (redirectUrlEl != null) {
105 | setRedirectUrl(redirectUrlEl.getValue());
106 | }
107 | } else {
108 | clientSecret = "";
109 | redirectUrl = "";
110 | }
111 | ArrayList reports = new ArrayList();
112 | Element usageReportsEl = root.getFirstChildElement("usage_reports");
113 | if (usageReportsEl != null) {
114 | Elements usageReports = usageReportsEl.getChildElements("usage_report");
115 | for (int upindex = 0; upindex < usageReports.size(); upindex++) {
116 | processUsageReport(reports, usageReports.get(upindex));
117 | }
118 | }
119 | setUsageReports(reports);
120 | return;
121 | } catch (ParsingException ex) {
122 | throw new ServerError("The xml received was invalid: " + httpContent);
123 | } catch (IOException ex) {
124 | throw new ServerError("Error processing the XML");
125 | }
126 | }
127 |
128 | /**
129 | * Parse and build a usage report.
130 | *
131 | * @param reports
132 | * @param usageEl
133 | */
134 | private void processUsageReport(ArrayList reports, Element usageEl) {
135 | final Attribute metricEl = usageEl.getAttribute("metric");
136 | final Attribute periodEl = usageEl.getAttribute("period");
137 | final Attribute exceededEl = usageEl.getAttribute("exceeded");
138 | final Element periodStartEl = usageEl.getFirstChildElement("period_start");
139 | final Element periodEndEl = usageEl.getFirstChildElement("period_end");
140 | final Element currentValue = usageEl.getFirstChildElement("current_value");
141 | final Element maxValue = usageEl.getFirstChildElement("max_value");
142 |
143 | reports.add(new UsageReport(getValueOrBlank(metricEl), getValueOrBlank(periodEl),
144 | getValueOrBlank(periodStartEl), getValueOrBlank(periodEndEl),
145 | getValueOrBlank(currentValue), getValueOrBlank(maxValue),
146 | (exceededEl == null) ? "false" : exceededEl.getValue()
147 | ));
148 | }
149 |
150 |
151 | /**
152 | * Get the name of the Plan
153 | *
154 | * @return Plan name
155 | */
156 | public String getPlan() {
157 | return plan;
158 | }
159 |
160 | private void setPlan(String plan) {
161 | this.plan = plan;
162 | }
163 |
164 | /**
165 | * Get the ClientSecret
166 | *
167 | * @return app key
168 | */
169 | public String getClientSecret() {
170 | return clientSecret;
171 | }
172 |
173 | private void setClientSecret(String clientSecret) {
174 | this.clientSecret = clientSecret;
175 | }
176 |
177 | /**
178 | * Get the redirect url
179 | *
180 | * @return redirect url
181 | */
182 | public String getRedirectUrl() {
183 | return redirectUrl;
184 | }
185 |
186 | /**
187 | * Get the usage reports for this authoize
188 | *
189 | * @return
190 | */
191 | public UsageReport[] getUsageReports() {
192 | return usageReports;
193 | }
194 |
195 | private void setUsageReports(ArrayList reports) {
196 | usageReports = new UsageReport[reports.size()];
197 | usageReports = reports.toArray(new UsageReport[0]);
198 | }
199 |
200 | /**
201 | * Get the status
202 | *
203 | * @return true / false
204 | */
205 | public boolean success() {
206 | return status;
207 | }
208 |
209 | /**
210 | * Get the error code
211 | *
212 | * @return error code
213 | */
214 | public String getErrorCode() {
215 | return errorCode;
216 | }
217 |
218 | private void setErrorCode(String code) {
219 | errorCode = code;
220 | }
221 |
222 | /**
223 | * Get the reason for the failure
224 | *
225 | * @return reason
226 | */
227 | public String getReason() {
228 | return reason;
229 | }
230 |
231 | private void setStatus(String status) {
232 | if (status.toLowerCase().equals("true")) {
233 | this.status = true;
234 | } else {
235 | this.status = false;
236 | }
237 | }
238 |
239 | private void setReason(String reason) {
240 | this.reason = reason;
241 | }
242 |
243 | private void setRedirectUrl(String url) {
244 | this.redirectUrl = url;
245 | }
246 |
247 | private String getValueOrBlank(Attribute attr) {
248 | if (attr == null) {
249 | return "";
250 | } else {
251 | return attr.getValue();
252 | }
253 | }
254 |
255 | private String getValueOrBlank(Element element) {
256 | if (element == null) {
257 | return "";
258 | } else {
259 | return element.getValue();
260 | }
261 | }
262 |
263 |
264 | }
265 |
--------------------------------------------------------------------------------
/src/main/java/threescale/v3/api/impl/ServiceApiDriver.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api.impl;
2 |
3 | import threescale.v3.api.*;
4 |
5 | /**
6 | * Concrete implementation of the ServiceApi.
7 | *
8 | * @see ServiceApi
9 | */
10 | public class ServiceApiDriver implements ServiceApi {
11 |
12 | /**
13 | * Creates a Service Api with default settings. This will communicate with the 3scale
14 | * platform SaaS default server.
15 | */
16 | public static ServiceApi createApi() {
17 | return ServiceApiDriver.createApi(ServiceApi.DEFAULT_HOST, 443, true);
18 | }
19 |
20 | /**
21 | * Creates a Service Api for the given host. Use this method when connecting to an on-premise
22 | * instance of the 3scale platform.
23 | */
24 | public static ServiceApi createApi(String host, int port, boolean useHttps) {
25 | ServiceApiDriver driver = new ServiceApiDriver();
26 | driver.host = host + ":" + port;
27 | driver.useHttps = useHttps;
28 | return driver;
29 | }
30 |
31 | private String provider_key = null;
32 | private String host = DEFAULT_HOST;
33 | private boolean useHttps = false;
34 | // private String redirect_url = "http://localhost:8080/oauth/oauth_redirect";
35 |
36 | private ServerAccessor server = null;
37 |
38 | public ServiceApiDriver() {
39 | this.server = new ServerAccessorDriver();
40 | }
41 |
42 | /**
43 | * @deprecated Instead of using a provider_key, use service tokens. See static constructor methods: createApi().
44 | */
45 | @Deprecated
46 | public ServiceApiDriver(String provider_key) {
47 | this.provider_key = provider_key;
48 | this.server = new ServerAccessorDriver();
49 | }
50 |
51 | /**
52 | * @deprecated Instead of using a provider_key, use service tokens. See static constructor methods: createApi().
53 | */
54 | @Deprecated
55 | public ServiceApiDriver(String provider_key, boolean useHttps) {
56 | this.provider_key = provider_key;
57 | this.useHttps = useHttps;
58 | this.server = new ServerAccessorDriver();
59 | }
60 |
61 | /**
62 | * @deprecated Instead of using a provider_key, use service tokens. See static constructor methods: createApi().
63 | */
64 | @Deprecated
65 | public ServiceApiDriver(String provider_key, String host) {
66 | this.provider_key = provider_key;
67 | this.host = host;
68 | this.server = new ServerAccessorDriver();
69 | }
70 |
71 | /**
72 | * @deprecated Instead of using a provider_key, use service tokens. See static constructor methods: createApi().
73 | */
74 | @Deprecated
75 | public ServiceApiDriver(String provider_key, String host, boolean useHttps) {
76 | this.provider_key = provider_key;
77 | this.host = host;
78 | this.useHttps = useHttps;
79 | this.server = new ServerAccessorDriver();
80 | }
81 |
82 | /* (non-Javadoc)
83 | * @see threescale.v3.api.ServiceApi#authrep(threescale.v3.api.ParameterMap)
84 | */
85 | public AuthorizeResponse authrep(ParameterMap metrics) throws ServerError {
86 | if (this.provider_key != null) {
87 | metrics.add("provider_key", provider_key);
88 | }
89 |
90 | ParameterMap usage = metrics.getMapValue("usage");
91 |
92 | if (usage == null || usage.size()==0) {
93 | if (usage == null) {
94 | usage = new ParameterMap();
95 | metrics.add("usage", usage);
96 | }
97 | usage.add("hits", "1");
98 | }
99 | String urlParams = encodeAsString(metrics);
100 |
101 | final String s = getFullHostUrl() + "/transactions/authrep.xml?" + urlParams;
102 | // System.out.println("Actual: " + s);
103 |
104 | HttpResponse response = server.get(s);
105 | if (response.getStatus() == 500) {
106 | throw new ServerError(response.getBody());
107 | }
108 | return convertXmlToAuthorizeResponse(response);
109 | }
110 |
111 | /* (non-Javadoc)
112 | * @see threescale.v3.api.ServiceApi#authrep(java.lang.String, java.lang.String, threescale.v3.api.ParameterMap)
113 | */
114 | public AuthorizeResponse authrep(String serviceToken, String serviceId, ParameterMap metrics) throws ServerError {
115 | if (serviceToken != null) {
116 | metrics.add("service_token", serviceToken);
117 | }
118 | if (serviceId != null) {
119 | metrics.add("service_id", serviceId);
120 | }
121 | return authrep(metrics);
122 | }
123 |
124 | /* (non-Javadoc)
125 | * @see threescale.v3.api.ServiceApi#report(java.lang.String, java.lang.String, threescale.v3.api.ParameterMap[])
126 | */
127 | public ReportResponse report(String serviceToken, String serviceId, ParameterMap... transactions)
128 | throws ServerError {
129 | if (transactions == null || transactions.length == 0)
130 | throw new IllegalArgumentException("No transactions provided");
131 |
132 | ParameterMap params = new ParameterMap();
133 | if (this.provider_key != null) {
134 | params.add("provider_key", provider_key);
135 | }
136 | if (serviceToken != null) {
137 | params.add("service_token", serviceToken);
138 | }
139 | if (serviceId != null) {
140 | params.add("service_id", serviceId);
141 | }
142 | params.add("transactions", transactions);
143 |
144 | HttpResponse response = server.post(getFullHostUrl() + "/transactions.xml", encodeAsString(params));
145 | if (response.getStatus() == 500) {
146 | throw new ServerError(response.getBody());
147 | }
148 | return new ReportResponse(response);
149 | }
150 |
151 | @Override
152 | public ReportResponse report(String serviceId, ParameterMap... transactions) throws ServerError {
153 | return this.report(null, serviceId, transactions);
154 | }
155 |
156 | /* (non-Javadoc)
157 | * @see threescale.v3.api.ServiceApi#authorize(threescale.v3.api.ParameterMap)
158 | */
159 | public AuthorizeResponse authorize(ParameterMap parameters) throws ServerError {
160 | if (this.provider_key != null) {
161 | parameters.add("provider_key", provider_key);
162 | }
163 | String urlParams = encodeAsString(parameters);
164 |
165 | final String s = getFullHostUrl() + "/transactions/authorize.xml?" + urlParams;
166 | HttpResponse response = server.get(s);
167 | if (response.getStatus() == 500) {
168 | throw new ServerError(response.getBody());
169 | }
170 | return convertXmlToAuthorizeResponse(response);
171 | }
172 |
173 | @Override
174 | public AuthorizeResponse authorize(String serviceToken, String serviceId, ParameterMap parameters)
175 | throws ServerError {
176 | if (serviceToken != null) {
177 | parameters.add("service_token", serviceToken);
178 | }
179 | if (serviceId != null) {
180 | parameters.add("service_id", serviceId);
181 | }
182 | return authorize(parameters);
183 | }
184 |
185 | public String getHost() {
186 | return host;
187 | }
188 |
189 | /* (non-Javadoc)
190 | * @see threescale.v3.api.ServiceApi#oauth_authorize(threescale.v3.api.ParameterMap)
191 | */
192 | public AuthorizeResponse oauth_authorize(ParameterMap params) throws ServerError {
193 | if (this.provider_key != null) {
194 | params.add("provider_key", provider_key);
195 | }
196 |
197 | String urlParams = encodeAsString(params);
198 |
199 | final String s = getFullHostUrl() + "/transactions/oauth_authorize.xml?" + urlParams;
200 | // System.out.println("Actual: " + s);
201 |
202 | HttpResponse response = server.get(s);
203 | if (response.getStatus() == 500) {
204 | throw new ServerError(response.getBody());
205 | }
206 | return convertXmlToAuthorizeResponse(response);
207 | }
208 |
209 | /* (non-Javadoc)
210 | * @see threescale.v3.api.ServiceApi#oauth_authorize(java.lang.String, java.lang.String, threescale.v3.api.ParameterMap)
211 | */
212 | public AuthorizeResponse oauth_authorize(String serviceToken, String serviceId, ParameterMap params)
213 | throws ServerError {
214 | if (serviceToken != null) {
215 | params.add("service_token", serviceToken);
216 | }
217 | if (serviceId != null) {
218 | params.add("service_id", serviceId);
219 | }
220 | return oauth_authorize(params);
221 | }
222 |
223 | private String getFullHostUrl() {
224 |
225 | return useHttps ? "https://" + getHost() : "http://" + getHost();
226 | }
227 |
228 |
229 | public String encodeAsString(ParameterMap params) {
230 | ParameterEncoder encoder = new ParameterEncoder();
231 | return encoder.encode(params);
232 | }
233 |
234 |
235 | private AuthorizeResponse convertXmlToAuthorizeResponse(HttpResponse res) throws ServerError {
236 | return new AuthorizeResponse(res.getStatus(), res.getBody());
237 | }
238 |
239 |
240 | public ServiceApiDriver setServer(ServerAccessor server) {
241 | this.server = server;
242 | return this;
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://travis-ci.org/3scale/3scale_ws_api_for_java)
2 |
3 | 3scale is an API Infrastructure service which handles API Keys, Rate Limiting, Analytics, Billing Payments and Developer Management. Includes a configurable API dashboard and developer portal CMS. More product stuff at http://www.3scale.net/, support information at http://support.3scale.net/.
4 |
5 | Plugin Versions
6 | ===============
7 |
8 | This is the version 3 of the plugin, if you were using this plugin before March 8th 2013, you are using the old [version 2](https://github.com/3scale/3scale_ws_api_for_java/tree/v2) of it, but we strongly recommend you to port your code to this new simpler version.
9 |
10 | Synopsis
11 | ========
12 |
13 | This plugin supports the 3 main calls to the 3scale backend:
14 |
15 | - *authrep* grants access to your API and reports the traffic on it in one call.
16 | - *authorize* grants access to your API.
17 | - *report* reports traffic on your API.
18 |
19 | 3scale supports 3 authentication modes: App Id, User Key and OAuth. The first two are similar on their calls to the backend, they support *authrep*. OAuth differs in its usage two calls are required: first *authorize* then *report*.
20 |
21 | Install
22 | =======
23 |
24 | This is a [Maven](http://maven.apache.org/) project, to add it to your project you can use one of the following options:
25 | - add a dependency to this artifact inside your `pom.xml` like below (specify the version you need):
26 | ```
27 |
28 | net.3scale
29 | 3scale-api
30 | 3.0.4
31 |
32 | ```
33 | and run `mvn install` inside your project.
34 |
35 | - download the [JAR file](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22net.3scale%22%20AND%20a%3A%223scale-api%22) for the version you want to use and install it to your repository using the instructions described here: http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
36 |
37 |
38 | Usage on App Id auth mode
39 | =========================
40 |
41 | On App Id mode you call *authrep* to: grant access to your API, and also report the traffic on it at the same time.
42 |
43 | ```java
44 | // import the 3scale library into your code
45 | import threescale.v3.api.*;
46 | import threescale.v3.api.impl.*;
47 |
48 | // ... somewhere inside your code
49 |
50 | // Create the API object with default settings. This will communicate with the 3scale platform SaaS default server.
51 | ServiceApi serviceApi = ServiceApiDriver.createApi();
52 |
53 | // When connecting to an on-premise instance of the 3scale platform, create the API object for a given host and port:
54 | // ServiceApi serviceApi = ServiceApiDriver.createApi("backend.example.com", 80, true);
55 |
56 |
57 | ParameterMap params = new ParameterMap(); // the parameters of your call
58 | params.add("app_id", "your_app_id"); // Add app_id of your application for authorization
59 | params.add("app_key", "your_app_key"); // Add app_key of your application for authorization
60 |
61 | String serviceToken = ...; // Your 3scale service token
62 | String serviceId = ...; // The service id of your application
63 |
64 | ParameterMap usage = new ParameterMap(); // Add a metric to the call
65 | usage.add("hits", "1");
66 | params.add("usage", usage); // metrics belong inside the usage parameter
67 |
68 | AuthorizeResponse response = null;
69 | // the 'preferred way' of calling the backend: authrep
70 | try {
71 | response = serviceApi.authrep(serviceToken, serviceId, params);
72 | System.out.println("AuthRep on App Id Success: " + response.success());
73 | if (response.success() == true) {
74 | // your api access got authorized and the traffic added to 3scale backend
75 | System.out.println("Plan: " + response.getPlan());
76 | } else {
77 | // your api access did not authorized, check why
78 | System.out.println("Error: " + response.getErrorCode());
79 | System.out.println("Reason: " + response.getReason());
80 | }
81 | } catch (ServerError serverError) {
82 | serverError.printStackTrace();
83 | }
84 | ```
85 |
86 | Usage on API Key auth mode
87 | ==========================
88 |
89 | On API Key mode you call *authrep* to: grant access to your API, and also report the traffic on it at the same time.
90 |
91 | ```java
92 | // import the 3scale library into your code
93 | import threescale.v3.api.*;
94 | import threescale.v3.api.impl.*;
95 |
96 | // ... somewhere inside your code
97 |
98 | // Create the API object with default settings. This will communicate with the 3scale platform SaaS default server.
99 | ServiceApi serviceApi = ServiceApiDriver.createApi();
100 |
101 | // When connecting to an on-premise instance of the 3scale platform, create the API object for a given host and port:
102 | //ServiceApi serviceApi = ServiceApiDriver.createApi("backend.example.com", 80, true);
103 |
104 | ParameterMap params = new ParameterMap(); // the parameters of your call
105 | params.add("user_key", "your_user_key"); // Add the user key of your application for authorization
106 |
107 | String serviceToken = ...; // Your 3scale service token
108 | String serviceId = ...; // The service id for your user key
109 |
110 | ParameterMap usage = new ParameterMap(); // Add a metric to the call
111 | usage.add("hits", "1");
112 | params.add("usage", usage); // metrics belong inside the usage parameter
113 |
114 | AuthorizeResponse response = null;
115 | // the 'preferred way' of calling the backend: authrep
116 | try {
117 | response = serviceApi.authrep(serviceToken, serviceId, params);
118 | System.out.println("AuthRep on User Key Success: " + response.success());
119 | if (response.success() == true) {
120 | // your api access got authorized and the traffic added to 3scale backend
121 | System.out.println("Plan: " + response.getPlan());
122 | } else {
123 | // your api access did not authorized, check why
124 | System.out.println("Error: " + response.getErrorCode());
125 | System.out.println("Reason: " + response.getReason());
126 | }
127 | } catch (ServerError serverError) {
128 | serverError.printStackTrace();
129 | }
130 | ```
131 |
132 | Usage on OAuth auth mode
133 | ==========================
134 |
135 | On OAuth you have to make two calls, first *authorize* to grant access to your API and then *report* the traffic on it.
136 |
137 | ```java
138 | // import the 3scale library into your code
139 | import threescale.v3.api.*;
140 | import threescale.v3.api.impl.*;
141 |
142 | // ... somewhere inside your code
143 |
144 | // Create the API object with default settings. This will communicate with the 3scale platform SaaS default server.
145 | ServiceApi serviceApi = ServiceApiDriver.createApi();
146 |
147 | // When connecting to an on-premise instance of the 3scale platform, create the API object for a given host and port:
148 | //ServiceApi serviceApi = ServiceApiDriver.createApi("backend.example.com", 80, true);
149 |
150 | ParameterMap params = new ParameterMap(); // the parameters of your call
151 | params.add("app_id", "your_oauth_app_id"); // Add the app_id of your application for authorization
152 |
153 | String serviceToken = ...; // Your 3scale service token
154 | String serviceId = ...; // The service id of your application
155 |
156 | ParameterMap usage = new ParameterMap(); // Add a metric to the call
157 | usage.add("hits", "1");
158 | params.add("usage", usage); // metrics belong inside the usage parameter
159 |
160 | // for OAuth only the '2 steps way' (authorize + report) is available
161 | try {
162 | AuthorizeResponse response = serviceApi.oauth_authorize(serviceToken, serviceId, params); // Perform OAuth authorize
163 | System.out.println("Authorize on OAuth Success: " + response.success());
164 | if (response.success() == true) {
165 |
166 | // your api access got authorized
167 |
168 | // you check the client's secret returned by the backend
169 | System.out.println("OAuth Client Secret: " + response.getClientSecret());
170 |
171 | // let's do a report
172 | ParameterMap transaction = new ParameterMap();
173 | transaction.add("app_id", "your_oauth_app_id");
174 |
175 | ParameterMap transaction_usage = new ParameterMap();
176 | transaction_usage.add("hits", "1");
177 | transaction.add("usage", transaction_usage);
178 |
179 | try {
180 | final ReportResponse report_response = serviceApi.report("your_oauth_service_id", transaction);
181 |
182 | if (report_response.success()) {
183 | System.out.println("Report on OAuth was successful");
184 | } else {
185 | System.out.println("Report on OAuth failed");
186 | }
187 | } catch (ServerError serverError) {
188 | serverError.printStackTrace();
189 | }
190 | } else {
191 | // your api access did not got authorized, check why
192 | System.out.println("Error: " + response.getErrorCode());
193 | System.out.println("Reason: " + response.getReason());
194 | }
195 | } catch (ServerError serverError) {
196 | serverError.printStackTrace();
197 | }
198 | ```
199 |
200 | To test
201 | =======
202 |
203 | To test the plugin with your real data:
204 | - edit the interface [TestKeys](https://github.com/3scale/3scale_ws_api_for_java/blob/master/src/main/java/threescale/v3/api/example/TestKeys.java) and put in there your provider key as well as service ids and apps auth fields
205 | - run [AllCallsExample](https://github.com/3scale/3scale_ws_api_for_java/blob/master/src/main/java/threescale/v3/api/example/AllCallsExample.java) class
206 |
--------------------------------------------------------------------------------
/src/test/java/threescale/v3/api/ServiceApiDriverTest.java:
--------------------------------------------------------------------------------
1 | package threescale.v3.api;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertFalse;
5 | import static org.junit.Assert.assertTrue;
6 |
7 | import java.util.Arrays;
8 | import java.util.List;
9 |
10 | import org.hamcrest.Description;
11 | import org.hamcrest.TypeSafeMatcher;
12 | import org.jmock.Expectations;
13 | import org.jmock.integration.junit4.JUnitRuleMockery;
14 | import org.joda.time.DateTime;
15 | import org.joda.time.DateTimeZone;
16 | import org.joda.time.format.DateTimeFormat;
17 | import org.joda.time.format.DateTimeFormatter;
18 | import org.junit.Before;
19 | import org.junit.Rule;
20 | import org.junit.Test;
21 |
22 | import threescale.v3.api.impl.ServiceApiDriver;
23 |
24 | /**
25 | * Test class for the Service Api.
26 | */
27 |
28 | public class ServiceApiDriverTest {
29 |
30 | @Rule
31 | public JUnitRuleMockery context = new JUnitRuleMockery();
32 |
33 | private final String host = ServiceApi.DEFAULT_HOST;
34 | private final String provider_key = "1234abcd";
35 |
36 | private ServiceApi serviceApi;
37 | private ServerAccessor htmlServer;
38 |
39 | DateTimeFormatter fmt;
40 |
41 | @Before
42 | public void setup() {
43 | htmlServer = context.mock(ServerAccessor.class);
44 | serviceApi = new ServiceApiDriver(provider_key).setServer(htmlServer);
45 |
46 | fmt = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss Z");
47 | }
48 |
49 | @Test
50 | public void test_default_host() {
51 | serviceApi = new ServiceApiDriver();
52 |
53 | assertEquals("su1.3scale.net", serviceApi.getHost());
54 | }
55 |
56 | @Test
57 | public void test_custom_host() {
58 | serviceApi = new ServiceApiDriver("1234abcd", "example.com");
59 |
60 | assertEquals("example.com", serviceApi.getHost());
61 | }
62 |
63 | @Test
64 | public void test_authrep_usage_is_encoded() throws ServerError {
65 | assertAuthrepUrlWithParams("usage%5Bmethod%5D=666");
66 |
67 | ParameterMap params = new ParameterMap();
68 | ParameterMap usage = new ParameterMap();
69 | usage.add("method", "666");
70 | params.add("usage", usage);
71 |
72 | serviceApi.authrep(params);
73 | }
74 |
75 | @Test
76 | public void test_authrep_usage_values_are_encoded() throws ServerError {
77 |
78 | assertAuthrepUrlWithParams("usage%5Bhits%5D=%230");
79 |
80 | ParameterMap params = new ParameterMap();
81 | ParameterMap usage = new ParameterMap();
82 | usage.add("hits", "#0");
83 | params.add("usage", usage);
84 |
85 | serviceApi.authrep(params);
86 | }
87 |
88 | @Test
89 | public void test_authrep_usage_defaults_to_hits_1() throws ServerError {
90 |
91 | assertAuthrepUrlWithParams("usage%5Bhits%5D=1&app_id=appid");
92 |
93 | ParameterMap params = new ParameterMap();
94 | params.add("app_id", "appid");
95 |
96 | serviceApi.authrep(params);
97 | }
98 |
99 | @Test
100 | public void test_authrep_supports_app_id_app_key_auth_mode() throws ServerError {
101 | assertAuthrepUrlWithParams("usage%5Bhits%5D=1&app_key=appkey&app_id=appid");
102 |
103 | ParameterMap params = new ParameterMap();
104 | params.add("app_id", "appid");
105 | params.add("app_key", "appkey");
106 | serviceApi.authrep(params);
107 | }
108 |
109 | @Test
110 | public void test_successful_authrep_with_app_keys() throws ServerError {
111 | final String body = "" +
112 | "true " +
113 | "Ultimate " +
114 | " ";
115 |
116 | context.checking(new UrlWithParamsExpectations() {{
117 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authrep.xml?provider_key=1234abcd&usage%5Bhits%5D=1&app_key=toosecret&app_id=foo"));
118 | will(returnValue(new HttpResponse(200, body)));
119 | }});
120 |
121 | ParameterMap params = new ParameterMap();
122 | params.add("app_id", "foo");
123 | params.add("app_key", "toosecret");
124 |
125 | AuthorizeResponse response = serviceApi.authrep(params);
126 | assertTrue(response.success());
127 | }
128 |
129 |
130 | @Test
131 | public void test_successful_authorize() throws ServerError {
132 | final String body = "" +
133 | "true " +
134 | "Ultimate " +
135 | "" +
136 | " " +
137 | " 2010-04-26 00:00:00 +0000 " +
138 | " 2010-04-27 00:00:00 +0000 " +
139 | " 10023 " +
140 | " 50000 " +
141 | " " +
142 |
143 | " " +
144 | " 2010-04-01 00:00:00 +0000 " +
145 | " 2010-05-01 00:00:00 +0000 " +
146 | " 999872 " +
147 | " 150000 " +
148 | " " +
149 | " " +
150 | " ";
151 |
152 | context.checking(new UrlWithParamsExpectations() {{
153 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authorize.xml?provider_key=1234abcd&app_id=foo"));
154 | will(returnValue(new HttpResponse(200, body)));
155 | }});
156 |
157 | ParameterMap params = new ParameterMap();
158 | params.add("app_id", "foo");
159 | AuthorizeResponse response = serviceApi.authorize(params);
160 |
161 | assertTrue(response.success());
162 | assertEquals("Ultimate", response.getPlan());
163 | assertEquals(2, response.getUsageReports().length);
164 |
165 | assertEquals("day", response.getUsageReports()[0].getPeriod());
166 | assertEquals(fmt.print(new DateTime(2010, 4, 26, 00, 00, DateTimeZone.UTC)), response.getUsageReports()[0].getPeriodStart());
167 | assertEquals(fmt.print(new DateTime(2010, 4, 27, 00, 00, DateTimeZone.UTC)), response.getUsageReports()[0].getPeriodEnd());
168 | assertEquals("10023", response.getUsageReports()[0].getCurrentValue());
169 | assertEquals("50000", response.getUsageReports()[0].getMaxValue());
170 |
171 | assertEquals("month", response.getUsageReports()[1].getPeriod());
172 | assertEquals(fmt.print(new DateTime(2010, 4, 1, 0, 0, DateTimeZone.UTC)), response.getUsageReports()[1].getPeriodStart());
173 | assertEquals(fmt.print(new DateTime(2010, 5, 1, 0, 0, DateTimeZone.UTC)), response.getUsageReports()[1].getPeriodEnd());
174 | assertEquals("999872", response.getUsageReports()[1].getCurrentValue());
175 | assertEquals("150000", response.getUsageReports()[1].getMaxValue());
176 | }
177 |
178 | @Test
179 | public void test_successful_authorize_with_app_keys() throws ServerError {
180 | final String body = "" +
181 | "true " +
182 | "Ultimate " +
183 | " ";
184 |
185 | context.checking(new UrlWithParamsExpectations() {{
186 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authorize.xml?provider_key=1234abcd&app_key=toosecret&app_id=foo"));
187 | will(returnValue(new HttpResponse(200, body)));
188 | }});
189 |
190 | ParameterMap params = new ParameterMap();
191 | params.add("app_id", "foo");
192 | params.add("app_key", "toosecret");
193 |
194 | AuthorizeResponse response = serviceApi.authorize(params);
195 | assertTrue(response.success());
196 | }
197 |
198 | @Test
199 | public void test_authorize_with_exceeded_usage_limits() throws ServerError {
200 | final String body = "" +
201 | "false " +
202 | "usage limits are exceeded " +
203 |
204 | "Ultimate " +
205 |
206 | "" +
207 | " " +
208 | " 2010-04-26 00:00:00 +0000 " +
209 | " 2010-04-27 00:00:00 +0000 " +
210 | " 50002 " +
211 | " 50000 " +
212 | " " +
213 |
214 | "" +
215 | " 2010-04-01 00:00:00 +0000 " +
216 | " 2010-05-01 00:00:00 +0000 " +
217 | " 999872 " +
218 | " 150000 " +
219 | " " +
220 | " " +
221 | " ";
222 |
223 |
224 | context.checking(new UrlWithParamsExpectations() {{
225 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authorize.xml?provider_key=1234abcd&app_id=foo"));
226 | will(returnValue(new HttpResponse(409, body)));
227 | }});
228 |
229 | ParameterMap params = new ParameterMap();
230 | params.add("app_id", "foo");
231 | AuthorizeResponse response = serviceApi.authorize(params);
232 |
233 | assertFalse(response.success());
234 | assertTrue("usage limits are exceeded".equals(response.getReason()));
235 | assertTrue(response.getUsageReports()[0].hasExceeded());
236 | }
237 |
238 | @Test
239 | public void test_authorize_with_invalid_app_id() throws ServerError {
240 | final String body = "application with id=\"foo\" was not found ";
241 |
242 | context.checking(new UrlWithParamsExpectations() {{
243 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authorize.xml?provider_key=1234abcd&app_id=foo"));
244 | will(returnValue(new HttpResponse(403, body)));
245 | }});
246 |
247 | ParameterMap params = new ParameterMap();
248 | params.add("app_id", "foo");
249 | AuthorizeResponse response = serviceApi.authorize(params);
250 |
251 | assertFalse(response.success());
252 | assertTrue("application_not_found".equals(response.getErrorCode()));
253 | assertTrue("application with id=\"foo\" was not found".equals(response.getReason()));
254 | }
255 |
256 |
257 | @Test
258 | public void test_authorize_metric_period_eternity() throws ServerError {
259 | final String body = "" +
260 | "true " +
261 | " Per hit " +
262 | " " +
263 | " " +
264 | " 0 " +
265 | " 0 " +
266 | " " +
267 | " " +
268 | " ";
269 |
270 |
271 | context.checking(new UrlWithParamsExpectations() {{
272 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authorize.xml?provider_key=1234abcd&app_id=foo"));
273 | will(returnValue(new HttpResponse(200, body)));
274 | }});
275 |
276 | ParameterMap params = new ParameterMap();
277 | params.add("app_id", "foo");
278 | AuthorizeResponse response = serviceApi.authorize(params);
279 |
280 | assertTrue(response.success());
281 |
282 | assertEquals("Per hit", response.getPlan());
283 | assertEquals(1, response.getUsageReports().length);
284 |
285 | assertEquals("0", response.getUsageReports()[0].getCurrentValue());
286 | assertEquals("0", response.getUsageReports()[0].getMaxValue());
287 |
288 | assertEquals("", response.getUsageReports()[0].getPeriodStart());
289 | assertEquals("", response.getUsageReports()[0].getPeriodEnd());
290 |
291 | }
292 |
293 | @Test(expected = ServerError.class)
294 | public void test_authorize_with_server_error() throws ServerError {
295 | context.checking(new UrlWithParamsExpectations() {{
296 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/authorize.xml?provider_key=1234abcd&app_id=foo"));
297 | will(returnValue(new HttpResponse(500, "OMG! WTF!")));
298 | }});
299 |
300 | // FakeWeb.register_uri(:get, "http://#{@host}/transactions/authorize.xml?provider_key=1234abcd&app_id=foo", :status => ['500', 'Internal Server Error'], :body => 'OMG! WTF!')
301 | ParameterMap params = new ParameterMap();
302 | params.add("app_id", "foo");
303 |
304 | serviceApi.authorize(params);
305 | }
306 |
307 | @Test
308 | public void test_successful_oauth_authorize() throws ServerError {
309 | final String body = "" +
310 | "true " +
311 | "" +
312 | " 94bd2de3 " +
313 | " 883bdb8dbc3b6b77dbcf26845560fdbb " +
314 | " http://localhost:8080/oauth/oauth_redirect " +
315 | " " +
316 | "Ultimate " +
317 | "" +
318 | " " +
319 | " 2012-01-30 00:00:00 +0000 " +
320 | " 2012-02-06 00:00:00 +0000 " +
321 | " 5000 " +
322 | " 1 " +
323 | " " +
324 | " " +
325 | " 2012-02-03 00:00:00 +0000 " +
326 | " 2012-02-03 00:00:00 +0000 " +
327 | " 0 " +
328 | " 0 " +
329 | " " +
330 | " " +
331 | " ";
332 |
333 | context.checking(new UrlWithParamsExpectations() {{
334 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/oauth_authorize.xml?redirect_url=http%3A//localhost%3A8080/oauth/oauth_redirect&provider_key=1234abcd&app_id=foo"));
335 | will(returnValue(new HttpResponse(200, body)));
336 | }});
337 |
338 | ParameterMap params = new ParameterMap();
339 | params.add("app_id", "foo");
340 | params.add("redirect_url", "http://localhost:8080/oauth/oauth_redirect");
341 |
342 | AuthorizeResponse response = serviceApi.oauth_authorize(params);
343 | assertTrue(response.success());
344 |
345 | assertEquals("883bdb8dbc3b6b77dbcf26845560fdbb", response.getClientSecret());
346 | assertEquals("http://localhost:8080/oauth/oauth_redirect", response.getRedirectUrl());
347 |
348 | assertEquals("Ultimate", response.getPlan());
349 | assertEquals(2, response.getUsageReports().length);
350 |
351 | assertEquals("week", response.getUsageReports()[0].getPeriod());
352 | assertEquals(fmt.print(new DateTime(2012, 1, 30, 0, 0, DateTimeZone.UTC)), response.getUsageReports()[0].getPeriodStart());
353 | assertEquals(fmt.print(new DateTime(2012, 02, 06, 0, 0, DateTimeZone.UTC)), response.getUsageReports()[0].getPeriodEnd());
354 | assertEquals("1", response.getUsageReports()[0].getCurrentValue());
355 | assertEquals("5000", response.getUsageReports()[0].getMaxValue());
356 |
357 | assertEquals("minute", response.getUsageReports()[1].getPeriod());
358 | assertEquals(fmt.print(new DateTime(2012, 2, 03, 0, 0, DateTimeZone.UTC)), response.getUsageReports()[1].getPeriodStart());
359 | assertEquals(fmt.print(new DateTime(2012, 2, 03, 0, 0, DateTimeZone.UTC)), response.getUsageReports()[1].getPeriodEnd());
360 | assertEquals("0", response.getUsageReports()[1].getCurrentValue());
361 | assertEquals("0", response.getUsageReports()[1].getMaxValue());
362 | }
363 |
364 | @Test
365 | public void test_oauth_authorize_with_exceeded_usage_limits() throws ServerError {
366 | final String body = "" +
367 | "false " +
368 | "usage limits are exceeded " +
369 | "" +
370 | " 94bd2de3 " +
371 | " 883bdb8dbc3b6b77dbcf26845560fdbb " +
372 | " http://localhost:8080/oauth/oauth_redirect " +
373 | " " +
374 | "Ultimate " +
375 | "" +
376 | " " +
377 | " 2010-04-26 00:00:00 +0000 " +
378 | " 2010-04-27 00:00:00 +0000 " +
379 | " 50002 " +
380 | " 50000 " +
381 | " " +
382 |
383 | " " +
384 | " 2010-04-01 00:00:00 +0000 " +
385 | " 2010-05-01 00:00:00 +0000 " +
386 | " 999872 " +
387 | " 150000 " +
388 | " " +
389 | " " +
390 | " ";
391 |
392 | context.checking(new UrlWithParamsExpectations() {{
393 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo"));
394 | will(returnValue(new HttpResponse(409, body)));
395 | }});
396 |
397 |
398 | ParameterMap params = new ParameterMap();
399 | params.add("app_id", "foo");
400 | AuthorizeResponse response = serviceApi.oauth_authorize(params);
401 |
402 | assertFalse(response.success());
403 | assertEquals("usage limits are exceeded", response.getReason());
404 | assertTrue(response.getUsageReports()[0].hasExceeded());
405 | }
406 |
407 | @Test
408 | public void test_oauth_authorize_with_invalid_app_id() throws ServerError {
409 | final String body = "application with id=\"foo\" was not found ";
410 |
411 | context.checking(new UrlWithParamsExpectations() {{
412 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo"));
413 | will(returnValue(new HttpResponse(403, body)));
414 | }});
415 |
416 | ParameterMap params = new ParameterMap();
417 | params.add("app_id", "foo");
418 |
419 | AuthorizeResponse response = serviceApi.oauth_authorize(params);
420 |
421 | assertFalse(response.success());
422 | assertEquals("application_not_found", response.getErrorCode());
423 | assertEquals("application with id=\"foo\" was not found", response.getReason());
424 | }
425 |
426 | @Test(expected = ServerError.class)
427 | public void test_oath_authorize_with_server_error() throws ServerError {
428 |
429 | context.checking(new UrlWithParamsExpectations() {{
430 | oneOf(htmlServer).get(withUrl("http://" + host + "/transactions/oauth_authorize.xml?provider_key=1234abcd&app_id=foo"));
431 | will(returnValue(new HttpResponse(500, "OMG! WTF!")));
432 | }});
433 |
434 | ParameterMap params = new ParameterMap();
435 | params.add("app_id", "foo");
436 |
437 | serviceApi.oauth_authorize(params);
438 | }
439 |
440 | @Test(expected = IllegalArgumentException.class)
441 | public void test_report_raises_an_exception_if_no_transactions_given() throws ServerError {
442 | serviceApi.report(null);
443 | }
444 |
445 | @Test
446 | public void test_successful_report() throws ServerError {
447 |
448 | context.checking(new UrlWithParamsExpectations() {{
449 | oneOf(htmlServer).post(with("http://" + host + "/transactions.xml"), with(any(String.class)));
450 | will(returnValue(new HttpResponse(202, "")));
451 | }});
452 |
453 | ParameterMap params = new ParameterMap();
454 | params.add("app_id", "foo");
455 | params.add("timestamp", fmt.print(new DateTime(2010, 4, 27, 15, 0)));
456 |
457 | ParameterMap usage = new ParameterMap();
458 | usage.add("hits", "1");
459 | params.add("usage", usage);
460 |
461 | ReportResponse response = serviceApi.report(null, params);
462 |
463 | assertTrue(response.success());
464 | }
465 |
466 | @Test
467 | public void test_report_encodes_transactions() throws ServerError {
468 |
469 | final String urlParams =
470 | "transactions%5B0%5D%5Btimestamp%5D=2010-04-27%2015%3A42%3A17%200200" +
471 | "&transactions%5B0%5D%5Busage%5D%5Bmetric2%5D=2" +
472 | "&transactions%5B0%5D%5Busage%5D%5Bhits%5D=1" +
473 | "&transactions%5B0%5D%5Bapp_id%5D=foo" +
474 | "&transactions%5B1%5D%5Btimestamp%5D=2010-04-27%2015%3A55%3A12%200200" +
475 | "&transactions%5B1%5D%5Busage%5D%5Bhits%5D=1" +
476 | "&transactions%5B1%5D%5Bapp_id%5D=bar" +
477 | "&provider_key=1234abcd";
478 |
479 | context.checking(new UrlWithParamsExpectations() {{
480 | oneOf(htmlServer).post(with("http://" + host + "/transactions.xml"), withParams(urlParams));
481 | will(returnValue(new HttpResponse(200, "")));
482 | }});
483 |
484 |
485 | ParameterMap app1 = new ParameterMap();
486 | app1.add("app_id", "foo");
487 | app1.add("timestamp", "2010-04-27 15:42:17 0200");
488 |
489 | ParameterMap usage1 = new ParameterMap();
490 | usage1.add("hits", "1");
491 | usage1.add("metric2", "2");
492 | app1.add("usage", usage1);
493 |
494 | ParameterMap app2 = new ParameterMap();
495 | app2.add("app_id", "bar");
496 | app2.add("timestamp", "2010-04-27 15:55:12 0200");
497 |
498 | ParameterMap usage2 = new ParameterMap();
499 | usage2.add("hits", "1");
500 | app2.add("usage", usage2);
501 |
502 | serviceApi.report(null, app1, app2);
503 | }
504 |
505 | @Test
506 | public void test_failed_report() throws ServerError {
507 | final String error_body = "provider key \"foo\" is invalid ";
508 |
509 | context.checking(new UrlWithParamsExpectations() {{
510 | oneOf(htmlServer).post(with("http://" + host + "/transactions.xml"), with(any(String.class)));
511 | will(returnValue(new HttpResponse(403, error_body)));
512 | }});
513 |
514 | ParameterMap params = new ParameterMap();
515 | params.add("app_id", "abc");
516 | ParameterMap usage = new ParameterMap();
517 | usage.add("hits", "1");
518 | params.add("usage", usage);
519 |
520 | ReportResponse response = serviceApi.report(null, params);
521 |
522 | assertFalse(response.success());
523 | assertEquals("provider_key_invalid", response.getErrorCode());
524 | assertEquals("provider key \"foo\" is invalid", response.getErrorMessage());
525 | }
526 |
527 | @Test(expected = ServerError.class)
528 | public void test_report_with_server_error() throws ServerError {
529 |
530 | context.checking(new UrlWithParamsExpectations() {{
531 | oneOf(htmlServer).post(with("http://" + host + "/transactions.xml"), with(any(String.class)));
532 | will(returnValue(new HttpResponse(500, "OMG! WTF!")));
533 | }});
534 |
535 | ParameterMap params = new ParameterMap();
536 | params.add("app_id", "foo");
537 | ParameterMap usage = new ParameterMap();
538 | usage.add("hits", "1");
539 | params.add("usage", usage);
540 | serviceApi.report(null, params);
541 | }
542 |
543 |
544 | private void assertAuthrepUrlWithParams(final String params) throws ServerError {
545 | final String authrep_url = "http://" + host + "/transactions/authrep.xml?" + params + "&provider_key=" + provider_key;
546 |
547 | final String body = "" +
548 | "true " +
549 | "Ultimate " +
550 | " ";
551 | //System.out.println("Expect: "+ authrep_url);
552 | context.checking(new UrlWithParamsExpectations() {
553 | {
554 | oneOf(htmlServer).get(withUrl(authrep_url));
555 | will(returnValue(new HttpResponse(200, body)));
556 | }
557 | });
558 | }
559 |
560 | private static class UrlWithParamsExpectations extends Expectations {
561 |
562 | protected String withUrl(String url) {
563 | currentBuilder().addParameterMatcher(new UrlWithParamsMatcher(url));
564 | return url;
565 | }
566 |
567 | protected String withParams(String params) {
568 | currentBuilder().addParameterMatcher(new ParamsMatcher(params));
569 | return params;
570 | }
571 |
572 | }
573 |
574 | private static class UrlWithParamsMatcher extends TypeSafeMatcher {
575 |
576 | private final String expectedUrl;
577 |
578 | public UrlWithParamsMatcher(String expectedUrl) {
579 | this.expectedUrl = expectedUrl;
580 | }
581 |
582 | @Override
583 | public boolean matchesSafely(String actualUrl) {
584 | // Match the first part of the URL (scheme, host, port, etc)
585 | String expectedUrlHead = expectedUrl.substring(0, expectedUrl.indexOf("?"));
586 | String actualUrlHead = actualUrl.substring(0, actualUrl.indexOf("?"));
587 |
588 | // Match the params (order then compare)
589 | String expectedParams = expectedUrl.substring(expectedUrl.indexOf("?") + 1);
590 | String[] expectedParamsSplit = expectedParams.split("&");
591 | Arrays.sort(expectedParamsSplit);
592 | String actualParams = actualUrl.substring(actualUrl.indexOf("?") + 1);
593 | String[] actualParamsSplit = actualParams.split("&");
594 | Arrays.sort(actualParamsSplit);
595 |
596 | List expected = Arrays.asList(expectedParamsSplit);
597 | List actual = Arrays.asList(actualParamsSplit);
598 |
599 | return expected.equals(actual) && expectedUrlHead.equals(actualUrlHead);
600 | }
601 |
602 | @Override
603 | public void describeTo(Description description) {
604 | description.appendText("a url matching '" + this.expectedUrl + "'");
605 | }
606 | }
607 |
608 | private static class ParamsMatcher extends TypeSafeMatcher {
609 |
610 | private final String expectedParams;
611 |
612 | public ParamsMatcher(String expectedParams) {
613 | this.expectedParams = expectedParams;
614 | }
615 |
616 | @Override
617 | public boolean matchesSafely(String actualParams) {
618 | String[] expectedParamsSplit = expectedParams.split("&");
619 | Arrays.sort(expectedParamsSplit);
620 | String[] actualParamsSplit = actualParams.split("&");
621 | Arrays.sort(actualParamsSplit);
622 |
623 | List expected = Arrays.asList(expectedParamsSplit);
624 | List actual = Arrays.asList(actualParamsSplit);
625 |
626 | return expected.equals(actual);
627 | }
628 |
629 | @Override
630 | public void describeTo(Description description) {
631 | description.appendText("params matching '" + this.expectedParams + "'");
632 | }
633 | }
634 |
635 | }
636 |
--------------------------------------------------------------------------------