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