소스 검색

HPCC-17058 Support server list in dropzone settings for WsTopology, etc

Support server list in dropzone settings for two ESP web services:
WsTopology and FileSpray.

Also add getDropZoneIteratorByAddress() into environment lib.
And clean old getComputerName(), getDropZoneByComputer() and
getDropZoneIteratorByComputer().

Signed-off-by: wangkx <kevin.wang@lexisnexis.com>
wangkx 8 년 전
부모
커밋
2bb51ad03f

+ 68 - 175
common/environment/environment.cpp

@@ -95,25 +95,6 @@ protected:
     unsigned maxIndex = 0;
 };
 
-class CConstDropZoneIteratorByComputer : public CSimpleInterfaceOf<IConstDropZoneInfoIterator>
-{
-public:
-    CConstDropZoneIteratorByComputer(const char * computer);
-
-    virtual bool first() override;
-    virtual bool next() override;
-    virtual bool isValid() override;
-    virtual IConstDropZoneInfo & query() override;
-    virtual unsigned count() const override;
-
-protected:
-    StringBuffer computerName;
-    Owned<IConstDropZoneInfo> curr;
-    Owned<CLocalEnvironment> constEnv;
-    unsigned index = 1;
-    unsigned maxIndex = 0;
-};
-
 //==========================================================================================
 
 class CConstInstanceInfo;
@@ -129,7 +110,6 @@ private:
     mutable bool dropZoneCacheBuilt;
     mutable bool machineCacheBuilt;
     StringBuffer xPath;
-    Owned<IPropertyTree> numOfDropzonesByComputer;
     mutable unsigned numOfMachines;
     mutable unsigned numOfDropZones;
 
@@ -139,12 +119,6 @@ private:
     void buildMachineCache() const;
     void buildDropZoneCache() const;
     void init();
-    StringBuffer & createComputerNameXpath(const char * computer, StringBuffer &xpath) const
-    {
-        xpath.append("numberOfDropZones[@name=\"");
-        xpath.append(computer).append("\"]/number");
-        return xpath;
-    }
     mutable bool isDropZoneRestrictionLoaded = false;
     mutable bool dropZoneRestrictionEnabled = true;
 
@@ -164,7 +138,6 @@ public:
     virtual IConstMachineInfo * getMachineByAddress(const char * machineIp) const;
     virtual IConstMachineInfo * getMachineForLocalHost() const;
     virtual IConstDropZoneInfo * getDropZone(const char * name) const;
-    virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const;
     virtual IConstInstanceInfo * getInstance(const char * type, const char * version, const char *domain) const;
     virtual CConstInstanceInfo * getInstanceByIP(const char *type, const char *version, IpAddress &ip) const;
     virtual IConstComputerTypeInfo * getComputerType(const char * name) const;
@@ -181,8 +154,7 @@ public:
 
     virtual IConstMachineInfoIterator * getMachineIterator() const;
 
-    virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer, const char * dzname) const;
-    virtual IConstDropZoneInfoIterator * getDropZoneIteratorByComputer(const char * computer) const;
+    virtual IConstDropZoneInfoIterator * getDropZoneIteratorByAddress(const char * address) const;
     virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const;
 
     virtual IConstDropZoneInfoIterator * getDropZoneIterator() const;
@@ -190,15 +162,6 @@ public:
     unsigned getNumberOfMachines() const { buildMachineCache(); return numOfMachines; }
     IConstMachineInfo * getMachineByIndex(unsigned index) const;
 
-    unsigned getNumberOfDropZonesByComputer(const char * computer) const
-    {
-        buildDropZoneCache();
-        StringBuffer xpath;
-        createComputerNameXpath(computer, xpath);
-        return numOfDropzonesByComputer->getPropInt(xpath);
-    }
-    IConstDropZoneInfo * getDropZoneByComputerByIndex(const char * computer, unsigned index) const;
-
     unsigned getNumberOfDropZones() const { buildDropZoneCache(); return numOfDropZones; }
     IConstDropZoneInfo * getDropZoneByIndex(unsigned index) const;
     bool isDropZoneRestrictionEnabled() const;
@@ -286,8 +249,6 @@ public:
             { return c->getMachineForLocalHost(); }
     virtual IConstDropZoneInfo * getDropZone(const char * name) const
             { return c->getDropZone(name); }
-    virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const
-            { return c->getDropZoneByComputer(computer); }
     virtual IConstInstanceInfo * getInstance(const char *type, const char *version, const char *domain) const
             { return c->getInstance(type, version, domain); }
     virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char *type, const char *version, const char *machineaddr,const char *defprogname) const
@@ -308,10 +269,8 @@ public:
 
     virtual IConstMachineInfoIterator * getMachineIterator() const
             { return c->getMachineIterator(); }
-    virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer, const char * dzname) const
-            { return c->getDropZoneByComputer(computer, dzname); }
-    virtual IConstDropZoneInfoIterator * getDropZoneIteratorByComputer(const char * computer) const
-            { return c->getDropZoneIteratorByComputer(computer); }
+    virtual IConstDropZoneInfoIterator * getDropZoneIteratorByAddress(const char * address) const
+            { return c->getDropZoneIteratorByAddress(address); }
     virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const
             { return c->getDropZoneByAddressPath(netaddress, targetPath); }
     virtual IConstDropZoneInfoIterator * getDropZoneIterator() const
@@ -1082,7 +1041,6 @@ void CLocalEnvironment::init()
     dropZoneCacheBuilt = false;
     numOfMachines = 0;
     numOfDropZones = 0;
-    numOfDropzonesByComputer.setown(createPTree("computers"));
     isDropZoneRestrictionLoaded = false;
 }
 
@@ -1207,31 +1165,6 @@ void CLocalEnvironment::buildDropZoneCache() const
                 Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
                 cache.setValue(x.str(), cached);
             }
-            const char * computer = it->query().queryProp("@computer");
-            if (computer)
-            {
-                StringBuffer xpath;
-                createComputerNameXpath(computer, xpath);
-                unsigned numOfDropZoneByComputer = numOfDropzonesByComputer->getPropInt(xpath.str(), -1);
-                if (numOfDropZoneByComputer == -1)
-                {
-                    numOfDropZoneByComputer = 0;
-                    IPropertyTree * val = createPTree("numberOfDropZones");
-                    val->addPropInt("@number",numOfDropZoneByComputer);
-                    val->addProp("@name", computer);
-                    numOfDropzonesByComputer->addPropTree("numberOfDropZones",val);
-                }
-                numOfDropZoneByComputer++;
-                numOfDropzonesByComputer->setPropInt(xpath.str(), numOfDropZoneByComputer);
-
-                StringBuffer x("Software/DropZone[@computer=\"");
-                x.append(computer);
-                x.append(DROPZONE_BY_MACHINE_SUFFIX).append(numOfDropZoneByComputer);
-                x.append("\"]");
-
-                Owned<IConstEnvBase> cached = new CConstDropZoneInfo((CLocalEnvironment *) this, &it->query());
-                cache.setValue(x.str(), cached);
-            }
 
             numOfDropZones++;
             StringBuffer x("Software/DropZone[@id=\"");
@@ -1364,59 +1297,6 @@ IConstDropZoneInfo * CLocalEnvironment::getDropZone(const char * name) const
     return (CConstDropZoneInfo *) getCache(xpath.str());
 }
 
-
-IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputer(const char * computer) const
-{
-    if (!computer)
-        return nullptr;
-    buildDropZoneCache();
-
-    StringBuffer x;
-    createComputerNameXpath(computer, x);
-    unsigned numOfDropZoneByComputer = numOfDropzonesByComputer->getPropInt(x, -1);
-    if (numOfDropZoneByComputer == -1)
-        return nullptr;
-
-    StringBuffer xpath("Software/DropZone[@computer=\"");
-    xpath.append(computer);
-    xpath.append(DROPZONE_BY_MACHINE_SUFFIX).append(DEFAULT_DROPZONE_INDEX);
-    xpath.append("\"]");
-
-    synchronized procedure(safeCache);
-    return (CConstDropZoneInfo *) getCache(xpath.str());
-}
-
-IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputer(const char * computer, const char * dzname) const
-{
-    IConstDropZoneInfo * dzInfo = getDropZone(dzname);
-    if (!dzInfo)
-        return nullptr;
-
-    SCMStringBuffer cachedComputer;
-    dzInfo->getComputerName(cachedComputer);
-
-    if (!streq(computer, cachedComputer.str()))
-        return nullptr;
-
-    return dzInfo;
-
-}
-
-IConstDropZoneInfo * CLocalEnvironment::getDropZoneByComputerByIndex(const char * computer, unsigned index) const
-{
-    if (!computer || (index == 0))
-        return nullptr;
-
-    buildDropZoneCache();
-    if (index > getNumberOfDropZonesByComputer(computer))
-        return nullptr;
-
-    StringBuffer xpath("Software/DropZone[@computer=\"");
-    xpath.append(computer).append(DROPZONE_BY_MACHINE_SUFFIX).append(index).append("\"]");
-    synchronized procedure(safeCache);
-    return (CConstDropZoneInfo *) getCache(xpath.str());
-}
-
 IConstDropZoneInfo * CLocalEnvironment::getDropZoneByIndex(unsigned index) const
 {
     if (!numOfDropZones || (index == 0))
@@ -1623,7 +1503,6 @@ void CLocalEnvironment::clearCache()
         p.setown(conn->getRoot());
     }
     cache.kill();
-    numOfDropzonesByComputer.clear();
     init();
     resetPasswordsFromSDS();
 }
@@ -1684,13 +1563,74 @@ IConstDropZoneInfo * CLocalEnvironment::getDropZoneByAddressPath(const char * ne
     return LINK(dropZone);
 }
 
-
-
-IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIteratorByComputer(const char * computer) const
+IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIteratorByAddress(const char *addr) const
 {
-    return new CConstDropZoneIteratorByComputer(computer);
+    class CByAddrIter : public CSimpleInterfaceOf<IConstDropZoneInfoIterator>
+    {
+        IArrayOf<IConstDropZoneInfo> matches;
+        unsigned cur = NotFound;
+
+    public:
+        CByAddrIter(IConstDropZoneInfoIterator *baseIter, const char *addr)
+        {
+            IpAddress toMatch(addr);
+            ForEach(*baseIter)
+            {
+                IConstDropZoneInfo &dz = baseIter->query();
+                Owned<IConstDropZoneServerInfoIterator> serverIter = dz.getServers();
+                ForEach(*serverIter)
+                {
+                    IConstDropZoneServerInfo &serverElem = serverIter->query();
+                    StringBuffer serverName;
+                    IpAddress serverIp(serverElem.getServer(serverName).str());
+                    if (serverIp.ipequals(toMatch))
+                    {
+                        matches.append(*LINK(&dz));
+                        break;
+                    }
+                }
+            }
+        }
+        virtual bool first() override
+        {
+            if (0 == matches.ordinality())
+            {
+                cur = NotFound;
+                return false;
+            }
+            cur = 0;
+            return true;
+        }
+        virtual bool next() override
+        {
+            if (cur+1==matches.ordinality())
+            {
+                cur = NotFound;
+                return false;
+            }
+            ++cur;
+            return true;
+        }
+        virtual bool isValid() override
+        {
+            return NotFound != cur;
+        }
+        virtual IConstDropZoneInfo &query() override
+        {
+            assertex(NotFound != cur);
+            return matches.item(cur);
+        }
+        virtual unsigned count() const override
+        {
+            return matches.ordinality();
+        }
+    };
+    Owned<IConstDropZoneInfoIterator> baseIter = new CConstDropZoneInfoIterator();
+    return new CByAddrIter(baseIter, addr);
 }
 
+
+
 IConstDropZoneInfoIterator * CLocalEnvironment::getDropZoneIterator() const
 {
     return new CConstDropZoneInfoIterator();
@@ -1756,53 +1696,6 @@ unsigned CConstMachineInfoIterator::count() const
     return maxIndex;
 }
 
-//--------------------------------------------------
-
-CConstDropZoneIteratorByComputer::CConstDropZoneIteratorByComputer(const char * computer)
-{
-    Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
-    constEnv.setown((CLocalEnvironment *)factory->openEnvironment());
-    computerName.set(computer);
-    maxIndex = constEnv->getNumberOfDropZonesByComputer(computer);
-}
-
-bool CConstDropZoneIteratorByComputer::first()
-{
-    index = 1;
-    curr.setown(constEnv->getDropZoneByComputerByIndex(computerName.str(), index));
-    return curr != nullptr;
-}
-bool CConstDropZoneIteratorByComputer::next()
-{
-    if (index < maxIndex)
-    {
-        index++;
-        curr.setown(constEnv->getDropZoneByComputerByIndex(computerName.str(), index));
-    }
-    else
-        curr.clear();
-
-    return curr != nullptr;
-}
-
-bool CConstDropZoneIteratorByComputer::isValid()
-{
-    return curr != nullptr;
-}
-
-IConstDropZoneInfo & CConstDropZoneIteratorByComputer::query()
-{
-    return *curr;
-}
-
-unsigned CConstDropZoneIteratorByComputer::count() const
-{
-    return maxIndex;
-}
-
-//--------------------------------------------------
-
-
 CConstDropZoneServerInfoIterator::CConstDropZoneServerInfoIterator(const IConstDropZoneInfo * dropZone)
 {
     Owned<IEnvironmentFactory> factory = getEnvironmentFactory();

+ 1 - 3
common/environment/environment.hpp

@@ -137,7 +137,6 @@ interface IConstEnvironment : extends IConstEnvBase
     virtual IConstMachineInfo * getMachineByAddress(const char * netaddress) const = 0;
     virtual IConstMachineInfo * getMachineForLocalHost() const = 0;
     virtual IConstDropZoneInfo * getDropZone(const char * name) const = 0;
-    virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer) const = 0;
     virtual IConstInstanceInfo * getInstance(const char * type, const char * version, const char * domain) const = 0;
     virtual IConstComputerTypeInfo * getComputerType(const char * name) const = 0;
     virtual bool getRunInfo(IStringVal & path, IStringVal & dir, const char * type, const char * version, const char * machineaddr, const char * defaultprogname) const = 0;
@@ -146,8 +145,7 @@ interface IConstEnvironment : extends IConstEnvBase
     virtual void clearCache() = 0;
 
     virtual IConstMachineInfoIterator * getMachineIterator() const = 0;
-    virtual IConstDropZoneInfo * getDropZoneByComputer(const char * computer, const char * dzname) const = 0;
-    virtual IConstDropZoneInfoIterator * getDropZoneIteratorByComputer(const char * computer) const = 0;
+    virtual IConstDropZoneInfoIterator * getDropZoneIteratorByAddress(const char * address) const = 0;
     // returns a drop zone that is defined on IP with the shortest path that's a parent of targetPath
     virtual IConstDropZoneInfo * getDropZoneByAddressPath(const char * netaddress, const char *targetPath) const = 0;
     virtual IConstDropZoneInfoIterator * getDropZoneIterator() const = 0;

+ 13 - 11
esp/eclwatch/ws_XSLT/dropzonefile.xslt

@@ -38,7 +38,7 @@
         <title>EclWatch</title>
         <script language="JavaScript1.2">
           var initialPath = '<xsl:value-of select="/DropZoneFilesResponse/Path"/>';
-          var currentNetAddress = '<xsl:value-of select="/DropZoneFilesResponse/NetAddress"/>';
+          var currentDropZone = '<xsl:value-of select="/DropZoneFilesResponse/NetAddress"/>/<xsl:value-of select="/DropZoneFilesResponse/DropZoneName"/>';
           <xsl:text disable-output-escaping="yes"><![CDATA[
             var intervalId = 0;
             var hideLoading = 1;
@@ -49,7 +49,8 @@
               if (machineDropDown.selectedIndex > 0)
               {
                 selected=machineDropDown.options[machineDropDown.selectedIndex];               
-                document.forms['DropZoneForm'].NetAddress.value=selected.value;
+                var vals = selected.value.split('/');
+                document.forms['DropZoneForm'].NetAddress.value=vals[0];
                 pos = selected.title.indexOf(';');
                 directory = selected.title.substring(0, pos);
                 linux = selected.title.substring(pos+1);
@@ -64,7 +65,7 @@
                   }
                 }
 
-                document.location.href = "/FileSpray/DropZoneFiles?NetAddress=" + selected.value + "&OS=" + sourceOS+ "&Path=" + directory;
+                document.location.href = "/FileSpray/DropZoneFiles?DropZoneName=" + vals[1] + "&NetAddress=" + vals[0] + "&OS=" + sourceOS+ "&Path=" + directory;
               }
               else
               {
@@ -196,11 +197,11 @@
             function getSelectedDropZone()
             {
               machineDropDown = document.forms['DropZoneForm'].machine;
-              if ((machineDropDown.selectedIndex < 1) && (machineDropDown.length > 1) && (currentNetAddress != ""))
+              if ((machineDropDown.selectedIndex < 1) && (machineDropDown.length > 1) && (currentDropZone != "/"))
               {
                 for (i=1; i<machineDropDown.length; i++)
                 {
-                  if (machineDropDown.options[i].value == currentNetAddress)
+                  if (machineDropDown.options[i].value == currentDropZone)
                   {
                     machineDropDown.selectedIndex = i;
                     break;
@@ -209,8 +210,9 @@
               }
               if (machineDropDown.selectedIndex > 0)
               {
-                selected=machineDropDown.options[machineDropDown.selectedIndex];               
-                document.forms['DropZoneForm'].NetAddress.value=selected.value;
+                selected=machineDropDown.options[machineDropDown.selectedIndex];
+                var vals = selected.value.split('/');
+                document.forms['DropZoneForm'].NetAddress.value=vals[0];
                 pos = selected.title.indexOf(';');
                 if (initialPath == '')
                   directory = selected.title.substring(0, pos);
@@ -221,11 +223,11 @@
 
                 document.forms['DropZoneForm'].Directory.value = directory;
 
-                document.forms['DropZoneFileForm'].NetAddress.value=selected.value;
+                document.forms['DropZoneFileForm'].NetAddress.value=vals[0];
                 document.forms['DropZoneFileForm'].Path.value=directory;
                 document.forms['DropZoneFileForm'].OS.value=sourceOS;
 
-                url0 = "/FileSpray/UploadFile?upload_&NetAddress=" + selected.value + "&OS=" + sourceOS + "&Path=" + directory;
+                url0 = "/FileSpray/UploadFile?upload_&DropZoneName=" + vals[1] + "&NetAddress=" + vals[0] + "&OS=" + sourceOS + "&Path=" + directory;
               }
               else
               {
@@ -271,7 +273,7 @@
                               <option>
                                 <xsl:variable name="curip" select="NetAddress"/>
                                 <xsl:attribute name="value">
-                                  <xsl:value-of select="NetAddress"/>
+                                  <xsl:value-of select="NetAddress"/>/<xsl:value-of select="Name"/>
                                 </xsl:attribute>
                                 <xsl:attribute name="title">
                                   <xsl:value-of select="Path"/>;<xsl:value-of select="Linux"/>
@@ -408,7 +410,7 @@
             <input type="checkbox" name="Names_i{position()}" value="{name}" onclick="return checkSelected(this)"/>
           </td>
           <td align="left">
-            <a title="Open folder..." href="javascript:go('/FileSpray/DropZoneFiles?Subfolder={name}&amp;NetAddress={../../NetAddress}&amp;Path={../../Path}&amp;OS={../../OS}')">
+            <a title="Open folder..." href="javascript:go('/FileSpray/DropZoneFiles?Subfolder={name}&amp;DropZoneName={../../DropZoneName}&amp;NetAddress={../../NetAddress}&amp;Path={../../Path}&amp;OS={../../OS}')">
               <img src="/esp/files_/img/folder.gif" width="19" height="16" border="0" alt="Open folder..." style="vertical-align:bottom"/>
             </a>
             <xsl:value-of select="name"/>

+ 8 - 1
esp/scm/ws_fs.ecm

@@ -547,6 +547,8 @@ ESPresponse [exceptions_inline] FileListResponse
 ESPrequest [nil_remove] DropZoneFileSearchRequest
 {
     string DropZoneName;
+    [min_ver("1.15")] string Server;
+    [min_ver("1.15")] bool ECLWatchVisibleOnly(false);
     string NameFilter;
 };
 
@@ -612,18 +614,22 @@ ESPStruct [nil_remove] DropZone
 
 ESPrequest DropZoneFilesRequest
 {
+    [min_ver("1.15")] string DropZoneName;
     string NetAddress;
     string Path;
     string OS;
     string Subfolder;
+    [min_ver("1.15")] bool ECLWatchVisibleOnly(false);
     bool DirectoryOnly(false);
 };
 
 ESPresponse [exceptions_inline, nil_remove] DropZoneFilesResponse
 {
+    [min_ver("1.15")] string DropZoneName;
     string NetAddress;
     string Path;
     int OS;
+    [min_ver("1.15")] bool ECLWatchVisibleOnly;
 
     ESParray<ESPStruct DropZone> DropZones; 
     ESParray<ESPStruct PhysicalFileStruct> Files;   
@@ -631,6 +637,7 @@ ESPresponse [exceptions_inline, nil_remove] DropZoneFilesResponse
 
 ESPrequest DeleteDropZoneFilesRequest
 {
+    [min_ver("1.15")]string DropZoneName;
     string NetAddress;
     string Path;
     string OS;
@@ -669,7 +676,7 @@ ESPresponse [exceptions_inline, nil_remove] GetDFUServerQueuesResponse
 
 ESPservice [
     auth_feature("DEFERRED"),
-    version("1.14"),
+    version("1.15"),
     exceptions_inline("./smc_xslt/exceptions.xslt")] FileSpray
 {
     ESPuses ESPstruct DFUWorkunit;

+ 15 - 1
esp/scm/ws_topology.ecm

@@ -204,6 +204,8 @@ ESPStruct TpDropZone
     string Description;
     string Build;
     string Path;
+    [min_ver("1.26")]bool ECLWatchVisible;
+    [min_ver("1.26")]string UMask;
     ESParray<ESPstruct TpMachine> TpMachines;
 
 };
@@ -598,7 +600,18 @@ ESPresponse [exceptions_inline,encode(0)] TpGetServicePluginsResponse
     ESParray<ESPstruct TpEspServicePlugin, Plugin> Plugins;
 };
 
-ESPservice [auth_feature("DEFERRED"), noforms, version("1.25"), exceptions_inline("./smc_xslt/exceptions.xslt")] WsTopology
+ESPrequest TpDropZoneQueryRequest
+{
+    string Name;
+    bool ECLWatchVisibleOnly;
+};
+
+ESPresponse [nil_remove, exceptions_inline] TpDropZoneQueryResponse
+{
+    ESParray<ESPstruct TpDropZone>    TpDropZones;
+};
+
+ESPservice [auth_feature("DEFERRED"), noforms, version("1.26"), exceptions_inline("./smc_xslt/exceptions.xslt")] WsTopology
 {
     ESPuses ESPStruct TpBinding;
     ESPuses ESPstruct TpCluster;
@@ -628,6 +641,7 @@ ESPservice [auth_feature("DEFERRED"), noforms, version("1.25"), exceptions_inlin
     ESPmethod [resp_xsl_default("/esp/xslt/cluster_info.xslt")] TpClusterInfo(TpClusterInfoRequest, TpClusterInfoResponse);
     ESPmethod [resp_xsl_default("/esp/xslt/thor_status.xslt")] TpThorStatus(TpThorStatusRequest, TpThorStatusResponse);
 
+    ESPmethod [min_ver("1.26")] TpDropZoneQuery(TpDropZoneQueryRequest, TpDropZoneQueryResponse);
     ESPmethod [resp_xsl_default("/esp/xslt/services.xslt")] TpServiceQuery(TpServiceQueryRequest, TpServiceQueryResponse);
     ESPmethod TpSetMachineStatus(TpSetMachineStatusRequest, TpSetMachineStatusResponse);
     ESPmethod TpSwapNode(TpSwapNodeRequest, TpSwapNodeResponse);

+ 60 - 74
esp/services/ws_fs/ws_fsBinding.cpp

@@ -18,7 +18,6 @@
 #include "ws_fsService.hpp"
 #include "ws_fsBinding.hpp"
 #include "TpWrapper.hpp"
-#include "environment.hpp"
 #include "jwrapper.hpp"
 #include "dfuwu.hpp"
 #include "dadfs.hpp"
@@ -175,7 +174,7 @@ int CFileSpraySoapBindingEx::onGetInstantQuery(IEspContext &context, CHttpReques
 
             StringBuffer wuid;
             request->getParameter("wuid", wuid);
-            Owned<IPropertyTree> pTree = createPTreeForXslt(method, wuid.str());
+            Owned<IPropertyTree> pTree = createPTreeForXslt(context.getClientVersion(), method, wuid.str());
             toXML(pTree, xml, false);
         }
     
@@ -199,7 +198,7 @@ int CFileSpraySoapBindingEx::onGetInstantQuery(IEspContext &context, CHttpReques
         return CFileSpraySoapBinding::onGetInstantQuery(context, request, response, service, method);
 }
 
-IPropertyTree* CFileSpraySoapBindingEx::createPTreeForXslt(const char* method, const char* dfuwuid)
+IPropertyTree* CFileSpraySoapBindingEx::createPTreeForXslt(double clientVersion, const char* method, const char* dfuwuid)
 {
     Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
     Owned<IConstEnvironment> m_constEnv = factory->openEnvironment();
@@ -230,80 +229,11 @@ IPropertyTree* CFileSpraySoapBindingEx::createPTreeForXslt(const char* method, c
             }
         }
 
-        Owned<IPropertyTreeIterator> it = pEnvSoftware->getElements("DropZone");
-        ForEach(*it)
-        {
-            if (!it->query().getPropBool("@ECLWatchVisible", true))
-                continue;
-            IPropertyTree* pDropZone = pSoftware->addPropTree("DropZone", &it->get());
-            //get IP Address of the computer associated with this drop zone
-            const char* pszComputer = it->query().queryProp("@computer");
-            if (!strcmp(pszComputer, "."))
-                pszComputer = "localhost";
-
-            StringBuffer xpath;
-            xpath.appendf("Hardware/Computer[@name='%s']/@netAddress", pszComputer);
-
-            StringBuffer sNetAddr;
-            const char* pszNetAddr = pEnvRoot->queryProp(xpath.str());
-            if (strcmp(pszNetAddr, "."))
-            {       
-                sNetAddr.append(pszNetAddr);
-            }
-            else
-            {
-                StringBuffer ipStr;
-                IpAddress ipaddr = queryHostIP();
-                ipaddr.getIpText(ipStr);
-                if (ipStr.length() > 0)
-                {
-#ifdef MACHINE_IP
-                    sNetAddr.append(MACHINE_IP);
-#else
-                    sNetAddr.append(ipStr.str());
-#endif
-                }
-            }
-            pDropZone->addProp("@netAddress", sNetAddr.str());
-            if ((dfuwuidSourcePartIP.length() > 0) && (sNetAddr.length() > 0))
-            {
-                IpAddress ip1(dfuwuidSourcePartIP.str()), ip2(sNetAddr.str());
-                if (ip1.ipequals(ip2))              
-                    pDropZone->addProp("@sourceNode", "1");
-            }
-
-            Owned<IConstMachineInfo> machine;
-            if (strcmp(pszNetAddr, "."))
-                machine.setown(m_constEnv->getMachineByAddress(sNetAddr.str()));
-            else
-            {
-                machine.setown(m_constEnv->getMachineByAddress(pszNetAddr));
-                if (!machine)
-                    machine.setown(m_constEnv->getMachineByAddress(sNetAddr.str()));
-            }
-
-            if (machine)
-            {
-                //int os = machine->getOS();
-                StringBuffer dir;
-                pDropZone->getProp("@directory", dir);
-                if (machine->getOS() == MachineOsLinux || machine->getOS() == MachineOsSolaris)
-                {         
-                    dir.replace('\\', '/');//replace all '\\' by '/'
-                    pDropZone->setProp("@linux", "true");
-                }
-                else
-                {       
-                    dir.replace('/', '\\');
-                    dir.replace('$', ':');
-                }
-                pDropZone->setProp("@directory", dir);
-            }
-        }
+        appendDropZones(clientVersion, m_constEnv, dfuwuidSourcePartIP.str(), pSoftware);
 
         //For Spray files on Thor Cluster, fetch all the group names for all the thor instances (and dedup them)
         BoolHash uniqueThorClusterGroupNames;
-        it.setown(pEnvSoftware->getElements("ThorCluster"));
+        Owned<IPropertyTreeIterator> it =pEnvSoftware->getElements("ThorCluster");
         ForEach(*it)
         {
             StringBuffer thorClusterGroupName;
@@ -370,6 +300,62 @@ IPropertyTree* CFileSpraySoapBindingEx::createPTreeForXslt(const char* method, c
     return pRoot.getClear();
 }
 
+//For every ECLWatchVisible dropzones, read: dropZoneName, directory, and, if available, computer.
+//For every Servers/Server in ECLWatchVisible dropzones, read: directory,
+// server name, and hostname(or IP). Create dropzone("@name", "@directory", "@computer",
+// "@netAddress", "@linux", "@sourceNode") tree into pSoftware.
+void CFileSpraySoapBindingEx::appendDropZones(double clientVersion, IConstEnvironment* env, const char* dfuwuidSourcePartIP, IPropertyTree* softwareTree)
+{
+    Owned<IConstDropZoneInfoIterator> dropZoneItr = env->getDropZoneIterator();
+    ForEach(*dropZoneItr)
+    {
+        IConstDropZoneInfo& dropZoneInfo = dropZoneItr->query();
+        if (!dropZoneInfo.isECLWatchVisible()) //This code is used by ECLWatch. So, skip the DZs not for ECLWatch.
+            continue;
+
+        SCMStringBuffer dropZoneName, directory, computerName;
+        dropZoneInfo.getName(dropZoneName);
+        dropZoneInfo.getDirectory(directory);
+        if (!dropZoneName.length() || !directory.length())
+            continue;
+
+        bool isLinux = getPathSepChar(directory.str()) == '/' ? true : false;
+        Owned<IConstDropZoneServerInfoIterator> dropZoneServerItr = dropZoneInfo.getServers();
+        ForEach(*dropZoneServerItr)
+        {
+            IConstDropZoneServerInfo& dropZoneServer = dropZoneServerItr->query();
+
+            StringBuffer name, server, networkAddress;
+            dropZoneServer.getName(name);
+            dropZoneServer.getServer(server);
+            if (name.isEmpty() || server.isEmpty())
+                continue;
+
+            IPropertyTree* dropZone = softwareTree->addPropTree("DropZone", createPTree());
+            dropZone->setProp("@name", dropZoneName.str());
+            dropZone->setProp("@computer", name.str());
+            dropZone->setProp("@directory", directory.str());
+            if (isLinux)
+                dropZone->setProp("@linux", "true");
+
+            IpAddress ipAddr;
+            ipAddr.ipset(server.str());
+            ipAddr.getIpText(networkAddress);
+            if (!ipAddr.isNull())
+            {
+                dropZone->addProp("@netAddress", networkAddress);
+
+                if (!isEmptyString(dfuwuidSourcePartIP))
+                {
+                    IpAddress ip(dfuwuidSourcePartIP);
+                    if (ip.ipequals(ipAddr))
+                        dropZone->addProp("@sourceNode", "1");
+                }
+            }
+        }
+    }
+}
+
 
 void CFileSpraySoapBindingEx::xsltTransform(const char* xml, const char* sheet, IProperties *params, StringBuffer& ret)
 {

+ 3 - 1
esp/services/ws_fs/ws_fsBinding.hpp

@@ -28,6 +28,7 @@
 
 #pragma warning(disable:4786)
 #include "ws_fs_esp.ipp"
+#include "environment.hpp"
 
 class CFileSpraySoapBindingEx : public CFileSpraySoapBinding
 {
@@ -72,9 +73,10 @@ public:
     int onFinishUpload(IEspContext &ctx, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method, StringArray& fileNames, StringArray& files, IMultiException *me);
 
 private:
-    IPropertyTree* createPTreeForXslt(const char* method, const char* dfuwuid);
+    IPropertyTree* createPTreeForXslt(double clientVersion, const char* method, const char* dfuwuid);
     static void xsltTransform(const char* xml, const char* sheet, IProperties *params, StringBuffer& ret);
     void downloadFile(IEspContext &ctx, CHttpRequest* request, CHttpResponse* response);
+    void appendDropZones(double clientVersion, IConstEnvironment* env, const char* dfuwuidSourcePartIP, IPropertyTree* softwareTree);
 };
 
 

+ 196 - 308
esp/services/ws_fs/ws_fsService.cpp

@@ -31,7 +31,6 @@
 #ifdef _WIN32
 #include "windows.h"
 #endif
-#include "TpWrapper.hpp"
 
 #include "dalienv.hpp"
 
@@ -2219,7 +2218,7 @@ bool CFileSprayEx::onReplicate(IEspContext &context, IEspReplicate &req, IEspRep
     return true;
 }
 
-void CFileSprayEx::getDropZoneInfoByIP(const char* ip, const char* destFileIn, StringBuffer& destFileOut, StringBuffer& mask)
+void CFileSprayEx::getDropZoneInfoByIP(double clientVersion, const char* ip, const char* destFileIn, StringBuffer& destFileOut, StringBuffer& umask)
 {
     if (destFileIn && *destFileIn)
         destFileOut.set(destFileIn);
@@ -2228,56 +2227,57 @@ void CFileSprayEx::getDropZoneInfoByIP(const char* ip, const char* destFileIn, S
         throw MakeStringExceptionDirect(ECLWATCH_INVALID_IP, "Network address must be specified for a dropzone!");
 
     Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
-    Owned<IConstEnvironment> env = factory->openEnvironment();
-    if (!env)
+    Owned<IConstEnvironment> constEnv = factory->openEnvironment();
+    if (!constEnv)
         throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Failed to get environment information.");
 
-    SCMStringBuffer directory;
-    Owned<IConstDropZoneInfo> dropZone;
-
     StringBuffer destFile;
     if (isAbsolutePath(destFileIn))
     {
         destFile.set(destFileIn);
-        dropZone.setown(env->getDropZoneByAddressPath(ip, destFile.str()));
+        Owned<IConstDropZoneInfo> dropZone = constEnv->getDropZoneByAddressPath(ip, destFile.str());
         if (!dropZone)
             throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone not found for network address %s.", ip);
+
+        SCMStringBuffer directory, maskBuf;
         dropZone->getDirectory(directory);
+        destFileOut.set(destFile.str());
+        dropZone->getUMask(maskBuf);
+        if (maskBuf.length())
+            umask.set(maskBuf.str());
+
+        return;
     }
-    else
+
+    Owned<IConstDropZoneInfoIterator> dropZoneItr = constEnv->getDropZoneIteratorByAddress(ip);
+    if (dropZoneItr->count() < 1)
+        throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone not found for network address %s.", ip);
+
+    bool dzFound = false;
+    ForEach(*dropZoneItr)
     {
-        SCMStringBuffer computer;
-        Owned<IConstMachineInfo> machine = env->getMachineByAddress(ip);
-        if (!machine)
+        IConstDropZoneInfo& dropZoneInfo = dropZoneItr->query();
+
+        SCMStringBuffer dropZoneDirectory, dropZoneUMask;
+        dropZoneInfo.getDirectory(dropZoneDirectory);
+        dropZoneInfo.getUMask(dropZoneUMask);
+        if (!dropZoneDirectory.length())
+            continue;
+
+        if (!dzFound)
         {
-            IpAddress ipAddr;
-            ipAddr.ipset(ip);
-            if (!ipAddr.isLocal())
-                throw MakeStringException(ECLWATCH_INVALID_INPUT, "Computer not found for network address %s.", ip);
-            machine.setown(env->getMachineForLocalHost());
-            if (!machine)
-                throw MakeStringException(ECLWATCH_INVALID_INPUT, "Computer not found for local host.");
-        }
-        machine->getName(computer);
-        if (!computer.length())
-            throw MakeStringException(ECLWATCH_INVALID_INPUT, "Computer name not found for network address %s.", ip);
-        dropZone.setown(env->getDropZoneByComputer(computer.str()));
-        if (!dropZone)
-            throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone not found for network address %s.", ip);
-        dropZone->getDirectory(directory);
-        destFile.set(directory.str());
-        if (destFile.length())
-            addPathSepChar(destFile);
-        destFile.append(destFileIn);
-    }
-    destFileOut.set(destFile.str());
-    if ((destFile.length() >= directory.length()) && !strnicmp(destFile.str(), directory.str(), directory.length()))
-    {
-        SCMStringBuffer maskBuf;
-        dropZone->getUMask(maskBuf);
-        if (maskBuf.length())
-            mask.set(maskBuf.str());
+            dzFound = true;
+            destFileOut.set(dropZoneDirectory.str());
+            addPathSepChar(destFileOut);
+            destFileOut.append(destFileIn);
+            if (dropZoneUMask.length())
+                umask.set(dropZoneUMask.str());
+        }
+        else
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "> 1 dropzones found for network address %s.", ip);
     }
+    if (!dzFound)
+        throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "No valid dropzone found for network address %s.", ip);
 }
 
 bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDesprayResponse &resp)
@@ -2292,6 +2292,7 @@ bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDespray
             throw MakeStringException(ECLWATCH_INVALID_INPUT, "Source logical file not specified.");
 
         PROGLOG("Despray %s", srcname);
+        double version = context.getClientVersion();
         const char* destip = req.getDestIP();
         StringBuffer fnamebuf(req.getDestPath());
         const char* destfile = fnamebuf.trim().str();
@@ -2327,7 +2328,7 @@ bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDespray
             RemoteFilename rfn;
             SocketEndpoint ep(destip);
             StringBuffer destfileWithPath, umask;
-            getDropZoneInfoByIP(destip, destfile, destfileWithPath, umask);
+            getDropZoneInfoByIP(version, destip, destfile, destfileWithPath, umask);
             rfn.setPath(ep, destfileWithPath.str());
             if (umask.length())
                 options->setUMask(umask.str());
@@ -2347,7 +2348,6 @@ bool CFileSprayEx::onDespray(IEspContext &context, IEspDespray &req, IEspDespray
         if(splitprefix && *splitprefix)
             options->setSplitPrefix(splitprefix);
 
-        double version = context.getClientVersion();
         if (version > 1.01)
         {
             if(req.getMaxConnections() > 0)
@@ -2684,86 +2684,6 @@ bool CFileSprayEx::onDFUWUFile(IEspContext &context, IEspDFUWUFileRequest &req,
     return true;
 }
 
-int CFileSprayEx::doFileCheck(const char* mask, const char* netaddr, const char* osStr, const char* path)
-{
-    int iRet = 1;
-    if (mask && *mask)
-    {
-        char *str = (char *) mask + strlen(mask) - 4;
-        if (!stricmp(str, ".cfg") || !stricmp(str, ".log"))
-            iRet = 0;
-    }
-    else    if (netaddr && *netaddr && path && *path)
-    {
-        iRet = 2;
-
-        Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
-        factory->validateCache();
-        Owned<IConstEnvironment> env = factory->openEnvironment();
-        Owned<IPropertyTree> pEnvRoot = &env->getPTree();
-        IPropertyTree* pEnvSoftware = pEnvRoot->queryPropTree("Software");
-        Owned<IPropertyTree> pRoot = createPTreeFromXMLString("<Environment/>");
-        IPropertyTree* pSoftware = pRoot->addPropTree("Software", createPTree("Software"));
-        if (pEnvSoftware && pSoftware)
-        {
-            Owned<IPropertyTreeIterator> it = pEnvSoftware->getElements("DropZone");
-            ForEach(*it)
-            {
-                const char* pszComputer = it->query().queryProp("@computer");
-                if (!strcmp(pszComputer, "."))
-                    pszComputer = "localhost";
-
-                StringBuffer xpath, sNetAddr;
-                xpath.appendf("Hardware/Computer[@name='%s']/@netAddress", pszComputer);
-                const char* pszNetAddr = pEnvRoot->queryProp(xpath.str());
-                if (strcmp(pszNetAddr, "."))
-                {
-                    sNetAddr.append(pszNetAddr);
-                }
-                else
-                {
-                    StringBuffer ipStr;
-                    IpAddress ipaddr = queryHostIP();
-                    ipaddr.getIpText(ipStr);
-                    if (ipStr.length() > 0)
-                    {
-#ifdef MACHINE_IP
-                        sNetAddr.append(MACHINE_IP);
-#else
-                        sNetAddr.append(ipStr.str());
-#endif
-                    }
-                }
-#ifdef MACHINE_IP
-                if ((sNetAddr.length() > 0) && !stricmp(sNetAddr.str(), MACHINE_IP))
-#else
-                if ((sNetAddr.length() > 0) && !stricmp(sNetAddr.str(), netaddr))
-#endif
-                {
-                    StringBuffer dir;
-                    IPropertyTree* pDropZone = pSoftware->addPropTree("DropZone", &it->get());
-                    pDropZone->getProp("@directory", dir);
-
-                    if (osStr && *osStr)
-                    {
-                        int os = atoi(osStr);
-                        const char pathSep = (os == OS_WINDOWS) ? '\\' : '/';
-                        dir.replace(pathSep=='\\'?'/':'\\', pathSep);
-                    }
-
-                    if ((dir.length() > 0) && !strnicmp(path, dir.str(), dir.length()))
-                    {
-                        iRet = 0;
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    return iRet;
-}
-
 bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IEspFileListResponse &resp)
 {
     try
@@ -2779,7 +2699,7 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
         const char* netaddr = req.getNetaddr();
         if (!netaddr || !*netaddr)
             throw MakeStringException(ECLWATCH_INVALID_INPUT, "Network address not specified.");
-        const char* mask = req.getMask();
+        const char* fileNameMask = req.getMask();
         bool directoryOnly = req.getDirectoryOnly();
         PROGLOG("FileList:  Netaddr %s, Path %s", netaddr, path);
 
@@ -2794,11 +2714,12 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
                 sPath.append( pathSep );
         }
 
-        int checkReturn = doFileCheck(mask, netaddr, osStr, sPath.str());
-        if (checkReturn > 1)
-            throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone is not found in the environment settings.");
-        else if (checkReturn > 0)
-            throw MakeStringException(ECLWATCH_ACCESS_TO_FILE_DENIED, "Access to the file path denied.");
+        if (!isEmptyString(fileNameMask))
+        {
+            const char* ext = pathExtension(sPath.str());
+            if (!strieq(ext, "cfg") && !strieq(ext, "log"))
+                throw MakeStringException(ECLWATCH_ACCESS_TO_FILE_DENIED, "Only cfg or log file allowed.");
+        }
 
         RemoteFilename rfn;
         SocketEndpoint ep;
@@ -2813,9 +2734,6 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
             throw MakeStringException(ECLWATCH_INVALID_DIRECTORY, "%s is not a directory.", path);
 
         IArrayOf<IEspPhysicalFileStruct> files;
-        if (mask && !*mask)
-            mask = NULL;
-
         Owned<IDirectoryIterator> di = f->directoryFiles(NULL, false, true);
         if(di.get() != NULL)
         {
@@ -2824,7 +2742,7 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
                 StringBuffer fname;
                 di->getName(fname);
 
-                if (fname.length() == 0 || (directoryOnly && !di->isDir()) || (!di->isDir() && mask && !WildMatch(fname.str(), mask, true)))
+                if (fname.length() == 0 || (directoryOnly && !di->isDir()) || (!di->isDir() && !isEmptyString(fileNameMask) && !WildMatch(fname.str(), fileNameMask, true)))
                     continue;
 
                 Owned<IEspPhysicalFileStruct> onefile = createPhysicalFileStruct();
@@ -2854,8 +2772,8 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
             resp.setOS(os);
         }
 
-        if (mask && *mask)
-            resp.setMask(mask);
+        if (!isEmptyString(fileNameMask))
+            resp.setMask(fileNameMask);
 
         if (version >= 1.10)
         {
@@ -2872,32 +2790,30 @@ bool CFileSprayEx::onFileList(IEspContext &context, IEspFileListRequest &req, IE
     return true;
 }
 
-void CFileSprayEx::queryDropZoneInfo(const char* dropZone, StringBuffer& path, EnvMachineOS& os, IpAddress& ip)
+bool CFileSprayEx::checkDropZoneIPAndPath(double clientVersion, const char* dropZoneName, const char* netAddr, const char* path)
 {
-    Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
-    factory->validateCache();
-
-    Owned<IConstEnvironment> env = factory->openEnvironment();
-    if (!env)
-        throw MakeStringException(ECLWATCH_CANNOT_GET_ENV_INFO,"Cannot get environment information.");
+    if (isEmptyString(netAddr) || isEmptyString(path))
+        throw MakeStringException(ECLWATCH_INVALID_INPUT, "NetworkAddress or Path not defined.");
 
-    Owned<IPropertyTree> root = &env->getPTree();
-    VStringBuffer xpath("Software/DropZone[@name='%s']", dropZone);
-    IPropertyTree *pt = root->queryPropTree(xpath.str());
-    if (!pt)
-        throw MakeStringException(ECLWATCH_INVALID_INPUT, "DropZone %s not found.", dropZone);
-
-    const char* computer = pt->queryProp("@computer");
-    IConstMachineInfo* machine = env->getMachine(computer);
-    if (!machine)
-        throw MakeStringException(ECLWATCH_INVALID_INPUT, "DropZone %s: machine %s not found.", dropZone, computer);
-
-    SCMStringBuffer netAddr;
-    machine->getNetAddress(netAddr);
-    ip.ipset(netAddr.str());
+    Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
+    Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
+    Owned<IConstDropZoneInfoIterator> dropZoneItr = constEnv->getDropZoneIteratorByAddress(netAddr);
+    ForEach(*dropZoneItr)
+    {
+        SCMStringBuffer directory, name;
+        IConstDropZoneInfo& dropZoneInfo = dropZoneItr->query();
+        dropZoneInfo.getDirectory(directory);
+        if (directory.length() && (strnicmp(path, directory.str(), directory.length()) == 0))
+        {
+            if (isEmptyString(dropZoneName))
+                return true;
 
-    os = machine->getOS();
-    pt->getProp("@directory", path);
+            dropZoneInfo.getName(name);
+            if (strieq(name.str(), dropZoneName))
+                return true;
+        }
+    }
+    return false;
 }
 
 void CFileSprayEx::addDropZoneFile(IEspContext& context, IDirectoryIterator* di, const char* name, const char* dropZonePath,
@@ -2967,6 +2883,21 @@ bool CFileSprayEx::searchDropZoneFileInFolder(IEspContext& context, IFile* f, co
     return foundMatch;
 }
 
+void CFileSprayEx::appendDropZoneFiles(IEspContext& context, IpAddress& ip, const char* dir, const char* nameFilter, IArrayOf<IEspPhysicalFileStruct>& files)
+{
+    RemoteFilename rfn;
+    SocketEndpoint ep;
+    ep.ipset(ip);
+    rfn.setPath(ep, dir);
+    Owned<IFile> f = createIFile(rfn);
+    if(!f->isDirectory())
+        throw MakeStringException(ECLWATCH_INVALID_DIRECTORY, "%s is not a directory.", dir);
+
+    StringBuffer relativePath;
+    searchDropZoneFileInFolder(context, f, nameFilter, !nameFilter || !*nameFilter, dir,
+        relativePath, getPathSepChar(dir), files);
+}
+
 bool CFileSprayEx::onDropZoneFileSearch(IEspContext &context, IEspDropZoneFileSearchRequest &req, IEspDropZoneFileSearchResponse &resp)
 {
     try
@@ -2974,28 +2905,45 @@ bool CFileSprayEx::onDropZoneFileSearch(IEspContext &context, IEspDropZoneFileSe
         if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Access, false))
             throw MakeStringException(ECLWATCH_FILE_SPRAY_ACCESS_DENIED, "Failed to do FileList. Permission denied.");
 
-        const char* dropZone = req.getDropZoneName();
-        if (!dropZone || !*dropZone)
+        const char* dropZoneName = req.getDropZoneName();
+        if (isEmptyString(dropZoneName))
             throw MakeStringException(ECLWATCH_INVALID_INPUT, "DropZone not specified.");
-        PROGLOG("DropZoneFileSearch: %s", dropZone);
 
-        IpAddress ip;
-        EnvMachineOS os;
-        StringBuffer path, relativePath;
-        queryDropZoneInfo(dropZone, path, os, ip);
+        Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
+        Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
+        Owned<IConstDropZoneInfo> dropZoneInfo = constEnv->getDropZone(dropZoneName);
+        if (!dropZoneInfo || (req.getECLWatchVisibleOnly() && !dropZoneInfo->isECLWatchVisible()))
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "DropZone %s not found.", dropZoneName);
 
-        RemoteFilename rfn;
-        SocketEndpoint ep;
-        ep.ipset(ip);
-        rfn.setPath(ep, path);
-        Owned<IFile> f = createIFile(rfn);
-        if(!f->isDirectory())
-            throw MakeStringException(ECLWATCH_INVALID_DIRECTORY, "%s is not a directory.", path.str());
+        SCMStringBuffer directory, computer;
+        dropZoneInfo->getDirectory(directory);
+        if (!directory.length())
+            throw MakeStringException(ECLWATCH_INVALID_INPUT, "DropZone Directory not found for %s.", dropZoneName);
+
+        IpAddress ipToMatch;
+        const char* dropZoneServerReq = req.getServer(); //IP or hostname
+        if (!isEmptyString(dropZoneServerReq))
+        {
+            ipToMatch.ipset(dropZoneServerReq);
+            if (ipToMatch.isNull())
+                throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid server %s specified.", dropZoneServerReq);
+        }
 
         IArrayOf<IEspPhysicalFileStruct> files;
-        const char* nameFilter = req.getNameFilter();
-        searchDropZoneFileInFolder(context, f, nameFilter, !nameFilter || !*nameFilter, path.str(),
-            relativePath, (os == MachineOsW2K) ? '\\' : '/', files);
+        Owned<IConstDropZoneServerInfoIterator> dropZoneServerItr = dropZoneInfo->getServers();
+        ForEach(*dropZoneServerItr)
+        {
+            StringBuffer server, networkAddress;
+            IConstDropZoneServerInfo& dropZoneServer = dropZoneServerItr->query();
+            dropZoneServer.getServer(server);
+            if (server.isEmpty())
+                throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid server for dropzone %s.", dropZoneName);
+
+            IpAddress ipAddr;
+            ipAddr.ipset(server.str());
+            if (isEmptyString(dropZoneServerReq) || ipAddr.ipequals(ipToMatch))
+                appendDropZoneFiles(context, ipAddr, directory.str(), req.getNameFilter(), files);
+        }
         resp.setFiles(files);
     }
     catch(IException* e)
@@ -3097,16 +3045,13 @@ bool CFileSprayEx::onOpenSave(IEspContext &context, IEspOpenSaveRequest &req, IE
     return true;
 }
 
-bool CFileSprayEx::getDropZoneFiles(IEspContext &context, const char* netaddr, const char* osStr, const char* path,
+bool CFileSprayEx::getDropZoneFiles(IEspContext &context, const char* dropZone, const char* netaddr, const char* path,
                                     IEspDropZoneFilesRequest &req, IEspDropZoneFilesResponse &resp)
 {
-    bool directoryOnly = req.getDirectoryOnly();
-
-    int checkReturn = doFileCheck(NULL, netaddr, osStr, path);
-    if (checkReturn > 1)
+    if (!checkDropZoneIPAndPath(context.getClientVersion(), dropZone, netaddr, path))
         throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone is not found in the environment settings.");
-    else if (checkReturn > 0)
-        throw MakeStringException(ECLWATCH_ACCESS_TO_FILE_DENIED, "Access to the file path denied.");
+
+    bool directoryOnly = req.getDirectoryOnly();
 
     RemoteFilename rfn;
     SocketEndpoint ep;
@@ -3155,6 +3100,7 @@ bool CFileSprayEx::getDropZoneFiles(IEspContext &context, const char* netaddr, c
     return true;
 }
 
+//This method returns all dropzones and, if NetAddress and Path specified, returns filtered list of files.
 bool CFileSprayEx::onDropZoneFiles(IEspContext &context, IEspDropZoneFilesRequest &req, IEspDropZoneFilesResponse &resp)
 {
     try
@@ -3162,97 +3108,60 @@ bool CFileSprayEx::onDropZoneFiles(IEspContext &context, IEspDropZoneFilesReques
         if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Read, false))
             throw MakeStringException(ECLWATCH_FILE_SPRAY_ACCESS_DENIED, "Permission denied.");
 
+        IpAddress ipToMatch;
         const char* netAddress = req.getNetAddress();
-        const char* directory = req.getPath();
-        const char* subfolder = req.getSubfolder();
-
-        StringBuffer netAddressStr, directoryStr, osStr;
-        if (netAddress && *netAddress && directory && *directory)
+        if (!isEmptyString(netAddress))
         {
-            netAddressStr.append(netAddress);
-            directoryStr.append(directory);
+            ipToMatch.ipset(netAddress);
+            if (ipToMatch.isNull())
+                throw MakeStringException(ECLWATCH_INVALID_INPUT, "Invalid server %s specified.", netAddress);
         }
 
+        bool filesFromALinux = false;
         IArrayOf<IEspDropZone> dropZoneList;
-
-        Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
-        Owned<IConstEnvironment> m_constEnv = factory->openEnvironment();
-        Owned<IPropertyTree> pEnvRoot = &m_constEnv->getPTree();
-        IPropertyTree* pEnvSoftware = pEnvRoot->queryPropTree("Software");
-        if (pEnvSoftware)
+        bool ECLWatchVisibleOnly = req.getECLWatchVisibleOnly();
+        Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
+        Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
+        Owned<IConstDropZoneInfoIterator> dropZoneItr = constEnv->getDropZoneIterator();
+        ForEach(*dropZoneItr)
         {
-            Owned<IPropertyTreeIterator> it = pEnvSoftware->getElements("DropZone");
-            ForEach(*it)
-            {
-                IPropertyTree& pDropZone = it->query();
-                if (!pDropZone.getPropBool("@ECLWatchVisible", true))
-                    continue;
-
-                //get IP Address of the computer associated with this drop zone
-                const char* pszName = pDropZone.queryProp("@name");
-                const char* pszComputer = pDropZone.queryProp("@computer");
-                if (!strcmp(pszComputer, "."))
-                    pszComputer = "localhost";
-
-                StringBuffer xpath;
-                xpath.appendf("Hardware/Computer[@name='%s']/@netAddress", pszComputer);
+            IConstDropZoneInfo& dropZoneInfo = dropZoneItr->query();
+            if (ECLWatchVisibleOnly && !dropZoneInfo.isECLWatchVisible())
+                continue;
 
-                StringBuffer sNetAddr;
-                const char* pszNetAddr = pEnvRoot->queryProp(xpath.str());
-                if (strcmp(pszNetAddr, "."))
-                {
-                    sNetAddr.append(pszNetAddr);
-                }
-                else
-                {
-                    StringBuffer ipStr;
-                    IpAddress ipaddr = queryHostIP();
-                    ipaddr.getIpText(ipStr);
-                    if (ipStr.length() > 0)
-                    {
-#ifdef MACHINE_IP
-                        sNetAddr.append(MACHINE_IP);
-#else
-                        sNetAddr.append(ipStr.str());
-#endif
-                    }
-                }
+            SCMStringBuffer dropZoneName, directory, computerName;
+            dropZoneInfo.getName(dropZoneName);
+            dropZoneInfo.getDirectory(directory);
+            dropZoneInfo.getComputerName(computerName); //legacy env
+            if (!dropZoneName.length() || !directory.length())
+                continue;
 
-                Owned<IConstMachineInfo> machine;
-                if (strcmp(pszNetAddr, "."))
-                    machine.setown(m_constEnv->getMachineByAddress(sNetAddr.str()));
-                else
-                {
-                    machine.setown(m_constEnv->getMachineByAddress(pszNetAddr));
-                    if (!machine)
-                        machine.setown(m_constEnv->getMachineByAddress(sNetAddr.str()));
-                }
+            bool isLinux = getPathSepChar(directory.str()) == '/' ? true : false;
+            Owned<IConstDropZoneServerInfoIterator> dropZoneServerItr = dropZoneInfo.getServers();
+            ForEach(*dropZoneServerItr)
+            {
+                IConstDropZoneServerInfo& dropZoneServer = dropZoneServerItr->query();
 
-                StringBuffer dir;
-                pDropZone.getProp("@directory", dir);
+                StringBuffer name, server, networkAddress;
+                dropZoneServer.getName(name);
+                dropZoneServer.getServer(server);
+                if (name.isEmpty() || server.isEmpty())
+                    continue;
 
-                Owned<IEspDropZone> aDropZone= createDropZone("","");
+                IpAddress ipAddr;
+                ipAddr.ipset(server.str());
+                ipAddr.getIpText(networkAddress);
 
-                if (machine)
-                {
-                    if (machine->getOS() == MachineOsLinux || machine->getOS() == MachineOsSolaris)
-                    {
-                        dir.replace('\\', '/');//replace all '\\' by '/'
-                        aDropZone->setLinux("true");
-                        osStr = "1";
-                    }
-                    else
-                    {
-                        dir.replace('/', '\\');
-                        dir.replace('$', ':');
-                        osStr = "0";
-                    }
-                }
+                Owned<IEspDropZone> aDropZone = createDropZone();
+                aDropZone->setName(dropZoneName.str());
+                aDropZone->setComputer(name.str());
+                aDropZone->setNetAddress(networkAddress.str());
 
-                aDropZone->setComputer(pszComputer);
-                aDropZone->setPath(dir.str());
-                aDropZone->setName(pszName);
-                aDropZone->setNetAddress(sNetAddr.str());
+                aDropZone->setPath(directory.str());
+                if (isLinux)
+                    aDropZone->setLinux("true");
+                if (!isEmptyString(netAddress) && ipAddr.ipequals(ipToMatch))
+                    filesFromALinux = isLinux;
 
                 dropZoneList.append(*aDropZone.getClear());
             }
@@ -3261,39 +3170,32 @@ bool CFileSprayEx::onDropZoneFiles(IEspContext &context, IEspDropZoneFilesReques
         if (dropZoneList.ordinality())
             resp.setDropZones(dropZoneList);
 
-        if (netAddressStr.length() < 1)
-            return true;
-
-        char pathSep = '/';
-        if (osStr && *osStr)
-        {
-            int os = atoi(osStr);
-            if (os == OS_WINDOWS)
-                pathSep = '\\';
-        }
+        const char* dzName = req.getDropZoneName();
+        const char* directory = req.getPath();
+        const char* subfolder = req.getSubfolder();
 
-        directoryStr.replace(pathSep=='\\'?'/':'\\', pathSep);
+        if (isEmptyString(netAddress) || (isEmptyString(directory) && isEmptyString(subfolder)))
+            return true;
 
-        if (subfolder && *subfolder)
+        StringBuffer netAddressStr, directoryStr, osStr;
+        netAddressStr.set(netAddress);
+        if (!isEmptyString(directory))
+            directoryStr.set(directory);
+        if (!isEmptyString(subfolder))
         {
-            if (*(directoryStr.str() + directoryStr.length() -1) != pathSep)
-                directoryStr.append( pathSep );
-
+            if (directoryStr.length())
+                addPathSepChar(directoryStr);
             directoryStr.append(subfolder);
         }
+        addPathSepChar(directoryStr);
 
-        if (*(directoryStr.str() + directoryStr.length() -1) != pathSep)
-            directoryStr.append( pathSep );
+        getDropZoneFiles(context, dzName, netAddress, directoryStr.str(), req, resp);
 
-        PROGLOG("getDropZoneFiles: netAddress %s, path %s", netAddressStr.str(), directoryStr.str());
-        getDropZoneFiles(context, netAddressStr.str(), osStr.str(), directoryStr.str(), req, resp);
-
-        if (pathSep=='\\')
-            directoryStr.replaceString("\\", "\\\\");
-
-        resp.setNetAddress(netAddressStr.str());
+        resp.setDropZoneName(dzName);
+        resp.setNetAddress(netAddress);
         resp.setPath(directoryStr.str());
-        resp.setOS(atoi(osStr.str()));
+        resp.setOS(filesFromALinux);
+        resp.setECLWatchVisibleOnly(ECLWatchVisibleOnly);
     }
     catch(IException* e)
     {
@@ -3310,43 +3212,31 @@ bool CFileSprayEx::onDeleteDropZoneFiles(IEspContext &context, IEspDeleteDropZon
         if (!context.validateFeatureAccess(FILE_SPRAY_URL, SecAccess_Full, false))
             throw MakeStringException(ECLWATCH_FILE_SPRAY_ACCESS_DENIED, "Permission denied.");
 
+        double version = context.getClientVersion();
+        const char* dzName = req.getDropZoneName();
         const char* netAddress = req.getNetAddress();
         const char* directory = req.getPath();
         const char* osStr = req.getOS();
         StringArray & files = req.getNames();
-
-        if (!netAddress || !*netAddress || !directory || !*directory)
-            throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone not specified.");
-
         if (!files.ordinality())
             throw MakeStringException(ECLWATCH_INVALID_INPUT, "File not specified.");
 
-        char pathSep = '/';
-        StringBuffer sPath(directory);
-        if (osStr && *osStr)
+        StringBuffer path(directory);
+        if (!isEmptyString(osStr))
         {
-            int os = atoi(osStr);
-            pathSep = (os == OS_WINDOWS) ? '\\' : '/';
-            sPath.replace(pathSep=='\\'?'/':'\\', pathSep);
-            if (*(sPath.str() + sPath.length() -1) != pathSep)
-                sPath.append( pathSep );
+            char pathSep = (atoi(osStr) == OS_WINDOWS) ? '\\' : '/';
+            path.replace(pathSep=='\\' ? '/' : '\\', pathSep);
         }
+        addPathSepChar(path, getPathSepChar(path.str()));
 
-        int checkReturn = doFileCheck(NULL, netAddress, osStr, sPath.str());
-        if (checkReturn > 1)
+        if (!checkDropZoneIPAndPath(version, dzName, netAddress, path.str()))
             throw MakeStringException(ECLWATCH_DROP_ZONE_NOT_FOUND, "Dropzone is not found in the environment settings.");
-        else if (checkReturn > 0)
-            throw MakeStringException(ECLWATCH_ACCESS_TO_FILE_DENIED, "Access to the file path denied.");
 
         RemoteFilename rfn;
         SocketEndpoint ep;
-#ifdef MACHINE_IP
-        ep.set(MACHINE_IP);
-#else
         ep.set(netAddress);
-#endif
 
-        rfn.setPath(ep, sPath.str());
+        rfn.setPath(ep, path.str());
         Owned<IFile> f = createIFile(rfn);
         if(!f->isDirectory())
             throw MakeStringException(ECLWATCH_INVALID_DIRECTORY, "%s is not a directory.", directory);
@@ -3368,9 +3258,7 @@ bool CFileSprayEx::onDeleteDropZoneFiles(IEspContext &context, IEspDeleteDropZon
 
             try
             {
-                StringBuffer fileToDelete = sPath;
-                if (*(fileToDelete.str() + fileToDelete.length() -1) != pathSep)
-                    fileToDelete.append( pathSep );
+                StringBuffer fileToDelete = path;
                 fileToDelete.append(file);
 
                 rfn.setPath(ep, fileToDelete.str());

+ 5 - 4
esp/services/ws_fs/ws_fsService.hpp

@@ -23,6 +23,7 @@
 #include "jthread.hpp"
 #include "dfuwu.hpp"
 #include "environment.hpp"
+#include "TpWrapper.hpp"
 
 class Schedule : public Thread
 {
@@ -107,24 +108,24 @@ protected:
     Owned<IPropertyTree> directories;
 
     void addToQueryString(StringBuffer &queryString, const char *name, const char *value);
-    int doFileCheck(const char* mask, const char* netaddr, const char* osStr, const char* path);
     void getInfoFromSasha(IEspContext &context, const char *sashaServer, const char* wuid, IEspDFUWorkunit *info);
     bool getArchivedWUInfo(IEspContext &context, IEspGetDFUWorkunit &req, IEspGetDFUWorkunitResponse &resp);
     bool GetArchivedDFUWorkunits(IEspContext &context, IEspGetDFUWorkunits &req, IEspGetDFUWorkunitsResponse &resp);
-    bool getDropZoneFiles(IEspContext &context, const char* netaddr, const char* osStr, const char* path, IEspDropZoneFilesRequest &req, IEspDropZoneFilesResponse &resp);
+    bool getDropZoneFiles(IEspContext &context, const char* dropZone, const char* netaddr, const char* path, IEspDropZoneFilesRequest &req, IEspDropZoneFilesResponse &resp);
     bool ParseLogicalPath(const char * pLogicalPath, StringBuffer &title);
     bool ParseLogicalPath(const char * pLogicalPath, const char *group, const char* cluster, StringBuffer &folder, StringBuffer &title, StringBuffer &defaultFolder, StringBuffer &defaultReplicateFolder);
     StringBuffer& getAcceptLanguage(IEspContext& context, StringBuffer& acceptLanguage);
     void appendGroupNode(IArrayOf<IEspGroupNode>& groupNodes, const char* nodeName, const char* clusterType, bool replicateOutputs);
     bool getOneDFUWorkunit(IEspContext& context, const char* wuid, IEspGetDFUWorkunitsResponse& resp);
-    void getDropZoneInfoByIP(const char* destIP, const char* destFile, StringBuffer& path, StringBuffer& mask);
-    void queryDropZoneInfo(const char* dropZone, StringBuffer& path, EnvMachineOS& os, IpAddress& ip);
+    void getDropZoneInfoByIP(double clientVersion, const char* destIP, const char* destFile, StringBuffer& path, StringBuffer& mask);
+    bool checkDropZoneIPAndPath(double clientVersion, const char* dropZone, const char* netAddr, const char* path);
     void addDropZoneFile(IEspContext& context, IDirectoryIterator* di, const char* name, const char* dropZonePath, StringBuffer& relativePath,
         const char pathSep, IArrayOf<IEspPhysicalFileStruct>& filesInFolder, IArrayOf<IEspPhysicalFileStruct>&files);
     bool searchDropZoneFileInFolder(IEspContext& context, IFile* f, const char* nameFilter, bool returnAll,
         const char* dropZonePath, StringBuffer& relativePath, const char pathSep, IArrayOf<IEspPhysicalFileStruct>& files);
     void setDFUServerQueueReq(const char* dfuServerQueue, IDFUWorkUnit* wu);
     void setUserAuth(IEspContext &context, IDFUWorkUnit* wu);
+    void appendDropZoneFiles(IEspContext& context, IpAddress& ip, const char* dir, const char* nameFilter, IArrayOf<IEspPhysicalFileStruct>& files);
 };
 
 #endif //_ESPWIZ_FileSpray_HPP__

+ 17 - 1
esp/services/ws_topology/ws_topologyService.cpp

@@ -1287,7 +1287,7 @@ bool CWsTopologyEx::onTpServiceQuery(IEspContext &context, IEspTpServiceQueryReq
             m_TpWrapper.getTpSashaServers( ServiceList.getTpSashaServers() );   
             m_TpWrapper.getTpGenesisServers( ServiceList.getTpGenesisServers() );
             m_TpWrapper.getTpLdapServers( ServiceList.getTpLdapServers() );
-            m_TpWrapper.getTpDropZones( ServiceList.getTpDropZones() );
+            m_TpWrapper.getTpDropZones(version, nullptr, true, ServiceList.getTpDropZones() );
             m_TpWrapper.getTpFTSlaves( ServiceList.getTpFTSlaves() );
             m_TpWrapper.getTpDkcSlaves( ServiceList.getTpDkcSlaves() );
 
@@ -1773,5 +1773,21 @@ bool CWsTopologyEx::onTpGetServicePlugins(IEspContext &context, IEspTpGetService
     {
         FORWARDEXCEPTION(context, e,  ECLWATCH_INTERNAL_ERROR);
     }
+    return true;
+}
+
+bool CWsTopologyEx::onTpDropZoneQuery(IEspContext &context, IEspTpDropZoneQueryRequest &req, IEspTpDropZoneQueryResponse &resp)
+{
+    try
+    {
+        if (!context.validateFeatureAccess(FEATURE_URL, SecAccess_Read, false))
+            throw MakeStringException(ECLWATCH_TOPOLOGY_ACCESS_DENIED, "Failed to do Machine Query. Permission denied.");
+
+        m_TpWrapper.getTpDropZones(context.getClientVersion(), req.getName(), req.getECLWatchVisibleOnly(), resp.getTpDropZones());
+    }
+    catch(IException* e)
+    {
+        FORWARDEXCEPTION(context, e,  ECLWATCH_INTERNAL_ERROR);
+    }
     return false;
 }

+ 2 - 0
esp/services/ws_topology/ws_topologyService.hpp

@@ -134,6 +134,8 @@ public:
 
     bool onTpMachineInfo(IEspContext &context, IEspTpMachineInfoRequest &req, IEspTpMachineInfoResponse &resp);
 
+    bool onTpDropZoneQuery(IEspContext &context, IEspTpDropZoneQueryRequest &req, IEspTpDropZoneQueryResponse &resp);
+
     bool onTpSetMachineStatus(IEspContext &context,IEspTpSetMachineStatusRequest  &req, IEspTpSetMachineStatusResponse &resp);
 
     bool onTpSwapNode(IEspContext &context,IEspTpSwapNodeRequest  &req, IEspTpSwapNodeResponse &resp);

+ 146 - 94
esp/smc/SMCLib/TpWrapper.cpp

@@ -132,7 +132,7 @@ void CTpWrapper::getClusterMachineList(double clientVersion,
         }
         else if (strcmp("DROPZONE",ClusterType) == 0)
         {
-            getDropZoneList(eqDropZone,"/Environment/Software", ClusterDirectory, MachineList);
+            getDropZoneMachineList(clientVersion, false, MachineList);
         }
         else if (strcmp("STANDBYNNODE",ClusterType) == 0)
         {
@@ -595,61 +595,6 @@ void CTpWrapper::getTpLdapServers(IArrayOf<IConstTpLdapServer>& list)
     }
 }
 
-void CTpWrapper::getTpDropZones(IArrayOf<IConstTpDropZone>& list)
-{
-    Owned<IPropertyTree> root = getEnvironment("Software");
-    if (!root)
-        throw MakeStringExceptionDirect(ECLWATCH_CANNOT_GET_ENV_INFO, MSG_FAILED_GET_ENVIRONMENT_INFO);
-
-    Owned<IEnvironmentFactory> factory = getEnvironmentFactory();
-    Owned<IConstEnvironment> m_pConstEnvironment = factory->openEnvironment();
-
-    Owned<IPropertyTreeIterator> services= root->getElements(eqDropZone);
-    ForEach(*services)
-    {
-        IPropertyTree& serviceTree = services->query();
-        if (!serviceTree.getPropBool("@ECLWatchVisible", true))
-            continue;
-
-        Owned<IEspTpDropZone> pService = createTpDropZone("","");
-        pService->setName(serviceTree.queryProp("@name"));
-        pService->setDescription(serviceTree.queryProp("@description"));
-        pService->setBuild(serviceTree.queryProp("@build"));
-
-        const char* directory = serviceTree.queryProp("@directory");
-
-        IArrayOf<IEspTpMachine> tpMachines;
-        const char* computer = serviceTree.queryProp("@computer");
-        if (computer && *computer)
-        {
-              StringBuffer computerName;
-              if (strcmp(computer, "."))
-                  computerName.append(computer);
-              else
-                    computerName.append("localhost");
-
-              Owned<IEspTpMachine> machine = createTpMachine("", "");
-
-            setMachineInfo(computerName, "DropZone", *machine);
-            StringBuffer tmpPath;
-            StringBuffer ppath("/Environment/Software");
-            setAttPath(ppath, "", "name", computerName, tmpPath);
-            machine->setPath(tmpPath.str());
-
-           if (directory && *directory)
-              machine->setDirectory(directory);
-
-              Owned<IConstMachineInfo> pMachineInfo =  m_pConstEnvironment->getMachine(computerName.str());
-              machine->setOS(pMachineInfo->getOS());
-
-           tpMachines.append(*machine.getLink());
-        }
-        pService->setTpMachines(tpMachines);
-
-        list.append(*pService.getLink());
-    }
-}
-
 void CTpWrapper::getTpFTSlaves(IArrayOf<IConstTpFTSlave>& list)
 {
     Owned<IPropertyTree> root = getEnvironment("Software");
@@ -1667,56 +1612,162 @@ const char* CTpWrapper::getNodeNameTag(const char* MachineType)
         return "@computer";
 }
 
-void CTpWrapper::getDropZoneList(const char* MachineType,
-                                            const char* ParentPath,
-                                            const char* Directory,
-                                            IArrayOf<IEspTpMachine> &MachineList)
+void CTpWrapper::getDropZoneMachineList(double clientVersion, bool ECLWatchVisibleOnly, IArrayOf<IEspTpMachine> &MachineList)
 {
     try
     {
-        Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
-        Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
-        Owned<IPropertyTree> root0 = &constEnv->getPTree();
-        if (!root0)
-            throw MakeStringExceptionDirect(ECLWATCH_CANNOT_GET_ENV_INFO, MSG_FAILED_GET_ENVIRONMENT_INFO);
+        IArrayOf<IConstTpDropZone> list;
+        getTpDropZones(clientVersion, nullptr, ECLWatchVisibleOnly, list);
+        ForEachItemIn(i, list)
+        {
+            IConstTpDropZone& dropZone = list.item(i);
+
+            IArrayOf<IConstTpMachine>& tpMachines = dropZone.getTpMachines();
+            ForEachItemIn(ii, tpMachines)
+            {
+                IConstTpMachine& tpMachine = tpMachines.item(ii);
+                Owned<IEspTpMachine> machine = createTpMachine();
+                machine->copy(tpMachine);
+
+                MachineList.append(*machine.getLink());
+            }
+        }
+    }
+    catch(IException* e)
+    {
+        EXCLOG(e);
+        e->Release();
+    }
+    catch(...)
+    {
+        WARNLOG("Unknown Exception caught within CTpWrapper::getDropZoneMachineList");
+    }
     
-        char* xpath = (char*)ParentPath;
-        if (!strnicmp(xpath, "/Environment/", 13))
-            xpath += 13;
+}
 
-        IPropertyTree* root = root0->queryPropTree( xpath );
-        if (!root)
-            throw MakeStringExceptionDirect(ECLWATCH_CANNOT_GET_ENV_INFO, MSG_FAILED_GET_ENVIRONMENT_INFO);
+//For a given dropzone or every dropzones (check ECLWatchVisible if needed), read: "@name",
+// "@description", "@build", "@directory", "@ECLWatchVisible" into an IEspTpDropZone object.
+//For each ServerList, read "@name" and "@server" (hostname or IP) into an IEspTpMachine object.
+//Add the IEspTpMachine object into the IEspTpDropZone.
 
-        Owned<IPropertyTreeIterator> nodes=  root->getElements(eqDropZone);
-        if (nodes->first()) {
-            do {
+void CTpWrapper::getTpDropZones(double clientVersion, const char* name, bool ECLWatchVisibleOnly, IArrayOf<IConstTpDropZone>& list)
+{
+    Owned<IEnvironmentFactory> envFactory = getEnvironmentFactory();
+    Owned<IConstEnvironment> constEnv = envFactory->openEnvironment();
+    if (!isEmptyString(name))
+    {
+        Owned<IConstDropZoneInfo> pDropZoneInfo = constEnv->getDropZone(name);
+        if (pDropZoneInfo && (!ECLWatchVisibleOnly || pDropZoneInfo->isECLWatchVisible()))
+            appendTpDropZone(clientVersion, constEnv, *pDropZoneInfo, list);
+    }
+    else
+    {
+        Owned<IConstDropZoneInfoIterator> it = constEnv->getDropZoneIterator();
+        ForEach(*it)
+        {
+            IConstDropZoneInfo& dropZoneInfo = it->query();
+            if (!ECLWatchVisibleOnly || dropZoneInfo.isECLWatchVisible())
+                appendTpDropZone(clientVersion, constEnv, dropZoneInfo, list);
+        }
+    }
+}
 
-                IPropertyTree &machine = nodes->query();
-            
-                IEspTpMachine & machineInfo = *(createTpMachine("",""));
-                const char* name = machine.queryProp("@computer");
-                StringBuffer ppath(ParentPath);
-                StringBuffer tmpPath;
-                setAttPath(ppath,machine.queryName(),"name",name,tmpPath);
-                machineInfo.setPath(tmpPath.str());
-                setMachineInfo(name,MachineType,machineInfo);
-                machineInfo.setDirectory(machine.queryProp("@directory"));
-                MachineList.append(machineInfo);
 
-            } while (nodes->next());
+void CTpWrapper::appendTpDropZone(double clientVersion, IConstEnvironment* constEnv, IConstDropZoneInfo& dropZoneInfo, IArrayOf<IConstTpDropZone>& list)
+{
+    SCMStringBuffer dropZoneName, description, directory, umask, build, computer;
+    dropZoneInfo.getName(dropZoneName);
+    dropZoneInfo.getDescription(description);
+    dropZoneInfo.getDirectory(directory);
+    dropZoneInfo.getUMask(umask);
+    dropZoneInfo.getComputerName(computer);
+
+    Owned<IEspTpDropZone> dropZone = createTpDropZone();
+    if (dropZoneName.length() > 0)
+        dropZone->setName(dropZoneName.str());
+    if (description.length() > 0)
+        dropZone->setDescription(description.str());
+    if (directory.length() > 0)
+        dropZone->setPath(directory.str());
+    if (build.length() > 0)
+        dropZone->setBuild(build.str());
+    dropZone->setECLWatchVisible(dropZoneInfo.isECLWatchVisible());
+
+    IArrayOf<IEspTpMachine> tpMachines;
+    Owned<IConstDropZoneServerInfoIterator> itr = dropZoneInfo.getServers();
+    ForEach(*itr)
+    {
+        IConstDropZoneServerInfo& dropZoneServer = itr->query();
+
+        StringBuffer name, server, networkAddress;
+        dropZoneServer.getName(name);
+        dropZoneServer.getServer(server);
+        if (name.isEmpty() && server.isEmpty())
+            continue;
+
+        Owned<IEspTpMachine> machine = createTpMachine();
+        if (!name.isEmpty())
+            machine->setName(name.str());
+        if (!server.isEmpty())
+        {
+            IpAddress ipAddr;
+            ipAddr.ipset(server.str());
+            ipAddr.getIpText(networkAddress);
+            machine->setNetaddress(networkAddress.str());
         }
+        if (directory.length() > 0)
+        {
+            machine->setDirectory(directory.str());
+            machine->setOS(getPathSepChar(directory.str()) == '/' ? MachineOsLinux : MachineOsW2K);
+        }
+        tpMachines.append(*machine.getLink());
     }
-    catch(IException* e){   
-        StringBuffer msg;
-        e->errorMessage(msg);
-        WARNLOG("%s", msg.str());
-        e->Release();
+    dropZone->setTpMachines(tpMachines);
+
+    list.append(*dropZone.getLink());
+}
+
+IEspTpMachine* CTpWrapper::createTpMachineEx(const char* name, const char* type, IConstMachineInfo* machineInfo)
+{
+    if (!machineInfo)
+        return nullptr;
+
+    Owned<IEspTpMachine> machine = createTpMachine();
+    machine->setName(name);
+    machine->setType(type);
+    machine->setOS(machineInfo->getOS());
+
+    Owned<IConstDomainInfo> domain = machineInfo->getDomain();
+    if (domain)
+    {
+        SCMStringBuffer sName;
+        machine->setDomain(domain->getName(sName).str());
     }
-    catch(...){
-        WARNLOG("Unknown Exception caught within CTpWrapper::getDropZoneList");
+
+    SCMStringBuffer netAddr;
+    machineInfo->getNetAddress(netAddr);
+    if (netAddr.length() > 0)
+    {
+        StringBuffer networkAddress;
+        IpAddress ipAddr;
+        ipAddr.ipset(netAddr.str());
+        ipAddr.getIpText(networkAddress);
+        machine->setNetaddress(networkAddress.str());
     }
-    
+
+    switch(machineInfo->getState())
+    {
+        case MachineStateAvailable:
+            machine->setAvailable("Available");
+            break;
+        case MachineStateUnavailable:
+            machine->setAvailable("Unavailable");
+            break;
+        default:
+            machine->setAvailable("Unknown");
+            break;
+    }
+    return machine.getClear();
 }
 
 void CTpWrapper::setMachineInfo(const char* name,const char* type,IEspTpMachine& machine)
@@ -1808,3 +1859,4 @@ void CTpWrapper::getAttPath(const char* Path,StringBuffer& returnStr)
     StringBuffer decodedStr;
     JBASE64_Decode(Path, returnStr);
 }
+

+ 4 - 2
esp/smc/SMCLib/TpWrapper.hpp

@@ -134,6 +134,7 @@ private:
     const char* getNodeNameTag(const char* MachineType);
     void fetchInstances(const char* ServiceType, IPropertyTree& service, IArrayOf<IEspTpMachine>& tpMachines);
     bool checkGroupReplicateOutputs(const char* groupName, const char* kind);
+    void appendTpDropZone(double clientVersion, IConstEnvironment* constEnv, IConstDropZoneInfo& dropZoneInfo, IArrayOf<IConstTpDropZone>& list);
 
 public:
     IMPLEMENT_IINTERFACE;
@@ -155,12 +156,13 @@ public:
                         set<string>* pMachineNames=NULL);
     void getMachineList(double clientVersion, const char* clusterName, const char* MachineType, const char* ParentPath, const char* Status,
                                 const char* Directory, bool& multiSlaves, IArrayOf<IEspTpMachine> &MachineList);
-    void getDropZoneList(const char* MachineType, const char* MachinePath, const char* Directory, IArrayOf<IEspTpMachine> &MachineList);
+    void getDropZoneMachineList(double clientVersion, bool ECLWatchVisibleOnly, IArrayOf<IEspTpMachine> &MachineList);
     void setMachineInfo(const char* name,const char* type,IEspTpMachine& machine);
     void resolveGroupInfo(const char* groupName,StringBuffer& Cluster, StringBuffer& ClusterPrefix);
     void getMachineInfo(IEspTpMachine& machineInfo,IPropertyTree& machine,const char* ParentPath,const char* MachineType,const char* nodenametag);
     void getMachineInfo(double clientVersion, const char* name, const char* netAddress, IEspTpMachine& machineInfo);
     void setTpMachine(IConstMachineInfo* machine, IEspTpMachine& tpMachine);
+    IEspTpMachine* createTpMachineEx(const char* name, const char* type, IConstMachineInfo* machineInfo);
 
     void getTpDaliServers(IArrayOf<IConstTpDali>& list);
     void getTpEclServers(IArrayOf<IConstTpEclServer>& ServiceList, const char* name = NULL);
@@ -172,7 +174,7 @@ public:
     void getTpDfuServers(IArrayOf<IConstTpDfuServer>& list);
     void getTpSashaServers(IArrayOf<IConstTpSashaServer>& list);
     void getTpLdapServers(IArrayOf<IConstTpLdapServer>& list);
-    void getTpDropZones(IArrayOf<IConstTpDropZone>& list);
+    void getTpDropZones(double clientVersion, const char* name, bool ECLWatchVisibleOnly, IArrayOf<IConstTpDropZone>& list);
     void getTpFTSlaves(IArrayOf<IConstTpFTSlave>& list);
     void getTpDkcSlaves(IArrayOf<IConstTpDkcSlave>& list);
     void getTpGenesisServers(IArrayOf<IConstTpGenesisServer>& list);