Line | Hits | Source |
---|---|---|
1 | /* | |
2 | * Copyright (C) 2006 TopCoder Inc., All Rights Reserved. | |
3 | */ | |
4 | package com.topcoder.testframework; | |
5 | ||
6 | import org.apache.tools.ant.BuildException; | |
7 | import org.apache.tools.ant.DynamicElement; | |
8 | ||
9 | import java.lang.reflect.Constructor; | |
10 | ||
11 | ||
12 | /** | |
13 | * This class represents a <tt>server</tt> XML element to be used in the Ant build file. It acts as container for an XML | |
14 | * element representing the actual server to be used for running tests. The name of the element in the build file is not | |
15 | * actually <tt>server</tt>, but is the fully qualified class name of the {@link Server} subclass to be used as | |
16 | * implementation. | |
17 | * <p/> | |
18 | * <ul><li>Supported attributes: <ul><li>None</li></ul> </li><li>Nested elements: <ul><li>Should include one nested | |
19 | * element with a custom name, specifying server type. </li></ul></li></ul> | |
20 | * <p/> | |
21 | * This class is mutable, i.e. not thread-safe. | |
22 | * | |
23 | * @author real_vg, TCSDEVELOPER | |
24 | * @version 1.0 | |
25 | */ | |
26 | public class ServerElement implements DynamicElement { | |
27 | ||
28 | /** | |
29 | * This field represents the <tt>class</tt> attribute, which represents the name of class derived from {@link | |
30 | * Server}, which supports the server described by this element. This attribute is required. | |
31 | * <p/> | |
32 | * The field is initialized in the constructor. | |
33 | */ | |
34 | private final String clazz; | |
35 | ||
36 | /** | |
37 | * This field represents the server described by this element. | |
38 | * <p/> | |
39 | * The field is initialized to <tt>null</tt> and set in the {@link #createDynamicElement(String)} method. | |
40 | */ | |
41 | 25 | private Server server = null; |
42 | ||
43 | /** | |
44 | * This field represents information about the current Ant project, task, etc. The field is initialized to | |
45 | * <tt>null</tt> and set via the {@link #setAntTaskInfo(AntTaskInfo)} method. | |
46 | */ | |
47 | 25 | private AntTaskInfo antTaskInfo = null; |
48 | ||
49 | /** | |
50 | * Creates a ServerElement instance. | |
51 | * | |
52 | * @param className the name of class derived from {@link Server}, which supports the server described by this | |
53 | * element | |
54 | * | |
55 | * @throws IllegalArgumentException incase the given className is <tt>null</tt> or an empty (trim'd) String | |
56 | */ | |
57 | 25 | public ServerElement(final String className) { |
58 | 25 | if (className == null) { |
59 | 1 | throw new IllegalArgumentException("The parameter named [className] was null."); |
60 | } | |
61 | 24 | if (className.trim().length() == 0) { |
62 | 1 | throw new IllegalArgumentException("The parameter named [className] was an empty String."); |
63 | } | |
64 | 23 | clazz = className; |
65 | 23 | } |
66 | ||
67 | /** | |
68 | * This method creates an element with a specified name. Handles unknown elements. Really this methods creates an | |
69 | * instance of class derived from {@link Server} The name of the element specifies the type of the server to be | |
70 | * passed to class constructor. The name of actual class to create instance of is taken from <tt>class</tt> | |
71 | * attribute. | |
72 | * | |
73 | * @param name the name of element to be created, specifies the type of server this element describes | |
74 | * | |
75 | * @return an instance of class derived from AbstractServer, represents the actual server described by this element | |
76 | * | |
77 | * @throws BuildException if can't create an instance of specified class via reflection, or if the created | |
78 | * class doesn't support the specified server type | |
79 | * @throws IllegalArgumentException if name is <tt>null</tt> or empty (trim'd) string | |
80 | */ | |
81 | public Object createDynamicElement(final String name) { | |
82 | 12 | if (name == null) { |
83 | 1 | throw new IllegalArgumentException("The parameter named [name] was null."); |
84 | } | |
85 | 11 | if (name.trim().length() == 0) { |
86 | 1 | throw new IllegalArgumentException("The parameter named [name] was an empty String."); |
87 | } | |
88 | // Check if there was no previously created element | |
89 | 10 | if (server != null) { |
90 | 1 | throw new BuildException("There should be only one nested element describing server."); |
91 | } | |
92 | 9 | if (getAntTaskInfo() == null) { |
93 | 1 | throw new BuildException("The dynamic element cannot be constructed as this ServerElement instance " |
94 | + "does not have a valid AntTaskInfo instance assigned yet."); | |
95 | } | |
96 | ||
97 | //lookup and load instance implementation class | |
98 | final Class implClass; | |
99 | try { | |
100 | 8 | implClass = Class.forName(clazz); |
101 | 1 | } catch (Throwable t) { |
102 | // catch of Throwable is normally discouraged by the TC coding style, but | |
103 | // as a lot of Errors can arise from a class load and these | |
104 | // errors don't need to be let pass through this catch clause (as they | |
105 | // definitely belong to the class load and not the normal program | |
106 | // execution) all Throwables are caught here and | |
107 | // wrapped into a BuildException. | |
108 | 1 | throw new BuildException("Unable to load implementation class [" + clazz + "].", t); |
109 | 7 | } |
110 | ||
111 | //check if class matches expected type | |
112 | 9 | if (!Server.class.isAssignableFrom(implClass)) { |
113 | 1 | throw new BuildException( |
114 | "The implementation class [" + clazz + "] is not of type [" + Server.class.getName() + "]."); | |
115 | } | |
116 | ||
117 | //find constructor | |
118 | final Constructor constructor; | |
119 | try { | |
120 | 6 | constructor = implClass.getConstructor(new Class[]{String.class}); |
121 | 1 | } catch (NoSuchMethodException e) { |
122 | 1 | throw new BuildException("The implementation class [" + implClass .getName() |
123 | + "] did not have a constructor with single String argument signature.", e); | |
124 | 5 | } |
125 | ||
126 | //create instance | |
127 | try { | |
128 | 5 | server = (Server) constructor.newInstance(new Object[]{name}); |
129 | 1 | } catch (Throwable t) { |
130 | // catch of Throwable is normally discouraged by the TC coding style, but | |
131 | // as a lot of Errors can arise from a reflection invocation and these | |
132 | // errors don't need to be let pass through this catch clause (as they | |
133 | // definitely belong to the reflective invocation and not the normal program | |
134 | // execution) all Throwables are caught here and | |
135 | // wrapped into a BuildException. | |
136 | 1 | throw new BuildException("the implementation class [" + clazz |
137 | + "] could not be instantiated, constructor invocation failed.", t); | |
138 | 4 | } |
139 | 4 | server.setAntTaskInfo(getAntTaskInfo()); |
140 | 4 | return server; |
141 | } | |
142 | ||
143 | /** | |
144 | * This method returns the server described by this element. | |
145 | * | |
146 | * @return the server described by this element | |
147 | */ | |
148 | public Server getServer() { | |
149 | 6 | return server; |
150 | } | |
151 | ||
152 | /** | |
153 | * This method sets the information about the current Ant project, task, etc. | |
154 | * | |
155 | * @param antTaskInfo the AntTaskInfo to be set | |
156 | * | |
157 | * @throws IllegalArgumentException if antTaskInfo is <tt>null</tt> | |
158 | */ | |
159 | public void setAntTaskInfo(final AntTaskInfo antTaskInfo) { | |
160 | 12 | if (antTaskInfo == null) { |
161 | 1 | throw new IllegalArgumentException("The parameter named [antTaskInfo] was null."); |
162 | } | |
163 | ||
164 | 11 | this.antTaskInfo = antTaskInfo; |
165 | 11 | } |
166 | ||
167 | /** | |
168 | * This method returns the information about the current Ant project, task, etc. | |
169 | * | |
170 | * @return the ant Task Info | |
171 | */ | |
172 | public AntTaskInfo getAntTaskInfo() { | |
173 | 17 | return antTaskInfo; |
174 | } | |
175 | ||
176 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |