Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/** j-Interop (Pure Java implementation of DCOM protocol)
* Copyright (C) 2006 Vikram Roopchand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* Though a sincere effort has been made to deliver a professional,
* quality product,the library itself is distributed WITHOUT ANY WARRANTY;
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*/
package org.jinterop.dcom.core;
import com.iwombat.foundation.IdentifierFactory;
import com.iwombat.util.GUIDUtil;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.ServerSocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import org.jinterop.dcom.common.JIErrorCodes;
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.common.JISystem;
import rpc.Security;
/**
* Thread for Oxid Resolver. Creates and accepts socket connections for
* resolving oxids. Gets started once for each instance of the library.
*
* Please note that the "Server" Service should be running on the machine
* where the
* COM server is running.
*
* @since 1.0
*
*/
final class JIComOxidRuntime {
private static Properties defaults = new Properties();
private static Properties defaults2 = new Properties();
private static boolean stopSystem = false;
private static boolean resolverStarted = false;
// private static ArrayList listOfSockets = new ArrayList();
private static int oxidResolverPort = -1;
private static HashMap mapOfIPIDVsComponent = new HashMap(); //java client , com server
private static HashMap mapOfJavaVsOxidDetails = new HashMap(); //java client , com server
private static HashMap mapOfOxidVsOxidDetails = new HashMap();//java client , com server
private static HashMap mapOfOIDVsComponents = new HashMap(); //java client , com server
//list of all exported oids per session, all these oids have to be removed.
private static HashMap mapOfSessionIdsVsOIDs = new HashMap(); //java server , com client
private static HashMap mapOfSetIdVsListOfOIDs = new HashMap(); //com client , java server
private static HashMap mapOfSessionVsPingSetHolder = new HashMap(); //com client , java server
//private static HashMap mapOfIPIDVsOID = new HashMap(); //com client , java server, //IPID vs JIObjectId, for increasing\decreasing references
private static HashMap mapOfAddressVsStub = new HashMap(); //java client , com server, so that we don't have to keep doing bind everytime.
private static List listOfExportedJavaComponents = new ArrayList();
static final Object mutex = new Object(); //for access to the sockets
private static final Object mutex2 = new Object();//for access to the maps
private static final Object mutex3 = new Object(); //for access to the AddressVsSession,Stub Map
private static final Object mutex4 = new Object(); //for access to the mapOfAddressVsStub
private static ServerSocket serverSocket = null;
private static Random randomGen = new Random(Double.doubleToRawLongBits(Math.random()));
private static Timer pingTimer_2minutes = new Timer(true);
private static Timer pingTimer_8minutes = new Timer(true);
//one per session.
private static class PingSetHolder {
byte[] setId = null;
String username = null;
String password = null;
String domain = null;
boolean modified = false;
boolean closed = false;
int seqNum = 1;
//JISession session = null;
Map currentSetOIDs = new HashMap();//list of JIObjectId, this list is iterated and if the IPID ref count is 0 ,
//it is added as a delete in set and a complex ping is sent.
Map pingedOnce = new HashMap();
@Override
public String toString() {
return "SetID[" + Arrays.toString(setId) + "] , currentSetOIDs[" + currentSetOIDs + "]";
}
}
//this task just checks for expired OIDs in the mapOfOIDVsComponents, each OID carries with itself, lastPingedTime,
//if that (currenttime - thattime) is < ping interval...all is okay, otherwise , all it's details are erased, thus
//removing any reference of the given java server from j-Interop library, after which if no one outside has references, this
//object can be GCed.
private static class ServerPingTimerTask extends TimerTask {
@Override
public void run() {
synchronized (mutex2) {
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().info("Running ServerPingTimerTask !");
}
Iterator itr = mapOfOIDVsComponents.keySet().iterator();
while (itr.hasNext()) {
JIObjectId oid = (JIObjectId) itr.next();
if (oid.hasExpired()) {
//remove all
JILocalCoClass component = (JILocalCoClass) mapOfOIDVsComponents.get(oid);
//this means the local system still has references and we cannot delete this object
//since the user may reuse it.
if (component.isAssociatedReferenceAlive()) {
continue;
}
JIComOxidDetails details = (JIComOxidDetails) mapOfJavaVsOxidDetails.get(component);
mapOfOxidVsOxidDetails.remove(details.getOxid());
mapOfIPIDVsComponent.remove(details.getIpid());
mapOfJavaVsOxidDetails.remove(component);
listOfExportedJavaComponents.remove(component);
itr.remove();
//the thread associated with this will also stop.
details.interruptRemUnknownThreadGroup();
component = null;
details = null;
}
}
}
}
}
static void destroySessionOIDs(int sessionId) {
synchronized (mutex2) {
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "destroySessionOIDs for session: {0}", sessionId);
}
List oids = (List) mapOfSessionIdsVsOIDs.remove(new Integer(sessionId));
if (oids == null || oids.isEmpty()) {
return;
}
for (int i = 0; i < oids.size(); i++) {
JIObjectId oid = (JIObjectId) oids.get(i);
//remove all
JILocalCoClass component = (JILocalCoClass) mapOfOIDVsComponents.remove(oid);
JIComOxidDetails details = (JIComOxidDetails) mapOfJavaVsOxidDetails.get(component);
if (details != null) {
mapOfOxidVsOxidDetails.remove(details.getOxid());
mapOfIPIDVsComponent.remove(details.getIpid());
}
mapOfJavaVsOxidDetails.remove(component);
listOfExportedJavaComponents.remove(component);
//the thread associated with this will also stop.
if (details != null) {
details.interruptRemUnknownThreadGroup();
}
component = null;
details = null;
oid = null;
}
oids.clear();
}
}
private static class ClientPingTimerTask extends TimerTask {
@Override
public void run() {
Iterator itr = null;
synchronized (mutex3) {
itr = ((Map) mapOfSessionVsPingSetHolder.clone()).entrySet().iterator();
}
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().info("Running ClientPingTimerTask !");
}
//iterate over the map and get the corresponding stubs and use there sessions to
//stub is created here and used per address
//if set id is null send a complex ping to get back the set id for all the OIDs in the
//PingSetHolder
while (itr.hasNext()) {
Map.Entry entry = (Map.Entry) itr.next();
PingSetHolder holder = (PingSetHolder) (entry).getValue();
String address = ((JISession) entry.getKey()).getTargetServer();
//will get it from the cache, since it is getting called after every 4 minutes
//what if this stub has timed out, I guess I will have to ask the developers to increase the timeout for now.
JIComOxidStub stub = null;
synchronized (mutex4) {
stub = (JIComOxidStub) mapOfAddressVsStub.get(address);
if (stub == null) {
stub = new JIComOxidStub(address, holder.domain, holder.username, holder.password);
mapOfAddressVsStub.put(address, stub);
}
}
ArrayList listOfAddedOIDs = new ArrayList();
ArrayList listOfRemovedOIDs = new ArrayList();
//form a list if OID is 0 ref
synchronized (mutex3) {
for (Iterator itr2 = holder.currentSetOIDs.keySet().iterator(); itr2.hasNext();) {
JIObjectId oid = (JIObjectId) itr2.next();
if (oid.getIPIDRefCount() == 0) {
if (!oid.dontping) {
listOfRemovedOIDs.add(oid);
holder.pingedOnce.remove(oid);
holder.modified = true;
}
itr2.remove();
} else {
if (!oid.dontping && !holder.pingedOnce.containsKey(oid)) {
listOfAddedOIDs.add(oid);
holder.pingedOnce.put(oid, oid);
holder.modified = true;
}
}
}
}
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "Within ClientPingTimerTask: holder.currentSetOIDs, current size of which is {0}", holder.currentSetOIDs.size());
}
//this is the first time this is going and objects with no references will not be added to ping set.
if (holder.setId == null) {
listOfRemovedOIDs.clear();
}
boolean isSimplePing = false;
//No additions and no deletions
if (holder.setId != null && !holder.modified) {
//send simple set ping
isSimplePing = true;
}
//seqNum will be 0 for simple ping, but incremented for complex pings. seqNum is per setId. first one will be 0 and increments
//there on...
holder.setId = stub.call(isSimplePing, holder.setId, listOfAddedOIDs, listOfRemovedOIDs, isSimplePing ? 0 : holder.seqNum++);
if (JISystem.getLogger().isLoggable(Level.FINEST)) {
JISystem.getLogger().log(Level.INFO, "Within ClientPingTimerTask: holder.seqNum {0}", holder.seqNum);
}
holder.modified = false;
//stub.close(); commenting this since we are caching the stub.
if (holder.closed) {
//this means that this set is empty and there is no need for it. The set has emptied itself and
//will get removed from COM servers side as well.
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "Within ClientPingTimerTask: Holder {0} is empty, will remove this from mapOfSessionVsPingSetHolder", holder);
}
itr.remove();
synchronized (mutex3) {
mapOfSessionVsPingSetHolder.remove(entry.getKey());
}
}
}
}
}
static {
defaults2.put("rpc.ntlm.lanManagerKey", "false");
defaults2.put("rpc.ntlm.sign", "false");
defaults2.put("rpc.ntlm.seal", "false");
defaults2.put("rpc.ntlm.keyExchange", "false");
defaults2.put("rpc.connectionContext", "org.jinterop.dcom.transport.JIComRuntimeNTLMConnectionContext");
defaults.put("rpc.connectionContext", "org.jinterop.dcom.transport.JIComRuntimeConnectionContext");
}
//ip address
static void addUpdateOXIDs(JISession session, String IPID, JIObjectId oid) {
synchronized (mutex3) {
//make sure this is the IP address
PingSetHolder holder = (PingSetHolder) mapOfSessionVsPingSetHolder.get(session);
if (holder == null) {
//new
holder = new PingSetHolder();
holder.username = session.getUserName();
holder.password = session.getPassword();
holder.domain = session.getDomain();
holder.currentSetOIDs.put(oid, oid);
holder.modified = true;
holder.seqNum = 0;
mapOfSessionVsPingSetHolder.put(session, holder);
} else //found , means it is another call for a new IPID
{
JIObjectId oid2 = (JIObjectId) holder.currentSetOIDs.get(oid);
if (oid2 != null) {
//have to update this oid, since the one from parameters is a "new" one.
oid = oid2;
} else {
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "addUpdateOXIDs: Adding OID to holder {0}, current size of currentSetOIDs is {1}", new Object[]{holder, holder.currentSetOIDs.size()});
}
holder.currentSetOIDs.put(oid, oid);
holder.modified = true;
}
}
oid.incrementIPIDRefCountBy1();
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "addUpdateOXIDs: finally this oid is {0}", oid);
}
}
}
static void delIPIDReference(String IPID, JIObjectId oid, JISession session) {
synchronized (mutex3) {
PingSetHolder holder = (PingSetHolder) mapOfSessionVsPingSetHolder.get(session);
//this will be non-null, since we are trying to remove an IPID reference so the PingSet for its OID should exist
if (holder != null) {
JIObjectId oid2 = (JIObjectId) holder.currentSetOIDs.get(oid);
if (oid2 != null) {
//temp gets replaced by the real one.
oid = oid2;
} else {
if (JISystem.getLogger().isLoggable(Level.WARNING)) {
JISystem.getLogger().log(Level.WARNING, "In delIPIDReference: Could not find Original OID for this temp OID for session: {0} , temp oid is {1} , and IPID is {2}", new Object[]{session.getSessionIdentifier(), oid, IPID});
}
return;
}
//this is the same OID as in the PingSetHolder.
oid.decrementIPIDRefCountBy1();
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "delIPIDReference: Decrementing reference count for IPID {0} on OID {1}", new Object[]{IPID, oid});
}
//should we retain this now ??? , we need not send a ping for this as well. It is being retained for the last ping only.
if (oid.getIPIDRefCount() <= 0) {
holder.currentSetOIDs.remove(oid);
//everything is gone, remove the session
if (holder.currentSetOIDs.isEmpty()) {
holder.closed = true;
mapOfSessionVsPingSetHolder.remove(session);
}
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "delIPIDReference: sessionid {0}Ref count is <= 0, for OID {1}, holder status: {2}", new Object[]{session.getSessionIdentifier(), oid, holder.closed});
}
}
} else {
if (JISystem.getLogger().isLoggable(Level.WARNING)) {
JISystem.getLogger().log(Level.WARNING, "In delIPIDReference: Could not find PingSetHolder for this session: {0} , temp oid is {1} , and IPID is {2}", new Object[]{session.getSessionIdentifier(), oid, IPID});
}
}
}
}
static void clearIPIDsforSession(JISession session) {
synchronized (mutex3) {
//make sure this is the IP address
PingSetHolder holder = (PingSetHolder) mapOfSessionVsPingSetHolder.get(session);
if (holder != null) {
if (JISystem.getLogger().isLoggable(Level.INFO)) {
JISystem.getLogger().log(Level.INFO, "clearIPIDsforSession: holder.currentSetOIDs''s size is {0}", holder.currentSetOIDs.size());
}
//No need to do this we are clearing the map anyways.
// for (Iterator itr2 = holder.currentSetOIDs.keySet().iterator();itr2.hasNext();)
// {
// JIObjectId oid = (JIObjectId)itr2.next();
// oid.setIPIDRefCountTo0();
// }
holder.modified = true;
holder.currentSetOIDs.clear(); //being done since this session is being destroyed and the corresponding COM server
//need not be retained by us.
holder.closed = true;
//Should be not remove this entry ??? I think it is being retained only for the pings ... we should let this go.
mapOfSessionVsPingSetHolder.remove(session);
}
}
//remove the socket for this session associated with ping timer
synchronized (mutex4) {
JIComOxidStub stub = (JIComOxidStub) mapOfAddressVsStub.remove(session.getTargetServer());
if (stub != null) {
stub.close();
}
}
}
static synchronized void startResolverTimer() {
//schedule only 1 timer task , the task to ping the OIDs obtained.
pingTimer_2minutes.scheduleAtFixedRate(new ClientPingTimerTask(), 0, (4 * 60 * 1000));
if (JISystem.isJavaCoClassAutoCollectionSet()) {
pingTimer_8minutes.scheduleAtFixedRate(new ServerPingTimerTask(), 0, 8 * 60 * 1000);
}
}
//only one thread , that is the main is expected to enter this one.
static synchronized void startResolver() {
if (resolverStarted) {
return;
}
Runnable thread = new Runnable() {
@Override
public void run() {
try {
final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocket = serverSocketChannel.socket();//new ServerSocket(0); //bind on any free port
serverSocket.bind(null);
oxidResolverPort = serverSocket.getLocalPort();
//System.err.println("VIKRAM: oxidResolverPort: " + oxidResolverPort);
// server infinite loop
while (!stopSystem) {
Socket socket = serverSocket.accept();
//listOfSockets.add(socket);
//System.err.println("VIKRAM: Accepting new Call from " + socket.getPort());
//in a multithreaded scenario this will be serialized.
synchronized (mutex) {
JISystem.internal_setSocket(socket);
//now create the JIComOxidRuntimeHelper Object and start it.
Properties properties = new Properties(defaults);
properties.put("IID", "99fcfec4-5260-101b-bbcb-00aa0021347a:0.0".toUpperCase()); //IOxidResolver
JIComOxidRuntimeHelper oxidResolver = new JIComOxidRuntimeHelper(properties);
oxidResolver.startOxid(socket.getLocalPort(), socket.getPort());
}
}
} catch (IOException e) {
//e.printStackTrace();
}
//close all sockets.
// for (int i = 0; i < listOfSockets.size(); i++)
// {
// Socket s = (Socket)listOfSockets.get(i);
// try {
// s.close();
// } catch (IOException e) {}
// }
}
};
Thread thread2 = new Thread(thread, "jI_OxidResolver");
thread2.setDaemon(true);
thread2.start();
resolverStarted = true;
}
static int getOxidResolverPort() {
return oxidResolverPort;
}
//Will be called from shutDownHook thread.
static synchronized void stopResolver() {
stopSystem = true;
try {
serverSocket.close();
} catch (IOException e) {
}
pingTimer_2minutes.cancel();
pingTimer_8minutes.cancel();
Iterator itr = mapOfAddressVsStub.values().iterator();
while (itr.hasNext()) {
JIComOxidStub s = (JIComOxidStub) itr.next();
s.close();
}
mapOfAddressVsStub.clear(); //will clean up all the others as well
}
/**
* Returns the MIP for the Java Instance, this will also have the
* OXID,OID,IPID for the same.
*
* @param javaInstance
* @return
*/
static JIInterfacePointer getInterfacePointer(JISession session, JILocalCoClass component) throws JIException {
JIInterfacePointer ptr = null;
synchronized (mutex2) {
if (component.isAlreadyExported()) {
throw new JIException(JIErrorCodes.JI_JAVACOCLASS_ALREADY_EXPORTED);
}
component.setSession(session);
//
// JIComOxidDetails details = (JIComOxidDetails)mapOfJavaVsOxidDetails.get(component);
//
// if (details != null)
// {
// return details.getInterfacePtr();
// }
//as the ID could be repeated, this is the ipid of the interface being requested.
String ipid = GUIDUtil.guidStringFromHexString(IdentifierFactory.createUniqueIdentifier().toHexString());
String iid = component.isCoClassUnderRealIID() ? component.getCoClassIID() : IJIComObject.IID;//has to be IUnknown's IID.
byte[] bytes = new byte[8];
randomGen.nextBytes(bytes);
JIOxid oxid = new JIOxid(bytes);
byte[] bytes2 = new byte[8];
randomGen.nextBytes(bytes2);
JIObjectId oid = new JIObjectId(bytes2, false);
component.setObjectId(oid.getOID());
//JIComOxidDetails details = new JIComOxidDetails();
JIStdObjRef objref = new JIStdObjRef(ipid, oxid, oid);
ptr = new JIInterfacePointer(iid, oxidResolverPort, objref);
Properties properties = new Properties(defaults2);
properties.put("IID", "00000131-0000-0000-C000-000000000046:0.0".toUpperCase()); //IRemUnknown
properties.put("rpc.ntlm.domain", session.getTargetServer());
int protecttionLevel = 2;
if (session.isSessionSecurityEnabled()) {
protecttionLevel = 6;
properties.setProperty("rpc.ntlm.seal", "true");
properties.setProperty("rpc.ntlm.sign", "true");
properties.setProperty("rpc.ntlm.keyExchange", "true");
properties.setProperty("rpc.ntlm.keyLength", "128");
properties.setProperty("rpc.ntlm.ntlm2", "true");
properties.setProperty(Security.USERNAME, session.getUserName());
properties.setProperty(Security.PASSWORD, session.getPassword());
properties.setProperty("rpc.ntlm.ntlm2", "true");
}
if (session.isNTLMv2Enabled()) {
properties.setProperty("rpc.ntlm.ntlmv2", "true");
}
JIComOxidRuntimeHelper remUnknown = new JIComOxidRuntimeHelper(properties);
//now create a new JIComOxidDetails
//this carries a reference to the javaInstance , incase we do not get pings from the client
//at the right times, the cleaup thread will remove this entry and it's OXID as well from both the maps.
JIComOxidDetails details = new JIComOxidDetails(component, oxid, oid, iid, ipid, ptr, remUnknown, protecttionLevel);
mapOfJavaVsOxidDetails.put(component, details);
mapOfOxidVsOxidDetails.put(oxid, details);
mapOfOIDVsComponents.put(oid, component);
listOfExportedJavaComponents.add(component);
mapOfIPIDVsComponent.put(ipid, details); //this is the ipid of the component.
List oids = (List) mapOfSessionIdsVsOIDs.get(new Integer(session.getSessionIdentifier()));
if (oids == null) {
oids = new ArrayList();
mapOfSessionIdsVsOIDs.put(new Integer(session.getSessionIdentifier()), oids);
}
oids.add(oid);
component.setAssociatedInterfacePointer(ptr);
}
return ptr;
}
//will get called from OxidResolverImpl only
static JIComOxidDetails getOxidDetails(JIOxid oxid) {
synchronized (mutex2) {
return (JIComOxidDetails) mapOfOxidVsOxidDetails.get(oxid);
}
}
//Will get called from RemQueryInterface of IRemUnknown, when it gets the IPID
//it will identify the correct component to act on.
//on this component the IID (provided again by the client) will do a exportInstance, with a
//randomly generated IPID and this IPID will be returned to the client.
//The oid be the one present in details object.
//Now , when the alter context call will come with the new IID (which was just QIed), the
//state of RemUnknownObject will get set for the correct component using getJavaComponentForIID.
//The next call of requestcopdu will contain the request along with the field object having the IPID of the
//instance to call on. Pass this to the components (identified previously) invoke API., along with the rest of params
//How will the request get decoded with out IDL info ??? Hard code for now for toString ??
static JIComOxidDetails getComponentFromIPID(String ipid) {
synchronized (mutex2) {
return (JIComOxidDetails) mapOfIPIDVsComponent.get(ipid);
}
}
static void addUpdateSets(JISetId setId, ArrayList objectIdsAdded, ArrayList objectIdsDel) {
synchronized (mutex2) {
ArrayList listOfOIDs = (ArrayList) mapOfSetIdVsListOfOIDs.get(setId);
if (listOfOIDs == null) {
listOfOIDs = new ArrayList();
//first time
listOfOIDs.addAll(objectIdsAdded);
mapOfSetIdVsListOfOIDs.put(setId, listOfOIDs);
//del list would be empty I presume
} else {
for (int i = 0; i < listOfOIDs.size(); i++) {
JIObjectId oid = (JIObjectId) listOfOIDs.get(i);
if (!objectIdsDel.contains(oid)) {
oid.updateLastPingTime();
}
}
listOfOIDs.addAll(objectIdsAdded);
}
}
}
//since the IID is unique and we have to consider nested IIDs, this API will not work for component's IID
// static JILocalCoClass getJavaComponentForIID(String uniqueIID)
// {
// JILocalCoClass component = null;
// synchronized (mutex2) {
// for (int i = 0; i < listOfExportedJavaComponents.size(); i++ )
// {
// component = (JILocalCoClass)listOfExportedJavaComponents.get(i);
// if (component.isPresent(uniqueIID))
// {
// break;
// }
// component = null;
// }
// }
//
// return component;
// }
static JILocalCoClass getJavaComponentFromIPID(String ipid) {
JILocalCoClass component = null;
synchronized (mutex2) {
for (int i = 0; i < listOfExportedJavaComponents.size(); i++) {
component = (JILocalCoClass) listOfExportedJavaComponents.get(i);
//this will be unique, no two components will ever have same IPID for an IID.They will have different IPIDs for same IIDs.
if (component.getIIDFromIpid(ipid) != null) {
break;
}
component = null;
}
}
return component;
}
private JIComOxidRuntime() {
}
}