Initial commit from SVN.
This commit is contained in:
10
Orb/.classpath
Normal file
10
Orb/.classpath
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="/Common"/>
|
||||
<classpathentry kind="src" path="/Foundation"/>
|
||||
<classpathentry kind="src" path="/Class File Services"/>
|
||||
<classpathentry kind="lib" path="ORB ExceptionSupport.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
20
Orb/.project
Normal file
20
Orb/.project
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Orb</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>Class File Services</project>
|
||||
<project>Common</project>
|
||||
<project>Foundation</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
1716
Orb/src/com/de22/orb/AbstractConnection.java
Normal file
1716
Orb/src/com/de22/orb/AbstractConnection.java
Normal file
File diff suppressed because it is too large
Load Diff
253
Orb/src/com/de22/orb/AbstractConnectionServer.java
Normal file
253
Orb/src/com/de22/orb/AbstractConnectionServer.java
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import com.common.util.*;
|
||||
import com.common.event.VoidHandler1;
|
||||
import com.common.event.VoidHandler2;
|
||||
import com.common.util.optimized.*;
|
||||
import com.de22.orb.security.AbstractSecurityProvider;
|
||||
|
||||
public abstract class AbstractConnectionServer {
|
||||
/** The orb that created this server socket. */
|
||||
private Orb orb = null;
|
||||
/** The collection of connections produced by this connection server indexed by the session identifier. */
|
||||
private LongObjectHashMap connectionsBySessionId = new LongObjectHashMap(1000);
|
||||
/** The last used session identifier. */
|
||||
private long lastUsedSessionId = 0;
|
||||
/** The security provider that will setup the accepted socket's security systems. */
|
||||
private AbstractSecurityProvider securityProvider = null;
|
||||
private String externalAddress = null;
|
||||
private int totalReferenceCount = 0;
|
||||
private ObjectIntHashMap referenceMap = new ObjectIntHashMap(4);
|
||||
private ClassLoader classLoader = null;
|
||||
private VoidHandler2 messageHandler = null;
|
||||
private VoidHandler1 initCompleteHandler = null;
|
||||
private IServerSocketOptions options = null;
|
||||
private String nameAndPort = null;
|
||||
/**
|
||||
* AbstractConnectionServer constructor.
|
||||
*/
|
||||
public AbstractConnectionServer() {
|
||||
super();
|
||||
}//AbstractConnectionServer()//
|
||||
/**
|
||||
* Gets a connection given it's session identifier.
|
||||
* @param sessionId The identifier generated by the connection server when the connection was accepted.
|
||||
* @return The socket found, or null if the socket has already been closed.
|
||||
*/
|
||||
public AbstractConnection getConnection(long sessionId) {
|
||||
return (AbstractConnection) connectionsBySessionId.get(sessionId);
|
||||
}//getConnection()//
|
||||
/**
|
||||
* Gets the next session identifier in the sequence.
|
||||
* @return The next identifier for the session sequence.
|
||||
*/
|
||||
protected long getNextSessionId() {
|
||||
return getServerSocketOptions().getAutoReconnectTimeLimit() != 0 ? ++lastUsedSessionId : 0;
|
||||
}//getNextSessionId()//
|
||||
/**
|
||||
* Registers the socket with the server socket's mappings.
|
||||
* @return The next identifier for the session sequence.
|
||||
*/
|
||||
protected void registerConnection(AbstractConnection socket) {
|
||||
if(getServerSocketOptions().getAutoReconnectTimeLimit() != 0) {
|
||||
connectionsBySessionId.put(socket.getSessionId(), socket);
|
||||
}//if//
|
||||
}//registerConnection()//
|
||||
/**
|
||||
* Unregisters the connection by removing it from the server socket's mappings.
|
||||
* @param socket The socket to unregister.
|
||||
*/
|
||||
public void unregisterConnection(AbstractConnection socket) {
|
||||
if(getServerSocketOptions().getAutoReconnectTimeLimit() != 0) {
|
||||
connectionsBySessionId.remove(socket.getSessionId());
|
||||
}//if//
|
||||
}//unregisterConnection()//
|
||||
/**
|
||||
* Closes the abstract server socket and the underlying socket system.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
//Notify the orb.//
|
||||
orb.closeServerSocket(null, this);
|
||||
}//close()//
|
||||
/**
|
||||
* Gets the number of times the server socket is being referenced. When this value reaches zero the orb will close the server socket.
|
||||
* @return The total number of times the server socket is referenced.
|
||||
*/
|
||||
public int getReferenceCount() {
|
||||
return totalReferenceCount;
|
||||
}//getReferenceCount()//
|
||||
/**
|
||||
* Gets the number of times the server socket is referenced with a given name.
|
||||
* @param name The name of the server socket.
|
||||
* @return The count of references to the server socket by the name.
|
||||
*/
|
||||
public int getReferenceCount(String name) {
|
||||
int result = 0;
|
||||
|
||||
if(referenceMap.containsKey(name)) {
|
||||
result = referenceMap.get(name);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getReferenceCount()//
|
||||
/**
|
||||
* Increments the reference count which tracks the number of times the server socket is being referenced.
|
||||
* @param name The name on which to increment the reference count for the server socket.
|
||||
*/
|
||||
public void incrementReferenceCount(String name) {
|
||||
if(referenceMap.containsKey(name)) {
|
||||
referenceMap.put(name, referenceMap.get(name) + 1);
|
||||
}//if//
|
||||
else {
|
||||
referenceMap.put(name, 1);
|
||||
}//else//
|
||||
|
||||
totalReferenceCount++;
|
||||
}//incrementReferenceCount()//
|
||||
/**
|
||||
* Decrements the reference count which tracks the number of times the server socket is being referenced.
|
||||
* @param name The name on which to decrement the reference count for the server socket.
|
||||
* @return The number of references by the name after the decrement.
|
||||
*/
|
||||
public int decrementReferenceCount(String name) {
|
||||
if(referenceMap.containsKey(name)) {
|
||||
int count = referenceMap.get(name) - 1;
|
||||
|
||||
if(count == 0) {
|
||||
referenceMap.remove(name);
|
||||
}//if//
|
||||
else {
|
||||
referenceMap.put(name, count);
|
||||
}//else//
|
||||
|
||||
totalReferenceCount--;
|
||||
|
||||
return count;
|
||||
}//if//
|
||||
else {
|
||||
throw new RuntimeException("Unable to decrement the server socket count on \"" + name + "\" because the name is not associated with this server socket.");
|
||||
}//else//
|
||||
}//decrementReferenceCount()//
|
||||
/**
|
||||
* Gets the class loader that this server socket and all accepted sockets will use for loading classes.
|
||||
* @return The class loader that will be used for class loading.
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}//getClassLoader()//
|
||||
/**
|
||||
* Gets the external address that this server socket is available through.
|
||||
* <p>Often times the server socket is listening on an intranet address & port, but it is mapped to an external internet address & port. This method will return that externally visible internet address & port as an address string.
|
||||
* @return The externally visible address & port that a client may reconnect on. This value should never be null and should at least return the address and port number that the server is listening on.
|
||||
*/
|
||||
public String getExternalAddress() {
|
||||
return externalAddress;
|
||||
}//getExternalAddress()//
|
||||
/**
|
||||
* Gets the name and port that the server socket is listening to.
|
||||
* @return The name and port in the [name]:[port] formatted string.
|
||||
*/
|
||||
public String getNameAndPort() {
|
||||
return nameAndPort;
|
||||
}//getNameAndPort()//
|
||||
/**
|
||||
* Gets the collection of names for this server socket.
|
||||
* <p>TODO: Is thread safty a problem here?
|
||||
* <p>Warning: This method is not thread safe.</p>
|
||||
* @return The names that have been assigned to this server socket.
|
||||
*/
|
||||
public IList getNames() {
|
||||
IList result = new LiteList(referenceMap.getSize(), 10);
|
||||
IIterator keyIterator = referenceMap.keyIterator();
|
||||
|
||||
while(keyIterator.hasNext()) {
|
||||
result.add(keyIterator.next());
|
||||
}//while//
|
||||
|
||||
return result;
|
||||
}//getNames()//
|
||||
/**
|
||||
* Gets the socket options that all accepted connections will use.
|
||||
* @return Socket options accepted connections will adhere to.
|
||||
*/
|
||||
public ISocketOptions getSocketOptions() {
|
||||
return options.getSocketOptions();
|
||||
}//getSocketOptions()//
|
||||
/**
|
||||
* Gets the orb that the server socket exists in.
|
||||
* @return The server socket's orb.
|
||||
*/
|
||||
public Orb getOrb() {
|
||||
return orb;
|
||||
}//getOrb()//
|
||||
/**
|
||||
* Gets the message handler called after reading a message.
|
||||
* @return The handler called to process a message.
|
||||
*/
|
||||
public VoidHandler2 getMessageHandler() {
|
||||
return messageHandler;
|
||||
}//getMessageHandler()//
|
||||
/**
|
||||
* Gets the initialization complete handler.
|
||||
* @return ?
|
||||
*/
|
||||
public VoidHandler1 getInitCompleteHandler() {
|
||||
return initCompleteHandler;
|
||||
}//getInitCompleteHandler()//
|
||||
/**
|
||||
* Initializes the connection server for use.
|
||||
* The user may call the acceptSocket() method after this method has successfully returned.
|
||||
* @param orb The orb that created the server socket.
|
||||
* @param options The server socket options used to setup the server socket.
|
||||
* @param selector The selector to be used to listen for incomming socket connections.
|
||||
* @param address An optional address only used to optimize performance since the caller often will have to get this address before deciding to create a new server socket.
|
||||
* @param classLoader The class loader that the server socket and all accepted sockets will use for loading classes.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, IServerSocketOptions options, InetAddress address, ClassLoader classLoader, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler) throws IOException {
|
||||
//Setup the external address string.//
|
||||
if((options.getExternalAddress() == null) || (options.getExternalAddress().getName() == null)) {
|
||||
externalAddress = (address != null ? address.getHostAddress() : "") + ':' + options.getAddress().getPort();
|
||||
}//if//
|
||||
else if(options.getExternalAddress().getPort() != Address.INVALID_PORT) {
|
||||
externalAddress = options.getExternalAddress().toString();
|
||||
}//else if//
|
||||
else {
|
||||
externalAddress = options.getExternalAddress().getName() + ":" + options.getAddress().getPort();
|
||||
}//else//
|
||||
|
||||
this.orb = orb;
|
||||
this.options = options;
|
||||
this.messageHandler = messageHandler;
|
||||
this.initCompleteHandler = initCompleteHandler;
|
||||
this.classLoader = classLoader;
|
||||
this.nameAndPort = (address != null ? address.getHostAddress() : "") + ':' + options.getAddress().getPort();
|
||||
this.securityProvider = options.getSecurityProvider();
|
||||
this.options = options;
|
||||
}//initialize()//
|
||||
/**
|
||||
* Gets the server socket options used by the connection server.
|
||||
* @return The options for this connection server.
|
||||
*/
|
||||
protected IServerSocketOptions getServerSocketOptions() {
|
||||
return options;
|
||||
}//getServerSocketOptions()//
|
||||
/**
|
||||
* Gets the security provider that will supply the security system instances for all incomming sockets.
|
||||
* @return The server socket's security provider.
|
||||
*/
|
||||
protected AbstractSecurityProvider getSecurityProvider() {
|
||||
return securityProvider;
|
||||
}//getSecurityProvider()//
|
||||
}//AbstractConnectionServer//
|
||||
243
Orb/src/com/de22/orb/Address.java
Normal file
243
Orb/src/com/de22/orb/Address.java
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import com.common.comparison.Comparator;
|
||||
import com.common.debug.*;
|
||||
|
||||
public class Address implements IAddress {
|
||||
public static final int INVALID_PORT = -1;
|
||||
|
||||
private String name = null;
|
||||
private int port = INVALID_PORT;
|
||||
private String resource = null;
|
||||
/**
|
||||
* Address constructor.
|
||||
*/
|
||||
public Address() {
|
||||
this(null, -1, null);
|
||||
}//Address()//
|
||||
/**
|
||||
* Address constructor.
|
||||
* @param address The address in string form which follows the URL rules.
|
||||
*/
|
||||
public Address(String address) {
|
||||
super();
|
||||
|
||||
parseAddress(address);
|
||||
}//Address()//
|
||||
/**
|
||||
* Address constructor.
|
||||
* @param name The address URL or IP address.
|
||||
* @param port The address port number.
|
||||
*/
|
||||
public Address(String name, int port) {
|
||||
this(name, port, null);
|
||||
}//Address()//
|
||||
/**
|
||||
* Address constructor.
|
||||
* <p>Note: At least one of the parameters should normally be non-null. Some methods will require that multiple parameters be non-null.</p>
|
||||
* @param name The address URL or IP address.
|
||||
* @param port The address port number.
|
||||
* @param resource The referenced resource at the address.
|
||||
*/
|
||||
public Address(String name, int port, String resource) {
|
||||
super();
|
||||
|
||||
this.name = name;
|
||||
this.port = port;
|
||||
this.resource = resource;
|
||||
}//Address()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#clone()
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}//clone()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode() {
|
||||
return port ^ (name != null ? name.hashCode() : 0) ^ (resource != null ? resource.hashCode() : 0);
|
||||
}//hashCode()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof Address && ((Address) object).port == port && Comparator.equals(((Address) object).name, name) && Comparator.equals(((Address) object).resource, resource);
|
||||
}//equals()//
|
||||
/**
|
||||
* Gets the ip address or machine name that identifies the first part of the address.
|
||||
* @return The IP or URL name of the computer being addressed.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}//getName()//
|
||||
/**
|
||||
* Gets the port number that identifies the second part of the address.
|
||||
* @return The addressed computer's port identifying the listener (server socket) being addressed.
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}//getPort()//
|
||||
/**
|
||||
* Gets the name of the resource that is being referenced at the address.
|
||||
* @return The addressed resource's name.
|
||||
*/
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}//getResource()//
|
||||
/**
|
||||
* Parses the address from a string containing the name and port in the format (or variation of): [protocol]://[name]:[port]/[object].
|
||||
* @param address The address in string form.
|
||||
*/
|
||||
private void parseAddress(String address) {
|
||||
address = address.trim();
|
||||
|
||||
try {
|
||||
int lastIndex = 0;
|
||||
int index = address.indexOf("://", lastIndex);
|
||||
|
||||
//Try both slash directions.//
|
||||
if(index == -1) {
|
||||
index = address.indexOf(":\\\\", lastIndex);
|
||||
}//if//
|
||||
|
||||
//Ignore beginning protocol and slashes.//
|
||||
if(index != -1) {
|
||||
//TODO: Capture the protocol.//
|
||||
lastIndex = index + 3;
|
||||
}//if//
|
||||
|
||||
index = address.indexOf("//", lastIndex);
|
||||
|
||||
//Try both slash directions.//
|
||||
if(index == -1) {
|
||||
index = address.indexOf("\\\\", lastIndex);
|
||||
}//if//
|
||||
|
||||
//Ignore beginning slashes.//
|
||||
if(index != -1) {
|
||||
lastIndex = index + 2;
|
||||
}//if//
|
||||
|
||||
index = address.indexOf(':', lastIndex);
|
||||
|
||||
//Capture the name and or port.//
|
||||
if((index != -1) && (address.indexOf('/', lastIndex) != lastIndex) && (address.indexOf('\\', lastIndex) != lastIndex)) {
|
||||
int index2 = 0;
|
||||
|
||||
if(index != lastIndex) {
|
||||
name = address.substring(lastIndex, index);
|
||||
}//if//
|
||||
|
||||
lastIndex = index + 1;
|
||||
index = address.indexOf('/', lastIndex);
|
||||
index2 = address.indexOf("\\", lastIndex);
|
||||
index = (index2 != -1) && (index2 < index) ? index2 : index;
|
||||
|
||||
if(index == -1) {
|
||||
port = Integer.parseInt(address.substring(lastIndex));
|
||||
lastIndex = -1;
|
||||
}//if//
|
||||
else {
|
||||
port = Integer.parseInt(address.substring(lastIndex, index));
|
||||
lastIndex = index;
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
if((lastIndex != -1) && (name == null) && (address.indexOf('/', lastIndex) != lastIndex) && (address.indexOf('\\', lastIndex) != lastIndex)) {
|
||||
int index2 = address.indexOf("\\", lastIndex);
|
||||
|
||||
index = address.indexOf('/', lastIndex);
|
||||
index = (index2 != -1) && (index2 < index) ? index2 : index;
|
||||
|
||||
if(index == -1) {
|
||||
String part = address.substring(lastIndex);
|
||||
boolean isNumber = true;
|
||||
|
||||
for(int ch = 0; isNumber && ch < part.length(); ch++) {
|
||||
isNumber = Character.isDigit(part.charAt(ch));
|
||||
}//for//
|
||||
|
||||
if(isNumber) {
|
||||
//This allows input of just a port number.//
|
||||
port = Integer.parseInt(part);
|
||||
}//if//
|
||||
else {
|
||||
name = address.substring(lastIndex);
|
||||
}//else//
|
||||
|
||||
lastIndex = -1;
|
||||
}//if//
|
||||
else {
|
||||
name = address.substring(lastIndex, index);
|
||||
lastIndex = index + 1;
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
//Read the resource name.//
|
||||
if(lastIndex != -1) {
|
||||
if(address.startsWith("\\", lastIndex) || address.startsWith("/", lastIndex)) {
|
||||
lastIndex++;
|
||||
}//if//
|
||||
|
||||
resource = address.substring(lastIndex);
|
||||
}//if//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
Debug.halt();
|
||||
}//catch//
|
||||
}//parseAddress()//
|
||||
/**
|
||||
* Sets the ip address or machine name that identifies the first part of the address.
|
||||
* @param name The IP or URL name of the computer being addressed.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}//setName()//
|
||||
/**
|
||||
* Sets the port number that identifies the second part of the address.
|
||||
* @param port The addressed computer's port identifying the listener (server socket) being addressed.
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}//setPort()//
|
||||
/**
|
||||
* Sets the name of the resource that is being referenced at the address.
|
||||
* @param resource The addressed resource's name.
|
||||
*/
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}//setResource()//
|
||||
/**
|
||||
* Gets a string representation of the address.
|
||||
* @return A representation of the address in string form.
|
||||
*/
|
||||
public String toString() {
|
||||
String result = "";
|
||||
|
||||
if(name != null) {
|
||||
result += name;
|
||||
|
||||
if(port != INVALID_PORT) {
|
||||
result += ":" + port;
|
||||
}//if//
|
||||
}//if//
|
||||
else if(port != INVALID_PORT) {
|
||||
result += "<any>:" + port;
|
||||
}//else if//
|
||||
|
||||
if(resource != null) {
|
||||
result += '/' + resource;
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//toString()//
|
||||
}//Address//
|
||||
111
Orb/src/com/de22/orb/BufferRepository.java
Normal file
111
Orb/src/com/de22/orb/BufferRepository.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.common.util.IList;
|
||||
import com.common.util.LiteList;
|
||||
import com.common.util.optimized.IntObjectHashMap;
|
||||
|
||||
/**
|
||||
* This class provides the orb an opportunity to reduce GC by reusing a majority of the buffers, but also increases overhead due to additional synchronization.
|
||||
* The caller must synchronize on the repository prior to checking out or checking in any buffers.
|
||||
*/
|
||||
public class BufferRepository {
|
||||
/** The maximum number of buffers that will be cached. */
|
||||
private final static int maximumCachedBuffers = 100;
|
||||
/** The size of the message buffers. All cached message buffers will be of the same size. */
|
||||
private final static int messageBufferSize = 100000; //Note: This must be larger than the encryption buffer sizes.//
|
||||
/** The only instance of this class. */
|
||||
private final static BufferRepository singleton = new BufferRepository();
|
||||
|
||||
/** The collection of currently cached message buffers. */
|
||||
private LiteList cachedMessageBuffers = new LiteList(maximumCachedBuffers);
|
||||
/** The collection of collections of cached byte buffers. The byte buffer lists are mapped by their size. */
|
||||
private IntObjectHashMap cachedByteBuffers = new IntObjectHashMap(20);
|
||||
/**
|
||||
* Gets the one and only instance of this class.
|
||||
* @return The only instance of this class.
|
||||
*/
|
||||
public static BufferRepository getSingleton() {
|
||||
return singleton;
|
||||
}//getSingleton()//
|
||||
/**
|
||||
* BufferRepository constructor.
|
||||
*/
|
||||
private BufferRepository() {
|
||||
}//BufferRepository()//
|
||||
/**
|
||||
* Gets the size of the message buffers.
|
||||
* <p>Note: The caller does not need to synchronize on this since it must either be final, or set before the orb is started and never changed.</p>
|
||||
* @return The message buffer size.
|
||||
*/
|
||||
public int getMessageBufferSize() {
|
||||
return messageBufferSize;
|
||||
}//getMessageBufferSize()//
|
||||
/**
|
||||
* Checks out a message buffer.
|
||||
* @return The buffer checked out, never null.
|
||||
*/
|
||||
public byte[] checkOutMessageBuffer() {
|
||||
byte[] result;
|
||||
|
||||
if(cachedMessageBuffers.getSize() > 0) {
|
||||
result = (byte[]) cachedMessageBuffers.remove(cachedMessageBuffers.getSize() - 1);
|
||||
}//if//
|
||||
else {
|
||||
result = new byte[messageBufferSize];
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//checkOutMessageBuffer()//
|
||||
/**
|
||||
* Checks in a previously checked out message buffer.
|
||||
* @param buffer The buffer being checked in for reuse.
|
||||
*/
|
||||
public void checkInMessageBuffer(byte[] buffer) {
|
||||
if(buffer.length == messageBufferSize && cachedMessageBuffers.getSize() < maximumCachedBuffers) {
|
||||
cachedMessageBuffers.add(buffer);
|
||||
}//if//
|
||||
}//checkInMessageBuffer()//
|
||||
/**
|
||||
* Checks out a byte buffer.
|
||||
* @param size The size of the required byte buffer.
|
||||
* @return The buffer checked out, never null.
|
||||
*/
|
||||
public ByteBuffer checkOutByteBuffer(int size) {
|
||||
IList buffers = (IList) cachedByteBuffers.get(size);
|
||||
ByteBuffer result;
|
||||
|
||||
if(buffers != null && buffers.getSize() > 0) {
|
||||
result = (ByteBuffer) buffers.remove(buffers.getSize() - 1);
|
||||
}//if//
|
||||
else {
|
||||
result = ByteBuffer.allocate(size);
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//checkOutByteBuffer()//
|
||||
/**
|
||||
* Checks in a previously checked out byte buffer.
|
||||
* @param buffer The buffer being checked in for reuse.
|
||||
*/
|
||||
public void checkInByteBuffer(ByteBuffer buffer) {
|
||||
IList buffers = (IList) cachedByteBuffers.get(buffer.capacity());
|
||||
|
||||
if(buffers == null) {
|
||||
buffers = new LiteList(maximumCachedBuffers);
|
||||
buffers.add(buffer);
|
||||
cachedByteBuffers.put(buffer.capacity(), buffers);
|
||||
}//if//
|
||||
else if(buffers.getSize() < maximumCachedBuffers) {
|
||||
buffers.add(buffer);
|
||||
}//else if//
|
||||
}//checkInByteBuffer()//
|
||||
}//BufferRepository//
|
||||
50
Orb/src/com/de22/orb/DefaultProxyInterfaceLoader.java
Normal file
50
Orb/src/com/de22/orb/DefaultProxyInterfaceLoader.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
public class DefaultProxyInterfaceLoader implements IProxyInterfaceLoader {
|
||||
/**
|
||||
* DefaultProxyInterfaceLoader constructor.
|
||||
*/
|
||||
public DefaultProxyInterfaceLoader() {
|
||||
}//DefaultProxyInterfaceLoader()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IProxyInterfaceLoader#loadDefaultProxyInterface(java.lang.Object, java.lang.ClassLoader)
|
||||
*/
|
||||
public Class loadDefaultProxyInterface(Object proxiedObject, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
Class result = null;
|
||||
String interfaceClassName = proxiedObject.getClass().getName();
|
||||
int index = interfaceClassName.lastIndexOf('.') + 1;
|
||||
|
||||
interfaceClassName = interfaceClassName.substring(0, index) + 'I' + interfaceClassName.substring(index);
|
||||
|
||||
if(classLoader == null) {
|
||||
result = Class.forName(interfaceClassName);
|
||||
}//if//
|
||||
else {
|
||||
result = classLoader.loadClass(interfaceClassName);
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//loadDefaultProxyInterface()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IProxyInterfaceLoader#loadProxyClass(java.lang.Class, java.lang.ClassLoader)
|
||||
*/
|
||||
public Class loadProxyClass(Class interfaceClass, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
Class result = null;
|
||||
|
||||
if(classLoader == null) {
|
||||
result = Class.forName(interfaceClass.getName() + Proxy.PROXY_EXTENSION);
|
||||
}//if//
|
||||
else {
|
||||
result = classLoader.loadClass(interfaceClass.getName() + Proxy.PROXY_EXTENSION);
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//loadProxyClass()//
|
||||
}//DefaultProxyInterfaceLoader//
|
||||
17
Orb/src/com/de22/orb/ExceptionProcessor.java
Normal file
17
Orb/src/com/de22/orb/ExceptionProcessor.java
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
public abstract class ExceptionProcessor {
|
||||
/**
|
||||
* ExceptionProcessor constructor.
|
||||
*/
|
||||
public ExceptionProcessor() {
|
||||
super();
|
||||
}//ExceptionProcessor()//
|
||||
}//ExceptionProcessor//
|
||||
41
Orb/src/com/de22/orb/IAddress.java
Normal file
41
Orb/src/com/de22/orb/IAddress.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
public interface IAddress extends Cloneable {
|
||||
/**
|
||||
* Gets the ip address or machine name that identifies the first part of the address.
|
||||
* @return The IP or URL name of the computer being addressed.
|
||||
*/
|
||||
public String getName();
|
||||
/**
|
||||
* Gets the port number that identifies the second part of the address.
|
||||
* @return The addressed computer's port identifying the listener (server socket) being addressed.
|
||||
*/
|
||||
public int getPort();
|
||||
/**
|
||||
* Gets the name of the resource that is being referenced at the address.
|
||||
* @return The addressed resource's name.
|
||||
*/
|
||||
public String getResource();
|
||||
/**
|
||||
* Sets the ip address or machine name that identifies the first part of the address.
|
||||
* @param name The IP or URL name of the computer being addressed.
|
||||
*/
|
||||
public void setName(String name);
|
||||
/**
|
||||
* Sets the port number that identifies the second part of the address.
|
||||
* @param port The addressed computer's port identifying the listener (server socket) being addressed.
|
||||
*/
|
||||
public void setPort(int port);
|
||||
/**
|
||||
* Sets the name of the resource that is being referenced at the address.
|
||||
* @param resource The addressed resource's name.
|
||||
*/
|
||||
public void setResource(String resource);
|
||||
}//IAddress//
|
||||
25
Orb/src/com/de22/orb/IProxyInterfaceLoader.java
Normal file
25
Orb/src/com/de22/orb/IProxyInterfaceLoader.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
public interface IProxyInterfaceLoader {
|
||||
/**
|
||||
* Loads the proxied interface class given the proxied object.
|
||||
* <p>Usually this puts an I infront of the class name and hopes the class exists.</p>
|
||||
* @param proxiedObject The proxied object.
|
||||
* @return The interface class to be proxied.
|
||||
*/
|
||||
public Class loadDefaultProxyInterface(Object proxiedObject, ClassLoader classLoader) throws ClassNotFoundException;
|
||||
/**
|
||||
* Loads the proxy class given the proxied interface class and an optional class loader.
|
||||
* @param interfaceClass The class that will be proxied.
|
||||
* @param classLoader The optional class loader used to load the proxy class.
|
||||
* @return The proxy class.
|
||||
*/
|
||||
public Class loadProxyClass(Class interfaceClass, ClassLoader classLoader) throws ClassNotFoundException;
|
||||
}//IProxyInterfaceLoader//
|
||||
16
Orb/src/com/de22/orb/IProxyInvalidListener.java
Normal file
16
Orb/src/com/de22/orb/IProxyInvalidListener.java
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
public interface IProxyInvalidListener {
|
||||
/**
|
||||
* Called when the proxy becomes invalid due to a socket closure or fatal error.
|
||||
* @param proxy The proxy that is no longer valid.
|
||||
*/
|
||||
public void onProxyInvalid(Proxy proxy);
|
||||
}//IProxyInvalidListener//
|
||||
41
Orb/src/com/de22/orb/IReconnectListener.java
Normal file
41
Orb/src/com/de22/orb/IReconnectListener.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import com.common.util.ICollection;
|
||||
|
||||
public interface IReconnectListener {
|
||||
/**
|
||||
* Notifies the listener that the orb is starting a reconnection of a lost socket.
|
||||
* @param socketNames The collection of names used to create the socket (there could be many since the orb doesn't create a second socket to the same address, but the code to create the socket may not use the same name as the first call to create the socket). Only active names are in this collection (ie calls to close the socket by a name will remove the name from the collection if it was only referenced the one time).
|
||||
* @return The listener generated identifier which will be passed to subsiquent method calls about this reconnection attempt.
|
||||
*/
|
||||
public Object startingReconnect(ICollection socketNames);
|
||||
/**
|
||||
* Checks the listener to see if the ORB should continue to reconnect. This allows the listener to cancel the reconnect if the user no longer wishes to keep trying.
|
||||
* @param reconnectIdentifier The identifier returned as a result of the call to startingReconnect(..).
|
||||
* @return Whether the ORB should continue to reconnect.
|
||||
*/
|
||||
public boolean keepReconnecting(Object reconnectIdentifier);
|
||||
/**
|
||||
* Notifies the listener that the reconnection attempt has succeeded and the ORB is no longer trying to reconnect.
|
||||
* @param reconnectIdentifier The identifier returned as a result of the call to startingReconnect(..).
|
||||
*/
|
||||
public void reconnectSucceeded(Object reconnectIdentifier);
|
||||
/**
|
||||
* Notifies the listener that the reconnection attempt has failed and the ORB is no longer trying to reconnect.
|
||||
* @param reconnectIdentifier The identifier returned as a result of the call to startingReconnect(..).
|
||||
*/
|
||||
public void reconnectFailed(Object reconnectIdentifier);
|
||||
/**
|
||||
* Notifies the listener of how much time is remaining before the reconnection attempts cease.
|
||||
* @param reconnectIdentifier The identifier returned as a result of the call to startingReconnect(..).
|
||||
* @param remainingTime The number of milliseconds before the connection attempts cease.
|
||||
*/
|
||||
public void reconnectRemainingTime(Object reconnectIdentifier, long remainingTime);
|
||||
}//IReconnectListener//
|
||||
19
Orb/src/com/de22/orb/IResultCallback.java
Normal file
19
Orb/src/com/de22/orb/IResultCallback.java
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2004,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
/**
|
||||
* Defines the method that will be called by the orb when a bi-directional method call returns a result and the caller didn't want to wait.
|
||||
*/
|
||||
public interface IResultCallback {
|
||||
/**
|
||||
* Called when a remote call receives a result and the thread didn't wait around.
|
||||
* @param result The result that was received.
|
||||
*/
|
||||
public void run(Object result);
|
||||
}//IResultCallback//
|
||||
77
Orb/src/com/de22/orb/IServerSocketOptions.java
Normal file
77
Orb/src/com/de22/orb/IServerSocketOptions.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import com.de22.orb.security.AbstractSecurityProvider;
|
||||
|
||||
public interface IServerSocketOptions {
|
||||
/**
|
||||
* Gets the address that the server socket will listen on.
|
||||
* @return The address the orb will find or create a server socket for.
|
||||
*/
|
||||
public Address getAddress();
|
||||
/**
|
||||
* Gets the URIs for downloading the latest application version.
|
||||
* @return The URI's useable by the client to download the latest version of the client application. Handling of these URI's is application specific. They will passed to the client's IVersionChangeHandler.
|
||||
*/
|
||||
public String[] getDownloadUris();
|
||||
/**
|
||||
* Gets the size of the backlog that the server socket will maintain.
|
||||
* @return The server socket's backlog size, or null to use the default value for the server socket.
|
||||
*/
|
||||
public Integer getBacklog();
|
||||
/**
|
||||
* Gets the externally visible address and optional port that clients may reconnect through.
|
||||
* <p>This allows clients to reconnect to the exact same server when the actual server address may be internal (and visible only via NAT or some other networking layer).
|
||||
* Often times a server farm may have multiple servers a client may connect to and the default address for a service will be redirected to one of the identical servers.
|
||||
* This feature allows the client to connect to the exact same server as the last time it connected so that the session information may be reused which will increase overall performance.</p>
|
||||
* @return The address the server socket is visible on externally such that clients can reconnect. This may be null if the address that the server socket opens on is externally visible to clients. The port number may be optionally specified if it differs from the port number the server socket listens on.
|
||||
*/
|
||||
public Address getExternalAddress();
|
||||
/**
|
||||
* Gets the socket options that all accepted sockets will use.
|
||||
* @return Socket options accepted sockets will adhere to.
|
||||
*/
|
||||
public ISocketOptions getSocketOptions();
|
||||
/**
|
||||
* Gets the number of milliseconds the server will wait for the client to auto-reconnect.
|
||||
* @return The count of milliseconds the server will wait for a client to connect back up after a socket failure before the application is notified of the failure. Any value less than 1000 will be equivalent to zero and a zero value indicates that the orb will not allow the client to reconnect automatically.
|
||||
*/
|
||||
public long getAutoReconnectTimeLimit();
|
||||
/**
|
||||
* Gets the number of milliseconds between keep alive messages. If there has been any outbound activity between keep alive messages then the next keep alive will not be sent.
|
||||
* @return The time between attempts to send keep alive messages.
|
||||
*/
|
||||
public long getKeepAliveInterval();
|
||||
/**
|
||||
* Gets the security provider that will supply the security system instances for all incomming sockets.
|
||||
* @return The server socket's security provider.
|
||||
*/
|
||||
public AbstractSecurityProvider getSecurityProvider();
|
||||
/**
|
||||
* Gets the NIO Engine to be used for the server socket being created.
|
||||
* @return The optional custom NIO Engine for the server socket.
|
||||
*/
|
||||
public NioEngine getNioEngine();
|
||||
/**
|
||||
* Gets the size of the signature returned to the client.
|
||||
* @param applicationProtocolVersion The version of the application - used to determine what algorithms and keys are to be used when signing the messages to the client.
|
||||
* @return The number of bytes in the signature.
|
||||
*/
|
||||
public int getSignatureSize(int applicationProtocolVersion);
|
||||
/**
|
||||
* Provides the server an opportunity to sign the passed data to authenticate to the client that the server is who it says it is.
|
||||
* The idea is that the client will send a timestamp to the server in the handshake and the server will sign the timestamp and the client can then verify the server's signature.
|
||||
* This prevents a spoofed server instructing a valid client from download a bogus version of the client.
|
||||
* @param applicationProtocolVersion The application's protocol version passed by the client. This can be used to select which algorithm and private key to use when signing - allowing for keys and algorithms to be updated and still be backward compatable.
|
||||
* @param unsignedBytes The bytes of data to be signed.
|
||||
* @param responseBytes The bytes of the message being sent to the client. These bytes should be hashed with the same algorithm as the client, xor'd with the unsigned bytes (also a hash), which is then signed.
|
||||
* @return The signature bytes, or null if no signature is being used.
|
||||
*/
|
||||
public byte[] sign(int applicationProtocolVersion, byte[] unsignedBytes, byte[] responseBytes);
|
||||
}//IServerSocketOptions//
|
||||
16
Orb/src/com/de22/orb/ISocketCloseListener.java
Normal file
16
Orb/src/com/de22/orb/ISocketCloseListener.java
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
public interface ISocketCloseListener {
|
||||
/**
|
||||
* Called when the socket closes.
|
||||
* @param socket The socket that is closing.
|
||||
*/
|
||||
public void onSocketClosed(AbstractConnection socket);
|
||||
}//ISocketCloseListener//
|
||||
80
Orb/src/com/de22/orb/ISocketOptions.java
Normal file
80
Orb/src/com/de22/orb/ISocketOptions.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import com.common.security.IHashAlgorithm;
|
||||
|
||||
/**
|
||||
* Provides the orb with the options for the socket being created, or for each socket created via the server socket these options are attached to.
|
||||
*/
|
||||
public interface ISocketOptions {
|
||||
/**
|
||||
* Gets the timeout used while attempting to connect to the server.
|
||||
* @return The timeout value in milliseconds.
|
||||
*/
|
||||
public int getSocketConnectionTimeout();
|
||||
/**
|
||||
* Gets the permissions object associated with this socket.
|
||||
* @return The permissions that callers over this socket have.
|
||||
*/
|
||||
public Object getPermissions();
|
||||
/**
|
||||
* Gets the addresses that the orb will use to first locate an existing socket, and then attempt to connect on.
|
||||
* @return The addresses the orb will find or create a socket for.
|
||||
*/
|
||||
public Address[] getAddresses();
|
||||
/**
|
||||
* Determines whether the tcp no delay algorithm should be used for the socket.
|
||||
* @return Whether TCP no delay will be used.
|
||||
*/
|
||||
public boolean useTcpNoDelay();
|
||||
/**
|
||||
* Gets the application protocol version for this connection (or connections if associated with a server socket).
|
||||
* @return The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
*/
|
||||
public int getApplicationProtocolVersion();
|
||||
/**
|
||||
* Gets the stream injector used by the socket.
|
||||
* @return The stream injector to be used when creating streams for the socket.
|
||||
*/
|
||||
public IStreamInjector getStreamInjector();
|
||||
/**
|
||||
* Gets the manipulator which if provided will be called prior to serializing or deserializing a class name.
|
||||
* @return The manipulator which allows the application to control whether the class names being received or sent are mangled or not.
|
||||
*/
|
||||
public IStreamClassNameManipulator getStreamClassNameManipulator();
|
||||
/**
|
||||
* Gets the NIO Engine to be used for the server socket being created.
|
||||
* @return The optional custom NIO Engine for the server socket.
|
||||
*/
|
||||
public NioEngine getNioEngine();
|
||||
/**
|
||||
* Gets the handler called when the orb detects a newer version of the application is required to connect to the server.
|
||||
* @return The handler invoked when the orb requires the application be updated.
|
||||
*/
|
||||
public IVersionChangeHandler getVersionChangeHandler();
|
||||
/**
|
||||
* Gets the expected signature size in terms of bytes.
|
||||
* @return The count of bytes in a signature expected by the socket options.
|
||||
*/
|
||||
public int getSignatureSize();
|
||||
/**
|
||||
* Gets the algorithm used to hash the message for signing.
|
||||
* @return The algorithm the client will use to hash messages received from the server to authenticate them.
|
||||
*/
|
||||
public IHashAlgorithm getHashAlgorithm();
|
||||
/**
|
||||
* Determines whether the server's signature is valid, authenticating that the server is who it says it is.
|
||||
* This method assumes that the client is valid and has a valid public key.
|
||||
* The default implementation performs no validation.
|
||||
* @param data The data sent to the server.
|
||||
* @param signedData The signed data.
|
||||
* @return Whether the signed data matches the data.
|
||||
*/
|
||||
public boolean isValidSignature(byte[] data, byte[] signedData);
|
||||
}//ISocketOptions//
|
||||
26
Orb/src/com/de22/orb/IStreamClassNameManipulator.java
Normal file
26
Orb/src/com/de22/orb/IStreamClassNameManipulator.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
/**
|
||||
* Allows an application control over whether certain class names are mangled or demangled over a socket.
|
||||
*/
|
||||
public interface IStreamClassNameManipulator {
|
||||
/**
|
||||
* Provides the implementation a chance to either mangle or demangle the class name prior to sending it.
|
||||
* @param className The class name to be manipulated.
|
||||
* @return The modified class name to be sent.
|
||||
*/
|
||||
public String send(String className);
|
||||
/**
|
||||
* Provides the implementation a chance to either mangle or demangle the class name after receiving it and prior to placing or using it in the deserialized model.
|
||||
* @param className The class name received.
|
||||
* @return The modified class name, possibly to be used to instantiate objects necessary for deserialization.
|
||||
*/
|
||||
public String receive(String className);
|
||||
}//IStreamClassNameManipulator//
|
||||
29
Orb/src/com/de22/orb/IStreamInjector.java
Normal file
29
Orb/src/com/de22/orb/IStreamInjector.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import com.de22.orb.io.IOrbInputStream;
|
||||
import com.de22.orb.io.IOrbOutputStream;
|
||||
|
||||
/**
|
||||
* Allows the application to inject its own streams into the stream stack used by the orb. This can be used to do things like compress the messages.
|
||||
*/
|
||||
public interface IStreamInjector {
|
||||
/**
|
||||
* Injects stream instances into the stack being created by the orb for sending and receiving messages.
|
||||
* @param in The stream that should be wrappered by the application's streams.
|
||||
* @return The top most application stream in the stack that the orb will end up using.
|
||||
*/
|
||||
public IOrbInputStream inject(IOrbInputStream in);
|
||||
/**
|
||||
* Injects stream instances into the stack being created by the orb for sending and receiving messages.
|
||||
* @param out The stream that should be wrappered by the application's streams.
|
||||
* @return The top most application stream in the stack that the orb will end up using.
|
||||
*/
|
||||
public IOrbOutputStream inject(IOrbOutputStream out);
|
||||
}//IStreamInjector//
|
||||
21
Orb/src/com/de22/orb/IVersionChangeHandler.java
Normal file
21
Orb/src/com/de22/orb/IVersionChangeHandler.java
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
/**
|
||||
* Allows the application to provide a handler for when the server determines the client must upgrade to a newer version.
|
||||
*/
|
||||
public interface IVersionChangeHandler {
|
||||
/**
|
||||
* Requests that the client download the new application version(s).
|
||||
* <p><b> ** This method should return immediatly. ** </b></p>
|
||||
* @param uris The URI's useable to download the new version of the client.
|
||||
* @param isRequired Whether the version must be upgraded for the client to connect to the server.
|
||||
*/
|
||||
public void newVersionAvailable(String[] uris, boolean isRequired);
|
||||
}//IVersionChangeHandler//
|
||||
153
Orb/src/com/de22/orb/MessageFilter.java
Normal file
153
Orb/src/com/de22/orb/MessageFilter.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package com.de22.orb;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.util.StreamBuffer;
|
||||
|
||||
public class MessageFilter {
|
||||
/** Indicates that the filter processed the data properly and that the output should be used if there is any. Anything left in the input stream buffer will be saved for future use (when additional bytes arrive). */
|
||||
public static final int RESULT_OK = 0;
|
||||
/** Indicates that the filter did not perform any operation on the data. The input data should be provided as is to the next filter in the chain. The output stream buffer will be ignored. */
|
||||
public static final int RESULT_NO_OPERATION = 2;
|
||||
|
||||
/** The next filter in the input chain. */
|
||||
private MessageFilter inFilter = null;
|
||||
/** The next filter in the output chain. */
|
||||
private MessageFilter outFilter = null;
|
||||
/** The remaining input bytes that could not be processed in the last set of message bytes. */
|
||||
private StreamBuffer inputBuffer = null;
|
||||
/** The remaining input bytes that could not be processed in the last set of message bytes. */
|
||||
private StreamBuffer outputBuffer = null;
|
||||
/**
|
||||
* Called by the system when the filter has an oportunity to handle or alter an incomming message before handled by the orb.
|
||||
* @param input The incomming stream of content.
|
||||
* @param output The outgoing stream of content which will be processed by the next filter.
|
||||
* @return The result of the processing.
|
||||
*/
|
||||
public int processIncommingMessage(StreamBuffer input, StreamBuffer output) {
|
||||
return RESULT_NO_OPERATION;
|
||||
}//processIncommingMessage()//
|
||||
/**
|
||||
* Called by the system when the filter has an oportunity to handle or alter an outgoing message before sent over the socket.
|
||||
* @param input The incomming stream of content.
|
||||
* @param output The outgoing stream of content which will be processed by the next filter.
|
||||
* @return The result of the processing.
|
||||
*/
|
||||
public int processOutgoingMessage(StreamBuffer input, StreamBuffer output) {
|
||||
return RESULT_NO_OPERATION;
|
||||
}//processOutgoingMessage()//
|
||||
/**
|
||||
* Handles an incomming message either from the Socket or a previous filter in the chain.
|
||||
* @param input The bytes that are the input to this filter.
|
||||
*/
|
||||
private void startIncommingMessage(StreamBuffer input) {
|
||||
StreamBuffer buffer;
|
||||
StreamBuffer output = new StreamBuffer();
|
||||
|
||||
if(inputBuffer == null) {
|
||||
buffer = input;
|
||||
}//if//
|
||||
else {
|
||||
inputBuffer.writeBytes(input);
|
||||
buffer = inputBuffer;
|
||||
}//else//
|
||||
|
||||
switch(processIncommingMessage(buffer, output)) {
|
||||
case RESULT_OK: {
|
||||
if(output.getSize() > 0) {
|
||||
//Forward output bytes to the next filter.//
|
||||
if(inFilter != null) {
|
||||
inFilter.startIncommingMessage(output);
|
||||
}//if//
|
||||
else {
|
||||
//TODO: Pass the message to the ORB.
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
//Save any remaining input for use when additional bytes come into the filter.//
|
||||
if(input.getSize() > 0) {
|
||||
inputBuffer = input;
|
||||
}//if//
|
||||
break;
|
||||
}//case//
|
||||
case RESULT_NO_OPERATION: {
|
||||
if(input.getSize() > 0) {
|
||||
//Forward the input bytes to the next filter.//
|
||||
if(inFilter != null) {
|
||||
inFilter.startIncommingMessage(input);
|
||||
}//if//
|
||||
else {
|
||||
//TODO: Pass the message to the ORB.
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
inputBuffer = null;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log(new RuntimeException("Invalid result type."));
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
}//startIncommingMessage()//
|
||||
/**
|
||||
* Handles an outgoing message either from the ORB or a previous filter in the chain.
|
||||
* @param input The bytes that are the input to this filter.
|
||||
*/
|
||||
private void startOutgoingMessage(StreamBuffer input) {
|
||||
StreamBuffer buffer;
|
||||
StreamBuffer output = new StreamBuffer();
|
||||
|
||||
if(outputBuffer == null) {
|
||||
buffer = input;
|
||||
}//if//
|
||||
else {
|
||||
outputBuffer.writeBytes(input);
|
||||
buffer = outputBuffer;
|
||||
}//else//
|
||||
|
||||
switch(processIncommingMessage(buffer, output)) {
|
||||
case RESULT_OK: {
|
||||
if(output.getSize() > 0) {
|
||||
//Forward output bytes to the next filter.//
|
||||
if(inFilter != null) {
|
||||
inFilter.startOutgoingMessage(output);
|
||||
}//if//
|
||||
else {
|
||||
//TODO: Pass the output to the socket.
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
//Save any remaining input for use when additional bytes come into the filter.//
|
||||
if(input.getSize() > 0) {
|
||||
outputBuffer = input;
|
||||
}//if//
|
||||
break;
|
||||
}//case//
|
||||
case RESULT_NO_OPERATION: {
|
||||
if(input.getSize() > 0) {
|
||||
//Forward the input bytes to the next filter.//
|
||||
if(inFilter != null) {
|
||||
inFilter.startOutgoingMessage(input);
|
||||
}//if//
|
||||
else {
|
||||
//TODO: Pass the output to the socket.
|
||||
}//else//
|
||||
}//if//
|
||||
|
||||
outputBuffer = null;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log(new RuntimeException("Invalid result type."));
|
||||
break;
|
||||
}//default//
|
||||
}//switch//
|
||||
}//startOutgoingMessage()//
|
||||
/**
|
||||
* Called when processing an incomming message that requires an immediate response that should not go through higher level filters.
|
||||
* @param output The contents of the message being sent.
|
||||
*/
|
||||
public final void sendMessage(StreamBuffer output) {
|
||||
|
||||
}//sendMessage()//
|
||||
}//MessageFilter//
|
||||
431
Orb/src/com/de22/orb/NioConnection.java
Normal file
431
Orb/src/com/de22/orb/NioConnection.java
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.event.VoidHandler1;
|
||||
import com.common.event.VoidHandler2;
|
||||
import com.common.io.ObjectInputStream;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.thread.ThreadService;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.AbstractConnection.SocketData;
|
||||
import com.de22.orb.exception.NewVersionFoundException;
|
||||
import com.de22.orb.io.OrbObjectOutputStream;
|
||||
|
||||
/**
|
||||
* A non-blocking socket implementation.
|
||||
*/
|
||||
public class NioConnection extends AbstractConnection {
|
||||
/** The NIO engine used by the socket. */
|
||||
private NioEngine nioEngine = null;
|
||||
|
||||
/**
|
||||
* Encapsulates the underlying actual connection to the remote machine and the connection's state, such that if the connection fails, this data object can be swapped out for a new connection (upon a successful reconnect).
|
||||
*/
|
||||
public class NioSocketData extends SocketData implements NioEngine.ISocketHandler {
|
||||
/** The actual socket channel that will be used for transmission and reception of messages. */
|
||||
private SocketChannel socketChannel = null;
|
||||
/** The selection key is used to link the socket to the selector which allows multiple sockets to be serviced by a single or pool of threads. */
|
||||
private SelectionKey key = null;
|
||||
/** The incomming raw bytes from the socket. */
|
||||
private StreamBuffer rawInputBuffer = null;
|
||||
/** The outgoing raw bytes from the orb. */
|
||||
private StreamBuffer rawOutputBuffer = null;
|
||||
|
||||
/**
|
||||
* StSocketData constructor.
|
||||
* @param nioEngine The engine used to handle NIO listening.
|
||||
* @param socketChannel The actual socket channel that will be used for transmission and reception of messages.
|
||||
* @param key The selection key is used to link the socket to the selector which allows multiple sockets to be serviced by a single or pool of threads.
|
||||
*/
|
||||
public NioSocketData(SocketChannel socketChannel, SelectionKey key) throws IOException {
|
||||
super();
|
||||
this.socketChannel = socketChannel;
|
||||
this.key = key;
|
||||
nioEngine.start();
|
||||
}//NioSocketData()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.SocketData#close()
|
||||
*/
|
||||
protected void close() {
|
||||
if(key != null) {
|
||||
try {
|
||||
key.interestOps(0);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Ignored.//
|
||||
}//catch//
|
||||
}//if//
|
||||
|
||||
if(socketChannel != null) {
|
||||
try {
|
||||
socketChannel.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Ignored.//
|
||||
}//catch//
|
||||
}//if//
|
||||
|
||||
nioEngine.stop();
|
||||
}//close()//
|
||||
/**
|
||||
* Gets the actual socket channel that will be used for transmission and reception of messages.
|
||||
* @return The socket channel.
|
||||
*/
|
||||
public SocketChannel getSocketChannel() {
|
||||
return socketChannel;
|
||||
}//getSocketChannel()//
|
||||
/**
|
||||
* Gets the selection key is used to link the socket to the selector which allows multiple sockets to be serviced by a single or pool of threads.
|
||||
* @return The selection key.
|
||||
*/
|
||||
public SelectionKey getKey() {
|
||||
return key;
|
||||
}//getKey()//
|
||||
/**
|
||||
* Gets the NIO engine used by the socket.
|
||||
* @return The socket's NIO engine.
|
||||
*/
|
||||
public NioEngine getNioEngine() {
|
||||
return nioEngine;
|
||||
}//getNioEngine()//
|
||||
/**
|
||||
* Called by the NIO Engine when the socket has available bytes for reading.
|
||||
* @param buffer The reusable buffer provided to the thread for reading data off the socket.
|
||||
*/
|
||||
public void receivePendingMessages(ByteBuffer buffer) {
|
||||
try {
|
||||
if(rawInputBuffer == null) {
|
||||
rawInputBuffer = new StreamBuffer();
|
||||
}//if//
|
||||
|
||||
//Read until the socket is out of available bytes.//
|
||||
do {
|
||||
//Prepare the buffer for writting.//
|
||||
buffer.clear();
|
||||
//Read data from the socket to the buffer. If the buffer cannot be filled then the buffer's eventual limit will not equal the buffer's capacity.//
|
||||
socketChannel.read(buffer);
|
||||
//Prepare the buffer for reading.//
|
||||
buffer.flip();
|
||||
//Buffer the available bytes to the raw input buffer.//
|
||||
rawInputBuffer.writeBytes(buffer);
|
||||
} while(buffer.limit() == buffer.capacity());
|
||||
|
||||
//Process as much of the raw buffer as possible.//
|
||||
receiveMessage(rawInputBuffer);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
//Note: This will happen when the client forcably closes the connection.//
|
||||
NioConnection.this.close(true, false);
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//receivePendingMessages()//
|
||||
/**
|
||||
* Called by the NIO Engine when the socket has available capacity for writing.
|
||||
* <p>Note: We are using the NioSocketData's monitor for ensuring that another thread doesn't add content to be written while we are sending content to be written.</p>
|
||||
* @param buffer The reusable buffer provided to the thread for reading data off the socket.
|
||||
*/
|
||||
public synchronized void sendPendingMessages(ByteBuffer buffer) {
|
||||
try {
|
||||
if(rawOutputBuffer != null) {
|
||||
//Ensure that the buffer will report no bytes available to be written.//
|
||||
buffer.position(buffer.limit());
|
||||
|
||||
//Keep sending as long as all bytes were sent via the socket and there are more bytes in the raw output buffer.//
|
||||
while(!buffer.hasRemaining() && rawOutputBuffer.getSize() > 0) {
|
||||
//Prepare the buffer to be written to.//
|
||||
buffer.clear();
|
||||
//Gets as many bytes as possible placed in the buffer.//
|
||||
rawOutputBuffer.getBytes(0, buffer);
|
||||
//Prepare the buffer to be read from.//
|
||||
buffer.flip();
|
||||
//Write as much as possible to the socket.//
|
||||
socketChannel.write(buffer);
|
||||
//Remove the written bytes from the raw output buffer.//
|
||||
rawOutputBuffer.skipBytes(buffer.position());
|
||||
}//while//
|
||||
|
||||
if(rawOutputBuffer.getSize() > 0) {
|
||||
synchronized(key) {
|
||||
//Turn on the write flag.//
|
||||
key.interestOps(key.interestOps() | key.OP_WRITE);
|
||||
}//synchronized//
|
||||
|
||||
key.selector().wakeup();
|
||||
}//if//
|
||||
else {
|
||||
rawOutputBuffer = null;
|
||||
}//else//
|
||||
}//if//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//sendPendingMessages()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.SocketData#writeMessage(com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
protected synchronized void writeMessage(StreamBuffer buffer) {
|
||||
if(rawOutputBuffer != null) {
|
||||
//Add the output to the end of the already pending output. The key will already be flagged for writing.//
|
||||
rawOutputBuffer.writeBytes(buffer);
|
||||
}//if//
|
||||
else {
|
||||
ByteBuffer b = nioEngine.getBuffer();
|
||||
|
||||
rawOutputBuffer = buffer;
|
||||
sendPendingMessages(b);
|
||||
nioEngine.returnBuffer(b);
|
||||
}//else//
|
||||
}//writeMessage()//
|
||||
public void filterInitializationComplete() {
|
||||
super.filterInitializationComplete();
|
||||
|
||||
try {
|
||||
//TODO: Should this be on or off?
|
||||
socketChannel.socket().setKeepAlive(true);
|
||||
}//try//
|
||||
catch(SocketException e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//filterInitializationComplete()//
|
||||
}//NioSocketData//
|
||||
/**
|
||||
* NioSocket constructor.
|
||||
*/
|
||||
public NioConnection() {
|
||||
super();
|
||||
}//NioSocket()//
|
||||
/**
|
||||
* NioSocket constructor.
|
||||
* @param sessionId The session identifier issued by the server socket.
|
||||
* @param autoReconnectTimeLimit The amount of time the server should wait for the client to auto reconnect.
|
||||
*/
|
||||
public NioConnection(long sessionId, long autoReconnectTimeLimit) {
|
||||
super(sessionId, autoReconnectTimeLimit);
|
||||
}//NioSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket#reconnect(java.net.InetAddress, int)
|
||||
*/
|
||||
protected void reconnect(InetAddress address, int port) {
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
socket = new Socket(address, port);
|
||||
//Code that uses the non-blocking connect. Commented because it is more work than it is worth.//
|
||||
//socketChannel = listener.getSelector().provider().openSocketChannel();
|
||||
|
||||
if(socket != null) {
|
||||
SelectionKey key = null;
|
||||
|
||||
//Code that uses the non-blocking connect. Commented because it is more work than it is worth.//
|
||||
// socketChannel.configureBlocking(false);
|
||||
// key = socketChannel.register(listener.getSelector(), SelectionKey.OP_CONNECT);
|
||||
//
|
||||
// //Will return true if the connection was made immediately.//
|
||||
// if(socketChannel.connect(socketAddress)) {
|
||||
// key.interestOps(0);
|
||||
// socketChannel.finishConnect();
|
||||
// }//if//
|
||||
|
||||
NioSocketData socketData;
|
||||
SocketChannel socketChannel = socket.getChannel();
|
||||
|
||||
//Register for read operations.//
|
||||
key = socket.getChannel().register(nioEngine.getSelector(), SelectionKey.OP_READ);
|
||||
//Setup the socket data (the data regarding the socket which may be altered when a reconnect occurs).//
|
||||
socketData = new NioSocketData(socketChannel, key);
|
||||
//Attach the SocketData instance to the key - what the NioEngine will call when the socket is available to be read/written from/to.//
|
||||
key.attach(socketData);
|
||||
//Save the socket data, representing the socket this NioSocket is currently using for the underlying communications.//
|
||||
setSocketData(socketData);
|
||||
//Initialize the socket.//
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.setTcpNoDelay(getSocketOptions().useTcpNoDelay());
|
||||
socket.setSoTimeout(0);
|
||||
socket.setReuseAddress(true);
|
||||
socket.setReceiveBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
socket.setSendBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
//Start the handshake process.//
|
||||
socketData.startHandshake();
|
||||
}//if//
|
||||
}//try//
|
||||
catch(java.net.ConnectException e) {
|
||||
// Debug.log(e);
|
||||
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
}//reconnect()//
|
||||
/**
|
||||
* Initializes the client side socket.
|
||||
* @param orb The orb instance that created this socket.
|
||||
* @param listener The selector listener the socket will be using.
|
||||
* @param address The address to connect to.
|
||||
* @param port The port to connect on.
|
||||
* @param options The socket options that will be used to open the socket and to reconnect the socket.
|
||||
* @param classLoader The loader that will be used to load classes.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, InetAddress address, int port, ISocketOptions options, ClassLoader classLoader, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler, NioEngine nioEngine) throws IOException {
|
||||
Socket s = new Socket();
|
||||
int timeout = options.getSocketConnectionTimeout();
|
||||
|
||||
try {
|
||||
s.connect(new InetSocketAddress(address, port), timeout < 500 ? 500 : timeout);
|
||||
}//try//
|
||||
catch(SocketTimeoutException e) {
|
||||
s = null;
|
||||
}//catch//
|
||||
|
||||
try {
|
||||
final Socket socket = s;
|
||||
|
||||
this.nioEngine = nioEngine;
|
||||
|
||||
//Code that uses the non-blocking connect. Commented because it is more work than it is worth.//
|
||||
//socketChannel = listener.getSelector().provider().openSocketChannel();
|
||||
|
||||
if(socket != null) {
|
||||
|
||||
//Code that uses the non-blocking connect. Commented because it is more work than it is worth.//
|
||||
// socketChannel.configureBlocking(false);
|
||||
// key = socketChannel.register(listener.getSelector(), SelectionKey.OP_CONNECT);
|
||||
//
|
||||
// //Will return true if the connection was made immediately.//
|
||||
// if(socketChannel.connect(socketAddress)) {
|
||||
// key.interestOps(0);
|
||||
// socketChannel.finishConnect();
|
||||
// }//if//
|
||||
|
||||
//Complete the initialization of the socket.//
|
||||
super.initialize(orb, options, classLoader, messageHandler, initCompleteHandler, socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
|
||||
|
||||
//Initialize the socket.//
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.setTcpNoDelay(options.useTcpNoDelay());
|
||||
socket.setSoTimeout(0);
|
||||
socket.setReuseAddress(true);
|
||||
socket.setReceiveBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
socket.setSendBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
|
||||
nioEngine.process(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
SelectionKey key = null;
|
||||
NioSocketData socketData;
|
||||
|
||||
//Setup the socket data (the data regarding the socket which may be altered when a reconnect occurs).//
|
||||
socketData = new NioSocketData(socket.getChannel(), key);
|
||||
//Save the socket data, representing the socket this NioSocket is currently using for the underlying communications.//
|
||||
setSocketData(socketData);
|
||||
|
||||
//Register for read operations.//
|
||||
key = socket.getChannel().register(NioConnection.this.nioEngine.getSelector(), SelectionKey.OP_READ);
|
||||
//Attach the SocketData instance to the key - what the NioEngine will call when the socket is available to be read/written from/to.//
|
||||
key.attach(socketData);
|
||||
//Start the handshake process.//
|
||||
socketData.startHandshake();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
close(true, false);
|
||||
}//catch//
|
||||
}//run()//
|
||||
});
|
||||
}//if//
|
||||
}//try//
|
||||
catch(java.net.ConnectException e) {
|
||||
// Debug.log(e);
|
||||
|
||||
if(s != null) {
|
||||
try {
|
||||
s.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
|
||||
if(s != null) {
|
||||
try {
|
||||
s.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
}//initialize()//
|
||||
/**
|
||||
* Initializes a server side socket accepted through a server socket.
|
||||
* @param orb The orb instance that created this socket.
|
||||
* @param socketChannel The socket channel created by the server socket.
|
||||
* @param serverSocket The server socket that accepted this socket.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, SocketChannel socketChannel, NioConnectionServer serverSocket, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler, NioEngine nioEngine) throws IOException {
|
||||
super.initialize(orb, serverSocket, messageHandler, initCompleteHandler, socketChannel.socket().getInetAddress().getHostAddress() + ':' + socketChannel.socket().getPort());
|
||||
Socket socket = socketChannel.socket();
|
||||
NioSocketData socketData;
|
||||
SelectionKey key;
|
||||
|
||||
//Flag the channel as non-blocking.//
|
||||
socketChannel.configureBlocking(false);
|
||||
//Setup the channel key.//
|
||||
key = socketChannel.register(nioEngine.getSelector(), SelectionKey.OP_READ, this);
|
||||
//Save the NIO engine reference.//
|
||||
this.nioEngine = nioEngine;
|
||||
//Make sure that the socket is setup properly (tcpNoDelay, SoLinger, etc).//
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.setTcpNoDelay(serverSocket.getSocketOptions().useTcpNoDelay());
|
||||
socket.setSoTimeout(0);
|
||||
socket.setReuseAddress(true);
|
||||
socket.setKeepAlive(true);
|
||||
socket.setReceiveBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
socket.setSendBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
//Setup the socket data (the data that might change if the socket is reconnected in the future).//
|
||||
socketData = new NioSocketData(socketChannel, key);
|
||||
socketData.setActivityTime();
|
||||
//Attach the SocketData instance to the key - what the NioEngine will call when the socket is available to be read/written from/to.//
|
||||
key.attach(socketData);
|
||||
//Save the socket data, representing the socket this NioSocket is currently using for the underlying communications.//
|
||||
setSocketData(socketData);
|
||||
}//initialize()//
|
||||
}//NioSocket//
|
||||
126
Orb/src/com/de22/orb/NioConnectionServer.java
Normal file
126
Orb/src/com/de22/orb/NioConnectionServer.java
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.event.VoidHandler1;
|
||||
import com.common.event.VoidHandler2;
|
||||
import com.de22.orb.Orb.SocketInitCompletionHandler;
|
||||
import com.de22.orb.Orb.SocketProcessMessageHandler;
|
||||
|
||||
public class NioConnectionServer extends AbstractConnectionServer implements NioEngine.IServerSocketHandler {
|
||||
/** The channel used to listen for new sockets connecting up. */
|
||||
private ServerSocketChannel serverSocketChannel = null;
|
||||
/** The selection key is used to link the socket to the selector which allows multiple sockets to be serviced by a single or pool of threads. */
|
||||
private SelectionKey key = null;
|
||||
/** The NIO Engine servicing this server socket. */
|
||||
private NioEngine nioEngine = null;
|
||||
/**
|
||||
* NioServerSocket constructor.
|
||||
* @param selectorListener The selector listener used by the server socket.
|
||||
* @param isListenerSocketSpecific Whether the selector listener must be cleaned up with the socket.
|
||||
*/
|
||||
public NioConnectionServer(NioEngine nioEngine) {
|
||||
this.nioEngine = nioEngine;
|
||||
}//NioConnectionServer()//
|
||||
/**
|
||||
* Accepts a socket connection through the server socket.
|
||||
* @return The socket that was accepted.
|
||||
* @throws IOException If the socket accept fails, or if the accepted socket is unable to initialize.
|
||||
*/
|
||||
public void acceptSocket() {
|
||||
try {
|
||||
SocketChannel socketChannel = serverSocketChannel.accept();
|
||||
|
||||
if(socketChannel != null) {
|
||||
NioConnection result = new NioConnection(getNextSessionId(), getServerSocketOptions().getAutoReconnectTimeLimit());
|
||||
|
||||
registerConnection(result);
|
||||
result.initialize(getOrb(), socketChannel, this, getMessageHandler(), getInitCompleteHandler(), nioEngine);
|
||||
Debug.log("Socket listener started on: " + result.getNameAndPort() + " connecting via server socket: " + this.getNameAndPort());
|
||||
}//if//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//acceptSocket()//
|
||||
/**
|
||||
* Closes the abstract server socket and the underlying socket system.
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
try {
|
||||
if(serverSocketChannel != null) {
|
||||
try {
|
||||
serverSocketChannel.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
}//catch//
|
||||
|
||||
//Set the server socket channel and key to null so everyone knows this server socket is not open.//
|
||||
serverSocketChannel = null;
|
||||
key = null;
|
||||
|
||||
super.close();
|
||||
}//if//
|
||||
}//try//
|
||||
finally {
|
||||
if(nioEngine != null) {
|
||||
nioEngine.stop();
|
||||
nioEngine = null;
|
||||
}//if//
|
||||
}//finally//
|
||||
}//close()//
|
||||
/**
|
||||
* Initializes the server socket for use.
|
||||
* The user may call the acceptSocket() method after this method has successfully returned.
|
||||
* @param orb The orb that created the server socket.
|
||||
* @param options The server socket options used to setup the server socket.
|
||||
* @param address An optional address only used to optimize performance since the caller often will have to get this address before deciding to create a new server socket.
|
||||
* @param classLoader The class loader that the server socket and all accepted sockets will use for loading classes.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, IServerSocketOptions options, InetAddress address, ClassLoader classLoader, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler) throws IOException {
|
||||
SocketAddress socketAddress;
|
||||
|
||||
nioEngine.start();
|
||||
|
||||
//Setup the address if necessary.//
|
||||
if((address == null) && (options.getAddress().getName() != null)) {
|
||||
address = InetAddress.getByName(options.getAddress().getName());
|
||||
}//if//
|
||||
|
||||
super.initialize(orb, options, address, classLoader, messageHandler, initCompleteHandler);
|
||||
socketAddress = new InetSocketAddress(address, options.getAddress().getPort());
|
||||
serverSocketChannel = ServerSocketChannel.open();
|
||||
serverSocketChannel.configureBlocking(false);
|
||||
serverSocketChannel.socket().bind(socketAddress, options.getBacklog() != null ? options.getBacklog().intValue() : 50);
|
||||
nioEngine.process(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
key = serverSocketChannel.register(nioEngine.getSelector(), SelectionKey.OP_ACCEPT);
|
||||
key.attach(NioConnectionServer.this);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
try {close();} catch(Throwable e2) {Debug.log(e2);}
|
||||
}//catch//
|
||||
}//run()//
|
||||
});
|
||||
}//internalInitialize()//
|
||||
}//NioConnectionServer//
|
||||
296
Orb/src/com/de22/orb/NioEngine.java
Normal file
296
Orb/src/com/de22/orb/NioEngine.java
Normal file
@@ -0,0 +1,296 @@
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.thread.ThreadService;
|
||||
import com.common.util.LiteList;
|
||||
|
||||
/**
|
||||
* A reusable NIO engine that abstracts the threading model used with NIO.
|
||||
* The user code should attach ISocketHandler and IServerSocketHandler implementations to the keys which will be called when data is available.
|
||||
*/
|
||||
public class NioEngine implements Runnable {
|
||||
private static final int BUFFER_SIZE = 10000;
|
||||
|
||||
private int startCounter = 0;
|
||||
private Selector selector = null;
|
||||
private int maxThreadCount = 0;
|
||||
private int activeThreadCount = 0;
|
||||
private Iterator selectedKeys = null;
|
||||
private volatile boolean stop = true;
|
||||
/** The reusable buffer stack. */
|
||||
private LiteList buffers = new LiteList(20, 40);
|
||||
/** Whether there are any pending tasks. */
|
||||
private volatile boolean hasTasks = false;
|
||||
/** The pending tasks for the engine thread. */
|
||||
private LiteList tasks = new LiteList(10, 20);
|
||||
|
||||
/**
|
||||
* The handler attached to the socket channel's key and called by the engine.
|
||||
*/
|
||||
public interface ISocketHandler {
|
||||
/**
|
||||
* Notifies the handler that the socket channel is able to send additional data.
|
||||
* @param buffer A reusable buffer provided by the NIO Engine for reading messages from the socket channel.
|
||||
*/
|
||||
public void sendPendingMessages(ByteBuffer buffer);
|
||||
/**
|
||||
* Notifies the handler that the socket channel has data available to be read.
|
||||
* @param buffer A reusable buffer provided by the NIO Engine for reading messages from the socket channel.
|
||||
*/
|
||||
public void receivePendingMessages(ByteBuffer buffer);
|
||||
}//ISocketHandler//
|
||||
|
||||
/**
|
||||
* The handler attached to the server socket channel's key and called by the engine.
|
||||
*/
|
||||
public interface IServerSocketHandler {
|
||||
/**
|
||||
* Note: This method should never block.
|
||||
*/
|
||||
public void acceptSocket();
|
||||
}//IServerSocketHandler//
|
||||
/**
|
||||
* NioEngine constructor.
|
||||
* @param maxThreadCount The maximum number of threads the engine should use at any one time. This is also the maximum number of cached buffers (~10kb) used by the engine.
|
||||
* @throws IOException Thrown if the platform does not support NIO operations.
|
||||
*/
|
||||
public NioEngine(int maxThreadCount) throws IOException {
|
||||
this.selector = Selector.open();
|
||||
this.maxThreadCount = maxThreadCount;
|
||||
}//NioEngine()//
|
||||
/**
|
||||
* Stops the network listener.
|
||||
* Note that this may take a short time to complete.
|
||||
*/
|
||||
protected synchronized void stop() {
|
||||
if(--startCounter == 0) {
|
||||
stop = true;
|
||||
selector.wakeup();
|
||||
}//if//
|
||||
}//stop()//
|
||||
/**
|
||||
* Starts the network listener.
|
||||
*/
|
||||
protected synchronized void start() {
|
||||
if(++startCounter == 1) {
|
||||
stop = false;
|
||||
ThreadService.run(this);
|
||||
}//if//
|
||||
}//start()//
|
||||
/**
|
||||
* Cleans up after the client channel.
|
||||
* @param channel The client connection that is now closed.
|
||||
*/
|
||||
private void cleanupClientChannel(SocketChannel channel) {
|
||||
// if(debug) {
|
||||
// Debug.log("Connection closed to " + channel.socket().getInetAddress() + ":" + channel.socket().getPort());
|
||||
// }//if//
|
||||
}//cleanupClientChannel()//
|
||||
/**
|
||||
* Queues a runnable task for processing by the engine thread.
|
||||
* @param runnable The task to be run while there is no thread in the selector.
|
||||
*/
|
||||
public void process(Runnable runnable) {
|
||||
synchronized(this) {
|
||||
hasTasks = true;
|
||||
tasks.add(runnable);
|
||||
}//synchronized//
|
||||
|
||||
selector.wakeup();
|
||||
}//process()//
|
||||
/**
|
||||
* Gets the selector for the engine.
|
||||
* @return The engine's selector.
|
||||
*/
|
||||
public Selector getSelector() {
|
||||
return selector;
|
||||
}//getSelector()//
|
||||
/**
|
||||
* Gets or creates a buffer. The caller must call returnBuffer(ByteBuffer) when done.
|
||||
* @return The reusable buffer.
|
||||
*/
|
||||
public synchronized ByteBuffer getBuffer() {
|
||||
return buffers.getSize() > 0 ? (ByteBuffer) buffers.remove(buffers.getSize() - 1) : ByteBuffer.allocate(BUFFER_SIZE);
|
||||
}//getBuffer()//
|
||||
/**
|
||||
* Reuses the buffer previously retrieved with getBuffer().
|
||||
* @param buffer The buffer retrieved by getBuffer().
|
||||
*/
|
||||
public synchronized void returnBuffer(ByteBuffer buffer) {
|
||||
buffers.add(buffer);
|
||||
}//returnBuffer()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
boolean loop = true;
|
||||
|
||||
//Looping only occurs when we are at the maximum allowed number of threads handling messages.//
|
||||
while(!stop && loop) {
|
||||
SelectionKey key = null;
|
||||
boolean isWrite = false;
|
||||
|
||||
try {
|
||||
//Synchronize so that we ensure thread safe access to the activeThreadCount variable.//
|
||||
// synchronized(this) { //TODO: Remove me when we are sure that the threading works correctly.
|
||||
// if(hasListener) {
|
||||
// Debug.log(new RuntimeException("Failed to properly thread the NetworkListener."));
|
||||
// }//if//
|
||||
//
|
||||
// hasListener = true;
|
||||
// }//synchronized//
|
||||
|
||||
//If we don't have an iterator over the active channels then get one and block if necessary.//
|
||||
if(selectedKeys == null) {
|
||||
int keyCount = 0;
|
||||
|
||||
//Block until we have keys or were awakened by another thread.//
|
||||
keyCount = selector.select();
|
||||
|
||||
//If we have active keys then retrieve them.//
|
||||
if(keyCount > 0) {
|
||||
selectedKeys = selector.selectedKeys().iterator();
|
||||
}//if//
|
||||
|
||||
if(hasTasks) {
|
||||
synchronized(this) {
|
||||
while(tasks.getSize() > 0) {
|
||||
((Runnable) tasks.remove(0)).run();
|
||||
}//while//
|
||||
|
||||
hasTasks = false;
|
||||
}//synchronized//
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
//If we have an iterator over the active channels then get and remove the next one (clean up the iterator if empty).//
|
||||
if(selectedKeys != null) {
|
||||
key = (SelectionKey) selectedKeys.next();
|
||||
selectedKeys.remove();
|
||||
|
||||
//Weed out invalid (cancelled) keys.//
|
||||
if(key.isValid()) {
|
||||
isWrite = key.isWritable();
|
||||
}//if//
|
||||
else {
|
||||
key = null;
|
||||
}//else//
|
||||
|
||||
if(!selectedKeys.hasNext()) {
|
||||
selectedKeys = null;
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
// synchronized(this) { //TODO: Remove me when we are sure that the threading works correctly.
|
||||
// hasListener = false;
|
||||
// }//synchronized//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//TODO: Can we recover?
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
|
||||
if(key != null) {
|
||||
SelectableChannel channel = key.channel();
|
||||
|
||||
if(channel instanceof ServerSocketChannel) {
|
||||
((IServerSocketHandler) key.attachment()).acceptSocket();
|
||||
}//if//
|
||||
else if(channel instanceof SocketChannel) {
|
||||
boolean socketClosed = false;
|
||||
ByteBuffer buffer = null;
|
||||
|
||||
//Toggle the write or read flag.//
|
||||
synchronized(key) {
|
||||
key.interestOps(key.interestOps() ^ (isWrite ? SelectionKey.OP_WRITE : SelectionKey.OP_READ));
|
||||
}//synchronized//
|
||||
|
||||
try {
|
||||
if(((SocketChannel) channel).isOpen()) {
|
||||
synchronized(this) {
|
||||
buffer = buffers.getSize() > 0 ? (ByteBuffer) buffers.remove(buffers.getSize() - 1) : ByteBuffer.allocate(BUFFER_SIZE);
|
||||
|
||||
if(++activeThreadCount != maxThreadCount) {
|
||||
//Start another thread to take this thread's place.//
|
||||
ThreadService.run(this);
|
||||
}//if//
|
||||
}//synchronized//
|
||||
|
||||
if(isWrite) {
|
||||
// if(debug) {
|
||||
// ((SocketContext) context).debugBuffer.append("Socket is now write available.\n");
|
||||
// Debug.log("Socket is write available: " + ((SocketChannel) channel).socket().getInetAddress() + ":" + ((SocketChannel) channel).socket().getPort());
|
||||
// }//if//
|
||||
|
||||
//Process the pending write to the socket as much as is possible, then return.//
|
||||
((ISocketHandler) key.attachment()).sendPendingMessages(buffer);
|
||||
}//if//
|
||||
else {
|
||||
// if(debug) {
|
||||
// ((SocketContext) context).debugBuffer.append("Socket is now read available.\n");
|
||||
// Debug.log("Socket is read available: " + ((SocketChannel) channel).socket().getInetAddress() + ":" + ((SocketChannel) channel).socket().getPort());
|
||||
// }//if//
|
||||
|
||||
//Process the incomming request and send the response (a partial response may be sent in which case the socket will be set to wait for a write opportunity and not a read opportunity).//
|
||||
((ISocketHandler) key.attachment()).receivePendingMessages(buffer);
|
||||
}//else//
|
||||
}//if//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
// if(debug) {
|
||||
// Debug.log(e);
|
||||
// }//if//
|
||||
|
||||
//Force the socket to be closed (for sure).//
|
||||
try {((SocketChannel) channel).close();} catch(Throwable e2) {}
|
||||
//Debug.log(e);
|
||||
socketClosed = true;
|
||||
}//catch//
|
||||
finally {
|
||||
boolean requiresWakeup = false;
|
||||
|
||||
if(channel != null && !socketClosed && channel.isOpen() && key != null) {
|
||||
if(!isWrite) {
|
||||
//Synchronize on the key so we don't conflict with a write operation thread that might be setting the write flag.//
|
||||
synchronized(key) {
|
||||
key.interestOps(SelectionKey.OP_READ | key.interestOps());
|
||||
}//synchronized//
|
||||
|
||||
requiresWakeup = true;
|
||||
}//if//
|
||||
}//if//
|
||||
else if(channel != null && (!channel.isOpen() || socketClosed) && channel instanceof SocketChannel) {
|
||||
cleanupClientChannel((SocketChannel) channel);
|
||||
}//else if//
|
||||
|
||||
//Loop if the last thread to wait for a message couldn't start another thread due to the max number of threads allowed.//
|
||||
synchronized(this) {
|
||||
if(buffer != null) {
|
||||
buffers.add(buffer);
|
||||
}//if//
|
||||
|
||||
if(activeThreadCount-- != maxThreadCount) {
|
||||
loop = false;
|
||||
|
||||
if(requiresWakeup) {
|
||||
selector.wakeup();
|
||||
}//if//
|
||||
}//if//
|
||||
}//synchronized//
|
||||
}//finally//
|
||||
}//else if//
|
||||
}//if//
|
||||
}//while//
|
||||
}//run()//
|
||||
}//NioEngine//
|
||||
2622
Orb/src/com/de22/orb/Orb.java
Normal file
2622
Orb/src/com/de22/orb/Orb.java
Normal file
File diff suppressed because it is too large
Load Diff
183
Orb/src/com/de22/orb/OrbMessageFilter.java
Normal file
183
Orb/src/com/de22/orb/OrbMessageFilter.java
Normal file
@@ -0,0 +1,183 @@
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.util.Date;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.security.IHashAlgorithm;
|
||||
import com.common.security.ISignatureAlgorithm;
|
||||
import com.common.security.RsaAlgorithm;
|
||||
import com.common.security.Sha512;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.AbstractConnection.MessageFilter;
|
||||
import com.de22.orb.AbstractConnection.SocketData;
|
||||
import com.de22.orb.StConnection.StSocketData;
|
||||
import com.de22.orb.exception.AuthenticationException;
|
||||
import com.de22.orb.exception.NewVersionFoundException;
|
||||
import com.de22.orb.io.OrbByteArrayInputStream;
|
||||
import com.de22.orb.io.OrbObjectOutputStream;
|
||||
import com.de22.orb.security.AbstractSecurityProvider;
|
||||
import com.de22.orb.security.AbstractSecuritySystem;
|
||||
|
||||
/**
|
||||
* The final filter in the orb filter stack. Adds a message size to the messages that need it, and marshels messages prior to the orb processing it.
|
||||
*/
|
||||
public class OrbMessageFilter extends MessageFilter {
|
||||
protected static final byte CLOSED = -1;
|
||||
protected static final byte PING = -2;
|
||||
protected static final byte MESSAGE = -3;
|
||||
protected static final byte CLOSE = -4;
|
||||
protected static final byte RECEIVED = -5;
|
||||
|
||||
/** The socket - used to access metadata on the socket & orb for the handshake. */
|
||||
private AbstractConnection socket = null;
|
||||
/**
|
||||
* PreSecurityHandshakeFilter constructor.
|
||||
* @param socket The socket that is the context for this filter.
|
||||
*/
|
||||
public OrbMessageFilter(AbstractConnection socket) {
|
||||
this.socket = socket;
|
||||
}//PreSecurityHandshakeFilter()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processIncommingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processIncommingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
try {
|
||||
switch(input.getByte(0)) {
|
||||
case PING: {
|
||||
//TODO: Note that there was communication on the socket.
|
||||
input.skipBytes(1);
|
||||
break;
|
||||
}//break//
|
||||
case MESSAGE: {
|
||||
if(input.getSize() > 4) {
|
||||
int size = input.getInt(1, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(input.getSize() >= size) {
|
||||
int messageNumber;
|
||||
|
||||
input.skipBytes(5);
|
||||
messageNumber = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
socket.lastVerifiedMessageNumberListenerOnly = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
output.writeBytes(input, size - 13);
|
||||
socket.lastReceivedMessageNumberListenerOnly = messageNumber;
|
||||
}//if//
|
||||
}//if//
|
||||
break;
|
||||
}//break//
|
||||
case CLOSED:
|
||||
case CLOSE: {
|
||||
input.skipBytes(1);
|
||||
//A normal close message.//
|
||||
socket.close(false, false);
|
||||
break;
|
||||
}//break//
|
||||
case RECEIVED: {
|
||||
if(input.getSize() > 4) {
|
||||
int confirmedMessageNumber;
|
||||
|
||||
input.skipBytes(1);
|
||||
confirmedMessageNumber = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//TODO: Synchronize?
|
||||
socket.lastReceivedMessageNumberListenerOnly = confirmedMessageNumber;
|
||||
socket.clearCachedMessages(confirmedMessageNumber);
|
||||
}//if//
|
||||
break;
|
||||
}//break//
|
||||
default: {
|
||||
Debug.log(new RuntimeException("Unexpected message header code."));
|
||||
throw new IOException();
|
||||
}//default//
|
||||
}//switch//
|
||||
}//try//
|
||||
catch(BufferUnderflowException e) {
|
||||
//Ignore - the filter will re-try the message when more bytes arrive.//
|
||||
}//catch//
|
||||
|
||||
return result;
|
||||
}//processIncommingMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processOutgoingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processOutgoingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
output.writeByte(MESSAGE);
|
||||
//Place holder for the message size.//
|
||||
output.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
//The message number.//
|
||||
output.writeInt(socket.getCurrentMessageNumber(), StreamBuffer.NUMBER_LSF);
|
||||
//The last received message number.//
|
||||
output.writeInt(socket.lastReceivedMessageNumberSenderOnly, StreamBuffer.NUMBER_LSF);
|
||||
//Write the message.//
|
||||
output.writeBytes(input);
|
||||
//Write the message size.//
|
||||
output.putInt(1, output.getSize(), StreamBuffer.NUMBER_LSF);
|
||||
|
||||
return result;
|
||||
}//processOutgoingMessage()//
|
||||
/**
|
||||
* Sends a close message to the remote process.
|
||||
*/
|
||||
public void sendClose() {
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
message.writeByte(CLOSE);
|
||||
|
||||
try {
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
//Debug.log(e);
|
||||
//closeConnection(true);
|
||||
}//catch//
|
||||
}//sendClose()//
|
||||
/**
|
||||
* Sends a ping message to the remote process.
|
||||
*/
|
||||
public void sendPing() {
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
message.writeByte(PING);
|
||||
|
||||
try {
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendPing()//
|
||||
/**
|
||||
* Sends a receipt confirmation message to the remote process.
|
||||
* @param confirmationMessageNumber The message number we have received.
|
||||
*/
|
||||
public void sendConfirmation(int confirmationMessageNumber) {
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
message.writeByte(RECEIVED);
|
||||
message.writeInt(confirmationMessageNumber, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
try {
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendConfirmation()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#beginInitialization()
|
||||
*/
|
||||
public boolean beginInitialization() throws IOException {
|
||||
//No initialization required.//
|
||||
return false;
|
||||
}//beginInitialization()//
|
||||
}//PreSecurityHandshakeFilter//
|
||||
371
Orb/src/com/de22/orb/PostSecurityHandshakeFilter.java
Normal file
371
Orb/src/com/de22/orb/PostSecurityHandshakeFilter.java
Normal file
@@ -0,0 +1,371 @@
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Date;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.security.IHashAlgorithm;
|
||||
import com.common.security.ISignatureAlgorithm;
|
||||
import com.common.security.RsaAlgorithm;
|
||||
import com.common.security.Sha512;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.AbstractConnection.MessageFilter;
|
||||
import com.de22.orb.AbstractConnection.SocketData;
|
||||
import com.de22.orb.exception.AuthenticationException;
|
||||
import com.de22.orb.exception.NewVersionFoundException;
|
||||
import com.de22.orb.io.OrbObjectOutputStream;
|
||||
|
||||
/**
|
||||
* The first filter for the ORB handshake. This should be followed by the optional security filter, then the post-security handshake fitler.
|
||||
*/
|
||||
public class PostSecurityHandshakeFilter extends MessageFilter {
|
||||
/** Whether the handshake is actively occuring. */
|
||||
private boolean isHandshaking = false;
|
||||
/** Whether the handshake has finished yet. */
|
||||
private boolean isHandshakeComplete = false;
|
||||
/** Whether the handshake is occuring on the server. */
|
||||
private boolean isServerSide;
|
||||
/** The socket - used to access metadata on the socket & orb for the handshake. */
|
||||
private AbstractConnection socket = null;
|
||||
/** The unsigned date used to authenticate the server's message. */
|
||||
private byte[] unsignedData = null;
|
||||
/** Whether the socket is a reconnection. */
|
||||
private boolean isReconnecting;
|
||||
/** The last received message number used if reconnecting. */
|
||||
private int lastReceivedMessageNumber;
|
||||
/**
|
||||
* PostSecurityHandshakeFilter constructor.
|
||||
* @param isServerSide Whether the handshake is occuring on the server.
|
||||
* @param socket The socket that is the context for this filter.
|
||||
* @param securityFilter The security filter where the optional security system will be placed.
|
||||
* @param isReconnecting Whether the socket is a reconnection.
|
||||
*/
|
||||
public PostSecurityHandshakeFilter(boolean isServerSide, AbstractConnection socket, boolean isReconnecting, int lastReceivedMessageNumber) {
|
||||
this.isServerSide = isServerSide;
|
||||
this.socket = socket;
|
||||
this.isReconnecting = isReconnecting;
|
||||
this.lastReceivedMessageNumber = lastReceivedMessageNumber;
|
||||
}//PostSecurityHandshakeFilter()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processIncommingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processIncommingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
if(isHandshakeComplete) {
|
||||
result = super.processIncommingMessage(input, output);
|
||||
}//if//
|
||||
else {
|
||||
//Debug.log("Running next post-sec handshake.");
|
||||
if(isServerSide) {
|
||||
if(input.getSize() > 3) {
|
||||
int messageSize = input.getInt(0, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(input.getSize() >= messageSize) {
|
||||
byte[] unsignedBytes = null;
|
||||
boolean isReconnect = false;
|
||||
long sessionId = 0;
|
||||
int lastMessageReceived = 0;
|
||||
String sessionPassword = null;
|
||||
int unsignedByteCount;
|
||||
|
||||
input.skipBytes(4);
|
||||
|
||||
switch(input.readByte()) {
|
||||
case 0x0: {
|
||||
break;
|
||||
}//case//
|
||||
case 0x1: {
|
||||
sessionId = input.readLong(StreamBuffer.NUMBER_LSF);
|
||||
lastMessageReceived = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
sessionPassword = input.readString(StreamBuffer.NUMBER_VLSF, null);
|
||||
isReconnect = true;
|
||||
break;
|
||||
}//case//
|
||||
default: {
|
||||
throw new IOException("Unexpected stream identifier.");
|
||||
}//case//
|
||||
}//switch//
|
||||
|
||||
unsignedByteCount = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(unsignedByteCount > 0) {
|
||||
unsignedBytes = new byte[unsignedByteCount];
|
||||
input.readBytes(unsignedBytes);
|
||||
}//if//
|
||||
|
||||
if(isReconnect) {
|
||||
AbstractConnection oldSocket = (AbstractConnection) socket.getServerSocket().getConnection(sessionId);
|
||||
|
||||
if(oldSocket != null && sessionPassword.equals(oldSocket.getSessionPassword())) {
|
||||
//Tell the old socket to reconnect using the underlying connection.//
|
||||
oldSocket.reconnect(socket, lastMessageReceived);
|
||||
//Unregister this socket with the server socket since the connection will be placed inside the old socket.//
|
||||
socket.getServerSocket().unregisterConnection(socket);
|
||||
//Clear the socket data for this socket and set the result to success.//
|
||||
socket.setSocketData(null);
|
||||
//Save the reconnected socket as the handshake's socket so the response will return the correct session information.//
|
||||
socket = oldSocket;
|
||||
//Notify the client that the reconnect was successful.//
|
||||
sendReconnectSuccess(unsignedBytes);
|
||||
}//if//
|
||||
else {
|
||||
sendReconnectFailed(unsignedBytes);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
sendConnectionSuccess(unsignedBytes);
|
||||
}//else//
|
||||
|
||||
//Flag the handshake as completed.//
|
||||
isHandshakeComplete = true;
|
||||
//Initialize the next filter in the bunch.//
|
||||
endInitialization();
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//if//
|
||||
else { //Read the server response.//
|
||||
if(input.getSize() > 3) {
|
||||
int messageSize = input.getInt(0, StreamBuffer.NUMBER_LSF);
|
||||
int signatureSize = socket.getSocketOptions().getSignatureSize();
|
||||
|
||||
if(input.getSize() >= messageSize) {
|
||||
boolean isValid = true;
|
||||
|
||||
//Authenticate the server if we can.//
|
||||
if(signatureSize > 0) {
|
||||
IHashAlgorithm hashAlgorithm = socket.getSocketOptions().getHashAlgorithm();
|
||||
byte[] hashSource = messageSize - signatureSize > 0 ? new byte[messageSize - signatureSize] : null;
|
||||
byte[] signature = new byte[signatureSize];
|
||||
byte[] hash;
|
||||
|
||||
//Initialize the hash algorithm.//
|
||||
input.getBytes(0, hashSource);
|
||||
hashAlgorithm.add(hashSource);
|
||||
//Gather the signature.//
|
||||
input.getBytes(messageSize - signatureSize, signature);
|
||||
hash = hashAlgorithm.hash();
|
||||
|
||||
//Merge the two hashes.//
|
||||
for(int index = 0; index < hash.length; index++) {
|
||||
hash[index] ^= unsignedData[index];
|
||||
}//for//
|
||||
|
||||
//Validate the signature.//
|
||||
isValid = socket.getSocketOptions().isValidSignature(hash, signature);
|
||||
}//if//
|
||||
|
||||
if(!isValid) {
|
||||
throw new AuthenticationException();
|
||||
}//if//
|
||||
|
||||
//Skip the size bytes.//
|
||||
input.skipBytes(4);
|
||||
|
||||
switch(input.readByte()) {
|
||||
case 0x0: { //Normal connection completed successfully.//
|
||||
socket.setSessionId(input.readLong(StreamBuffer.NUMBER_LSF));
|
||||
socket.setSessionPassword(input.readString(StreamBuffer.NUMBER_VLSF, null));
|
||||
break;
|
||||
}//case//
|
||||
case 0x1: { //Reconnect completed successfully.//
|
||||
//TODO:
|
||||
break;
|
||||
}//case//
|
||||
case 0x2: { //Reconnect failed.//
|
||||
//TODO:
|
||||
break;
|
||||
}//case//
|
||||
}//switch//
|
||||
|
||||
//Skip the last bytes in the message which was the signature used above.//
|
||||
input.skipBytes(signatureSize);
|
||||
//Flag the handshake as completed.//
|
||||
isHandshakeComplete = true;
|
||||
//Initialize the next filter in the bunch.//
|
||||
endInitialization();
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//else//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//processIncommingMessage()//
|
||||
/**
|
||||
* Sends the response handshake to the client indicating that the reconnect operation succeeded.
|
||||
* @param unsignedBytes The unsigned bytes to use when signing the response.
|
||||
*/
|
||||
private void sendReconnectSuccess(byte[] unsignedBytes) {
|
||||
int signatureSize = socket.getServerSocket().getServerSocketOptions().getSignatureSize(socket.getSocketOptions().getApplicationProtocolVersion());
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
//Reserve space for the message size.//
|
||||
message.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
//Write the message type.//
|
||||
message.writeByte(0x1);
|
||||
//Write the last message received by the server (so the client can resend any that were not received).//
|
||||
message.writeInt(lastReceivedMessageNumber, StreamBuffer.NUMBER_LSF);
|
||||
//Write the actual size of the message to the client.//
|
||||
message.putInt(0, message.getSize() + signatureSize, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//Write the signature bytes.//
|
||||
if(signatureSize > 0) {
|
||||
//Write the signature at the end of the message.//
|
||||
message.writeBytes(socket.getServerSocket().getServerSocketOptions().sign(socket.getSocketOptions().getApplicationProtocolVersion(), unsignedBytes, message.toByteArray()));
|
||||
}//if//
|
||||
|
||||
try {
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendReconnectSuccess()//
|
||||
/**
|
||||
* Sends the response handshake to the client indicating that the reconnect operation failed (connection will be closed).
|
||||
* @param unsignedBytes The unsigned bytes to use when signing the response.
|
||||
*/
|
||||
private void sendReconnectFailed(byte[] unsignedBytes) {
|
||||
int signatureSize = socket.getServerSocket().getServerSocketOptions().getSignatureSize(socket.getSocketOptions().getApplicationProtocolVersion());
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
//Reserve space for the message size.//
|
||||
message.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
//Write the message type.//
|
||||
message.writeByte(0x2);
|
||||
//Write the actual size of the message to the client.//
|
||||
message.putInt(0, message.getSize() + signatureSize, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//Write the signature bytes.//
|
||||
if(signatureSize > 0) {
|
||||
//Write the signature at the end of the message.//
|
||||
message.writeBytes(socket.getServerSocket().getServerSocketOptions().sign(socket.getSocketOptions().getApplicationProtocolVersion(), unsignedBytes, message.toByteArray()));
|
||||
}//if//
|
||||
|
||||
try {
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendReconnectFailed()//
|
||||
/**
|
||||
* Sends the response handshake to the client indicating that the connection operation succeeded.
|
||||
* @param unsignedBytes The unsigned bytes to use when signing the response.
|
||||
*/
|
||||
private void sendConnectionSuccess(byte[] unsignedBytes) {
|
||||
int signatureSize = socket.getServerSocket().getServerSocketOptions().getSignatureSize(socket.getSocketOptions().getApplicationProtocolVersion());
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
//Reserve space for the message size.//
|
||||
message.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
//Write the message type.//
|
||||
message.writeByte(0x0);
|
||||
//Write the session identifier.//
|
||||
message.writeLong(socket.getSessionId(), StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//Write the session password.//
|
||||
try {
|
||||
message.writeString(socket.getSessionPassword(), StreamBuffer.NUMBER_VLSF, null);
|
||||
}//try//
|
||||
catch(UnsupportedEncodingException e) {
|
||||
Debug.log(e); //Should never happen.//
|
||||
}//catch//
|
||||
|
||||
//Write the actual size of the message to the client.//
|
||||
message.putInt(0, message.getSize() + signatureSize, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//Write the signature bytes.//
|
||||
if(signatureSize > 0) {
|
||||
//Write the signature at the end of the message.//
|
||||
message.writeBytes(socket.getServerSocket().getServerSocketOptions().sign(socket.getSocketOptions().getApplicationProtocolVersion(), unsignedBytes, message.toByteArray()));
|
||||
}//if//
|
||||
|
||||
try {
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendConnectionSuccess()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processOutgoingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processOutgoingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
if(isHandshakeComplete) {
|
||||
result = super.processOutgoingMessage(input, output);
|
||||
}//if//
|
||||
else {
|
||||
//Shouldn't happen.//
|
||||
Debug.log(new RuntimeException());
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//processOutgoingMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#beginInitialization()
|
||||
*/
|
||||
public boolean beginInitialization() throws IOException {
|
||||
if(!isServerSide && !isHandshaking && !isHandshakeComplete) {
|
||||
//Debug.log("Starting Post-Sec Initialization");
|
||||
StreamBuffer buffer = new StreamBuffer();
|
||||
IHashAlgorithm hashAlgorithm = socket.getSocketOptions().getHashAlgorithm();
|
||||
|
||||
//Message size reserved space.//
|
||||
buffer.writeInt(0, StreamSupport.NUMBER_LSF);
|
||||
|
||||
if(isReconnecting) {
|
||||
buffer.writeByte(0x1);
|
||||
buffer.writeLong(socket.getSessionId(), StreamBuffer.NUMBER_LSF);
|
||||
buffer.writeInt(socket.getLastReceivedMessageNumber(), StreamBuffer.NUMBER_LSF);
|
||||
}//if//
|
||||
else {
|
||||
buffer.writeByte(0x0);
|
||||
}//else//
|
||||
|
||||
//Write the message size at the beginning of the stream (the zero'd bytes).//
|
||||
buffer.putInt(0, buffer.getSize() + (hashAlgorithm != null ? hashAlgorithm.getHashSize() + 4 : 4), StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(hashAlgorithm != null) {
|
||||
//Set the unsigned data used to validate the server's authenticity.//
|
||||
byte[] date = new byte[8];
|
||||
StreamSupport.writeLong(new Date().getTime(), date, 0, StreamSupport.NUMBER_LSF);
|
||||
hashAlgorithm.add(date);
|
||||
hashAlgorithm.add(buffer.toByteArray());
|
||||
unsignedData = hashAlgorithm.hash();
|
||||
|
||||
//Write Unsigned Bytes.//
|
||||
buffer.writeInt(unsignedData.length, StreamBuffer.NUMBER_LSF);
|
||||
buffer.writeBytes(unsignedData);
|
||||
}//if//
|
||||
else {
|
||||
buffer.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
}//else//
|
||||
|
||||
//Write the message to the socket.//
|
||||
sendMessage(buffer);
|
||||
isHandshaking = true;
|
||||
}//if//
|
||||
|
||||
return isHandshaking || !isHandshakeComplete;
|
||||
}//beginInitialization()//
|
||||
}//PostSecurityHandshakeFilter//
|
||||
408
Orb/src/com/de22/orb/PreSecurityHandshakeFilter.java
Normal file
408
Orb/src/com/de22/orb/PreSecurityHandshakeFilter.java
Normal file
@@ -0,0 +1,408 @@
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Date;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.security.IHashAlgorithm;
|
||||
import com.common.security.ISignatureAlgorithm;
|
||||
import com.common.security.RsaAlgorithm;
|
||||
import com.common.security.Sha512;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.AbstractConnection.MessageFilter;
|
||||
import com.de22.orb.AbstractConnection.SocketData;
|
||||
import com.de22.orb.exception.AuthenticationException;
|
||||
import com.de22.orb.exception.NewVersionFoundException;
|
||||
import com.de22.orb.io.OrbObjectOutputStream;
|
||||
import com.de22.orb.security.AbstractSecurityProvider;
|
||||
import com.de22.orb.security.AbstractSecuritySystem;
|
||||
|
||||
/**
|
||||
* The first filter for the ORB handshake. This should be followed by the optional security filter, then the post-security handshake fitler.
|
||||
*/
|
||||
public class PreSecurityHandshakeFilter extends MessageFilter {
|
||||
/** Whether the handshake is actively occuring. */
|
||||
private boolean isHandshaking = false;
|
||||
/** Whether the handshake has finished yet. */
|
||||
private boolean isHandshakeComplete = false;
|
||||
/** Whether the handshake is occuring on the server. */
|
||||
private boolean isServerSide;
|
||||
/** The socket - used to access metadata on the socket & orb for the handshake. */
|
||||
private AbstractConnection socket = null;
|
||||
/** The security filter, used to set the security for the communications based on the initial handshake results. */
|
||||
private SecurityMessageFilter securityFilter;
|
||||
/** The unsigned date used to authenticate the server's message. */
|
||||
private byte[] unsignedData = null;
|
||||
/**
|
||||
* PreSecurityHandshakeFilter constructor.
|
||||
* @param isServerSide Whether the handshake is occuring on the server.
|
||||
* @param socket The socket that is the context for this filter.
|
||||
* @param securityFilter The security filter where the optional security system will be placed.
|
||||
*/
|
||||
public PreSecurityHandshakeFilter(boolean isServerSide, AbstractConnection socket, SecurityMessageFilter securityFilter) {
|
||||
this.isServerSide = isServerSide;
|
||||
this.socket = socket;
|
||||
this.securityFilter = securityFilter;
|
||||
}//PreSecurityHandshakeFilter()//
|
||||
/**
|
||||
* Sends the response to the client's first handshake message indicating that the orb or app version's did not match.
|
||||
* @param orbProtocolVersion The orb version read from the client.
|
||||
* @param appProtocolVersion The app version read from the client.
|
||||
* @param unsignedBytes The unsigned bytes that must be incorporated into the signature returned to the client authenticating the message and validating a 3rd party has not tampered with the messages.
|
||||
*/
|
||||
private void sendBadVersionMessage(int orbProtocolVersion, int appProtocolVersion, byte[] unsignedBytes) {
|
||||
try {
|
||||
int signatureSize = socket.getServerSocket().getServerSocketOptions().getSignatureSize(appProtocolVersion);
|
||||
String[] downloadUris = socket.getServerSocket().getServerSocketOptions().getDownloadUris();
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
//Write a spacer for the message size.//
|
||||
message.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
//Write the message type identifier.//
|
||||
message.writeByte(0x1);
|
||||
//Write the number of download URI's being sent.//
|
||||
message.writeInt(downloadUris != null ? downloadUris.length : 0, StreamBuffer.NUMBER_VLSF);
|
||||
|
||||
//Write each download URI.//
|
||||
for(int index = 0, length = downloadUris != null ? downloadUris.length : 0; index < length; index++) {
|
||||
message.writeString(downloadUris[index], StreamBuffer.NUMBER_VLSF, null);
|
||||
}//for//
|
||||
|
||||
//Write the actual size of the message to the client.//
|
||||
message.putInt(0, message.getSize() + signatureSize, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//Write the signature bytes.//
|
||||
if(signatureSize > 0) {
|
||||
//Write the signature at the end of the message.//
|
||||
message.writeBytes(socket.getServerSocket().getServerSocketOptions().sign(appProtocolVersion, unsignedBytes, message.toByteArray()));
|
||||
}//if//
|
||||
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(UnsupportedEncodingException e) {
|
||||
Debug.log(e); //Never should happen.//
|
||||
}//catch//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendBadVersionMessage()//
|
||||
/**
|
||||
* Sends the accept message to the client.
|
||||
* @param unsignedBytes The unsigned bytes that must be incorporated into the signature returned to the client authenticating the message and validating a 3rd party has not tampered with the messages.
|
||||
*/
|
||||
public void sendAcceptConnectionMessage(byte[] unsignedBytes) {
|
||||
try {
|
||||
int signatureSize = socket.getServerSocket().getServerSocketOptions().getSignatureSize(socket.getSocketOptions().getApplicationProtocolVersion());
|
||||
AbstractSecurityProvider securityProvider = socket.getServerSocket().getServerSocketOptions().getSecurityProvider();
|
||||
StreamBuffer message = new StreamBuffer();
|
||||
|
||||
//Write a spacer for the message size.//
|
||||
message.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
//Write the message type identifier.//
|
||||
message.writeByte(0x0);
|
||||
//Write the reconnect time.//
|
||||
message.writeLong(socket.getServerSocket().getServerSocketOptions().getAutoReconnectTimeLimit(), StreamBuffer.NUMBER_VLSF);
|
||||
//Write the keep alive time.//
|
||||
message.writeLong(socket.getServerSocket().getServerSocketOptions().getKeepAliveInterval(), StreamBuffer.NUMBER_VLSF);
|
||||
|
||||
if(securityProvider != null) {
|
||||
byte[] metadata = securityProvider.getSecuritySystemClientMetadata();
|
||||
|
||||
//Write the security algorithm class name.//
|
||||
message.writeString(securityProvider.getSecuritySystemClientClassName(), StreamBuffer.NUMBER_VLSF, null);
|
||||
|
||||
//Write the security algorithm metadata.//
|
||||
if(metadata == null || metadata.length == 0) {
|
||||
message.writeInt(0, StreamBuffer.NUMBER_VLSF);
|
||||
}//if//
|
||||
else {
|
||||
message.writeInt(metadata.length, StreamBuffer.NUMBER_VLSF);
|
||||
message.writeBytes(metadata);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
//Write a zero indicating no security.//
|
||||
message.writeString(null, StreamBuffer.NUMBER_VLSF, null);
|
||||
}//else//
|
||||
|
||||
//Write the server's external address.//
|
||||
message.writeString(socket.getServerSocket().getExternalAddress(), StreamBuffer.NUMBER_VLSF, null);
|
||||
//Write the actual size of the message to the client.//
|
||||
message.putInt(0, message.getSize() + signatureSize, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
//Write the signature bytes.//
|
||||
if(signatureSize > 0) {
|
||||
//Write the signature at the end of the message.//
|
||||
message.writeBytes(socket.getServerSocket().getServerSocketOptions().sign(socket.getSocketOptions().getApplicationProtocolVersion(), unsignedBytes, message.toByteArray()));
|
||||
}//if//
|
||||
|
||||
sendMessage(message);
|
||||
}//try//
|
||||
catch(UnsupportedEncodingException e) {
|
||||
Debug.log(e); //Never should happen.//
|
||||
}//catch//
|
||||
catch(IOException e) {
|
||||
Debug.log(e);
|
||||
closeConnection(true);
|
||||
}//catch//
|
||||
}//sendAcceptConnectionMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processIncommingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processIncommingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
if(isHandshakeComplete) {
|
||||
result = super.processIncommingMessage(input, output);
|
||||
}//if//
|
||||
else {
|
||||
//Debug.log("Running next pre-sec handshake.");
|
||||
if(isServerSide) {
|
||||
if(input.getSize() > 3 && (input.getByte(0) != 0xD || input.getByte(1) != 0xE || input.getByte(2) != 0x2 || input.getByte(3) != 0x2)) {
|
||||
throw new IOException("Invalid stream header.");
|
||||
}//if//
|
||||
|
||||
//TODO: Read the client request and generate a server response.
|
||||
if(input.getSize() > 7) {
|
||||
int messageSize = input.getInt(4, StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(input.getSize() >= messageSize) {
|
||||
int orbProtocolVersion;
|
||||
int appProtocolVersion;
|
||||
int unsignedByteCount;
|
||||
byte[] unsignedBytes = null;
|
||||
|
||||
input.skipBytes(8);
|
||||
orbProtocolVersion = input.readInt(StreamBuffer.NUMBER_VLSF);
|
||||
appProtocolVersion = input.readInt(StreamBuffer.NUMBER_VLSF);
|
||||
unsignedByteCount = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(unsignedByteCount > 0) {
|
||||
unsignedBytes = new byte[unsignedByteCount];
|
||||
input.readBytes(unsignedBytes);
|
||||
}//if//
|
||||
|
||||
//Test to see if the orb or app protocol versions don't match.//
|
||||
if(socket.getOrb().getProtocolVersion() != orbProtocolVersion || socket.getSocketOptions().getApplicationProtocolVersion() != appProtocolVersion) {
|
||||
sendBadVersionMessage(orbProtocolVersion, appProtocolVersion, unsignedBytes);
|
||||
}//if//
|
||||
|
||||
//TODO: Check to see if the server is forwarding to another server.
|
||||
|
||||
else {
|
||||
try {
|
||||
securityFilter.initializeSecurity(socket.getServerSocket().getSecurityProvider() != null ? socket.getServerSocket().getSecurityProvider().createSecuritySystem() : null);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Failed to initialize the newly connected socket's security system.");
|
||||
}//catch//
|
||||
|
||||
sendAcceptConnectionMessage(unsignedBytes);
|
||||
}//else//
|
||||
|
||||
//Flag the handshake as completed.//
|
||||
isHandshakeComplete = true;
|
||||
//Notify the filter that the handshake should be continued up the filter chain.//
|
||||
endInitialization();
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
//Read the server response and set the security system if needed.//
|
||||
if(input.getSize() > 3) {
|
||||
int messageSize = input.getInt(0, StreamBuffer.NUMBER_LSF);
|
||||
int signatureSize = socket.getSocketOptions().getSignatureSize();
|
||||
|
||||
//The headers have an upper limit of 40k bytes.//
|
||||
if(messageSize > 40000) {
|
||||
throw new IOException("Message header size exceeded.");
|
||||
}//if//
|
||||
|
||||
if(input.getSize() >= messageSize) {
|
||||
boolean isValid = true;
|
||||
|
||||
//Authenticate the server if we can.//
|
||||
if(signatureSize > 0) {
|
||||
IHashAlgorithm hashAlgorithm = socket.getSocketOptions().getHashAlgorithm();
|
||||
byte[] hashSource = messageSize - signatureSize > 0 ? new byte[messageSize - signatureSize] : null;
|
||||
byte[] signature = new byte[signatureSize];
|
||||
byte[] hash;
|
||||
|
||||
//Initialize the hash algorithm.//
|
||||
input.getBytes(0, hashSource);
|
||||
hashAlgorithm.add(hashSource);
|
||||
//Gather the signature.//
|
||||
input.getBytes(messageSize - signatureSize, signature);
|
||||
hash = hashAlgorithm.hash();
|
||||
|
||||
//Merge the two hashes.//
|
||||
for(int index = 0; index < hash.length; index++) {
|
||||
hash[index] ^= unsignedData[index];
|
||||
}//for//
|
||||
|
||||
//Validate the signature.//
|
||||
isValid = socket.getSocketOptions().isValidSignature(hash, signature);
|
||||
}//if//
|
||||
|
||||
if(!isValid) {
|
||||
throw new AuthenticationException();
|
||||
}//if//
|
||||
|
||||
//Skip the size bytes.//
|
||||
input.skipBytes(4);
|
||||
|
||||
//If the response indicates compatability it will be 0x00, otherwise it will be 0x01 for not compatible, or 0x02 for a forward to another server.//
|
||||
switch((int) input.readByte()) {
|
||||
case 0x00: { //The server has accepted our connection.//
|
||||
long autoReconnectTimeLimit = input.readLong(StreamSupport.NUMBER_VLSF);
|
||||
long keepAliveInterval = input.readLong(StreamSupport.NUMBER_VLSF);
|
||||
String securitySystemClassName;
|
||||
byte[] securitySystemMetadata = null;
|
||||
String connectedAddress = null;
|
||||
int size;
|
||||
|
||||
//Read Security System Class Name.//
|
||||
securitySystemClassName = input.readString(StreamSupport.NUMBER_VLSF, null);
|
||||
|
||||
if(securitySystemClassName != null) {
|
||||
//Read Security System Metadata.//
|
||||
size = input.readInt(StreamSupport.NUMBER_VLSF);
|
||||
securitySystemMetadata = size > 0 ? new byte[size] : null;
|
||||
|
||||
if(securitySystemMetadata != null) {
|
||||
input.readBytes(securitySystemMetadata);
|
||||
}//if//
|
||||
}//if//
|
||||
|
||||
connectedAddress = input.readString(StreamSupport.NUMBER_VLSF, null);
|
||||
//Sets up the socket and initializes the security system.//
|
||||
socket.processServerInitializationResponse(autoReconnectTimeLimit, new Address(connectedAddress), keepAliveInterval);
|
||||
|
||||
if(securityFilter != null) {
|
||||
securityFilter.initializeSecurity(securitySystemClassName, securitySystemMetadata);
|
||||
}//if//
|
||||
break;
|
||||
}//case//
|
||||
case 0x01: { //Bad orb or app version - extract the URI's where the client can get the current version.//
|
||||
String[] uris = new String[input.readInt(StreamSupport.NUMBER_VLSF)];
|
||||
|
||||
//Read URI's//
|
||||
for(int index = 0; index < uris.length; index++) {
|
||||
uris[index] = input.readString(StreamSupport.NUMBER_VLSF, null);
|
||||
}//for//
|
||||
|
||||
if(socket.getNewVersionHandler() != null) {
|
||||
socket.getNewVersionHandler().newVersionAvailable(uris, true);
|
||||
}//if//
|
||||
|
||||
socket.close(true, false);
|
||||
//Stop connecting to the server since the versions are not compatible.//
|
||||
throw new NewVersionFoundException();
|
||||
}//case//
|
||||
case 0x02: { //The server is requesting the client connect to a different server.//
|
||||
|
||||
//TODO: Forward to another server.
|
||||
throw new IOException("Not supported yet.");
|
||||
//break;
|
||||
}//case//
|
||||
default: {
|
||||
Debug.log(new RuntimeException("Unexpected response code."));
|
||||
//TODO: Shutdown the socket?
|
||||
}//default//
|
||||
}//switch//
|
||||
|
||||
//Skip the last bytes in the message which was the signature used above.//
|
||||
input.skipBytes(signatureSize);
|
||||
//Flag the handshake as completed.//
|
||||
isHandshakeComplete = true;
|
||||
//Notify the filter that the handshake should be continued up the filter chain.//
|
||||
endInitialization();
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
//Message has not all been received. Wait until more comes in.//
|
||||
}//else//
|
||||
}//else//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//processIncommingMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processOutgoingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processOutgoingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
if(isHandshakeComplete) {
|
||||
result = super.processOutgoingMessage(input, output);
|
||||
}//if//
|
||||
else {
|
||||
//TODO: Save the outgoing message until the handshake has finished.
|
||||
Debug.log(new RuntimeException("Shouldn't get here."));
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//processOutgoingMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#beginInitialization()
|
||||
*/
|
||||
public boolean beginInitialization() throws IOException {
|
||||
if(!isServerSide && !isHandshaking && !isHandshakeComplete) {
|
||||
//Debug.log("Starting Pre-Sec Initialization");
|
||||
StreamBuffer buffer = new StreamBuffer();
|
||||
IHashAlgorithm hashAlgorithm = socket.getSocketOptions().getHashAlgorithm();
|
||||
|
||||
//Stream identifier.//
|
||||
buffer.writeByte(0xD);
|
||||
buffer.writeByte(0xE);
|
||||
buffer.writeByte(0x2);
|
||||
buffer.writeByte(0x2);
|
||||
//Message size reserved space.//
|
||||
buffer.writeByte(0x0);
|
||||
buffer.writeByte(0x0);
|
||||
buffer.writeByte(0x0);
|
||||
buffer.writeByte(0x0);
|
||||
//ORB Protocol Version.//
|
||||
buffer.writeInt(socket.getOrb().getProtocolVersion(), StreamBuffer.NUMBER_VLSF);
|
||||
//Application Protocol Version.//
|
||||
buffer.writeInt(socket.getSocketOptions().getApplicationProtocolVersion(), StreamBuffer.NUMBER_VLSF);
|
||||
//Write the message size at the beginning of the stream (the zero'd bytes).//
|
||||
buffer.putInt(4, buffer.getSize() + (hashAlgorithm != null ? hashAlgorithm.getHashSize() + 4 : 4), StreamBuffer.NUMBER_LSF);
|
||||
|
||||
if(hashAlgorithm != null) {
|
||||
//Set the unsigned data used to validate the server's authenticity.//
|
||||
byte[] date = new byte[8];
|
||||
StreamSupport.writeLong(new Date().getTime(), date, 0, StreamSupport.NUMBER_LSF);
|
||||
hashAlgorithm.add(date);
|
||||
hashAlgorithm.add(buffer.toByteArray());
|
||||
unsignedData = hashAlgorithm.hash();
|
||||
|
||||
//Write Unsigned Bytes.//
|
||||
buffer.writeInt(unsignedData.length, StreamBuffer.NUMBER_LSF);
|
||||
buffer.writeBytes(unsignedData);
|
||||
}//if//
|
||||
else {
|
||||
buffer.writeInt(0, StreamBuffer.NUMBER_LSF);
|
||||
}//else//
|
||||
|
||||
//Write the message to the socket.//
|
||||
sendMessage(buffer);
|
||||
isHandshaking = true;
|
||||
}//if//
|
||||
|
||||
return isHandshaking || !isHandshakeComplete;
|
||||
}//beginInitialization()//
|
||||
}//PreSecurityHandshakeFilter//
|
||||
672
Orb/src/com/de22/orb/Proxy.java
Normal file
672
Orb/src/com/de22/orb/Proxy.java
Normal file
@@ -0,0 +1,672 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import com.common.util.*;
|
||||
import com.common.debug.*;
|
||||
import com.common.event.ObjectHandler1;
|
||||
import com.common.util.optimized.*;
|
||||
import com.de22.orb.exception.*;
|
||||
import com.de22.orb.io.*;
|
||||
|
||||
/**
|
||||
* The base class for all proxies used by the ORB.
|
||||
* <p><b>Warning:</b> The proxy is designed to be comparable, but only with the proxied object, or another proxy to the proxied object when the other proxy connects to the proxied object over the same socket chain.
|
||||
* This means that if you have two proxies to the same object, but one communcates with the proxied object via process D->B->A, and the other communicates via process D->C->A, then the two proxies will be deamed NOT equal.
|
||||
* The previous example assumes the proxied object is on process A and the process doing the comparison is on process D and the proxies are transfered via processes B & C.
|
||||
*/
|
||||
public class Proxy implements java.io.Externalizable, com.common.io.IExternalizable, com.common.comparison.IComparable {
|
||||
public static final String PROXY_EXTENSION = "__SZProxy";
|
||||
public static final int PROXY_EXTENSION_LENGTH = PROXY_EXTENSION.length();
|
||||
public static final long DEFAULT_TIMEOUT = 0L;
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
/** A set of threads requesting the next call be one way. */
|
||||
private LiteHashSet oneWayThreadSet = null;
|
||||
/** A mapping of result callback objects by thread requesting the next call return immediatly and send the result to the callback. */
|
||||
private ThreadLocal resultCallback = new ThreadLocal();
|
||||
/**
|
||||
* A mapping of the interface to use to auto-proxy the result.
|
||||
* Note: I am assuming that the thread local is GC'd if the proxy is GC'd, but the thread is not. This could cause memory leaks if this assumption is incorrect.
|
||||
*/
|
||||
private ThreadLocal autoProxyInterface = new ThreadLocal();
|
||||
/**
|
||||
* A mapping of the interface to use to auto-morph the result.
|
||||
* Note: I am assuming that the thread local is GC'd if the proxy is GC'd, but the thread is not. This could cause memory leaks if this assumption is incorrect.
|
||||
*/
|
||||
private ThreadLocal autoMorphInterface = new ThreadLocal();
|
||||
/** A mapping of timeout values by thread requesting the timeout. */
|
||||
private ObjectLongHashMap timeoutMap = null;
|
||||
/** The set of listeners that wish to be notified when this proxy is no longer valid. */
|
||||
private LiteHashSet invalidListeners = null;
|
||||
/** The listener registered with the orb to receive notification when the socket this proxy is communicating over is closed. */
|
||||
private SocketCloseListener socketCloseListener = null;
|
||||
private Orb orb = null; //The orb that this proxy interacts with.//
|
||||
private int hash = 0; //The hash value of the proxied object.//
|
||||
private long remoteLuid = -1; //The luid of the remote reference that this proxy talks to across the socket. The remote reference may or may not be local.//
|
||||
private long luid = -1; //The local identifier for the proxy. If the proxy is remote, then it will also have a remoteLuid identifying the proxied object on the remote process connected by the socket reference.//
|
||||
private Object localObject = null;
|
||||
private AbstractConnection socket = null; //A reference to the socket that the proxy last moved over. This will only be null if the proxy is local.//
|
||||
private int typeId = -1; //The identifier of the proxy's type, valid only on the process containing the local object.//
|
||||
|
||||
/**
|
||||
* Listens for a socket closure so that listeners to whether the proxy is invalid can be notified.
|
||||
*/
|
||||
private class SocketCloseListener implements ISocketCloseListener {
|
||||
/**
|
||||
* SocketCloseListener constructor.
|
||||
*/
|
||||
public SocketCloseListener() {
|
||||
}//SocketCloseListener()//
|
||||
public void onSocketClosed(AbstractConnection socket) {
|
||||
invalidate();
|
||||
}//onSocketClosed()//
|
||||
}//SocketCloseListener//
|
||||
/**
|
||||
* Proxy constructor.
|
||||
*/
|
||||
public Proxy() {
|
||||
super();
|
||||
}//Proxy()//
|
||||
/**
|
||||
* Adds the listener to the collection of proxy invalid listeners for this proxy.
|
||||
* @param listener The proxy invalid listener to be notified as soon as the proxy determines it is no longer valid. If the proxy is currently not valid then this handler will be called immediatly.
|
||||
*/
|
||||
public synchronized void addProxyInvalidListener(IProxyInvalidListener listener) {
|
||||
AbstractConnection socket = this.socket;
|
||||
|
||||
if(socket != null) {
|
||||
if(invalidListeners == null) {
|
||||
invalidListeners = new LiteHashSet(4);
|
||||
}//if//
|
||||
|
||||
invalidListeners.add(listener);
|
||||
|
||||
if(socketCloseListener == null) {
|
||||
socketCloseListener = new SocketCloseListener();
|
||||
socket.addCloseListener(socketCloseListener);
|
||||
}//if//
|
||||
}//if//
|
||||
}//addProxyInvalidListener()//
|
||||
/**
|
||||
* Calls a method on the specified object using the proxy.
|
||||
* @param object The local object to call the method on. This allows one proxy to service many local objects. It is most useful to allow the orb to use one proxy to call remotely invoked methods on all local objects of the correct type.
|
||||
* @param name The name of the method to call.
|
||||
* @param params The parameters for the method.
|
||||
* @return The return value of the method. This will be null if the return value is null, or if there is no return value.
|
||||
*/
|
||||
public Object callMethod__Proxy(Object object, String name, Object[] params) {
|
||||
if((object != null) || (getIsProxyLocal__Proxy())) {
|
||||
return remoteExecute__Proxy(object == null ? getLocalObject__Proxy() : object, getMethodId__Proxy(name), params);
|
||||
}//if//
|
||||
else {
|
||||
return proxyMethodCall__Proxy(getMethodId__Proxy(name), params);
|
||||
}//else//
|
||||
}//callMethod__Proxy()//
|
||||
/**
|
||||
* Cloning of a proxy is not a supported feature.
|
||||
*/
|
||||
protected Object clone() throws CloneNotSupportedException{
|
||||
throw new CloneNotSupportedException();
|
||||
}//clone()//
|
||||
/**
|
||||
* @link IComparator.compareTo(Object)
|
||||
*/
|
||||
public int compareTo(Object object) {
|
||||
return equalsEquals(object) ? EQUAL : NOT_EQUAL;
|
||||
}//compareTo()//
|
||||
/**
|
||||
* A debugging tool.
|
||||
*/
|
||||
protected void debug__Proxy(int methodNumber) {
|
||||
Debug.log("Calling method " + methodNumber + " on " + getClass().getName());
|
||||
}//debug__Proxy()//
|
||||
/**
|
||||
* @link IComparator.equals(Object)
|
||||
*/
|
||||
public boolean equals(Object object) {
|
||||
return equalsEquals(object);
|
||||
}//equals()//
|
||||
/**
|
||||
* @link IComparator.equalsEquals(Object)
|
||||
*/
|
||||
public boolean equalsEquals(Object object) {
|
||||
return ((object instanceof Proxy) && (((Proxy) object).luid == luid) && (((Proxy) object).socket == socket)) || ((localObject != null) && (localObject == object));
|
||||
}//equalsEquals()//
|
||||
/**
|
||||
* Cleans up after the proxy. The primary function is to decrement the reference count.
|
||||
*/
|
||||
public synchronized void finalize() throws Throwable {
|
||||
//If the proxy hasn't already decremented the count then do so now.//
|
||||
if(luid != -1) {
|
||||
//Decrement the reference count for the proxy.//
|
||||
orb.decrementProxyCount(socket, luid, 1);
|
||||
//Help cleanup the proxy object.//
|
||||
localObject = null;
|
||||
socket = null;
|
||||
}//if//
|
||||
}//finalize()//
|
||||
/**
|
||||
* Gets the auto proxy interface class, or null if the return value should not be auto-proxied.
|
||||
* <p>Note: This will only work properly if the return value of the method is the same interface type or this interface type can be cast.</p>
|
||||
* @return The interface class that should be used to auto proxy the resulting value.
|
||||
*/
|
||||
private Class getAutoProxy__Proxy() {
|
||||
Class result = (Class) autoProxyInterface.get();
|
||||
|
||||
if(result != null) {
|
||||
autoProxyInterface.set(null);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getAutoProxy__Proxy()//
|
||||
private ObjectHandler1 getMorphHandler__Proxy() {
|
||||
ObjectHandler1 result = (ObjectHandler1) autoMorphInterface.get();
|
||||
|
||||
if(result != null) {
|
||||
autoMorphInterface.set(null);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getMorphHandler__Proxy()//
|
||||
/**
|
||||
* Determines whether the next call is a one way call.
|
||||
* <p>Note: The caller must synchronize on this proxy first.</p>
|
||||
* @param thread The thread to get the is one way flag for.
|
||||
* @return Whether the next method call will be uni-directional.
|
||||
*/
|
||||
private boolean getIsOneWay__Proxy(Thread thread) {
|
||||
return (oneWayThreadSet != null) && (oneWayThreadSet.getSize() > 0)? oneWayThreadSet.remove(thread) : false;
|
||||
}//getIsOneWay__Proxy()//
|
||||
/**
|
||||
* Gets the callback to be invoked when the next call returns a result.
|
||||
* <p>Note: The caller must synchronize on this proxy first.</p>
|
||||
* @param thread The thread to get the result callback for.
|
||||
* @return Non-null if the next method call will return immediatly and call this callback with the result when it arrives.
|
||||
*/
|
||||
private IResultCallback getResultCallback__Proxy(Thread thread) {
|
||||
IResultCallback result = (IResultCallback) resultCallback.get();
|
||||
|
||||
if(result != null) {
|
||||
resultCallback.set(null);
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getResultCallback__Proxy()//
|
||||
/**
|
||||
* Determines whether the proxy is in the same process as the object being proxied.
|
||||
* @return Whether the proxy and proxied object are in the same process.
|
||||
*/
|
||||
public boolean getIsProxyLocal__Proxy() {
|
||||
return localObject != null;
|
||||
}//getIsProxyLocal__Proxy()//
|
||||
/**
|
||||
* Determines whether the proxy is a valid reference to an object.
|
||||
* @return Whether the proxy can be used to communcated with the proxied object.
|
||||
*/
|
||||
public boolean getIsProxyValid__Proxy() {
|
||||
return (localObject != null) || ((socket != null) && (socket.isOpen()));
|
||||
}//getIsProxyValid__Proxy()//
|
||||
/**
|
||||
* Gets the local object that this proxy encapsulates.
|
||||
* @return The local object being proxied, or null if the proxy is invalid or remote.
|
||||
*/
|
||||
public Object getLocalObject__Proxy() {
|
||||
return localObject;
|
||||
}//getLocalObject__Proxy()//
|
||||
/**
|
||||
* The locally unique id for the object on the next process in the chain of processes between this proxy and the proxied object.
|
||||
* @return The number that identifies the object or forwarding reference on the process that the socket is connected to. This will be -1 in the event that the proxy is local.
|
||||
*/
|
||||
long getLuid__Proxy() {
|
||||
return luid;
|
||||
}//getLuid__Proxy()//
|
||||
/**
|
||||
* Gets the array of all method hashes.
|
||||
* @return The array containing method hashes for the proxied methods.
|
||||
*/
|
||||
protected long[] getMethodHashes__Proxy() {
|
||||
return null; //TODO: Implement this in each proxy so that a mapping of names to hashes can be formed.//
|
||||
}//getMethodHashes__Proxy()//
|
||||
/**
|
||||
* Gets the array of all method hashes.
|
||||
* @param name The name of the method whose hash id is desired.
|
||||
* @return The method hash for the method.
|
||||
*/
|
||||
protected long getMethodId__Proxy(String name) {
|
||||
if(getMethodNameMap__Proxy().containsKey(name)) {
|
||||
return getMethodNameMap__Proxy().get(name);
|
||||
}//if//
|
||||
else {
|
||||
throw new MethodNotFoundException("Method " + name + " not found in " + getClass().getName());
|
||||
}//else//
|
||||
}//getMethodId__Proxy()//
|
||||
/**
|
||||
* Gets the mapping of method names to their hashes.
|
||||
* <p>TODO: Provide some way of disinguishing between two methods with the same name.</p>
|
||||
* @return A mappping of method hashes by method name.
|
||||
*/
|
||||
protected ObjectLongHashMap getMethodNameMap__Proxy() {
|
||||
return null; //TODO: Use the hashes array and name array to create a mapping. This should be in each proxy so that it can maintain a static reference to the mapping.//
|
||||
}//getMethodNameMap__Proxy()//
|
||||
/**
|
||||
* Gets the array of all method names.
|
||||
* @return An array of method names for the methods proxied.
|
||||
*/
|
||||
protected String[] getMethodNames__Proxy() {
|
||||
return EMPTY_STRING_ARRAY; //TODO: Implement this in each proxy so that a mapping of method names to hashes can be formed.//
|
||||
}//getMethodNames__Proxy()//
|
||||
/**
|
||||
* Gets the network connection identifier for next step toward the proxied object.
|
||||
* This value can be useful for grouping messages by the direction they are going so as to bulk send messages. It can also be used to identify a network connection when sending an agent.
|
||||
* @return An object that uniquely identifies the first network connection along the path to the proxied object.
|
||||
*/
|
||||
public Object getNetworkConnectionIdentifier__Proxy() {
|
||||
return new Orb.NetworkConnectionIdentifier(socket);
|
||||
}//getNetworkConnectionIdentifier__Proxy()//
|
||||
/**
|
||||
* Gets the proxied interface class.
|
||||
* @return The proxied class.
|
||||
*/
|
||||
public Class getProxiedClass__Proxy() {
|
||||
//TODO: We could be a bit more efficient and cache this if we add this method to the proxy subclasses.//
|
||||
//The problem with doing this is we would have to also add the try/catch block which is no fun.//
|
||||
try {
|
||||
return Class.forName(getProxiedClassName__Proxy());
|
||||
}//try//
|
||||
catch(ClassNotFoundException e) {
|
||||
throw new NoClassDefFoundError(e.getMessage());
|
||||
}//catch//
|
||||
}//getProxiedClass__Proxy()//
|
||||
/**
|
||||
* Gets the name of the proxied class (interface).
|
||||
* @return The proxied class' fully qualified name.
|
||||
*/
|
||||
public String getProxiedClassName__Proxy() {
|
||||
return Proxy.class.getName();
|
||||
}//getProxiedClassName__Proxy()//
|
||||
/**
|
||||
*
|
||||
*/
|
||||
long getRemoteLuid__Proxy() {
|
||||
return remoteLuid;
|
||||
}//getRemoteLuid__Proxy()//
|
||||
/**
|
||||
* Gets the socket that the proxy last moved over.
|
||||
* @return The last socket the proxy was serialized through, or null if the proxy is local.
|
||||
*/
|
||||
AbstractConnection getSocket__Proxy() {
|
||||
return socket;
|
||||
}//getSocket__Proxy()//
|
||||
/**
|
||||
* Gets the timeout time for the next remote call on the current thread.
|
||||
* <p>Note: The caller must synchronize on this proxy first.</p>
|
||||
* @param thread The thread to get the timeout value for.
|
||||
* @return The amout of time in milliseconds to wait for the remote process to respond before throwing a timeout exception.
|
||||
*/
|
||||
private long getTimeout__Proxy(Thread thread) {
|
||||
return (timeoutMap != null) && (timeoutMap.getSize() > 0) && (timeoutMap.containsKey(thread)) ? timeoutMap.remove(thread) : DEFAULT_TIMEOUT;
|
||||
}//getTimeout__Proxy()//
|
||||
/**
|
||||
* Gets the proxied object's hash code.
|
||||
* @return The hash code of the proxied object.
|
||||
*/
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}//hashCode()//
|
||||
/**
|
||||
* Notifies the proxy invalid listeners that proxy is no longer valid.
|
||||
*/
|
||||
private synchronized void invalidate() {
|
||||
AbstractConnection socket = this.socket;
|
||||
long luid = this.luid;
|
||||
|
||||
//Help cleanup and set the luid to indicate we already have decremented the reference count.//
|
||||
this.socket = null;
|
||||
this.localObject = null;
|
||||
this.luid = -1;
|
||||
|
||||
//Just in case we will try to decrement the remote proxy count. This will of course fail if the proxy is invalid because the socket closed.//
|
||||
if(socket != null) {
|
||||
try {
|
||||
//Decrement the local count for the proxy.//
|
||||
orb.decrementProxyCount(socket, luid, 1);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.handle(e);
|
||||
}//catch//
|
||||
}//if//
|
||||
|
||||
//Notify listeners if there are any.//
|
||||
if(invalidListeners != null) {
|
||||
IIterator iterator = invalidListeners.iterator();
|
||||
|
||||
while(iterator.hasNext()) {
|
||||
((IProxyInvalidListener) iterator.next()).onProxyInvalid(this);
|
||||
}//while//
|
||||
|
||||
invalidListeners.removeAll();
|
||||
|
||||
if(socketCloseListener != null) {
|
||||
|
||||
if(socket != null) {
|
||||
socket.removeCloseListener(socketCloseListener);
|
||||
}//if//
|
||||
|
||||
socketCloseListener = null;
|
||||
}//if//
|
||||
}//if//
|
||||
}//invalidate()//
|
||||
/**
|
||||
* Calls a method on the remote object proxied by this proxy object.
|
||||
* @param method The method's unique identifier (unique within the context of this proxy).
|
||||
* @param params The array of parameters or null if there are no method parameters.
|
||||
* @return The return value of the method call.
|
||||
*/
|
||||
protected Object proxyMethodCall__Proxy(long method, Object[] params) {
|
||||
Object retVal = null;
|
||||
|
||||
if(getIsProxyValid__Proxy()) {
|
||||
ValueHolder valueHolder = null;
|
||||
Thread thread = Thread.currentThread();
|
||||
boolean isOneWay;
|
||||
Class autoProxyClass;
|
||||
long timeout;
|
||||
IResultCallback callback;
|
||||
ObjectHandler1 morphHandler;
|
||||
|
||||
synchronized(this) {
|
||||
isOneWay = getIsOneWay__Proxy(thread);
|
||||
autoProxyClass = getAutoProxy__Proxy();
|
||||
timeout = getTimeout__Proxy(thread);
|
||||
callback = getResultCallback__Proxy(thread);
|
||||
morphHandler = getMorphHandler__Proxy();
|
||||
}//synchronized//
|
||||
|
||||
valueHolder = orb.localExecute(socket, remoteLuid, typeId, method, params, isOneWay, autoProxyClass, timeout, callback);
|
||||
|
||||
if(valueHolder.status == ValueHolder.STATUS_OK) {
|
||||
if((!isOneWay) && (callback == null)) {
|
||||
//TODO: May wish to identify the exceptions that should be rethrown just in case one is returned as a legitimate return value (not thrown).//
|
||||
if(valueHolder.value instanceof Throwable) {
|
||||
com.de22.orb.exception.ExceptionSupport.rethrow((Throwable) valueHolder.value);
|
||||
}//if//
|
||||
|
||||
retVal = valueHolder.value;
|
||||
|
||||
//Morph the result if a handler was provided to do this. This is useful if the result type or value must be altered prior to being returned by the proxy.//
|
||||
if(morphHandler != null) {
|
||||
retVal = morphHandler.evaluate(retVal);
|
||||
}//if//
|
||||
}//if//
|
||||
}//if//
|
||||
else if(valueHolder.status == ValueHolder.STATUS_SOCKET_NOT_FOUND) {
|
||||
invalidate();
|
||||
throw new InvalidProxyException();
|
||||
}//else if//
|
||||
else if(valueHolder.status == ValueHolder.STATUS_SOCKET_ERROR) {
|
||||
invalidate();
|
||||
throw new InvalidProxyException();
|
||||
}//else if//
|
||||
else if(valueHolder.status == ValueHolder.STATUS_TIMEOUT) {
|
||||
throw new TimeoutException();
|
||||
}//else if//
|
||||
else {
|
||||
throw new RuntimeException("Unexpected error in making a remote method call.");
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new InvalidProxyException();
|
||||
}//else//
|
||||
|
||||
return retVal;
|
||||
}//proxyMethodCall__Proxy()//
|
||||
/**
|
||||
* Reads the proxy from the stream.
|
||||
* <p>Warning: This proxy will only be read from an Orb stream.
|
||||
* @param in The stream to read from.
|
||||
*/
|
||||
public Object readExternal(com.common.io.IObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
|
||||
if(in instanceof OrbObjectInputStream) {
|
||||
socket = ((OrbObjectInputStream) in).getSocket();
|
||||
localObject = null;
|
||||
orb = socket.getOrb();
|
||||
hash = in.readInt();
|
||||
typeId = in.readInt();
|
||||
|
||||
if(in.readBoolean()) {
|
||||
luid = in.readLong();
|
||||
orb.fixProxy(this);
|
||||
}//if//
|
||||
else {
|
||||
remoteLuid = in.readLong();
|
||||
luid = orb.incrementProxyCount(socket, this);
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
throw new java.io.IOException("A proxy may only be streamed via its ORB.");
|
||||
}//else//
|
||||
|
||||
return null;
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Reads the proxy from the stream.
|
||||
* <p>Warning: This proxy will only be read from an Orb stream.
|
||||
* @param in The stream to read from.
|
||||
*/
|
||||
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException {
|
||||
throw new java.io.IOException("A proxy may only be streamed via its ORB.");
|
||||
}//readExternal()//
|
||||
/**
|
||||
* Executes the specified method using the given parameter values.
|
||||
* @param object The object whose method will be called.
|
||||
* @param method The method that will be called.
|
||||
* @param parameters The parameter values that will be passed.
|
||||
* @return The return value of the method call, or null if there is no return value.
|
||||
*/
|
||||
protected Object remoteExecute__Proxy(Object object, long method, Object[] parameters) {
|
||||
//This should be overridden in all non-generic proxies.//
|
||||
return null;
|
||||
}//remoteExecute__Proxy()//
|
||||
/**
|
||||
* Removes the listener from the collection of proxy invalid listeners for this proxy.
|
||||
* @param listener The listener previously added to the listener collection.
|
||||
*/
|
||||
public synchronized void removeProxyInvalidListener(IProxyInvalidListener listener) {
|
||||
AbstractConnection socket = this.socket;
|
||||
|
||||
//Only must remove the listeners if the proxy is not already invalid.//
|
||||
if((socket != null) && (invalidListeners != null)) {
|
||||
//Remove the listener.//
|
||||
invalidListeners.remove(listener);
|
||||
|
||||
//Cleanup after the listeners.//
|
||||
if(invalidListeners.getSize() == 0) {
|
||||
if(socketCloseListener != null) {
|
||||
socket.removeCloseListener(socketCloseListener);
|
||||
socketCloseListener = null;
|
||||
}//if//
|
||||
|
||||
invalidListeners = null;
|
||||
}//if//
|
||||
}//if//
|
||||
}//removeProxyInvalidListener()//
|
||||
/**
|
||||
* Sets the auto proxy interface class, or null if the return value should not be auto-proxied.
|
||||
* <p>Note: This will only work properly if the return value of the method is the same interface type or this interface type can be cast.</p>
|
||||
* @param interfaceType The interface class that should be used to auto proxy the resulting value.
|
||||
*/
|
||||
public void setAutoProxy__Proxy(Class interfaceType) {
|
||||
if(!getIsProxyLocal__Proxy()) {
|
||||
autoProxyInterface.set(interfaceType);
|
||||
}//if//
|
||||
}//setAutoProxy__Proxy()//
|
||||
/**
|
||||
* Sets the auto proxy interface class and morph handler. Used to alter both the value returned by a remote call (prior to being sent to this local process), and to alter the value returned by the local proxy to the application.
|
||||
* <p>Note: This will only work properly if the return value of the method is the same interface type or this interface type can be cast.</p>
|
||||
* @param interfaceType The interface class that should be used to auto proxy the resulting value.
|
||||
* @param morphHandler The handler called after the result is obtained by the local proxy (the remote or local actual object has returned a value), passing the returned value, and its self returning the result of the handler. Allows the handler to alter the result prior to the proxy returning it as the result of the application's call.
|
||||
*/
|
||||
public void setAutoMorph__Proxy(Class interfaceType, ObjectHandler1 morphHandler) {
|
||||
if(!getIsProxyLocal__Proxy() && interfaceType != null) {
|
||||
autoProxyInterface.set(interfaceType);
|
||||
}//if//
|
||||
|
||||
autoMorphInterface.set(morphHandler);
|
||||
}//setAutoMorph__Proxy()//
|
||||
/**
|
||||
* Determines whether the next call is a one way call.
|
||||
* @param isOneWay Whether the next method call will be uni-directional.
|
||||
*/
|
||||
public synchronized void setIsOneWay__Proxy(boolean isOneWay) {
|
||||
if(!getIsProxyLocal__Proxy()) {
|
||||
Thread thread = Thread.currentThread();
|
||||
|
||||
if(isOneWay) {
|
||||
if(oneWayThreadSet == null) {
|
||||
oneWayThreadSet = new LiteHashSet(3);
|
||||
}//if//
|
||||
|
||||
oneWayThreadSet.add(thread);
|
||||
}//if//
|
||||
else if(oneWayThreadSet != null) {
|
||||
oneWayThreadSet.remove(thread);
|
||||
}//else//
|
||||
}//if//
|
||||
}//setIsOneWay__Proxy()//
|
||||
/**
|
||||
* Sets the callback that will be invoked when the result of the next call via this proxy is received.
|
||||
* @param callback The callback object that will process the next remote call's result.
|
||||
*/
|
||||
public synchronized void setResultCallback__Proxy(IResultCallback callback) {
|
||||
if(!getIsProxyLocal__Proxy()) {
|
||||
resultCallback.set(callback);
|
||||
}//if//
|
||||
}//setResultCallback__Proxy()//
|
||||
/**
|
||||
* Sets the local object for the proxy.
|
||||
* @param object The object that is being proxied. This should be null if the proxy is remote.
|
||||
*/
|
||||
void setLocalObject__Proxy(Object object) {
|
||||
this.localObject = object;
|
||||
this.hash = object.hashCode();
|
||||
}//setLocalObject__Proxy()//
|
||||
/**
|
||||
* Sets the luid for the proxy.
|
||||
* @param luid ?
|
||||
*/
|
||||
void setLuid__Proxy(long luid) {
|
||||
this.luid = luid;
|
||||
}//setLuid__Proxy()//
|
||||
/**
|
||||
* Sets the orb reference for the proxy.
|
||||
* @param orb The ORB instance that created the proxy or that the proxy is required to go through to get to the proxied object.
|
||||
*/
|
||||
void setOrb__Proxy(Orb orb) {
|
||||
this.orb = orb;
|
||||
}//setOrb__Proxy()//
|
||||
/**
|
||||
* Sets the remote luid for the proxy.
|
||||
* @param remoteLuid The unique identifier on the process connected to by the socket reference. This luid will be sent when executing methods remotely.
|
||||
*/
|
||||
void setRemoteLuid__Proxy(long remoteLuid) {
|
||||
this.remoteLuid = remoteLuid;
|
||||
}//setRemoteLuid__Proxy()//
|
||||
/**
|
||||
* Sets the proxy's communciation socket.
|
||||
* @param socket The socket that the proxy must communicate across to reach the proxied object. This will be null for a local proxy.
|
||||
*/
|
||||
void setSocket__Proxy(AbstractConnection socket) {
|
||||
this.socket = socket;
|
||||
}//setSocket__Proxy()//
|
||||
/**
|
||||
* Sets the timeout time for the next remote call on the current thread.
|
||||
* @param timeout The amout of time in milliseconds to wait for the remote process to respond before throwing a timeout exception.
|
||||
*/
|
||||
public synchronized void setTimeout__Proxy(long timeout) {
|
||||
if(!getIsProxyLocal__Proxy()) {
|
||||
if(timeoutMap == null) {
|
||||
timeoutMap = new ObjectLongHashMap(3);
|
||||
}//if//
|
||||
|
||||
timeoutMap.put(Thread.currentThread(), timeout);
|
||||
}//if//
|
||||
}//setTimeout__Proxy()//
|
||||
/**
|
||||
* Sets the type id for the proxy.
|
||||
* @param typeId Identifies the proxy class on the process holding the proxied object.
|
||||
*/
|
||||
void setTypeId__Proxy(int typeId) {
|
||||
this.typeId = typeId;
|
||||
}//setTypeId__Proxy()//
|
||||
/**
|
||||
* Sets up the mapping of method names to method hashes.
|
||||
* @return The map of method hashes by method names.
|
||||
*/
|
||||
protected ObjectLongHashMap setupMethodNameMap__Proxy() {
|
||||
String[] methodNames = getMethodNames__Proxy();
|
||||
ObjectLongHashMap retVal = new ObjectLongHashMap(methodNames.length);
|
||||
long[] methodHashes = getMethodHashes__Proxy();
|
||||
|
||||
for(int index = 0; index < methodHashes.length; index++) {
|
||||
retVal.put(methodNames[index], methodHashes[index]);
|
||||
}//for//
|
||||
|
||||
return retVal;
|
||||
}//setupMethodNameMap__Proxy()//
|
||||
/**
|
||||
* Gets a string representation of the proxy object.
|
||||
* @return A debug string representing the proxy object.
|
||||
*/
|
||||
public String toString() {
|
||||
return getClass().getName() + '[' + luid + ';' + socket + ']';
|
||||
}//toString()//
|
||||
/**
|
||||
* Writes the proxy to the stream.
|
||||
* <p>Warning: This proxy will only be written to an Orb stream.
|
||||
* @param out The stream to write to.
|
||||
*/
|
||||
public void writeExternal(com.common.io.IObjectOutputStream out) throws java.io.IOException {
|
||||
if(out instanceof OrbObjectOutputStream) {
|
||||
AbstractConnection socket = ((OrbObjectOutputStream) out).getSocket();
|
||||
long luid;
|
||||
boolean isLooping = socket == this.socket;
|
||||
|
||||
//TODO: Investigate streaming a proxy via a second (different) orb.//
|
||||
if(orb != socket.getOrb()) {
|
||||
throw new java.io.IOException("A proxy may only be streamed via its ORB.");
|
||||
}//if//
|
||||
|
||||
//Increment the proxy count on the socket before sending unless we are back-tracking (sending the proxy back over the socket it came from).//
|
||||
if(this.socket != socket) {
|
||||
luid = orb.incrementProxyCount(socket, this);
|
||||
}//if//
|
||||
else {
|
||||
//Since we are back-tracking, send the remote process' luid.//
|
||||
luid = getLuid__Proxy();
|
||||
}//else//
|
||||
|
||||
out.writeInt(hash);
|
||||
out.writeInt(typeId);
|
||||
out.writeBoolean(isLooping);
|
||||
out.writeLong(isLooping ? remoteLuid : luid);
|
||||
}//if//
|
||||
else {
|
||||
throw new java.io.IOException("A proxy may only be streamed via its ORB.");
|
||||
}//else//
|
||||
}//writeExternal()//
|
||||
/**
|
||||
* Writes the proxy to the stream.
|
||||
* <p>Warning: This proxy will only be written to an Orb stream.
|
||||
* @param out The stream to write to.
|
||||
*/
|
||||
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException {
|
||||
throw new java.io.IOException("A proxy may only be streamed via its ORB.");
|
||||
}//writeExternal()//
|
||||
}//Proxy//
|
||||
328
Orb/src/com/de22/orb/SecurityMessageFilter.java
Normal file
328
Orb/src/com/de22/orb/SecurityMessageFilter.java
Normal file
@@ -0,0 +1,328 @@
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.AbstractConnection.MessageFilter;
|
||||
import com.de22.orb.security.AbstractSecuritySystem;
|
||||
|
||||
/**
|
||||
* The security filter for the ORB streams.
|
||||
*/
|
||||
public class SecurityMessageFilter extends MessageFilter {
|
||||
private AbstractSecuritySystem securitySystem;
|
||||
private StreamBuffer pendingSends = null;
|
||||
/**
|
||||
* SecurityMessageFilter constructor.
|
||||
* @param securitySystem The system used to handle security.
|
||||
*/
|
||||
public SecurityMessageFilter(AbstractSecuritySystem securitySystem) {
|
||||
super();
|
||||
this.securitySystem = securitySystem;
|
||||
}//SecurityMessageFilter()//
|
||||
/**
|
||||
* Initializes the security filter.
|
||||
* @param securitySystem The security system to use.
|
||||
*/
|
||||
public void initializeSecurity(AbstractSecuritySystem securitySystem) {
|
||||
this.securitySystem = securitySystem;
|
||||
}//initializeSecurity()//
|
||||
/**
|
||||
* Initializes the security filter.
|
||||
* @param securitySystemClassName The name of the security system to use.
|
||||
* @param securitySystemData The security system data.
|
||||
*/
|
||||
public void initializeSecurity(String securitySystemClassName, byte[] securitySystemData) throws IOException {
|
||||
if(securitySystemClassName != null) {
|
||||
try {
|
||||
Class cls = Class.forName(securitySystemClassName);
|
||||
|
||||
securitySystem = (AbstractSecuritySystem) cls.newInstance();
|
||||
securitySystem.initialize(securitySystemData);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
throw new IOException("Invalid security system parameters.");
|
||||
}//catch//
|
||||
}//if//
|
||||
}//initializeSecurity()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processIncommingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processIncommingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
if(securitySystem == null) {
|
||||
result = super.processIncommingMessage(input, output);
|
||||
}//if//
|
||||
else {
|
||||
ByteBuffer encryptedBuffer;
|
||||
ByteBuffer decryptedBuffer;
|
||||
|
||||
synchronized(BufferRepository.getSingleton()) {
|
||||
encryptedBuffer = BufferRepository.getSingleton().checkOutByteBuffer(securitySystem.getEncryptedChunkSize());
|
||||
decryptedBuffer = BufferRepository.getSingleton().checkOutByteBuffer(securitySystem.getDecryptedChunkSize());
|
||||
}//synchronized//
|
||||
|
||||
encryptedBuffer.clear();
|
||||
decryptedBuffer.clear();
|
||||
|
||||
try {
|
||||
//Run any handshaking.//
|
||||
if(securitySystem.isInitializing()) {
|
||||
Debug.log("Running next security handshake.");
|
||||
receiveHandshake(encryptedBuffer, decryptedBuffer, input);
|
||||
|
||||
if(!securitySystem.isInitializing()) {
|
||||
endInitialization();
|
||||
}//if//
|
||||
|
||||
sendHandshake(encryptedBuffer, decryptedBuffer);
|
||||
encryptedBuffer.clear();
|
||||
decryptedBuffer.clear();
|
||||
}//if//
|
||||
|
||||
//If we are not initializing, and there is more data in the input stream buffers or the encrypted buffer then attempt to process it.//
|
||||
if(!securitySystem.isInitializing() && input.getSize() > 0) {
|
||||
boolean hasMoreInput = true;
|
||||
|
||||
while(hasMoreInput) {
|
||||
int blockSize;
|
||||
|
||||
//Prepare the buffers.//
|
||||
encryptedBuffer.compact();
|
||||
decryptedBuffer.clear();
|
||||
//Read the size of the next block of encrypted data.//
|
||||
blockSize = input.readInt(StreamBuffer.NUMBER_VLSF);
|
||||
//Fill the encrypted buffer.//
|
||||
encryptedBuffer.flip();
|
||||
input.readBytes(encryptedBuffer, blockSize);
|
||||
encryptedBuffer.flip();
|
||||
//Perform the decryption.//
|
||||
securitySystem.decryptData(encryptedBuffer, decryptedBuffer);
|
||||
decryptedBuffer.flip();
|
||||
//Detect whether we have more data to decrypt.//
|
||||
hasMoreInput = decryptedBuffer.hasRemaining() && (input.getSize() > 0 || encryptedBuffer.hasRemaining());
|
||||
//Pass the decrypted bytes to the output buffer.//
|
||||
output.writeBytes(decryptedBuffer);
|
||||
}//while//
|
||||
}//else//
|
||||
}//try//
|
||||
catch(BufferUnderflowException e) {
|
||||
//Ignored - there were not enough bytes to
|
||||
}
|
||||
finally {
|
||||
synchronized(BufferRepository.getSingleton()) {
|
||||
BufferRepository.getSingleton().checkInByteBuffer(encryptedBuffer);
|
||||
BufferRepository.getSingleton().checkInByteBuffer(decryptedBuffer);
|
||||
}//synchronized//
|
||||
}//finally//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//processIncommingMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#processOutgoingMessage(com.de22.orb.StreamBuffer, com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
public int processOutgoingMessage(StreamBuffer input, StreamBuffer output) throws IOException {
|
||||
int result = RESULT_OK;
|
||||
|
||||
if(securitySystem == null) {
|
||||
result = super.processOutgoingMessage(input, output);
|
||||
}//if//
|
||||
else {
|
||||
ByteBuffer encryptedBuffer;
|
||||
ByteBuffer decryptedBuffer;
|
||||
|
||||
synchronized(BufferRepository.getSingleton()) {
|
||||
encryptedBuffer = BufferRepository.getSingleton().checkOutByteBuffer(securitySystem.getEncryptedChunkSize());
|
||||
decryptedBuffer = BufferRepository.getSingleton().checkOutByteBuffer(securitySystem.getDecryptedChunkSize());
|
||||
}//synchronized//
|
||||
|
||||
try {
|
||||
//If initializing then try to send the next initialization message.//
|
||||
if(securitySystem.isInitializing()) {
|
||||
//TODO: Allow a re-negotiation of the security settings - in which case messages going out should be suspended.
|
||||
Debug.log(new RuntimeException("Shouldn't get here."));
|
||||
}//if//
|
||||
|
||||
if(securitySystem.isInitializing()) { //TODO: Remove this.
|
||||
if(pendingSends == null) {
|
||||
pendingSends = new StreamBuffer();
|
||||
}//if//
|
||||
|
||||
pendingSends.writeBytes(input);
|
||||
}//if//
|
||||
else {
|
||||
// boolean isFirst = true;
|
||||
|
||||
//Send the pending messages first.//
|
||||
if(pendingSends != null) {
|
||||
pendingSends.writeBytes(input);
|
||||
input.release();
|
||||
input = pendingSends;
|
||||
}//if//
|
||||
|
||||
//Keep sending until all bytes are encrypted and sent.//
|
||||
while(input.getSize() > 0) {
|
||||
//Reset the buffers.//
|
||||
encryptedBuffer.clear();
|
||||
decryptedBuffer.clear();
|
||||
|
||||
// //Write the size of the outgoing byte stream chunk. This is required by the reading code to ensure trailing bytes are ignored.//
|
||||
// if(isFirst) {
|
||||
// StreamSupport.writeInt(input.getSize(), decryptedBuffer, StreamSupport.NUMBER_VLSF);
|
||||
// isFirst = false;
|
||||
// }//if//
|
||||
//Set the limit to the position so the encryption code knows how long the message is.//
|
||||
// decryptedBuffer.limit(decryptedBuffer.position());
|
||||
//TODO: Flip?
|
||||
|
||||
//Fill the decrypted data.//
|
||||
input.readBytes(decryptedBuffer);
|
||||
decryptedBuffer.flip();
|
||||
//Generate the encrypted data.//
|
||||
securitySystem.encryptData(encryptedBuffer, decryptedBuffer);
|
||||
//Flip the buffer so we can read from it.//
|
||||
encryptedBuffer.flip();
|
||||
//Write the encrypted bytes to the output buffer.//
|
||||
output.writeInt(encryptedBuffer.limit(), StreamBuffer.NUMBER_VLSF);
|
||||
output.writeBytes(encryptedBuffer);
|
||||
}//while//
|
||||
}//if//
|
||||
}//try//
|
||||
finally {
|
||||
synchronized(BufferRepository.getSingleton()) {
|
||||
BufferRepository.getSingleton().checkInByteBuffer(encryptedBuffer);
|
||||
BufferRepository.getSingleton().checkInByteBuffer(decryptedBuffer);
|
||||
}//synchronized//
|
||||
}//finally//
|
||||
}//else//
|
||||
|
||||
return result;
|
||||
}//processOutgoingMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.MessageFilter#beginInitialization()
|
||||
*/
|
||||
public boolean beginInitialization() throws IOException {
|
||||
boolean result = securitySystem != null && securitySystem.isInitializing();
|
||||
|
||||
if(securitySystem != null && !securitySystem.hasSentFirstInitializeMessage()) {
|
||||
Debug.log("Starting Sec Initialization");
|
||||
ByteBuffer encryptedBuffer;
|
||||
ByteBuffer decryptedBuffer;
|
||||
|
||||
synchronized(BufferRepository.getSingleton()) {
|
||||
encryptedBuffer = BufferRepository.getSingleton().checkOutByteBuffer(securitySystem.getEncryptedChunkSize());
|
||||
decryptedBuffer = BufferRepository.getSingleton().checkOutByteBuffer(securitySystem.getDecryptedChunkSize());
|
||||
}//synchronized//
|
||||
|
||||
try {
|
||||
sendHandshake(encryptedBuffer, decryptedBuffer);
|
||||
}//try//
|
||||
finally {
|
||||
synchronized(BufferRepository.getSingleton()) {
|
||||
BufferRepository.getSingleton().checkInByteBuffer(encryptedBuffer);
|
||||
BufferRepository.getSingleton().checkInByteBuffer(decryptedBuffer);
|
||||
}//synchronized//
|
||||
}//finally//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//beginInitialization()//
|
||||
/**
|
||||
* Sends zero or more handshake messages to the remote process.
|
||||
* @param encryptedBuffer The reusable encryption buffer.
|
||||
* @param decryptedBuffer The reusable decryption buffer.
|
||||
* @throws IOException
|
||||
*/
|
||||
private void sendHandshake(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer) throws IOException {
|
||||
StreamBuffer output = new StreamBuffer();
|
||||
int result = securitySystem.getInitializationStatus();
|
||||
|
||||
while(result == AbstractSecuritySystem.INIT_REQUIRES_SEND) {
|
||||
//Reset the buffers.//
|
||||
encryptedBuffer.clear();
|
||||
decryptedBuffer.clear();
|
||||
//Generate the response.//
|
||||
result = securitySystem.sendInitializationMessage(encryptedBuffer, decryptedBuffer);
|
||||
//Debug.log("Sending SSL handshake message on the " + (isServerSide() ? "server" : "client") + " of size " + encryptedBuffer.position() + ".");
|
||||
|
||||
//If the security system produced a response then send it.//
|
||||
if(encryptedBuffer.position() > 0) {
|
||||
//Write the message bytes.//
|
||||
//Note: Forcing the buffer to use all the bytes.//
|
||||
encryptedBuffer.flip();
|
||||
output.writeInt(encryptedBuffer.limit(), StreamBuffer.NUMBER_VLSF);
|
||||
output.writeBytes(encryptedBuffer);
|
||||
//getSocket().getOutputStream().write(encryptedBuffer.array(), 0, encryptedBuffer.position());
|
||||
|
||||
//Process any pending runnables.//
|
||||
while(securitySystem.hasPendingTask()) {
|
||||
securitySystem.getPendingTask().run();
|
||||
result = securitySystem.getInitializationStatus();
|
||||
}//while//
|
||||
}//if//
|
||||
}//while//
|
||||
|
||||
if(output.getSize() > 0) {
|
||||
sendMessage(output);
|
||||
}//if//
|
||||
}//sendHandshake()//
|
||||
/**
|
||||
* Receives zero or more handshake messages.
|
||||
* @param encryptedBuffer The reusable encryption buffer.
|
||||
* @param decryptedBuffer The reusable decryption buffer.
|
||||
* @param input The handshake bytes.
|
||||
*/
|
||||
private void receiveHandshake(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer, StreamBuffer input) {
|
||||
// int messageSize = encryptedBuffer.capacity();
|
||||
int result = securitySystem.getInitializationStatus();
|
||||
|
||||
try {
|
||||
//Keep processing incomming handshake messages until the last one is received or there isn't a message worth of bytes to process.//
|
||||
while(result == AbstractSecuritySystem.INIT_REQUIRES_RECEIVE && input.getSize() > 0) {
|
||||
// int readCount = 0;
|
||||
|
||||
//Read the message size.//
|
||||
// messageSize = input.readInt(StreamBuffer.NUMBER_LSF);
|
||||
//messageSize = StreamSupport.readInt(in);
|
||||
|
||||
// if(messageSize > 0) {
|
||||
//Reset the buffers.//
|
||||
encryptedBuffer.clear();
|
||||
decryptedBuffer.clear();
|
||||
//Fill the encrypted buffer.//
|
||||
input.readBytes(encryptedBuffer, input.readInt(StreamBuffer.NUMBER_VLSF));
|
||||
encryptedBuffer.flip();
|
||||
// encryptedBuffer.limit(messageSize);
|
||||
|
||||
//Keep processing the message until finished.//
|
||||
// while(result == AbstractSecuritySystem.INIT_REQUIRES_RECEIVE && encryptedBuffer.position() != encryptedBuffer.limit()) {
|
||||
//Debug.log("Receiving SSL handshake message on the " + (isServerSide() ? "server" : "client") + " of size " + messageSize + ".");
|
||||
//Process the initialization message.//
|
||||
result = securitySystem.receiveInitializationMessage(encryptedBuffer, decryptedBuffer);
|
||||
|
||||
//Process any pending runnables.//
|
||||
while(securitySystem.hasPendingTask()) {
|
||||
securitySystem.getPendingTask().run();
|
||||
result = securitySystem.getInitializationStatus();
|
||||
}//while//
|
||||
// }//while//
|
||||
// }//if//
|
||||
// else {
|
||||
// closeInternal(this, true);
|
||||
// result = AbstractSecuritySystem.INIT_ERROR;
|
||||
// }//else//
|
||||
}//while//
|
||||
}//try//
|
||||
catch(BufferUnderflowException e) {
|
||||
//Ignore - there are not enough bytes to process the next part of the handshake. More bytes will eventually be read.
|
||||
}//catch//
|
||||
}
|
||||
}//SecurityMessageFilter//
|
||||
328
Orb/src/com/de22/orb/StConnection.java
Normal file
328
Orb/src/com/de22/orb/StConnection.java
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.event.VoidHandler1;
|
||||
import com.common.event.VoidHandler2;
|
||||
import com.common.io.IClassReplacementHandler;
|
||||
import com.common.io.ObjectInputStream;
|
||||
import com.common.io.StreamSupport;
|
||||
import com.common.thread.ThreadService;
|
||||
import com.common.util.LiteList;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.AbstractConnection.ClassReplacementHandler;
|
||||
import com.de22.orb.exception.NewVersionFoundException;
|
||||
import com.de22.orb.exception.SocketFailedException;
|
||||
import com.de22.orb.io.OrbByteArrayOutputStream;
|
||||
import com.de22.orb.io.OrbObjectInputStream;
|
||||
import com.de22.orb.io.OrbObjectOutputStream;
|
||||
import com.de22.orb.security.AbstractSecuritySystem;
|
||||
|
||||
/**
|
||||
* The single threaded socket for use in a one thread per socket model.
|
||||
*/
|
||||
public class StConnection extends AbstractConnection {
|
||||
/**
|
||||
* The single threaded socket data.
|
||||
*/
|
||||
public class StSocketData extends SocketData {
|
||||
/** The actual socket that will be used for transmission and reception of messages. */
|
||||
private Socket socket = null;
|
||||
|
||||
/**
|
||||
* StSocketData constructor.
|
||||
* @param socket The socket that is being encapsulated.
|
||||
*/
|
||||
public StSocketData(Socket socket) throws IOException {
|
||||
super();
|
||||
this.socket = socket;
|
||||
}//StSocketData()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.SocketData#close()
|
||||
*/
|
||||
protected void close() {
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Ignored.//
|
||||
}//catch//
|
||||
}//if//
|
||||
}//close()//
|
||||
/**
|
||||
* Gets the socket.
|
||||
* @return The socket.
|
||||
*/
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}//getSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.SocketData#filterInitializationComplete()
|
||||
*/
|
||||
public void filterInitializationComplete() {
|
||||
super.filterInitializationComplete();
|
||||
|
||||
try {
|
||||
//TODO: Should this be on or off?
|
||||
socket.setKeepAlive(true);
|
||||
}//try//
|
||||
catch(SocketException e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//filterInitializationComplete()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket.SocketData#writeMessage(com.de22.orb.StreamBuffer)
|
||||
*/
|
||||
protected void writeMessage(StreamBuffer buffer) {
|
||||
//TODO: Is this correct code?
|
||||
try {
|
||||
socket.getOutputStream().write(buffer.toByteArray());
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
StConnection.this.close(this, true);
|
||||
}//catch//
|
||||
}//writeMessage()//
|
||||
}//StSocketData//
|
||||
|
||||
private class ListenerRunnable implements Runnable {
|
||||
public ListenerRunnable() {
|
||||
}//ListenerRunnable()//
|
||||
public void run() {
|
||||
boolean stop = false;
|
||||
StreamBuffer buffer = null;
|
||||
StSocketData socketData;
|
||||
|
||||
synchronized(StConnection.this) {
|
||||
socketData = (StSocketData) getSocketData();
|
||||
}//synchronized//
|
||||
|
||||
//Begin the handshaking.//
|
||||
socketData.startHandshake();
|
||||
|
||||
while(!stop) {
|
||||
buffer = new StreamBuffer();
|
||||
|
||||
try {
|
||||
InputStream in = socketData.getSocket().getInputStream();
|
||||
|
||||
if(in.available() > 0) {
|
||||
//Buffer the available bytes.//
|
||||
buffer.writeBytes(in);
|
||||
}//if//
|
||||
else {
|
||||
//Block until at least one more byte is available.//
|
||||
int next = in.read();
|
||||
|
||||
if(next != -1) {
|
||||
buffer.writeByte((byte) next);
|
||||
|
||||
if(in.available() > 0) {
|
||||
buffer.writeBytes(in);
|
||||
}//if//
|
||||
}//if//
|
||||
else {
|
||||
//Socket closed.//
|
||||
stop = true;
|
||||
}//else//
|
||||
}//else//
|
||||
|
||||
//Process as much of the buffered data as possible.//
|
||||
socketData.receiveMessage(buffer);
|
||||
|
||||
//Clean up after the buffer if it was used up (otherwise it is likely held by an input handler for future use).//
|
||||
if(buffer.getSize() == 0) {
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
}//if//
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
if(isOpen()) {
|
||||
Debug.log(e);
|
||||
close(socketData, true, false);
|
||||
}//if//
|
||||
|
||||
stop = true;
|
||||
}//catch//
|
||||
}//while//
|
||||
}//run()//
|
||||
}//ListenerRunnable//
|
||||
/**
|
||||
* StSocket constructor.
|
||||
*/
|
||||
public StConnection() {
|
||||
}//StSocket()//
|
||||
/**
|
||||
* StSocket constructor.
|
||||
* @param sessionId The session identifier issued by the server socket.
|
||||
* @param autoReconnectTimeLimit The amount of time the server should wait for the client to auto reconnect.
|
||||
*/
|
||||
public StConnection(long sessionId, long autoReconnectTimeLimit) {
|
||||
super(sessionId, autoReconnectTimeLimit);
|
||||
}//StSocket()//
|
||||
/**
|
||||
* Initializes a server side socket accepted through a server socket.
|
||||
* @param orb The orb instance that created this socket.
|
||||
* @param socket The underlying socket object that will perform the basic socket functions necessary for this perticular abstract socket.
|
||||
* @param serverSocket The server socket that accepted this socket.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, Socket socket, AbstractConnectionServer serverSocket, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler) throws IOException {
|
||||
super.initialize(orb, serverSocket, messageHandler, initCompleteHandler, socket.getInetAddress().getHostAddress() + ':' + socket.getPort());
|
||||
//Make sure that the socket is setup properly (tcpNoDelay, SoLinger, etc).//
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.setTcpNoDelay(serverSocket.getSocketOptions().useTcpNoDelay());
|
||||
socket.setSoTimeout(0);
|
||||
socket.setReuseAddress(true);
|
||||
socket.setKeepAlive(true);
|
||||
socket.setReceiveBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
socket.setSendBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
StSocketData socketData = new StSocketData(socket);
|
||||
|
||||
setSocketData(socketData);
|
||||
socketData.setActivityTime();
|
||||
//Start the listener thread.//
|
||||
//Wait for the client to send the first message.//
|
||||
ThreadService.run(new ListenerRunnable());
|
||||
}//initialize()//
|
||||
/**
|
||||
* Initializes the client side socket.
|
||||
* @param orb The orb instance that created this socket.
|
||||
* @param address The address to connect to.
|
||||
* @param port The port to connect on.
|
||||
* @param options The socket options that will be used to open the socket and to reconnect the socket.
|
||||
* @param classLoader The loader that will be used to load classes.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, InetAddress address, int port, ISocketOptions options, ClassLoader classLoader, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler) throws IOException {
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
int timeout = options.getSocketConnectionTimeout();
|
||||
|
||||
socket = new Socket();
|
||||
|
||||
try {
|
||||
socket.connect(new InetSocketAddress(address, port), timeout < 500 ? 500 : timeout);
|
||||
}//try//
|
||||
catch(SocketTimeoutException e) {
|
||||
socket = null;
|
||||
}//catch//
|
||||
|
||||
if(socket != null) {
|
||||
StSocketData socketData = new StSocketData(socket);
|
||||
|
||||
//Save the socket data.//
|
||||
setSocketData(socketData);
|
||||
//Initialize the base class.//
|
||||
super.initialize(orb, options, classLoader, messageHandler, initCompleteHandler, socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
|
||||
|
||||
//Initialize the socket.//
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.setTcpNoDelay(options.useTcpNoDelay());
|
||||
socket.setSoTimeout(0);
|
||||
socket.setReuseAddress(true);
|
||||
socket.setReceiveBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
socket.setSendBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
//Start the thread that will listen for incomming messages.//
|
||||
ThreadService.run(new ListenerRunnable());
|
||||
}//if//
|
||||
}//try//
|
||||
catch(NewVersionFoundException e) {
|
||||
//A newer version was found and we were forced to upgrade.//
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
catch(java.net.ConnectException e) {
|
||||
// Debug.log(e);
|
||||
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
}//initialize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractSocket#reconnect(java.net.InetAddress, int)
|
||||
*/
|
||||
protected void reconnect(InetAddress address, int port) {
|
||||
Socket socket = null;
|
||||
|
||||
try {
|
||||
socket = new Socket(address, port);
|
||||
|
||||
if(socket != null) {
|
||||
StSocketData socketData = new StSocketData(socket);
|
||||
|
||||
//Save the socket data.//
|
||||
setSocketData(socketData);
|
||||
|
||||
//Initialize the socket.//
|
||||
socket.setSoLinger(false, 0);
|
||||
socket.setTcpNoDelay(getSocketOptions().useTcpNoDelay());
|
||||
socket.setSoTimeout(0);
|
||||
socket.setReuseAddress(true);
|
||||
socket.setReceiveBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
socket.setSendBufferSize(internalSocketBufferSize); //TODO: Place this in the options.
|
||||
//Start the thread that will listen for incomming messages.//
|
||||
ThreadService.run(new ListenerRunnable());
|
||||
}//if//
|
||||
}//try//
|
||||
catch(java.net.ConnectException e) {
|
||||
// Debug.log(e);
|
||||
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
|
||||
if(socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
}//try//
|
||||
catch(Throwable e2) {}
|
||||
}//if//
|
||||
}//catch//
|
||||
}//reconnect()//
|
||||
}//StSocket//
|
||||
111
Orb/src/com/de22/orb/StServerSocket.java
Normal file
111
Orb/src/com/de22/orb/StServerSocket.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.event.VoidHandler1;
|
||||
import com.common.event.VoidHandler2;
|
||||
import com.common.thread.ThreadService;
|
||||
|
||||
public class StServerSocket extends AbstractConnectionServer {
|
||||
/** The underlying server socket. */
|
||||
private ServerSocket serverSocket = null;
|
||||
/** The listener thread. */
|
||||
private Thread listener = null;
|
||||
|
||||
/**
|
||||
* The runnable for a server socket to manage and thread the processing of new client sockets.
|
||||
*/
|
||||
private class ServerSocketRunnable implements Runnable {
|
||||
public void run() {
|
||||
while(serverSocket != null) {
|
||||
try {
|
||||
acceptSocket();
|
||||
}//try//
|
||||
catch(java.net.SocketException e) {
|
||||
break;
|
||||
}//catch//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
Debug.halt();
|
||||
break;
|
||||
}//catch//
|
||||
}//while//
|
||||
}//run()//
|
||||
}//ServerSocketRunnable//
|
||||
/**
|
||||
* StServerSocket constructor.
|
||||
*/
|
||||
public StServerSocket() {
|
||||
}//StServerSocket()//
|
||||
/**
|
||||
* Accepts a socket connection through the server socket.
|
||||
* @return The socket that was accepted.
|
||||
*/
|
||||
public AbstractConnection acceptSocket() throws IOException {
|
||||
StConnection result = null;
|
||||
Socket socket = serverSocket.accept();
|
||||
|
||||
if(socket != null) {
|
||||
result = new StConnection(getNextSessionId(), getServerSocketOptions().getAutoReconnectTimeLimit());
|
||||
registerConnection(result);
|
||||
result.initialize(getOrb(), socket, this, getMessageHandler(), getInitCompleteHandler());
|
||||
Debug.log("Socket listener started on: " + result.getNameAndPort() + " connecting via server socket: " + this.getNameAndPort());
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//acceptSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.AbstractServerSocket#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if(serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
}//catch//
|
||||
|
||||
//Set the server socket reference to null so everyone knows this server socket is not open.//
|
||||
serverSocket = null;
|
||||
|
||||
//If there is a server socket runnable then stop it.//
|
||||
if(listener != null) {
|
||||
//Don't need to do this at this time. Closing the socket will take care of this for us.//
|
||||
//listener.interrupt();
|
||||
}//if//
|
||||
|
||||
super.close();
|
||||
}//if//
|
||||
}//close()//
|
||||
/**
|
||||
* Initializes the server socket for use.
|
||||
* The user may call the acceptSocket() method after this method has successfully returned.
|
||||
* @param orb The orb that created the server socket.
|
||||
* @param options The server socket options used to setup the server socket.
|
||||
* @param address An optional address only used to optimize performance since the caller often will have to get this address before deciding to create a new server socket.
|
||||
* @param classLoader The class loader that the server socket and all accepted sockets will use for loading classes.
|
||||
* @param messageHandler The handler called to process a message after the bytes have been read from the stream.
|
||||
* @param initCompleteHandler The handler called to finish the initialization process (after all initialization of the socket has finished).
|
||||
*/
|
||||
public void initialize(Orb orb, IServerSocketOptions options, InetAddress address, ClassLoader classLoader, VoidHandler2 messageHandler, VoidHandler1 initCompleteHandler) throws IOException {
|
||||
//Setup the address if necessary.//
|
||||
if((address == null) && (options.getAddress().getName() != null)) {
|
||||
address = InetAddress.getByName(options.getAddress().getName());
|
||||
}//if//
|
||||
|
||||
super.initialize(orb, options, address, classLoader, messageHandler, initCompleteHandler);
|
||||
serverSocket = new ServerSocket(options.getAddress().getPort(), (options.getBacklog() != null ? options.getBacklog().intValue() : 50), address);
|
||||
listener = ThreadService.run(new ServerSocketRunnable(), false);
|
||||
}//internalInitialize()//
|
||||
}//StServerSocket//
|
||||
35
Orb/src/com/de22/orb/ValueHolder.java
Normal file
35
Orb/src/com/de22/orb/ValueHolder.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2005,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb;
|
||||
|
||||
/**
|
||||
* Holds a value and status information so that the orb can return extended information about a return value.
|
||||
*/
|
||||
class ValueHolder {
|
||||
public static final int STATUS_OK = 0;
|
||||
public static final int STATUS_TIMEOUT = 1;
|
||||
public static final int STATUS_SOCKET_NOT_FOUND = 2;
|
||||
public static final int STATUS_SOCKET_ERROR = 3;
|
||||
|
||||
public int status = 0;
|
||||
public Object value = null;
|
||||
/**
|
||||
* ValueHolder constructor.
|
||||
*/
|
||||
ValueHolder() {
|
||||
super();
|
||||
}//ValueHolder()//
|
||||
/**
|
||||
* ValueHolder constructor.
|
||||
*/
|
||||
ValueHolder(Object value, int status) {
|
||||
super();
|
||||
this.value = value;
|
||||
this.status = status;
|
||||
}//ValueHolder()//
|
||||
}//ValueHolder//
|
||||
166
Orb/src/com/de22/orb/development/OrbClassLoader.java
Normal file
166
Orb/src/com/de22/orb/development/OrbClassLoader.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.development;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import com.common.debug.*;
|
||||
import com.de22.orb.Proxy;
|
||||
|
||||
public class OrbClassLoader extends ClassLoader {
|
||||
private File writeDirectory = null;
|
||||
private boolean isParentSystemClassLoader = false;
|
||||
/**
|
||||
* OrbClassLoader constructor.
|
||||
*/
|
||||
public OrbClassLoader() {
|
||||
super();
|
||||
isParentSystemClassLoader = getParent() == ClassLoader.getSystemClassLoader();
|
||||
}//OrbClassLoader()//
|
||||
/**
|
||||
* OrbClassLoader constructor.
|
||||
* @param parent The parent class loader.
|
||||
*/
|
||||
public OrbClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
isParentSystemClassLoader = getParent() == ClassLoader.getSystemClassLoader();
|
||||
}//OrbClassLoader()//
|
||||
/**
|
||||
* OrbClassLoader constructor.
|
||||
* @param parent The parent class loader.
|
||||
*/
|
||||
public OrbClassLoader(ClassLoader parent, String writeDirectory) {
|
||||
super(parent);
|
||||
|
||||
this.writeDirectory = new File(writeDirectory);
|
||||
isParentSystemClassLoader = getParent() == ClassLoader.getSystemClassLoader();
|
||||
}//OrbClassLoader()//
|
||||
/**
|
||||
* OrbClassLoader constructor.
|
||||
*/
|
||||
public OrbClassLoader(String writeDirectory) {
|
||||
super();
|
||||
|
||||
this.writeDirectory = new File(writeDirectory);
|
||||
isParentSystemClassLoader = getParent() == ClassLoader.getSystemClassLoader();
|
||||
}//OrbClassLoader()//
|
||||
/**
|
||||
* OrbClassLoader constructor.
|
||||
* @param parent The parent class loader.
|
||||
*/
|
||||
public OrbClassLoader(ClassLoader parent, File writeDirectory) {
|
||||
super(parent);
|
||||
|
||||
this.writeDirectory = writeDirectory;
|
||||
isParentSystemClassLoader = getParent() == ClassLoader.getSystemClassLoader();
|
||||
}//OrbClassLoader()//
|
||||
/**
|
||||
* OrbClassLoader constructor.
|
||||
*/
|
||||
public OrbClassLoader(File writeDirectory) {
|
||||
super();
|
||||
|
||||
this.writeDirectory = writeDirectory;
|
||||
isParentSystemClassLoader = getParent() == ClassLoader.getSystemClassLoader();
|
||||
}//OrbClassLoader()//
|
||||
/**
|
||||
* Locates the specified class name.
|
||||
* @param name The name of the class.
|
||||
* @return The class associated with the name.
|
||||
*/
|
||||
protected Class findClass(String name) throws ClassNotFoundException {
|
||||
if(name.endsWith(Proxy.PROXY_EXTENSION)) {
|
||||
String proxiedClassName = name.substring(0, name.length() - Proxy.PROXY_EXTENSION_LENGTH);
|
||||
|
||||
return loadProxyClass(proxiedClassName, name);
|
||||
}//if//
|
||||
else if(!isParentSystemClassLoader) {
|
||||
//TODO: This doesn't appear to work if the parent is the default system class loader. Does it work if it any other class loader? Note: This problem appears to have been introduced in 1.6 of the JDK.
|
||||
return getParent().loadClass(name);
|
||||
}//else if//
|
||||
else {
|
||||
return Class.forName(name);
|
||||
}//else//
|
||||
}//findClass()//
|
||||
/**
|
||||
* Creates and loads the given class' proxy.
|
||||
* @param name The name of the class to be proxied.
|
||||
* @param proxyName The name of the proxy class.
|
||||
* @return The proxy class associated with the named class.
|
||||
*/
|
||||
protected Class loadProxyClass(String name, String proxyName) throws ClassNotFoundException {
|
||||
ProxyGenerator proxyGenerator = new ProxyGenerator(name + Proxy.PROXY_EXTENSION, false, writeDirectory);
|
||||
byte[] classBytes = null;
|
||||
Class proxyClass = null;
|
||||
|
||||
try {
|
||||
classBytes = proxyGenerator.generate(loadClass(name));
|
||||
//Note: I think this is done by the proxy generator...TODO: Write the class file if necessary.//
|
||||
|
||||
//TODO: Track which proxies were generated if necessary.//
|
||||
|
||||
proxyClass = defineClass(proxyName, classBytes, 0, classBytes.length);
|
||||
//TODO: Should I resolve the class?//
|
||||
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
Debug.halt();
|
||||
}//catch//
|
||||
|
||||
return proxyClass;
|
||||
}//loadProxyClass()//
|
||||
/**
|
||||
* Regenerates (refreshes) proxy classes based on the proxy text files in a given directory.
|
||||
* Searches a directory (not including subdirectories) for files containing qualified type names (dot notation) and ending in ".txt" instead of ".class" or ".java".
|
||||
* Uses the qualified type names to recreate the proxy class files, placing them in the proper sub-directories of the given directory.
|
||||
* <p>Warning: Deletes all class files in the given directory and any sub-directories.</p>
|
||||
* @param args Only one argument is expected or required. The first argument is the path to the directory containing files whose names end with "__SZProxy.txt", and where the generated proxy files will be placed. All other class files in any subdirectories will be deleted.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
boolean printInstructions = false;
|
||||
|
||||
if(args.length == 1) {
|
||||
File directory = new File(args[0]);
|
||||
|
||||
if(directory.exists() && directory.isDirectory() && directory.canRead() && directory.canWrite()) {
|
||||
OrbClassLoader loader = new OrbClassLoader(args[0]);
|
||||
File[] files = directory.listFiles();
|
||||
|
||||
for(int index = 0; index < files.length; index++) {
|
||||
if(files[index].getName().endsWith("__SZProxy.txt")) {
|
||||
String qualifiedProxyName = files[index].getName().substring(0, files[index].getName().length() - 4);
|
||||
|
||||
try {
|
||||
loader.loadClass(qualifiedProxyName);
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
Debug.log(e);
|
||||
}//catch//
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
else {
|
||||
printInstructions = true;
|
||||
}//else//
|
||||
}//if//
|
||||
else {
|
||||
printInstructions = true;
|
||||
}//else//
|
||||
|
||||
if(printInstructions) {
|
||||
System.out.println("Expecting a single argument: The directory path containing files ending with '__SZProxy.txt' whose names are the qualified interface used to generate the proxy. All classes in this directory or any sub-directory will be deleted.");
|
||||
|
||||
if(args.length > 0) {
|
||||
System.out.println("Received:\r\n" + args[0]);
|
||||
}//if//
|
||||
|
||||
System.out.println("Current Path:\r\n" + new File(".").getAbsolutePath());
|
||||
}//if//
|
||||
}//main()//
|
||||
}//OrbClassLoader//
|
||||
1218
Orb/src/com/de22/orb/development/ProxyGenerator.java
Normal file
1218
Orb/src/com/de22/orb/development/ProxyGenerator.java
Normal file
File diff suppressed because it is too large
Load Diff
14
Orb/src/com/de22/orb/exception/AuthenticationException.java
Normal file
14
Orb/src/com/de22/orb/exception/AuthenticationException.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.de22.orb.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Used by the orb to flag an error authenticating the server when connecting from the client.
|
||||
*/
|
||||
public class AuthenticationException extends IOException {
|
||||
public AuthenticationException() {
|
||||
}
|
||||
public AuthenticationException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
24
Orb/src/com/de22/orb/exception/InvalidProxyException.java
Normal file
24
Orb/src/com/de22/orb/exception/InvalidProxyException.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.exception;
|
||||
|
||||
public class InvalidProxyException extends RuntimeException {
|
||||
/**
|
||||
* InvalidProxyException constructor.
|
||||
*/
|
||||
public InvalidProxyException() {
|
||||
super();
|
||||
}//InvalidProxyException()//
|
||||
/**
|
||||
* InvalidProxyException constructor.
|
||||
* @param description The exception description.
|
||||
*/
|
||||
public InvalidProxyException(String description) {
|
||||
super(description);
|
||||
}//InvalidProxyException()//
|
||||
}//InvalidProxyException//
|
||||
24
Orb/src/com/de22/orb/exception/MethodNotFoundException.java
Normal file
24
Orb/src/com/de22/orb/exception/MethodNotFoundException.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2002,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.exception;
|
||||
|
||||
public class MethodNotFoundException extends RuntimeException {
|
||||
/**
|
||||
* MethodNotFoundException constructor.
|
||||
*/
|
||||
public MethodNotFoundException() {
|
||||
super();
|
||||
}//MethodNotFoundException()//
|
||||
/**
|
||||
* MethodNotFoundException constructor.
|
||||
* @param description The exception description.
|
||||
*/
|
||||
public MethodNotFoundException(String description) {
|
||||
super(description);
|
||||
}//MethodNotFoundException()//
|
||||
}//MethodNotFoundException//
|
||||
25
Orb/src/com/de22/orb/exception/NewVersionFoundException.java
Normal file
25
Orb/src/com/de22/orb/exception/NewVersionFoundException.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NewVersionFoundException extends IOException {
|
||||
/**
|
||||
* NewVersionFoundException constructor.
|
||||
*/
|
||||
public NewVersionFoundException() {
|
||||
}//NewVersionFoundException()//
|
||||
/**
|
||||
* NewVersionFoundException constructor.
|
||||
* @param s
|
||||
*/
|
||||
public NewVersionFoundException(String s) {
|
||||
super(s);
|
||||
}//NewVersionFoundException()//
|
||||
}//NewVersionFoundException//
|
||||
27
Orb/src/com/de22/orb/exception/SocketFailedException.java
Normal file
27
Orb/src/com/de22/orb/exception/SocketFailedException.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SocketFailedException extends IOException {
|
||||
/**
|
||||
* SocketFailedException constructor.
|
||||
* @param socket The socket that failed.
|
||||
*/
|
||||
public SocketFailedException() {
|
||||
}//SocketFailedException()//
|
||||
/**
|
||||
* SocketFailedException constructor.
|
||||
* @param message Exception message.
|
||||
* @param socket The socket that failed.
|
||||
*/
|
||||
public SocketFailedException(String message) {
|
||||
super(message);
|
||||
}//SocketFailedException()//
|
||||
}//SocketFailedException//
|
||||
27
Orb/src/com/de22/orb/exception/SocketFailureException.java
Normal file
27
Orb/src/com/de22/orb/exception/SocketFailureException.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.exception;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SocketFailureException extends RuntimeException {
|
||||
/**
|
||||
* SocketFailureException constructor.
|
||||
* @param socket The socket that failed.
|
||||
*/
|
||||
public SocketFailureException() {
|
||||
}//SocketFailureException()//
|
||||
/**
|
||||
* SocketFailureException constructor.
|
||||
* @param message Exception message.
|
||||
* @param socket The socket that failed.
|
||||
*/
|
||||
public SocketFailureException(String message) {
|
||||
super(message);
|
||||
}//SocketFailureException()//
|
||||
}//SocketFailureException//
|
||||
24
Orb/src/com/de22/orb/exception/TimeoutException.java
Normal file
24
Orb/src/com/de22/orb/exception/TimeoutException.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2003,2005 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.exception;
|
||||
|
||||
public class TimeoutException extends RuntimeException {
|
||||
/**
|
||||
* TimeoutException constructor.
|
||||
*/
|
||||
public TimeoutException() {
|
||||
super();
|
||||
}//TimeoutException()//
|
||||
/**
|
||||
* TimeoutException constructor.
|
||||
* @param description The exception description.
|
||||
*/
|
||||
public TimeoutException(String description) {
|
||||
super(description);
|
||||
}//TimeoutException()//
|
||||
}//TimeoutException//
|
||||
35
Orb/src/com/de22/orb/io/IOrbInputStream.java
Normal file
35
Orb/src/com/de22/orb/io/IOrbInputStream.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Defines functionality required by the orb of its streams.
|
||||
*/
|
||||
public interface IOrbInputStream {
|
||||
/**
|
||||
* Determines whether the input stream supports the read from functionality.
|
||||
* Implementors should return true if they support the functionality, or should determine whether the encapsulated stream(s) support the functionality.
|
||||
* @return Whether the readFrom functionality is supported by the aggregate stream (this stream and all necessary substreams).
|
||||
*/
|
||||
public boolean canReadFrom();
|
||||
/**
|
||||
* Reads bytes from this stream and places them into the supplied output stream.
|
||||
* @param out The output stream to write the read bytes to.
|
||||
* @param length The number of bytes to read from the stream.
|
||||
* @return The number of bytes read from the stream.
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException;
|
||||
/**
|
||||
* Reads bytes from another stream and appends them to this stream.
|
||||
* @param in The input stream to read the bytes from.
|
||||
* @param numberOfBytes The number of bytes to read from the stream.
|
||||
*/
|
||||
public void readFrom(java.io.InputStream in, int numberOfBytes) throws IOException;
|
||||
}//IOrbInputStream//
|
||||
43
Orb/src/com/de22/orb/io/IOrbOutputStream.java
Normal file
43
Orb/src/com/de22/orb/io/IOrbOutputStream.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface IOrbOutputStream extends com.common.io.IOutputStream {
|
||||
/**
|
||||
* Determines whether the stream is capable of determining the message size in terms of bytes.
|
||||
* @return Whether the data stream is capable of getting a message size.
|
||||
*/
|
||||
public boolean canGetSize();
|
||||
/**
|
||||
* Determines whether the stream is capable of reseting the output stream so it can be reused.
|
||||
* @return Whether the data stream is capable of being reused after a call to reset.
|
||||
*/
|
||||
public boolean canReset();
|
||||
/**
|
||||
* Determines whether the stream is capable of writing the message to another output stream.
|
||||
* @return Whether the data stream is capable of writing to an output stream.
|
||||
*/
|
||||
public boolean canWriteTo();
|
||||
/**
|
||||
* Gets the number of bytes in the stream (including reserved or inset bytes if there are any).
|
||||
* @return The number of bytes in the stream.
|
||||
*/
|
||||
public int getSize();
|
||||
/**
|
||||
* Resets the stream so that it may be reused.
|
||||
*/
|
||||
public void reset() throws IOException;
|
||||
/**
|
||||
* Writes the contents of the stream buffer to the given output stream.
|
||||
* @param out The output stream to write the data to.
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException;
|
||||
}//IOrbOutputStream//
|
||||
125
Orb/src/com/de22/orb/io/OrbByteArrayInputStream.java
Normal file
125
Orb/src/com/de22/orb/io/OrbByteArrayInputStream.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.common.exception.MethodNotSupportedException;
|
||||
import com.common.io.IInputStream;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.BufferRepository;
|
||||
|
||||
public class OrbByteArrayInputStream extends InputStream implements IOrbInputStream, IInputStream {
|
||||
private StreamBuffer buffer = null;
|
||||
/**
|
||||
* OrbByteArrayInputStream constructor.
|
||||
* @param size The size of the underlying byte array.
|
||||
*/
|
||||
public OrbByteArrayInputStream(StreamBuffer buffer) {
|
||||
super();
|
||||
this.buffer = buffer;
|
||||
}//OrbByteArrayInputStream()//
|
||||
/**
|
||||
* Gets the number of available bytes in the input stream.
|
||||
* @return The number of bytes that have not yet been read from the input stream.
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return buffer.getSize();
|
||||
}//available()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#canDecrypt()
|
||||
*/
|
||||
public boolean canDecrypt() {
|
||||
return false;
|
||||
}//canDecrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.io.IOrbInputStream#canReadFrom()
|
||||
*/
|
||||
public boolean canReadFrom() {
|
||||
return true;
|
||||
}//canReadFrom()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
release();
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#decrypt(boolean)
|
||||
*/
|
||||
public void decrypt(boolean decrypt) throws java.io.IOException {
|
||||
//Not functional.//
|
||||
}//encrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#isDecrypting()
|
||||
*/
|
||||
public boolean isDecrypting() {
|
||||
return false;
|
||||
}//isDecrypting()//
|
||||
/**
|
||||
* Gets the next byte from the stream without actually incrementing the stream.
|
||||
* @return The next byte in the stream.
|
||||
*/
|
||||
public byte peek() throws IOException {
|
||||
return peek(1);
|
||||
}//peek()//
|
||||
/**
|
||||
* Gets the byte from the stream at the requested offset without actually incrementing the stream.
|
||||
* @param offset The offset from the current location in the stream. This value must be positive and should not exceed the number of bytes left in the stream.
|
||||
* @return The byte found at the specified offset.
|
||||
*/
|
||||
public byte peek(int offset) throws IOException {
|
||||
return buffer.getByte(offset);
|
||||
}//peek()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
return buffer.getSize() > 0 ? buffer.readByte() & 0xFF : -1;
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read(byte[], int, int)
|
||||
*/
|
||||
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||
return buffer.readBytes(bytes, offset, length);
|
||||
}//read()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IInputStream#read(java.io.OutputStream, int)
|
||||
*/
|
||||
public int read(java.io.OutputStream out, int length) throws IOException {
|
||||
return buffer.readBytes(out, length);
|
||||
}//read()//
|
||||
/**
|
||||
* Replaces the buffered data in this input stream with the bytes from the given input stream.
|
||||
* @param in The input stream containing the data to be buffered by this input stream.
|
||||
* @param numberOfBytes The number of bytes to be read.
|
||||
* @throws IOException If there are not enough bytes on the given input stream.
|
||||
*/
|
||||
public void readFrom(InputStream in, int numberOfBytes) throws IOException {
|
||||
buffer.release();
|
||||
buffer = new StreamBuffer();
|
||||
buffer.writeBytes(in, numberOfBytes);
|
||||
}//readFrom()//
|
||||
/**
|
||||
* Releases the stream resources and resets the stream so that the object may be GC'd or reused.
|
||||
* This stream will no longer be re-readable.
|
||||
*/
|
||||
public void release() {
|
||||
if(buffer != null) {
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
}//if//
|
||||
}//release()//
|
||||
/**
|
||||
* Resets the stream so that it may be re-read.
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
throw new MethodNotSupportedException();
|
||||
}//reset()//
|
||||
}//OrbByteArrayInputStream//
|
||||
204
Orb/src/com/de22/orb/io/OrbByteArrayOutputStream.java
Normal file
204
Orb/src/com/de22/orb/io/OrbByteArrayOutputStream.java
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.common.io.*;
|
||||
import com.common.security.ISymmetricAlgorithm;
|
||||
import com.common.util.StreamBuffer;
|
||||
import com.de22.orb.BufferRepository;
|
||||
|
||||
/*
|
||||
* <p>Note: Removed the code that leaves space since it didn't mesh well with the crappy SSL implementation which doesn't use a known block size even though it reports one (that is wrong).</p>
|
||||
* This special output stream leaves space for unecrypted data at the beginning of the stream, and leaves space for encrypted data between each block of unencrypted data.
|
||||
*/
|
||||
public class OrbByteArrayOutputStream extends OutputStream implements IOrbOutputStream {
|
||||
private StreamBuffer buffer = new StreamBuffer();
|
||||
private int skippedByteCount = 0;
|
||||
/**
|
||||
* OrbByteArrayOutputStream constructor.
|
||||
* @param skipCount The number of bytes at the beginning of the stream to not include in the encryption blocks.
|
||||
*/
|
||||
public OrbByteArrayOutputStream(int skipCount) {
|
||||
super();
|
||||
byte[] skipped = new byte[skipCount];
|
||||
|
||||
skippedByteCount = skipCount;
|
||||
buffer.writeBytes(skipped);
|
||||
}//OrbByteArrayOutputStream()//
|
||||
/**
|
||||
* Gets the number of bytes at the beginning of the stream that were skipped.
|
||||
* @return The skipped number of bytes at the start of the stream.
|
||||
*/
|
||||
public int getSkippedByteCount() {
|
||||
return skippedByteCount;
|
||||
}//getSkippedByteCount()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return false;
|
||||
}//canEncrypt()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.io.IOrbOutputStream#canGetSize()
|
||||
*/
|
||||
public boolean canGetSize() {
|
||||
return true;
|
||||
}//canGetSize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.io.IOrbOutputStream#canReset()
|
||||
*/
|
||||
public boolean canReset() {
|
||||
return true;
|
||||
}//canReset()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.io.IOrbOutputStream#canWriteTo()
|
||||
*/
|
||||
public boolean canWriteTo() {
|
||||
return true;
|
||||
}//canWriteTo()//
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if(buffer != null) {
|
||||
buffer.release();
|
||||
buffer = null;
|
||||
}//if//
|
||||
}//close()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws java.io.IOException {
|
||||
//Not supported.//
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Makes sure there is enough space available to write <code>size</code> bytes to the stream.
|
||||
* @param size The number of bytes of space that should be available.
|
||||
*/
|
||||
protected void ensureSpace(int size) {
|
||||
//Doesn't do anything.//
|
||||
}//ensureSpace()//
|
||||
/**
|
||||
* Gets the buffer used by this stream.
|
||||
* @return The buffer used by the stream for storing bytes written.
|
||||
*/
|
||||
public StreamBuffer getBuffer() {
|
||||
return buffer;
|
||||
}//getBuffer()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.io.IOrbOutputStream#getSize()
|
||||
*/
|
||||
public int getSize() {
|
||||
return buffer.getSize();
|
||||
}//getSize()//
|
||||
/**
|
||||
* Resets the stream so it may be reused.
|
||||
*/
|
||||
private void internalReset() {
|
||||
if(buffer != null) {
|
||||
buffer.release();
|
||||
}//if//
|
||||
|
||||
buffer = new StreamBuffer();
|
||||
}//internalReset()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.IOutputStream#isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return false;
|
||||
}//isEncrypting()//
|
||||
/**
|
||||
* Will add padding to the stream.
|
||||
* <p>NOTE: The purpose of this method is to get around timing problems in win95/98 where streams of a size less than 255 bytes causes 150ms delays in reading from the stream.
|
||||
* @param size The number of padding bytes to be written to the stream.
|
||||
*/
|
||||
public void padTo(int size) throws IOException {
|
||||
int paddingSize = size;
|
||||
|
||||
//Write zeros to the stream for padding.//
|
||||
if(paddingSize > 0) {
|
||||
while(paddingSize != 0) {
|
||||
write(0);
|
||||
paddingSize--;
|
||||
}//while//
|
||||
}//if//
|
||||
}//padTo()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.io.IOrbOutputStream#reset()
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
internalReset();
|
||||
}//reset()//
|
||||
/**
|
||||
* Copies the contents of the stream's buffer into a new byte array. This will clear the contents of the output stream.
|
||||
* @return A byte array containing all of the bytes written to this stream.
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] newbuffer = new byte[buffer.getSize()];
|
||||
|
||||
buffer.readBytes(newbuffer, 0, newbuffer.length);
|
||||
|
||||
return newbuffer;
|
||||
}//toByteArray()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
*/
|
||||
public void write(ByteBuffer bytes) throws java.io.IOException {
|
||||
buffer.writeBytes(bytes);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
* @param length The number of bytes to write to this stream.
|
||||
*/
|
||||
public void write(ByteBuffer bytes, int count) throws java.io.IOException {
|
||||
buffer.writeBytes(bytes, count);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
*/
|
||||
public void write(byte[] bytes) throws java.io.IOException {
|
||||
buffer.writeBytes(bytes);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the bytes to this stream.
|
||||
* @param bytes The data to be written to this stream.
|
||||
* @param offset The offset of the first byte to write.
|
||||
* @param length The number of bytes to write to this stream.
|
||||
*/
|
||||
public void write(byte[] bytes, int offset, int length) throws java.io.IOException {
|
||||
buffer.writeBytes(bytes, offset, length);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the specified byte to this stream.
|
||||
* @param b The byte to append to this stream.
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
buffer.writeByte((byte) b);
|
||||
}//write()//
|
||||
/**
|
||||
* Writes the contents of the stream buffer to the given output stream.
|
||||
* @param out The output stream to write the data to.
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
buffer.readBytes(out);
|
||||
}//writeTo()//
|
||||
/**
|
||||
* Writes the contents of the stream buffer to the given byte buffer.
|
||||
* @param bytes The byte buffer to write the data to.
|
||||
*/
|
||||
public void writeTo(ByteBuffer bytes) throws IOException {
|
||||
buffer.readBytes(bytes);
|
||||
}//writeTo()//
|
||||
}//OrbByteArrayOutputStream//
|
||||
80
Orb/src/com/de22/orb/io/OrbObjectInputStream.java
Normal file
80
Orb/src/com/de22/orb/io/OrbObjectInputStream.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.io;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import com.common.io.*;
|
||||
import com.de22.orb.*;
|
||||
|
||||
public class OrbObjectInputStream extends ObjectInputStream implements IOrbInputStream {
|
||||
private AbstractConnection socket = null;
|
||||
private IOrbInputStream inputStream = null;
|
||||
private OrbByteArrayInputStream byteInputStream = null;
|
||||
/**
|
||||
* OrbObjectInputStream constructor.
|
||||
* @param inputStream
|
||||
* @param byteInputStream
|
||||
* @param loader
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList
|
||||
* @param classTracker
|
||||
* @param socket The socket associated with the stream.
|
||||
* @exception java.io.IOException
|
||||
*/
|
||||
public OrbObjectInputStream(IOrbInputStream inputStream, OrbByteArrayInputStream byteInputStream, ClassLoader loader, IClassReplacementHandler classReplacementHandler, com.common.util.IList classList, com.common.io.IInstanceFactory instancefactory, com.common.io.IClassTracker classTracker, AbstractConnection socket) throws java.io.IOException {
|
||||
super((InputStream) inputStream, loader, classReplacementHandler, classList, instancefactory, classTracker, STYLE_MSF);
|
||||
|
||||
this.inputStream = inputStream;
|
||||
this.socket = socket;
|
||||
this.byteInputStream = byteInputStream;
|
||||
}//OrbObjectInputStream()//
|
||||
/**
|
||||
* OrbObjectInputStream constructor.
|
||||
* @param inputStream
|
||||
* @param byteInputStream
|
||||
* @param loader
|
||||
* @param classReplacementHandler The optional handler called when the stream loads a class. Allows the stream to replace one class name with another.
|
||||
* @param classList
|
||||
* @param socket The socket associated with the stream.
|
||||
* @exception java.io.IOException
|
||||
*/
|
||||
public OrbObjectInputStream(IOrbInputStream inputStream, OrbByteArrayInputStream byteInputStream, ClassLoader loader, IClassReplacementHandler classReplacementHandler, com.common.util.IList classList, AbstractConnection socket) throws java.io.IOException {
|
||||
super((InputStream) inputStream, loader, classReplacementHandler, classList, null, null);
|
||||
|
||||
this.inputStream = inputStream;
|
||||
this.socket = socket;
|
||||
this.byteInputStream = byteInputStream;
|
||||
}//OrbObjectInputStream()//
|
||||
/**
|
||||
* Gets the byte array input stream.
|
||||
* @return The underlying byte array input stream.
|
||||
*/
|
||||
public OrbByteArrayInputStream getByteInputStream() {
|
||||
return byteInputStream;
|
||||
}//getByteInputStream()//
|
||||
/**
|
||||
* @see IInputStream.canReadFrom()
|
||||
*/
|
||||
public boolean canReadFrom() {
|
||||
return inputStream.canReadFrom();
|
||||
}//canReadFrom()//
|
||||
/**
|
||||
* Gets the socket associated with this stream.
|
||||
* @return The socket associated with the stream.
|
||||
*/
|
||||
public AbstractConnection getSocket() {
|
||||
return socket;
|
||||
}//getSocket()//
|
||||
/**
|
||||
* @see IInputStream.readFrom(java.io.InputStream, int)
|
||||
*/
|
||||
public void readFrom(InputStream in, int numberOfBytes) throws IOException {
|
||||
inputStream.readFrom(in, numberOfBytes);
|
||||
}//readFrom()//
|
||||
}//OrbObjectInputStream//
|
||||
110
Orb/src/com/de22/orb/io/OrbObjectOutputStream.java
Normal file
110
Orb/src/com/de22/orb/io/OrbObjectOutputStream.java
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import com.common.io.*;
|
||||
import com.de22.orb.*;
|
||||
|
||||
public class OrbObjectOutputStream extends ObjectOutputStream implements IOrbOutputStream {
|
||||
private AbstractConnection socket = null;
|
||||
private IOrbOutputStream outputStream = null;
|
||||
private OrbByteArrayOutputStream byteOutputStream = null;
|
||||
/**
|
||||
* OrbObjectOutputStream constructor.
|
||||
* @param outputStream This can be null in which case the byte output stream will be wrappered directly.
|
||||
* @param byteOutputStream The underlying byte output stream, making it easier to access from the orb.
|
||||
* @param classMap The map of Integer identifers indexed by the class name that they represent.
|
||||
* @param socket The socket associated with the stream.
|
||||
* @param classReplacementHandler The handler called when writing a class name to the stream. This allows the application to swap the name for another name.
|
||||
* @exception java.io.IOException
|
||||
*/
|
||||
public OrbObjectOutputStream(IOrbOutputStream outputStream, OrbByteArrayOutputStream byteOutputStream, com.common.util.LiteHashMap classMap, AbstractConnection socket, IClassReplacementHandler classReplacementHandler) throws java.io.IOException {
|
||||
super((OutputStream) (outputStream == null ? byteOutputStream : outputStream), classMap, classReplacementHandler, STYLE_MSF);
|
||||
|
||||
this.outputStream = outputStream == null ? byteOutputStream : outputStream;
|
||||
this.byteOutputStream = byteOutputStream;
|
||||
this.socket = socket;
|
||||
}//OrbObjectOutputStream()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.io.ObjectOutputStream#canEncrypt()
|
||||
*/
|
||||
public boolean canEncrypt() {
|
||||
return outputStream.canEncrypt();
|
||||
}//canEncrypt()//
|
||||
/**
|
||||
* @see IOutputStream.canEncrypt()
|
||||
*/
|
||||
public boolean canGetSize() {
|
||||
return outputStream.canGetSize();
|
||||
}//canGetSize()//
|
||||
/**
|
||||
* @see IOutputStream.canReset()
|
||||
*/
|
||||
public boolean canReset() {
|
||||
return outputStream.canReset();
|
||||
}//canReset()//
|
||||
/**
|
||||
* @see IOutputStream.canWriteTo()
|
||||
*/
|
||||
public boolean canWriteTo() {
|
||||
return outputStream.canWriteTo();
|
||||
}//canWriteTo()//
|
||||
/**
|
||||
* @see IOutputStream.encrypt(boolean)
|
||||
*/
|
||||
public void encrypt(boolean encrypt) throws IOException {
|
||||
outputStream.encrypt(encrypt);
|
||||
|
||||
//Keep track of whether encryption is used in the streaming.//
|
||||
if(outputStream.isEncrypting()) {
|
||||
containsEncryptedSegments(true);
|
||||
}//if//
|
||||
}//encrypt()//
|
||||
/**
|
||||
* Gets the underlying output stream used for writing data.
|
||||
* @return The output stream encapsulated by this object output stream.
|
||||
*/
|
||||
public OrbByteArrayOutputStream getOutputStream() {
|
||||
return byteOutputStream;
|
||||
}//getOutputStream()//
|
||||
/**
|
||||
* @see IOrbObjectOutputStream.getSize()
|
||||
*/
|
||||
public int getSize() {
|
||||
return outputStream.getSize();
|
||||
}//getSize()//
|
||||
/**
|
||||
* Gets the socket associated with this stream.
|
||||
* @return The socket associated with the stream.
|
||||
*/
|
||||
public AbstractConnection getSocket() {
|
||||
return socket;
|
||||
}//getSocket()//
|
||||
/**
|
||||
* @see IOutputStream.isEncrypting()
|
||||
*/
|
||||
public boolean isEncrypting() {
|
||||
return outputStream.isEncrypting();
|
||||
}//isEncrypting()//
|
||||
/**
|
||||
* Resets the stream for reuse.
|
||||
*/
|
||||
public void reset() throws IOException {
|
||||
outputStream.reset();
|
||||
internalReset();
|
||||
}//reset()//
|
||||
/**
|
||||
* Writes the contents of this stream to the given output stream.
|
||||
* @param out The output stream where the data will be written to.
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
outputStream.writeTo(out);
|
||||
}//writeTo()//
|
||||
}//OrbObjectOutputStream//
|
||||
306
Orb/src/com/de22/orb/optional/CommonOrbWrapper.java
Normal file
306
Orb/src/com/de22/orb/optional/CommonOrbWrapper.java
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (c) 2005,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.optional;
|
||||
|
||||
import com.common.event.ObjectHandler1;
|
||||
import com.common.orb.IResultCallback;
|
||||
import com.common.util.*;
|
||||
import com.de22.orb.*;
|
||||
|
||||
public class CommonOrbWrapper implements com.common.orb.IOrbWrapper {
|
||||
private Orb orb = null;
|
||||
|
||||
/**
|
||||
* Listens for a proxy to become invalid and notifies the proper listener in the application.
|
||||
*/
|
||||
private static class ProxyInvalidListener implements IProxyInvalidListener {
|
||||
com.common.orb.IInvalidProxyListener invalidProxyListener = null;
|
||||
|
||||
private ProxyInvalidListener(com.common.orb.IInvalidProxyListener invalidProxyListener) {
|
||||
this.invalidProxyListener = invalidProxyListener;
|
||||
}//ProxyInvalidListener()//
|
||||
public void onProxyInvalid(Proxy proxy) {
|
||||
invalidProxyListener.evaluate(proxy);
|
||||
}//onProxyInvalid()//
|
||||
public int hashCode() {
|
||||
return invalidProxyListener.hashCode();
|
||||
}//hashCode()//
|
||||
public boolean equals(Object object) {
|
||||
return (object instanceof ProxyInvalidListener) ? invalidProxyListener.equals(((ProxyInvalidListener) object).invalidProxyListener) : false;
|
||||
}//equals()//
|
||||
}//ProxyInvalidListener//
|
||||
/**
|
||||
* CommonOrbWrapper constructor.
|
||||
* @param classLoader An optional class loader provided to the orb. This is most often an instance of <code>com.de22.orb.development.OrbClassLoader</code>
|
||||
* @param instanceFactory An optional factory to allow the application control over how classes are instantiated.
|
||||
* @param classTracker An optional object that allows the application notification of which classes are being used by the orb.
|
||||
* @see com.de22.orb.development.OrbClassLoader
|
||||
*/
|
||||
public CommonOrbWrapper(ClassLoader classLoader, com.common.io.IInstanceFactory instanceFactory, com.common.io.IClassTracker classTracker) {
|
||||
super();
|
||||
|
||||
orb = new Orb(classLoader, instanceFactory, classTracker, null, null, null);
|
||||
}//CommonOrbWrapper()//
|
||||
/**
|
||||
* CommonOrbWrapper constructor.
|
||||
* @param classLoader An optional class loader provided to the orb. This is most often an instance of <code>com.de22.orb.development.OrbClassLoader</code>
|
||||
* @param instanceFactory An optional factory to allow the application control over how classes are instantiated.
|
||||
* @param classTracker An optional object that allows the application notification of which classes are being used by the orb.
|
||||
* @param nioEngine The optional NIO Engine instance to be used by all connections that are not otherwise provided an NIO Engine via their options. If this is null and the options don't provide an NIO Engine then a thread per socket will be used.
|
||||
* @param proxyInterfaceLoader The optional object used to load proxy classes from the proxy'd interface or object.
|
||||
* @see com.de22.orb.development.OrbClassLoader
|
||||
*/
|
||||
public CommonOrbWrapper(ClassLoader classLoader, com.common.io.IInstanceFactory instanceFactory, com.common.io.IClassTracker classTracker, NioEngine nioEngine, IProxyInterfaceLoader proxyInterfaceLoader) {
|
||||
super();
|
||||
|
||||
orb = new Orb(classLoader, instanceFactory, classTracker, nioEngine, proxyInterfaceLoader, null);
|
||||
}//CommonOrbWrapper()//
|
||||
/**
|
||||
* CommonOrbWrapper constructor.
|
||||
* @param classLoader An optional class loader provided to the orb. This is most often an instance of <code>com.de22.orb.development.OrbClassLoader</code>
|
||||
* @param instanceFactory An optional factory to allow the application control over how classes are instantiated.
|
||||
* @param classTracker An optional object that allows the application notification of which classes are being used by the orb.
|
||||
* @param nioEngine The optional NIO Engine instance to be used by all connections that are not otherwise provided an NIO Engine via their options. If this is null and the options don't provide an NIO Engine then a thread per socket will be used.
|
||||
* @param proxyInterfaceLoader The optional object used to load proxy classes from the proxy'd interface or object.
|
||||
* @param reconnectListener The optional listener called when a socket attempts to reconnect. The listener is given some feedback and control over the process.
|
||||
* @see com.de22.orb.development.OrbClassLoader
|
||||
*/
|
||||
public CommonOrbWrapper(ClassLoader classLoader, com.common.io.IInstanceFactory instanceFactory, com.common.io.IClassTracker classTracker, NioEngine nioEngine, IProxyInterfaceLoader proxyInterfaceLoader, IReconnectListener reconnectListener) {
|
||||
super();
|
||||
|
||||
orb = new Orb(classLoader, instanceFactory, classTracker, nioEngine, proxyInterfaceLoader, reconnectListener);
|
||||
}//CommonOrbWrapper()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#bind(java.lang.Object, java.lang.Object, com.common.util.LiteHashSet)
|
||||
*/
|
||||
public void bind(Object object, Object resource, LiteHashSet permissions) {
|
||||
orb.bind(object, resource, permissions);
|
||||
}//bind()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#checkExactEquality(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public boolean checkExactEquality(Object object1, Object object2) {
|
||||
if(object1 instanceof com.common.comparison.IComparable) {
|
||||
return ((com.common.comparison.IComparable) object1).equalsEquals(object2);
|
||||
}//if//
|
||||
else if(object2 instanceof com.common.comparison.IComparable) {
|
||||
return ((com.common.comparison.IComparable) object2).equalsEquals(object1);
|
||||
}//else if//
|
||||
else if(isProxy(object1)) {
|
||||
return ((Proxy) object1).equalsEquals(object2);
|
||||
}//else if//
|
||||
else if(isProxy(object2)) {
|
||||
return ((Proxy) object2).equalsEquals(object1);
|
||||
}//else if//
|
||||
else {
|
||||
return object1 == object2;
|
||||
}//else//
|
||||
}//checkExactEquality()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#closeServerSocket(java.lang.Object)
|
||||
*/
|
||||
public void closeServerSocket(Object serverSocketIdentifier) throws java.io.IOException {
|
||||
orb.closeServerSocket(serverSocketIdentifier);
|
||||
}//closeServerSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#closeSocket(java.lang.Object)
|
||||
*/
|
||||
public void closeSocket(Object socketIdentifier) throws java.io.IOException {
|
||||
orb.closeSocket(socketIdentifier);
|
||||
}//closeSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#closeSocket(java.lang.Object, long)
|
||||
*/
|
||||
public void closeSocket(Object socketIdentifier, long delayTime) throws java.io.IOException {
|
||||
orb.closeSocket(socketIdentifier, delayTime);
|
||||
}//closeSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#closeSocket(java.lang.String)
|
||||
*/
|
||||
public void closeSocket(String socketName) throws java.io.IOException {
|
||||
orb.closeSocket(socketName);
|
||||
}//closeSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#closeSocket(java.lang.String, long)
|
||||
*/
|
||||
public void closeSocket(String socketName, long delayTime) throws java.io.IOException {
|
||||
orb.closeSocket(socketName, delayTime);
|
||||
}//closeSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#getConnectionIdentifier(java.lang.Object)
|
||||
*/
|
||||
public Object getConnectionIdentifier(Object proxy) throws IllegalArgumentException {
|
||||
Object result = null;
|
||||
|
||||
if((isProxy(proxy)) && (!isLocal(proxy))) {
|
||||
result = ((Proxy) proxy).getNetworkConnectionIdentifier__Proxy();
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getConnectionIdentifier()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#getLocal(java.lang.Object)
|
||||
*/
|
||||
public Object getLocal(Object object) {
|
||||
return object instanceof Proxy ? ((Proxy) object).getIsProxyLocal__Proxy() ? ((Proxy) object).getLocalObject__Proxy() : null : object;
|
||||
}//getLocal()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#getNonProxyClass(java.lang.Object)
|
||||
*/
|
||||
public Class getNonProxyClass(Object object) {
|
||||
return object instanceof Proxy ? ((Proxy) object).getProxiedClass__Proxy() : object.getClass();
|
||||
}//getNonProxyClass()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#getNonProxyClassName(java.lang.Object)
|
||||
*/
|
||||
public String getNonProxyClassName(Object object) {
|
||||
return object instanceof Proxy ? ((Proxy) object).getProxiedClassName__Proxy() : object.getClass().getName();
|
||||
}//getNonProxyClassName()//
|
||||
/**
|
||||
* Gets the underlying orb reference.
|
||||
* @return The orb that is being wrappered.
|
||||
*/
|
||||
public Orb getOrb() {
|
||||
return orb;
|
||||
}//getOrb()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#getProxy(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
public Object getProxy(Object object, Class type) throws IllegalArgumentException {
|
||||
//Convert default proxy into a generic proxy. I am assuming I will create a getDefaultProxy(Object) method if I want to allow default proxy interface detection. Currently this detection is not possible only because of the orb interface in the Common project.//
|
||||
if(type == null) {
|
||||
type = Proxy.class;
|
||||
}//if//
|
||||
|
||||
return object == null ? null : orb.getProxy(object, type);
|
||||
}//getProxy()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#isInvalidProxyException(java.lang.Throwable)
|
||||
*/
|
||||
public boolean isInvalidProxyException(Throwable exception) {
|
||||
return exception instanceof com.de22.orb.exception.InvalidProxyException;
|
||||
}//isInvalidProxyException()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#isLocal(java.lang.Object)
|
||||
*/
|
||||
public boolean isLocal(Object object) {
|
||||
return object instanceof Proxy ? ((Proxy) object).getIsProxyLocal__Proxy() : true;
|
||||
}//isLocal()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#isProxy(java.lang.Object)
|
||||
*/
|
||||
public boolean isProxy(Object object) {
|
||||
return object instanceof Proxy;
|
||||
}//isProxy()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#isProxyValid(java.lang.Object)
|
||||
*/
|
||||
public boolean isProxyValid(Object object) {
|
||||
return (object != null) && (object instanceof Proxy) ? ((Proxy) object).getIsProxyValid__Proxy() : object != null;
|
||||
}//isProxy()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#isTimeoutException(java.lang.Throwable)
|
||||
*/
|
||||
public boolean isTimeoutException(Throwable exception) {
|
||||
return exception instanceof com.de22.orb.exception.TimeoutException;
|
||||
}//isTimeoutException()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#lookup(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public Object lookup(Object resource, Object socketId) {
|
||||
return orb.lookup(resource, socketId);
|
||||
}//lookup()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#openServerSocket(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public Object openServerSocket(String socketName, Object serverSocketOptions) throws java.io.IOException {
|
||||
if(!(serverSocketOptions instanceof IServerSocketOptions)) {
|
||||
throw new IllegalArgumentException("Expecting an instance of: " + IServerSocketOptions.class.getName());
|
||||
}//if//
|
||||
|
||||
return orb.openServerSocket(socketName, (IServerSocketOptions) serverSocketOptions);
|
||||
}//openServerSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#openSocket(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public Object openSocket(String socketName, Object socketOptions) throws java.io.IOException {
|
||||
if(!(socketOptions instanceof ISocketOptions)) {
|
||||
throw new IllegalArgumentException("Expecting an instance of: " + ISocketOptions.class.getName());
|
||||
}//if//
|
||||
|
||||
return orb.openSocket(socketName, (ISocketOptions) socketOptions);
|
||||
}//openSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#registerInvalidProxyListener(java.lang.Object, com.common.orb.IInvalidProxyListener)
|
||||
*/
|
||||
public void registerInvalidProxyListener(Object proxy, com.common.orb.IInvalidProxyListener invalidProxyListener) {
|
||||
if((proxy != null) && (proxy instanceof Proxy)) {
|
||||
((Proxy) proxy).addProxyInvalidListener(new ProxyInvalidListener(invalidProxyListener));
|
||||
}//if//
|
||||
}//registerInvalidProxyListener()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#sendAgent(java.lang.Object, java.lang.Object, boolean, long, com.common.orb.IResultCallback)
|
||||
*/
|
||||
public Object sendAgent(Object agent, Object connection, boolean isOneWay, long timeout, IResultCallback callback) {
|
||||
return orb.sendAgent(agent, connection, isOneWay, timeout, callback == null ? null : new ResultCallbackWrapper(callback));
|
||||
}//closeSocket()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#setAutoProxy(java.lang.Object, java.lang.Class)
|
||||
*/
|
||||
public void setAutoProxy(Object object, Class interfaceType) {
|
||||
if((object != null) && (object instanceof Proxy) && !((Proxy) object).getIsProxyLocal__Proxy()) {
|
||||
((Proxy) object).setAutoProxy__Proxy(interfaceType);
|
||||
}//if//
|
||||
}//setAutoProxy()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#setAutoMorph(java.lang.Object, java.lang.Class, com.common.event.ObjectHandler1)
|
||||
*/
|
||||
public void setAutoMorph(Object object, Class interfaceType, ObjectHandler1 handler) {
|
||||
if((object != null) && (object instanceof Proxy) && !((Proxy) object).getIsProxyLocal__Proxy()) {
|
||||
((Proxy) object).setAutoMorph__Proxy(interfaceType, handler);
|
||||
}//if//
|
||||
}//setAutoMorph()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#setCallTimeout(java.lang.Object, long)
|
||||
*/
|
||||
public void setCallTimeout(Object object, long timeout) {
|
||||
if((object != null) && (object instanceof Proxy)) {
|
||||
((Proxy) object).setTimeout__Proxy(timeout);
|
||||
}//if//
|
||||
}//setCallTimeout()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#setOneWayCall(java.lang.Object)
|
||||
*/
|
||||
public void setOneWayCall(Object object) {
|
||||
if((object != null) && (object instanceof Proxy)) {
|
||||
((Proxy) object).setIsOneWay__Proxy(true);
|
||||
}//if//
|
||||
}//setOneWayCall()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#setResultCallback(java.lang.Object, com.common.orb.IResultCallback)
|
||||
*/
|
||||
public void setResultCallback(Object object, IResultCallback callback) {
|
||||
if((object != null) && (object instanceof Proxy) && (callback != null)) {
|
||||
((Proxy) object).setResultCallback__Proxy(new ResultCallbackWrapper(callback));
|
||||
}//if//
|
||||
}//setResultCallback()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#unregisterInvalidProxyListener(java.lang.Object, com.common.orb.IInvalidProxyListener)
|
||||
*/
|
||||
public void unregisterInvalidProxyListener(Object proxy, com.common.orb.IInvalidProxyListener invalidProxyListener) {
|
||||
if((proxy != null) && (proxy instanceof Proxy)) {
|
||||
((Proxy) proxy).removeProxyInvalidListener(new ProxyInvalidListener(invalidProxyListener));
|
||||
}//if//
|
||||
}//unregisterInvalidProxyListener()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.common.orb.IOrbWrapper#shutdown()
|
||||
*/
|
||||
public void shutdown() {
|
||||
orb.shutdown();
|
||||
}//shutdown()//
|
||||
}//CommonOrbWrapper//
|
||||
28
Orb/src/com/de22/orb/optional/ResultCallbackWrapper.java
Normal file
28
Orb/src/com/de22/orb/optional/ResultCallbackWrapper.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2004,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.optional;
|
||||
|
||||
/*
|
||||
* Simply wrappers the orb wrapper's callback interface with an object that implements this orb's callback interface.
|
||||
*/
|
||||
public class ResultCallbackWrapper implements com.de22.orb.IResultCallback {
|
||||
private com.common.orb.IResultCallback callback = null;
|
||||
/**
|
||||
* ResultCallbackWrapper constructor.
|
||||
*/
|
||||
public ResultCallbackWrapper(com.common.orb.IResultCallback callback) {
|
||||
super();
|
||||
this.callback = callback;
|
||||
}//ResultCallbackWrapper()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IResultCallback#run(java.lang.Object)
|
||||
*/
|
||||
public void run(Object result) {
|
||||
callback.run(result);
|
||||
}//run()//
|
||||
}//ResultCallbackWrapper//
|
||||
176
Orb/src/com/de22/orb/optional/ServerSocketOptions.java
Normal file
176
Orb/src/com/de22/orb/optional/ServerSocketOptions.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.optional;
|
||||
|
||||
import com.de22.orb.*;
|
||||
import com.de22.orb.security.AbstractSecurityProvider;
|
||||
|
||||
/**
|
||||
* A basic implementation of the IServerSocketOptions interface. Most applications can use this implementation.
|
||||
* <p>It should be noted that the sign(..) method should be overloaded for applications requiring authentication of the server.</p>
|
||||
*/
|
||||
public class ServerSocketOptions implements IServerSocketOptions {
|
||||
public static final Integer DEFAULT_BACKLOG = new Integer(50);
|
||||
public static final long DEFAULT_AUTO_RECONNECT_TIME_LIMIT = 180000; //3 minutes.//
|
||||
public static final long DEFAULT_KEEP_ALIVE_INTERVAL = 60000; //1 minute.//
|
||||
|
||||
private Address address = null;
|
||||
private Address externalAddress = null;
|
||||
private Integer backlog = DEFAULT_BACKLOG;
|
||||
private ISocketOptions socketOptions = null;
|
||||
private long autoReconnectTimeLimit = DEFAULT_AUTO_RECONNECT_TIME_LIMIT;
|
||||
private long keepAliveInterval = DEFAULT_KEEP_ALIVE_INTERVAL;
|
||||
private AbstractSecurityProvider securityProvider = null;
|
||||
/** The optional NIO Engine. If provided then the server socket will utilize the NIO Engine to handle all threading. */
|
||||
private NioEngine nioEngine = null;
|
||||
/** The download URI's passed to the client when is has the wrong version of either the orb protocol or the application protocol (not used for custom app version management). */
|
||||
private String[] downloadUris = null;
|
||||
/**
|
||||
* ServerSocketOptions constructor.
|
||||
* @param address The address the server socket will listen to.
|
||||
* @param externalAddress If the external address is not the same as the one being bound to (for example when using NAT) then this would be the external address that the client might see.
|
||||
* @param socketOptions The socket options that will define the accepted sockets.
|
||||
* @deprecated
|
||||
*/
|
||||
public ServerSocketOptions(Address address, Address externalAddress, ISocketOptions socketOptions) {
|
||||
this(address, externalAddress, socketOptions, null);
|
||||
}//ServerSocketOptions()//
|
||||
/**
|
||||
* ServerSocketOptions constructor.
|
||||
* @param address The address the server socket will listen to.
|
||||
* @param externalAddress If the external address is not the same as the one being bound to (for example when using NAT) then this would be the external address that the client might see.
|
||||
* @param socketOptions The socket options that will define the accepted sockets.
|
||||
* @param nioEngine The optional NIO Engine. This must be provided if the server socket will use an NIO selector.
|
||||
*/
|
||||
public ServerSocketOptions(Address address, Address externalAddress, ISocketOptions socketOptions, NioEngine nioEngine) {
|
||||
super();
|
||||
|
||||
if((address == null) || (address.getPort() == Address.INVALID_PORT)) {
|
||||
throw new RuntimeException("Invalid address.");
|
||||
}//if//
|
||||
|
||||
if(socketOptions == null) {
|
||||
throw new RuntimeException("Invalid socket options.");
|
||||
}//if//
|
||||
|
||||
this.address = address;
|
||||
this.externalAddress = externalAddress;
|
||||
//Note: We don't need to clone this since the options cannot be changed once created.//
|
||||
this.socketOptions = socketOptions;
|
||||
this.nioEngine = nioEngine;
|
||||
}//ServerSocketOptions()//
|
||||
/**
|
||||
* ServerSocketOptions constructor.
|
||||
* @param address The address the server socket will listen to.
|
||||
* @param externalAddress If the external address is not the same as the one being bound to (for example when using NAT) then this would be the external address that the client might see.
|
||||
* @param socketOptions The socket options that will define the accepted sockets.
|
||||
* @param downloadUris The (optional if upgrading is irrelevant) download URI's passed to the client when is has the wrong version of either the orb protocol or the application protocol (not used for custom app version management).
|
||||
* @param autoReconnectTimeLimit The number of milliseconds the server will wait for the client to reconnect a failed socket. A value less than 1000 will be equivalent to zero and a zero value (default) indicates the server does not allow the client to reconnect automatically.
|
||||
* @param keepAliveInterval The number of milliseconds between keep alive messages. This should be roughly half the auto-reconnect time limit so that the client is notified of a socket error with enough time to reconnect even if the client is inactive. This number should not be less than 500 in which case the default value will be used, and not greater than 600,000 (the longest possible length of time without a message before a socket seems to get closed).
|
||||
* @param securityProvider The security provider that will supply the security system instances for all incomming sockets.
|
||||
* @deprecated
|
||||
*/
|
||||
public ServerSocketOptions(Address address, Address externalAddress, ISocketOptions socketOptions, String[] downloadUris, long autoReconnectTimeLimit, long keepAliveInterval, AbstractSecurityProvider securityProvider) {
|
||||
this(address, externalAddress, socketOptions, null);
|
||||
this.downloadUris = downloadUris;
|
||||
this.autoReconnectTimeLimit = autoReconnectTimeLimit < 1000 ? 0 : autoReconnectTimeLimit;
|
||||
this.securityProvider = securityProvider;
|
||||
this.keepAliveInterval = keepAliveInterval < 500 ? DEFAULT_KEEP_ALIVE_INTERVAL : keepAliveInterval > 600000 ? 600000 : keepAliveInterval;
|
||||
}//ServerSocketOptions()//
|
||||
/**
|
||||
* ServerSocketOptions constructor.
|
||||
* @param address The address the server socket will listen to.
|
||||
* @param externalAddress If the external address is not the same as the one being bound to (for example when using NAT) then this would be the external address that the client might see.
|
||||
* @param socketOptions The socket options that will define the accepted sockets.
|
||||
* @param nioEngine The optional NIO Engine. This must be provided if the server socket will use an NIO selector.
|
||||
* @param downloadUris The (optional if upgrading is irrelevant) download URI's passed to the client when is has the wrong version of either the orb protocol or the application protocol (not used for custom app version management).
|
||||
* @param autoReconnectTimeLimit The number of milliseconds the server will wait for the client to reconnect a failed socket. A value less than 1000 will be equivalent to zero and a zero value (default) indicates the server does not allow the client to reconnect automatically.
|
||||
* @param keepAliveInterval The number of milliseconds between keep alive messages. This should be roughly half the auto-reconnect time limit so that the client is notified of a socket error with enough time to reconnect even if the client is inactive. This number should not be less than 500 in which case the default value will be used, and not greater than 600,000 (the longest possible length of time without a message before a socket seems to get closed).
|
||||
* @param securityProvider The security provider that will supply the security system instances for all incomming sockets.
|
||||
*/
|
||||
public ServerSocketOptions(Address address, Address externalAddress, ISocketOptions socketOptions, NioEngine nioEngine, String[] downloadUris, long autoReconnectTimeLimit, long keepAliveInterval, AbstractSecurityProvider securityProvider) {
|
||||
this(address, externalAddress, socketOptions, nioEngine);
|
||||
this.downloadUris = downloadUris;
|
||||
this.autoReconnectTimeLimit = autoReconnectTimeLimit < 1000 ? 0 : autoReconnectTimeLimit;
|
||||
this.securityProvider = securityProvider;
|
||||
this.keepAliveInterval = keepAliveInterval < 500 ? DEFAULT_KEEP_ALIVE_INTERVAL : keepAliveInterval > 600000 ? 600000 : keepAliveInterval;
|
||||
}//ServerSocketOptions()//
|
||||
/**
|
||||
* Gets the address that the server socket will listen on.
|
||||
* @return The address the orb will find or create a server socket for.
|
||||
*/
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}//getAddress()//
|
||||
/**
|
||||
* Gets the size of the backlog that the server socket will maintain.
|
||||
* @return The server socket's backlog size, or null to use the default value for the server socket.
|
||||
*/
|
||||
public Integer getBacklog() {
|
||||
return backlog;
|
||||
}//getBacklog()//
|
||||
/**
|
||||
* Gets the externally visible address and optional port that clients may reconnect through.
|
||||
* <p>This allows clients to reconnect to the exact same server when the actual server address may be internal (and visible only via NAT or some other networking layer).
|
||||
* Often times a server farm may have multiple servers a client may connect to and the default address for a service will be redirected to one of the identical servers.
|
||||
* This feature allows the client to connect to the exact same server as the last time it connected so that the session information may be reused which will increase overall performance.</p>
|
||||
* @return The address the server socket is visible on externally such that clients can reconnect. This may be null if the address that the server socket opens on is externally visible to clients. The port number may be optionally specified if it differs from the port number the server socket listens on.
|
||||
*/
|
||||
public Address getExternalAddress() {
|
||||
return externalAddress;
|
||||
}//getExternalAddress()//
|
||||
/**
|
||||
* Gets the socket options that all accepted sockets will use.
|
||||
* @return Socket options accepted sockets will adhere to.
|
||||
*/
|
||||
public ISocketOptions getSocketOptions() {
|
||||
return socketOptions;
|
||||
}//getSocketOptions()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#getAutoReconnectTimeLimit()
|
||||
*/
|
||||
public long getAutoReconnectTimeLimit() {
|
||||
return autoReconnectTimeLimit;
|
||||
}//getAutoReconnectTimeLimit()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#getKeepAliveInterval()
|
||||
*/
|
||||
public long getKeepAliveInterval() {
|
||||
return keepAliveInterval;
|
||||
}//getKeepAliveInterval()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#getSecurityProvider()
|
||||
*/
|
||||
public AbstractSecurityProvider getSecurityProvider() {
|
||||
return securityProvider;
|
||||
}//getSecurityProvider()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#getNioEngine()
|
||||
*/
|
||||
public NioEngine getNioEngine() {
|
||||
return nioEngine;
|
||||
}//getNioEngine()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#getDownloadUris()
|
||||
*/
|
||||
public String[] getDownloadUris() {
|
||||
return downloadUris;
|
||||
}//getDownloadUris()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#getSignatureSize(int)
|
||||
*/
|
||||
public int getSignatureSize(int applicationProtocolVersion) {
|
||||
return 0;
|
||||
}//getSignatureSize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.IServerSocketOptions#sign(int, byte[], byte[])
|
||||
*/
|
||||
public byte[] sign(int applicationProtocolVersion, byte[] unsignedBytes, byte[] responseBytes) {
|
||||
return null;
|
||||
}//sign()//
|
||||
}//ServerSocketOptions//
|
||||
348
Orb/src/com/de22/orb/optional/SocketOptions.java
Normal file
348
Orb/src/com/de22/orb/optional/SocketOptions.java
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* Copyright (c) 1999,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.optional;
|
||||
|
||||
import com.common.comparison.Comparator;
|
||||
import com.common.security.IHashAlgorithm;
|
||||
import com.common.security.ISignatureAlgorithm;
|
||||
import com.de22.orb.*;
|
||||
|
||||
/**
|
||||
* A simple implementation of the ISocketOptions interface, useable by most ORB users.
|
||||
* <p>The user may wish to override the implementation of the isValidSignature(..) method.</p>
|
||||
*/
|
||||
public class SocketOptions implements ISocketOptions {
|
||||
/** The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero. */
|
||||
private int applicationProtocolVersion = 1;
|
||||
/** The address's that the socket is connecting on (only one will be selected). (Client Sockets Only) */
|
||||
private Address[] addresses = null;
|
||||
/** The permissions object used to identify the bound objects the remote process can access. (Client Sockets Only) */
|
||||
private Object permissions = null;
|
||||
/** The handler activated if the connected server is incompatible with this process. (Client Sockets Only) */
|
||||
private IVersionChangeHandler versionChangeHandler = null;
|
||||
private IStreamInjector streamInjector = null;
|
||||
private IStreamClassNameManipulator streamClassNameManipulator = null;
|
||||
/** The optional NIO Engine. If provided then the socket will utilize the NIO Engine to handle all threading. */
|
||||
private NioEngine nioEngine = null;
|
||||
/** The optional signature algorithm used to validate the server when a socket connects. */
|
||||
private ISignatureAlgorithm signatureAlgorithm = null;
|
||||
/** The hashAlgorithm used to hash a message for signing. */
|
||||
private IHashAlgorithm hashAlgorithm = null;
|
||||
/** The number of milliseconds to wait before timing out when connecting to the server. */
|
||||
private int socketConnectionTimeout = 8000;
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a server socket options object.</p>
|
||||
* @deprecated Call SocketOptions(int) instead.
|
||||
*/
|
||||
public SocketOptions() {
|
||||
super();
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a server socket options object.</p>
|
||||
* @param applicationProtocolVersion The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
*/
|
||||
public SocketOptions(int applicationProtocolVersion) {
|
||||
super();
|
||||
this.applicationProtocolVersion = applicationProtocolVersion;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a server socket options object.</p>
|
||||
* @param applicationProtocolVersion The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
*/
|
||||
public SocketOptions(int applicationProtocolVersion, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator) {
|
||||
super();
|
||||
this.applicationProtocolVersion = applicationProtocolVersion;
|
||||
this.permissions = permissions;
|
||||
this.streamInjector = streamInjector;
|
||||
this.streamClassNameManipulator = streamClassNameManipulator;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* @param primaryAddress The primary address that the socket should bind to.
|
||||
* @param secondaryAddress The secondary (backup) address that the socket should bind to if the primary address fails.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @deprecated
|
||||
*/
|
||||
public SocketOptions(Address primaryAddress, Address secondaryAddress, Object permissions) {
|
||||
super();
|
||||
|
||||
//Note: The primary address can be null if the socket options are part of the server socket options.//
|
||||
if((primaryAddress != null) && ((primaryAddress.getName() == null) || (primaryAddress.getPort() == Address.INVALID_PORT))) {
|
||||
throw new RuntimeException("Invalid primary address.");
|
||||
}//if//
|
||||
|
||||
if((secondaryAddress != null) && ((secondaryAddress.getName() == null) || (secondaryAddress.getPort() == Address.INVALID_PORT))) {
|
||||
throw new RuntimeException("Invalid secondary address.");
|
||||
}//if//
|
||||
|
||||
try {
|
||||
this.addresses = new Address[secondaryAddress == null ? primaryAddress == null ? 0 : 1 : 2];
|
||||
|
||||
if(primaryAddress != null) {
|
||||
this.addresses[0] = (Address) primaryAddress.clone();
|
||||
|
||||
if(secondaryAddress != null) {
|
||||
this.addresses[1] = (Address) secondaryAddress.clone();
|
||||
}//if//
|
||||
}//if//
|
||||
}//try//
|
||||
catch(CloneNotSupportedException e) {
|
||||
//Ignored.//
|
||||
}//catch//
|
||||
|
||||
this.permissions = permissions;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* @param primaryAddress The primary address that the socket should bind to.
|
||||
* @param secondaryAddress The secondary (backup) address that the socket should bind to if the primary address fails.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
* @deprecated
|
||||
*/
|
||||
public SocketOptions(Address primaryAddress, Address secondaryAddress, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator) {
|
||||
this(primaryAddress, secondaryAddress, permissions);
|
||||
this.streamInjector = streamInjector;
|
||||
this.streamClassNameManipulator = streamClassNameManipulator;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* @param primaryAddress The primary address that the socket should bind to.
|
||||
* @param secondaryAddress The secondary (backup) address that the socket should bind to if the primary address fails.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
* @param versionChangeHandler The optional handler called when the server reports a newer version of the application. This should not be specified via server sockets.
|
||||
* @deprecated
|
||||
*/
|
||||
public SocketOptions(Address primaryAddress, Address secondaryAddress, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator, IVersionChangeHandler versionChangeHandler) {
|
||||
this(primaryAddress, secondaryAddress, permissions, streamInjector, streamClassNameManipulator);
|
||||
this.versionChangeHandler = versionChangeHandler;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* @deprecated
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
*/
|
||||
public SocketOptions(Address[] addresses, Object permissions) {
|
||||
this(1, addresses, permissions);
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* @deprecated
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
*/
|
||||
public SocketOptions(Address[] addresses, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator) {
|
||||
this(1, addresses, permissions);
|
||||
this.streamInjector = streamInjector;
|
||||
this.streamClassNameManipulator = streamClassNameManipulator;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* @deprecated
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
* @param versionChangeHandler The optional handler called when the server reports a newer version of the application. This should not be specified via server sockets.
|
||||
*/
|
||||
public SocketOptions(Address[] addresses, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator, IVersionChangeHandler versionChangeHandler) {
|
||||
this(1, addresses, permissions, streamInjector, streamClassNameManipulator);
|
||||
this.versionChangeHandler = versionChangeHandler;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a client side socket.</p>
|
||||
* @param applicationProtocolVersion The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
*/
|
||||
public SocketOptions(int applicationProtocolVersion, Address[] addresses, Object permissions) {
|
||||
super();
|
||||
|
||||
//Note: The addresses can be null or empty if the options are part of a server socket.//
|
||||
if(addresses != null) {
|
||||
for(int index = 0; index < addresses.length; index++) {
|
||||
if(addresses[index] == null || addresses[index].getName() == null || addresses[index].getPort() == Address.INVALID_PORT) {
|
||||
throw new RuntimeException("Invalid address found in the address set at index: " + index + ".");
|
||||
}//if//
|
||||
}//for//
|
||||
|
||||
//Clone the collection of addresses.//
|
||||
try {
|
||||
this.addresses = new Address[addresses.length];
|
||||
|
||||
for(int index = 0; index < addresses.length; index++) {
|
||||
this.addresses[index] = (Address) addresses[index].clone();
|
||||
}//for//
|
||||
}//try//
|
||||
catch(CloneNotSupportedException e) {
|
||||
}//catch//
|
||||
}//if//
|
||||
|
||||
this.applicationProtocolVersion = applicationProtocolVersion;
|
||||
this.permissions = permissions;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a client side socket.</p>
|
||||
* @param applicationProtocolVersion The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
*/
|
||||
public SocketOptions(int applicationProtocolVersion, Address[] addresses, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator) {
|
||||
this(applicationProtocolVersion, addresses, permissions);
|
||||
this.streamInjector = streamInjector;
|
||||
this.streamClassNameManipulator = streamClassNameManipulator;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a client side socket.</p>
|
||||
* @param applicationProtocolVersion The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
* @param versionChangeHandler The optional handler called when the server reports a newer version of the application. This should not be specified via server sockets.
|
||||
* @param nioEngine The optional NIO Engine. This must be provided if the server socket will use an NIO selector.
|
||||
*/
|
||||
public SocketOptions(int applicationProtocolVersion, Address[] addresses, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator, IVersionChangeHandler versionChangeHandler, NioEngine nioEngine) {
|
||||
this(applicationProtocolVersion, addresses, permissions, streamInjector, streamClassNameManipulator);
|
||||
this.versionChangeHandler = versionChangeHandler;
|
||||
this.nioEngine = nioEngine;
|
||||
}//SocketOptions()//
|
||||
/**
|
||||
* SocketOptions constructor.
|
||||
* <p>This constructor should only be used to create socket options for a client side socket.</p>
|
||||
* @param applicationProtocolVersion The application's protocol version, used to ensure that an older incompatible version of a client/server don't mix. The value should never be zero.
|
||||
* @param addresses The addresses that the socket should try to bind to. An existing socket will be looked for on each address prior to attempting a new connection.
|
||||
* @param permissions The application defined permissions object that can be assigned to the server socket. This can be used to restrict access to named objects (and possibly for other security features in the future).
|
||||
* @param streamInjector The optional injector to use by the application to place application defined streams in the stream stack used by the socket.
|
||||
* @param streamClassNameManipulator The optional manipulator that can change a class name being sent or received over the socket.
|
||||
* @param versionChangeHandler The optional handler called when the server reports a newer version of the application. This should not be specified via server sockets.
|
||||
* @param nioEngine The optional NIO Engine. This must be provided if the server socket will use an NIO selector.
|
||||
* @param socketConnectionTimeout The number of milliseconds to wait before timing out when connecting to the server. The default value is 8000 (8 seconds), and the value should not be less than 500 otherwise the orb will set it to 500.
|
||||
*/
|
||||
public SocketOptions(int applicationProtocolVersion, Address[] addresses, Object permissions, IStreamInjector streamInjector, IStreamClassNameManipulator streamClassNameManipulator, IVersionChangeHandler versionChangeHandler, NioEngine nioEngine, int socketConnectionTimeout) {
|
||||
this(applicationProtocolVersion, addresses, permissions, streamInjector, streamClassNameManipulator, versionChangeHandler, nioEngine);
|
||||
this.socketConnectionTimeout = socketConnectionTimeout;
|
||||
}//SocketOptions()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getSocketConnectionTimeout()
|
||||
*/
|
||||
public int getSocketConnectionTimeout() {
|
||||
return socketConnectionTimeout;
|
||||
}//getSocketConnectionTimeout()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getPermissions()
|
||||
*/
|
||||
public Object getPermissions() {
|
||||
return permissions;
|
||||
}//getPermissions()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getAddresses()
|
||||
*/
|
||||
public Address[] getAddresses() {
|
||||
return addresses;
|
||||
}//getAddresses()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#useTcpNoDelay()
|
||||
*/
|
||||
public boolean useTcpNoDelay() {
|
||||
return false;
|
||||
}//useTcpNoDelay()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getVersionChangeHandler()
|
||||
*/
|
||||
public IVersionChangeHandler getVersionChangeHandler() {
|
||||
return versionChangeHandler;
|
||||
}//getVersionChangeHandler()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getStreamInjector()
|
||||
*/
|
||||
public IStreamInjector getStreamInjector() {
|
||||
return streamInjector;
|
||||
}//getStreamInjector()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getStreamClassNameManipulator()
|
||||
*/
|
||||
public IStreamClassNameManipulator getStreamClassNameManipulator() {
|
||||
return streamClassNameManipulator;
|
||||
}//getStreamClassNameManipulator()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getApplicationProtocolVersion()
|
||||
*/
|
||||
public int getApplicationProtocolVersion() {
|
||||
return applicationProtocolVersion;
|
||||
}//getApplicationProtocolVersion()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getNioEngine()
|
||||
*/
|
||||
public NioEngine getNioEngine() {
|
||||
return nioEngine;
|
||||
}//getNioEngine()//
|
||||
/**
|
||||
* Initializes the server authentication routines.
|
||||
* @param hashAlgorithm The algorithm used to hash messages received from the server to authenticate them.
|
||||
* @param signatureAlgorithm The signature algorithm (initialized with public key only) used to verify the signature sent by the server.
|
||||
*/
|
||||
public void initializeServerAuthentication(IHashAlgorithm hashAlgorithm, ISignatureAlgorithm signatureAlgorithm) {
|
||||
this.hashAlgorithm = hashAlgorithm;
|
||||
this.signatureAlgorithm = signatureAlgorithm;
|
||||
}//initializeServerAuthentication()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getSignatureSize()
|
||||
*/
|
||||
public int getSignatureSize() {
|
||||
return signatureAlgorithm != null && hashAlgorithm != null ? signatureAlgorithm.getSignedSize(hashAlgorithm.getHashSize()) : 0;
|
||||
}//getSignatureSize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.ISocketOptions#getHashAlgorithm()
|
||||
*/
|
||||
public IHashAlgorithm getHashAlgorithm() {
|
||||
return hashAlgorithm;
|
||||
}//getHashAlgorithm()//
|
||||
/**
|
||||
* Determines whether the server's signature is valid, authenticating that the server is who it says it is.
|
||||
* This method assumes that the client is valid and has a valid public key.
|
||||
* The default implementation performs no validation.
|
||||
* @param data The data sent to the server.
|
||||
* @param signedData The signed data.
|
||||
* @return Whether the signed data matches the data.
|
||||
*/
|
||||
public boolean isValidSignature(byte[] data, byte[] signedData) {
|
||||
boolean result = true;
|
||||
|
||||
if(signatureAlgorithm != null && hashAlgorithm != null) {
|
||||
byte[] unsignedData = signatureAlgorithm.verify(signedData);
|
||||
|
||||
result = unsignedData.length == data.length;
|
||||
|
||||
for(int index = 0; result && index < data.length; index++) {
|
||||
if(data[index] != unsignedData[index]) {
|
||||
result = false;
|
||||
}//if//
|
||||
}//for//
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//isValidSignature()//
|
||||
}//SocketOptions//
|
||||
31
Orb/src/com/de22/orb/security/AbstractSecurityProvider.java
Normal file
31
Orb/src/com/de22/orb/security/AbstractSecurityProvider.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.security;
|
||||
|
||||
public abstract class AbstractSecurityProvider {
|
||||
/**
|
||||
* AbstractSecurityProvider constructor.
|
||||
*/
|
||||
public AbstractSecurityProvider() {
|
||||
}//AbstractSecurityProvider()//
|
||||
/**
|
||||
* Creates a security system instance.
|
||||
* @return The system that will manage security for a connection.
|
||||
*/
|
||||
public abstract AbstractSecuritySystem createSecuritySystem() throws Exception;
|
||||
/**
|
||||
* Gets the client class name for this security system.
|
||||
* @return The qualified class name for the client side security system. The class name will be used on the client to try to instantiate the system.
|
||||
*/
|
||||
public abstract String getSecuritySystemClientClassName();
|
||||
/**
|
||||
* Gets the metadata required to setup the client side security system.
|
||||
* @return The security system specific metadata required by the client to setup the security system object.
|
||||
*/
|
||||
public abstract byte[] getSecuritySystemClientMetadata();
|
||||
}//AbstractSecurityProvider//
|
||||
93
Orb/src/com/de22/orb/security/AbstractSecuritySystem.java
Normal file
93
Orb/src/com/de22/orb/security/AbstractSecuritySystem.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.security;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class AbstractSecuritySystem {
|
||||
public static final int INIT_REQUIRES_SEND = 0;
|
||||
public static final int INIT_REQUIRES_RECEIVE = 1;
|
||||
public static final int INIT_FINISHED = 2;
|
||||
public static final int INIT_ERROR = 3;
|
||||
public static final int INIT_OK = 4;
|
||||
/**
|
||||
* AbstractSecuritySystem constructor.
|
||||
*/
|
||||
public AbstractSecuritySystem() {
|
||||
}//AbstractSecuritySystem()//
|
||||
/**
|
||||
* Initializes the security system with the metadata provided by the security provider on the server.
|
||||
* @param metadata The metadata sent by the server and used to setup the client security system.
|
||||
*/
|
||||
public abstract void initialize(byte[] metadata) throws Exception;
|
||||
/**
|
||||
* Resets the security system after the connection fails.
|
||||
*/
|
||||
public abstract void reset() throws Exception;
|
||||
/**
|
||||
* Determines whether the security system requires more initialization.
|
||||
* @return Whether the system is still initializing.
|
||||
*/
|
||||
public abstract boolean isInitializing();
|
||||
/**
|
||||
* Determines whether the security system has sent the first initialization message.
|
||||
* @return Whether the system has already sent an initialization message. This is useful to determine if the client should be sending the kickoff message versus reading the response and sending the next round.
|
||||
*/
|
||||
public abstract boolean hasSentFirstInitializeMessage();
|
||||
/**
|
||||
* Gets the size of an encrypted chunk of data.
|
||||
* @return The maximum size of one chunk of encrypted data.
|
||||
*/
|
||||
public abstract int getEncryptedChunkSize();
|
||||
/**
|
||||
* Gets the size of a decrypted chunk of data.
|
||||
* @return The maximum size of one chunk of decrypted (or yet to be encrypted) data.
|
||||
*/
|
||||
public abstract int getDecryptedChunkSize();
|
||||
/**
|
||||
* Determines whether the security system has any pending tasks that must be run.
|
||||
* @return Whether there is a task pending.
|
||||
*/
|
||||
public abstract boolean hasPendingTask();
|
||||
/**
|
||||
* Gets the next pending task.
|
||||
* @return The next task needing to be run, or null if there isn't another task.
|
||||
*/
|
||||
public abstract Runnable getPendingTask();
|
||||
/**
|
||||
* Asks the system to send the next initialization message.
|
||||
* @param encryptedBuffer The buffer containing encrypted data.
|
||||
* @param decryptedBuffer The buffer containing decrypted or pre-encrypted data.
|
||||
* @return One of the INIT_ identifiers.
|
||||
*/
|
||||
public abstract int sendInitializationMessage(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer);
|
||||
/**
|
||||
* Receives an initialization message.
|
||||
* @param encryptedBuffer The buffer containing encrypted data.
|
||||
* @param decryptedBuffer The buffer containing decrypted or pre-encrypted data.
|
||||
* @return One of the INIT_ identifiers.
|
||||
*/
|
||||
public abstract int receiveInitializationMessage(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer);
|
||||
/**
|
||||
* Gets the current initialization status.
|
||||
* @return One of the INIT_ identifiers.
|
||||
*/
|
||||
public abstract int getInitializationStatus();
|
||||
/**
|
||||
* Encrypts the data in the decrypted buffer and places it in the encrypted buffer.
|
||||
* @param encryptedBuffer The buffer containing encrypted data.
|
||||
* @param decryptedBuffer The buffer containing decrypted or pre-encrypted data.
|
||||
*/
|
||||
public abstract void encryptData(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer);
|
||||
/**
|
||||
* Decrypts the data in the encrypted buffer and places it in the decrypted buffer.
|
||||
* @param encryptedBuffer The buffer containing encrypted data.
|
||||
* @param decryptedBuffer The buffer containing decrypted or pre-encrypted data.
|
||||
*/
|
||||
public abstract void decryptData(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer);
|
||||
}//AbstractSecuritySystem//
|
||||
86
Orb/src/com/de22/orb/security/SslSecurityProvider.java
Normal file
86
Orb/src/com/de22/orb/security/SslSecurityProvider.java
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2009 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.security;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
import com.common.io.StreamSupport;
|
||||
|
||||
public class SslSecurityProvider extends AbstractSecurityProvider {
|
||||
/** The SSL context used to create an SSL connection. */
|
||||
private SSLContext sslContext;
|
||||
/**
|
||||
* SslSecurityProvider constructor.
|
||||
* @param protocol The desired SSL protocol (TLS, SSLv3).
|
||||
* @param keyStorePath The path to the keystore file.
|
||||
* @param keyStorePassword The password used to read the keystore file.
|
||||
* @param keyPassword The password used to read the material for key generation.
|
||||
*/
|
||||
public SslSecurityProvider(String protocol, String keyStorePath, String keyStorePassword, String keyPassword) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
|
||||
KeyStore keyStore = KeyStore.getInstance("JKS");
|
||||
KeyManagerFactory keyManagerFactory;
|
||||
|
||||
keyStore.load(new ByteArrayInputStream(StreamSupport.readBytes(new File(keyStorePath))), keyStorePassword.toCharArray());
|
||||
keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
|
||||
keyManagerFactory.init(keyStore, keyPassword.toCharArray());
|
||||
sslContext = SSLContext.getInstance(protocol);
|
||||
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
|
||||
}//SslSecurityProvider()//
|
||||
/**
|
||||
* SslSecurityProvider constructor.
|
||||
* @param protocol The desired SSL protocol (TLS, SSLv3).
|
||||
* @param keyStore The keystore to use for the SSL connections.
|
||||
* @param keyPassword The password used to read the material for key generation.
|
||||
*/
|
||||
public SslSecurityProvider(String protocol, KeyStore keyStore, String keyPassword) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
|
||||
KeyManagerFactory keyManagerFactory;
|
||||
|
||||
keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
|
||||
keyManagerFactory.init(keyStore, keyPassword.toCharArray());
|
||||
sslContext = SSLContext.getInstance(protocol);
|
||||
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
|
||||
}//SslSecurityProvider()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecurityProvider#createSecuritySystem()
|
||||
*/
|
||||
public AbstractSecuritySystem createSecuritySystem() throws Exception {
|
||||
return new SslSecuritySystem(sslContext);
|
||||
}//createSecuritySystem()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecurityProvider#getSecuritySystemClientClassName()
|
||||
*/
|
||||
public String getSecuritySystemClientClassName() {
|
||||
return SslSecuritySystem.class.getName();
|
||||
}//getSecuritySystemClientClassName()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecurityProvider#getSecuritySystemClientMetadata()
|
||||
*/
|
||||
public byte[] getSecuritySystemClientMetadata() {
|
||||
try {
|
||||
return sslContext.getProtocol().getBytes("UTF8");
|
||||
}//try//
|
||||
catch(Throwable e) {
|
||||
//Should never occur.//
|
||||
Debug.log(e);
|
||||
return null;
|
||||
}//catch//
|
||||
}//getSecuritySystemClientMetadata()//
|
||||
}//SslSecurityProvider()//
|
||||
193
Orb/src/com/de22/orb/security/SslSecuritySystem.java
Normal file
193
Orb/src/com/de22/orb/security/SslSecuritySystem.java
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2008 Declarative Engineering LLC.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Declarative Engineering LLC
|
||||
* verson 1 which accompanies this distribution, and is available at
|
||||
* http://declarativeengineering.com/legal/DE_Developer_License_v1.txt
|
||||
*/
|
||||
package com.de22.orb.security;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
||||
|
||||
import com.common.debug.Debug;
|
||||
|
||||
/*
|
||||
* A Java SSL based security system.
|
||||
*/
|
||||
public class SslSecuritySystem extends AbstractSecuritySystem {
|
||||
/** The engine that makes the SSL stuff happen. */
|
||||
private SSLEngine engine = null;
|
||||
/** The next task that needs to be run. */
|
||||
private Runnable nextTask = null;
|
||||
/** Whether the first initialization message has already been sent. */
|
||||
private boolean hasSentFirstInitializationMessage = false;
|
||||
/**
|
||||
* SslSecuritySystem constructor.
|
||||
*/
|
||||
public SslSecuritySystem() {
|
||||
}//SslSecuritySystem()//
|
||||
/**
|
||||
* SslSecuritySystem constructor.
|
||||
*/
|
||||
public SslSecuritySystem(SSLContext context) throws Exception {
|
||||
engine = context.createSSLEngine();
|
||||
engine.setUseClientMode(false);
|
||||
engine.setWantClientAuth(false);
|
||||
engine.setNeedClientAuth(false);
|
||||
engine.beginHandshake();
|
||||
hasSentFirstInitializationMessage = false;
|
||||
}//SslSecuritySystem()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#initialize(java.lang.Object)
|
||||
*/
|
||||
public void initialize(byte[] metadata) throws Exception {
|
||||
SSLContext sslContext = SSLContext.getInstance(metadata != null ? new String(metadata, "UTF8") : "TLS");
|
||||
|
||||
sslContext.init(null, new X509TrustManager[] {new X509TrustManager() {
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
}}, null);
|
||||
engine = sslContext.createSSLEngine();
|
||||
engine.setUseClientMode(true);
|
||||
engine.setWantClientAuth(false);
|
||||
engine.setNeedClientAuth(false);
|
||||
engine.beginHandshake();
|
||||
hasSentFirstInitializationMessage = false;
|
||||
}//initialize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#reset()
|
||||
*/
|
||||
public void reset() throws Exception {
|
||||
engine.beginHandshake();
|
||||
}//reset()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#getDecryptedChunkSize()
|
||||
*/
|
||||
public int getDecryptedChunkSize() {
|
||||
return engine.getSession().getApplicationBufferSize();
|
||||
}//getDecryptedChunkSize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#getEncryptedChunkSize()
|
||||
*/
|
||||
public int getEncryptedChunkSize() {
|
||||
return engine.getSession().getPacketBufferSize();
|
||||
}//getEncryptedChunkSize()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#hasPendingTask()
|
||||
*/
|
||||
public boolean hasPendingTask() {
|
||||
if(nextTask == null) {
|
||||
nextTask = engine.getDelegatedTask();
|
||||
}//if//
|
||||
|
||||
return nextTask != null;
|
||||
}//hasPendingTask()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#getPendingTask()
|
||||
*/
|
||||
public Runnable getPendingTask() {
|
||||
Runnable result = nextTask;
|
||||
|
||||
nextTask = null;
|
||||
|
||||
if(result == null) {
|
||||
result = engine.getDelegatedTask();
|
||||
}//if//
|
||||
|
||||
return result;
|
||||
}//getPendingTask()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#isInitializing()
|
||||
*/
|
||||
public boolean isInitializing() {
|
||||
return engine.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
|
||||
}//isInitializing()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#hasSentFirstInitializeMessage()
|
||||
*/
|
||||
public boolean hasSentFirstInitializeMessage() {
|
||||
return hasSentFirstInitializationMessage;
|
||||
}//hasSentFirstInitializeMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#decryptData(java.nio.ByteBuffer, java.nio.ByteBuffer)
|
||||
*/
|
||||
public void decryptData(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer) {
|
||||
SSLEngineResult result;
|
||||
|
||||
try {
|
||||
result = engine.unwrap(encryptedBuffer, decryptedBuffer);
|
||||
}//try//
|
||||
catch(SSLException e) {
|
||||
Debug.log(e);
|
||||
throw new RuntimeException();
|
||||
}//catch//
|
||||
}//decryptData()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#encryptData(java.nio.ByteBuffer, java.nio.ByteBuffer)
|
||||
*/
|
||||
public void encryptData(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer) {
|
||||
SSLEngineResult result;
|
||||
|
||||
try {
|
||||
result = engine.wrap(decryptedBuffer, encryptedBuffer);
|
||||
}//try//
|
||||
catch(SSLException e) {
|
||||
Debug.log(e);
|
||||
throw new RuntimeException();
|
||||
}//catch//
|
||||
}//encryptData()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#receiveInitializationMessage(java.nio.ByteBuffer, java.nio.ByteBuffer)
|
||||
*/
|
||||
public int receiveInitializationMessage(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer) {
|
||||
SSLEngineResult result;
|
||||
|
||||
try {
|
||||
result = engine.unwrap(encryptedBuffer, decryptedBuffer);
|
||||
}//try//
|
||||
catch(SSLException e) {
|
||||
Debug.log(e);
|
||||
throw new RuntimeException();
|
||||
}//catch//
|
||||
|
||||
return result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ? INIT_REQUIRES_RECEIVE : result.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ? INIT_REQUIRES_SEND : result.getHandshakeStatus() == HandshakeStatus.FINISHED || result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ? INIT_FINISHED : INIT_OK;
|
||||
}//receiveInitializationMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#sendInitializationMessage(java.nio.ByteBuffer, java.nio.ByteBuffer)
|
||||
*/
|
||||
public int sendInitializationMessage(ByteBuffer encryptedBuffer, ByteBuffer decryptedBuffer) {
|
||||
SSLEngineResult result;
|
||||
|
||||
hasSentFirstInitializationMessage = true;
|
||||
|
||||
try {
|
||||
result = engine.wrap(decryptedBuffer, encryptedBuffer);
|
||||
}//try//
|
||||
catch(SSLException e) {
|
||||
Debug.log(e);
|
||||
throw new RuntimeException();
|
||||
}//catch//
|
||||
|
||||
return result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ? INIT_REQUIRES_RECEIVE : result.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ? INIT_REQUIRES_SEND : result.getHandshakeStatus() == HandshakeStatus.FINISHED || result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ? INIT_FINISHED : INIT_OK;
|
||||
}//sendInitializationMessage()//
|
||||
/* (non-Javadoc)
|
||||
* @see com.de22.orb.security.AbstractSecuritySystem#getInitializationStatus()
|
||||
*/
|
||||
public int getInitializationStatus() {
|
||||
return engine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ? INIT_REQUIRES_RECEIVE : engine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ? INIT_REQUIRES_SEND : engine.getHandshakeStatus() == HandshakeStatus.FINISHED || engine.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ? INIT_FINISHED : INIT_OK;
|
||||
}//getInitializationStatus()//
|
||||
}//SslSecuritySystem//
|
||||
Reference in New Issue
Block a user