blob: dcce3b60ac49daa23e90cf253b8364bd31b53a79 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 IBM Corporation and others All rights reserved. This
* program and the accompanying materials are made available under the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.rhino.transport;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.wst.jsdt.debug.transport.Connection;
import org.eclipse.wst.jsdt.debug.transport.ListenerKey;
import org.eclipse.wst.jsdt.debug.transport.TransportService;
/**
* {@link TransportService} specialization for a {@link PipedConnection}
*
* @since 1.0
*/
public class PipedTransportService implements TransportService {
/**
* Key specialized for a {@link PipedTransportService}
*/
public static class PipedListenerKey implements ListenerKey {
private String address;
public PipedListenerKey(String address) {
this.address = address;
}
public String address() {
return address;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PipedListenerKey other = (PipedListenerKey) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
return true;
}
}
Map listeners = new HashMap();
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.transport.TransportService#startListening(java.lang.String)
*/
public synchronized ListenerKey startListening(String address) throws IOException {
ListenerKey key = new PipedListenerKey(address == null ? Constants.EMPTY_STRING : address);
listeners.put(key, null);
return key;
};
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.transport.TransportService#stopListening(org.eclipse.wst.jsdt.debug.transport.ListenerKey)
*/
public void stopListening(ListenerKey key) throws IOException {
synchronized (key) {
if (listeners.containsKey(key)) {
key.notify();
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.transport.TransportService#accept(org.eclipse.wst.jsdt.debug.transport.ListenerKey, long, long)
*/
public Connection accept(ListenerKey key, long attachTimeout, long handshakeTimeout) throws IOException {
long timeout = attachTimeout;
if (timeout > 0) {
if (timeout > Integer.MAX_VALUE) {
timeout = Integer.MAX_VALUE; // approximately 25 days!
}
}
synchronized (listeners) {
if (!listeners.containsKey(key))
throw new IllegalStateException("not listening"); //$NON-NLS-1$
if (listeners.get(key) != null)
throw new IllegalStateException("PipedTransport only accepts one accept at a time"); //$NON-NLS-1$
PipedInputStream serveris = new PipedInputStream();
PipedOutputStream clientos = new PipedOutputStream();
serveris.connect(clientos);
PipedOutputStream serveros = new PipedOutputStream();
PipedInputStream clientis = new PipedInputStream();
serveros.connect(clientis);
listeners.put(key, new PipedConnection(clientis, clientos));
listeners.notifyAll();
long startTime = System.currentTimeMillis();
while (true) {
try {
listeners.wait(timeout);
} catch (InterruptedException e) {
throw new IOException("accept failed: interrupted"); //$NON-NLS-1$
}
if (!listeners.containsKey(key))
throw new IOException("accept failed: stopped listening"); //$NON-NLS-1$
if (listeners.get(key) != null) {
if (System.currentTimeMillis() - startTime > timeout) {
listeners.put(key, null);
throw new IOException("accept failed: timed out"); //$NON-NLS-1$
}
continue;
}
return new PipedConnection(serveris, serveros);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.wst.jsdt.debug.transport.TransportService#attach(java.lang.String, long, long)
*/
public Connection attach(String address, long attachTimeout, long handshakeTimeout) throws IOException {
ListenerKey key = new PipedListenerKey(address == null ? Constants.EMPTY_STRING : address);
Connection connection;
long startTime = System.currentTimeMillis();
synchronized (listeners) {
connection = (Connection) listeners.get(key);
while (connection == null) {
if (System.currentTimeMillis() - startTime > attachTimeout)
throw new IOException("attach failed: timed out"); //$NON-NLS-1$
try {
listeners.wait(attachTimeout);
} catch (InterruptedException e) {
throw new IOException("attach failed: interrupted"); //$NON-NLS-1$
}
connection = (Connection) listeners.get(key);
}
listeners.put(key, null);
listeners.notifyAll();
}
return connection;
}
}