Revision 5311
Added by daigle about 14 years ago
Eml200SAXHandler.java | ||
---|---|---|
59 | 59 |
import edu.ucsb.nceas.utilities.PropertyNotFoundException; |
60 | 60 |
|
61 | 61 |
/** |
62 |
* A database aware Class implementing callback bethods for the SAX parser to
|
|
62 |
* A database aware Class implementing callback methods for the SAX parser to
|
|
63 | 63 |
* call when processing the XML stream and generating events |
64 | 64 |
* Here is the rules for user which has write permission in top level access |
65 | 65 |
* rules(he can update metadata but can't update access module) try to update |
66 | 66 |
* a document: |
67 | 67 |
* 1. Checking access part (both in top level and additional level, node by node) |
68 | 68 |
* If something was modified, reject the document. Note: for additional part |
69 |
* The access subtree startnode starts at "<describ>" rather than <access>. |
|
69 |
* The access subtree startnode starts at "<describe>" rather than <access>.
|
|
70 | 70 |
* This is because make sure ids wouldn't be mess up by user. |
71 | 71 |
* 2. Checking ids in additional access part, if they points a distribution |
72 | 72 |
* module with online or inline. If some ids don't, reject the documents. |
... | ... | |
74 | 74 |
* If user can't read the inline data, the empty string in inline element |
75 | 75 |
* will be send to user if he read this eml document(user has read access |
76 | 76 |
* at top level - metadata, but user couldn't read inline data). |
77 |
* Here is some intrested senario: If user does have read and write
|
|
77 |
* Here is some interested scenario: If user does have read and write
|
|
78 | 78 |
* permission in top level access rules(for metadata) |
79 | 79 |
* but 1) user doesn't have read and write permission in inline data block, |
80 | 80 |
* so if user update the document with some inline data rather than |
81 | 81 |
* empty string in same inline data block(same distribution inline id), |
82 | 82 |
* this means user updated the inline data. So the document should be |
83 | 83 |
* rejected. |
84 |
* 2) user doesn't have read permssion, but has write premission in
|
|
84 |
* 2) user doesn't have read permission, but has write permission in
|
|
85 | 85 |
* inline data block. If user send back inline data block with empty |
86 | 86 |
* string, we will think user doesn't update inline data and we will |
87 | 87 |
* copy old inline data back to the new one. If user send something |
... | ... | |
116 | 116 |
public class Eml200SAXHandler extends DBSAXHandler implements |
117 | 117 |
AccessControlInterface |
118 | 118 |
{ |
119 |
private boolean processTopLeverAccess = false; |
|
119 |
// Boolean that tells whether we are processing top level (document level) access. |
|
120 |
// this is true when we hit an 'access' element, and the grandparent element is |
|
121 |
// 'eml' and we are not inside an 'additionalMetadata' section. Set back to false |
|
122 |
// in endElement |
|
123 |
private boolean processTopLevelAccess = false; |
|
120 | 124 |
|
121 | 125 |
// now additionalAccess will be explained as distribution access control |
122 | 126 |
// - data file |
123 | 127 |
private boolean processAdditionalAccess = false; |
124 | 128 |
|
129 |
// Boolean that tells whether we are processing other access. This is true when |
|
130 |
// we find an 'access' element inside an 'additionalMetadata' element. Set back |
|
131 |
// to false in endElement |
|
125 | 132 |
private boolean processOtherAccess = false; |
126 | 133 |
|
134 |
// if we are inside an 'access' element, we use this object to hold the |
|
135 |
// current access info |
|
127 | 136 |
private AccessSection accessObject = null; |
128 | 137 |
|
138 |
// for each 'access/allow' and 'access/deny' we create a new access Rule to hold |
|
139 |
// the info |
|
129 | 140 |
private AccessRule accessRule = null; |
130 | 141 |
|
131 | 142 |
private Vector describesId = new Vector(); // store the ids in |
... | ... | |
157 | 168 |
// temporarily store distribution id |
158 | 169 |
private String distributionId = null; |
159 | 170 |
|
160 |
// flag to indicate to handle distrubiton
|
|
171 |
// flag to indicate to handle distribution
|
|
161 | 172 |
private boolean proccessDistribution = false; |
162 | 173 |
|
163 | 174 |
// a hash table to stored the distribution which is a reference and this |
... | ... | |
171 | 182 |
// id (300) will be stored in above distribution lists. |
172 | 183 |
private Hashtable distributionReferenceList = new Hashtable(); |
173 | 184 |
|
174 |
private boolean needCheckingAccessModule = false; |
|
185 |
// if the action is update and the user does not have ALL permission |
|
186 |
// and the user is not an administrator, then we will need to compare |
|
187 |
// access modules to make sure the user has update permissions |
|
188 |
private boolean needToCheckAccessModule = false; |
|
175 | 189 |
|
176 |
private AccessSection unChangebleTopAccessSubTree = null;
|
|
190 |
private AccessSection topAccessSubTreeFromDB = null;
|
|
177 | 191 |
|
178 |
private Vector unChangebleAdditionalAccessSubTreeVector = new Vector();
|
|
192 |
private Vector additionalAccessSubTreeListFromDB = new Vector();
|
|
179 | 193 |
|
180 |
private Hashtable unChangebleReferencedAccessSubTreeHash = new Hashtable();
|
|
194 |
private Hashtable referencedAccessSubTreeListFromDB = new Hashtable();
|
|
181 | 195 |
|
196 |
// this holds the top level (document level) access section. |
|
182 | 197 |
private AccessSection topAccessSection; |
183 | 198 |
|
184 | 199 |
private Vector additionalAccessVector = new Vector(); |
... | ... | |
206 | 221 |
|
207 | 222 |
private Vector inlineFileIDList = new Vector(); |
208 | 223 |
|
209 |
private boolean inadditionalMetaData = false;
|
|
224 |
private boolean inAdditionalMetaData = false;
|
|
210 | 225 |
|
211 | 226 |
//user has unwritable inline data object when it updates a document |
212 | 227 |
private boolean unWritableInlineDataObject = false; |
... | ... | |
322 | 337 |
//unChangableSubTreeHash = getUnchangableSubTree(control, user, |
323 | 338 |
// groups); |
324 | 339 |
|
325 |
//If the action is update and user doesn't have "ALL" permission |
|
340 |
// If the action is update and user doesn't have "ALL" permission
|
|
326 | 341 |
// we need to check if user update access subtree |
327 | 342 |
if (action != null && action.equals("UPDATE") |
328 | 343 |
&& !control.hasPermission(user, groups, |
329 | 344 |
AccessControlInterface.ALLSTRING) |
330 | 345 |
&& !AuthUtil.isAdministrator(user, groups)) |
331 | 346 |
{ |
332 |
needCheckingAccessModule = true;
|
|
333 |
unChangebleTopAccessSubTree = getTopAccessSubTreeFromDB();
|
|
334 |
unChangebleAdditionalAccessSubTreeVector =
|
|
347 |
needToCheckAccessModule = true;
|
|
348 |
topAccessSubTreeFromDB = getTopAccessSubTreeFromDB();
|
|
349 |
additionalAccessSubTreeListFromDB =
|
|
335 | 350 |
getAdditionalAccessSubTreeListFromDB(); |
336 |
unChangebleReferencedAccessSubTreeHash =
|
|
351 |
referencedAccessSubTreeListFromDB =
|
|
337 | 352 |
getReferencedAccessSubTreeListFromDB(); |
338 | 353 |
} |
339 | 354 |
|
... | ... | |
596 | 611 |
|
597 | 612 |
//start handle inline data |
598 | 613 |
//===================================================== |
599 |
if (qName.equals(INLINE) && !inadditionalMetaData)
|
|
614 |
if (qName.equals(INLINE) && !inAdditionalMetaData)
|
|
600 | 615 |
{ |
601 | 616 |
handleInlineData = true; |
602 | 617 |
inLineDataIndex++; |
... | ... | |
654 | 669 |
{ |
655 | 670 |
|
656 | 671 |
|
657 |
if (needCheckingAccessModule
|
|
658 |
&& (processAdditionalAccess || processOtherAccess || processTopLeverAccess)) {
|
|
672 |
if (needToCheckAccessModule
|
|
673 |
&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
|
|
659 | 674 |
// stored the pull out nodes into storedNode stack |
660 | 675 |
NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", |
661 | 676 |
null, null, MetacatUtil.normalize(textBuffer |
... | ... | |
807 | 822 |
} |
808 | 823 |
else if (attributeName != null && attributeName.equals(ID) && |
809 | 824 |
currentNode.getTagName().equals(DISTRIBUTION) && |
810 |
!inadditionalMetaData)
|
|
825 |
!inAdditionalMetaData)
|
|
811 | 826 |
{ |
812 | 827 |
// this is a distribution element and the id is distributionID |
813 | 828 |
distributionId = attributeValue; |
... | ... | |
834 | 849 |
// put parent node back |
835 | 850 |
nodeStack.push(tmpNode); |
836 | 851 |
String grandParentTag = grandParentNode.getTagName(); |
837 |
if (grandParentTag.equals(EML) && !inadditionalMetaData)
|
|
852 |
if (grandParentTag.equals(EML) && !inAdditionalMetaData)
|
|
838 | 853 |
{ |
839 |
processTopLeverAccess = true;
|
|
854 |
processTopLevelAccess = true;
|
|
840 | 855 |
|
841 | 856 |
} |
842 |
else if ( !inadditionalMetaData )
|
|
857 |
else if ( !inAdditionalMetaData )
|
|
843 | 858 |
{ |
844 | 859 |
// process other access embedded into resource level |
845 | 860 |
// module |
... | ... | |
847 | 862 |
} |
848 | 863 |
else |
849 | 864 |
{ |
850 |
// this for access in additional data which don't have
|
|
851 |
// described element. If it has a descirbed element,
|
|
852 |
// this code would hurt any thing
|
|
865 |
// this for access in additional data which doesn't have a
|
|
866 |
// described element. If it has a described element,
|
|
867 |
// this code won't hurt any thing
|
|
853 | 868 |
processAdditionalAccess = true; |
854 |
logMetacat.info("accessing process additional access true when meet access"); |
|
855 | 869 |
} |
856 | 870 |
|
857 | 871 |
|
... | ... | |
871 | 885 |
accessObject.setStartedDescribesNodeId(firstDescribesNodeId); |
872 | 886 |
accessObject.setControlLevel(DATAACCESSLEVEL); |
873 | 887 |
} |
874 |
else if (processTopLeverAccess)
|
|
888 |
else if (processTopLevelAccess)
|
|
875 | 889 |
{ |
876 | 890 |
accessObject.setControlLevel(TOPLEVEL); |
877 | 891 |
} |
... | ... | |
918 | 932 |
nodeIndex.addElement(currentNode); |
919 | 933 |
|
920 | 934 |
// store access module element and attributes into stored stack |
921 |
if (needCheckingAccessModule
|
|
922 |
&& (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
|
|
935 |
if (needToCheckAccessModule
|
|
936 |
&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess))
|
|
923 | 937 |
{ |
924 | 938 |
// stored the pull out nodes into storedNode stack |
925 | 939 |
NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "ELEMENT", |
... | ... | |
938 | 952 |
|
939 | 953 |
if (currentNode.getTagName().equals(ADDITIONALMETADATA)) |
940 | 954 |
{ |
941 |
inadditionalMetaData = true;
|
|
955 |
inAdditionalMetaData = true;
|
|
942 | 956 |
} |
943 | 957 |
else if (currentNode.getTagName().equals(DESCRIBES) && |
944 | 958 |
parentNode.getTagName().equals(ADDITIONALMETADATA) && |
... | ... | |
954 | 968 |
processAdditionalAccess = true; |
955 | 969 |
logMetacat.info("set processAdditonalAccess true when meet describe"); |
956 | 970 |
} |
957 |
else if (inadditionalMetaData && processAdditionalAccess &&
|
|
971 |
else if (inAdditionalMetaData && processAdditionalAccess &&
|
|
958 | 972 |
parentNode.getTagName().equals(ADDITIONALMETADATA) && |
959 | 973 |
!currentNode.getTagName().equals(DESCRIBES) && |
960 | 974 |
!currentNode.getTagName().equals(ACCESS)) |
... | ... | |
971 | 985 |
logMetacat.warn("set processAddtionAccess false if the there is no access in additional"); |
972 | 986 |
} |
973 | 987 |
else if (currentNode.getTagName().equals(DISTRIBUTION) && |
974 |
!inadditionalMetaData)
|
|
988 |
!inAdditionalMetaData)
|
|
975 | 989 |
{ |
976 | 990 |
proccessDistribution = true; |
977 | 991 |
} |
... | ... | |
1053 | 1067 |
DBSAXNode currentNode = (DBSAXNode) nodeStack.peek(); |
1054 | 1068 |
endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, |
1055 | 1069 |
currentNode); |
1056 |
if (needCheckingAccessModule
|
|
1057 |
&& (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
|
|
1070 |
if (needToCheckAccessModule
|
|
1071 |
&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess))
|
|
1058 | 1072 |
{ |
1059 | 1073 |
// stored the pull out nodes into storedNode stack |
1060 | 1074 |
NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", |
... | ... | |
1237 | 1251 |
//firstDescribesNodeId = 0; |
1238 | 1252 |
} |
1239 | 1253 |
else if (currentTag.equals(REFERENCES) |
1240 |
&& (processTopLeverAccess || processAdditionalAccess || processOtherAccess))
|
|
1254 |
&& (processTopLevelAccess || processAdditionalAccess || processOtherAccess))
|
|
1241 | 1255 |
{ |
1242 | 1256 |
// get reference |
1243 | 1257 |
data = (textBuffer.toString()).trim(); |
... | ... | |
1257 | 1271 |
} |
1258 | 1272 |
|
1259 | 1273 |
} |
1260 |
else if (currentTag.equals(URL) && !inadditionalMetaData)
|
|
1274 |
else if (currentTag.equals(URL) && !inAdditionalMetaData)
|
|
1261 | 1275 |
{ |
1262 | 1276 |
//handle online data, make sure its'parent is online |
1263 | 1277 |
DBSAXNode parentNode = (DBSAXNode) nodeStack.peek(); |
... | ... | |
1284 | 1298 |
endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, |
1285 | 1299 |
currentNode); |
1286 | 1300 |
|
1287 |
if (needCheckingAccessModule
|
|
1288 |
&& (processAdditionalAccess || processOtherAccess || processTopLeverAccess)) {
|
|
1301 |
if (needToCheckAccessModule
|
|
1302 |
&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
|
|
1289 | 1303 |
// stored the pull out nodes into storedNode stack |
1290 | 1304 |
NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", |
1291 | 1305 |
null, null, MetacatUtil.normalize(textBuffer |
... | ... | |
1325 | 1339 |
if (newAccessObject != null) |
1326 | 1340 |
{ |
1327 | 1341 |
|
1328 |
if (processTopLeverAccess)
|
|
1342 |
if (processTopLevelAccess)
|
|
1329 | 1343 |
{ |
1330 | 1344 |
topAccessSection = newAccessObject; |
1331 | 1345 |
|
... | ... | |
1362 | 1376 |
|
1363 | 1377 |
// reset flag |
1364 | 1378 |
processAdditionalAccess = false; |
1365 |
processTopLeverAccess = false;
|
|
1379 |
processTopLevelAccess = false;
|
|
1366 | 1380 |
processOtherAccess = false; |
1367 | 1381 |
|
1368 | 1382 |
}//access element |
... | ... | |
1371 | 1385 |
//reset describesId |
1372 | 1386 |
describesId = null; |
1373 | 1387 |
describesId = new Vector(); |
1374 |
inadditionalMetaData = false;
|
|
1388 |
inAdditionalMetaData = false;
|
|
1375 | 1389 |
firstDescribesNodeId = -1; |
1376 | 1390 |
// reset tmp stored node stack |
1377 | 1391 |
storedAccessNodeStack = null; |
... | ... | |
1379 | 1393 |
|
1380 | 1394 |
|
1381 | 1395 |
} |
1382 |
else if (currentTag.equals(DISTRIBUTION) && !inadditionalMetaData)
|
|
1396 |
else if (currentTag.equals(DISTRIBUTION) && !inAdditionalMetaData)
|
|
1383 | 1397 |
{ |
1384 | 1398 |
//reset distribution id |
1385 | 1399 |
distributionId = null; |
1386 | 1400 |
proccessDistribution = false; |
1387 | 1401 |
} |
1388 |
else if (currentTag.equals(OFFLINE) && !inadditionalMetaData)
|
|
1402 |
else if (currentTag.equals(OFFLINE) && !inAdditionalMetaData)
|
|
1389 | 1403 |
{ |
1390 | 1404 |
if (distributionId != null) |
1391 | 1405 |
{ |
... | ... | |
1393 | 1407 |
} |
1394 | 1408 |
} |
1395 | 1409 |
else if ((currentTag.equals(CONNECTION) || currentTag.equals(CONNECTIONDEFINITION)) |
1396 |
&& !inadditionalMetaData)
|
|
1410 |
&& !inAdditionalMetaData)
|
|
1397 | 1411 |
{ |
1398 | 1412 |
//handle online data, make sure its'parent is online |
1399 | 1413 |
DBSAXNode parentNode = (DBSAXNode) nodeStack.peek(); |
... | ... | |
1537 | 1551 |
str, PERMISSIONERROR); |
1538 | 1552 |
}//if*/ |
1539 | 1553 |
//compare top level access module |
1540 |
if (processTopLeverAccess && needCheckingAccessModule) {
|
|
1554 |
if (processTopLevelAccess && needToCheckAccessModule) {
|
|
1541 | 1555 |
/*compareCommentNode(currentUnchangableAccessModuleNodeStack, |
1542 | 1556 |
str, UPDATEACCESSERROR);*/ |
1543 | 1557 |
} |
1544 | 1558 |
endNodeId = currentNode.writeChildNodeToDB("COMMENT", null, |
1545 | 1559 |
str, docid); |
1546 |
if (needCheckingAccessModule
|
|
1547 |
&& (processAdditionalAccess || processOtherAccess || processTopLeverAccess)) {
|
|
1560 |
if (needToCheckAccessModule
|
|
1561 |
&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
|
|
1548 | 1562 |
// stored the pull out nodes into storedNode stack |
1549 | 1563 |
NodeRecord nodeElement = new NodeRecord(-2, -2, -2, |
1550 | 1564 |
"COMMENT", null, null, MetacatUtil.normalize(str)); |
... | ... | |
1621 | 1635 |
String data = new String(cbuf, start, len); |
1622 | 1636 |
|
1623 | 1637 |
//compare whitespace in access top module |
1624 |
if (processTopLeverAccess && needCheckingAccessModule) {
|
|
1638 |
if (processTopLevelAccess && needToCheckAccessModule) {
|
|
1625 | 1639 |
/*compareWhiteSpace(currentUnchangableAccessModuleNodeStack, |
1626 | 1640 |
data, UPDATEACCESSERROR);*/ |
1627 | 1641 |
} |
1628 | 1642 |
// Write the content of the node to the database |
1629 |
if (needCheckingAccessModule
|
|
1630 |
&& (processAdditionalAccess || processOtherAccess || processTopLeverAccess)) {
|
|
1643 |
if (needToCheckAccessModule
|
|
1644 |
&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
|
|
1631 | 1645 |
// stored the pull out nodes into storedNode stack |
1632 | 1646 |
NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", |
1633 | 1647 |
null, null, MetacatUtil.normalize(data)); |
... | ... | |
1650 | 1664 |
public void endDocument() throws SAXException |
1651 | 1665 |
{ |
1652 | 1666 |
logMetacat.info("end Document"); |
1653 |
if (needCheckingAccessModule)
|
|
1667 |
if (needToCheckAccessModule)
|
|
1654 | 1668 |
{ |
1655 | 1669 |
compareAllAccessModules(); |
1656 | 1670 |
} |
... | ... | |
1691 | 1705 |
private void compareAllAccessModules() throws SAXException |
1692 | 1706 |
{ |
1693 | 1707 |
//compare top level |
1694 |
compareAccessSubtree(unChangebleTopAccessSubTree, topAccessSection);
|
|
1708 |
compareAccessSubtree(topAccessSubTreeFromDB, topAccessSection);
|
|
1695 | 1709 |
|
1696 | 1710 |
//compare additional level |
1697 |
int oldSize = unChangebleAdditionalAccessSubTreeVector.size();
|
|
1711 |
int oldSize = additionalAccessSubTreeListFromDB.size();
|
|
1698 | 1712 |
int newSize = additionalAccessVector.size(); |
1699 | 1713 |
// if size is different, use deleted or added rules, so throw a exception |
1700 | 1714 |
if (oldSize != newSize) |
... | ... | |
1706 | 1720 |
for ( int i = 0; i < newSize; i++) |
1707 | 1721 |
{ |
1708 | 1722 |
AccessSection fromDB = (AccessSection) |
1709 |
unChangebleAdditionalAccessSubTreeVector.elementAt(i);
|
|
1723 |
additionalAccessSubTreeListFromDB.elementAt(i);
|
|
1710 | 1724 |
AccessSection fromParser = (AccessSection) |
1711 | 1725 |
additionalAccessVector.elementAt(i); |
1712 | 1726 |
compareAccessSubtree(fromDB, fromParser); |
1713 | 1727 |
} |
1714 | 1728 |
|
1715 | 1729 |
//compare referenced level |
1716 |
Enumeration em = unChangebleReferencedAccessSubTreeHash.keys();
|
|
1730 |
Enumeration em = referencedAccessSubTreeListFromDB.keys();
|
|
1717 | 1731 |
while (em.hasMoreElements()) |
1718 | 1732 |
{ |
1719 | 1733 |
String id = (String)em.nextElement(); |
1720 | 1734 |
AccessSection fromDB = (AccessSection) |
1721 |
unChangebleReferencedAccessSubTreeHash.get(id);
|
|
1735 |
referencedAccessSubTreeListFromDB.get(id);
|
|
1722 | 1736 |
AccessSection fromParser = (AccessSection) |
1723 | 1737 |
possibleReferencedAccessHash.get(id); |
1724 | 1738 |
compareAccessSubtree(fromDB, fromParser); |
... | ... | |
1926 | 1940 |
//System.out.println("in write additional"); |
1927 | 1941 |
// we should delete all inline access rules in xml_access if |
1928 | 1942 |
// user has all permission |
1929 |
if (!needCheckingAccessModule)
|
|
1943 |
if (!needToCheckAccessModule)
|
|
1930 | 1944 |
{ |
1931 | 1945 |
deleteAllInlineDataAccessRules(); |
1932 | 1946 |
} |
Also available in: Unified diff
Merge 1.9.2 changes back into the trunk