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&lt;prop&gt;=&lt;value&gt;"
+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;
+    }
+}