001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: /*
066: * PerfTests.java
067: *
068: * Copyright 1999, 2000, 2001 Jcorporate Ltd.
069: */
070: package com.jcorporate.expresso.ext.dbobj;
071:
072: import com.jcorporate.expresso.core.controller.ControllerRequest;
073: import com.jcorporate.expresso.core.db.DBException;
074: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
075: import com.jcorporate.expresso.core.dbobj.ValidValue;
076: import com.jcorporate.expresso.core.misc.ConfigManager;
077: import com.jcorporate.expresso.core.misc.DateTime;
078: import com.jcorporate.expresso.core.misc.StringUtil;
079: import org.apache.log4j.Logger;
080:
081: import java.io.IOException;
082: import java.io.InputStream;
083: import java.io.InputStreamReader;
084: import java.net.HttpURLConnection;
085: import java.net.MalformedURLException;
086: import java.net.URL;
087: import java.util.Hashtable;
088: import java.util.Iterator;
089: import java.util.List;
090: import java.util.Vector;
091:
092: /**
093: * PerfTests
094: * List of URL's to execute and time, along with statistics on their
095: * execution time.
096: *
097: * @author Michael Nash
098: */
099: public class PerfTests extends SecuredDBObject {
100: private static Vector httpValues = null;
101: private static Vector sessionValues = null;
102: private static Logger log = Logger.getLogger(PerfTests.class);
103:
104: /**
105: * Constructor
106: */
107: public PerfTests() throws DBException {
108: super ();
109: } /* PerfTests() */
110:
111: /**
112: * Use over (String) constructor. Initializes the object in the context
113: * of the user who's uid belongs to the parameter.
114: *
115: * @param uid the Uid of the user context
116: * @throws DBException if there's an initialization problem
117: */
118: public PerfTests(int uid) throws DBException {
119: super (uid);
120: }
121:
122: /**
123: * For using DBObjects within Controllers. Initializes based upon the current
124: * user and the requested db. [Of course this can be modified later]
125: *
126: * @param request - The controller request handed to you by the framework.
127: * @throws DBException if there's an initialization problem
128: */
129: public PerfTests(ControllerRequest request) throws DBException {
130: super (request);
131: }
132:
133: /**
134: * @param fieldName the name of the field
135: * @return java.lang.String
136: * @throws DBException upon error
137: */
138: public String getField(String fieldName) throws DBException {
139: if (fieldName.equals("AverageTime")) {
140: long totCounts = 0;
141:
142: try {
143: totCounts = new Long(getField("TestCount")).longValue();
144: } catch (NumberFormatException ne) {
145: totCounts = 0;
146: }
147:
148: long totTime = 0;
149:
150: try {
151: totTime = new Long(getField("TotalTime")).longValue();
152: } catch (NumberFormatException ne) {
153: totTime = 0;
154: }
155: if (totTime <= 0) {
156: return ("0");
157: } else {
158: return ("" + totTime / totCounts);
159: }
160: } else if (fieldName.equals("FailedTests")) {
161: long totCounts = 0;
162:
163: try {
164: totCounts = new Long(getField("TestCount")).longValue();
165: } catch (NumberFormatException ne) {
166: totCounts = 0;
167: }
168:
169: long successCount = 0;
170:
171: try {
172: successCount = new Long(getField("SuccessfulTests"))
173: .longValue();
174: } catch (NumberFormatException ne) {
175: successCount = 0;
176: }
177:
178: return ("" + (totCounts - successCount));
179: }
180:
181: return super .getField(fieldName);
182: } /* getField(String) */
183:
184: public Vector getValidValues(String fieldName) throws DBException {
185: if (fieldName.equals("HttpMethod")) {
186: if (httpValues == null) {
187: httpValues = new Vector();
188: httpValues.addElement(new ValidValue("GET", "GET"));
189: httpValues.addElement(new ValidValue("POST", "POST"));
190: }
191:
192: return httpValues;
193: } else if (fieldName.equals("GetSession")) {
194: if (sessionValues == null) {
195: sessionValues = new Vector();
196: sessionValues.addElement(new ValidValue("Y", "Yes"));
197: sessionValues.addElement(new ValidValue("N", "No"));
198: }
199:
200: return sessionValues;
201: }
202:
203: return super .getValidValues(fieldName);
204: } /* getValidValues(String) */
205:
206: /**
207: * Define the table and fields for this object
208: */
209: public void setupFields() throws DBException {
210: setTargetTable("PTESTS");
211: setDescription("DBptests");
212: setCharset("ISO-8859-1");
213: addField("TestNumber", "auto-inc", 0, false, "testNumber");
214: addField("URLToTest", "text", 0, false, "urlToTest");
215: addField("Descrip", "varchar", 80, false, "descriptionOfTest");
216: addField("NormTime", "int", 0, true, "normalTime");
217: addField("WarnTime", "int", 0, true, "warningTime");
218: addField("MaxTime", "int", 0, true, "maxTime");
219: addField("LastTime", "int", 0, true, "lastRunTime");
220: addField("TestCount", "int", 0, true, "nofRuns");
221: addField("TotalTime", "int", 0, true, "totalTimeAllRuns");
222: addVirtualField("AverageTime", "int", 0, "avgTimeAllRuns");
223: addField("ExpectString", "text", 0, true, "expectText");
224: addField("SuccessfulTests", "int", 0, true, "successfulTests");
225: addVirtualField("FailedTests", "int", 0, "failedTests");
226: addField("LastTestSucceeded", "char", 1, true,
227: "lastTestSucceeded");
228: addField("LastRun", "datetime", 0, true, "testLastRunOn");
229: addField("LastFailureReason", "text", 0, true,
230: "reasonForLastFailure");
231: addField("HttpMethod", "char", 10, false, "httpMethod");
232: addField("GetSession", "char", 1, false, "getSession");
233: this .getJDBCMetaData().setAttribute("GetSession", "checkbox",
234: "Y");
235: setStringFilter("URLToTest", "rawFilter");
236: setStringFilter("ExpectString", "rawFilter");
237: addKey("TestNumber");
238:
239: /* setReadOnly("TestNumber");
240:
241: setReadOnly("LastTime");
242:
243: setReadOnly("SuccessfulTests");
244:
245: setReadOnly("LastRun");
246:
247: setReadOnly("LastTestSucceeded");
248:
249: setReadOnly("TotalTime");
250:
251: setReadOnly("TestCount"); */
252: setMultiValued("HttpMethod");
253: setMultiValued("GetSession");
254: } /* setupFields() */
255:
256: /**
257: * Run the current test
258: *
259: * @param currentSessionId ?
260: * @return PerfTestResult
261: */
262: public PerfTestResult run(String currentSessionId)
263: throws DBException {
264: PerfTestResult myResult = new PerfTestResult();
265: URL myUrl = null;
266: HttpURLConnection c;
267: String reason = "";
268: boolean failed = false;
269: String urlString = ConfigManager
270: .expandValue(getField("URLToTest"));
271:
272: if (currentSessionId != null) {
273: try {
274: URL myURL = new URL(urlString);
275: String queryPart = StringUtil.notNull(myURL.getQuery());
276: String pathPart = myURL.getPath();
277: int port = myURL.getPort();
278: String protocol = myURL.getProtocol();
279: String hostPart = myURL.getHost();
280:
281: /*System.out.println("PATH:" + pathPart);
282:
283: System.out.println("Query:" + queryPart);
284:
285: System.out.println("Protocol:" + protocol);
286:
287: System.out.println("Host:" + hostPart); */
288:
289: //System.exit(1);
290: urlString = protocol + "://" + hostPart + ":" + port
291: + pathPart + ";jsessionid=" + currentSessionId;
292:
293: if (!queryPart.equals("")) {
294: urlString = urlString + "?" + queryPart;
295: }
296:
297: //System.out.println("New URL:" + urlString);
298: log.info("Session was established: new URL '"
299: + urlString + "'");
300: } catch (MalformedURLException me) {
301: throw new DBException(me);
302: }
303: }
304:
305: long runTime = 0;
306: String encodedURL = null;
307:
308: try {
309: encodedURL = urlString; //URLEncoder.encode(urlString);
310:
311: if (encodedURL == null) {
312: throw new IllegalArgumentException(
313: "Unable to encode URL '" + urlString + "'");
314: }
315:
316: myUrl = new URL(encodedURL);
317:
318: if (myUrl == null) {
319: throw new IllegalArgumentException(
320: "Unable to encode URL '" + urlString + "'");
321: }
322: } catch (MalformedURLException m) {
323: m.printStackTrace(System.out);
324: throw new IllegalArgumentException("URL '" + urlString
325: + "' is not valid.");
326: }
327: try {
328: c = (HttpURLConnection) myUrl.openConnection();
329:
330: if (c == null) {
331: throw new IllegalArgumentException(
332: "No connection established to '" + urlString
333: + "'");
334: }
335:
336: c.setDoOutput(true);
337: HttpURLConnection.setFollowRedirects(true);
338: c.setAllowUserInteraction(true);
339: c.setRequestMethod(getField("HttpMethod"));
340:
341: /* Now listen for the answer */
342: boolean printme = false;
343: InputStream is = null;
344:
345: try {
346: is = c.getInputStream();
347: } catch (IOException ie) {
348: is = c.getErrorStream();
349: printme = true;
350:
351: if (is == null) {
352: System.out
353: .println("No input or error stream from URL '"
354: + encodedURL + "'");
355: } else {
356: System.out.println("Got error stream");
357: }
358: try {
359: int responseCode = c.getResponseCode();
360: System.out.println("Response code:" + responseCode);
361: } catch (Exception ee) {
362: System.out.println("No response code available:"
363: + ee.getMessage());
364: ee.printStackTrace(System.out);
365: }
366:
367: //System.out.println("Response code:" + c.getResponseCode());
368: //System.out.println("Response message:" + StringUtil.notNull(c.getResponseMessage()));
369: }
370: if (is == null) {
371: throw new IllegalArgumentException(
372: "No input or error stream returned");
373: }
374:
375: InputStreamReader dis = new InputStreamReader(is);
376: long startTime = System.currentTimeMillis();
377: URLReader ur = new URLReader(dis, getField("ExpectString"),
378: printme);
379:
380: if (getField("GetSession").equals("Y")) {
381: ur.setRequireSession(true);
382: }
383:
384: ur.start();
385:
386: long maxMillis = 0;
387:
388: try {
389: maxMillis = new Long(getField("MaxTime")).longValue();
390: } catch (NumberFormatException ne) {
391: maxMillis = 0;
392: }
393: if (maxMillis == 0) {
394: maxMillis = 99999;
395: }
396:
397: ur.join(maxMillis);
398:
399: boolean success = ur.completedSuccessfully();
400: long endTime = System.currentTimeMillis();
401: runTime = endTime - startTime;
402: myResult.setRunTime(runTime);
403:
404: Hashtable allUsers = ConfigManager.getCurrentLogins();
405: myResult.setCurrentUsers(allUsers.size());
406:
407: if (success) {
408:
409: /* PerfTestStat myStat = new PerfTestStat();
410:
411: myStat.setDBName(getDBName());
412:
413: myStat.setField("UserCount", "" + allUsers.size());
414:
415: myStat.setField("TestNumber", getField("TestNumber"));
416:
417: myStat.setField("RunWhen", DateTime.getDateTimeForDB());
418:
419: myStat.setField("RunTime", new Long(runTime).toString());
420:
421: try {
422:
423: myStat.add();
424:
425: } catch (DBException de) {
426:
427: log.error("Unable to log test run statistic:", de);
428:
429: } */
430: }
431: if (getField("GetSession").equals("Y")) {
432: currentSessionId = ur.getSessionId();
433: myResult.setSessionId(currentSessionId);
434: currentSessionId = myResult.getSessionId();
435: log.info("Logged in with session id '"
436: + currentSessionId + "'");
437:
438: if (currentSessionId == null) {
439: reason = "No jsessionid (Session ID) found in output";
440: failed = true;
441: }
442: }
443: if (!success) {
444: failed = true;
445: reason = ur.getFailureReason();
446: }
447: } /* try */catch (Exception io) {
448: log.error("I/O Error:", io);
449: io.printStackTrace(System.out);
450: reason = "I/O Error communicating with server:"
451: + io.getMessage();
452: failed = true;
453: }
454: if (failed) {
455: setField("LastTestSucceeded", "N");
456: setField("LastFailureReason", reason);
457: } else {
458: setField("LastTestSucceeded", "Y");
459: addToField("SuccessfulTests", 1);
460: }
461:
462: addToField("TestCount", 1);
463: addToField("TotalTime", runTime);
464: setField("LastTime", "" + runTime);
465: setField("LastRun", DateTime.getDateTimeForDB(this
466: .getDataContext()));
467: setCheckZeroUpdate(false);
468: update();
469:
470: /* Prepare result */
471: long lastTime = 0;
472: StringBuffer detailMessage = new StringBuffer();
473:
474: if (getField("LastTestSucceeded").equals("N")) {
475: myResult.setFailureCount(1);
476: detailMessage.append("\nERROR: Test "
477: + getField("TestNumber") + " ("
478: + getField("Descrip") + ") for URL '"
479: + getField("URLToTest")
480: + "' failed. Reason reported was '"
481: + getField("LastFailureReason") + "'\n");
482: } else {
483: lastTime = getFieldLong("LastTime");
484:
485: if (lastTime > getFieldLong("WarnTime")) {
486: myResult.setWarningCount(1);
487: detailMessage
488: .append("\nWARNING: Test "
489: + getField("TestNumber")
490: + " ("
491: + getField("Descrip")
492: + ") for URL '"
493: + getField("URLToTest")
494: + "' responded slower than it's set warning time of "
495: + getField("WarnTime")
496: + " milliseconds. It ran in "
497: + getField("LastTime")
498: + " milliseconds.\n");
499: } else if (lastTime > getFieldLong("NormTime")) {
500: myResult.setCautionCount(1);
501: detailMessage
502: .append("\nCAUTION: Test "
503: + getField("TestNumber")
504: + " ("
505: + getField("Descrip")
506: + ") for URL '"
507: + getField("URLToTest")
508: + "' responded slower than it's set normal time of "
509: + getField("NormTime")
510: + " milliseconds. It ran in "
511: + getField("LastTime")
512: + " milliseconds.\n");
513: }
514: }
515:
516: myResult.setMessage(detailMessage.toString());
517:
518: return myResult;
519: } /* run() */
520:
521: /**
522: * @param fieldName name of the field
523: * @param valueToAdd value for the field
524: * @throws DBException upon error
525: */
526: private void addToField(String fieldName, long valueToAdd)
527: throws DBException {
528: long currentValue = 0;
529:
530: try {
531: currentValue = new Long(getField(fieldName)).longValue();
532: } catch (NumberFormatException ne) {
533: throw new DBException("Unable to add to field '"
534: + fieldName + "', current value of '"
535: + getField(fieldName) + "' is not a number.");
536: }
537:
538: currentValue = currentValue + valueToAdd;
539: setField(fieldName, "" + currentValue);
540: } /* addToField(String, long) */
541:
542: /**
543: * Run all defined tests
544: *
545: * @param dbName database context
546: * @param currentSessionId where to store the results
547: * @return PerfTestResult
548: * @throws DBException upon error
549: */
550: public static PerfTestResult runAll(String dbName,
551: String currentSessionId) throws DBException {
552: PerfTests tl = new PerfTests();
553: tl.setDataContext(dbName);
554:
555: PerfTestResult overallResult = new PerfTestResult();
556: PerfTestResult oneResult = null;
557: PerfTests oneTest = null;
558:
559: List list = tl.searchAndRetrieveList();
560: for (Iterator iterator = list.iterator(); iterator.hasNext();) {
561: oneTest = (PerfTests) iterator.next();
562: oneResult = oneTest.run(currentSessionId);
563: overallResult.add(oneResult);
564: }
565:
566: return overallResult;
567: } /* runAll(String) */
568:
569: /**
570: * Run all defined tests
571: *
572: * @param dbName database context
573: * @param setNumber the 'id' of the test set
574: * @param currentSessionId ?
575: * @return PerfTestResult
576: */
577: public static PerfTestResult runSet(String dbName,
578: String setNumber, String currentSessionId)
579: throws DBException {
580: PerfTestResult overallResult = new PerfTestResult();
581: PerfTestResult oneResult = null;
582: PerfTestSet ps = new PerfTestSet();
583: ps.setDataContext(dbName);
584: ps.setField("SetNumber", setNumber);
585: ps.retrieve();
586:
587: PerfTestSetDet psd = new PerfTestSetDet();
588: psd.setDataContext(dbName);
589: psd.setField("SetNumber", setNumber);
590:
591: PerfTestSetDet oneDet = null;
592: PerfTests oneTest = new PerfTests();
593: oneTest.setDataContext(dbName);
594:
595: List list = psd.searchAndRetrieveList("SequenceNumber");
596: for (Iterator iterator = list.iterator(); iterator.hasNext();) {
597: oneDet = (PerfTestSetDet) iterator.next();
598: oneTest.setField("TestNumber", oneDet
599: .getField("TestNumber"));
600: oneTest.retrieve();
601: oneResult = oneTest.run(currentSessionId);
602:
603: if (currentSessionId == null) {
604: currentSessionId = oneResult.getSessionId();
605: overallResult.setSessionId(currentSessionId);
606: log.info("Test " + oneDet.getField("TestNumber")
607: + " logged in - session id now '"
608: + currentSessionId + "'");
609: }
610:
611: overallResult.add(oneResult);
612: }
613:
614: return overallResult;
615: } /* runSet(String, String) */
616:
617: /**
618: * Read from the specified URL, looking for the "ExpectString". If you find it,
619: * return true, if not - return false
620: *
621: * @param dis
622: * @throws DBException
623: * @throws IOException
624: * @return
625: */
626: // private boolean readFromStream(DataInputStream dis)
627: // throws DBException, IOException {
628: // boolean returnVal = false;
629: //
630: // if (dis == null) {
631: // throw new DBException("No connection to server:DataInputStream dis is null");
632: // }
633: //
634: // //System.out.println(myName + ":Bytes available from stream:"
635: // // + dis.available());
636: // int linesRead = 0;
637: //
638: // //System.out.println(myName + ":Reading line");
639: // String OneLine = dis.readLine();
640: //
641: // if (OneLine.indexOf(getField("ExpectString")) > 0) {
642: // returnVal = true;
643: // }
644: // //System.out.println("Read (initial) from server:" + OneLine);
645: // if (OneLine == null) {
646: // throw new DBException("Server never sent EOF");
647: // }
648: //
649: // String oneValue = ("");
650: // String oneKey = ("");
651: //
652: // while (OneLine != null) {
653: // if (OneLine.indexOf(getField("ExpectString")) > 0) {
654: // returnVal = true;
655: // }
656: // if (!OneLine.equals("")) {
657: // linesRead++;
658: // } /* if */
659: //
660: //
661: // OneLine = dis.readLine();
662: // } /* while */
663: //
664: //
665: // dis.close();
666: //
667: // //Log.log(myName, "Read " + linesRead + " lines from server", "");
668: // return returnVal;
669: // } /* readFromStream(DataInputStream) */
670:
671: } /* PerfTests */
|