0031709: Draw Harness - move methods ViewerTest::ParseOnOff()/ParseColor() to package...
[occt.git] / src / Draw / Draw_PloadCommands.cxx
1 // Created on: 2003-10-09
2 // Created by: Mikhail KUZMITCHEV
3 // Copyright (c) 2003-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Draw_Interpretor.hxx>
17 #include <Draw_MapOfAsciiString.hxx>
18 #include <Draw.hxx>
19 #include <Message.hxx>
20 #include <OSD_Path.hxx>
21 #include <OSD_Directory.hxx>
22 #include <OSD_File.hxx>
23 #include <OSD_Environment.hxx>
24 #include <OSD_SharedLibrary.hxx>
25 #include <Resource_Manager.hxx>
26 #include <TCollection_AsciiString.hxx>
27
28 //! Searches for the existence of the plugin file according to its name thePluginName:
29 //! - if thePluginName is empty then it defaults to DrawPlugin
30 //! - the search directory is defined according to the variable
31 //!   CSF_<filename>Defaults (if it is omitted then it defaults to
32 //!   $CASROOT/src/DrawResources)
33 //! - finally existence of the file is verified in the search directory
34 //! - if the file exists but corresponding variable (CSF_...) has not been
35 //!   explicitly set, it is forced to (for further reuse by Resource_Manager)
36 //! @return TRUE if the file exists, otherwise - False
37 static Standard_Boolean findPluginFile (TCollection_AsciiString& thePluginName,
38                                         TCollection_AsciiString& thePluginDir)
39 {
40   // check if the file name has been specified and use default value if not
41   if (thePluginName.IsEmpty())
42   {
43     thePluginName += "DrawPlugin";
44 #ifdef OCCT_DEBUG
45     std::cout << "Plugin file name has not been specified. Defaults to " << thePluginName.ToCString() << std::endl;
46 #endif
47   }
48
49   Standard_Boolean aToSetCSFVariable = Standard_False;
50   
51   // the order of search : by CSF_<PluginFileName>Defaults and then by CASROOT
52   const TCollection_AsciiString aCSFVariable = TCollection_AsciiString ("CSF_") + thePluginName + "Defaults";
53   thePluginDir = OSD_Environment (aCSFVariable).Value();
54   if (thePluginDir.IsEmpty())
55   {
56     thePluginDir = OSD_Environment ("DRAWHOME").Value();
57     if (!thePluginDir.IsEmpty())
58     {
59       aToSetCSFVariable = Standard_True; //CSF variable to be set later
60     }
61     else
62     {
63       // now try by CASROOT
64       thePluginDir = OSD_Environment ("CASROOT").Value();
65       if (!thePluginDir.IsEmpty())
66       {
67         thePluginDir += "/src/DrawResources";
68         aToSetCSFVariable = Standard_True; //CSF variable to be set later
69       }
70       else
71       {
72         Message::SendFail() << "Failed to load plugin: Neither " << aCSFVariable << ", nor CASROOT variables have been set";
73         return Standard_False;
74       }
75     }
76   }
77
78   // search directory name has been constructed, now check whether it and the file exist
79   const TCollection_AsciiString aPluginFileName = thePluginDir + "/" + thePluginName;
80   OSD_File aPluginFile (aPluginFileName);
81   if (!aPluginFile.Exists())
82   {
83     Message::SendFail() << "Failed to load plugin: File " << aPluginFileName << " not found";
84     return Standard_False;
85   }
86
87   if (aToSetCSFVariable)
88   {
89     OSD_Environment aCSFVarEnv (aCSFVariable, thePluginDir);
90     aCSFVarEnv.Build();
91 #ifdef OCCT_DEBUG
92     std::cout << "Variable " << aCSFVariable << " has not been explicitly defined. Set to " << thePluginDir << std::endl;
93 #endif
94     if (aCSFVarEnv.Failed())
95     {
96       Message::SendFail() << "Failed to load plugin: Failed to initialize " << aCSFVariable << " with " << thePluginDir;
97       return Standard_False;
98     }
99   }
100   
101   return Standard_True;
102 }
103
104 //! Resolve keys within input map (groups, aliases and toolkits) to the list of destination toolkits (plugins to load).
105 //! @param theMap [in] [out] map to resolve (will be rewritten)
106 //! @param theResMgr [in] resource manager to resolve keys
107 static void resolveKeys (Draw_MapOfAsciiString& theMap,
108                          const Handle(Resource_Manager)& theResMgr)
109 {
110   if (theResMgr.IsNull())
111   {
112     return;
113   }
114
115   Draw_MapOfAsciiString aMap, aMap2;
116   const Standard_Integer aMapExtent = theMap.Extent();
117   for (Standard_Integer j = 1; j <= aMapExtent; ++j)
118   {
119     TCollection_AsciiString aValue;
120     const TCollection_AsciiString aResource = theMap.FindKey (j);
121     if (theResMgr->Find (aResource, aValue))
122     {
123     #ifdef OCCT_DEBUG
124       std::cout << "Parse Value ==> " << aValue << std::endl;
125     #endif
126       for (Standard_Integer aKeyIter = 1;; ++aKeyIter)
127       {
128         const TCollection_AsciiString aCurKey = aValue.Token (" \t,", aKeyIter);
129       #ifdef OCCT_DEBUG
130         std::cout << "Parse aCurKey = " << aCurKey << std::endl;
131       #endif
132         if (aCurKey.IsEmpty())
133         {
134           break;
135         }
136
137         if (theResMgr->Find (aCurKey.ToCString()))
138         {
139           aMap2.Add (aCurKey);
140         }
141         else
142         {
143           aMap.Add (aResource); // It is toolkit
144         }
145       }
146     }
147     else
148     {
149       Message::SendFail() << "Pload : Resource = " << aResource << " is not found";
150     }
151
152     if (!aMap2.IsEmpty())
153     {
154       resolveKeys (aMap2, theResMgr);
155     }
156
157     //
158     const Standard_Integer aMap2Extent = aMap2.Extent();
159     for (Standard_Integer k = 1; k <= aMap2Extent; ++k)
160     {
161       aMap.Add (aMap2.FindKey (k));
162     }
163   }
164
165   theMap.Assign (aMap);
166 }
167
168 //=======================================================================
169 //function : Pload
170 //purpose  : 
171 //=======================================================================
172
173 static Standard_Integer Pload (Draw_Interpretor& theDI,
174                                Standard_Integer  theNbArgs,
175                                const char**      theArgVec)
176 {
177   Draw_MapOfAsciiString aMap;
178   TCollection_AsciiString aPluginFileName;
179   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
180   {
181     const TCollection_AsciiString aTK (theArgVec[anArgIter]);
182     if (anArgIter == 1
183      && aTK.Value (1) == '-')
184     {
185       aPluginFileName = aTK.SubString (2, aTK.Length());
186     }
187     else
188     {
189       aMap.Add (aTK);
190     }
191   }
192   if (aMap.IsEmpty())
193   {
194     aMap.Add ("DEFAULT"); // Load DEFAULT key
195   }
196
197   TCollection_AsciiString aPluginDir, aPluginDir2;
198   if (!findPluginFile (aPluginFileName, aPluginDir))
199   {
200     return 1;
201   }
202
203   Handle(Resource_Manager) aResMgr = new Resource_Manager (aPluginFileName.ToCString(), aPluginDir, aPluginDir2, Standard_False);
204   resolveKeys (aMap, aResMgr);
205
206   const Standard_Integer aMapExtent = aMap.Extent();
207   for (Standard_Integer aResIter = 1; aResIter <= aMapExtent; ++aResIter)
208   {
209     const TCollection_AsciiString aResource = aMap.FindKey (aResIter);
210   #ifdef OCCT_DEBUG
211     std::cout << "aResource = " << aResource << std::endl;
212   #endif
213     TCollection_AsciiString aValue;
214     if (!aResMgr->Find (aResource, aValue))
215     {
216       Message::SendWarning() <<"Pload : Resource = " << aResource << " is not found";
217       continue;
218     }
219
220   #ifdef OCCT_DEBUG
221     std::cout << "Value ==> " << aValue << std::endl;
222   #endif
223
224     Draw::Load (theDI, aResource, aPluginFileName, aPluginDir, aPluginDir2, Standard_False);
225
226     // Load TclScript
227     const TCollection_AsciiString aTclScriptDir = OSD_Environment ("CSF_DrawPluginTclDir").Value();
228     const TCollection_AsciiString aTclScriptFileName         = aTclScriptDir + "/" + aValue + ".tcl";
229     const TCollection_AsciiString aTclScriptFileNameDefaults = aPluginDir    + "/" + aValue + ".tcl";
230     OSD_File aTclScriptFile (aTclScriptFileName);
231     OSD_File aTclScriptFileDefaults (aTclScriptFileNameDefaults);
232     if (!aTclScriptDir.IsEmpty()
233       && aTclScriptFile.Exists())
234     {
235     #ifdef OCCT_DEBUG
236       std::cout << "Load " << aTclScriptFileName << " TclScript" << std::endl;
237     #endif
238       theDI.EvalFile (aTclScriptFileName.ToCString());
239     }
240     else if (!aPluginDir.IsEmpty()
241            && aTclScriptFileDefaults.Exists())
242     {
243     #ifdef OCCT_DEBUG
244       std::cout << "Load " << aTclScriptFileNameDefaults << " TclScript" << std::endl;
245     #endif
246       theDI.EvalFile (aTclScriptFileNameDefaults.ToCString());
247     }
248   }
249   return 0;
250 }
251
252 //=======================================================================
253 //function : dtryload
254 //purpose  : 
255 //=======================================================================
256
257 static Standard_Integer dtryload (Draw_Interpretor& di, Standard_Integer n, const char** argv)
258 {
259   if (n != 2)
260   {
261     std::cout << "Error: specify path to library to be loaded" << std::endl;
262     return 1;
263   }
264
265   OSD_SharedLibrary aLib(argv[1]);
266   if (aLib.DlOpen(OSD_RTLD_NOW))
267   {
268     di << "Loading " << argv[1] << " successful";
269     aLib.DlClose();
270   }
271   else 
272   {
273     di << "Loading " << argv[1] << " failed: " << aLib.DlError();
274   }
275   return 0;
276 }
277
278 //=======================================================================
279 //function : PloadCommands
280 //purpose  : 
281 //=======================================================================
282
283 void Draw::PloadCommands(Draw_Interpretor& theCommands)
284 {
285   static Standard_Boolean Done = Standard_False;
286   if (Done) return;
287   Done = Standard_True;
288
289   const char* g = "Draw Plugin";
290   
291   theCommands.Add("pload" , "pload [-PluginFilename] [[Key1] [Key2] ...]: Loads Draw plugins " ,
292                   __FILE__, Pload, g);
293   theCommands.Add("dtryload" , "dtryload path : load and unload specified dynamic loaded library" ,
294                   __FILE__, dtryload, g);
295 }