src/share/classes/com/sun/jndi/ldap/LdapSchemaParser.java

Print this page




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.jndi.ldap;
  27 
  28 import javax.naming.*;
  29 import javax.naming.directory.*;
  30 import java.util.Hashtable;
  31 import java.util.Vector;
  32 
  33 /**
  34  * Netscape's 3.1 servers have some schema bugs:
  35  * - It puts quotes around OIDs (such as those for SUP, SYNTAX).
  36  * - When you try to write out the MUST/MAY list (such as "MUST cn"),
  37  *   it wants ("MUST (cn)") instead
  38  */
  39 
  40 final class LdapSchemaParser {
  41 
  42     // do debugging
  43     private static final boolean debug = false;
  44 
  45 
  46     // names of attribute IDs in the LDAP schema entry
  47     static final String OBJECTCLASSDESC_ATTR_ID = "objectClasses";
  48     static final String ATTRIBUTEDESC_ATTR_ID = "attributeTypes";
  49     static final String SYNTAXDESC_ATTR_ID = "ldapSyntaxes";
  50     static final String MATCHRULEDESC_ATTR_ID = "matchingRules";


 124         attributeDefAttr = schemaAttrs.get(ATTRIBUTEDESC_ATTR_ID);
 125         if(attributeDefAttr != null) {
 126             attrDescs2AttrDefs(attributeDefAttr, schemaRoot);
 127         }
 128 
 129         syntaxDefAttr = schemaAttrs.get(SYNTAXDESC_ATTR_ID);
 130         if(syntaxDefAttr != null) {
 131             syntaxDescs2SyntaxDefs(syntaxDefAttr, schemaRoot);
 132         }
 133 
 134         matchRuleDefAttr = schemaAttrs.get(MATCHRULEDESC_ATTR_ID);
 135         if(matchRuleDefAttr != null) {
 136             matchRuleDescs2MatchRuleDefs(matchRuleDefAttr, schemaRoot);
 137         }
 138     }
 139 
 140     final private static DirContext objectDescs2ClassDefs(Attribute objDescsAttr,
 141                                                    LdapSchemaCtx schemaRoot)
 142         throws NamingException {
 143 
 144         NamingEnumeration       objDescs;
 145         Attributes      objDef;
 146         LdapSchemaCtx   classDefTree;
 147 
 148         // create the class def subtree
 149         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 150         attrs.put(CLASS_DEF_ATTRS[0], CLASS_DEF_ATTRS[1]);
 151         classDefTree = schemaRoot.setup(LdapSchemaCtx.OBJECTCLASS_ROOT,
 152             OBJECTCLASS_DEFINITION_NAME, attrs);
 153 
 154         objDescs = objDescsAttr.getAll();
 155         String currentName;
 156         while(objDescs.hasMore()) {
 157             String objDesc = (String)objDescs.next();
 158             try {
 159                 Object[] def = desc2Def(objDesc);
 160                 currentName = (String) def[0];
 161                 objDef = (Attributes) def[1];
 162                 classDefTree.setup(LdapSchemaCtx.OBJECTCLASS,
 163                     currentName, objDef);
 164             } catch (NamingException ne) {
 165                 // error occurred while parsing, ignore current entry
 166             }
 167         }
 168 
 169         return classDefTree;
 170     }
 171 
 172     final private static DirContext attrDescs2AttrDefs(Attribute attributeDescAttr,
 173                                                 LdapSchemaCtx schemaRoot)
 174         throws NamingException {
 175 
 176         NamingEnumeration       attrDescs;
 177         Attributes      attrDef;
 178         LdapSchemaCtx   attrDefTree;
 179 
 180         // create the AttributeDef subtree
 181         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 182         attrs.put(ATTR_DEF_ATTRS[0], ATTR_DEF_ATTRS[1]);
 183         attrDefTree = schemaRoot.setup(LdapSchemaCtx.ATTRIBUTE_ROOT,
 184             ATTRIBUTE_DEFINITION_NAME, attrs);
 185 
 186         attrDescs = attributeDescAttr.getAll();
 187         String currentName;
 188         while(attrDescs.hasMore()) {
 189             String attrDesc = (String)attrDescs.next();
 190             try {
 191                 Object[] def = desc2Def(attrDesc);
 192                 currentName = (String) def[0];
 193                 attrDef = (Attributes) def[1];
 194                 attrDefTree.setup(LdapSchemaCtx.ATTRIBUTE,
 195                     currentName, attrDef);
 196             } catch (NamingException ne) {
 197                 // error occurred while parsing, ignore current entry
 198             }
 199         }
 200 
 201         return attrDefTree;
 202     }
 203 
 204     final private static DirContext syntaxDescs2SyntaxDefs(
 205                                                 Attribute syntaxDescAttr,
 206                                                 LdapSchemaCtx schemaRoot)
 207         throws NamingException {
 208 
 209         NamingEnumeration       syntaxDescs;
 210         Attributes      syntaxDef;
 211         LdapSchemaCtx   syntaxDefTree;
 212 
 213         // create the SyntaxDef subtree
 214         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 215         attrs.put(SYNTAX_DEF_ATTRS[0], SYNTAX_DEF_ATTRS[1]);
 216         syntaxDefTree = schemaRoot.setup(LdapSchemaCtx.SYNTAX_ROOT,
 217             SYNTAX_DEFINITION_NAME, attrs);
 218 
 219         syntaxDescs = syntaxDescAttr.getAll();
 220         String currentName;
 221         while(syntaxDescs.hasMore()) {
 222             String syntaxDesc = (String)syntaxDescs.next();
 223             try {
 224                 Object[] def = desc2Def(syntaxDesc);
 225                 currentName = (String) def[0];
 226                 syntaxDef = (Attributes) def[1];
 227                 syntaxDefTree.setup(LdapSchemaCtx.SYNTAX,
 228                     currentName, syntaxDef);
 229             } catch (NamingException ne) {
 230                 // error occurred while parsing, ignore current entry
 231             }
 232         }
 233 
 234         return syntaxDefTree;
 235     }
 236 
 237     final private static DirContext matchRuleDescs2MatchRuleDefs(
 238                                                 Attribute matchRuleDescAttr,
 239                                                 LdapSchemaCtx schemaRoot)
 240         throws NamingException {
 241 
 242         NamingEnumeration       matchRuleDescs;
 243         Attributes      matchRuleDef;
 244         LdapSchemaCtx   matchRuleDefTree;
 245 
 246         // create the MatchRuleDef subtree
 247         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 248         attrs.put(MATCHRULE_DEF_ATTRS[0], MATCHRULE_DEF_ATTRS[1]);
 249         matchRuleDefTree = schemaRoot.setup(LdapSchemaCtx.MATCHRULE_ROOT,
 250             MATCHRULE_DEFINITION_NAME, attrs);
 251 
 252         matchRuleDescs = matchRuleDescAttr.getAll();
 253         String currentName;
 254         while(matchRuleDescs.hasMore()) {
 255             String matchRuleDesc = (String)matchRuleDescs.next();
 256             try {
 257                 Object[] def = desc2Def(matchRuleDesc);
 258                 currentName = (String) def[0];
 259                 matchRuleDef = (Attributes) def[1];
 260                 matchRuleDefTree.setup(LdapSchemaCtx.MATCHRULE,
 261                     currentName, matchRuleDef);
 262             } catch (NamingException ne) {


 503         switch( string.charAt(pos[0]) ) {
 504         case OID_LIST_BEGIN:
 505             return readQDescrList(string, pos);
 506         case SINGLE_QUOTE:
 507             return readQDString(string, pos);
 508         default:
 509             throw new InvalidAttributeValueException("unexpected oids " +
 510                                                      "string: " + string);
 511         }
 512     }
 513 
 514     /**
 515      * qdescrlist      = [ qdescr *( qdescr ) ]
 516      * qdescr          = whsp "'" descr "'" whsp
 517      * descr           = keystring
 518      */
 519     final private static String[] readQDescrList(String string, int[] pos)
 520         throws NamingException {
 521 
 522         int     begin, end;
 523         Vector  values = new Vector(5);
 524 
 525         if (debug) {
 526             System.err.println("ReadQDescrList: pos="+pos[0]);
 527         }
 528 
 529         pos[0]++; // skip '('
 530         skipWhitespace(string, pos);
 531         begin = pos[0];
 532         end = string.indexOf(OID_LIST_END, begin);
 533 
 534         if(end == -1) {
 535             throw new InvalidAttributeValueException ("oidlist has no end "+
 536                                                       "mark: " + string);
 537         }
 538 
 539         while(begin < end) {
 540             String[] one = readQDString(string,  pos);
 541 
 542             if (debug) {
 543                 System.err.println("ReadQDescrList: found '" + one[0] +
 544                                    "' at begin=" + begin + " end =" + end);
 545             }
 546 
 547             values.addElement(one[0]);
 548             skipWhitespace(string, pos);
 549             begin = pos[0];
 550         }
 551 
 552         pos[0] = end+1; // skip ')'
 553 
 554         String[] answer = new String[values.size()];
 555         for (int i = 0; i < answer.length; i++) {
 556             answer[i] = (String)values.elementAt(i);
 557         }
 558         return answer;
 559     }
 560 
 561     final private static String[] readWOID(String string, int[] pos)
 562         throws NamingException {
 563 
 564         if (debug) {
 565             System.err.println("readWOIDs: pos="+pos[0]);
 566         }
 567 
 568         skipWhitespace(string, pos);
 569 
 570         if (string.charAt(pos[0]) == SINGLE_QUOTE) {
 571             // %%% workaround for Netscape schema bug
 572             return readQDString(string, pos);
 573         }
 574 
 575         int begin, end;
 576 


 597      * oidlist         = woid *( "$" woid )
 598      */
 599     final private static String[] readOIDs(String string, int[] pos)
 600         throws NamingException {
 601 
 602         if (debug) {
 603             System.err.println("readOIDs: pos="+pos[0]);
 604         }
 605 
 606         skipWhitespace(string, pos);
 607 
 608         // Single OID
 609         if (string.charAt(pos[0]) != OID_LIST_BEGIN) {
 610             return readWOID(string, pos);
 611         }
 612 
 613         // Multiple OIDs
 614 
 615         int     begin, cur, end;
 616         String  oidName = null;
 617         Vector  values = new Vector(5);
 618 
 619         if (debug) {
 620             System.err.println("ReadOIDList: pos="+pos[0]);
 621         }
 622 
 623         pos[0]++;
 624         skipWhitespace(string, pos);
 625         begin = pos[0];
 626         end = string.indexOf(OID_LIST_END, begin);
 627         cur = string.indexOf(OID_SEPARATOR, begin);
 628 
 629         if(end == -1) {
 630             throw new InvalidAttributeValueException ("oidlist has no end "+
 631                                                       "mark: " + string);
 632         }
 633 
 634         if(cur == -1 || end < cur) {
 635             cur = end;
 636         }
 637 


 646             pos[0] = cur + 1;
 647             skipWhitespace(string, pos);
 648             begin = pos[0];
 649             cur = string.indexOf(OID_SEPARATOR, begin);
 650             if(debug) {System.err.println("ReadOIDList: begin = " + begin);}
 651         }
 652 
 653         if (debug) {
 654             System.err.println("ReadOIDList: found '" + oidName +
 655                                "' at begin=" + begin + " end =" + end);
 656         }
 657 
 658         int wsBegin = findTrailingWhitespace(string, end - 1);
 659         oidName = string.substring(begin, wsBegin);
 660         values.addElement(oidName);
 661 
 662         pos[0] = end+1;
 663 
 664         String[] answer = new String[values.size()];
 665         for (int i = 0; i < answer.length; i++) {
 666             answer[i] = (String)values.elementAt(i);
 667         }
 668         return answer;
 669     }
 670 
 671 // ----------------- "unparser" methods
 672 // Methods that are used for translating a node in the schema tree
 673 // into RFC2252 format for storage back into the LDAP directory
 674 /*
 675      static Attributes JNDI2LDAPSchema(DirContext schemaRoot)
 676         throws NamingException {
 677 
 678         Attribute objDescAttr = new BasicAttribute(OBJECTCLASSDESC_ATTR_ID);
 679         Attribute attrDescAttr = new BasicAttribute(ATTRIBUTEDESC_ATTR_ID);
 680         Attribute syntaxDescAttr = new BasicAttribute(SYNTAXDESC_ATTR_ID);
 681         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 682         DirContext classDefs, attributeDefs, syntaxDefs;
 683         Attributes classDefsAttrs, attributeDefsAttrs, syntaxDefsAttrs;
 684         NamingEnumeration defs;
 685         Object obj;
 686         int i = 0;


 826             count++;
 827         }
 828 
 829         attr = attrs.get(MUST_ID);
 830         if (attr != null) {
 831             objectDesc.append(writeOIDs(attr));
 832             count++;
 833         }
 834 
 835         attr = attrs.get(MAY_ID);
 836         if (attr != null) {
 837             objectDesc.append(writeOIDs(attr));
 838             count++;
 839         }
 840 
 841         // process any remaining attributes
 842         if (count < attrs.size()) {
 843             String attrId = null;
 844 
 845             // use enumeration because attribute ID is not known
 846             for (NamingEnumeration ae = attrs.getAll();
 847                 ae.hasMoreElements(); ) {
 848 
 849                 attr = (Attribute)ae.next();
 850                 attrId = attr.getID();
 851 
 852                 // skip those already processed
 853                 if (attrId.equals(NUMERICOID_ID) ||
 854                     attrId.equals(NAME_ID) ||
 855                     attrId.equals(SUP_ID) ||
 856                     attrId.equals(MAY_ID) ||
 857                     attrId.equals(MUST_ID) ||
 858                     attrId.equals(STRUCTURAL_ID) ||
 859                     attrId.equals(DESC_ID) ||
 860                     attrId.equals(AUXILARY_ID) ||
 861                     attrId.equals(ABSTRACT_ID) ||
 862                     attrId.equals(OBSOLETE_ID)) {
 863                     continue;
 864 
 865                 } else {
 866                     objectDesc.append(writeQDStrings(attr));
 867                 }
 868             }
 869         }


 956             count++;
 957         }
 958 
 959         attr = attrs.get(NO_USER_MOD_ID);
 960         if (attr != null) {
 961             attrDesc.append(writeBoolean(attr));
 962             count++;
 963         }
 964 
 965         attr = attrs.get(USAGE_ID);
 966         if (attr != null) {
 967             attrDesc.append(writeQDString(attr));
 968             count++;
 969         }
 970 
 971         // process any remaining attributes
 972         if (count < attrs.size()) {
 973             String attrId = null;
 974 
 975             // use enumeration because attribute ID is not known
 976             for (NamingEnumeration ae = attrs.getAll();
 977                 ae.hasMoreElements(); ) {
 978 
 979                 attr = (Attribute)ae.next();
 980                 attrId = attr.getID();
 981 
 982                 // skip those already processed
 983                 if (attrId.equals(NUMERICOID_ID) ||
 984                     attrId.equals(NAME_ID) ||
 985                     attrId.equals(SYNTAX_ID) ||
 986                     attrId.equals(DESC_ID) ||
 987                     attrId.equals(SINGLE_VAL_ID) ||
 988                     attrId.equals(EQUALITY_ID) ||
 989                     attrId.equals(ORDERING_ID) ||
 990                     attrId.equals(SUBSTR_ID) ||
 991                     attrId.equals(NO_USER_MOD_ID) ||
 992                     attrId.equals(USAGE_ID) ||
 993                     attrId.equals(SUP_ID) ||
 994                     attrId.equals(COLLECTIVE_ID) ||
 995                     attrId.equals(OBSOLETE_ID)) {
 996                     continue;
 997 
 998                 } else {
 999                     attrDesc.append(writeQDStrings(attr));


1023         attr = attrs.get(NUMERICOID_ID);
1024         if (attr != null) {
1025             syntaxDesc.append(writeNumericOID(attr));
1026             count++;
1027         } else {
1028             throw new ConfigurationException("Attribute type doesn't" +
1029                                              "have a numeric OID");
1030         }
1031 
1032         attr = attrs.get(DESC_ID);
1033         if (attr != null) {
1034             syntaxDesc.append(writeQDString(attr));
1035             count++;
1036         }
1037 
1038         // process any remaining attributes
1039         if (count < attrs.size()) {
1040             String attrId = null;
1041 
1042             // use enumeration because attribute ID is not known
1043             for (NamingEnumeration ae = attrs.getAll();
1044                 ae.hasMoreElements(); ) {
1045 
1046                 attr = (Attribute)ae.next();
1047                 attrId = attr.getID();
1048 
1049                 // skip those already processed
1050                 if (attrId.equals(NUMERICOID_ID) ||
1051                     attrId.equals(DESC_ID)) {
1052                     continue;
1053 
1054                 } else {
1055                     syntaxDesc.append(writeQDStrings(attr));
1056                 }
1057             }
1058         }
1059 
1060         syntaxDesc.append(")");
1061 
1062         return syntaxDesc.toString();
1063     }
1064 
1065     /**
1066       * Translate attributes that describe an attribute matching rule


1100         attr = attrs.get(OBSOLETE_ID);
1101         if (attr != null) {
1102             matchRuleDesc.append(writeBoolean(attr));
1103             count++;
1104         }
1105 
1106         attr = attrs.get(SYNTAX_ID);
1107         if (attr != null) {
1108             matchRuleDesc.append(writeWOID(attr));
1109             count++;
1110         } else {
1111             throw new ConfigurationException("Attribute type doesn't" +
1112                                              "have a syntax OID");
1113         }
1114 
1115         // process any remaining attributes
1116         if (count < attrs.size()) {
1117             String attrId = null;
1118 
1119             // use enumeration because attribute ID is not known
1120             for (NamingEnumeration ae = attrs.getAll();
1121                 ae.hasMoreElements(); ) {
1122 
1123                 attr = (Attribute)ae.next();
1124                 attrId = attr.getID();
1125 
1126                 // skip those already processed
1127                 if (attrId.equals(NUMERICOID_ID) ||
1128                     attrId.equals(NAME_ID) ||
1129                     attrId.equals(SYNTAX_ID) ||
1130                     attrId.equals(DESC_ID) ||
1131                     attrId.equals(OBSOLETE_ID)) {
1132                     continue;
1133 
1134                 } else {
1135                     matchRuleDesc.append(writeQDStrings(attr));
1136                 }
1137             }
1138         }
1139 
1140         matchRuleDesc.append(")");
1141 
1142         return matchRuleDesc.toString();
1143     }


1184      * qdescrs         = qdescr / ( whsp "(" qdescrlist ")" whsp )
1185      * qdescrlist      = [ qdescr *( qdescr ) ]
1186      * qdescr          = whsp "'" descr "'" whsp
1187      * descr           = keystring
1188      */
1189     private final String writeQDescrs(Attribute attr) throws NamingException {
1190         switch(attr.size()) {
1191         case 0:
1192             throw new InvalidAttributeValueException(
1193                 attr.getID() + "has no values");
1194         case 1:
1195             return writeQDString(attr);
1196         }
1197 
1198         // write QDList
1199 
1200         StringBuffer qdList = new StringBuffer(attr.getID());
1201         qdList.append(WHSP);
1202         qdList.append(OID_LIST_BEGIN);
1203 
1204         NamingEnumeration values = attr.getAll();
1205 
1206         while(values.hasMore()) {
1207             qdList.append(WHSP);
1208             qdList.append(SINGLE_QUOTE);
1209             qdList.append((String)values.next());
1210             qdList.append(SINGLE_QUOTE);
1211             qdList.append(WHSP);
1212         }
1213 
1214         qdList.append(OID_LIST_END);
1215         qdList.append(WHSP);
1216 
1217         return qdList.toString();
1218     }
1219 
1220     final private String writeOIDs(Attribute oidsAttr)
1221         throws NamingException {
1222 
1223         switch(oidsAttr.size()) {
1224         case 0:
1225             throw new InvalidAttributeValueException(
1226                 oidsAttr.getID() + "has no values");
1227 
1228         case 1:
1229             if (netscapeBug) {
1230                 break; // %%% write out as list to avoid crashing server
1231             }
1232             return writeWOID(oidsAttr);
1233         }
1234 
1235         // write OID List
1236 
1237         StringBuffer oidList = new StringBuffer(oidsAttr.getID());
1238         oidList.append(WHSP);
1239         oidList.append(OID_LIST_BEGIN);
1240 
1241         NamingEnumeration values = oidsAttr.getAll();
1242         oidList.append(WHSP);
1243         oidList.append(values.next());
1244 
1245         while(values.hasMore()) {
1246             oidList.append(WHSP);
1247             oidList.append(OID_SEPARATOR);
1248             oidList.append(WHSP);
1249             oidList.append((String)values.next());
1250         }
1251 
1252         oidList.append(WHSP);
1253         oidList.append(OID_LIST_END);
1254         oidList.append(WHSP);
1255 
1256         return oidList.toString();
1257     }
1258 
1259     private final String writeBoolean(Attribute booleanAttr)
1260         throws NamingException {
1261             return booleanAttr.getID() + WHSP;




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.jndi.ldap;
  27 
  28 import javax.naming.*;
  29 import javax.naming.directory.*;

  30 import java.util.Vector;
  31 
  32 /**
  33  * Netscape's 3.1 servers have some schema bugs:
  34  * - It puts quotes around OIDs (such as those for SUP, SYNTAX).
  35  * - When you try to write out the MUST/MAY list (such as "MUST cn"),
  36  *   it wants ("MUST (cn)") instead
  37  */
  38 
  39 final class LdapSchemaParser {
  40 
  41     // do debugging
  42     private static final boolean debug = false;
  43 
  44 
  45     // names of attribute IDs in the LDAP schema entry
  46     static final String OBJECTCLASSDESC_ATTR_ID = "objectClasses";
  47     static final String ATTRIBUTEDESC_ATTR_ID = "attributeTypes";
  48     static final String SYNTAXDESC_ATTR_ID = "ldapSyntaxes";
  49     static final String MATCHRULEDESC_ATTR_ID = "matchingRules";


 123         attributeDefAttr = schemaAttrs.get(ATTRIBUTEDESC_ATTR_ID);
 124         if(attributeDefAttr != null) {
 125             attrDescs2AttrDefs(attributeDefAttr, schemaRoot);
 126         }
 127 
 128         syntaxDefAttr = schemaAttrs.get(SYNTAXDESC_ATTR_ID);
 129         if(syntaxDefAttr != null) {
 130             syntaxDescs2SyntaxDefs(syntaxDefAttr, schemaRoot);
 131         }
 132 
 133         matchRuleDefAttr = schemaAttrs.get(MATCHRULEDESC_ATTR_ID);
 134         if(matchRuleDefAttr != null) {
 135             matchRuleDescs2MatchRuleDefs(matchRuleDefAttr, schemaRoot);
 136         }
 137     }
 138 
 139     final private static DirContext objectDescs2ClassDefs(Attribute objDescsAttr,
 140                                                    LdapSchemaCtx schemaRoot)
 141         throws NamingException {
 142 
 143         NamingEnumeration<?> objDescs;
 144         Attributes                objDef;
 145         LdapSchemaCtx             classDefTree;
 146 
 147         // create the class def subtree
 148         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 149         attrs.put(CLASS_DEF_ATTRS[0], CLASS_DEF_ATTRS[1]);
 150         classDefTree = schemaRoot.setup(LdapSchemaCtx.OBJECTCLASS_ROOT,
 151             OBJECTCLASS_DEFINITION_NAME, attrs);
 152 
 153         objDescs = objDescsAttr.getAll();
 154         String currentName;
 155         while(objDescs.hasMore()) {
 156             String objDesc = (String)objDescs.next();
 157             try {
 158                 Object[] def = desc2Def(objDesc);
 159                 currentName = (String) def[0];
 160                 objDef = (Attributes) def[1];
 161                 classDefTree.setup(LdapSchemaCtx.OBJECTCLASS,
 162                     currentName, objDef);
 163             } catch (NamingException ne) {
 164                 // error occurred while parsing, ignore current entry
 165             }
 166         }
 167 
 168         return classDefTree;
 169     }
 170 
 171     final private static DirContext attrDescs2AttrDefs(Attribute attributeDescAttr,
 172                                                 LdapSchemaCtx schemaRoot)
 173         throws NamingException {
 174 
 175         NamingEnumeration<?> attrDescs;
 176         Attributes           attrDef;
 177         LdapSchemaCtx        attrDefTree;
 178 
 179         // create the AttributeDef subtree
 180         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 181         attrs.put(ATTR_DEF_ATTRS[0], ATTR_DEF_ATTRS[1]);
 182         attrDefTree = schemaRoot.setup(LdapSchemaCtx.ATTRIBUTE_ROOT,
 183             ATTRIBUTE_DEFINITION_NAME, attrs);
 184 
 185         attrDescs = attributeDescAttr.getAll();
 186         String currentName;
 187         while(attrDescs.hasMore()) {
 188             String attrDesc = (String)attrDescs.next();
 189             try {
 190                 Object[] def = desc2Def(attrDesc);
 191                 currentName = (String) def[0];
 192                 attrDef = (Attributes) def[1];
 193                 attrDefTree.setup(LdapSchemaCtx.ATTRIBUTE,
 194                     currentName, attrDef);
 195             } catch (NamingException ne) {
 196                 // error occurred while parsing, ignore current entry
 197             }
 198         }
 199 
 200         return attrDefTree;
 201     }
 202 
 203     final private static DirContext syntaxDescs2SyntaxDefs(
 204                                                 Attribute syntaxDescAttr,
 205                                                 LdapSchemaCtx schemaRoot)
 206         throws NamingException {
 207 
 208         NamingEnumeration<?> syntaxDescs;
 209         Attributes           syntaxDef;
 210         LdapSchemaCtx        syntaxDefTree;
 211 
 212         // create the SyntaxDef subtree
 213         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 214         attrs.put(SYNTAX_DEF_ATTRS[0], SYNTAX_DEF_ATTRS[1]);
 215         syntaxDefTree = schemaRoot.setup(LdapSchemaCtx.SYNTAX_ROOT,
 216             SYNTAX_DEFINITION_NAME, attrs);
 217 
 218         syntaxDescs = syntaxDescAttr.getAll();
 219         String currentName;
 220         while(syntaxDescs.hasMore()) {
 221             String syntaxDesc = (String)syntaxDescs.next();
 222             try {
 223                 Object[] def = desc2Def(syntaxDesc);
 224                 currentName = (String) def[0];
 225                 syntaxDef = (Attributes) def[1];
 226                 syntaxDefTree.setup(LdapSchemaCtx.SYNTAX,
 227                     currentName, syntaxDef);
 228             } catch (NamingException ne) {
 229                 // error occurred while parsing, ignore current entry
 230             }
 231         }
 232 
 233         return syntaxDefTree;
 234     }
 235 
 236     final private static DirContext matchRuleDescs2MatchRuleDefs(
 237                                                 Attribute matchRuleDescAttr,
 238                                                 LdapSchemaCtx schemaRoot)
 239         throws NamingException {
 240 
 241         NamingEnumeration<?> matchRuleDescs;
 242         Attributes           matchRuleDef;
 243         LdapSchemaCtx        matchRuleDefTree;
 244 
 245         // create the MatchRuleDef subtree
 246         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 247         attrs.put(MATCHRULE_DEF_ATTRS[0], MATCHRULE_DEF_ATTRS[1]);
 248         matchRuleDefTree = schemaRoot.setup(LdapSchemaCtx.MATCHRULE_ROOT,
 249             MATCHRULE_DEFINITION_NAME, attrs);
 250 
 251         matchRuleDescs = matchRuleDescAttr.getAll();
 252         String currentName;
 253         while(matchRuleDescs.hasMore()) {
 254             String matchRuleDesc = (String)matchRuleDescs.next();
 255             try {
 256                 Object[] def = desc2Def(matchRuleDesc);
 257                 currentName = (String) def[0];
 258                 matchRuleDef = (Attributes) def[1];
 259                 matchRuleDefTree.setup(LdapSchemaCtx.MATCHRULE,
 260                     currentName, matchRuleDef);
 261             } catch (NamingException ne) {


 502         switch( string.charAt(pos[0]) ) {
 503         case OID_LIST_BEGIN:
 504             return readQDescrList(string, pos);
 505         case SINGLE_QUOTE:
 506             return readQDString(string, pos);
 507         default:
 508             throw new InvalidAttributeValueException("unexpected oids " +
 509                                                      "string: " + string);
 510         }
 511     }
 512 
 513     /**
 514      * qdescrlist      = [ qdescr *( qdescr ) ]
 515      * qdescr          = whsp "'" descr "'" whsp
 516      * descr           = keystring
 517      */
 518     final private static String[] readQDescrList(String string, int[] pos)
 519         throws NamingException {
 520 
 521         int begin, end;
 522         Vector<String> values = new Vector<>(5);
 523 
 524         if (debug) {
 525             System.err.println("ReadQDescrList: pos="+pos[0]);
 526         }
 527 
 528         pos[0]++; // skip '('
 529         skipWhitespace(string, pos);
 530         begin = pos[0];
 531         end = string.indexOf(OID_LIST_END, begin);
 532 
 533         if(end == -1) {
 534             throw new InvalidAttributeValueException ("oidlist has no end "+
 535                                                       "mark: " + string);
 536         }
 537 
 538         while(begin < end) {
 539             String[] one = readQDString(string,  pos);
 540 
 541             if (debug) {
 542                 System.err.println("ReadQDescrList: found '" + one[0] +
 543                                    "' at begin=" + begin + " end =" + end);
 544             }
 545 
 546             values.addElement(one[0]);
 547             skipWhitespace(string, pos);
 548             begin = pos[0];
 549         }
 550 
 551         pos[0] = end+1; // skip ')'
 552 
 553         String[] answer = new String[values.size()];
 554         for (int i = 0; i < answer.length; i++) {
 555             answer[i] = values.elementAt(i);
 556         }
 557         return answer;
 558     }
 559 
 560     final private static String[] readWOID(String string, int[] pos)
 561         throws NamingException {
 562 
 563         if (debug) {
 564             System.err.println("readWOIDs: pos="+pos[0]);
 565         }
 566 
 567         skipWhitespace(string, pos);
 568 
 569         if (string.charAt(pos[0]) == SINGLE_QUOTE) {
 570             // %%% workaround for Netscape schema bug
 571             return readQDString(string, pos);
 572         }
 573 
 574         int begin, end;
 575 


 596      * oidlist         = woid *( "$" woid )
 597      */
 598     final private static String[] readOIDs(String string, int[] pos)
 599         throws NamingException {
 600 
 601         if (debug) {
 602             System.err.println("readOIDs: pos="+pos[0]);
 603         }
 604 
 605         skipWhitespace(string, pos);
 606 
 607         // Single OID
 608         if (string.charAt(pos[0]) != OID_LIST_BEGIN) {
 609             return readWOID(string, pos);
 610         }
 611 
 612         // Multiple OIDs
 613 
 614         int     begin, cur, end;
 615         String  oidName = null;
 616         Vector<String> values = new Vector<>(5);
 617 
 618         if (debug) {
 619             System.err.println("ReadOIDList: pos="+pos[0]);
 620         }
 621 
 622         pos[0]++;
 623         skipWhitespace(string, pos);
 624         begin = pos[0];
 625         end = string.indexOf(OID_LIST_END, begin);
 626         cur = string.indexOf(OID_SEPARATOR, begin);
 627 
 628         if(end == -1) {
 629             throw new InvalidAttributeValueException ("oidlist has no end "+
 630                                                       "mark: " + string);
 631         }
 632 
 633         if(cur == -1 || end < cur) {
 634             cur = end;
 635         }
 636 


 645             pos[0] = cur + 1;
 646             skipWhitespace(string, pos);
 647             begin = pos[0];
 648             cur = string.indexOf(OID_SEPARATOR, begin);
 649             if(debug) {System.err.println("ReadOIDList: begin = " + begin);}
 650         }
 651 
 652         if (debug) {
 653             System.err.println("ReadOIDList: found '" + oidName +
 654                                "' at begin=" + begin + " end =" + end);
 655         }
 656 
 657         int wsBegin = findTrailingWhitespace(string, end - 1);
 658         oidName = string.substring(begin, wsBegin);
 659         values.addElement(oidName);
 660 
 661         pos[0] = end+1;
 662 
 663         String[] answer = new String[values.size()];
 664         for (int i = 0; i < answer.length; i++) {
 665             answer[i] = values.elementAt(i);
 666         }
 667         return answer;
 668     }
 669 
 670 // ----------------- "unparser" methods
 671 // Methods that are used for translating a node in the schema tree
 672 // into RFC2252 format for storage back into the LDAP directory
 673 /*
 674      static Attributes JNDI2LDAPSchema(DirContext schemaRoot)
 675         throws NamingException {
 676 
 677         Attribute objDescAttr = new BasicAttribute(OBJECTCLASSDESC_ATTR_ID);
 678         Attribute attrDescAttr = new BasicAttribute(ATTRIBUTEDESC_ATTR_ID);
 679         Attribute syntaxDescAttr = new BasicAttribute(SYNTAXDESC_ATTR_ID);
 680         Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
 681         DirContext classDefs, attributeDefs, syntaxDefs;
 682         Attributes classDefsAttrs, attributeDefsAttrs, syntaxDefsAttrs;
 683         NamingEnumeration defs;
 684         Object obj;
 685         int i = 0;


 825             count++;
 826         }
 827 
 828         attr = attrs.get(MUST_ID);
 829         if (attr != null) {
 830             objectDesc.append(writeOIDs(attr));
 831             count++;
 832         }
 833 
 834         attr = attrs.get(MAY_ID);
 835         if (attr != null) {
 836             objectDesc.append(writeOIDs(attr));
 837             count++;
 838         }
 839 
 840         // process any remaining attributes
 841         if (count < attrs.size()) {
 842             String attrId = null;
 843 
 844             // use enumeration because attribute ID is not known
 845             for (NamingEnumeration<? extends Attribute> ae = attrs.getAll();
 846                 ae.hasMoreElements(); ) {
 847 
 848                 attr = ae.next();
 849                 attrId = attr.getID();
 850 
 851                 // skip those already processed
 852                 if (attrId.equals(NUMERICOID_ID) ||
 853                     attrId.equals(NAME_ID) ||
 854                     attrId.equals(SUP_ID) ||
 855                     attrId.equals(MAY_ID) ||
 856                     attrId.equals(MUST_ID) ||
 857                     attrId.equals(STRUCTURAL_ID) ||
 858                     attrId.equals(DESC_ID) ||
 859                     attrId.equals(AUXILARY_ID) ||
 860                     attrId.equals(ABSTRACT_ID) ||
 861                     attrId.equals(OBSOLETE_ID)) {
 862                     continue;
 863 
 864                 } else {
 865                     objectDesc.append(writeQDStrings(attr));
 866                 }
 867             }
 868         }


 955             count++;
 956         }
 957 
 958         attr = attrs.get(NO_USER_MOD_ID);
 959         if (attr != null) {
 960             attrDesc.append(writeBoolean(attr));
 961             count++;
 962         }
 963 
 964         attr = attrs.get(USAGE_ID);
 965         if (attr != null) {
 966             attrDesc.append(writeQDString(attr));
 967             count++;
 968         }
 969 
 970         // process any remaining attributes
 971         if (count < attrs.size()) {
 972             String attrId = null;
 973 
 974             // use enumeration because attribute ID is not known
 975             for (NamingEnumeration<? extends Attribute> ae = attrs.getAll();
 976                 ae.hasMoreElements(); ) {
 977 
 978                 attr = ae.next();
 979                 attrId = attr.getID();
 980 
 981                 // skip those already processed
 982                 if (attrId.equals(NUMERICOID_ID) ||
 983                     attrId.equals(NAME_ID) ||
 984                     attrId.equals(SYNTAX_ID) ||
 985                     attrId.equals(DESC_ID) ||
 986                     attrId.equals(SINGLE_VAL_ID) ||
 987                     attrId.equals(EQUALITY_ID) ||
 988                     attrId.equals(ORDERING_ID) ||
 989                     attrId.equals(SUBSTR_ID) ||
 990                     attrId.equals(NO_USER_MOD_ID) ||
 991                     attrId.equals(USAGE_ID) ||
 992                     attrId.equals(SUP_ID) ||
 993                     attrId.equals(COLLECTIVE_ID) ||
 994                     attrId.equals(OBSOLETE_ID)) {
 995                     continue;
 996 
 997                 } else {
 998                     attrDesc.append(writeQDStrings(attr));


1022         attr = attrs.get(NUMERICOID_ID);
1023         if (attr != null) {
1024             syntaxDesc.append(writeNumericOID(attr));
1025             count++;
1026         } else {
1027             throw new ConfigurationException("Attribute type doesn't" +
1028                                              "have a numeric OID");
1029         }
1030 
1031         attr = attrs.get(DESC_ID);
1032         if (attr != null) {
1033             syntaxDesc.append(writeQDString(attr));
1034             count++;
1035         }
1036 
1037         // process any remaining attributes
1038         if (count < attrs.size()) {
1039             String attrId = null;
1040 
1041             // use enumeration because attribute ID is not known
1042             for (NamingEnumeration<? extends Attribute> ae = attrs.getAll();
1043                 ae.hasMoreElements(); ) {
1044 
1045                 attr = ae.next();
1046                 attrId = attr.getID();
1047 
1048                 // skip those already processed
1049                 if (attrId.equals(NUMERICOID_ID) ||
1050                     attrId.equals(DESC_ID)) {
1051                     continue;
1052 
1053                 } else {
1054                     syntaxDesc.append(writeQDStrings(attr));
1055                 }
1056             }
1057         }
1058 
1059         syntaxDesc.append(")");
1060 
1061         return syntaxDesc.toString();
1062     }
1063 
1064     /**
1065       * Translate attributes that describe an attribute matching rule


1099         attr = attrs.get(OBSOLETE_ID);
1100         if (attr != null) {
1101             matchRuleDesc.append(writeBoolean(attr));
1102             count++;
1103         }
1104 
1105         attr = attrs.get(SYNTAX_ID);
1106         if (attr != null) {
1107             matchRuleDesc.append(writeWOID(attr));
1108             count++;
1109         } else {
1110             throw new ConfigurationException("Attribute type doesn't" +
1111                                              "have a syntax OID");
1112         }
1113 
1114         // process any remaining attributes
1115         if (count < attrs.size()) {
1116             String attrId = null;
1117 
1118             // use enumeration because attribute ID is not known
1119             for (NamingEnumeration<? extends Attribute> ae = attrs.getAll();
1120                 ae.hasMoreElements(); ) {
1121 
1122                 attr = ae.next();
1123                 attrId = attr.getID();
1124 
1125                 // skip those already processed
1126                 if (attrId.equals(NUMERICOID_ID) ||
1127                     attrId.equals(NAME_ID) ||
1128                     attrId.equals(SYNTAX_ID) ||
1129                     attrId.equals(DESC_ID) ||
1130                     attrId.equals(OBSOLETE_ID)) {
1131                     continue;
1132 
1133                 } else {
1134                     matchRuleDesc.append(writeQDStrings(attr));
1135                 }
1136             }
1137         }
1138 
1139         matchRuleDesc.append(")");
1140 
1141         return matchRuleDesc.toString();
1142     }


1183      * qdescrs         = qdescr / ( whsp "(" qdescrlist ")" whsp )
1184      * qdescrlist      = [ qdescr *( qdescr ) ]
1185      * qdescr          = whsp "'" descr "'" whsp
1186      * descr           = keystring
1187      */
1188     private final String writeQDescrs(Attribute attr) throws NamingException {
1189         switch(attr.size()) {
1190         case 0:
1191             throw new InvalidAttributeValueException(
1192                 attr.getID() + "has no values");
1193         case 1:
1194             return writeQDString(attr);
1195         }
1196 
1197         // write QDList
1198 
1199         StringBuffer qdList = new StringBuffer(attr.getID());
1200         qdList.append(WHSP);
1201         qdList.append(OID_LIST_BEGIN);
1202 
1203         NamingEnumeration<?> values = attr.getAll();
1204 
1205         while(values.hasMore()) {
1206             qdList.append(WHSP);
1207             qdList.append(SINGLE_QUOTE);
1208             qdList.append((String)values.next());
1209             qdList.append(SINGLE_QUOTE);
1210             qdList.append(WHSP);
1211         }
1212 
1213         qdList.append(OID_LIST_END);
1214         qdList.append(WHSP);
1215 
1216         return qdList.toString();
1217     }
1218 
1219     final private String writeOIDs(Attribute oidsAttr)
1220         throws NamingException {
1221 
1222         switch(oidsAttr.size()) {
1223         case 0:
1224             throw new InvalidAttributeValueException(
1225                 oidsAttr.getID() + "has no values");
1226 
1227         case 1:
1228             if (netscapeBug) {
1229                 break; // %%% write out as list to avoid crashing server
1230             }
1231             return writeWOID(oidsAttr);
1232         }
1233 
1234         // write OID List
1235 
1236         StringBuffer oidList = new StringBuffer(oidsAttr.getID());
1237         oidList.append(WHSP);
1238         oidList.append(OID_LIST_BEGIN);
1239 
1240         NamingEnumeration<?> values = oidsAttr.getAll();
1241         oidList.append(WHSP);
1242         oidList.append(values.next());
1243 
1244         while(values.hasMore()) {
1245             oidList.append(WHSP);
1246             oidList.append(OID_SEPARATOR);
1247             oidList.append(WHSP);
1248             oidList.append((String)values.next());
1249         }
1250 
1251         oidList.append(WHSP);
1252         oidList.append(OID_LIST_END);
1253         oidList.append(WHSP);
1254 
1255         return oidList.toString();
1256     }
1257 
1258     private final String writeBoolean(Attribute booleanAttr)
1259         throws NamingException {
1260             return booleanAttr.getID() + WHSP;