/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Netscape's 3.1 servers have some schema bugs:
* - It puts quotes around OIDs (such as those for SUP, SYNTAX).
* it wants ("MUST (cn)") instead
*/
final class LdapSchemaParser {
// do debugging
private static final boolean debug = false;
// names of attribute IDs in the LDAP schema entry
// information for creating internal nodes in JNDI schema tree
"ClassDefinition";
"objectclass", "ClassDefinition"};
"AttributeDefinition";
"objectclass", "AttributeDefinition" };
"SyntaxDefinition";
"objectclass", "SyntaxDefinition" };
"MatchingRule";
"objectclass", "MatchingRule" };
// special tokens used in LDAP schema descriptions
// common IDs
// Object Class specific IDs
// Attribute Type specific IDs
// The string value we give to boolean variables
// To get around writing schemas that crash Netscape server
private boolean netscapeBug;
this.netscapeBug = netscapeBug;
}
if(objectClassesAttr != null) {
}
if(attributeDefAttr != null) {
}
if(syntaxDefAttr != null) {
}
if(matchRuleDefAttr != null) {
}
}
throws NamingException {
// create the class def subtree
try {
} catch (NamingException ne) {
// error occurred while parsing, ignore current entry
}
}
return classDefTree;
}
throws NamingException {
// create the AttributeDef subtree
try {
} catch (NamingException ne) {
// error occurred while parsing, ignore current entry
}
}
return attrDefTree;
}
throws NamingException {
// create the SyntaxDef subtree
while(syntaxDescs.hasMore()) {
try {
} catch (NamingException ne) {
// error occurred while parsing, ignore current entry
}
}
return syntaxDefTree;
}
throws NamingException {
// create the MatchRuleDef subtree
while(matchRuleDescs.hasMore()) {
try {
} catch (NamingException ne) {
// error occurred while parsing, ignore current entry
}
}
return matchRuleDefTree;
}
throws NamingException {
//System.err.println(desc);
boolean moreTags = true;
// Always begins with <whsp numericoid whsp>
while (moreTags) {
}
moreTags = false;
}
}
}
// returns the index of the first whitespace char of a linear whitspace
// sequince ending at the given position.
for(int i = pos; i > 0; i--) {
return i + 1;
}
}
return 0;
}
pos[0] = i;
if (debug) {
}
return;
}
}
}
throws NamingException {
if (debug) {
}
throw new InvalidAttributeValueException("no numericoid found: "
+ string);
}
}
throws NamingException {
if (debug) {
}
// get the name and values of the attribute to return
// tolerate a schema that omits the trailing space
if (trailingSpace < 0) {
} else {
}
// make sure at least one value was returned
throw new InvalidAttributeValueException("no values for " +
"attribute \"" +
tagName + "\"");
}
// create the attribute, using the first value
// add other values if there are any
}
return attr;
}
throws NamingException {
if (debug) {
}
// move parser past tag name
}
}
if (
}
return new String[] {SCHEMA_TRUE_VALUE};
}
}
// otherwise it's a schema element with a quoted string value
}
throws NamingException {
if (debug) {
}
throw new InvalidAttributeIdentifierException("malformed " +
"QDString: " +
string);
}
// make sure the qdstring end symbol is there
throw new InvalidAttributeIdentifierException("qdstring has " +
"no end mark: " +
string);
}
}
/**
* dstring = 1*utf8
* qdstring = whsp "'" dstring "'" whsp
* qdstringlist = [ qdstring *( qdstring ) ]
* qdstrings = qdstring / ( whsp "(" qdstringlist ")" whsp )
*/
throws NamingException {
}
/**
* ; object descriptors used as schema element names
* qdescrs = qdescr / ( whsp "(" qdescrlist ")" whsp )
* qdescrlist = [ qdescr *( qdescr ) ]
* qdescr = whsp "'" descr "'" whsp
* descr = keystring
*/
throws NamingException {
if (debug) {
}
case OID_LIST_BEGIN:
case SINGLE_QUOTE:
default:
throw new InvalidAttributeValueException("unexpected oids " +
"string: " + string);
}
}
/**
* qdescrlist = [ qdescr *( qdescr ) ]
* qdescr = whsp "'" descr "'" whsp
* descr = keystring
*/
throws NamingException {
if (debug) {
}
if(end == -1) {
throw new InvalidAttributeValueException ("oidlist has no end "+
"mark: " + string);
}
if (debug) {
}
}
}
return answer;
}
throws NamingException {
if (debug) {
}
// %%% workaround for Netscape schema bug
}
if (debug) {
}
throw new InvalidAttributeIdentifierException("malformed " +
"OID: " +
string);
}
}
/*
* oids = woid / ( "(" oidlist ")" )
* oidlist = woid *( "$" woid )
*/
throws NamingException {
if (debug) {
}
// Single OID
}
// Multiple OIDs
if (debug) {
}
pos[0]++;
if(end == -1) {
throw new InvalidAttributeValueException ("oidlist has no end "+
"mark: " + string);
}
}
if (debug) {
}
}
if (debug) {
}
}
return answer;
}
// ----------------- "unparser" methods
// Methods that are used for translating a node in the schema tree
// into RFC2252 format for storage back into the LDAP directory
/*
static Attributes JNDI2LDAPSchema(DirContext schemaRoot)
throws NamingException {
Attribute objDescAttr = new BasicAttribute(OBJECTCLASSDESC_ATTR_ID);
Attribute attrDescAttr = new BasicAttribute(ATTRIBUTEDESC_ATTR_ID);
Attribute syntaxDescAttr = new BasicAttribute(SYNTAXDESC_ATTR_ID);
Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
DirContext classDefs, attributeDefs, syntaxDefs;
Attributes classDefsAttrs, attributeDefsAttrs, syntaxDefsAttrs;
NamingEnumeration defs;
Object obj;
int i = 0;
try {
obj = schemaRoot.lookup(OBJECTCLASS_DEFINITION_NAME);
if(obj != null && obj instanceof DirContext) {
classDefs = (DirContext)obj;
defs = classDefs.listBindings("");
while(defs.hasMoreElements()) {
i++;
DirContext classDef = (DirContext)
((Binding)(defs.next())).getObject();
classDefAttrs = classDef.getAttributes("");
objDescAttr.add(classDef2ObjectDesc(classDefAttrs));
}
if (debug)
System.err.println(i + " total object classes");
attrs.put(objDescAttr);
} else {
throw new NamingException(
"Problem with Schema tree: the object named " +
OBJECTCLASS_DEFINITION_NAME + " is not a " +
"DirContext");
}
} catch (NameNotFoundException e) {} // ignore
i=0;
try {
obj = schemaRoot.lookup(ATTRIBUTE_DEFINITION_NAME);
if(obj instanceof DirContext) {
attributeDefs = (DirContext)obj;
defs = attributeDefs.listBindings("");
while(defs.hasMoreElements()) {
i++;
DirContext attrDef = (DirContext)
((Binding)defs.next()).getObject();
attrDefAttrs = attrDef.getAttributes("");
attrDescAttr.add(attrDef2AttrDesc(attrDefAttrs));
}
if (debug)
System.err.println(i + " attribute definitions");
attrs.put(attrDescAttr);
} else {
throw new NamingException(
"Problem with schema tree: the object named " +
ATTRIBUTE_DEFINITION_NAME + " is not a " +
"DirContext");
}
} catch (NameNotFoundException e) {} // ignore
i=0;
try {
obj = schemaRoot.lookup(SYNTAX_DEFINITION_NAME);
if(obj instanceof DirContext) {
syntaxDefs = (DirContext)obj;
defs =syntaxDefs.listBindings("");
while(defs.hasMoreElements()) {
i++;
DirContext syntaxDef = (DirContext)
((Binding)defs.next()).getObject();
syntaxDefAttrs = syntaxDef.getAttributes("");
syntaxDescAttr.add(syntaxDef2SyntaxDesc(syntaxDefAttrs));
}
if (debug)
System.err.println(i + " total syntax definitions");
attrs.put(syntaxDescAttr);
} else {
throw new NamingException(
"Problem with schema tree: the object named " +
SYNTAX_DEFINITION_NAME + " is not a " +
"DirContext");
}
} catch (NameNotFoundException e) {} // ignore
return attrs;
}
*/
/**
* Translate attributes that describe an object class into the
* string description as defined in RFC 2252.
*/
throws NamingException {
int count = 0;
// extract attributes by ID to guarantee ordering
count++;
} else {
throw new ConfigurationException("Class definition doesn't" +
"have a numeric OID");
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
// process any remaining attributes
// use enumeration because attribute ID is not known
ae.hasMoreElements(); ) {
// skip those already processed
continue;
} else {
}
}
}
return objectDesc.toString();
}
/**
* Translate attributes that describe an attribute definition into the
* string description as defined in RFC 2252.
*/
throws NamingException {
int count = 0;
// extract attributes by ID to guarantee ordering
count++;
} else {
throw new ConfigurationException("Attribute type doesn't" +
"have a numeric OID");
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
count++;
}
// process any remaining attributes
// use enumeration because attribute ID is not known
ae.hasMoreElements(); ) {
// skip those already processed
continue;
} else {
}
}
}
}
/**
* Translate attributes that describe an attribute syntax definition into the
* string description as defined in RFC 2252.
*/
throws NamingException {
int count = 0;
// extract attributes by ID to guarantee ordering
count++;
} else {
throw new ConfigurationException("Attribute type doesn't" +
"have a numeric OID");
}
count++;
}
// process any remaining attributes
// use enumeration because attribute ID is not known
ae.hasMoreElements(); ) {
// skip those already processed
continue;
} else {
}
}
}
return syntaxDesc.toString();
}
/**
* Translate attributes that describe an attribute matching rule
* definition into the string description as defined in RFC 2252.
*/
throws NamingException {
int count = 0;
// extract attributes by ID to guarantee ordering
count++;
} else {
throw new ConfigurationException("Attribute type doesn't" +
"have a numeric OID");
}
count++;
}
count++;
}
count++;
}
count++;
} else {
throw new ConfigurationException("Attribute type doesn't" +
"have a syntax OID");
}
// process any remaining attributes
// use enumeration because attribute ID is not known
ae.hasMoreElements(); ) {
// skip those already processed
continue;
} else {
}
}
}
return matchRuleDesc.toString();
}
throws NamingException {
throw new InvalidAttributeValueException(
"A class definition must have exactly one numeric OID");
}
}
if (netscapeBug)
return writeQDString(attr);
else
}
/* qdescr = whsp "'" descr "'" whsp */
throws NamingException {
throw new InvalidAttributeValueException(
}
}
/**
* dstring = 1*utf8
* qdstring = whsp "'" dstring "'" whsp
* qdstringlist = [ qdstring *( qdstring ) ]
* qdstrings = qdstring / ( whsp "(" qdstringlist ")" whsp )
*/
return writeQDescrs(attr);
}
/**
* qdescrs = qdescr / ( whsp "(" qdescrlist ")" whsp )
* qdescrlist = [ qdescr *( qdescr ) ]
* qdescr = whsp "'" descr "'" whsp
* descr = keystring
*/
case 0:
throw new InvalidAttributeValueException(
case 1:
return writeQDString(attr);
}
// write QDList
}
}
throws NamingException {
case 0:
throw new InvalidAttributeValueException(
case 1:
if (netscapeBug) {
break; // %%% write out as list to avoid crashing server
}
}
// write OID List
}
}
throws NamingException {
}
/**
* Returns an attribute for updating the Object Class Definition schema
* attribute
*/
throws NamingException {
return objDescAttr;
}
/**
* Returns an attribute for updating the Attribute Definition schema attribute
*/
throws NamingException {
return attrDescAttr;
}
/**
* Returns an attribute for updating the Syntax schema attribute
*/
throws NamingException {
return syntaxDescAttr;
}
/**
* Returns an attribute for updating the Matching Rule schema attribute
*/
throws NamingException {
return matchRuleDescAttr;
}
}