2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A *
2N/A * ident "%Z%%M% %I% %E% SMI"
2N/A */
2N/Apackage org.opensolaris.os.dtrace;
2N/A
2N/Aimport java.io.*;
2N/A
2N/A/**
2N/A * Identifies a compiled D program. This identifier is valid only on
2N/A * the {@link LocalConsumer} from which it was obtained. Some {@code
2N/A * Consumer} methods attach additional {@link ProgramInfo} to this
2N/A * identifier.
2N/A * <p>
2N/A * Not intended for persistence, since it identifies nothing after its
2N/A * source {@code LocalConsumer} closes.
2N/A *
2N/A * @see Consumer#compile(String program, String[] macroArgs)
2N/A * @see Consumer#compile(java.io.File program, String[] macroArgs)
2N/A * @see Consumer#enable(Program program)
2N/A * @see Consumer#getProgramInfo(Program program)
2N/A * @see Consumer#listProgramProbes(Program program)
2N/A * @see Consumer#listProgramProbeDetail(Program program)
2N/A *
2N/A * @author Tom Erickson
2N/A */
2N/Apublic class Program implements Serializable {
2N/A static final long serialVersionUID = 364989786308628466L;
2N/A
2N/A /**
2N/A * Identifies this program among all of a consumer's programs. Set
2N/A * by native code.
2N/A *
2N/A * @serial
2N/A */
2N/A private int id = -1;
2N/A
2N/A // Set by LocalConsumer.compile()
2N/A /** @serial */
2N/A LocalConsumer.Identifier consumerID;
2N/A /** @serial */
2N/A String contents;
2N/A
2N/A /** @serial */
2N/A private ProgramInfo info;
2N/A
2N/A /**
2N/A * Called by native code
2N/A */
2N/A private Program()
2N/A {
2N/A }
2N/A
2N/A // Called by LocalConsumer.compile() to ensure that only valid
2N/A // instances are made accessible to users. Similarly called by
2N/A // readObject to ensure that only valid instances are deserialized.
2N/A final void
2N/A validate()
2N/A {
2N/A if (id < 0) {
2N/A throw new IllegalArgumentException("id is negative");
2N/A }
2N/A if (consumerID == null) {
2N/A throw new NullPointerException("consumer ID is null");
2N/A }
2N/A }
2N/A
2N/A /**
2N/A * Gets the full pre-compiled text of the identified program.
2N/A *
2N/A * @return the {@code String} passed to {@link
2N/A * Consumer#compile(String program, String[] macroArgs)}, or the
2N/A * contents of the {@code File} passed to {@link
2N/A * Consumer#compile(java.io.File program, String[] macroArgs)}
2N/A */
2N/A public String
2N/A getContents()
2N/A {
2N/A return contents;
2N/A }
2N/A
2N/A /**
2N/A * Gets information about this compiled program provided by {@link
2N/A * Consumer#getProgramInfo(Program program)} or {@link
2N/A * Consumer#enable(Program program)}.
2N/A *
2N/A * @return information about this compiled program, or {@code null}
2N/A * if this {@code Program} has not been passed to {@link
2N/A * Consumer#getProgramInfo(Program program)} or {@link
2N/A * Consumer#enable(Program program)}
2N/A */
2N/A public ProgramInfo
2N/A getInfo()
2N/A {
2N/A return info;
2N/A }
2N/A
2N/A /**
2N/A * Sets additional information about this compiled program,
2N/A * including program stability and matching probe count. Several
2N/A * {@code Consumer} methods attach such information to a given
2N/A * {@code Program} argument. The method is {@code public} to
2N/A * support implementations of the {@code Consumer} interface other
2N/A * than {@link LocalConsumer}. Although a {@code Program} can only
2N/A * be obtained from a {@code LocalConsumer}, other {@code Consumer}
2N/A * implemenations may provide a helpful layer of abstraction while
2N/A * using a {@code LocalConsumer} internally to compile DTrace
2N/A * programs. Users of the API are not otherwise expected to call
2N/A * the {@code setInfo()} method directly.
2N/A *
2N/A * @param programInfo optional additional information about this
2N/A * compiled program
2N/A * @see #getInfo()
2N/A * @see Consumer#enable(Program program)
2N/A * @see Consumer#getProgramInfo(Program program)
2N/A */
2N/A public void
2N/A setInfo(ProgramInfo programInfo)
2N/A {
2N/A info = programInfo;
2N/A }
2N/A
2N/A private void
2N/A readObject(ObjectInputStream s)
2N/A throws IOException, ClassNotFoundException
2N/A {
2N/A s.defaultReadObject();
2N/A // check class invariants
2N/A try {
2N/A validate();
2N/A } catch (Exception e) {
2N/A InvalidObjectException x = new InvalidObjectException(
2N/A e.getMessage());
2N/A x.initCause(e);
2N/A throw x;
2N/A }
2N/A }
2N/A
2N/A /**
2N/A * Gets the contents of the given file as a string.
2N/A *
2N/A * @return non-null contents of the given file as a string
2N/A * @throws IOException if the method fails to read the contents of
2N/A * the given file
2N/A */
2N/A static String
2N/A getProgramString(java.io.File programFile) throws IOException
2N/A {
2N/A if (programFile == null) {
2N/A return null;
2N/A }
2N/A
2N/A StringBuilder buf = new StringBuilder();
2N/A InputStream in;
2N/A in = new BufferedInputStream(new FileInputStream(programFile));
2N/A int i = in.read();
2N/A while (i >= 0) {
2N/A buf.append((char)i);
2N/A i = in.read();
2N/A }
2N/A
2N/A String s = buf.toString();
2N/A return s;
2N/A }
2N/A
2N/A /**
2N/A * Gets a string representation of this {@code Program} instance
2N/A * useful for logging and not intended for display. The exact
2N/A * details of the representation are unspecified and subject to
2N/A * change, but the following format may be regarded as typical:
2N/A * <pre><code>
2N/A * class-name[property1 = value1, property2 = value2]
2N/A * </code></pre>
2N/A */
2N/A public String
2N/A toString()
2N/A {
2N/A StringBuilder buf = new StringBuilder();
2N/A buf.append(Program.class.getName());
2N/A buf.append("[contents = ");
2N/A buf.append(contents);
2N/A buf.append(", info = ");
2N/A buf.append(info);
2N/A buf.append(']');
2N/A return buf.toString();
2N/A }
2N/A
2N/A /**
2N/A * Identifies a compiled D program, specifically one that has been
2N/A * compiled from a file.
2N/A */
2N/A public static final class File extends Program {
2N/A static final long serialVersionUID = 6217493430514165300L;
2N/A
2N/A // Set by LocalConsumer.compile()
2N/A /** @serial */
2N/A java.io.File file;
2N/A
2N/A private
2N/A File()
2N/A {
2N/A }
2N/A
2N/A // Called by LocalConsumer.compile() to ensure that only valid
2N/A // instances are made accessible to users. Similarly called by
2N/A // readObject to ensure that only valid instances are deserialized.
2N/A final void
2N/A validateFile()
2N/A {
2N/A if (file == null) {
2N/A throw new NullPointerException("file is null");
2N/A }
2N/A }
2N/A
2N/A /**
2N/A * Gets the program file.
2N/A *
2N/A * @return the {@code File} passed to {@link
2N/A * Consumer#compile(java.io.File program, String[] macroArgs)}
2N/A */
2N/A public java.io.File
2N/A getFile()
2N/A {
2N/A return file;
2N/A }
2N/A
2N/A private void
2N/A readObject(ObjectInputStream s)
2N/A throws IOException, ClassNotFoundException
2N/A {
2N/A s.defaultReadObject();
2N/A // check class invariants
2N/A try {
2N/A validateFile();
2N/A } catch (Exception e) {
2N/A InvalidObjectException x = new InvalidObjectException(
2N/A e.getMessage());
2N/A x.initCause(e);
2N/A throw x;
2N/A }
2N/A }
2N/A
2N/A public String
2N/A toString()
2N/A {
2N/A StringBuilder buf = new StringBuilder();
2N/A buf.append(Program.File.class.getName());
2N/A buf.append("[super = ");
2N/A buf.append(super.toString());
2N/A buf.append(", file = ");
2N/A buf.append(file);
2N/A buf.append(']');
2N/A return buf.toString();
2N/A }
2N/A }
2N/A}