/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * 
 * $Id: JAXRSClient.java 70649 2013-03-13 17:15:00Z supol $ 
 */
package com.sun.ts.tests.jaxrs.api.client.clientrequestcontext;

import java.io.ByteArrayInputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.Variant;
import javax.ws.rs.ext.RuntimeDelegate;

import com.sun.ts.lib.util.TestUtil;
import com.sun.ts.tests.jaxrs.common.JAXRSCommonClient;
import com.sun.ts.tests.jaxrs.common.provider.StringBean;
import com.sun.ts.tests.jaxrs.common.provider.StringBeanEntityProvider;
import com.sun.ts.tests.jaxrs.common.provider.StringBeanRuntimeDelegate;
import com.sun.ts.tests.jaxrs.common.provider.StringBeanWithAnnotation;
import com.sun.ts.tests.jaxrs.common.util.JaxrsUtil;

/*
 * @class.setup_props: webServerHost;
 *                     webServerPort;
 *                     ts_home;
 */
public class JAXRSClient extends JAXRSCommonClient {

	private static final long serialVersionUID = 8883841555516513076L;

	/**
	 * Entry point for different-VM execution. It should delegate to method
	 * run(String[], PrintWriter, PrintWriter), and this method should not
	 * contain any test configuration.
	 */
	public static void main(String[] args) {
		new JAXRSClient().run(args);
	}

	/* Run test */

