142 lines
6.6 KiB
Java
142 lines
6.6 KiB
Java
/*
|
|
* Copyright (c) 2006,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.foundation.attribute;
|
|
|
|
import java.io.IOException;
|
|
import java.io.ObjectInput;
|
|
import java.io.ObjectOutput;
|
|
|
|
import com.common.orb.Orb;
|
|
import com.common.thread.IRunnable;
|
|
import com.common.util.IIterator;
|
|
import com.common.util.IList;
|
|
import com.common.util.LiteHashMap;
|
|
import com.common.util.LiteList;
|
|
|
|
/*
|
|
* An agent which will be sent to a remote process to create one or more reflections (actually returns reflection data objects which must be reconstituted into reflections).
|
|
* The result of the agent is an IList of ReflectDataContainers where the last container has the last used reflection identifier that is valid.
|
|
* The first result in each of the containers is the reflection that was asked for.
|
|
* <p>
|
|
* Warning: This agent is not a good way to get reflections. It is better to use metadata and load all the collection's reflections at the time the collection is reflected.
|
|
* This is possible because all reflection contexts are single threaded meaning that they can start reflecting data and the process can use as many id's as necessary since
|
|
* another thread cannot start loading other reflections at the same time from the same context. This agent is made to be functional, but may be inefficient.
|
|
* </p>
|
|
*/
|
|
public class ReflectionCreationAgent implements IRunnable, java.io.Externalizable {
|
|
/** The collection of references to reflectable objects requiring reflection. */
|
|
private IList reflectables = null;
|
|
/** The update handler that the reflected objects will notify when the reflection requires updating. */
|
|
private IReflectUpdateHandler updateHandler = null;
|
|
/** The optional class which defines metadata used for determining what is reflected. The defining class' metadata will be indexed in the metadata service by the class object. */
|
|
private Class metadataIndex = null;
|
|
|
|
/**
|
|
* ReflectionCreationAgent default constructor.
|
|
*/
|
|
public ReflectionCreationAgent() {
|
|
}//ReflectionCreationAgent()//
|
|
/**
|
|
* ReflectionCreationAgent constructor.
|
|
* @param reflectables The collection of reflectable proxies which either exist on the target process or exist furthor down the virtual network connection.
|
|
* @param updateHandler The update handler that will handle updates from the created reflections.
|
|
*/
|
|
public ReflectionCreationAgent(IList reflectables, IReflectUpdateHandler updateHandler, Class metadataIndex) {
|
|
this.reflectables = reflectables;
|
|
this.updateHandler = Orb.isLocal(updateHandler) ? (IReflectUpdateHandler) Orb.getProxy(updateHandler, IReflectUpdateHandler.class) : updateHandler;
|
|
}//ReflectionCreationAgent()//
|
|
/* (non-Javadoc)
|
|
* @see com.common.thread.IRunnable#run()
|
|
*/
|
|
public Object run() {
|
|
IList result = new LiteList(reflectables.getSize());
|
|
LiteHashMap binnedReflectables = new LiteHashMap(10);
|
|
|
|
//Organize the reflectable references into lists indexed by the process (identified by the connectionIdentifier) they exist on, where null is the local process.//
|
|
for(int index = 0; index < reflectables.getSize(); index++) {
|
|
IReflectable value = (IReflectable) reflectables.get(index);
|
|
Object connectionIdentifier = Orb.getConnectionIdentifier(value);
|
|
IList reflectables = null;
|
|
|
|
//Get the collection of reflectable objects for this connection (the bin).//
|
|
reflectables = (IList) binnedReflectables.get(connectionIdentifier);
|
|
|
|
//Lazily create the reflectables collection for this bin.//
|
|
if(reflectables == null) {
|
|
reflectables = new LiteList(this.reflectables.getSize());
|
|
binnedReflectables.put(connectionIdentifier, reflectables);
|
|
}//if//
|
|
|
|
//Add the reflectable value to the bin based on its related network connection.//
|
|
reflectables.add(value);
|
|
}//for//
|
|
|
|
//Collect the sorted reflection data into the result list.//
|
|
if(binnedReflectables != null) {
|
|
IIterator connectionIdentifierIterator = binnedReflectables.keyIterator();
|
|
|
|
while(connectionIdentifierIterator.hasNext()) {
|
|
Object connectionIdentifier = connectionIdentifierIterator.next();
|
|
IList reflectables = (IList) binnedReflectables.get(connectionIdentifier);
|
|
|
|
//If this is the local process then collect the reflectable's reflection data, otherwise forward the agent to the remote process.//
|
|
if(connectionIdentifier == null) {
|
|
LiteHashMap resultMap = new LiteHashMap(reflectables.getSize()); //Note: Used to handle multiple requests for the same object.//
|
|
|
|
for(int index = 0; index < reflectables.getSize(); index++) {
|
|
IReflectable value = (IReflectable) reflectables.get(index);
|
|
ReflectDataContainer reflectDataContainer = (ReflectDataContainer) resultMap.get(value);
|
|
|
|
//If we haven't already created the reflection data then do so now (it is possible to have more than one reference to the same object in a collection).//
|
|
if(reflectDataContainer == null) {
|
|
reflectDataContainer = value.zzrReflectionRegister(updateHandler, new ReflectRegistrationData(metadataIndex, ReflectRegistrationData.OPTIONS_INCLUDE_REFLECTED_PROXY));
|
|
|
|
if(reflectDataContainer != null) {
|
|
resultMap.put(value, reflectDataContainer);
|
|
}//if//
|
|
}//if//
|
|
|
|
result.add(reflectDataContainer);
|
|
}//for//
|
|
}//if//
|
|
else {
|
|
ReflectionCreationAgent agent = new ReflectionCreationAgent(reflectables, updateHandler, metadataIndex);
|
|
IList reflectionData = null;
|
|
|
|
//Send an agent to perform this same bit of code on the remote machine.//
|
|
//TODO: Should handle exceptions?//
|
|
reflectionData = (IList) Orb.sendAgent(agent, connectionIdentifier, false, 600000, null);
|
|
|
|
if(reflectionData != null) {
|
|
result.addAll(reflectionData);
|
|
}//if//
|
|
}//else//
|
|
}//while//
|
|
}//while//
|
|
|
|
return result;
|
|
}//run()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.Externalizable#readExternal(java.io.ObjectInput)
|
|
*/
|
|
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
|
/*byte version = */in.readByte();
|
|
reflectables = (IList) in.readObject();
|
|
updateHandler = (IReflectUpdateHandler) in.readObject();
|
|
metadataIndex = (Class) in.readObject();
|
|
}//readExternal()//
|
|
/* (non-Javadoc)
|
|
* @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
|
|
*/
|
|
public void writeExternal(ObjectOutput out) throws IOException {
|
|
out.writeByte(0);
|
|
out.writeObject(reflectables);
|
|
out.writeObject(updateHandler);
|
|
out.writeObject(metadataIndex);
|
|
}//writeExternal()//
|
|
}//ReflectionCreationAgent// |