001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.test.classloader.leak.test;
023:
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.io.InputStreamReader;
027: import java.io.StringWriter;
028: import java.net.HttpURLConnection;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.Set;
032:
033: import javax.management.MBeanServerConnection;
034: import javax.management.ObjectName;
035:
036: import org.apache.commons.httpclient.HttpClient;
037: import org.apache.commons.httpclient.methods.GetMethod;
038: import org.jboss.test.JBossTestCase;
039: import org.jboss.test.classloader.leak.clstore.ClassLoaderTrackerMBean;
040:
041: /**
042: * Abstract superclass of the EJB2 and EJB3 versions of the classloader leak
043: * tests.
044: *
045: * @author Brian Stansberry
046: */
047: public abstract class ClassloaderLeakTestBase extends JBossTestCase {
048: public static final String WEBAPP = "WEBAPP";
049: public static final String SERVLET = "SERVLET";
050: public static final String SERVLET_TCCL = "SERVLET_TCCL";
051: public static final String JSP = "JSP";
052: public static final String JSP_TCCL = "JSP_TCCL";
053:
054: public static final String[] WEB = new String[] { WEBAPP, SERVLET,
055: SERVLET_TCCL, JSP, JSP_TCCL };
056:
057: private static final Set<String> deployments = new HashSet<String>();
058:
059: private String baseURL = null;
060:
061: public ClassloaderLeakTestBase(String name) {
062: super (name);
063: }
064:
065: protected void setUp() throws Exception {
066: super .setUp();
067: cleanDeployments();
068:
069: for (int i = 0; i < WEB.length; i++)
070: removeClassLoader(WEB[i]);
071:
072: String[] ejbs = getEjbKeys();
073: for (int i = 0; i < ejbs.length; i++)
074: removeClassLoader(ejbs[i]);
075:
076: baseURL = "http://" + getServerHost() + ":8080/"
077: + getWarContextPath() + "/";
078: }
079:
080: protected void tearDown() throws Exception {
081: cleanDeployments();
082:
083: for (int i = 0; i < WEB.length; i++)
084: removeClassLoader(WEB[i]);
085:
086: String[] ejbs = getEjbKeys();
087: for (int i = 0; i < ejbs.length; i++)
088: removeClassLoader(ejbs[i]);
089:
090: super .tearDown();
091: }
092:
093: protected abstract String getWarContextPath();
094:
095: protected abstract String[] getEjbKeys();
096:
097: protected void cleanDeployments() throws Exception {
098: Iterator it = deployments.iterator();
099: while (it.hasNext()) {
100: undeployComponent((String) it.next(), false);
101: it = deployments.iterator();
102: }
103: }
104:
105: protected void undeployComponent(String deployment,
106: boolean propagateFailure) throws Exception {
107: try {
108: undeploy(deployment);
109: deployments.remove(deployment);
110: } catch (Exception e) {
111: if (propagateFailure)
112: throw e;
113: else {
114: log.error("Exception during undeploy of " + deployment,
115: e);
116: deployments.remove(deployment);
117: }
118: }
119: }
120:
121: private void deployComponent(String deployment) throws Exception {
122: deploy(deployment);
123: deployments.add(deployment);
124: }
125:
126: protected void warTest(String deployment) throws Exception {
127: // Ensure we are starting with a clean slate
128: checkCleanKeys(WEB);
129:
130: deployComponent(deployment);
131:
132: makeWebRequest(baseURL + "SimpleServlet", WEBAPP);
133: makeWebRequest(baseURL + "simple.jsp", WEBAPP);
134:
135: // Make sure the expected registrations were done
136: checkKeyRegistration(WEB);
137:
138: // This sleep is a workaround to JBAS-4060
139: sleep(500);
140:
141: undeployComponent(deployment, true);
142:
143: // TODO - probably not needed anymore; remove
144: flushSecurityCache("HsqlDbRealm");
145:
146: sleep(500);
147:
148: // Confirm the classloaders were released
149: String unregistered = checkClassLoaderRelease(WEB);
150:
151: if (unregistered.trim().length() > 0) {
152: fail("Classloaders unregistered: " + unregistered);
153: }
154: }
155:
156: protected void ejbTest(String deployment) throws Exception {
157: // Ensure we are starting with a clean slate
158: checkCleanKeys(getEjbKeys());
159:
160: deployComponent(deployment);
161:
162: makeEjbRequests();
163:
164: // Make sure the expected registrations were done
165: checkKeyRegistration(getEjbKeys());
166:
167: undeployComponent(deployment, true);
168:
169: // TODO - probably not needed anymore; remove
170: flushSecurityCache("HsqlDbRealm");
171:
172: sleep(500);
173:
174: // Confirm the classloaders were released
175: String unregistered = checkClassLoaderRelease(getEjbKeys());
176:
177: if (unregistered.length() > 0) {
178: fail("Classloaders unregistered: " + unregistered);
179: }
180: }
181:
182: protected void earTest(String deployment) throws Exception {
183: // Ensure we are starting with a clean slate
184: checkCleanKeys(WEB);
185: checkCleanKeys(getEjbKeys());
186:
187: deployComponent(deployment);
188:
189: // Simple web requests
190: makeWebRequest(baseURL + "simple.jsp", WEBAPP);
191: makeWebRequest(baseURL + "SimpleServlet", WEBAPP);
192:
193: // Make sure the expected registrations were done
194: checkKeyRegistration(WEB);
195:
196: // EJB related requests
197: makeWebRequest(baseURL + "ejb.jsp", "EJB");
198: makeWebRequest(baseURL + "EJBServlet", "EJB");
199:
200: makeEjbRequests();
201:
202: // Make sure the expected registrations were done
203: checkKeyRegistration(getEjbKeys());
204:
205: // This sleep is a workaround to JBAS-4060
206: sleep(500);
207:
208: undeployComponent(deployment, true);
209:
210: // TODO - probably not needed anymore; remove
211: flushSecurityCache("HsqlDbRealm");
212:
213: sleep(500);
214:
215: // Confirm the classloaders were released
216: String unregistered = checkClassLoaderRelease(WEB);
217:
218: unregistered += checkClassLoaderRelease(getEjbKeys());
219:
220: if (unregistered.trim().length() > 0) {
221: fail("Classloaders unregistered: " + unregistered);
222: }
223: }
224:
225: protected void checkCleanKeys(String[] keys) throws Exception {
226: for (int i = 0; i < keys.length; i++) {
227: if (hasClassLoader(keys[i]))
228: throw new IllegalStateException(
229: "Classloader already registered for " + keys[i]);
230: }
231: }
232:
233: protected void checkKeyRegistration(String[] keys) throws Exception {
234: for (int i = 0; i < keys.length; i++) {
235: assertTrue(keys[i] + " classloader registered",
236: hasClassLoader(keys[i]));
237: }
238: }
239:
240: protected String checkClassLoaderRelease(String[] keys)
241: throws Exception {
242: String faillist = "";
243: for (int i = 0; i < keys.length; i++) {
244: if (!hasClassLoaderBeenReleased(keys[i])) {
245: faillist += keys[i] + " ";
246: break; // don't check the others; don't want multiple reports
247: }
248: }
249:
250: return faillist;
251: }
252:
253: private boolean hasClassLoader(String key) throws Exception {
254: MBeanServerConnection adaptor = delegate.getServer();
255: ObjectName on = new ObjectName(
256: ClassLoaderTrackerMBean.OBJECT_NAME);
257: Object[] params = { key };
258: String[] signature = new String[] { String.class.getName() };
259: return ((Boolean) adaptor.invoke(on, "hasClassLoader", params,
260: signature)).booleanValue();
261: }
262:
263: private boolean hasClassLoaderBeenReleased(String key)
264: throws Exception {
265: MBeanServerConnection adaptor = delegate.getServer();
266: ObjectName on = new ObjectName(
267: ClassLoaderTrackerMBean.OBJECT_NAME);
268: Object[] params = { key };
269: String[] signature = new String[] { String.class.getName() };
270: return ((Boolean) adaptor.invoke(on,
271: "hasClassLoaderBeenReleased", params, signature))
272: .booleanValue();
273: }
274:
275: private void removeClassLoader(String key) throws Exception {
276: try {
277: MBeanServerConnection adaptor = delegate.getServer();
278: ObjectName on = new ObjectName(
279: ClassLoaderTrackerMBean.OBJECT_NAME);
280: Object[] params = { key };
281: String[] signature = new String[] { String.class.getName() };
282: adaptor.invoke(on, "removeClassLoader", params, signature);
283: } catch (Exception e) {
284: log.error(
285: "Caught exception removing classloader under key "
286: + key, e);
287: }
288: }
289:
290: private void flushSecurityCache(String domain) throws Exception {
291: log.debug("Flushing security cache " + domain);
292: MBeanServerConnection adaptor = delegate.getServer();
293: ObjectName on = new ObjectName(
294: ClassLoaderTrackerMBean.OBJECT_NAME);
295: Object[] params = { domain };
296: String[] signature = new String[] { String.class.getName() };
297: adaptor.invoke(on, "flushSecurityCache", params, signature);
298: }
299:
300: private void makeWebRequest(String url, String responseContent) {
301: HttpClient client = new HttpClient();
302: GetMethod method = new GetMethod(url);
303: int responseCode = 0;
304: try {
305: responseCode = client.executeMethod(method);
306:
307: assertTrue("Get OK with url: " + url + " responseCode: "
308: + responseCode,
309: responseCode == HttpURLConnection.HTTP_OK);
310:
311: InputStream rs = method.getResponseBodyAsStream();
312: InputStreamReader reader = new InputStreamReader(rs);
313: StringWriter writer = new StringWriter();
314: int c;
315: while ((c = reader.read()) != -1)
316: writer.write(c);
317:
318: String rsp = writer.toString();
319:
320: assertTrue("Response contains " + responseContent, rsp
321: .indexOf(responseContent) >= 0);
322: } catch (IOException e) {
323: e.printStackTrace();
324: fail("HttpClient executeMethod fails." + e.toString());
325: } finally {
326: method.releaseConnection();
327: }
328: }
329:
330: protected abstract void makeEjbRequests() throws Exception;
331: }
|