View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.tck.junit4.rule;
8   
9   import org.apache.commons.logging.Log;
10  import org.apache.commons.logging.LogFactory;
11  import org.junit.rules.ExternalResource;
12  
13  /**
14   * Defines a socket port number that will be dynamically assigned as an
15   * external resource. The instance will check that the port has been released
16   * on test shutdown.
17   * To use an instance dynamic socket port:
18   * <pre>
19   *     @Rule
20   *     public DynamicSocketPortNumber serverPort = new DynamicSocketPortNumber("server_port");
21   * </pre>
22   * <p/>
23   * In order to use static dynamic ports:
24   * <p/>
25   * <pre>
26   *     @ClassRule
27   *     public static DynamicPort dynamicPort;
28   * </pre>
29   */
30  public class DynamicPort extends ExternalResource
31  {
32  
33      final static private int MIN_PORT = 5000;
34      final static private int MAX_PORT = 6000;
35  
36      protected static FreePortFinder freePortFinder = new FreePortFinder(MIN_PORT, MAX_PORT);
37  
38      protected Log logger = LogFactory.getLog(getClass());
39  
40      private final String name;
41      private int number;
42      private boolean initialized = false;
43  
44      /**
45       * Creates a dynamic port resource for a given port name.
46       *
47       * @param name the name assigned to the port number. On resource creation
48       *             a new system property will be created with that name and the
49       *             value will be the port number.
50       */
51      public DynamicPort(String name)
52      {
53          this.name = name;
54      }
55  
56      /**
57       * Initializes the dynamic port.
58       * <p/>
59       * NOTE: this method was made public in order to support the usage of
60       * static dynamic ports because current JUnit version does not support
61       * class rules.
62       *
63       * @throws Throwable
64       */
65      @Override
66      public void before() throws Throwable
67      {
68          if (initialized)
69          {
70              throw new IllegalArgumentException("Dynamic port was already initialized");
71          }
72  
73          number = freePortFinder.find();
74          System.setProperty(name, String.valueOf(number));
75          initialized = true;
76      }
77  
78      /**
79       * Checks that the port has been released. For now if it was not released it
80       * just logs a message so we can track the problem.
81       * <p/>
82       * NOTE: this method was made public in order to support the usage of
83       * static dynamic ports because current JUnit version does not support
84       * class rules.
85       *
86       * @throws Throwable
87       */
88      @Override
89      public void after()
90      {
91          if (!initialized)
92          {
93              throw new IllegalArgumentException("Dynamic port was not initialized");
94          }
95  
96          freePortFinder.releasePort(number);
97          initialized = false;
98      }
99  
100     public int getNumber()
101     {
102         return number;
103     }
104 
105     public String getName()
106     {
107         return name;
108     }
109 }