	/*
	 * @testName: abortWithTest
	 * @assertion_ids: JAXRS:JAVADOC:427;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; 
	 * @test_Strategy: Abort the filter chain with a response. This method 
	 * 					breaks the filter chain processing and returns the 
	 * 					provided response back to the client. The provided 
	 * 					response goes through the chain of applicable 
	 * 					response filters. 
	 * 		
	 * 					ClientRequestFilter.filter
	 * 					ClientRequestFilter.abortWith
	 */
	public void abortWithTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Response r = Response.status(Status.CREATED).build();
				context.abortWith(r);
			}
		};
		Invocation i = buildInvocation(provider);
		Response r = invoke(i);
		assertStatus(r, Status.CREATED);
	}

	/*
	 * @testName: getAcceptableLanguagesTest
	 * @assertion_ids: JAXRS:JAVADOC:428;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a list of languages that are acceptable for the 
	 * 					response. Returns: a read-only list of acceptable 
	 * 					languages sorted according to their q-value, 
	 * 					with highest preference first.
	 * 
	 * 					ClientRequestFilter.filter
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getAcceptableLanguagesTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				List<Locale> locales = context.getAcceptableLanguages();
				String languages = JaxrsUtil.iterableToString(";", locales);
				Response r = Response.ok(languages).build();
				context.abortWith(r);
			}
		};
		Invocation.Builder builder = buildBuilder(provider);
		Invocation invocation;
		invocation = builder.acceptLanguage(Locale.CANADA_FRENCH)
				.acceptLanguage(Locale.PRC).buildGet();
		Response response = invoke(invocation);
		String entity = response.readEntity(String.class);
		assertContains(entity, Locale.CANADA_FRENCH.toString());
		assertContains(entity, Locale.PRC.toString());
	}

	/*
	 * @testName: getAcceptableLanguagesByWeightsTest
	 * @assertion_ids: JAXRS:JAVADOC:428; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: a read-only list of requested response media types 
	 * 					sorted according to their q-value, with highest 
	 * 					preference first.
	 * 
	 * 					ClientRequestFilter.filter
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getAcceptableLanguagesByWeightsTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				List<Locale> locales = context.getAcceptableLanguages();
				String languages = JaxrsUtil.iterableToString(";", locales);
				Response r = Response.ok(languages).build();
				context.abortWith(r);
			}
		};
		Invocation.Builder builder = buildBuilder(provider);
		Invocation invocation;
		invocation = builder.acceptLanguage("da, en-gb;q=0.6, en-us;q=0.7")
				.buildGet();
		Response response = invoke(invocation);
		String entity = response.readEntity(String.class).toLowerCase();
		assertContains(entity, "da");
		assertContains(entity, "gb");
		assertContains(entity, "us");
		int indexDa = entity.indexOf("da");
		int indexUs = entity.indexOf("us");
		int indexGb = entity.indexOf("gb");

		assertFault(indexDa < indexUs && indexUs < indexGb,
				"List of acceptable languages", entity,
				"is not sorted by q values");
	}

	/*
	 * @testName: getAcceptableLanguagesIsImmutableTest
	 * @assertion_ids: JAXRS:JAVADOC:428;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: a read-only list of requested response media types 
	 * 					sorted according to their q-value, with highest 
	 * 					preference first.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getAcceptableLanguagesIsImmutableTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				List<Locale> locales = context.getAcceptableLanguages();
				try {
					locales.add(Locale.JAPAN);
				} catch (Exception e) {
					// either exception is thrown, or add does nothing
				}
				locales = context.getAcceptableLanguages();
				boolean b = locales.contains(Locale.JAPAN);
				assertFault(!b, "getAcceptableLanguages is not read-only");
				Response r = Response.ok().build();
				context.abortWith(r);
			}
		};
		WebTarget target = buildTarget(provider);
		Invocation.Builder builder = target.request();
		Invocation invocation;
		invocation = builder.header("Accept-Language",
				"da, en-gb;q=0.6, en-us;q=0.7").buildGet();
		Response response = invoke(invocation);
		assertStatus(response, Status.OK);
	}

	/*
	 * @testName: getAcceptableMediaTypesTest
	 * @assertion_ids: JAXRS:JAVADOC:429; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a list of media types that are acceptable for the 
	 * 					response. Returns a read-only list of requested response 
	 * 					media types sorted according to their q-value, 
	 * 					with highest preference first.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getAcceptableMediaTypesTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				List<MediaType> types = context.getAcceptableMediaTypes();
				String medias = JaxrsUtil.iterableToString(";", types);
				Response r = Response.ok(medias).build();
				context.abortWith(r);
			}
		};
		String media = "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5";
		Invocation.Builder builder = buildBuilder(provider);
		Invocation invocation = builder.header("Accept", media).buildGet();
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "text/*");
		assertContains(entity, "text/html");
		assertContains(entity, "*/*");
	}

	/*
	 * @testName: getAcceptableMediaTypesIsSortedTest
	 * @assertion_ids: JAXRS:JAVADOC:429; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a list of media types that are acceptable for the 
	 * 					response. Returns a read-only list of requested response 
	 * 					media types sorted according to their q-value, 
	 * 					with highest preference first.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getAcceptableMediaTypesIsSortedTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				List<MediaType> types = context.getAcceptableMediaTypes();
				String medias = JaxrsUtil.iterableToString(";", types);
				Response r = Response.ok(medias).build();
				context.abortWith(r);
			}
		};
		String media = "text/plain;q=0.3, text/html;q=0.7, text/xml;level=1, text/java;level=2;q=0.4, */*;q=0.5";
		Invocation.Builder builder = buildBuilder(provider);
		Invocation invocation = builder.header("Accept", media).buildGet();
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class).toLowerCase();
		int indexXml = entity.indexOf(MediaType.TEXT_XML);
		int indexHtml = entity.indexOf(MediaType.TEXT_HTML);
		int indexAny = entity.indexOf(MediaType.WILDCARD);
		int indexJava = entity.indexOf("text/java");
		int indexPlain = entity.indexOf(MediaType.TEXT_PLAIN);

		assertFault(indexXml < indexHtml && indexHtml < indexAny
				&& indexAny < indexJava && indexJava < indexPlain,
				"Media Types", entity, "are not sorted");
	}

	/*
	 * @testName: getAcceptableMediaTypesIsImmutableTest
	 * @assertion_ids: JAXRS:JAVADOC:429;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a list of media types that are acceptable for the 
	 * 					response. Returns a read-only list of requested response 
	 * 					media types sorted according to their q-value, 
	 * 					with highest preference first.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getAcceptableMediaTypesIsImmutableTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				List<MediaType> types = context.getAcceptableMediaTypes();
				try {
					types.add(MediaType.APPLICATION_JSON_TYPE);
				} catch (Exception e) {
					// either exception is thrown or add does nothing
				}
				types = context.getAcceptableMediaTypes();
				boolean b = types.contains(MediaType.APPLICATION_JSON_TYPE);
				assertFault(!b, "getAcceptableMediaTypes is not read only");
				Response r = Response.ok().build();
				context.abortWith(r);
			}
		};
		String media = "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5";
		Invocation.Builder builder = buildBuilder(provider);
		Invocation invocation = builder.header("Accept", media).buildGet();
		Response response = invoke(invocation);
		assertStatus(response, Status.OK);
	}

	/*
	 * @testName: getClientTest
	 * @assertion_ids: JAXRS:JAVADOC:430; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the client instance associated with the request.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getClientTest() throws Fault {
		final Client client = ClientBuilder.newClient();

		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Client contextClient = context.getClient();
				assertFault(client == contextClient,
						"the client instance is different from the context one");
				Response r = Response.ok().build();
				context.abortWith(r);
			}
		};
		client.register(provider);
		WebTarget target = client.target(getUrl());
		Invocation invocation = target.request().buildGet();
		Response response = invoke(invocation);
		assertStatus(response, Status.OK);
	}

	/*
	 * @testName: getConfigurationTest
	 * @assertion_ids: JAXRS:JAVADOC:977; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the immutable configuration of the request.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getConfigurationTest() throws Fault {
		final Client client = ClientBuilder.newClient();
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Client contextClient = context.getClient();
				assertEquals(contextClient, client,
						"the client instance is different from the context one");
				Configuration contextConfig = context.getConfiguration();
				assertNotNull(contextConfig,
						"context.getConfiguration() returned null");
				Response r = Response.ok().build();
				context.abortWith(r);
			}
		};
		client.register(provider);
		WebTarget target = client.target(getUrl());
		Invocation invocation = target.request().buildGet();
		Response response = invoke(invocation);
		assertStatus(response, Status.OK);
	}

	/*
	 * @testName: getCookiesTest
	 * @assertion_ids: JAXRS:JAVADOC:432; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get any cookies that accompanied the request. 
	 * 					Returns a read-only map of cookie name (String) to 
	 * 					Cookie.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getCookiesTest() throws Fault {
		Cookie cts = new Cookie("cts", "cts");
		Cookie tck = new Cookie("tck", "tck");
		Cookie jee = new Cookie("jee", "jee");

		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				String cookies = JaxrsUtil.iterableToString(";", context
						.getCookies().values());
				Response r = Response.ok(cookies).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).cookie(cts).cookie(tck)
				.cookie(jee).buildGet();
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "cts");
		assertContains(entity, "tck");
		assertContains(entity, "jee");
	}

	/*
	 * @testName: getCookiesIsImmutableTest
	 * @assertion_ids: JAXRS:JAVADOC:432; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get any cookies that accompanied the request. 
	 * 					Returns a read-only map of cookie name (String) to 
	 * 					Cookie.
	 * 	 				
	 * 					ClientRequestFilter.abortWith
	 */
	public void getCookiesIsImmutableTest() throws Fault {
		final Cookie cts = new Cookie("cts", "cts");

		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Map<String, Cookie> cookies = context.getCookies();
				try {
					cookies.put("test", cts);
				} catch (Exception e) {
					// either exception is thrown or put does nothing
				}
				cookies = context.getCookies();
				Cookie cookie = cookies.get("test");
				assertFault(cookie == null, "getCookies is not read-only");
				Response r = Response.ok().build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).cookie(cts).buildGet();
		Response response = invoke(invocation);
		assertStatus(response, Status.OK);
	}

	/*
	 * @testName: getDateNullTest
	 * @assertion_ids: JAXRS:JAVADOC:433; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get message date. Returns:
	 *					the message date, otherwise null if not present.
	 *
	 *	 				ClientRequestFilter.abortWith
	 */
	public void getDateNullTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Date date = context.getDate();
				Response r = Response.ok(
						date == null ? "NULL" : date.toString()).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildInvocation(provider);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "NULL");
	}

	/*
	 * @testName: getDateTest
	 * @assertion_ids: JAXRS:JAVADOC:433; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get message date. Returns:
	 *					the message date, otherwise null if not present.
	 *
	 *	 				ClientRequestFilter.abortWith
	 */
	public void getDateTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Date date = context.getDate();
				Response r = Response.ok(date.toString()).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).header("Date",
				"Tue, 15 Nov 1994 08:12:31 GMT").buildGet();
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "Nov");
		assertContains(entity, "1994");
		assertContains(entity, "31");
	}

	/*
	 * @testName: getEntityNullTest
	 * @assertion_ids: JAXRS:JAVADOC:434; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the message entity Java instance. Returns null 
	 * 					if the message does not contain an entity.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityNullTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Object entity = context.getEntity();
				Response r = Response.ok(
						entity == null ? "NULL" : entity.toString()).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildInvocation(provider);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "NULL");
	}

	/*
	 * @testName: getEntityTest
	 * @assertion_ids: JAXRS:JAVADOC:434; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85;
	 * @test_Strategy: Get the message entity Java instance. Returns null 
	 * 					if the message does not contain an entity.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Object entity = context.getEntity();
				Response r = Response.ok(entity.toString()).build();
				context.abortWith(r);
			}
		};
		Entity<String> post = createEntity("test");
		Invocation invocation = buildBuilder(provider).buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "test");
	}

	/*
	 * @testName: getEntityAnnotationsTest
	 * @assertion_ids: JAXRS:JAVADOC:435; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the annotations attached to the entity.
	 * 					Note that the returned annotations array contains only 
	 * 					those annotations explicitly attached to entity 
	 * 					instance (such as the ones attached using 
	 * 					Entity.Entity(Object, javax.ws.rs.core.MediaType, 
	 * 						java.lang.annotation.Annotation[]) method).
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityAnnotationsTest() throws Fault {
		Annotation[] annotations = ContextProvider.class.getAnnotations();
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Annotation[] annotations = context.getEntityAnnotations();
				String first = annotations == null ? "NULL"
						: annotations.length == 0 ? "0" : annotations[0]
								.annotationType().getName();
				Response r = Response.ok(first).build();
				context.abortWith(r);
			}
		};
		Entity<String> post = Entity.entity("test", MediaType.WILDCARD_TYPE,
				annotations);
		Invocation invocation = buildBuilder(provider).buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, annotations[0].annotationType().getName());
	}

	/*
	 * @testName: getEntityAnnotationsIsNotTakenFromEntityClassTest
	 * @assertion_ids: JAXRS:JAVADOC:435; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the annotations attached to the entity.
	 * 					Note that the returned annotations array contains only 
	 * 					those annotations explicitly attached to entity 
	 * 					instance (such as the ones attached using 
	 * 					Entity.Entity(Object, javax.ws.rs.core.MediaType, 
	 * 						java.lang.annotation.Annotation[]) method). 
	 * 					The entity instance annotations array does not include 
	 * 					annotations declared on the entity implementation class 
	 * 					or its ancestors.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityAnnotationsIsNotTakenFromEntityClassTest()
			throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Annotation[] annotations = context.getEntityAnnotations();
				String first = annotations == null ? "0" : String
						.valueOf(annotations.length);
				Response r = Response.ok(first).build();
				context.abortWith(r);
			}
		};
		Entity<StringBeanWithAnnotation> post = createEntity(new StringBeanWithAnnotation(
				"test"));
		Invocation invocation = buildTarget(provider)
				.register(StringBeanEntityProvider.class).request()
				.buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "0");
	}

	/*
	 * @testName: getEntityAnnotationsNullTest
	 * @assertion_ids: JAXRS:JAVADOC:435; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the annotations attached to the entity.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityAnnotationsNullTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Annotation[] annotations = context.getEntityAnnotations();
				String len = annotations == null ? "0" : String
						.valueOf(annotations.length);
				Response r = Response.ok(len).build();
				context.abortWith(r);
			}
		};
		Entity<String> post = createEntity("test");
		Invocation invocation = buildBuilder(provider).buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "0");
	}

	/*
	 * @testName: getEntityClassTest
	 * @assertion_ids: JAXRS:JAVADOC:436; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the raw entity type information.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityClassTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Class<?> clazz = context.getEntityClass();
				Response r = Response.ok(clazz.getName()).build();
				context.abortWith(r);
			}
		};
		Entity<ByteArrayInputStream> post = createEntity(new ByteArrayInputStream(
				"test".getBytes()));
		Invocation invocation = buildBuilder(provider).buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, ByteArrayInputStream.class.getName());
	}

	/*
	 * @testName: getEntityClassListStringTest
	 * @assertion_ids: JAXRS:JAVADOC:436; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the raw entity type information.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityClassListStringTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Class<?> clazz = context.getEntityClass();
				Response r = Response.ok(clazz.getName()).build();
				context.abortWith(r);
			}
		};
		List<String> list = new ArrayList<String>();
		Entity<List<String>> post = createEntity(list);
		Invocation invocation = buildBuilder(provider).buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, ArrayList.class.getName());
	}

	/*
	 * @testName: getEntityTypeListStringTest
	 * @assertion_ids: JAXRS:JAVADOC:438; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the generic entity type information.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getEntityTypeListStringTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Type type = context.getEntityType();
				String entity = type.toString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		List<String> list = new ArrayList<String>();
		GenericEntity<List<String>> generic = new GenericEntity<List<String>>(
				list) {
		};
		Entity<GenericEntity<List<String>>> post = createEntity(generic);
		Invocation invocation = buildBuilder(provider).buildPost(post);
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, String.class.getName());
	}

	/*
	 * @testName: getHeadersTest
	 * @assertion_ids: JAXRS:JAVADOC:439; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the mutable request headers multivalued map.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getHeadersTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				MultivaluedMap<String, Object> headers = context.getHeaders();
				String entity = JaxrsUtil.iterableToString(";",
						headers.keySet());
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider)
				.header("Accept", MediaType.TEXT_HTML).header("tck", "cts")
				.header("Date", "Tue, 15 Nov 1994 08:12:31 GMT").buildGet();
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "Accept");
		assertContains(entity, "Date");
		assertContains(entity, "tck");
	}

	/*
	 * @testName: getHeadersIsMutableTest
	 * @assertion_ids: JAXRS:JAVADOC:440; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the mutable request headers multivalued map.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getHeadersIsMutableTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				MultivaluedMap<String, Object> headers = context.getHeaders();
				headers.add("Accept", MediaType.APPLICATION_JSON);

				headers = context.getHeaders();
				String entity = JaxrsUtil.iterableToString(";",
						headers.keySet());
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).buildGet();
		Response response = invoke(invocation);

		String entity = response.readEntity(String.class);
		assertContains(entity, "Accept");
	}

	/*
	 * @testName: getHeaderStringTest
	 * @assertion_ids: JAXRS:JAVADOC:440; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a message header as a single string value.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getHeaderStringTest() throws Fault {
		final String TCK = "cts";
		final String DATE = "Tue, 15 Nov 1994 08:12:31 GMT";
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				String value;
				value = context.getHeaderString("tck");
				assertContainsIgnoreCase(value, TCK, "The expected value", TCK,
						"was not found, found", value, "instead");
				value = context.getHeaderString("accept");
				assertContainsIgnoreCase(value, MediaType.TEXT_HTML,
						"The expected value", MediaType.TEXT_HTML,
						"was not found, found", value, "instead");
				value = context.getHeaderString("date");
				assertContainsIgnoreCase(value, DATE, "The expected value",
						DATE, "was not found, found", value, "instead");
				Response r = Response.ok().build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider)
				.header("Accept", MediaType.TEXT_HTML)
				.header("tck", new StringBuffer().append(TCK)) // toString()
				.header("Date", DATE).buildGet();
		Response response = invoke(invocation);
		assertStatus(response, Status.OK);
	}

	/*
	 * @testName: getHeaderStringUsingHeaderDelegateTest
	 * @assertion_ids: JAXRS:JAVADOC:440; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a message header as a single string value.
	 * 				   Each single header value is converted to String using a 
	 * 					RuntimeDelegate.HeaderDelegate.
	 * 
	 *  	 			ClientRequestFilter.abortWith
	 */
	public void getHeaderStringUsingHeaderDelegateTest() throws Fault {
		final String name = "BEAN";
		final StringBean bean = new StringBean(name);
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				String value = context.getHeaderString(name);
				Response r = Response.ok(value).build();
				context.abortWith(r);
			}
		};
		RuntimeDelegate original = RuntimeDelegate.getInstance();
		RuntimeDelegate.setInstance(new StringBeanRuntimeDelegate(original));
		try {
			Invocation invocation = buildBuilder(provider).header(name, bean)
					.buildGet();
			Response response = invoke(invocation);
			String body = response.readEntity(String.class);
			assertContains(name.toLowerCase(), body.toLowerCase());
		} finally {
			RuntimeDelegate.setInstance(original);
			StringBeanRuntimeDelegate.assertNotStringBeanRuntimeDelegate();
		}
	}

	/*
	 * @testName: getLanguageIsNullTest
	 * @assertion_ids: JAXRS:JAVADOC:441; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the language of the entity. Returns:
	 * 					the language of the entity or null if not specified
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getLanguageIsNullTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Locale lang = context.getLanguage();
				String entity = lang == null ? "NULL" : lang.toString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Entity<String> entity = createEntity("TEST");
		Invocation invocation = buildBuilder(provider).buildPost(entity);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, "NULL");
	}

	/*
	 * @testName: getLanguageTest
	 * @assertion_ids: JAXRS:JAVADOC:441; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the language of the entity. Returns:
	 * 					the language of the entity or null if not specified
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getLanguageTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Locale lang = context.getLanguage();
				String entity = lang == null ? "NULL" : lang.toString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Locale locale = Locale.TRADITIONAL_CHINESE;
		Variant variant = new Variant(MediaType.TEXT_XML_TYPE, locale, null);
		Entity<String> entity = Entity.entity("TEST", variant);
		Invocation invocation = buildBuilder(provider).buildPost(entity);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class).toLowerCase()
				.replace('-', '_');
		assertContains(body, locale.toString().toLowerCase());
	}

	/*
	 * @testName: getMediaTypeIsNullTest
	 * @assertion_ids: JAXRS:JAVADOC:442; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the media type of the entity. Returns: 
	 * 					the media type or null if not specified (e.g. 
	 * 					there's no request entity). 
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getMediaTypeIsNullTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				MediaType media = context.getMediaType();
				String entity = media == null ? "NULL" : media.toString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).buildGet();
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, "NULL");
	}

	/*
	 * @testName: getMediaTypeTest
	 * @assertion_ids: JAXRS:JAVADOC:442; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the media type of the entity. Returns: 
	 * 					the media type or null if not specified (e.g. 
	 * 					there's no request entity). 
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getMediaTypeTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				MediaType media = context.getMediaType();
				String entity = media == null ? "NULL" : media.toString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Entity<String> entity = Entity.entity("TEST",
				MediaType.APPLICATION_FORM_URLENCODED);
		Invocation invocation = buildBuilder(provider).buildPost(entity);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, MediaType.APPLICATION_FORM_URLENCODED);
	}

	/*
	 * @testName: getMethodTest
	 * @assertion_ids: JAXRS:JAVADOC:443; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the request method.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getMethodTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				String method = context.getMethod();
				Response r = Response.ok(method).build();
				context.abortWith(r);
			}
		};
		Entity<String> entity = createEntity("TEST");
		Invocation invocation;
		Response response;

		for (String method : new String[] { "OPTIONS", "DELETE", "GET", "TRACE" }) {
			invocation = buildBuilder(provider).build(method);
			response = invoke(invocation);
			String body = response.readEntity(String.class).toUpperCase();
			assertContains(body, method);
		}

		for (String method : new String[] { "PUT", "POST" }) {
			invocation = buildBuilder(provider).build(method, entity);
			response = invoke(invocation);
			String body = response.readEntity(String.class).toUpperCase();
			assertContains(body, method);
		}
	}

	/*
	 * @testName: getPropertyIsNullTest
	 * @assertion_ids: JAXRS:JAVADOC:444;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427; 
	 * @test_Strategy: Returns the property with the given name registered in 
	 * 					the current request/response exchange context, or null 
	 * 					if there is no property by that name.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getPropertyIsNullTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				Object property = context.getProperty("PROPERTY");
				String entity = property == null ? "NULL" : property.toString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).buildGet();
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, "NULL");
	}

	/*
	 * @testName: getSetPropertyTest
	 * @assertion_ids: JAXRS:JAVADOC:444; JAXRS:JAVADOC:453;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Returns the property with the given name registered in 
	 * 					the current request/response exchange context, or null 
	 * 					if there is no property by that name.
	 * 
	 * 					Binds an object to a given property name in the current 
	 * 					request/response exchange context.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getSetPropertyTest() throws Fault {
		final AtomicInteger counter = new AtomicInteger(0);
		ContextProvider provider = new GetSetPropertyProvider(counter);
		ContextProvider provider2 = new GetSetPropertyProvider(counter) {
		};

		Invocation invocation = buildInvocation(provider, provider2);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, "value");
	}

	/*
	 * @testName: getPropertyNamesTest
	 * @assertion_ids: JAXRS:JAVADOC:978; JAXRS:JAVADOC:453;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Returns an immutable collection containing the property names 
	 * 					available within the context of the current 
	 * 					request/response exchange context.
	 * 
	 * 					Binds an object to a given property name in the current 
	 * 					request/response exchange context.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getPropertyNamesTest() throws Fault {
		final AtomicInteger counter = new AtomicInteger(0);
		ContextProvider provider = new GetPropertyNamesProvider(counter);
		ContextProvider provider2 = new GetPropertyNamesProvider(counter) {
		};

		Invocation invocation = buildInvocation(provider, provider2);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, "PROPERTY1");
		assertContains(body, "PROPERTY2");
	}

	/*
	 * @testName: getPropertyNamesIsImmutableTest
	 * @assertion_ids: JAXRS:JAVADOC:978; JAXRS:JAVADOC:453;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Returns an immutable collection containing the property names 
	 * 					available within the context of the current 
	 * 					request/response exchange context.
	 * 
	 * 					Binds an object to a given property name in the current 
	 * 					request/response exchange context.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getPropertyNamesIsImmutableTest() throws Fault {
		final AtomicInteger counter = new AtomicInteger(0);
		ContextProvider provider = new GetPropertyNamesIsImmutableProvider(
				counter);

		Invocation invocation = buildInvocation(provider);
		Response response = invoke(invocation);
		String body = response.readEntity(String.class);
		assertEqualsInt(0, counter.get(),
				"getPropertyNames collection is not immutable");
		assertEquals("0", body, "getPropertyNames collection is not immutable");
		logMsg("getPropertyNames is immutable as expected");
	}

	/*
	 * @testName: getStringHeadersTest
	 * @assertion_ids: JAXRS:JAVADOC:446; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a string view of header values associated with the message.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getStringHeadersTest() throws Fault {
		final String TCK = "cts";
		final String DATE = "Tue, 15 Nov 1994 08:12:31 GMT";
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				MultivaluedMap<String, String> map;
				map = context.getStringHeaders();
				StringBuilder value = new StringBuilder();
				value.append(map.getFirst("Accept")).append(" ");
				value.append(map.getFirst("tck")).append(" ");
				value.append(map.getFirst("Date"));
				Response r = Response.ok(value.toString()).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider)
				.header("Accept", MediaType.TEXT_HTML).header("tck", TCK)
				.header("Date", DATE).buildGet();
		Response response = invoke(invocation);
		String body = response.readEntity(String.class);
		assertContains(body, MediaType.TEXT_HTML);
		assertContains(body, TCK);
		assertContains(body, DATE);
	}

	/*
	 * @testName: getStringHeadersReflectsTheUnderlayingMapTest
	 * @assertion_ids: JAXRS:JAVADOC:446; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a string view of header values associated with the message.
	 * 					Changes in the underlying headers map 
	 * 					are reflected in this view.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getStringHeadersReflectsTheUnderlayingMapTest() throws Fault {
		final String TCK = "cts";
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				context.getHeaders().add(TCK, TCK);
				MultivaluedMap<String, String> map;
				map = context.getStringHeaders();
				String value = map.getFirst(TCK);
				Response r = Response.ok(value).build();
				context.abortWith(r);
			}
		};
		Invocation invocation = buildBuilder(provider).buildGet();
		Response response = invoke(invocation);
		String body = response.readEntity(String.class);
		assertContains(body, TCK);
	}

	/*
	 * @testName: getStringHeadersUsingHeaderDelegateTest
	 * @assertion_ids: JAXRS:JAVADOC:446; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get a string view of header values associated with the message.
	 * 					The method converts the non-string header values to 
	 * 					strings using a RuntimeDelegate.HeaderDelegate
	 * 
	 *  	 				ClientRequestFilter.abortWith
	 */
	public void getStringHeadersUsingHeaderDelegateTest() throws Fault {
		final String TCK = "cts";
		final StringBean bean = new StringBean(TCK);
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				MultivaluedMap<String, String> map;
				map = context.getStringHeaders();
				StringBuilder value = new StringBuilder();
				value.append(map.getFirst(TCK));
				Response r = Response.ok(value.toString()).build();
				context.abortWith(r);
			}
		};
		RuntimeDelegate delegate = RuntimeDelegate.getInstance();
		RuntimeDelegate.setInstance(new StringBeanRuntimeDelegate(delegate));
		try {
			Invocation invocation = buildBuilder(provider).header(TCK, bean)
					.buildGet();
			Response response = invoke(invocation);
			String body = response.readEntity(String.class);
			assertContains(body, TCK);
		} finally {
			RuntimeDelegate.setInstance(delegate);
			StringBeanRuntimeDelegate.assertNotStringBeanRuntimeDelegate();
		}
	}

	/*
	 * @testName: getUriTest
	 * @assertion_ids: JAXRS:JAVADOC:447;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Get the request URI.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void getUriTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				URI uri = context.getUri();
				String entity = uri.toASCIIString();
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};

		Invocation invocation = buildInvocation(provider);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, getUrl());
	}

	/*
	 * @testName: hasEntityTest
	 * @assertion_ids: JAXRS:JAVADOC:448;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy: Check if there is an entity available in the request. 
	 * 					The method returns true if the entity is present, 
	 * 					returns false otherwise.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void hasEntityTest() throws Fault {
		ContextProvider provider = new ContextProvider() {
			@Override
			protected void checkFilterContext(ClientRequestContext context)
					throws Fault {
				boolean has = context.hasEntity();
				String entity = String.valueOf(has);
				Response r = Response.ok(entity).build();
				context.abortWith(r);
			}
		};

		Invocation invocation = buildInvocation(provider);
		Response response = invoke(invocation);
		String body = response.readEntity(String.class);
		assertContains(body, "false");

		Entity<String> entity = createEntity("TEST");
		WebTarget target = buildTarget(provider);
		invocation = target.request().buildPost(entity);
		response = invoke(invocation);
		body = response.readEntity(String.class);
		assertContains(body, "true");
	}

	/*
	 * @testName: removePropertyTest
	 * @assertion_ids: JAXRS:JAVADOC:449; 
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85; JAXRS:JAVADOC:427;
	 * @test_Strategy:Removes a property with the given name from the current 
	 * 					request/response exchange context. After removal, 
	 *					subsequent calls to getProperty(java.lang.String) to 
	 *					retrieve the property value will return null.
	 *
	 *	 				ClientRequestFilter.abortWith
	 */
	public void removePropertyTest() throws Fault {
		final AtomicInteger counter = new AtomicInteger(0);
		ContextProvider provider = new RemovePropertyProvider(counter);
		ContextProvider provider2 = new RemovePropertyProvider(counter) {
		};
		ContextProvider provider3 = new RemovePropertyProvider(counter) {
		};

		Invocation invocation = buildInvocation(provider, provider2, provider3);
		Response response = invoke(invocation);

		String body = response.readEntity(String.class);
		assertContains(body, "NULL");
	}

	/*
	 * @testName: setEntityTest
	 * @assertion_ids: JAXRS:JAVADOC:450; 
	 * 					JAXRS:JAVADOC:434; JAXRS:JAVADOC:435; JAXRS:JAVADOC:438;
	 * 					JAXRS:JAVADOC:455; JAXRS:JAVADOC:456;
	 * 					JAXRS:SPEC:85;
	 * @test_Strategy: Set a new response message entity. It is the callers 
	 * 					responsibility to wrap the actual entity with 
	 * 					javax.ws.rs.core.GenericEntity if preservation of its 
	 * 					generic type is required.
	 * 
	 * 	 				ClientRequestFilter.abortWith
	 */
	public void setEntityTest() throws Fault {
		final AtomicInteger counter = new AtomicInteger(0);

		ContextProvider provider = new SetEntityProvider(counter);
		ContextProvider provider2 = new SetEntityProvider(counter) {
		};

		Entity<ByteArrayInputStream> entity = createEntity(new ByteArrayInputStream(
				"test".getBytes()));

		WebTarget target = buildTarget(provider, provider2);
		Invocation invocation = target.request().buildPost(entity);
		Response response = invoke(invocation);

		assertStatus(response, Status.OK);
	}

	// ///////////////////////////////////////////////////////////////////////
	/**
	 * Call given provider CheckContextFilter method
	 */
	protected static Response invoke(Invocation i) throws Fault {
		Response r = null;
		try {
			r = i.invoke();
		} catch (Exception e) {
			Object cause = e.getCause();
			if (cause instanceof Fault)
				throw (Fault) cause;
			else
				throw new Fault(e);
		}
		return r;
	}

	protected static Invocation buildInvocation(ContextProvider... provider) {
		WebTarget target = buildTarget(provider);
		Invocation i = target.request().buildGet();
		return i;
	}

	protected static WebTarget buildTarget(ContextProvider... providers) {
		Client client = ClientBuilder.newClient();
		for (ContextProvider provider : providers)
			client.register(provider);
		WebTarget target = client.target(getUrl());
		return target;
	}

	protected static Invocation.Builder buildBuilder(
			ContextProvider... provider) {
		Invocation.Builder builder = buildTarget(provider).request();
		return builder;
	}

	protected static void assertStatus(Response r, Status status) throws Fault {
		assertFault(r.getStatus() == status.getStatusCode(), "Expected",
				status.getStatusCode(), "got", r.getStatus());
		TestUtil.logMsg("Found expected status: " + status.getStatusCode());
	}

	protected static void assertContains(String string, String substring)
			throws Fault {
		assertFault(string.contains(substring), string, "does NOT contain",
				substring, ", it is:", string);
		TestUtil.logMsg("Found expected substring: " + substring);
	}

	/**
	 * @return any possible url
	 */
	protected static String getUrl() {
		return "http://localhost:8080/404URL/";
	}

	protected <T> Entity<T> createEntity(T entity) {
		return Entity.entity(entity, MediaType.WILDCARD_TYPE);
	}
}
