All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.stormpath.sdk.client.ClientApplicationBuilder Maven / Gradle / Ivy

/*
 * Copyright 2013 Stormpath, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.stormpath.sdk.client;

import com.stormpath.sdk.application.Application;

import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Properties;

/**
 * 

Deprecated

* This class has been deprecated as of 0.8 and it will be removed before 1.0 final. Instead of using this class, * use the {@link ClientBuilder ClientBuilder} and after built, call *
 *     client.getResource(appUrl, Application.class);
 * 
* to acquire an application instance resource. *

*

* A Builder design pattern implementation similar to * the {@link ClientBuilder}, but focused on single-application interaction with Stormpath. *

Description

* The {@code ClientBuilder} produces a {@link Client} instance useful for interacting with any aspect * of an entire Stormpath Tenant's data space. However, a software application may only be interested in its own * functionality and not the entire Stormpath Tenant data space. *

* The {@code ClientApplicationBuilder} provides a means to more easily acquire a single * {@link Application} instance. From this {@code Application} instance, everything a particular Application needs to * perform can be based off of this instance and the wider-scoped concerns of an entire Tenant can be ignored. *

Default Usage

*
 * //this can be a classpath: or url: location as well:
 * String apiKeyFileLocation = "/home/jsmith/.stormpath/apiKey.properties";
 *
 * String appHref = "https://api.stormpath.com/v1/applications/YOUR_APP_UID_HERE";
 *
 * Application application = new ClientApplicationBuilder()
 *     .setApplicationHref(appHref)
 *     .build().getApplication();
 * 
*

* After acquiring the {@code application} instance, you can interact with it to login accounts, reset passwords, * etc. *

Service Provider Usage with only an Application URL

* Some hosting service providers (e.g. like Heroku) do not allow easy access to * a a configuration file and therefore it might be difficult to reference an API Key File. If you cannot reference an * API Key File via the {@code file:}, {@code classpath:} or {@code url:} * {@link #setApiKeyFileLocation(String) resource locations}, the Application HREF URL must * contain the API Key embedded as the user info portion * of the URL. For example: *

*

 * https://apiKeyId:apiKeySecret@api.stormpath.com/v1/applications/YOUR_APP_UID_HERE
 * 
*

* Notice this is just a normal Application HREF url with the apiKeyId:apiKeySecret@ part added in. *

* Example usage: *

 * String appHref = "https://apiKeyId:apiKeySecret@api.stormpath.com/v1/applications/YOUR_APP_UID_HERE";
 *
 * Application application = new ClientApplicationBuilder()
 *     .setApplicationHref(appHref)
 *     .build().getApplication();
 * 
*

* WARNING: ONLY use the embedded API Key technique if you do not have access to {@code file:}, {@code classpath:} * or {@code url:} {@link #setApiKeyFileLocation(String) resource locations}. File based API Key * storage is a more secure technique than embedding the key in the URL itself. Also, again, NEVER share your API Key * Secret with anyone (not even co-workers). Stormpath staff will never ask for your API Key Secret. * * @see #setApiKeyFileLocation(String) * @see #setApplicationHref(String) * @since 0.5 * @deprecated in 0.8 and will be removed before 1.0 final. Use the Client.Builder and then call client.getResource(appUrl, Application.class); */ @Deprecated public class ClientApplicationBuilder { private static final String DOUBLE_SLASH = "//"; private static final String ENCODING = "UTF-8"; private String applicationHref; private final ClientBuilder clientBuilder; //internal delegate object private final ApiKeyBuilder apiKeyBuilder; //internal delegate object public ClientApplicationBuilder() { this.clientBuilder = Clients.builder(); this.apiKeyBuilder = ApiKeys.builder(); } protected ClientApplicationBuilder(ClientBuilder clientBuilder, ApiKeyBuilder apiKeyBuilder) { this.clientBuilder = clientBuilder; this.apiKeyBuilder = apiKeyBuilder; } /** * Allows usage of a Properties instance instead of loading a {@code .properties} file via * {@link #setApiKeyFileLocation(String) apiKeyFileLocation} configuration. *

* The {@code Properties} contents and property name overrides function the same as described in the * {@link #setApiKeyFileLocation(String) setApiKeyFileLocation} JavaDoc. * * @param properties the properties instance to use to load the API Key ID and Secret. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApiKeyProperties(Properties properties) { this.apiKeyBuilder.setProperties(properties); return this; } /** * Creates an API Key Properties instance based on the specified Reader instead of loading a {@code .properties} * file via {@link #setApiKeyFileLocation(String) apiKeyFileLocation} configuration. *

* The constructed {@code Properties} contents and property name overrides function the same as described in the * {@link #setApiKeyFileLocation(String) setApiKeyFileLocation} JavaDoc. * @param reader the reader to use to construct a Properties instance. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApiKeyReader(Reader reader) { this.apiKeyBuilder.setReader(reader); return this; } /** * Creates an API Key Properties instance based on the specified InputStream * instead of loading a {@code .properties} file via * {@link #setApiKeyFileLocation(String) apiKeyFileLocation} configuration. *

* The constructed {@code Properties} contents and property name overrides function the same as described in the * {@link #setApiKeyFileLocation(String) setApiKeyFileLocation} JavaDoc. * @param is the InputStream to use to construct a Properties instance. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApiKeyInputStream(InputStream is) { this.apiKeyBuilder.setInputStream(is); return this; } /** * Sets the location of the {@code .properties} file to load containing the API Key (Id and secret) used by the * Client to communicate with the Stormpath REST API. *

* You may load files from the filesystem, classpath, or URLs by prefixing the location path with * {@code file:}, {@code classpath:}, or {@code url:} respectively. If no prefix is found, {@code file:} * is assumed by default. *

File Contents

*

* When the file is loaded, the following name/value pairs are expected to be present by default: *

* * * * * * * * * * * * *
KeyValue
apiKey.idAn individual account's API Key ID
apiKey.secretThe API Key Secret (password) that verifies the paired API Key ID.
*

* Assuming you were using these default property names, your {@code ClientApplicationBuilder} usage might look * like the following: *

     * String location = "/home/jsmith/.stormpath/apiKey.properties";
     *
     * Application app = new ClientApplicationBuilder().setApiKeyFileLocation(location).build().getApplication();
     * 
*

Custom Property Names

* If you want to control the property names used in the file, you may configure them via * {@link #setApiKeyIdPropertyName(String) setApiKeyIdPropertyName} and * {@link #setApiKeySecretPropertyName(String) setApiKeySecretPropertyName}. *

* For example, if you had a {@code /home/jsmith/.stormpath/apiKey.properties} file with the following * name/value pairs: *

     * myStormpathApiKeyId = foo
     * myStormpathApiKeySecret = mySuperSecretValue
     * 
* Your {@code ClientApplicationBuilder} usage would look like the following: *
     * String location = "/home/jsmith/.stormpath/apiKey.properties";
     *
     * Application app = new ClientApplicationBuilder()
     *     .setApiKeyFileLocation(location)
     *     .setApiKeyIdPropertyName("myStormpathApiKeyId")
     *     .setApiKeySecretPropertyName("myStormpathApiKeySecret")
     *     .build().getApplication();
     * 
* * @param location the file, classpath or url location of the API Key {@code .properties} file to load when * constructing the API Key to use for communicating with the Stormpath REST API. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApiKeyFileLocation(String location) { this.apiKeyBuilder.setFileLocation(location); return this; } /** * Sets the name used to query for the API Key ID from a Properties instance. That is: *
     * String apiKeyId = properties.getProperty(apiKeyIdPropertyName);
     * 
* * @param apiKeyIdPropertyName the name used to query for the API Key ID from a Properties instance. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApiKeyIdPropertyName(String apiKeyIdPropertyName) { this.apiKeyBuilder.setIdPropertyName(apiKeyIdPropertyName); return this; } /** * Sets the name used to query for the API Key Secret from a Properties instance. That is: *
     * String apiKeySecret = properties.getProperty(apiKeySecretPropertyName);
     * 
* * @param apiKeySecretPropertyName the name used to query for the API Key Secret from a Properties instance. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApiKeySecretPropertyName(String apiKeySecretPropertyName) { this.apiKeyBuilder.setSecretPropertyName(apiKeySecretPropertyName); return this; } /** * Sets the fully qualified Stormpath Application HREF (a URL) to use to acquire the Application instance when * {@link #build()} is called. See the Class-level JavaDoc for usage scenarios. * * @param applicationHref the fully qualified Stormpath Application HREF (a URL) to use to acquire the * Application instance when {@link #build()} is called. * @return this ClientApplicationBuilder instance for method chaining. */ public ClientApplicationBuilder setApplicationHref(String applicationHref) { this.applicationHref = applicationHref; return this; } /** * Builds a Client and Application wrapper instance based on the configured * {@link #setApplicationHref(String) applicationHref}. See the Class-level JavaDoc for usage scenarios. * * @return a Client and Application wrapper instance based on the configured {@link #setApplicationHref(String) applicationHref}. */ public ClientApplication build() { String href = this.applicationHref != null ? this.applicationHref.trim() : null; if (href == null || href.equals("")) { String msg = "'applicationHref' property must be specified when using this builder implementation."; throw new IllegalArgumentException(msg); } String cleanedHref = href; int atSignIndex = href.indexOf('@'); if (atSignIndex > 0) { String[] parts = getHrefWithUserInfo(href, atSignIndex); //parts[0] = up to and including the double slash //parts[1] = the raw user info //parts[2] = after the at sign cleanedHref = parts[0] + parts[2]; parts = parts[1].split(":", 2); Properties apiKeyProperties = createApiKeyProperties(parts); setApiKeyProperties(apiKeyProperties); } //otherwise an apiKey File/Reader/InputStream/etc for the API Key is required Client client = buildClient(); Application application = client.getDataStore().getResource(cleanedHref, Application.class); return new ClientApplication(client, application); } protected Client buildClient() { this.clientBuilder.setApiKey(this.apiKeyBuilder.build()); return this.clientBuilder.build(); } protected String[] getHrefWithUserInfo(String href, int atSignIndex) { int doubleSlashIndex = href.indexOf(DOUBLE_SLASH); if (doubleSlashIndex <= 0) { throw new IllegalArgumentException("Invalid application href URL"); } String[] parts = new String[3]; parts[0] = href.substring(0, doubleSlashIndex + DOUBLE_SLASH.length()); //up to and including the double slash parts[1] = href.substring(doubleSlashIndex + DOUBLE_SLASH.length(), atSignIndex); //raw user info parts[2] = href.substring(atSignIndex + 1); //after the @ character return parts; } protected Properties createApiKeyProperties(String[] pair) { if (pair == null || pair.length != 2) { String msg = "applicationHref userInfo segment must consist of the following format: " + "apiKeyId:apiKeySecret"; throw new IllegalArgumentException(msg); } Properties props = new Properties(); props.put("apiKey.id", urlDecode(pair[0])); props.put("apiKey.secret", urlDecode(pair[1])); return props; } protected String urlDecode(String s) { try { return urlDecode(s, ENCODING); } catch (UnsupportedEncodingException e) { throw new IllegalArgumentException("Unable to URL decode userInfo fragment: " + s, e); } } protected String urlDecode(String s, String encoding) throws UnsupportedEncodingException { return URLDecoder.decode(s, encoding); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy