/* * 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. *

* 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. *

*/ 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//