1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * ident "%Z%%M% %I% %E% SMI" 27 */ 28 package org.opensolaris.os.dtrace; 29 30 import java.io.*; 31 import java.beans.*; 32 import java.util.*; 33 34 /** 35 * A formatted string generated by the DTrace {@code printf()} action. 36 * <p> 37 * Immutable. Supports persistence using {@link java.beans.XMLEncoder}. 38 * 39 * @author Tom Erickson 40 */ 41 public final class PrintfRecord implements Record, Serializable { 42 static final long serialVersionUID = 727237355963977675L; 43 44 static { 45 try { 46 BeanInfo info = Introspector.getBeanInfo(PrintfRecord.class); 47 PersistenceDelegate persistenceDelegate = 48 new DefaultPersistenceDelegate( 49 new String[] {"records", "formattedString"}); 50 BeanDescriptor d = info.getBeanDescriptor(); 51 d.setValue("persistenceDelegate", persistenceDelegate); 52 } catch (IntrospectionException e) { 53 System.out.println(e); 54 } 55 } 56 57 /** @serial */ 58 private List <ValueRecord> records; 59 /** @serial */ 60 private String formattedString; 61 62 // package-level access, called by ProbeData 63 PrintfRecord() 64 { 65 records = new ArrayList <ValueRecord> (); 66 } 67 68 /** 69 * Creates a record with the unformatted elements passed to the 70 * DTrace {@code printf()} action and the resulting formatted 71 * output. Supports XML persistence. 72 * 73 * @param v variable number of unformatted elements passed to the 74 * DTrace {@code printf()} action 75 * @param s formatted {@code printf()} output 76 * @throws NullPointerException if the given list or any of its 77 * elements is {@code null}, or if the given formatted string is 78 * {@code null} 79 */ 80 public 81 PrintfRecord(List <ValueRecord> v, String s) 82 { 83 formattedString = s; 84 records = new ArrayList <ValueRecord> (v.size()); 85 records.addAll(v); 86 validate(); 87 } 88 89 private final void 90 validate() 91 { 92 if (formattedString == null) { 93 throw new NullPointerException("formatted string is null"); 94 } 95 if (records == null) { 96 throw new NullPointerException("list of format args is null"); 97 } 98 for (ValueRecord r : records) { 99 if (r == null) { 100 throw new NullPointerException("format arg is null"); 101 } 102 } 103 } 104 105 /** 106 * Called by ProbeData code to populate record list. 107 * 108 * @throws NullPointerException if o is null 109 */ 110 void 111 addUnformattedElement(ScalarRecord rec) 112 { 113 records.add(rec); 114 } 115 116 /** 117 * Gets the formatted string output of the DTrace {@code printf()} 118 * action. 119 * 120 * @return non-null formatted string output of the DTrace {@code 121 * printf()} action 122 */ 123 public String 124 getFormattedString() 125 { 126 return formattedString; 127 } 128 129 /** 130 * Package level access; called by ProbeData 131 */ 132 void 133 setFormattedString(String s) 134 { 135 if (s == null) { 136 throw new NullPointerException("formatted string is null"); 137 } 138 formattedString = s; 139 } 140 141 /** 142 * Gets the unfomatted elements passed to the DTrace {@code 143 * printf()} action after the format string. 144 * 145 * @return non-null, unmodifiable list of unformatted elements 146 * passed to the DTrace {@code printf()} action that generated this 147 * record, in the order they appear in the argument list after the 148 * format string 149 */ 150 public List <ValueRecord> 151 getRecords() 152 { 153 return Collections.unmodifiableList(records); 154 } 155 156 /** 157 * Gets the number of DTrace {@code printf()} unformatted elements 158 * (arguments following the format string). For example, the 159 * following action 160 * <pre><code> 161 * printf("%s %d\n", "cat", 9); 162 * </code></pre> 163 * generates a {@code PrintfRecord} with a record count of two. 164 * 165 * @return the number of unformatted elements passed to the DTrace 166 * {@code printf()} action that generated this record. 167 */ 168 public int 169 getRecordCount() 170 { 171 return records.size(); 172 } 173 174 /** 175 * Gets the unformatted element passed to the DTrace {@code 176 * printf()} action at the given offset in the {@code printf()} 177 * argument list after the format string, starting at offset zero 178 * for the first unformatted element. 179 * 180 * @return non-null record representing the unformatted {@code 181 * printf()} element at the given index (using the same order that 182 * they appear in the {@code printf()} argument list) 183 * @throws ArrayIndexOutOfBoundsException if the given index is 184 * out of range (index < 0 || index >= getRecordCount()) 185 */ 186 public ValueRecord 187 getRecord(int i) 188 { 189 return records.get(i); 190 } 191 192 private void 193 readObject(ObjectInputStream s) 194 throws IOException, ClassNotFoundException 195 { 196 s.defaultReadObject(); 197 // Defensively copy record list before validating 198 if (records == null) { 199 throw new InvalidObjectException("record list is null"); 200 } 201 List <ValueRecord> copy = new ArrayList <ValueRecord> (records.size()); 202 copy.addAll(records); 203 records = copy; 204 // check invariants 205 try { 206 validate(); 207 } catch (Exception e) { 208 InvalidObjectException x = new InvalidObjectException( 209 e.getMessage()); 210 x.initCause(e); 211 throw x; 212 } 213 } 214 215 /** 216 * Gets the formatted string output of the DTrace {@code printf()} 217 * action. 218 */ 219 public String 220 toString() 221 { 222 return formattedString; 223 } 224 } 225