View Javadoc
1   package net.avcompris.commons3.web.it.utils;
2   
3   import static com.google.common.base.Preconditions.checkArgument;
4   import static com.google.common.base.Preconditions.checkNotNull;
5   import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
6   import static org.apache.commons.lang3.StringUtils.substringBetween;
7   
8   import java.io.IOException;
9   import java.lang.reflect.InvocationHandler;
10  import java.lang.reflect.InvocationTargetException;
11  import java.lang.reflect.Method;
12  import java.lang.reflect.Proxy;
13  
14  import org.apache.commons.lang3.NotImplementedException;
15  
16  import net.avcompris.commons3.api.EnumRole;
17  import net.avcompris.commons3.api.User;
18  import net.avcompris.commons3.client.SessionPropagator;
19  import net.avcompris.commons3.client.impl.AbstractClient;
20  
21  public abstract class WebTestUtils {
22  
23  	public static Api api(final String apiBaseURL) throws IOException {
24  
25  		checkNotNull(apiBaseURL, "apiBaseURL");
26  
27  		return new ApiImpl(apiBaseURL);
28  	}
29  
30  	private static final class ApiImpl implements Api {
31  
32  		private final String apiBaseURL;
33  
34  		public ApiImpl(final String apiBaseURL) {
35  
36  			this.apiBaseURL = checkNotNull(apiBaseURL, "apiBaseURL");
37  		}
38  
39  		@Override
40  		public User user(final String authorization) {
41  
42  			return new UserImpl(authorization);
43  		}
44  
45  		@Override
46  		public <U, V extends U> U forge(final Class<U> serviceClass, final String apiBaseURL,
47  				final Class<V> serviceClientClass) {
48  
49  			checkNotNull(serviceClass, "serviceClass");
50  			checkNotNull(apiBaseURL, "apiBaseURL");
51  			checkNotNull(serviceClientClass, "serviceClientClass");
52  
53  			checkArgument(apiBaseURL.startsWith("${") && apiBaseURL.endsWith("}"), //
54  					"apiBaseURL should be of the form \"${...}\", e.g. \"${users.apiBaseURL}\", but was: %s",
55  					apiBaseURL);
56  
57  			final String propertyName = substringBetween(apiBaseURL, "${", "}");
58  
59  			System.setProperty(propertyName, this.apiBaseURL);
60  
61  			checkArgument(AbstractClient.class.isAssignableFrom(serviceClientClass), //
62  					"serviceClientClass shoud extend AbstractClient, but was: %s", serviceClientClass.getName());
63  
64  			final SessionPropagator sessionPropagator = new SessionPropagator();
65  
66  			final V client;
67  
68  			try {
69  
70  				client = serviceClientClass //
71  						.getConstructor(SessionPropagator.class) //
72  						.newInstance(sessionPropagator);
73  
74  			} catch (final InstantiationException | IllegalAccessException | InvocationTargetException
75  					| NoSuchMethodException e) {
76  
77  				throw new RuntimeException(e);
78  			}
79  
80  			final Object proxy = Proxy.newProxyInstance( //
81  					serviceClass.getClassLoader(), //
82  					new Class<?>[] { serviceClass }, //
83  					new InvocationHandler() {
84  
85  						@Override
86  						public Object invoke(final Object proxy, final Method method, final Object[] args)
87  								throws Throwable {
88  
89  							if (serviceClass.equals(method.getDeclaringClass())) {
90  
91  								return invokeServiceMethod(sessionPropagator, client, method, args);
92  
93  							} else {
94  
95  								throw new NotImplementedException(
96  										"method: " + method.getName() + "(), serviceClass: " + serviceClass.getName());
97  							}
98  						}
99  					});
100 
101 			return serviceClass.cast(proxy);
102 		}
103 
104 		private Object invokeServiceMethod(final SessionPropagator sessionPropagator, final Object client,
105 				final Method method, final Object[] args) throws Throwable {
106 
107 			checkArgument(args.length >= 2, //
108 					"args.length should be >= 2, but was: %s", args.length);
109 
110 			checkArgument(args[0] == null, //
111 					"args[0] should be null, but was: %s", args[0]);
112 
113 			final String correlationId = "C-" + randomAlphanumeric(20);
114 
115 			args[0] = correlationId;
116 
117 			final User user = (User) args[1];
118 
119 			checkArgument(user != null, "user arg should not be null");
120 
121 			checkArgument(user instanceof UserImpl, //
122 					"user arg should be obtained through the \"Api#user()\" method, but was: %s",
123 					user.getClass().getName());
124 
125 			final String authorization = ((UserImpl) user).getAuthorization();
126 
127 			sessionPropagator.setAuthorizationHeader(authorization);
128 
129 			return method.invoke(client, args);
130 		}
131 	}
132 
133 	private static final class UserImpl implements User {
134 
135 		private final String authorization;
136 
137 		public UserImpl(final String authorization) {
138 
139 			this.authorization = checkNotNull(authorization, "authorization");
140 		}
141 
142 		@Override
143 		public String getUsername() {
144 
145 			throw new NotImplementedException("");
146 		}
147 
148 		@Override
149 		public EnumRole getRole() {
150 
151 			throw new NotImplementedException("");
152 		}
153 
154 		public String getAuthorization() {
155 
156 			return authorization;
157 		}
158 	}
159 }