0001: /*
0002: * MCS Media Computer Software Copyright (c) 2005 by MCS
0003: * -------------------------------------- Created on 23.04.2005 by w.klaas
0004: *
0005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
0006: * use this file except in compliance with the License. You may obtain a copy of
0007: * the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0014: * License for the specific language governing permissions and limitations under
0015: * the License.
0016: */
0017: package de.mcs.jmeasurement;
0018:
0019: import java.io.ByteArrayInputStream;
0020: import java.io.ByteArrayOutputStream;
0021: import java.io.IOException;
0022: import java.io.ObjectInputStream;
0023: import java.io.ObjectOutputStream;
0024: import java.lang.ref.Reference;
0025: import java.lang.ref.ReferenceQueue;
0026: import java.lang.ref.SoftReference;
0027: import java.text.SimpleDateFormat;
0028: import java.util.ArrayList;
0029: import java.util.Date;
0030: import java.util.HashMap;
0031: import java.util.Map;
0032:
0033: import org.xml.sax.SAXException;
0034: import org.xml.sax.helpers.AttributesImpl;
0035:
0036: import com.megginson.sax.DataWriter;
0037:
0038: import de.mcs.utils.StringUtils;
0039: import de.mcs.utils.codecs.Base64;
0040:
0041: /**
0042: * This is the implementing class of a measure point. This class stores all the
0043: * measured data.
0044: *
0045: * @author w.klaas
0046: */
0047: public class DefaultMeasurePoint implements MeasurePoint {
0048: /** key for the getData and setData methodes. */
0049: public static final String DATA_KEY_USER_DATA = "userData";
0050:
0051: /**
0052: * key for the getData and setData methodes.
0053: *
0054: * @since 0.64
0055: */
0056: public static final String DATA_KEY_EXCEPTION_LIST = "exceptionList";
0057:
0058: /**
0059: * key for the getData and setData methodes.
0060: *
0061: * @since 0.64
0062: */
0063: public static final String DATA_KEY_EXCEPTION_COUNT = "exceptionCount";
0064:
0065: /** key for the getData and setData methodes. */
0066: public static final String DATA_KEY_LAST_ACTIVATION = "lastActivation";
0067:
0068: /** key for the getData and setData methodes. */
0069: public static final String DATA_KEY_DEATH_COUNT = "deathCount";
0070:
0071: /** key for the getData and setData methodes. */
0072: public static final String DATA_KEY_MAX_ACTIVE = "maxActive";
0073:
0074: /** key for the getData and setData methodes. */
0075: public static final String DATA_KEY_ACTIVE = "active";
0076:
0077: /** key for the getData and setData methodes. */
0078: public static final String DATA_KEY_MAX_MSEC = "maxMSec";
0079:
0080: /** key for the getData and setData methodes. */
0081: public static final String DATA_KEY_MIN_MSEC = "minMSec";
0082:
0083: /** key for the getData and setData methodes. */
0084: public static final String DATA_KEY_TOTAL_MSEC = "totalMSec";
0085:
0086: /** key for the getData and setData methodes. */
0087: public static final String DATA_KEY_AVERAGE_MSEC = "averageMSec";
0088:
0089: /**
0090: * key for the getData and setData methodes. *
0091: *
0092: * @since 0.65
0093: */
0094: public static final String DATA_KEY_DEVIATION = "deviation";
0095:
0096: /** key for the getData and setData methodes. */
0097: public static final String DATA_KEY_ACCESS_COUNT = "accessCount";
0098:
0099: /** key for the getData and setData methodes. */
0100: public static final String DATA_KEY_PRIORITY = "priority";
0101:
0102: /** key for the getData and setData methodes. */
0103: public static final String DATA_KEY_POINT_NAME = "pointName";
0104:
0105: /** key for the getData and setData methodes. */
0106: private static final String DATA_KEY_SQUARESUM = "squaresum";
0107:
0108: /** default buffer size. */
0109: private static final int BUFFER_SIZE = 1024;
0110:
0111: /** default arraylist size. */
0112: private static final int DEFAULT_ARRAY_SIZE = 10;
0113:
0114: /** hashmap default init. */
0115: private static final int DEFAULT_MEASURE_POINT_COUNT = 100;
0116:
0117: /** serial id. Do not change manually. */
0118: private static final long serialVersionUID = -3842886735720219978L;
0119:
0120: /** date formatter needed for this. */
0121: private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat();
0122:
0123: /** how often is this point accessed. */
0124: private long accessCount;
0125:
0126: /** average time of all accesses. */
0127: private long averageMSec;
0128:
0129: /** total time of all measurements. */
0130: private long totalMSec;
0131:
0132: /** minimal time of all measurements. */
0133: private long minMSec;
0134:
0135: /** maxmimal time of all measurements. */
0136: private long maxMSec;
0137:
0138: /** number of actual active monitors. */
0139: private volatile long active;
0140:
0141: /** maxmimal time of all measurements. */
0142: private long maxActive;
0143:
0144: /** count of all death monitors. */
0145: private long deathMonitors;
0146:
0147: /** last activation of the start() methode. */
0148: private Date lastActivation;
0149:
0150: /** maxmimal time of all measurements. */
0151: private IUserData userData;
0152:
0153: /** full qualified name of this point. */
0154: private String pointName;
0155:
0156: /** priority of this point. */
0157: private int priority;
0158:
0159: /**
0160: * square summm of all measure points data.
0161: *
0162: * @since 0.65
0163: */
0164: private double squareSumm;
0165:
0166: /**
0167: * exception counter for proxy use.
0168: *
0169: * @since 0.64
0170: */
0171: private long exceptionCount;
0172:
0173: /**
0174: * list of all exception descriptions.
0175: *
0176: * @since 0.64
0177: */
0178: private ArrayList<String> exceptionList;
0179:
0180: /** callback function of this measurepoint. */
0181: private transient MeasureDataCallback measureDataCallback;
0182:
0183: /** monitor map with softreferences. */
0184: private HashMap<String, Reference> hmMonitors;
0185:
0186: /** id of the last monitor. */
0187: private long monitorId;
0188:
0189: /** the reference queue. */
0190: private transient ReferenceQueue<Monitor> q;
0191:
0192: /** last deviation calculated. */
0193: private float deviation;
0194:
0195: /** optional settings for this point. */
0196: private transient JMConfig config;
0197:
0198: /** calculating the deviation of every monitor. */
0199: private boolean bCalculationDeviation;
0200:
0201: /**
0202: * This class is our class to reference all monitors. If the garbage
0203: * collector removes a monitor we will notice it with the referenceQueue.
0204: *
0205: * @author w.klaas
0206: */
0207: private static final class SoftEntry<T> extends SoftReference<T> {
0208: /** our key in the hashmap to find this Monitor. */
0209: private Object key;
0210:
0211: /**
0212: * Our Constructor, who will store the key into an internal field. All
0213: * other parameter will be handed over to the constructor of the
0214: * SoftReference.
0215: *
0216: * @param aKey
0217: * the key in our hashmap
0218: * @param value
0219: * the monitor object
0220: * @param aQ
0221: * the referenceQueue
0222: */
0223: private SoftEntry(final Object aKey, final T value,
0224: final ReferenceQueue<? super T> aQ) {
0225: super (value, aQ);
0226: this .key = aKey;
0227: }
0228: }
0229:
0230: /**
0231: * create a new measurement point with the name pointName. Priority is set
0232: * to 0.
0233: *
0234: * @param name
0235: * name of this measurement point
0236: * @param aOptions
0237: * options for this point
0238: */
0239: public DefaultMeasurePoint(final String name,
0240: final JMConfig aOptions) {
0241: pointName = name;
0242: priority = 0;
0243: accessCount = 0;
0244: averageMSec = 0;
0245: totalMSec = 0;
0246: minMSec = 0;
0247: maxMSec = 0;
0248: active = 0;
0249: maxActive = 0;
0250: deathMonitors = 0;
0251: userData = null;
0252: monitorId = 0;
0253: q = new ReferenceQueue<Monitor>();
0254: hmMonitors = new HashMap<String, Reference>(
0255: DEFAULT_MEASURE_POINT_COUNT);
0256: exceptionCount = 0;
0257: exceptionList = new ArrayList<String>(
0258: DEFAULT_MEASURE_POINT_COUNT);
0259: squareSumm = 0.0;
0260: bCalculationDeviation = true;
0261: if (aOptions != null) {
0262: config = aOptions;
0263: processOptions();
0264: }
0265: }
0266:
0267: /**
0268: * create a new measurement point with the name pointName. Priority is set
0269: * to aPriority.
0270: *
0271: * @param name
0272: * name of this measurement point
0273: * @param aPriority
0274: * priority of this point
0275: * @param aOptions
0276: * options for this point
0277: */
0278: public DefaultMeasurePoint(final String name, final int aPriority,
0279: final JMConfig aOptions) {
0280: this (name, aOptions);
0281: priority = aPriority;
0282: }
0283:
0284: /**
0285: * @see de.mcs.jmeasurement.MeasurePoint#getMonitor()
0286: * @return Monitor getting a new monitor for this measure point
0287: */
0288: public final Monitor getMonitor() {
0289: // process list of all death monitors
0290: processQueue();
0291: Monitor monitor;
0292: synchronized (this ) {
0293: monitorId++;
0294: monitor = new DefaultMonitor(this , Long.toString(monitorId));
0295: }
0296: return monitor;
0297: }
0298:
0299: /**
0300: * @see de.mcs.jmeasurement.MeasurePoint#start()
0301: * @return Monitor Getting an monitor for this measurepoint and start it.
0302: */
0303: public final Monitor start() {
0304: // process list of all death monitors
0305: processQueue();
0306: Monitor monitor = getMonitor();
0307: monitor.start();
0308: return monitor;
0309: }
0310:
0311: /**
0312: * one monitor has to be activated.
0313: *
0314: * @param monitor
0315: * the monitor that has been activated
0316: */
0317: public final void activateMonitor(final Monitor monitor) {
0318: synchronized (this ) {
0319: active++;
0320: if (active > maxActive) {
0321: maxActive = active;
0322: }
0323: lastActivation = new Date();
0324: // we add this monitor as SoftReference to our list of monitors
0325: Reference ref = new SoftEntry<Monitor>(monitor
0326: .getMonitoId(), monitor, q);
0327: hmMonitors.put(monitor.getMonitoId(), ref);
0328: }
0329: }
0330:
0331: /**
0332: * @see de.mcs.jmeasurement.MeasurePoint#getName()
0333: * @return String Fully qualified name of this MeasurePoint.
0334: */
0335: public final String getName() {
0336: return pointName;
0337: }
0338:
0339: /**
0340: * @see de.mcs.jmeasurement.MeasurePoint#getPriority()
0341: * @return int Getting the priority of this MeasurePoint
0342: */
0343: public final int getPriority() {
0344: return priority;
0345: }
0346:
0347: /**
0348: * @see de.mcs.jmeasurement.MeasurePoint#setPriority(int)
0349: * @param aPriority
0350: * Setting the priority of this MeasurePoint
0351: */
0352: public final void setPriority(final int aPriority) {
0353: this .priority = aPriority;
0354: }
0355:
0356: /**
0357: * @see de.mcs.jmeasurement.MeasurePoint#processMonitor(de.mcs.jmeasurement.Monitor)
0358: * @param monitor
0359: * the monitor to add the values to
0360: */
0361: public final void processMonitor(final Monitor monitor) {
0362: if (null != measureDataCallback) {
0363: measureDataCallback.setMonitor(this , monitor);
0364: }
0365: long accrued = monitor.getAccrued();
0366: synchronized (this ) {
0367: active--;
0368: accessCount++;
0369: totalMSec += accrued;
0370: averageMSec = totalMSec / accessCount;
0371: if (accrued > maxMSec) {
0372: maxMSec = accrued;
0373: }
0374: if ((accrued < minMSec) || (minMSec == 0)) {
0375: minMSec = accrued;
0376: }
0377: if (monitor.hasException()) {
0378: exceptionCount++;
0379: String exceptionText = monitor.getException();
0380: if ((null != exceptionText)
0381: && (!exceptionText.equals(""))) {
0382: exceptionList.add(monitor.getException());
0383: }
0384: }
0385: if (bCalculationDeviation) {
0386: squareSumm += Math.pow(accrued, 2);
0387: }
0388: // now we must delete this monitor from our reference list
0389: if (hmMonitors.containsKey(monitor.getMonitoId())) {
0390: hmMonitors.remove(monitor.getMonitoId());
0391: }
0392: }
0393: // process list of all death monitors
0394: processQueue();
0395: }
0396:
0397: /** Processing the softreference queue. */
0398: private void processQueue() {
0399: Reference r;
0400: synchronized (this ) {
0401: while ((r = q.poll()) != null) {
0402: SoftEntry e = (SoftEntry) r;
0403: if (hmMonitors.containsKey(e.key)) {
0404: // if this key is in our monitor list, the monitor was not
0405: // stopped with stop().
0406: active--;
0407: deathMonitors++;
0408: hmMonitors.remove(e.key);
0409: }
0410: }
0411: }
0412: }
0413:
0414: /**
0415: * @return Returns the userData.
0416: */
0417: public final IUserData getUserData() {
0418: return userData;
0419: }
0420:
0421: /**
0422: * @param aUserData
0423: * The userData to set.
0424: */
0425: public final void setUserData(final IUserData aUserData) {
0426: this .userData = aUserData;
0427: }
0428:
0429: /**
0430: * Getting the data values of this measure point. <br>
0431: * The following data value are present: <table border="1"> <tbody>
0432: * <tr>
0433: * <td>name</td>
0434: * <td>type of value</td>
0435: * <td>description</td>
0436: * </tr>
0437: * <tr>
0438: * <td>pointName</td>
0439: * <td>String</td>
0440: * <td>full qualified name of this point</td>
0441: * </tr>
0442: * <tr>
0443: * <td>priority</td>
0444: * <td>Integer</td>
0445: * <td>priority of this point</td>
0446: * </tr>
0447: * <tr>
0448: * <td>accessCount</td>
0449: * <td>Long</td>
0450: * <td>how often is this point accessed</td>
0451: * </tr>
0452: * <tr>
0453: * <td>averageMSec</td>
0454: * <td>Long</td>
0455: * <td>average time of all accesses</td>
0456: * </tr>
0457: * <tr>
0458: * <td>totalMSec</td>
0459: * <td>Long</td>
0460: * <td>total time of all measurements</td>
0461: * </tr>
0462: * <tr>
0463: * <td>minMSec</td>
0464: * <td>Long</td>
0465: * <td>minimal time of all measurements</td>
0466: * </tr>
0467: * <tr>
0468: * <td>maxMSec</td>
0469: * <td>Long</td>
0470: * <td>maxmimal time of all measurements</td>
0471: * </tr>
0472: * <tr>
0473: * <td>active</td>
0474: * <td>Long</td>
0475: * <td>number of actual active monitors</td>
0476: * </tr>
0477: * <tr>
0478: * <td>maxActive</td>
0479: * <td>Long</td>
0480: * <td>maxmimal time of all measurements</td>
0481: * </tr>
0482: * <tr>
0483: * <td>deathCount</td>
0484: * <td>Long</td>
0485: * <td>counting of all death monitors</td>
0486: * </tr>
0487: * <tr>
0488: * <td>lastActivation</td>
0489: * <td>Date</td>
0490: * <td>last activation of the measure point</td>
0491: * </tr>
0492: * <tr>
0493: * <tr>
0494: * <td>deviation</td>
0495: * <td>Float</td>
0496: * <td>standard deviation of all measurements (if activate)</td>
0497: * </tr>
0498: * <td>exceptionCount</td>
0499: * <td>Long</td>
0500: * <td>count of exceptions, only set in use with proxies</td>
0501: * </tr>
0502: * <tr>
0503: * <td>exceptionList</td>
0504: * <td>String[]</td>
0505: * <td>list of all exceptions</td>
0506: * </tr>
0507: * <tr>
0508: * <td>userData</td>
0509: * <td>Object</td>
0510: * <td>user data storage of this point</td>
0511: * </tr>
0512: * </tbody></table>
0513: *
0514: * @see de.mcs.jmeasurement.MeasurePoint#getData()
0515: * @return Array of MeasureData objects
0516: */
0517: public final MeasureData[] getData() {
0518: // process list of all death monitors
0519: processQueue();
0520: ArrayList<MeasureData> datas = new ArrayList<MeasureData>(
0521: DEFAULT_ARRAY_SIZE);
0522: synchronized (this ) {
0523: MeasureData data;
0524:
0525: data = new MeasureData(DATA_KEY_POINT_NAME, String.class,
0526: pointName, null,
0527: "full qualified name of this point");
0528: datas.add(data);
0529:
0530: data = new MeasureData(DATA_KEY_PRIORITY, Integer.class,
0531: Integer.valueOf(priority), Integer
0532: .toString(priority),
0533: "priority of this point");
0534: datas.add(data);
0535:
0536: data = new MeasureData(DATA_KEY_ACCESS_COUNT, Long.class,
0537: Long.valueOf(accessCount), Long
0538: .toString(accessCount),
0539: "how often is this point accessed");
0540: datas.add(data);
0541:
0542: data = new MeasureData(DATA_KEY_AVERAGE_MSEC, Long.class,
0543: Long.valueOf(averageMSec), Long
0544: .toString(averageMSec),
0545: "average time of all accesses");
0546: datas.add(data);
0547:
0548: data = new MeasureData(DATA_KEY_TOTAL_MSEC, Long.class,
0549: Long.valueOf(totalMSec), Long.toString(totalMSec),
0550: "total time of all measurements");
0551: datas.add(data);
0552:
0553: data = new MeasureData(DATA_KEY_MIN_MSEC, Long.class, Long
0554: .valueOf(minMSec), Long.toString(minMSec),
0555: "minimal time of all measurements");
0556: datas.add(data);
0557:
0558: data = new MeasureData(DATA_KEY_MAX_MSEC, Long.class, Long
0559: .valueOf(maxMSec), Long.toString(maxMSec),
0560: "maxmimal time of all measurements");
0561: datas.add(data);
0562:
0563: data = new MeasureData(DATA_KEY_ACTIVE, Long.class, Long
0564: .valueOf(active), Long.toString(active),
0565: "number of actual active monitors");
0566: datas.add(data);
0567:
0568: data = new MeasureData(DATA_KEY_MAX_ACTIVE, Long.class,
0569: Long.valueOf(maxActive), Long.toString(maxActive),
0570: "maxmimal time of all measurements");
0571: datas.add(data);
0572:
0573: data = new MeasureData(DATA_KEY_DEATH_COUNT, Long.class,
0574: Long.valueOf(deathMonitors), Long
0575: .toString(deathMonitors),
0576: "counting of all death monitors");
0577: datas.add(data);
0578:
0579: Date activation = new Date(0L);
0580: if (lastActivation != null) {
0581: activation = lastActivation;
0582: }
0583: data = new MeasureData(DATA_KEY_LAST_ACTIVATION,
0584: Date.class, activation,
0585: "no call has been executed.",
0586: "last activation of the measure point");
0587: if (null != lastActivation) {
0588: try {
0589: data.setAsString(SIMPLE_DATE_FORMAT
0590: .format(lastActivation));
0591: } catch (Exception e) {
0592: // nothing to do here
0593: }
0594: }
0595: datas.add(data);
0596:
0597: Float mydeviation = getDeviation();
0598: data = new MeasureData(DATA_KEY_DEVIATION, Float.class,
0599: mydeviation, mydeviation.toString(),
0600: "standard deviation of all measurements.");
0601: datas.add(data);
0602:
0603: data = new MeasureData(DATA_KEY_SQUARESUM, Double.class,
0604: new Double(squareSumm),
0605: Double.toString(squareSumm),
0606: "square sum of all measurements.");
0607: datas.add(data);
0608:
0609: data = new MeasureData(DATA_KEY_EXCEPTION_COUNT,
0610: Long.class, Long.valueOf(exceptionCount), Long
0611: .toString(exceptionCount),
0612: "counting of all exceptions, thrown in a proxy.");
0613: datas.add(data);
0614:
0615: String[] exceptions = (String[]) exceptionList
0616: .toArray(new String[0]);
0617: data = new MeasureData(DATA_KEY_EXCEPTION_LIST,
0618: String[].class, exceptions, StringUtils
0619: .arrayToCSVString(exceptions, ',', '"'),
0620: "all exceptions as plaint text, stacktrace is desired.");
0621: datas.add(data);
0622:
0623: data = new MeasureData(DATA_KEY_USER_DATA, String.class,
0624: userData, "", "user data storage of this point");
0625: if (null != userData) {
0626: data.setAsString(userData.toString());
0627: }
0628: datas.add(data);
0629: }
0630: return (MeasureData[]) datas.toArray(new MeasureData[0]);
0631: }
0632:
0633: /**
0634: * @return Float standard deviation of the measurement.
0635: *
0636: * @since 0.65
0637: */
0638: private Float getDeviation() {
0639: if (bCalculationDeviation) {
0640: if (accessCount < 2) {
0641: return new Float(0.0);
0642: } else {
0643: if (squareSumm == 0) {
0644: return new Float(deviation);
0645: }
0646: double dev = Math
0647: .sqrt(((accessCount * squareSumm) - Math.pow(
0648: totalMSec, 2))
0649: / (accessCount * (accessCount - 1)));
0650: deviation = (float) dev;
0651: return new Float(dev);
0652: }
0653: } else {
0654: return new Float(0.0);
0655: }
0656: }
0657:
0658: /**
0659: * Return the useradata as mime coded serilised object. Be aware of the
0660: * de/serilasation problems.
0661: *
0662: * @param data
0663: * the dataobject
0664: * @return String mimecoded userData as String
0665: * @throws IOException
0666: * serialisation of the user data could throw an exception.
0667: */
0668: private String getUserDataAsString(final MeasureData data)
0669: throws IOException {
0670: String output = "null";
0671: if (null != userData) {
0672: ByteArrayOutputStream bos = new ByteArrayOutputStream(
0673: BUFFER_SIZE);
0674: ObjectOutputStream oos;
0675: oos = new ObjectOutputStream(bos);
0676: oos.writeObject("class=" + userData.getClass());
0677: oos.writeObject(userData);
0678: oos.close();
0679: // output = Base64Encoder.encode(bos.toByteArray());
0680: output = Base64.encodeBytes(bos.toByteArray());
0681: bos.close();
0682: }
0683: return output;
0684: }
0685:
0686: /**
0687: * @see de.mcs.jmeasurement.MeasurePoint#setData(de.mcs.jmeasurement.MeasureData[])
0688: * @param datas
0689: * the MeasureData list to add
0690: */
0691: public final void setData(final MeasureData[] datas) {
0692: SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
0693: synchronized (this ) {
0694: for (int i = 0; i < datas.length; i++) {
0695: MeasureData data = datas[i];
0696: if (data.getName().equals(DATA_KEY_POINT_NAME)) {
0697: pointName = data.getAsString();
0698: } else if (data.getName().equals(DATA_KEY_PRIORITY)) {
0699: priority = Integer.parseInt(data.getAsString());
0700: } else if (data.getName().equals(DATA_KEY_ACCESS_COUNT)) {
0701: accessCount = Long.parseLong(data.getAsString());
0702: } else if (data.getName().equals(DATA_KEY_AVERAGE_MSEC)) {
0703: averageMSec = Long.parseLong(data.getAsString());
0704: } else if (data.getName().equals(DATA_KEY_TOTAL_MSEC)) {
0705: totalMSec = Long.parseLong(data.getAsString());
0706: } else if (data.getName().equals(DATA_KEY_MIN_MSEC)) {
0707: minMSec = Long.parseLong(data.getAsString());
0708: } else if (data.getName().equals(DATA_KEY_MAX_MSEC)) {
0709: maxMSec = Long.parseLong(data.getAsString());
0710: } else if (data.getName().equals(DATA_KEY_ACTIVE)) {
0711: active = Long.parseLong(data.getAsString());
0712: } else if (data.getName().equals(DATA_KEY_DEATH_COUNT)) {
0713: deathMonitors = Long.parseLong(data.getAsString());
0714: } else if (data.getName().equals(DATA_KEY_MAX_ACTIVE)) {
0715: maxActive = Long.parseLong(data.getAsString());
0716: } else if (data.getName().equals(
0717: DATA_KEY_LAST_ACTIVATION)) {
0718: try {
0719: lastActivation = simpleDateFormat.parse(data
0720: .getAsString());
0721: } catch (Exception e) {
0722: // nothing to do here
0723: lastActivation = null;
0724: }
0725: } else if (data.getName().equals(
0726: DATA_KEY_EXCEPTION_COUNT)) {
0727: exceptionCount = Long.parseLong(data.getAsString());
0728: } else if (data.getName().equals(DATA_KEY_SQUARESUM)) {
0729: squareSumm = Double.parseDouble(data.getAsString());
0730: } else if (data.getName().equals(DATA_KEY_DEVIATION)) {
0731: String dataStr = data.getAsString();
0732: if (dataStr.equalsIgnoreCase("nan")) {
0733: deviation = new Float(0.0);
0734: } else {
0735: deviation = Float.parseFloat(dataStr);
0736: }
0737: } else if (data.getName().equals(
0738: DATA_KEY_EXCEPTION_LIST)) {
0739: String[] exceptions = StringUtils.csvStringToArray(
0740: data.getAsString(), ',', '"');
0741: for (int j = 0; j < exceptions.length; j++) {
0742: exceptionList.add(exceptions[j]);
0743: }
0744: } else if (data.getName().equals(DATA_KEY_USER_DATA)) {
0745: userData = getUserDataObject(data.getAsString());
0746: }
0747: }
0748: }
0749: }
0750:
0751: /**
0752: * This methode will deserilise the user data object from the string.
0753: *
0754: * @param string
0755: * base64 coded user data object
0756: * @return Object
0757: */
0758: private IUserData getUserDataObject(final String string) {
0759: IUserData myUserData = null;
0760: try {
0761: if (null != string) {
0762: if (!string.equals("null")) {
0763: ByteArrayInputStream bis = new ByteArrayInputStream(
0764: Base64.decode(string));
0765: // ByteArrayInputStream bis = new ByteArrayInputStream(
0766: // Base64Decoder.decode(string));
0767: ObjectInputStream ois;
0768: ois = new ObjectInputStream(bis);
0769: ois.readObject();
0770:
0771: Object objUserData = ois.readObject();
0772:
0773: myUserData = (IUserData) objUserData;
0774: ois.close();
0775: bis.close();
0776: }
0777: }
0778: } catch (Exception e) {
0779: e.printStackTrace();
0780: }
0781: return myUserData;
0782: }
0783:
0784: /**
0785: * Converting all parameters of this measurepoint into an xml structure.
0786: *
0787: * @param writer
0788: * the writer to use for XML writing
0789: * @throws SAXException
0790: * if something goes wrong in xml writing
0791: * @throws IOException
0792: * serialisation of the user data could throw an exception.
0793: */
0794: public final void toXML(final DataWriter writer)
0795: throws SAXException, IOException {
0796: AttributesImpl atts = new AttributesImpl();
0797: atts.addAttribute("", "name", "", "String", pointName);
0798: atts.addAttribute("", "class", "", "String",
0799: DefaultMeasurePoint.class.getName());
0800: writer.startElement("", "measurepoint", "", atts);
0801: MeasureData[] datas = getData();
0802: for (int i = 0; i < datas.length; i++) {
0803: MeasureData data = datas[i];
0804: if (data.getName().equals(DATA_KEY_USER_DATA)) {
0805: writer.dataElement(data.getName(),
0806: getUserDataAsString(data));
0807: } else {
0808: writer.dataElement(data.getName(), data.getAsString());
0809: }
0810: }
0811:
0812: writer.endElement("", "measurepoint", "");
0813: }
0814:
0815: /**
0816: * This methode will return the call back object set with
0817: * <code>setMeasureDataCallback()</code>. This callback will be activate,
0818: * when monitor datas will be added to the measurement point.
0819: *
0820: * @return Returns the measureDataCallback.
0821: */
0822: public final MeasureDataCallback getMeasureDataCallback() {
0823: return measureDataCallback;
0824: }
0825:
0826: /**
0827: * With this methode a call back object will be set. This callback will be
0828: * activate, when monitor datas will be added to the measurement point.
0829: *
0830: * @param aMeasureDataCallback
0831: * The measureDataCallback to set.
0832: */
0833: public final void setMeasureDataCallback(
0834: final MeasureDataCallback aMeasureDataCallback) {
0835: measureDataCallback = aMeasureDataCallback;
0836: }
0837:
0838: /**
0839: * @see de.mcs.jmeasurement.MeasurePoint#getData(java.lang.String)
0840: * @param name
0841: * name of the data to get
0842: * @return MeasureData
0843: */
0844: public final MeasureData getData(final String name) {
0845: MeasureData[] datas = getData();
0846: for (int i = 0; i < datas.length; i++) {
0847: MeasureData data2 = datas[i];
0848: if (data2.getName().equals(name)) {
0849: return data2;
0850: }
0851: }
0852: return null;
0853: }
0854:
0855: /**
0856: * @see de.mcs.jmeasurement.MeasurePoint#getData(java.lang.String)
0857: * @param name
0858: * name of the data to get
0859: * @return MeasureData
0860: */
0861: public final Class getDataClass(final String name) {
0862: MeasureData[] datas = getData();
0863: for (int i = 0; i < datas.length; i++) {
0864: MeasureData data2 = datas[i];
0865: if (data2.getName().equals(name)) {
0866: return data2.getValueClass();
0867: }
0868: }
0869: return String.class;
0870: }
0871:
0872: /**
0873: * Getting the measurement data as simple string.
0874: *
0875: * @return String with a key=value list of all measurement data
0876: */
0877: public final String asString() {
0878: StringBuffer string = new StringBuffer(BUFFER_SIZE);
0879: MeasureData[] datas = getData();
0880: MeasureData data = null;
0881: for (int i = 0; i < datas.length; i++) {
0882: data = datas[i];
0883: string.append(data.getName()).append("=").append(
0884: data.getAsString()).append("\n");
0885: }
0886: return string.toString();
0887:
0888: }
0889:
0890: /**
0891: * This methode will be called from the DefaultMonitor if the monitor will
0892: * be finalized before stopped. Or is you explicit call this methode for a
0893: * monitor. The active counting will be reduced and the death counting will
0894: * be increased.
0895: *
0896: * @param monitor
0897: * the monitor which is death.
0898: * @see de.mcs.jmeasurement.MeasurePoint#deathMonitor(de.mcs.jmeasurement.Monitor)
0899: */
0900: public final void deathMonitor(final Monitor monitor) {
0901: synchronized (this ) {
0902: if (hmMonitors.containsKey(monitor.getMonitoId())) {
0903: active--;
0904: deathMonitors++;
0905: hmMonitors.remove(monitor.getMonitoId());
0906: }
0907: }
0908: }
0909:
0910: /**
0911: * cloning this Measure point.
0912: *
0913: * @return Object
0914: */
0915: public final Object clone() {
0916: DefaultMeasurePoint newPoint = new DefaultMeasurePoint(
0917: this .pointName, this .priority, this .config);
0918: newPoint.accessCount = this .accessCount;
0919: newPoint.active = this .active;
0920: newPoint.averageMSec = this .averageMSec;
0921: newPoint.deathMonitors = this .deathMonitors;
0922: newPoint.lastActivation = this .lastActivation;
0923: newPoint.maxActive = this .maxActive;
0924: newPoint.maxMSec = this .maxMSec;
0925: newPoint.minMSec = this .minMSec;
0926: newPoint.totalMSec = this .totalMSec;
0927: newPoint.exceptionCount = this .exceptionCount;
0928: newPoint.exceptionList.addAll(this .exceptionList);
0929: if (this .userData != null) {
0930: newPoint.userData = (IUserData) this .userData.clone();
0931: }
0932: return newPoint;
0933: }
0934:
0935: /**
0936: * getting all data as a hashmap with sting as keys and values.
0937: *
0938: * @return HashMap
0939: */
0940: public final Map getMap() {
0941: HashMap<String, String> map = new HashMap<String, String>();
0942: map.put("name", getName());
0943: MeasureData[] datas = getData();
0944: for (int i = 0; i < datas.length; i++) {
0945: MeasureData data = datas[i];
0946: map.put(data.getName(), data.getAsString());
0947: }
0948: return map;
0949: }
0950:
0951: /**
0952: * @return increasing the counter and get back the actual value.
0953: * @see de.mcs.jmeasurement.MeasurePoint#increaseCount()
0954: */
0955: public final long increaseCount() {
0956: synchronized (this ) {
0957: lastActivation = new Date();
0958: accessCount++;
0959: return accessCount;
0960: }
0961: }
0962:
0963: /**
0964: * reading with the default methode all non transient fields and initialise
0965: * my rtansient fields.
0966: *
0967: * @param ois
0968: * the stream to read from.
0969: * @throws IOException
0970: * if something goesw rong.
0971: */
0972: private void readObject(final ObjectInputStream ois)
0973: throws IOException {
0974: try {
0975: ois.defaultReadObject(); // Lese freundin, aber nicht das alter
0976: } catch (ClassNotFoundException e) {
0977: throw new IOException("Klasse nicht gefunden. HILFE!!");
0978: }
0979: q = new ReferenceQueue<Monitor>();
0980: }
0981:
0982: /**
0983: * reading and processing the options.
0984: */
0985: private void processOptions() {
0986: bCalculationDeviation = !config
0987: .getBoolean(JMConfig.OPTION_DISABLE_DEVIATION);
0988: }
0989:
0990: /**
0991: * @return <code>true</code> if this measurepoint has actually active
0992: * monitors, otherwise <code>false</code>
0993: */
0994: public final boolean hasActiveMonitors() {
0995: return !hmMonitors.isEmpty();
0996: }
0997:
0998: /**
0999: * for deserialsation we must offer a methode to set the config to the right
1000: * one.
1001: *
1002: * @param aConfig
1003: * the config to be used.
1004: */
1005: public final void setConfig(final JMConfig aConfig) {
1006: this.config = aConfig;
1007: }
1008: }
|