001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.wireprotocol;
042:
043: import java.io.IOException;
044: import java.io.ObjectInputStream;
045: import java.io.ObjectOutputStream;
046:
047: /**
048: * Implementation of our custom serialization. We use our own, specialized, simplified and optimized flavor of
049: * object serialization, to improve performance and avoid various things that standard serialization performes
050: * behind the scenes, such as loading of many classes, generating some classes on-the-fly, and so on. These
051: * actions can cause various undesirable side effects when used for such a sensitive thing as profiling.
052: * However, this kind of serialization is not completely automatic, and some manual changes in this class are
053: * required every time a new Command or Response subclass is created. Read the comments in this file to see
054: * where the changes should be made.
055: *
056: * @author Misha Dmitriev
057: * @author Ian Formanek
058: */
059: public class WireIO {
060: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
061:
062: private static final boolean DEBUG = System
063: .getProperty("org.netbeans.lib.profiler.wireprotocol.WireIO") != null; // NOI18N
064: private static final int IS_SIMPLE_COMMAND = 1;
065: private static final int IS_COMPLEX_COMMAND = 2;
066: private static final int IS_SIMPLE_RESPONSE = 3;
067: private static final int IS_COMPLEX_RESPONSE = 4;
068:
069: //~ Instance fields ----------------------------------------------------------------------------------------------------------
070:
071: private ObjectInputStream in;
072: private ObjectOutputStream out;
073: private long wasAlive;
074:
075: //~ Constructors -------------------------------------------------------------------------------------------------------------
076:
077: public WireIO(ObjectOutputStream pout, ObjectInputStream pin) {
078: out = pout;
079: in = pin;
080: }
081:
082: //~ Methods ------------------------------------------------------------------------------------------------------------------
083:
084: public Object receiveCommandOrResponse() throws IOException {
085: int code = in.read();
086:
087: /*if (code == -1) {
088: if (DEBUG) System.out.println("WireIO.DEBUG: received end of stream code");
089: return null; // end of stream, no more data
090: }*/
091: wasAlive = System.currentTimeMillis();
092: switch (code) {
093: case IS_SIMPLE_COMMAND:
094:
095: Command c = new Command(in.read());
096:
097: if (DEBUG) {
098: System.out
099: .println("WireIO.DEBUG: received simple command: "
100: + c); // NOI18N
101: }
102:
103: return c;
104: case IS_COMPLEX_COMMAND: {
105: int cmdType = in.read();
106:
107: if (DEBUG) {
108: System.out
109: .println("WireIO.DEBUG: received complex command type: " // NOI18N
110: + Command.cmdTypeToString(cmdType));
111: }
112:
113: Command cmd = null;
114:
115: switch (cmdType) {
116: case Command.METHOD_INVOKED_FIRST_TIME:
117: cmd = new MethodInvokedFirstTimeCommand();
118:
119: break;
120: case Command.CLASS_LOADED:
121: cmd = new ClassLoadedCommand();
122:
123: break;
124: case Command.MESSAGE:
125: cmd = new AsyncMessageCommand();
126:
127: break;
128: case Command.METHOD_LOADED:
129: cmd = new MethodLoadedCommand();
130:
131: break;
132: case Command.ROOT_CLASS_LOADED:
133: cmd = new RootClassLoadedCommand();
134:
135: break;
136: case Command.INITIATE_INSTRUMENTATION:
137: cmd = new InitiateInstrumentationCommand();
138:
139: break;
140: case Command.SET_CHANGEABLE_INSTR_PARAMS:
141: cmd = new SetChangeableInstrParamsCommand();
142:
143: break;
144: case Command.SET_UNCHANGEABLE_INSTR_PARAMS:
145: cmd = new SetUnchangeableInstrParamsCommand();
146:
147: break;
148: case Command.EVENT_BUFFER_DUMPED:
149: cmd = new EventBufferDumpedCommand();
150:
151: break;
152: case Command.INSTRUMENT_METHOD_GROUP:
153: cmd = new InstrumentMethodGroupCommand();
154:
155: break;
156: case Command.GET_METHOD_NAMES_FOR_JMETHOD_IDS:
157: cmd = new GetMethodNamesForJMethodIdsCommand();
158:
159: break;
160: case Command.GET_DEFINING_CLASS_LOADER:
161: cmd = new GetDefiningClassLoaderCommand();
162:
163: break;
164: case Command.TAKE_HEAP_DUMP:
165: cmd = new TakeHeapDumpCommand();
166:
167: break;
168: case Command.GET_CLASSID:
169: cmd = new GetClassIdCommand();
170:
171: break;
172: default:
173: throw new IOException(
174: "JFluid wire protocol error: received unknown command type. Value: " // NOI18N
175: + cmdType);
176: }
177:
178: cmd.readObject(in);
179:
180: if (DEBUG) {
181: System.out.println("WireIO.DEBUG: command is: "
182: + cmd); // NOI18N
183: }
184:
185: return cmd;
186: }
187: case IS_SIMPLE_RESPONSE:
188:
189: Response simpleResp = new Response(in.readBoolean());
190:
191: if (in.read() != 0) {
192: simpleResp.setErrorMessage(in.readUTF());
193: } else {
194: simpleResp.setErrorMessage(null);
195: }
196:
197: if (DEBUG) {
198: System.out
199: .println("WireIO.DEBUG: received simple response "
200: + simpleResp); // NOI18N
201: }
202:
203: return simpleResp;
204: case IS_COMPLEX_RESPONSE:
205:
206: int respType = in.read();
207:
208: if (DEBUG) {
209: System.out
210: .println("WireIO.DEBUG: received complex response " // NOI18N
211: + Response.respTypeToString(respType));
212: }
213:
214: Response resp = null;
215:
216: switch (respType) {
217: case Response.CODE_REGION_CPU_RESULTS:
218: resp = new CodeRegionCPUResultsResponse();
219:
220: break;
221: case Response.INSTRUMENT_METHOD_GROUP:
222: resp = new InstrumentMethodGroupResponse();
223:
224: break;
225: case Response.INTERNAL_STATS:
226: resp = new InternalStatsResponse();
227:
228: break;
229: case Response.VM_PROPERTIES:
230: resp = new VMPropertiesResponse();
231:
232: break;
233: case Response.DUMP_RESULTS:
234: resp = new DumpResultsResponse();
235:
236: break;
237: case Response.OBJECT_ALLOCATION_RESULTS:
238: resp = new ObjectAllocationResultsResponse();
239:
240: break;
241: case Response.METHOD_NAMES:
242: resp = new MethodNamesResponse();
243:
244: break;
245: case Response.THREAD_LIVENESS_STATUS:
246: resp = new ThreadLivenessStatusResponse();
247:
248: break;
249: case Response.MONITORED_NUMBERS:
250: resp = new MonitoredNumbersResponse();
251:
252: break;
253: case Response.DEFINING_LOADER:
254: resp = new DefiningLoaderResponse();
255:
256: break;
257: case Response.CALIBRATION_DATA:
258: resp = new CalibrationDataResponse();
259:
260: break;
261: case Response.CLASSID_RESPONSE:
262: resp = new GetClassIdResponse();
263:
264: break;
265: default:
266: throw new IOException(
267: "JFluid wire protocol error: received unknown response type. Value: "
268: + respType // NOI18N
269: );
270: }
271:
272: resp.setYes(in.readBoolean());
273:
274: if (in.read() != 0) {
275: resp.setErrorMessage(in.readUTF());
276: } else {
277: resp.setErrorMessage(null);
278: }
279:
280: resp.readObject(in);
281:
282: if (DEBUG) {
283: System.out.println("WireIO.DEBUG: response is: "
284: + resp); // NOI18N
285: }
286:
287: return resp;
288: default:
289:
290: if (DEBUG) {
291: System.out
292: .println("WireIO.DEBUG: received unknown code: "
293: + code); // NOI18N
294: }
295:
296: throw new IOException(
297: "JFluid wire protocol error: code does not correspond to command or response. Value "
298: + code // NOI18N
299: );
300: }
301: }
302:
303: public synchronized void sendComplexCommand(Command cmd)
304: throws IOException {
305: if (DEBUG) {
306: System.out
307: .println("WireIO.DEBUG: gonna send complex command: "
308: + cmd); // NOI18N
309: }
310:
311: out.write(IS_COMPLEX_COMMAND);
312: out.write(cmd.getType());
313: cmd.writeObject(out);
314: out.flush();
315: }
316:
317: public synchronized void sendComplexResponse(Response resp)
318: throws IOException {
319: if (DEBUG) {
320: System.out.println("WireIO.DEBUG: gonna send response: "
321: + resp); // NOI18N
322: }
323:
324: out.write(IS_COMPLEX_RESPONSE);
325: out.write(resp.getType());
326: out.writeBoolean(resp.yes());
327:
328: String errorMessage = resp.getErrorMessage();
329:
330: if (errorMessage == null) {
331: out.write(0);
332: } else {
333: out.write(1);
334: out.writeUTF(errorMessage);
335: }
336:
337: resp.writeObject(out);
338: out.flush();
339: }
340:
341: public synchronized void sendSimpleCommand(int cmdType)
342: throws IOException {
343: if (DEBUG) {
344: System.out
345: .println("WireIO.DEBUG: gonna send simple command:"
346: + Command.cmdTypeToString(cmdType)); // NOI18N
347: }
348:
349: out.write(IS_SIMPLE_COMMAND);
350: out.write(cmdType);
351: out.flush();
352: }
353:
354: public synchronized void sendSimpleResponse(boolean yes,
355: String errorMessage) throws IOException {
356: if (DEBUG) {
357: System.out
358: .println("WireIO.DEBUG: gonna send simple response: yes: "
359: + yes // NOI18N
360: + ", errorMessage: " + errorMessage // NOI18N
361: );
362: }
363:
364: out.write(IS_SIMPLE_RESPONSE);
365: out.writeBoolean(yes);
366:
367: if (errorMessage == null) {
368: out.write(0);
369: } else {
370: out.write(1);
371: out.writeUTF(errorMessage);
372: }
373:
374: out.flush();
375: }
376:
377: public long wasAlive() {
378: return wasAlive;
379: }
380: }
|