Initial Contribution
Signed-off-by: Jan Supol <jan.supol@oracle.com>
diff --git a/examples/oauth-client-twitter/README.MD b/examples/oauth-client-twitter/README.MD
new file mode 100644
index 0000000..ead17fc
--- /dev/null
+++ b/examples/oauth-client-twitter/README.MD
@@ -0,0 +1,80 @@
+[//]: # " Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved. "
+[//]: # " "
+[//]: # " This program and the accompanying materials are made available under the "
+[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at "
+[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. "
+[//]: # " "
+[//]: # " SPDX-License-Identifier: BSD-3-Clause "
+
+OAuth 1 Client Sample - Twitter Client
+======================================
+
+This example demonstrates how to develop a simple web app client
+utilizing JAX-RS client API and Jersey OAuth support.
+
+Contents
+--------
+
+This example consists of the main class (`App`) and two JAXB beans used
+for unmarshaling the responses from Twitter (`Status` and `User`).
+
+Running the Example
+-------------------
+
+### Registering with Twitter
+
+Before running the example, you have to register your own application
+with Twitter (to obtain consumer key and consumer secret you have to use
+to configure this client). You can do it as follows:
+
+1. Go to [Twitter Developers Page](http://dev.twitter.com/). You need
+ to sign in to the Twitter (if you are new to Twitter you need to
+ sign up). Then in the right upper corner you will see your profile
+ photo and drop down list in which you select "My Application". Click
+ on **Create a new application** button.
+
+2. Fill out the "Create an application" form - you have to pick a
+ unique application name (e.g. app12345678), put in some description,
+ put in something for app website (e.g. http://jersey.java.net),
+ Accept terms by selecting **Yes, I agree** in "Twitter Content"
+ checkbox, enter captcha.
+
+3. Click **Create your twitter application** button.
+
+4. You will be presented with consumer key, consumer secret and other
+ details for your registered application.
+
+### Running for the First Time
+
+Enter the following on the command-line:
+
+> mvn clean compile exec:java -DconsumerKey=<consumer key assigned to your app> -DconsumerSecret=<consumer secret assigned to your app>
+
+### Subsequent Runs
+
+After you run the application for the first time, it stores the consumer
+key, secret and token and token secret in a property file for future
+use. So, for subsequent runs you don't have to specify these as system
+properties. The following command is good enough for running the
+application after it was built, run for the first time and the property
+file was created:
+
+> mvn exec:java
+
+Troubleshooting
+---------------
+
+### HTTP Proxy
+
+Behind a HTTP proxy, you will need to setup the following system
+properties to communicate with the Twitter server:
+
+- http.proxyHost - the name of the proxy host.
+- http.proxyPort - the port of the proxy host.
+- http.proxyAuth - the user name and password to use when connecting
+ to the proxy; this string should be the user name and password
+ separated by a colon (e.g., rickhall:mypassword).
+
+These system properties can be set directly on the command line when
+starting the JVM using the standard "-D<prop>=<value>"
+syntax.
diff --git a/examples/oauth-client-twitter/pom.xml b/examples/oauth-client-twitter/pom.xml
new file mode 100644
index 0000000..8cc99cc
--- /dev/null
+++ b/examples/oauth-client-twitter/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Distribution License v. 1.0, which is available at
+ http://www.eclipse.org/org/documents/edl-v10.php.
+
+ SPDX-License-Identifier: BSD-3-Clause
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>project</artifactId>
+ <groupId>org.glassfish.jersey.examples</groupId>
+ <version>2.28-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>oauth-client-twitter</artifactId>
+ <packaging>jar</packaging>
+
+
+ <description>
+ Twitter client using OAuth 1 support for Jersey that retrieves Tweets from the home timeline of a
+ registered Twitter account.
+ </description>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.inject</groupId>
+ <artifactId>jersey-hk2</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-json-jackson</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.glassfish.jersey.examples.oauth.twitterclient.App</mainClass>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
new file mode 100644
index 0000000..f015aa5
--- /dev/null
+++ b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/App.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.oauth.twitterclient;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Properties;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Response;
+
+import org.glassfish.jersey.client.oauth1.AccessToken;
+import org.glassfish.jersey.client.oauth1.ConsumerCredentials;
+import org.glassfish.jersey.client.oauth1.OAuth1AuthorizationFlow;
+import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport;
+import org.glassfish.jersey.jackson.JacksonFeature;
+
+/** Simple command-line application that uses Jersey OAuth client library to authenticate
+ * with Twitter.
+ *
+ * @author Martin Matula
+ * @author Miroslav Fuksa
+ */
+public class App {
+ private static final BufferedReader IN = new BufferedReader(new InputStreamReader(System.in, Charset.forName("UTF-8")));
+ private static final String FRIENDS_TIMELINE_URI = "https://api.twitter.com/1.1/statuses/home_timeline.json";
+ private static final Properties PROPERTIES = new Properties();
+ private static final String PROPERTIES_FILE_NAME = "twitterclient.properties";
+ private static final String PROPERTY_CONSUMER_KEY = "consumerKey";
+ private static final String PROPERTY_CONSUMER_SECRET = "consumerSecret";
+ private static final String PROPERTY_TOKEN = "token";
+ private static final String PROPERTY_TOKEN_SECRET = "tokenSecret";
+
+ /**
+ * Main method that creates a {@link Client client} and initializes the OAuth support with
+ * configuration needed to connect to the Twitter and retrieve statuses.
+ * <p/>
+ * Execute this method to demo
+ *
+ * @param args Command line arguments.
+ * @throws Exception Thrown when error occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ // retrieve consumer key/secret and token/secret from the property file
+ // or system properties
+ loadSettings();
+
+ final ConsumerCredentials consumerCredentials = new ConsumerCredentials(
+ PROPERTIES.getProperty(PROPERTY_CONSUMER_KEY),
+ PROPERTIES.getProperty(PROPERTY_CONSUMER_SECRET));
+
+ final Feature filterFeature;
+ if (PROPERTIES.getProperty(PROPERTY_TOKEN) == null) {
+
+ // we do not have Access Token yet. Let's perfom the Authorization Flow first,
+ // let the user approve our app and get Access Token.
+ final OAuth1AuthorizationFlow authFlow = OAuth1ClientSupport.builder(consumerCredentials)
+ .authorizationFlow(
+ "https://api.twitter.com/oauth/request_token",
+ "https://api.twitter.com/oauth/access_token",
+ "https://api.twitter.com/oauth/authorize")
+ .build();
+ final String authorizationUri = authFlow.start();
+
+ System.out.println("Enter the following URI into a web browser and authorize me:");
+ System.out.println(authorizationUri);
+ System.out.print("Enter the authorization code: ");
+ final String verifier;
+ try {
+ verifier = IN.readLine();
+ } catch (final IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ final AccessToken accessToken = authFlow.finish(verifier);
+
+ // store access token for next application execution
+ PROPERTIES.setProperty(PROPERTY_TOKEN, accessToken.getToken());
+ PROPERTIES.setProperty(PROPERTY_TOKEN_SECRET, accessToken.getAccessTokenSecret());
+
+ // get the feature that will configure the client with consumer credentials and
+ // received access token
+ filterFeature = authFlow.getOAuth1Feature();
+ } else {
+ final AccessToken storedToken = new AccessToken(PROPERTIES.getProperty(PROPERTY_TOKEN),
+ PROPERTIES.getProperty(PROPERTY_TOKEN_SECRET));
+ // build a new feature from the stored consumer credentials and access token
+ filterFeature = OAuth1ClientSupport.builder(consumerCredentials).feature()
+ .accessToken(storedToken).build();
+ }
+
+
+ // create a new Jersey client and register filter feature that will add OAuth signatures and
+ // JacksonFeature that will process returned JSON data.
+ final Client client = ClientBuilder.newBuilder()
+ .register(filterFeature)
+ .register(JacksonFeature.class)
+ .build();
+
+ // make requests to protected resources
+ // (no need to care about the OAuth signatures)
+ final Response response = client.target(FRIENDS_TIMELINE_URI).request().get();
+ if (response.getStatus() != 200) {
+ String errorEntity = null;
+ if (response.hasEntity()) {
+ errorEntity = response.readEntity(String.class);
+ }
+ throw new RuntimeException("Request to Twitter was not successful. Response code: "
+ + response.getStatus() + ", reason: " + response.getStatusInfo().getReasonPhrase()
+ + ", entity: " + errorEntity);
+ }
+
+ // persist the current consumer key/secret and token/secret for future use
+ storeSettings();
+
+ final List<Status> statuses = response.readEntity(new GenericType<List<Status>>() {
+ });
+
+ System.out.println("Tweets:\n");
+ for (final Status s : statuses) {
+ System.out.println(s.getText());
+ System.out.println("[posted by " + s.getUser().getName() + " at " + s.getCreatedAt() + "]");
+ }
+
+
+ }
+
+ private static void loadSettings() {
+ FileInputStream st = null;
+ try {
+ st = new FileInputStream(PROPERTIES_FILE_NAME);
+ PROPERTIES.load(st);
+ } catch (final IOException e) {
+ // ignore
+ } finally {
+ if (st != null) {
+ try {
+ st.close();
+ } catch (final IOException ex) {
+ // ignore
+ }
+ }
+ }
+
+ for (final String name : new String[]{PROPERTY_CONSUMER_KEY, PROPERTY_CONSUMER_SECRET,
+ PROPERTY_TOKEN, PROPERTY_TOKEN_SECRET}) {
+ final String value = System.getProperty(name);
+ if (value != null) {
+ PROPERTIES.setProperty(name, value);
+ }
+ }
+
+ if (PROPERTIES.getProperty(PROPERTY_CONSUMER_KEY) == null
+ || PROPERTIES.getProperty(PROPERTY_CONSUMER_SECRET) == null) {
+ System.out.println("No consumerKey and/or consumerSecret found in twitterclient.properties file. "
+ + "You have to provide these as system properties. See README.html for more information.");
+ System.exit(1);
+ }
+ }
+
+ private static void storeSettings() {
+ FileOutputStream st = null;
+ try {
+ st = new FileOutputStream(PROPERTIES_FILE_NAME);
+ PROPERTIES.store(st, null);
+ } catch (final IOException e) {
+ // ignore
+ } finally {
+ try {
+ if (st != null) {
+ st.close();
+ }
+ } catch (final IOException ex) {
+ // ignore
+ }
+ }
+ }
+
+}
diff --git a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/Status.java b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/Status.java
new file mode 100644
index 0000000..34f2abe
--- /dev/null
+++ b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/Status.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.oauth.twitterclient;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * Entity into which the Twitter status (tweet) is deserialized
+ *
+ * @author Martin Matula
+ */
+@XmlRootElement
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class Status {
+
+ @XmlElement(name = "created_at")
+ private String createdAt;
+ @XmlElement(name = "text")
+ private String text;
+ @XmlElement(name = "user")
+ private User user;
+
+ public String getCreatedAt() {
+ return createdAt;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public User getUser() {
+ return user;
+ }
+}
diff --git a/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/User.java b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/User.java
new file mode 100644
index 0000000..9be2571
--- /dev/null
+++ b/examples/oauth-client-twitter/src/main/java/org/glassfish/jersey/examples/oauth/twitterclient/User.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0, which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.glassfish.jersey.examples.oauth.twitterclient;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+
+/**
+ * Entity into which the Twitter user is deserialized.
+ *
+ * @author Martin Matula
+ */
+@XmlRootElement
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class User {
+ @XmlElement(name = "name")
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+}