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

ar.com.fernandospr.wns.client.WnsClient Maven / Gradle / Ivy

package ar.com.fernandospr.wns.client;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

import org.apache.commons.httpclient.auth.AuthScope;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

import ar.com.fernandospr.wns.WnsProxyProperties;
import ar.com.fernandospr.wns.exceptions.WnsException;
import ar.com.fernandospr.wns.model.WnsAbstractNotification;
import ar.com.fernandospr.wns.model.WnsNotificationRequestOptional;
import ar.com.fernandospr.wns.model.WnsNotificationResponse;
import ar.com.fernandospr.wns.model.WnsOAuthToken;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.WebResource.Builder;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.apache.ApacheHttpClient;
import com.sun.jersey.client.apache.config.DefaultApacheHttpClientConfig;
import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.client.apache.config.ApacheHttpClientConfig;
import com.sun.jersey.core.util.MultivaluedMapImpl;


public class WnsClient {
	private static final String SCOPE = "notify.windows.com";
	private static final String GRANT_TYPE_CLIENT_CREDENTIALS = "client_credentials";
	private static final String AUTHENTICATION_URI = "https://login.live.com/accesstoken.srf";
	
	private String sid;
	private String clientSecret;
	private WnsOAuthToken token;
	private Client client;
	
	
	public WnsClient(String sid, String clientSecret, boolean logging) {
		this.sid = sid;
		this.clientSecret = clientSecret;
		this.client = createClient(logging);
	}
	
	public WnsClient(String sid, String clientSecret, WnsProxyProperties proxyProps, boolean logging) {
		this.sid = sid;
		this.clientSecret = clientSecret;
		this.client = createClient(logging, proxyProps);
	}
	
	private static Client createClient(boolean logging) {
		ClientConfig clientConfig = new DefaultClientConfig();
		clientConfig.getClasses().add(JacksonJsonProvider.class);
		Client client = Client.create(clientConfig);
		if (logging == true) {
			client.addFilter(new LoggingFilter(System.out));
		}
		return client;
	}
	
	private static Client createClient(boolean logging, WnsProxyProperties proxyProps) {
		DefaultApacheHttpClientConfig clientConfig = new DefaultApacheHttpClientConfig();
		setProxyCredentials(clientConfig, proxyProps);
		clientConfig.getClasses().add(JacksonJsonProvider.class);
		Client client = ApacheHttpClient.create(clientConfig);
		if (logging == true) {
			client.addFilter(new LoggingFilter(System.out));
		}
		return client;
	}
	
	private static void setProxyCredentials(DefaultApacheHttpClientConfig clientConfig, WnsProxyProperties proxyProps) {
		if(proxyProps != null) {
			String  proxyProtocol   = proxyProps.getProtocol();
			String  proxyHost  	= proxyProps.getHost();
			int     proxyPort  	= proxyProps.getPort();
			String  proxyUser	= proxyProps.getUser();
			String  proxyPass  	= proxyProps.getPass();
			
			if ((proxyHost != null) && (!proxyHost.trim().isEmpty())) {
				
				clientConfig.getProperties().put(ApacheHttpClientConfig.PROPERTY_PROXY_URI, proxyProtocol + "://" + proxyHost + ":" + proxyPort);
				
				if (!proxyUser.trim().isEmpty()) {
					clientConfig.getProperties().put(ApacheHttpClientConfig.PROPERTY_PREEMPTIVE_AUTHENTICATION, true);
					clientConfig.getProperties().put(ApacheHttpClientConfig.PROPERTY_INTERACTIVE, true);
					clientConfig.getState().setCredentials(AuthScope.ANY_REALM, AuthScope.ANY_HOST, AuthScope.ANY_PORT, proxyUser, proxyPass);
					clientConfig.getState().setProxyCredentials(AuthScope.ANY_REALM, proxyHost, proxyPort, proxyUser, proxyPass);
				}
			}
			
		}
		
	}
	
	/**
	 * Based on http://msdn.microsoft.com/en-us/library/windows/apps/hh465407.aspx
	 * @throws WnsException when authentication fails
	 */
	public void refreshAccessToken() throws WnsException {
		WebResource webResource = this.client.resource(AUTHENTICATION_URI);
		MultivaluedMap formData = new MultivaluedMapImpl();
		formData.add("grant_type", GRANT_TYPE_CLIENT_CREDENTIALS);
		formData.add("client_id", this.sid);
		formData.add("client_secret", this.clientSecret);
		formData.add("scope", SCOPE);
		ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
											 .accept(MediaType.APPLICATION_JSON_TYPE)
											 .post(ClientResponse.class, formData);
		if (response.getStatus() != 200) {
			throw new WnsException("Authentication failed. HTTP error code: " + response.getStatus());
		}
		
		this.token = response.getEntity(WnsOAuthToken.class);
	}
	
	/**
	 * @param channelUri
	 * @param resourceBuilder
	 * @param notification
	 * @param retriesLeft to push the notification if the token expires
	 * @return WnsNotificationResponse please see response headers from http://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx#send_notification_response
	 * @throws WnsException when authentication fails
	 */
	public WnsNotificationResponse push(WnsResourceBuilder resourceBuilder, String channelUri, WnsAbstractNotification notification, int retriesLeft, WnsNotificationRequestOptional optional) throws WnsException {
		WebResource webResource = this.client.resource(channelUri);
		
		Builder webResourceBuilder = resourceBuilder.build(webResource, notification, getToken().access_token, optional);
		
		ClientResponse response = webResourceBuilder.post(ClientResponse.class);
		
		WnsNotificationResponse notificationResponse = new WnsNotificationResponse(channelUri, response.getStatus(), response.getHeaders());
		if (notificationResponse.code == 200) {
			return notificationResponse;
		}
		
		if (notificationResponse.code == 401 && retriesLeft > 0) {
			retriesLeft--;
			// Access token may have expired
			refreshAccessToken();
			// Retry
			return this.push(resourceBuilder, channelUri, notification, retriesLeft, optional);
		}
		
		// Assuming push failed
		return notificationResponse;
	}
	
	private WnsOAuthToken getToken() throws WnsException {
		if (this.token == null) {
			refreshAccessToken();
		}
		return this.token;
	}

	/**
	 * @param channelUris
	 * @param resourceBuilder
	 * @param notification
	 * @param retriesLeft to push the notification if the token expires
	 * @return list of WnsNotificationResponse for each channelUri, please see response headers from http://msdn.microsoft.com/en-us/library/windows/apps/hh465435.aspx#send_notification_response
	 * @throws WnsException when authentication fails
	 */
	public List push(WnsResourceBuilder resourceBuilder, List channelUris, WnsAbstractNotification notification, int retriesLeft, WnsNotificationRequestOptional optional) throws WnsException {
		List responses = new ArrayList();
		for (String channelUri : channelUris) {
			WnsNotificationResponse response = push(resourceBuilder, channelUri, notification, retriesLeft, optional);
			responses.add(response);
		}
		return responses;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy