/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.protocol; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import com.slamd.asn1.ASN1Element; import com.slamd.asn1.ASN1OctetString; import com.slamd.asn1.ASN1Sequence; import com.slamd.common.SLAMDException; /** * This class defines a data structure for holding information about a class * transferred from the server to a client. * * * @author Neil A. Wilson */ public class ClassData { // The bytes that comprise the class file. private byte[] classBytes; // The fully-qualified name of the class. private String className; /** * Creates a new class data object with the provided information. * * @param className The fully-qualified name of the class. * @param classBytes The bytes that comprise the class file. */ public ClassData(String className, byte[] classBytes) { this.className = className; this.classBytes = classBytes; } /** * Retrieves the fully-qualified name of the class. * * @return The fully-qualified name of the class. */ public String getClassName() { return className; } /** * Specifies the fully-qualified name of the class. * * @param className The fully-qualified name of the class. */ public void setClassName(String className) { this.className = className; } /** * Retrieves the bytes that comprise the class file. * * @return The bytes that comprise the class file. */ public byte[] getClassBytes() { return classBytes; } /** * Specifies the bytes that comprise the class file. * * @param classBytes The bytes that comprise the class file. */ public void setClassBytes(byte[] classBytes) { this.classBytes = classBytes; } /** * Writes the contents of the class to an appropriate file below the given * directory. * * @param directory The path to the directory below which the class file * should be written. * * @throws IOException If an I/O problem occurs while attempting to write * the class file. * * @throws SecurityException If the security manager will not allow the file * to be written. */ public void writeClassFile(String directory) throws IOException, SecurityException { String fileName = directory + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; FileOutputStream outputStream = new FileOutputStream(fileName); outputStream.write(classBytes); outputStream.flush(); outputStream.close(); } /** * Encodes this class data structure to an ASN.1 element. * * @return The ASN.1 element containing the encoded class data structure. */ public ASN1Element encode() { ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>(); elementList.add(SLAMDMessage.encodeNameValuePair( ProtocolConstants.PROPERTY_CLASS_NAME, new ASN1OctetString(className))); elementList.add(SLAMDMessage.encodeNameValuePair( ProtocolConstants.PROPERTY_CLASS_BYTES, new ASN1OctetString(classBytes))); return new ASN1Sequence(elementList); } /** * Decodes the provided ASN.1 element as a set of class data information. * * @param encodedData The ASN.1 element containing the data to be decoded. * * @return The decoded class data information. * * @throws SLAMDException If a problem occurs while attempting to decode the * provided element. */ public static ClassData decode(ASN1Element encodedData) throws SLAMDException { HashMap<String,ASN1Element> propertyMap = SLAMDMessage.decodeNameValuePairSequence(encodedData); String className; ASN1Element valueElement = propertyMap.get(ProtocolConstants.PROPERTY_CLASS_NAME); if (valueElement == null) { throw new SLAMDException("Class data sequence does not include the " + "class name element."); } else { try { className = valueElement.decodeAsOctetString().getStringValue(); } catch (Exception e) { throw new SLAMDException("Unable to decode the class name property: " + e, e); } } byte[] classBytes; valueElement = propertyMap.get(ProtocolConstants.PROPERTY_CLASS_BYTES); if (valueElement == null) { throw new SLAMDException("Class data sequence does not include the " + "class bytes."); } else { try { classBytes = valueElement.decodeAsOctetString().getValue(); } catch (Exception e) { throw new SLAMDException("Unable to decode the class bytes " + "property: " + e, e); } } return new ClassData(className, classBytes); } /** * Retrieves a string representation of this class data structure. * * @return A string representation of this class data structure. */ @Override() public String toString() { return className + " (" + classBytes.length + " bytes)"; } }