1 package com.atlassian.pageobjects;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.InvocationTargetException;
5 import java.net.InetAddress;
6 import java.net.UnknownHostException;
7
8
9
10
11
12
13
14
15 public class TestedProductFactory
16 {
17
18
19
20
21 public static interface TesterFactory<T>
22 {
23
24
25
26 T create();
27 }
28
29
30
31
32
33 public static class SingletonTesterFactory<T extends Tester> implements TesterFactory<T>
34 {
35 private final T tester;
36
37 public SingletonTesterFactory(T tester)
38 {
39 this.tester = tester;
40 }
41
42 public T create()
43 {
44 return tester;
45 }
46 }
47
48
49
50
51
52
53 @SuppressWarnings("unchecked")
54 public static TestedProduct<?> create(String testedProductClass)
55 {
56 Class<TestedProduct<?>> clazz;
57 try
58 {
59 clazz = (Class<TestedProduct<?>>) TestedProductFactory.class.getClassLoader().loadClass(testedProductClass);
60 }
61 catch (ClassNotFoundException e)
62 {
63 throw new IllegalArgumentException("Cannot find tested product class: " + testedProductClass);
64 }
65 return create(clazz);
66 }
67
68
69
70
71
72
73
74 public static <P extends TestedProduct<?>> P create(Class<P> testedProductClass)
75 {
76 return create(testedProductClass, getDefaultInstanceId(testedProductClass), null);
77 }
78
79
80
81
82
83
84
85
86
87 public static <P extends TestedProduct<?>> P create(Class<P> testedProductClass, String instanceId, TesterFactory<?> testerFactory)
88 {
89 final String contextPath, baseUrl;
90 final int httpPort;
91
92 final String ampsBaseUrl = System.getProperty("baseurl." + instanceId);
93 final ProductInstance instance;
94 if (ampsBaseUrl != null)
95 {
96 httpPort = Integer.getInteger("http." + instanceId + ".port");
97 contextPath = System.getProperty("context." + instanceId + ".path");
98 baseUrl = ampsBaseUrl;
99 }
100 else
101 {
102 Defaults defaults = getDefaultsAnnotation(testedProductClass);
103 httpPort = defaults.httpPort();
104 contextPath = defaults.contextPath();
105 baseUrl = "http://" + getLocalHostName() + ":" + httpPort + contextPath;
106 }
107 instance = new DefaultProductInstance(instanceId, httpPort, contextPath, baseUrl);
108 return create(testedProductClass, instance, testerFactory);
109 }
110
111 private static String getDefaultInstanceId(Class<?> testedProductClass)
112 {
113 Defaults annotation = getDefaultsAnnotation(testedProductClass);
114 return annotation.instanceId();
115 }
116
117 private static Defaults getDefaultsAnnotation(Class<?> testedProductClass)
118 {
119 Defaults annotation = testedProductClass.getAnnotation(Defaults.class);
120 if (annotation == null)
121 {
122 throw new IllegalArgumentException("The tested product class '" + testedProductClass.getName() + "' is missing the @Defaults annotation");
123 }
124 return annotation;
125 }
126
127 private static <P extends TestedProduct<?>> P create(Class<P> testedProductClass, ProductInstance instance, TesterFactory<?> testerFactory) {
128 try
129 {
130 Constructor<P> c = testedProductClass.getConstructor(TesterFactory.class, ProductInstance.class);
131 return c.newInstance(testerFactory, instance);
132 }
133 catch (NoSuchMethodException e)
134 {
135 throw new RuntimeException(e);
136 }
137 catch (InvocationTargetException e)
138 {
139 throw new RuntimeException(e);
140 }
141 catch (InstantiationException e)
142 {
143 throw new RuntimeException(e);
144 }
145 catch (IllegalAccessException e)
146 {
147 throw new RuntimeException(e);
148 }
149 }
150
151 private static String getLocalHostName()
152 {
153 try
154 {
155 return InetAddress.getLocalHost().getHostName();
156 }
157 catch (UnknownHostException e)
158 {
159 throw new RuntimeException(e);
160 }
161 }
162
163
164
165
166 private static class DefaultProductInstance implements ProductInstance
167 {
168 private final String baseUrl;
169 private final String instanceId;
170 private final int httpPort;
171 private final String contextPath;
172
173
174 public DefaultProductInstance(final String instanceId, final int httpPort, final String contextPath, final String baseUrl)
175 {
176 this.instanceId = instanceId;
177 this.httpPort = httpPort;
178 this.contextPath = contextPath;
179 this.baseUrl = baseUrl;
180 }
181
182 public String getBaseUrl()
183 {
184 return baseUrl.toLowerCase();
185 }
186
187 public int getHttpPort()
188 {
189 return httpPort;
190 }
191
192 public String getContextPath()
193 {
194 return contextPath;
195 }
196
197 public String getInstanceId() {
198 return instanceId;
199 }
200 }
201 }