All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.karelherink.jdwpanalyzer.model.JDWPProxy Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 *
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package com.karelherink.jdwpanalyzer.model;

import com.karelherink.jdwpanalyzer.logger.PacketLogReader;
import com.karelherink.jdwpanalyzer.logger.PacketLogWriter;
import com.karelherink.jdwpanalyzer.ui.View;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;


/**
 *
 * @author  karel herink
 */
public class JDWPProxy {
	
	private PacketLogWriter packetLogWriter;
    
    /* References to Request objects in the same seqence they were received */
    static List sequentialRequests = Collections.synchronizedList(new ArrayList());
    
    private View view;

	private Socket socketVM;
	private Socket socketDebugger;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws NumberFormatException, IOException, UnknownHostException {
        if (args.length != 4 && args.length != 5 && args.length != 1) {
            System.err.println("\nUsage: java -jar JDWPAnalyzer.jar (    []) | \n\n" +
            		"inPort     = port to which debugger will connect\n" +
            		"outAddress = address as 'host:port' on which the remote VM is accepting debugger connections.\n" +
            		"             localhost addresses can just specify a port - no host required\n" +
            		"reqDelay   = num MS to wait before passing each request to VM\n" +
            		"respDelay  = num MS to wait before passing each response to debugger\n" +
            		"log_dir    = log directory path for writing or reading\n");
            System.exit(1);
        }
        if (args.length >= 4) {
        	int inPort = Integer.parseInt(args[0]);
        	String outAddress = args[1];
        	int reqDelay = Integer.parseInt(args[2]);
        	int respDelay = Integer.parseInt(args[3]);
        	if (args.length == 5) {
        		String logFile = args[4];
        		new JDWPProxy(inPort, outAddress, reqDelay, respDelay, logFile);
        	}
        	else
        		new JDWPProxy(inPort, outAddress, reqDelay, respDelay, null);
        }
        else {
        	new JDWPProxy(args[0]);
        }
        
    }
    
    public JDWPProxy(int inPort, String outAddress, int reqDelay, int respDelay, String logDir) throws IOException {
    	this.activeMode(inPort, outAddress, reqDelay, respDelay, logDir);
    }
    
    public JDWPProxy(String logDir) throws IOException {
    	this.passiveMode(logDir);
    }
    
    /**
     * In passive mode only use 1 thread for reading packets from files. Since logged packets
     * are already in sequence (sorted out by PacketLogreader) reading them with 2 threads
     * only messes things up, ie. packets are out of sequence unless some more syncing
     * is put in place.
     * 
     * @param logDir
     * @throws IOException
     */
    private void passiveMode(String logDir) throws IOException {
    	PipedInputStream pin = new PipedInputStream();
    	PipedOutputStream pout = new PipedOutputStream();
    	pin.connect(pout);
    	DataInputStream din = new DataInputStream(pin);
    	DataOutputStream dos = new DataOutputStream(pout);
    	
		T t = new T(din, null, 0);
		t.setName("Sequential reader");
        System.out.println("Starting replay..");
        
        view = new View(this, JDWPProxy.sequentialRequests);

        t.setDaemon(true);
        t.start();
    	
    	PacketLogReader packetLogReader = new PacketLogReader(logDir, dos);
    	packetLogReader.setDaemon(true);
    	packetLogReader.start();
    }
    
    private void activeMode(int inPort, String outAddress, int reqDelay, int respDelay, String logDir)  throws IOException {
    	if (logDir != null)
    		this.initLogWriter(logDir);
    	
        ServerSocket serverSock = new ServerSocket(inPort);
        System.out.println("JDWPProxy: waiting for connection on port " + inPort + "..");
        socketDebugger = serverSock.accept();
        
        /* if the address contains a ':', the address has a host - otherwise it is considered to be just a port */
		if (outAddress.indexOf(':') == -1 ) {
			/* no address specified, just use the port with the local address */
			System.out.println("JDWPProxy: Connection received, connecting to VM on port " + outAddress + "..");
	        socketVM = new Socket(InetAddress.getLocalHost(), Integer.valueOf(outAddress));
		} else {
			/* host is given - assume format of "host:port" */
			System.out.println("JDWPProxy: Connection received, connecting to VM at address " + outAddress + "..");
			StringTokenizer st = new StringTokenizer(outAddress, ":");
			String host = st.nextToken();
			int port = Integer.valueOf(st.nextToken());
	        socketVM = new Socket(host, port);
		}
        
		T dbToVm = new T(new DataInputStream(socketDebugger.getInputStream()), new DataOutputStream(socketVM.getOutputStream()), reqDelay);
		T vmToDb = new T(new DataInputStream(socketVM.getInputStream()), new DataOutputStream(socketDebugger.getOutputStream()), respDelay);
		dbToVm.setName("=> DEBUGGER TO VM");
        vmToDb.setName("<= VM TO DEBUGGER");
        
        System.out.println("JDWPProxy: Connected Starting communication..");
        
        view = new View(this, JDWPProxy.sequentialRequests);
        
        dbToVm.shakeHands();
        vmToDb.shakeHands();
        dbToVm.setDaemon(true);
        vmToDb.setDaemon(true);
        dbToVm.start();
        vmToDb.start();
    }
    
    private void initLogWriter(String logDir) throws IOException {
    	this.packetLogWriter = new PacketLogWriter(logDir);
    	this.packetLogWriter.setDaemon(true);
    	this.packetLogWriter.setPriority(Thread.MIN_PRIORITY);
    	this.packetLogWriter.start();
    }
    
    public void shutDown() {
    	try {
    		System.out.println("Shut down.");
    		if (this.socketDebugger != null)
    			this.socketDebugger.close();
    		if (this.socketVM != null)
    			this.socketVM.close();
			if (this.packetLogWriter != null)
				this.packetLogWriter.interrupt();
		} catch (IOException e) {
			e.printStackTrace();
		}	
    }
    
    private class T extends Thread {
        private DataInputStream dis;
        private DataOutputStream dos;
        private int delay;
        
        public T(DataInputStream dis, DataOutputStream dos, int delay) {
        	this.dis = dis;
        	this.dos = dos;
            this.delay = delay;
        }
        
        private void shakeHands() throws IOException {
            byte[] handShake = new byte[14];
            dis.readFully(handShake);
            for(int i = 0; i < handShake.length; i++) {
                System.out.print((char) handShake[i]);
            }
            System.out.println();
            dos.write(handShake);
        }
        
        public void run() {
            try {
                //main processing loop
                while (true) {
                    Packet packet = Packet.readPacket(dis, true);
                    
                    if (JDWPProxy.this.packetLogWriter != null)
                    	JDWPProxy.this.packetLogWriter.requestPacketLog(packet);
                    
                    PacketAnalyzer packetAnalyzer = AnalyzerManager.createPacketAnalyzer(packet);
                    
                    if (packet instanceof Request) {
                        packetAnalyzer.updateInternalDataModel(packet);
                        JDWPProxy.sequentialRequests.add(packet);
                    }
                	if (packet instanceof Response) {
            			Response resp = (Response) packet;
            			if (!resp.isError())
                            packetAnalyzer.updateInternalDataModel(packet);
            		}
                    JDWPProxy.this.view.updateView(packet);
                    if (dos != null)
                    	Packet.writePacket(packet, dos);
                    this.doDelay(delay);
                }
                
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    if (dis != null) dis.close();
                } catch (IOException e2) {}
                try {
                    if (dos != null) dos.close();
                } catch (IOException e2) {}
            }
        }
        
        private void doDelay(int delay) {
        	try {
				Thread.sleep(delay);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
        }
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy