/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.harmony.jndi.provider.ldap.parser;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.StringTokenizer;
import javax.naming.ConfigurationException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import org.apache.harmony.jndi.internal.nls.Messages;
public class SchemaParser {
public final static String SPACE = " "; //$NON-NLS-1$
public final static String LEFT_PARENTHESIS = "("; //$NON-NLS-1$
public final static String RIGHT_PARENTHESIS = ")"; //$NON-NLS-1$
public final static String SINGLE_QUOTE = "'"; //$NON-NLS-1$
public final static String DOLLAR = "$"; //$NON-NLS-1$
public final static String NAME = "NAME"; //$NON-NLS-1$
public final static String ORIG = "orig"; //$NON-NLS-1$
public final static String NUMERICOID = "NUMERICOID"; //$NON-NLS-1$
public final static String MUST = "MUST"; //$NON-NLS-1$
public final static String MAY = "MAY"; //$NON-NLS-1$
public final static String SUP = "SUP"; //$NON-NLS-1$
public final static String ABSTRACT = "ABSTRACT"; //$NON-NLS-1$
public final static String STRUCTURAL = "STRUCTURAL"; //$NON-NLS-1$
public final static String AUXILIARY = "AUXILIARY"; //$NON-NLS-1$
public final static String SINGLE_VALUE = "SINGLE-VALUE"; //$NON-NLS-1$
public final static String NO_USER_MODIFICATION = "NO-USER-MODIFICATION"; //$NON-NLS-1$
public final static String X_PREFIX = "X-"; //$NON-NLS-1$
public final static String DESC = "DESC"; //$NON-NLS-1$
public final static String USAGE = "USAGE"; //$NON-NLS-1$
public final static String EQUALITY = "EQUALITY"; //$NON-NLS-1$
public final static String SYNTAX = "SYNTAX"; //$NON-NLS-1$
public final static String SUBSTR = "SUBSTR"; //$NON-NLS-1$
public final static String ORDERING = "ORDERING"; //$NON-NLS-1$
public static String getName(String schemaLine) {
StringTokenizer st = new StringTokenizer(schemaLine);
st.nextToken();
String name = st.nextToken();
if (st.hasMoreTokens()) {
if (st.nextToken().equalsIgnoreCase(NAME)) {
name = st.nextToken();
if (name.equals(LEFT_PARENTHESIS)) {
name = st.nextToken();
}
name = name.substring(1, name.length() - 1);
}
}
return name;
}
public static Hashtable<String, Object> parseValue(String schemaLine) {
StringTokenizer st = new StringTokenizer(schemaLine);
// Skip (
st.nextToken();
String oid = st.nextToken();
Hashtable<String, Object> schemaDef = new Hashtable<String, Object>();
schemaDef.put(ORIG, schemaLine);
schemaDef.put(NUMERICOID, oid);
String token = null;
ArrayList<String> values = null;
StringBuilder desc = new StringBuilder();
while (st.hasMoreTokens()) {
String attrName = st.nextToken().toUpperCase();
if (attrName.startsWith(X_PREFIX)) {
token = st.nextToken();
// remove the ending ' symbol
token = token.substring(1, token.length() - 1);
schemaDef.put(attrName, token);
} else if (attrName.equals(USAGE) || attrName.equals(EQUALITY)
|| attrName.equals(SYNTAX) || attrName.equals(ORDERING)
|| attrName.equals(SUBSTR)) {
token = st.nextToken();
schemaDef.put(attrName, token);
} else if (attrName.equals(DESC)) {
token = st.nextToken();
// remove the leading ' symbol
if (token.startsWith(SINGLE_QUOTE)) {
token = token.substring(1);
}
while (token != null && !token.endsWith(SINGLE_QUOTE)) {
desc.append(token).append(SPACE);
token = st.nextToken();
}
if (token != null) {
// remove the ending ' symbol
desc.append(token.substring(0, token.length() - 1));
schemaDef.put(attrName, desc.toString());
desc.delete(0, desc.length());
}
} else if (attrName.equals(NAME)) {
token = st.nextToken();
values = new ArrayList<String>();
// Name has multiple values
if (token.startsWith(LEFT_PARENTHESIS)) {
token = st.nextToken();
while (!token.equals(RIGHT_PARENTHESIS)) {
// remove the leading ' symbol
if (token.startsWith(SINGLE_QUOTE)) {
token = token.substring(1);
}
while (!token.endsWith(SINGLE_QUOTE)) {
desc.append(token).append(SPACE);
token = st.nextToken();
}
// remove the ending ' symbol
desc.append(token.substring(0, token.length() - 1));
values.add(desc.toString());
desc.delete(0, desc.length());
token = st.nextToken();
}
} else {
// remove the leading ' symbol
if (token.startsWith(SINGLE_QUOTE)) {
token = token.substring(1);
}
while (token != null && !token.endsWith(SINGLE_QUOTE)) {
desc.append(token).append(SPACE);
token = st.nextToken();
}
if (token != null) {// remove the ending ' symbol
desc.append(token.substring(0, token.length() - 1));
values.add(desc.toString());
desc.delete(0, desc.length());
}
}
schemaDef.put(attrName, values);
} else if (attrName.equals(MUST) || attrName.equals(SUP)
|| attrName.equals(MAY)) {
token = st.nextToken();
values = new ArrayList<String>();
// has multiple values
if (token.startsWith(LEFT_PARENTHESIS)) {
token = st.nextToken();
while (!token.equals(RIGHT_PARENTHESIS)) {
if (!token.equals(DOLLAR))
values.add(token);
token = st.nextToken();
}
} else {
values.add(token);
}
schemaDef.put(attrName, values);
} else if (attrName.equals(ABSTRACT) || attrName.equals(STRUCTURAL)
|| attrName.equals(AUXILIARY)
|| attrName.equals(SINGLE_VALUE)
|| attrName.equals(NO_USER_MODIFICATION)) {
schemaDef.put(attrName, "true"); //$NON-NLS-1$
}
}
return schemaDef;
}
/*
* Format Attributes object to a string representation which can be
* understanded by server.
*/
public static String format(Attributes attributes) throws NamingException {
StringBuilder builder = new StringBuilder();
builder.append(LEFT_PARENTHESIS);
builder.append(SPACE);
Attribute attribute = attributes.get(NUMERICOID);
// The NUMERICOID must be presented. Throw exception if not.
if (attribute == null) {
// ldap.36=Must have numeric OID
throw new ConfigurationException(Messages.getString("ldap.36")); //$NON-NLS-1$
}
builder.append(attribute.get());
builder.append(SPACE);
NamingEnumeration<String> ids = attributes.getIDs();
/*
* Iterate each attribute, and append the correspoind string
* representation for each one.
*/
while (ids.hasMoreElements()) {
String id = ids.nextElement();
attribute = attributes.get(id);
// id is never null, so id.equals("something") can be used.
if (id.equals(MUST) || id.equals(MAY) || id.equals(SUP)) {
// Same kinds of attributes may have more than one value.
if (attribute.size() == 1) {
builder.append(id);
builder.append(SPACE);
builder.append(attribute.get());
builder.append(SPACE);
} else {
builder.append(id);
builder.append(SPACE);
builder.append(LEFT_PARENTHESIS);
builder.append(SPACE);
builder.append(attribute.get(0));
builder.append(SPACE);
for (int i = 1; i < attribute.size(); i++) {
builder.append(DOLLAR);
builder.append(SPACE);
builder.append(attribute.get(i));
builder.append(SPACE);
}
builder.append(RIGHT_PARENTHESIS);
builder.append(SPACE);
}
} else if (id.equals(ABSTRACT) || id.equals(STRUCTURAL)
|| id.equals(AUXILIARY) || id.equals(SINGLE_VALUE)
|| id.equals(NO_USER_MODIFICATION)) {
builder.append(id);
builder.append(SPACE);
} else if (!(id.equalsIgnoreCase(NUMERICOID))) {
builder.append(id);
builder.append(SPACE);
builder.append(SINGLE_QUOTE);
builder.append(attribute.get());
builder.append(SINGLE_QUOTE);
builder.append(SPACE);
}
}
builder.append(RIGHT_PARENTHESIS);
return builder.toString();
}
}