1 karl 1.21 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.4 //
|
3 karl 1.15 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.14 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.15 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.16 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.21 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.4 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
15 kumpf 1.6 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
18 mike 1.4 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.21 //
|
21 kumpf 1.6 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
22 mike 1.4 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
24 kumpf 1.6 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
27 mike 1.4 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 // Author: Mike Brasher (mbrasher@bmc.com)
33 //
|
34 kumpf 1.10 // Modified By: Carol Ann Krug Graves, Hewlett-Packard Company
|
35 david.dillard 1.18 // (carolann_graves@hp.com)
|
36 kumpf 1.13 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
37 david.dillard 1.18 // David Dillard, VERITAS Software Corp.
38 // (david.dillard@veritas.com)
|
39 r.kieninger 1.19 // Robert Kieninger, IBM (kieningr@de.ibm.com)
|
40 mike 1.4 //
41 //%/////////////////////////////////////////////////////////////////////////////
42
|
43 mike 1.5 #include <Pegasus/Common/Config.h>
|
44 kumpf 1.8 #include <Pegasus/Common/InternalException.h>
|
45 mike 1.4 #include <Pegasus/Common/FileSystem.h>
46 #include <Pegasus/Common/Exception.h>
|
47 mike 1.23 #include <Pegasus/Common/ReadWriteSem.h>
|
48 mike 1.4 #include "AssocClassTable.h"
49
50 PEGASUS_USING_STD;
51
52 PEGASUS_NAMESPACE_BEGIN
53
54 #define ASSOC_CLASS_NAME_INDEX 0
55 #define FROM_CLASS_NAME_INDEX 1
56 #define FROM_PROPERTY_NAME_INDEX 2
57 #define TO_CLASS_NAME_INDEX 3
58 #define TO_PROPERTY_NAME_INDEX 4
59 #define NUM_FIELDS 5
60
|
61 r.kieninger 1.19
62 ReadWriteSem AssocClassTable::_classCacheLock;
63
64
|
65 mike 1.4 static inline Boolean _MatchNoCase(const String& x, const String& pattern)
66 {
67 return pattern.size() == 0 || String::equalNoCase(x, pattern);
68 }
69
|
70 david.dillard 1.18 static inline Boolean _ContainsClass(const Array<CIMName>& classNames, const String& match )
|
71 karl 1.11 {
72 Uint32 n = classNames.size();
73
74 for (Uint32 i = 0; i < n; i++)
75 {
|
76 david.dillard 1.18 if (_MatchNoCase(classNames[i].getString(), match))
77 return true;
|
78 karl 1.11 }
79
80 return false;
81 }
82
83
|
84 mike 1.4 static String _Escape(const String& str)
85 {
86 String result;
87
88 for (Uint32 i = 0, n = str.size(); i < n; i++)
89 {
90 Char16 c = str[i];
91
92 switch (c)
93 {
94 case '\n':
|
95 kumpf 1.9 result.append("\\n");
|
96 mike 1.4 break;
97
98 case '\r':
|
99 kumpf 1.9 result.append("\\r");
|
100 mike 1.4 break;
101
102 case '\t':
|
103 kumpf 1.9 result.append("\\t");
|
104 mike 1.4 break;
105
106 case '\f':
|
107 kumpf 1.9 result.append("\\f");
|
108 mike 1.4 break;
109
110 case '\\':
|
111 kumpf 1.9 result.append("\\\\");
|
112 mike 1.4 break;
113
114 default:
|
115 kumpf 1.9 result.append(c);
|
116 mike 1.4 }
117 }
118
119 return result;
120 }
121
122 static String _Unescape(const String& str)
123 {
124 String result;
125
126 for (Uint32 i = 0, n = str.size(); i < n; i++)
127 {
128 Char16 c = str[i];
129
130 if (c == '\\')
131 {
132 if (i + 1 == n)
133 break;
134
135 c = str[i + 1];
136
137 mike 1.4 switch (c)
138 {
139 case 'n':
|
140 kumpf 1.9 result.append("\n");
|
141 mike 1.4 break;
142
143 case 'r':
|
144 kumpf 1.9 result.append("\r");
|
145 mike 1.4 break;
146
147 case 't':
|
148 kumpf 1.9 result.append("\t");
|
149 mike 1.4 break;
150
151 case 'f':
|
152 kumpf 1.9 result.append("\f");
|
153 mike 1.4 break;
154
155 default:
|
156 kumpf 1.9 result.append(c);
|
157 mike 1.4 }
158
159 i++;
160 }
161 else
|
162 kumpf 1.9 result.append(c);
|
163 mike 1.4 }
164
165 return result;
166 }
167
168 static Boolean _GetRecord(ifstream& is, Array<String>& fields)
169 {
170 fields.clear();
171 String line;
172
173 for (Uint32 i = 0; i < NUM_FIELDS; i++)
174 {
175 if (!GetLine(is, line))
176 return false;
177
|
178 r.kieninger 1.19 fields.append(line);
179 //Association names are not supposed to contain escapes
180 //fields.append(_Unescape(line));
|
181 mike 1.4 }
182
183 // Skip the blank line:
184
185 if (!GetLine(is, line))
186 return false;
187
188 return true;
189 }
190
191 static void _PutRecord(ofstream& os, Array<String>& fields)
192 {
193 for (Uint32 i = 0, n = fields.size(); i < n; i++)
|
194 chuck 1.17 {
195 // Calling getCString to ensure utf-8 goes to the file
196 // Calling write to ensure no data conversion by the stream
|
197 david.dillard 1.18 CString buffer = _Escape(fields[i]).getCString();
|
198 kumpf 1.20 os.write((const char *)buffer,
199 static_cast<streamsize>(strlen((const char *)buffer)));
|
200 chuck 1.17 os << endl;
201 }
|
202 mike 1.4 os << endl;
203 }
204
205 void AssocClassTable::append(
206 PEGASUS_STD(ofstream)& os,
|
207 r.kieninger 1.19 const String& path,
|
208 kumpf 1.10 const CIMName& assocClassName,
209 const CIMName& fromClassName,
210 const CIMName& fromPropertyName,
211 const CIMName& toClassName,
212 const CIMName& toPropertyName)
|
213 mike 1.4 {
214 Array<String> fields;
|
215 kumpf 1.7 fields.reserveCapacity(5);
|
216 kumpf 1.10 fields.append(assocClassName.getString());
217 fields.append(fromClassName.getString());
218 fields.append(fromPropertyName.getString());
219 fields.append(toClassName.getString());
220 fields.append(toPropertyName.getString());
|
221 mike 1.4
|
222 r.kieninger 1.19
|
223 mike 1.4 _PutRecord(os, fields);
|
224 r.kieninger 1.19
225 // Update cache
226 AssocClassCache *cache = AssocClassCache::getAssocClassCache(path);
227 if (cache != 0)
228 {
229 if (cache->isActive())
230 {
231 WriteLock lock(_classCacheLock);
232 cache->addRecord(fields[FROM_CLASS_NAME_INDEX],
233 fields);
234 }
235 }
|
236 mike 1.4 }
237
238 void AssocClassTable::append(
239 const String& path,
|
240 kumpf 1.10 const CIMName& assocClassName,
241 const CIMName& fromClassName,
242 const CIMName& fromPropertyName,
243 const CIMName& toClassName,
244 const CIMName& toPropertyName)
|
245 mike 1.4 {
246 // Open input file:
|
247 david.dillard 1.18
|
248 mike 1.4 ofstream os;
249
250 if (!OpenAppend(os, path))
251 throw CannotOpenFile(path);
252
253 // Insert the entry:
254
255 Array<String> fields;
|
256 kumpf 1.7 fields.reserveCapacity(5);
|
257 kumpf 1.10 fields.append(assocClassName.getString());
258 fields.append(fromClassName.getString());
259 fields.append(fromPropertyName.getString());
260 fields.append(toClassName.getString());
261 fields.append(toPropertyName.getString());
|
262 mike 1.4
|
263 r.kieninger 1.19
|
264 mike 1.4 _PutRecord(os, fields);
|
265 r.kieninger 1.19
266 // Update cache
267 AssocClassCache *cache = AssocClassCache::getAssocClassCache(path);
268 if (cache != 0)
269 {
270 if (cache->isActive())
271 {
272 WriteLock lock(_classCacheLock);
273 cache->addRecord(fields[FROM_CLASS_NAME_INDEX],
274 fields);
275 }
276 }
|
277 mike 1.4 }
278
279 Boolean AssocClassTable::deleteAssociation(
280 const String& path,
|
281 kumpf 1.10 const CIMName& assocClassName)
|
282 mike 1.4 {
283 // Open input file:
284
285 ifstream is;
286
287 if (!Open(is, path))
288 return false;
289
290 // Open output file:
291
292 String tmpPath = path + ".tmp";
293 ofstream os;
294
295 if (!Open(os, tmpPath))
296 throw CannotOpenFile(tmpPath);
297
298 // Copy over all lines except ones with the given association instance name:
299
300 Array<String> fields;
|
301 r.kieninger 1.19 Array<String> fieldsToDelete;
|
302 mike 1.4 Boolean found = false;
303
304 while (_GetRecord(is, fields))
305 {
|
306 kumpf 1.10 if (assocClassName.getString() != fields[ASSOC_CLASS_NAME_INDEX])
|
307 mike 1.4 {
308 _PutRecord(os, fields);
309 found = true;
310 }
|
311 r.kieninger 1.19 else
312 {
313 fieldsToDelete = fields;
314 }
|
315 mike 1.4 }
316
317 // Close both files:
318
319 is.close();
320 os.close();
321
322 // Remove orginal file:
323
324 if (!FileSystem::removeFile(path))
325 throw CannotRemoveFile(path);
326
327 // Rename back to original name:
328
329 if (!FileSystem::renameFile(tmpPath, path))
330 throw CannotRenameFile(path);
331
|
332 r.kieninger 1.19
333 // Update cache
334 if (found)
335 {
336 AssocClassCache *cache = AssocClassCache::getAssocClassCache(path);
337 if (cache != 0)
338 {
339 if (cache->isActive())
340 {
341 WriteLock lock(_classCacheLock);
342 cache->removeRecord(fieldsToDelete[FROM_CLASS_NAME_INDEX],
343 fieldsToDelete[ASSOC_CLASS_NAME_INDEX]);
344 }
345 }
346 }
347
|
348 mike 1.4 return found;
349 }
350
351 Boolean AssocClassTable::getAssociatorNames(
352 const String& path,
|
353 kumpf 1.13 const Array<CIMName>& classList,
354 const Array<CIMName>& assocClassList,
355 const Array<CIMName>& resultClassList,
|
356 mike 1.4 const String& role,
357 const String& resultRole,
358 Array<String>& associatorNames)
359 {
360 // Open input file:
361 ifstream is;
362
363 if (!Open(is, path))
|
364 kumpf 1.13 return false;
|
365 mike 1.4
366 Array<String> fields;
367 Boolean found = false;
368
|
369 kumpf 1.13 // For each line in the associations table:
|
370 mike 1.4 while (_GetRecord(is, fields))
371 {
|
372 kumpf 1.13 // Process associations from the right end class and with right roles
373 if (_ContainsClass(classList, fields[FROM_CLASS_NAME_INDEX]) &&
374 _MatchNoCase(fields[FROM_PROPERTY_NAME_INDEX], role) &&
375 _MatchNoCase(fields[TO_PROPERTY_NAME_INDEX], resultRole))
376 {
377 // Skip classes that do not appear in the association class list
378 if ((assocClassList.size() != 0) &&
379 (!_ContainsClass(assocClassList,
380 fields[ASSOC_CLASS_NAME_INDEX])))
381 {
382 continue;
383 }
384
385 // Skip classes that do not appear in the result class list
386 if ((resultClassList.size() != 0) &&
387 (!_ContainsClass(resultClassList,
388 fields[TO_CLASS_NAME_INDEX])))
389 {
390 continue;
391 }
392
393 kumpf 1.13 // This class qualifies; add it to the list (skipping duplicates)
394 if (!Contains(associatorNames, fields[TO_CLASS_NAME_INDEX]))
395 {
396 associatorNames.append(fields[TO_CLASS_NAME_INDEX]);
397 }
398 found = true;
399 }
|
400 mike 1.4 }
401
402 return found;
403 }
404
|
405 r.kieninger 1.19 Boolean AssocClassTable::_InitializeCache( AssocClassCache *cache,
406 const String& path)
407 {
408 WriteLock lock(_classCacheLock);
409
410 if (!cache->isActive())
411 {
412
413 // Open input file:
414 ifstream is;
415
416 if (!Open(is, path))
417 return false;
418
419 Array<String> fields;
420
421 // For each line in the associations table:
422 while (_GetRecord(is, fields))
423 {
424 cache->addRecord(fields[FROM_CLASS_NAME_INDEX],
425 fields);
426 r.kieninger 1.19 }
427
428 cache->setActive(true);
429 }
430
431 return true;
432 }
433
434 void AssocClassTable::removeCaches()
435 {
436 WriteLock lock(_classCacheLock);
437 AssocClassCache::cleanupAssocClassCaches();
438
439 return;
440 }
441
|
442 mike 1.4 Boolean AssocClassTable::getReferenceNames(
443 const String& path,
|
444 karl 1.11 const Array<CIMName>& classList,
|
445 kumpf 1.13 const Array<CIMName>& resultClassList,
|
446 mike 1.4 const String& role,
447 Array<String>& referenceNames)
448 {
449
|
450 r.kieninger 1.19 // First see if we can get the information from the association class cache.
451 AssocClassCache *cache = AssocClassCache::getAssocClassCache(path);
452 if (cache == 0)
|
453 kumpf 1.13 return false;
|
454 mike 1.4
|
455 r.kieninger 1.19 if (!cache->isActive())
456 {
457 if (!_InitializeCache(cache,path))
458 return false;
459 }
460
461 Array< Array<String> > records;
|
462 karl 1.11 Boolean found = false;
463
|
464 r.kieninger 1.19
465 // For each of the target classes retrieve the list of matching
466 // association classes from the cache.
467 // The cache uses the from class name as an index and returns all
468 // association class records having that from class.
469
470 ReadLock lock(_classCacheLock);
471 for (Uint16 idx=0; idx < classList.size(); idx++)
|
472 karl 1.11 {
|
473 r.kieninger 1.19 String fromClassName = classList[idx].getString();
474 if (cache->getAssocClassEntry(fromClassName, records))
475 {
476 for (Uint16 rx=0; rx <records.size(); rx++)
477 {
478 if (_MatchNoCase(records[rx][FROM_PROPERTY_NAME_INDEX], role))
|
479 kumpf 1.13 {
480 // Skip classes that do not appear in the result class list
481 if ((resultClassList.size() != 0) &&
482 (!_ContainsClass(resultClassList,
|
483 r.kieninger 1.19 records[rx][ASSOC_CLASS_NAME_INDEX])))
|
484 kumpf 1.13 {
485 continue;
486 }
|
487 karl 1.11
|
488 kumpf 1.13 // This class qualifies; add it to the list (skipping duplicates)
|
489 r.kieninger 1.19 if (!Contains(referenceNames, records[rx][ASSOC_CLASS_NAME_INDEX]))
|
490 karl 1.11 {
|
491 r.kieninger 1.19 referenceNames.append(records[rx][ASSOC_CLASS_NAME_INDEX]);
|
492 karl 1.11 }
|
493 kumpf 1.13 found = true;
|
494 karl 1.11 }
|
495 mike 1.4 }
|
496 r.kieninger 1.19 }
497 }
|
498 mike 1.4
499 return found;
500 }
501
502 PEGASUS_NAMESPACE_END
|