View Javadoc

1   package com.atlassian.pageobjects;
2   
3   import com.google.common.base.Supplier;
4   
5   import java.lang.reflect.Constructor;
6   import java.lang.reflect.InvocationTargetException;
7   import java.net.InetAddress;
8   import java.net.UnknownHostException;
9   
10  /**
11   * Constructs a {@link TestedProduct}.  The {@link TestedProduct} instance is created by calling the constructor
12   * with the following method signature:
13   * <pre>
14   *   TestedProduct(TesterFactory, ProductInstance)
15   * </pre>
16   */
17  public class TestedProductFactory
18  {
19      /**
20       * A factory for {@link Tester} instances
21       * @param <T> The tester type
22       */
23      public static interface TesterFactory<T>
24      {
25          /**
26           * @return The tester instance to be used through the tested product
27           */
28          T create();
29      }
30  
31      /**
32       * A factory that always returns the same {@link Tester}
33       * @param <T> The tester type
34       */
35      public static class SingletonTesterFactory<T extends Tester> implements TesterFactory<T>
36      {
37          private final T tester;
38  
39          public SingletonTesterFactory(T tester)
40          {
41              this.tester = tester;
42          }
43  
44          public T create()
45          {
46              return tester;
47          }
48      }
49  
50      public static <T extends TestedProduct<?>> Supplier<T> fromFactory(final Class<T> productClass)
51      {
52          return new Supplier<T>()
53          {
54              @Override
55              public T get()
56              {
57                  return create(productClass);
58              }
59          };
60      }
61  
62      /**
63       * Creates a tested product, allowing the instance to choose its own default {@link Tester} and instance id
64       * @param testedProductClass The tested product class name
65       * @return The created tested product
66       */
67      @SuppressWarnings("unchecked")
68      public static TestedProduct<?> create(String testedProductClass)
69      {
70          Class<TestedProduct<?>> clazz;
71          try
72          {
73              clazz = (Class<TestedProduct<?>>) TestedProductFactory.class.getClassLoader().loadClass(testedProductClass);
74          }
75          catch (ClassNotFoundException e)
76          {
77              throw new IllegalArgumentException("Cannot find tested product class: " + testedProductClass);
78          }
79          return create(clazz);
80      }
81  
82      /**
83       * Creates a tested product, allowing the instance to choose its own default {@link Tester} and instance id
84       * @param testedProductClass The tested product class
85       * @param <P> The tested product type
86       * @return The created tested product
87       */
88      public static <P extends TestedProduct<?>> P create(Class<P> testedProductClass)
89      {
90          return create(testedProductClass, getDefaultInstanceId(testedProductClass), null);
91      }
92  
93      /**
94       * Creates a tested product using the passed tester factory and instance id.
95       * @param testedProductClass The tested product class
96       * @param instanceId The instance id
97       * @param testerFactory The tester factory to use to pass to the tested product
98       * @param <P> The tested product type
99       * @return The created tested product
100      */
101     public static <P extends TestedProduct<?>> P create(Class<P> testedProductClass, String instanceId, TesterFactory<?> testerFactory)
102     {
103         final String contextPath, baseUrl;
104         final int httpPort;
105 
106         final String ampsBaseUrl = System.getProperty("baseurl." + instanceId);
107         final ProductInstance instance;
108         if (ampsBaseUrl != null)    // running within an AMPS IntegrationTestMojo invocation - read sys props for env vars
109         {
110             httpPort = Integer.getInteger("http." + instanceId + ".port");
111             contextPath = System.getProperty("context." + instanceId + ".path");
112             baseUrl = ampsBaseUrl;
113         }
114         else
115         {
116             Defaults defaults = getDefaultsAnnotation(testedProductClass);
117             httpPort = defaults.httpPort();
118             contextPath = defaults.contextPath();
119             baseUrl = "http://" + getLocalHostName() + ":" + httpPort + contextPath;
120         }
121         instance = new DefaultProductInstance(baseUrl, instanceId, httpPort, contextPath);
122         return create(testedProductClass, instance, testerFactory);
123     }
124 
125     private static String getDefaultInstanceId(Class<?> testedProductClass)
126     {
127         Defaults annotation = getDefaultsAnnotation(testedProductClass);
128         return annotation.instanceId();
129     }
130 
131     private static Defaults getDefaultsAnnotation(Class<?> testedProductClass)
132     {
133         Defaults annotation = testedProductClass.getAnnotation(Defaults.class);
134         if (annotation == null)
135         {
136             throw new IllegalArgumentException("The tested product class '" + testedProductClass.getName() + "' is missing the @Defaults annotation");
137         }
138         return annotation;
139     }
140 
141     /**
142      * Creates a tested product using the passed tester factory and product instance.
143      * @param testedProductClass The tested product class
144      * @param productInstance The product instance
145      * @param testerFactory The tester factory to use to pass to the tested product
146      * @param <P> The tested product type
147      * @return The created tested product
148      */
149     public static <P extends TestedProduct<?>> P create(Class<P> testedProductClass, ProductInstance productInstance, TesterFactory<?> testerFactory) {
150         try
151         {
152             Constructor<P> c = testedProductClass.getConstructor(TesterFactory.class, ProductInstance.class);
153             return c.newInstance(testerFactory, productInstance);
154         }
155         catch (NoSuchMethodException e)
156         {
157             throw new RuntimeException(e);
158         }
159         catch (InvocationTargetException e)
160         {
161             throw new RuntimeException(e);
162         }
163         catch (InstantiationException e)
164         {
165             throw new RuntimeException(e);
166         }
167         catch (IllegalAccessException e)
168         {
169             throw new RuntimeException(e);
170         }
171     }
172 
173     private static String getLocalHostName()
174     {
175         try
176         {
177             return InetAddress.getLocalHost().getHostName();
178         }
179         catch (UnknownHostException e)
180         {
181             throw new RuntimeException(e);
182         }
183     }
184 
185 }