You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2010/07/26 18:19:04 UTC

svn commit: r979343 - in /directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif: LdifAttributesReader.java LdifUtils.java

Author: elecharny
Date: Mon Jul 26 16:19:04 2010
New Revision: 979343

URL: http://svn.apache.org/viewvc?rev=979343&view=rev
Log:
Added some methods to parse a LDIF and returns a Schema aware entry

Modified:
    directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java
    directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java

Modified: directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java?rev=979343&r1=979342&r2=979343&view=diff
==============================================================================
--- directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java (original)
+++ directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifAttributesReader.java Mon Jul 26 16:19:04 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.shared.ldap.ldif;
 
@@ -33,90 +33,93 @@ import org.apache.directory.shared.i18n.
 import org.apache.directory.shared.ldap.entry.DefaultEntry;
 import org.apache.directory.shared.ldap.entry.Entry;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
 import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * <pre>
- *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; 
+ *  &lt;ldif-file&gt; ::= &quot;version:&quot; &lt;fill&gt; &lt;number&gt; &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt;
  *  &lt;ldif-content-change&gt;
- *  
- *  &lt;ldif-content-change&gt; ::= 
- *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
- *    &lt;ldif-attrval-record-e&gt; | 
- *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
- *    &lt;ldif-attrval-record-e&gt; | 
- *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
- *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *
+ *  &lt;ldif-content-change&gt; ::=
+ *    &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
+ *    &lt;ldif-attrval-record-e&gt; |
+ *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
+ *    &lt;ldif-attrval-record-e&gt; |
+ *    &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt;
+ *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt;
  *        &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; |
  *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt;
- *                              
- *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt; 
- *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; 
+ *
+ *  &lt;ldif-attrval-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;attributeType&gt;
+ *    &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt;
  *    &lt;ldif-attrval-record-e&gt; | e
- *                              
- *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; 
+ *
+ *  &lt;ldif-change-record-e&gt; ::= &lt;seps&gt; &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt;
  *    &quot;changetype:&quot; &lt;fill&gt; &lt;changerecord-type&gt; &lt;ldif-change-record-e&gt; | e
- *                              
+ *
  *  &lt;dn-spec&gt; ::= &quot;dn:&quot; &lt;fill&gt; &lt;safe-string&gt; | &quot;dn::&quot; &lt;fill&gt; &lt;base64-string&gt;
- *                              
- *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt; 
+ *
+ *  &lt;controls-e&gt; ::= &quot;control:&quot; &lt;fill&gt; &lt;number&gt; &lt;oid&gt; &lt;spaces-e&gt; &lt;criticality&gt;
  *    &lt;value-spec-e&gt; &lt;sep&gt; &lt;controls-e&gt; | e
- *                              
+ *
  *  &lt;criticality&gt; ::= &quot;true&quot; | &quot;false&quot; | e
- *                              
+ *
  *  &lt;oid&gt; ::= '.' &lt;number&gt; &lt;oid&gt; | e
- *                              
- *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; 
- *  &lt;attrval-specs-e&gt; | 
+ *
+ *  &lt;attrval-specs-e&gt; ::= &lt;number&gt; &lt;oid&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt;
+ *  &lt;attrval-specs-e&gt; |
  *    &lt;alpha&gt; &lt;chars-e&gt; &lt;options-e&gt; &lt;value-spec&gt; &lt;sep&gt; &lt;attrval-specs-e&gt; | e
- *                              
+ *
  *  &lt;value-spec-e&gt; ::= &lt;value-spec&gt; | e
- *  
- *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; | 
- *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; | 
+ *
+ *  &lt;value-spec&gt; ::= ':' &lt;fill&gt; &lt;safe-string-e&gt; |
+ *    &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt; |
  *    &quot;:&lt;&quot; &lt;fill&gt; &lt;url&gt;
- *  
+ *
  *  &lt;attributeType&gt; ::= &lt;number&gt; &lt;oid&gt; | &lt;alpha&gt; &lt;chars-e&gt;
- *  
+ *
  *  &lt;options-e&gt; ::= ';' &lt;char&gt; &lt;chars-e&gt; &lt;options-e&gt; |e
- *                              
+ *
  *  &lt;chars-e&gt; ::= &lt;char&gt; &lt;chars-e&gt; |  e
- *  
- *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;value-spec&gt; 
- *  &lt;sep&gt; &lt;attrval-specs-e&gt; | 
- *    &quot;delete&quot; &lt;sep&gt; | 
- *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;sep&gt; 
- *    &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | 
- *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; 
+ *
+ *  &lt;changerecord-type&gt; ::= &quot;add&quot; &lt;sep&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;value-spec&gt;
+ *  &lt;sep&gt; &lt;attrval-specs-e&gt; |
+ *    &quot;delete&quot; &lt;sep&gt; |
+ *    &quot;modify&quot; &lt;sep&gt; &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; &lt;sep&gt;
+ *    &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; |
+ *    &quot;moddn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt;
  *    &lt;newsuperior-e&gt; &lt;sep&gt; |
- *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt; 
+ *    &quot;modrdn&quot; &lt;sep&gt; &lt;newrdn&gt; &lt;sep&gt; &quot;deleteoldrdn:&quot; &lt;fill&gt; &lt;0-1&gt; &lt;sep&gt;
  *    &lt;newsuperior-e&gt; &lt;sep&gt;
- *  
+ *
  *  &lt;newrdn&gt; ::= ':' &lt;fill&gt; &lt;safe-string&gt; | &quot;::&quot; &lt;fill&gt; &lt;base64-chars&gt;
- *  
+ *
  *  &lt;newsuperior-e&gt; ::= &quot;newsuperior&quot; &lt;newrdn&gt; | e
- *  
- *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt; 
+ *
+ *  &lt;mod-specs-e&gt; ::= &lt;mod-type&gt; &lt;fill&gt; &lt;attributeType&gt; &lt;options-e&gt;
  *    &lt;sep&gt; &lt;attrval-specs-e&gt; &lt;sep&gt; '-' &lt;sep&gt; &lt;mod-specs-e&gt; | e
- *  
+ *
  *  &lt;mod-type&gt; ::= &quot;add:&quot; | &quot;delete:&quot; | &quot;replace:&quot;
- *  
+ *
  *  &lt;url&gt; ::= &lt;a Uniform Resource Locator, as defined in [6]&gt;
- *  
- *  
- *  
+ *
+ *
+ *
  *  LEXICAL
  *  -------
- *  
+ *
  *  &lt;fill&gt;           ::= ' ' &lt;fill&gt; | e
  *  &lt;char&gt;           ::= &lt;alpha&gt; | &lt;digit&gt; | '-'
  *  &lt;number&gt;         ::= &lt;digit&gt; &lt;digits&gt;
  *  &lt;0-1&gt;            ::= '0' | '1'
  *  &lt;digits&gt;         ::= &lt;digit&gt; &lt;digits&gt; | e
  *  &lt;digit&gt;          ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
- *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt; 
+ *  &lt;seps&gt;           ::= &lt;sep&gt; &lt;seps-e&gt;
  *  &lt;seps-e&gt;         ::= &lt;sep&gt; &lt;seps-e&gt; | e
  *  &lt;sep&gt;            ::= 0x0D 0x0A | 0x0A
  *  &lt;spaces&gt;         ::= ' ' &lt;spaces-e&gt;
@@ -130,17 +133,17 @@ import org.slf4j.LoggerFactory;
  *  &lt;base64-chars&gt;   ::= &lt;base64-char&gt; &lt;base64-chars&gt; | e
  *  &lt;base64-char&gt;    ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | [0x41-9x5A] | [0x61-0x7A]
  *  &lt;alpha&gt;          ::= [0x41-0x5A] | [0x61-0x7A]
- *  
+ *
  *  COMMENTS
  *  --------
  *  - The ldap-oid VN is not correct in the RFC-2849. It has been changed from 1*DIGIT 0*1(&quot;.&quot; 1*DIGIT) to
  *  DIGIT+ (&quot;.&quot; DIGIT+)*
  *  - The mod-spec lacks a sep between *attrval-spec and &quot;-&quot;.
  *  - The BASE64-UTF8-STRING should be BASE64-CHAR BASE64-STRING
- *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a 
+ *  - The ValueSpec rule must accept multilines values. In this case, we have a LF followed by a
  *  single space before the continued value.
  * </pre>
- * 
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public class LdifAttributesReader extends LdifReader
@@ -161,7 +164,7 @@ public class LdifAttributesReader extend
 
     /**
      * Parse an AttributeType/AttributeValue
-     * 
+     *
      * @param attributes The entry where to store the value
      * @param line The line to parse
      * @param lowerLine The same line, lowercased
@@ -184,7 +187,7 @@ public class LdifAttributesReader extend
 
         // Update the entry
         Attribute attribute = attributes.get( attributeType );
-        
+
         if ( attribute == null )
         {
             attributes.put( attributeType, attributeValue );
@@ -195,44 +198,83 @@ public class LdifAttributesReader extend
         }
     }
 
-    
+
 
 
     /**
      * Parse an AttributeType/AttributeValue
-     * 
+     *
      * @param attributes The entry where to store the value
      * @param line The line to parse
      * @param lowerLine The same line, lowercased
      * @throws NamingException If anything goes wrong
      */
-    private void parseEntryAttribute( Entry entry, String line, String lowerLine ) throws LdapLdifException
+    private void parseEntryAttribute( SchemaManager schemaManager, Entry entry, String line, String lowerLine ) throws LdapLdifException
     {
         int colonIndex = line.indexOf( ':' );
 
-        String attributeType = lowerLine.substring( 0, colonIndex );
+        String attributeName = lowerLine.substring( 0, colonIndex );
+        AttributeType attributeType = null;
 
         // We should *not* have a DN twice
-        if ( attributeType.equals( "dn" ) )
+        if ( attributeName.equals( "dn" ) )
         {
             LOG.error( I18n.err( I18n.ERR_12002 ) );
             throw new LdapLdifException( I18n.err( I18n.ERR_12003 ) );
         }
 
+        if ( schemaManager != null )
+        {
+            if ( ( attributeType = schemaManager.getAttributeType( attributeName ) ) == null )
+            {
+                LOG.error( "" );
+                throw new LdapLdifException( "" );
+            }
+        }
+
         Object attributeValue = parseValue( line, colonIndex );
 
         // Update the entry
-        EntryAttribute attribute = entry.get( attributeType );
-        
+        EntryAttribute attribute = null;
+
+        if ( schemaManager == null )
+        {
+            attribute = entry.get( attributeName );
+        }
+        else
+        {
+            attribute = entry.get( attributeType );
+        }
+
         if ( attribute == null )
         {
-            if ( attributeValue instanceof String )
+            if ( schemaManager == null )
             {
-                entry.put( attributeType, (String)attributeValue );
+                if ( attributeValue instanceof String )
+                {
+                    entry.put( attributeName, (String)attributeValue );
+                }
+                else
+                {
+                    entry.put( attributeName, (byte[])attributeValue );
+                }
             }
             else
             {
-                entry.put( attributeType, (byte[])attributeValue );
+                try
+                {
+                    if ( attributeValue instanceof String )
+                    {
+                        entry.put( attributeName, attributeType, (String)attributeValue );
+                    }
+                    else
+                    {
+                        entry.put( attributeName, attributeType, (byte[])attributeValue );
+                    }
+                }
+                catch ( LdapException le )
+                {
+                }
             }
         }
         else
@@ -248,21 +290,21 @@ public class LdifAttributesReader extend
         }
     }
 
-    
+
     /**
      * Parse a ldif file. The following rules are processed :
-     * 
+     *
      * &lt;ldif-file&gt; ::= &lt;ldif-attrval-record&gt; &lt;ldif-attrval-records&gt; |
      * &lt;ldif-change-record&gt; &lt;ldif-change-records&gt; &lt;ldif-attrval-record&gt; ::=
      * &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt; &lt;ldif-change-record&gt; ::=
      * &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt;
      * &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
      * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
-     * 
+     *
      * @return The read entry
      * @throws LdapLdifException If the entry can't be read or is invalid
      */
-    private Entry parseEntry() throws LdapLdifException
+    private Entry parseEntry( SchemaManager schemaManager ) throws LdapLdifException
     {
         if ( ( lines == null ) || ( lines.size() == 0 ) )
         {
@@ -270,7 +312,16 @@ public class LdifAttributesReader extend
             return null;
         }
 
-        Entry entry = new DefaultEntry();
+        Entry entry = null;
+
+        if ( schemaManager != null )
+        {
+            entry = new DefaultEntry( schemaManager );
+        }
+        else
+        {
+            entry = new DefaultEntry();
+        }
 
         // Now, let's iterate through the other lines
         for ( String line:lines )
@@ -295,7 +346,7 @@ public class LdifAttributesReader extend
             }
             else if ( line.indexOf( ':' ) > 0 )
             {
-                parseEntryAttribute( entry, line, lowerLine );
+                parseEntryAttribute( schemaManager, entry, line, lowerLine );
             }
             else
             {
@@ -306,21 +357,21 @@ public class LdifAttributesReader extend
         }
 
         LOG.debug( "Read an attributes : {}", entry );
-        
+
         return entry;
     }
 
 
     /**
      * Parse a ldif file. The following rules are processed :
-     * 
+     *
      * &lt;ldif-file&gt; ::= &lt;ldif-attrval-record&gt; &lt;ldif-attrval-records&gt; |
      * &lt;ldif-change-record&gt; &lt;ldif-change-records&gt; &lt;ldif-attrval-record&gt; ::=
      * &lt;dn-spec&gt; &lt;sep&gt; &lt;attrval-spec&gt; &lt;attrval-specs&gt; &lt;ldif-change-record&gt; ::=
      * &lt;dn-spec&gt; &lt;sep&gt; &lt;controls-e&gt; &lt;changerecord&gt; &lt;dn-spec&gt; ::= "dn:" &lt;fill&gt;
      * &lt;distinguishedName&gt; | "dn::" &lt;fill&gt; &lt;base64-distinguishedName&gt;
      * &lt;changerecord&gt; ::= "changetype:" &lt;fill&gt; &lt;change-op&gt;
-     * 
+     *
      * @return The read entry
      * @throws NamingException If the entry can't be read or is invalid
      */
@@ -368,14 +419,14 @@ public class LdifAttributesReader extend
         }
 
         LOG.debug( "Read an attributes : {}", attributes );
-        
+
         return attributes;
     }
 
 
     /**
      * A method which parses a ldif string and returns a list of Attributes.
-     * 
+     *
      * @param ldif The ldif string
      * @return A list of Attributes, or an empty List
      * @throws LdapLdifException If something went wrong
@@ -400,7 +451,7 @@ public class LdifAttributesReader extend
         try
         {
             readLines();
-            
+
             Attributes attributes = parseAttributes();
 
             if ( LOG.isDebugEnabled() )
@@ -427,11 +478,11 @@ public class LdifAttributesReader extend
             }
         }
     }
-    
-    
+
+
     /**
      * A method which parses a ldif string and returns an Entry.
-     * 
+     *
      * @param ldif The ldif string
      * @return An entry
      * @throws LdapLdifException If something went wrong
@@ -456,8 +507,64 @@ public class LdifAttributesReader extend
         try
         {
             readLines();
-            
-            Entry entry = parseEntry();
+
+            Entry entry = parseEntry( (SchemaManager)null );
+
+            if ( LOG.isDebugEnabled() )
+            {
+                LOG.debug( "Parsed {} entries.", ( entry == null ? 0 : 1 ) );
+            }
+
+            return entry;
+        }
+        catch (LdapLdifException ne)
+        {
+            LOG.error( I18n.err( I18n.ERR_12008, ne.getLocalizedMessage() ) );
+            throw new LdapLdifException( I18n.err( I18n.ERR_12009 ) );
+        }
+        finally
+        {
+            try
+            {
+                reader.close();
+            }
+            catch ( IOException ioe )
+            {
+                // Do nothing
+            }
+        }
+    }
+
+
+    /**
+     * A method which parses a ldif string and returns an Entry.
+     *
+     * @param ldif The ldif string
+     * @return An entry
+     * @throws LdapLdifException If something went wrong
+     */
+    // This will suppress PMD.EmptyCatchBlock warnings in this method
+    @SuppressWarnings("PMD.EmptyCatchBlock")
+    public Entry parseEntry( SchemaManager schemaManager, String ldif ) throws LdapLdifException
+    {
+        lines = new ArrayList<String>();
+        position = new Position();
+
+        LOG.debug( "Starts parsing ldif buffer" );
+
+        if ( StringTools.isEmpty( ldif ) )
+        {
+            return new DefaultEntry();
+        }
+
+        StringReader strIn = new StringReader( ldif );
+        reader = new BufferedReader( strIn );
+
+        try
+        {
+            readLines();
+
+            Entry entry = parseEntry( schemaManager );
 
             if ( LOG.isDebugEnabled() )
             {

Modified: directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java?rev=979343&r1=979342&r2=979343&view=diff
==============================================================================
--- directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java (original)
+++ directory/shared/trunk/ldap-ldif/src/main/java/org/apache/directory/shared/ldap/ldif/LdifUtils.java Mon Jul 26 16:19:04 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.shared.ldap.ldif;
 
@@ -34,6 +34,7 @@ import org.apache.directory.shared.ldap.
 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
 import org.apache.directory.shared.ldap.message.control.Control;
 import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
 import org.apache.directory.shared.ldap.util.AttributeUtils;
 import org.apache.directory.shared.ldap.util.Base64;
 import org.apache.directory.shared.ldap.util.StringTools;
@@ -49,48 +50,48 @@ public class LdifUtils
 {
     /** The array that will be used to match the first char.*/
     private static boolean[] LDIF_SAFE_STARTING_CHAR_ALPHABET = new boolean[128];
-    
+
     /** The array that will be used to match the other chars.*/
     private static boolean[] LDIF_SAFE_OTHER_CHARS_ALPHABET = new boolean[128];
-    
+
     /** The default length for a line in a ldif file */
     private static final int DEFAULT_LINE_LENGTH = 80;
-    
+
     private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
-    
+
     static
     {
         // Initialization of the array that will be used to match the first char.
-        for (int i = 0; i < 128; i++) 
+        for (int i = 0; i < 128; i++)
         {
             LDIF_SAFE_STARTING_CHAR_ALPHABET[i] = true;
         }
-        
+
         LDIF_SAFE_STARTING_CHAR_ALPHABET[0] = false; // 0 (NUL)
         LDIF_SAFE_STARTING_CHAR_ALPHABET[10] = false; // 10 (LF)
         LDIF_SAFE_STARTING_CHAR_ALPHABET[13] = false; // 13 (CR)
         LDIF_SAFE_STARTING_CHAR_ALPHABET[32] = false; // 32 (SPACE)
         LDIF_SAFE_STARTING_CHAR_ALPHABET[58] = false; // 58 (:)
         LDIF_SAFE_STARTING_CHAR_ALPHABET[60] = false; // 60 (>)
-        
+
         // Initialization of the array that will be used to match the other chars.
-        for (int i = 0; i < 128; i++) 
+        for (int i = 0; i < 128; i++)
         {
             LDIF_SAFE_OTHER_CHARS_ALPHABET[i] = true;
         }
-        
+
         LDIF_SAFE_OTHER_CHARS_ALPHABET[0] = false; // 0 (NUL)
         LDIF_SAFE_OTHER_CHARS_ALPHABET[10] = false; // 10 (LF)
         LDIF_SAFE_OTHER_CHARS_ALPHABET[13] = false; // 13 (CR)
     }
 
-    
+
     /**
      * Checks if the input String contains only safe values, that is, the data
      * does not need to be encoded for use with LDIF. The rules for checking safety
      * are based on the rules for LDIF (LDAP Data Interchange Format) per RFC 2849.
      * The data does not need to be encoded if all the following are true:
-     * 
+     *
      * The data cannot start with the following char values:
      *         00 (NUL)
      *         10 (LF)
@@ -99,15 +100,15 @@ public class LdifUtils
      *         58 (:)
      *         60 (<)
      *         Any character with value greater than 127
-     * 
+     *
      * The data cannot contain any of the following char values:
      *         00 (NUL)
      *         10 (LF)
      *         13 (CR)
      *         Any character with value greater than 127
-     * 
+     *
      * The data cannot end with a space.
-     * 
+     *
      * @param str the String to be checked
      * @return true if encoding not required for LDIF
      */
@@ -118,31 +119,31 @@ public class LdifUtils
             // A null string is LDIF safe
             return true;
         }
-        
+
         // Checking the first char
         char currentChar = str.charAt(0);
-        
+
         if ( ( currentChar > 127 ) || !LDIF_SAFE_STARTING_CHAR_ALPHABET[currentChar] )
         {
             return false;
         }
-        
+
         // Checking the other chars
         for (int i = 1; i < str.length(); i++)
         {
             currentChar = str.charAt(i);
-            
+
             if ( ( currentChar > 127 ) || !LDIF_SAFE_OTHER_CHARS_ALPHABET[currentChar] )
             {
                 return false;
             }
         }
-        
+
         // The String cannot end with a space
         return ( currentChar != ' ' );
     }
-    
-    
+
+
     /**
      * Convert an Attributes as LDIF
      * @param attrs the Attributes to convert
@@ -153,8 +154,8 @@ public class LdifUtils
     {
         return convertAttributesToLdif( AttributeUtils.toClientEntry( attrs, null ), DEFAULT_LINE_LENGTH );
     }
-    
-    
+
+
     /**
      * Convert an Attributes as LDIF
      * @param attrs the Attributes to convert
@@ -165,8 +166,8 @@ public class LdifUtils
     {
         return convertAttributesToLdif( AttributeUtils.toClientEntry( attrs, null ), length );
     }
-    
-    
+
+
     /**
      * Convert an Attributes as LDIF. The DN is written.
      * @param attrs the Attributes to convert
@@ -177,8 +178,8 @@ public class LdifUtils
     {
         return convertEntryToLdif( AttributeUtils.toClientEntry( attrs, dn ), length );
     }
-    
-    
+
+
     /**
      * Convert an Attributes as LDIF. The DN is written.
      * @param attrs the Attributes to convert
@@ -189,8 +190,8 @@ public class LdifUtils
     {
         return convertEntryToLdif( AttributeUtils.toClientEntry( attrs, dn ), DEFAULT_LINE_LENGTH );
     }
-    
-    
+
+
     /**
      * Convert an Entry to LDIF
      * @param entry the Entry to convert
@@ -201,7 +202,7 @@ public class LdifUtils
     {
         return convertEntryToLdif( entry, DEFAULT_LINE_LENGTH );
     }
-    
+
 
     /**
      * Convert an Entry to LDIF including a version number at the top
@@ -209,20 +210,20 @@ public class LdifUtils
      * @param includeVersionInfo flag to tell whether to include version number or not
      * @return the corresponding LDIF code as a String
      * @throws LdapException If a naming exception is encountered.
-     */    
+     */
     public static String convertEntryToLdif( Entry entry, boolean includeVersionInfo ) throws LdapException
     {
         String ldif = convertEntryToLdif( entry, DEFAULT_LINE_LENGTH );
-        
+
         if( includeVersionInfo )
         {
             ldif = "version: 1" + LINE_SEPARATOR + ldif;
         }
-        
+
         return ldif;
     }
 
-    
+
     /**
      * Convert all the Entry's attributes to LDIF. The DN is not written
      * @param entry the Entry to convert
@@ -233,11 +234,11 @@ public class LdifUtils
     {
         return convertAttributesToLdif( entry, DEFAULT_LINE_LENGTH );
     }
-    
-    
+
+
     /**
      * Convert a LDIF String to an attributes.
-     * 
+     *
      * @param ldif The LDIF string containing an attribute value
      * @return An Attributes instance
      * @exception LdapException If the LDIF String cannot be converted to an Attributes
@@ -245,11 +246,11 @@ public class LdifUtils
     public static Attributes convertAttributesFromLdif( String ldif ) throws LdapLdifException
     {
         LdifAttributesReader reader = new  LdifAttributesReader();
-        
+
         return AttributeUtils.toAttributes( reader.parseEntry( ldif ) );
     }
-    
-    
+
+
     /**
      * Convert an Entry as LDIF
      * @param entry the Entry to convert
@@ -260,7 +261,7 @@ public class LdifUtils
     public static String convertEntryToLdif( Entry entry, int length ) throws LdapException
     {
         StringBuilder sb = new StringBuilder();
-        
+
         if ( entry.getDn() != null )
         {
             // First, dump the DN
@@ -272,7 +273,7 @@ public class LdifUtils
             {
                 sb.append( stripLineToNChars( "dn:: " + encodeBase64( entry.getDn().getName() ), length ) );
             }
-        
+
             sb.append( '\n' );
         }
 
@@ -281,11 +282,11 @@ public class LdifUtils
         {
             sb.append( convertToLdif( attribute, length ) );
         }
-        
+
         return sb.toString();
     }
-    
-    
+
+
     /**
      * Convert the Entry's attributes to LDIF. The DN is not written.
      * @param entry the Entry to convert
@@ -296,17 +297,17 @@ public class LdifUtils
     public static String convertAttributesToLdif( Entry entry, int length ) throws LdapException
     {
         StringBuilder sb = new StringBuilder();
-        
+
         // Then all the attributes
         for ( EntryAttribute attribute:entry )
         {
             sb.append( convertToLdif( attribute, length ) );
         }
-        
+
         return sb.toString();
     }
 
-    
+
     /**
      * Convert an LdifEntry to LDIF
      * @param entry the LdifEntry to convert
@@ -318,18 +319,18 @@ public class LdifUtils
         return convertToLdif( entry, DEFAULT_LINE_LENGTH );
     }
 
-    
+
     /**
      * Convert an LdifEntry to LDIF
      * @param entry the LdifEntry to convert
-     * @param length The maximum line's length 
+     * @param length The maximum line's length
      * @return the corresponding LDIF as a String
      * @throws LdapException If a naming exception is encountered.
      */
     public static String convertToLdif( LdifEntry entry, int length ) throws LdapException
     {
         StringBuilder sb = new StringBuilder();
-        
+
         // First, dump the DN
         if ( isLDIFSafe( entry.getDn().getName() ) )
         {
@@ -339,12 +340,12 @@ public class LdifUtils
         {
             sb.append( stripLineToNChars( "dn:: " + encodeBase64( entry.getDn().getName() ), length ) );
         }
-        
+
         sb.append( '\n' );
-        
+
         // Dump the ChangeType
         String changeType = entry.getChangeType().toString().toLowerCase();
-        
+
         if ( entry.getChangeType() != ChangeType.None )
         {
             // First dump the controls if any
@@ -353,34 +354,34 @@ public class LdifUtils
                 for ( Control control : entry.getControls().values() )
                 {
                     StringBuilder controlStr = new StringBuilder();
-                    
+
                     controlStr.append( "control: " ).append( control.getOid() );
                     controlStr.append( " " ).append( control.isCritical() );
-                    
+
                     if ( control.hasValue() )
                     {
                         controlStr.append( "::" ).append( Base64.encode( control.getValue() ) );
                     }
-                    
+
                     sb.append( stripLineToNChars( controlStr.toString(), length ) );
                     sb.append( '\n' );
                 }
             }
-            
+
             sb.append( stripLineToNChars( "changetype: " + changeType, length ) );
             sb.append( '\n' );
         }
 
         switch ( entry.getChangeType() )
         {
-            case None : 
+            case None :
                 if ( entry.hasControls() )
                 {
                     sb.append( stripLineToNChars( "changetype: " + ChangeType.Add, length ) );
                 }
-                
+
                 // Fallthrough
-                
+
             case Add :
                 if ( ( entry.getEntry() == null ) )
                 {
@@ -392,7 +393,7 @@ public class LdifUtils
                 {
                     sb.append( convertToLdif( attribute, length ) );
                 }
-                
+
                 break;
 
             case Delete :
@@ -400,24 +401,24 @@ public class LdifUtils
                 {
                     throw new LdapException( I18n.err( I18n.ERR_12081 ) );
                 }
-                
+
                 break;
-                
+
             case ModDn :
             case ModRdn :
                 if ( entry.getEntry() != null )
                 {
                     throw new LdapException( I18n.err( I18n.ERR_12083 ) );
                 }
-                
-                
+
+
                 // Stores the new RDN
                 EntryAttribute newRdn = new DefaultEntryAttribute( "newrdn", entry.getNewRdn() );
                 sb.append( convertToLdif( newRdn, length ) );
 
                 // Stores the deleteoldrdn flag
                 sb.append( "deleteoldrdn: " );
-                
+
                 if ( entry.isDeleteOldRdn() )
                 {
                     sb.append( "1" );
@@ -426,18 +427,18 @@ public class LdifUtils
                 {
                     sb.append( "0" );
                 }
-                
+
                 sb.append( '\n' );
-                
+
                 // Stores the optional newSuperior
                 if ( ! StringTools.isEmpty( entry.getNewSuperior() ) )
                 {
                     EntryAttribute newSuperior = new DefaultEntryAttribute( "newsuperior", entry.getNewSuperior() );
                     sb.append( convertToLdif( newSuperior, length ) );
                 }
-                
+
                 break;
-                
+
             case Modify :
                 for ( Modification modification:entry.getModificationItems() )
                 {
@@ -446,38 +447,38 @@ public class LdifUtils
                         case ADD_ATTRIBUTE :
                             sb.append( "add: " );
                             break;
-                            
+
                         case REMOVE_ATTRIBUTE :
                             sb.append( "delete: " );
                             break;
-                            
+
                         case REPLACE_ATTRIBUTE :
                             sb.append( "replace: " );
                             break;
-                            
+
                         default :
                             break; // Do nothing
-                            
+
                     }
-                    
+
                     sb.append( modification.getAttribute().getId() );
                     sb.append( '\n' );
-                    
+
                     sb.append( convertToLdif( modification.getAttribute() ) );
                     sb.append( "-\n" );
                 }
                 break;
-                
+
             default :
                 break; // Do nothing
-                
+
         }
-        
+
         sb.append( '\n' );
-        
+
         return sb.toString();
     }
-    
+
     /**
      * Base64 encode a String
      * @param str The string to encode
@@ -486,7 +487,7 @@ public class LdifUtils
     private static String encodeBase64( String str )
     {
         char[] encoded =null;
-        
+
         try
         {
             // force encoding using UTF-8 charset, as required in RFC2849 note 7
@@ -496,10 +497,10 @@ public class LdifUtils
         {
             encoded = Base64.encode( str.getBytes() );
         }
-        
+
         return new String( encoded );
     }
-    
+
 
     /**
      * Converts an EntryAttribute to LDIF
@@ -511,8 +512,8 @@ public class LdifUtils
     {
         return convertToLdif( attr, DEFAULT_LINE_LENGTH );
     }
-    
-    
+
+
     /**
      * Converts an EntryAttribute as LDIF
      * @param attr the EntryAttribute to convert
@@ -523,13 +524,13 @@ public class LdifUtils
     public static String convertToLdif( EntryAttribute attr, int length ) throws LdapException
     {
         StringBuilder sb = new StringBuilder();
-        
+
         for ( Value<?> value:attr )
         {
             StringBuilder lineBuffer = new StringBuilder();
-            
+
             lineBuffer.append( attr.getUpId() );
-            
+
             // First, deal with null value (which is valid)
             if ( value.isNull() )
             {
@@ -539,14 +540,14 @@ public class LdifUtils
             {
                 // It is binary, so we have to encode it using Base64 before adding it
                 char[] encoded = Base64.encode( value.getBytes() );
-                
-                lineBuffer.append( ":: " + new String( encoded ) );                            
+
+                lineBuffer.append( ":: " + new String( encoded ) );
             }
             else if ( !value.isBinary() )
             {
                 // It's a String but, we have to check if encoding isn't required
                 String str = value.getString();
-                
+
                 if ( !LdifUtils.isLDIFSafe( str ) )
                 {
                     lineBuffer.append( ":: " + encodeBase64( str ) );
@@ -554,22 +555,22 @@ public class LdifUtils
                 else
                 {
                     lineBuffer.append( ":" );
-                    
-                    if ( str != null) 
+
+                    if ( str != null)
                     {
                         lineBuffer.append( " " ).append( str );
                     }
                 }
             }
-            
+
             lineBuffer.append( "\n" );
             sb.append( stripLineToNChars( lineBuffer.toString(), length ) );
         }
-        
+
         return sb.toString();
     }
-    
-    
+
+
     /**
      * Strips the String every n specified characters
      * @param str the string to strip
@@ -584,12 +585,12 @@ public class LdifUtils
         {
             return str;
         }
-        
+
         if ( nbChars < 2 )
         {
             throw new IllegalArgumentException( I18n.err( I18n.ERR_12084 ) );
         }
-        
+
         // We will first compute the new size of the LDIF result
         // It's at least nbChars chars plus one for \n
         int charsPerLine = nbChars - 1;
@@ -603,19 +604,19 @@ public class LdifUtils
 
         char[] buffer = new char[ nbCharsTotal ];
         char[] orig = str.toCharArray();
-        
+
         int posSrc = 0;
         int posDst = 0;
-        
+
         System.arraycopy( orig, posSrc, buffer, posDst, nbChars );
         posSrc += nbChars;
         posDst += nbChars;
-        
+
         for ( int i = 0; i < nbLines - 2; i ++ )
         {
             buffer[posDst++] = '\n';
             buffer[posDst++] = ' ';
-            
+
             System.arraycopy( orig, posSrc, buffer, posDst, charsPerLine );
             posSrc += charsPerLine;
             posDst += charsPerLine;
@@ -624,35 +625,35 @@ public class LdifUtils
         buffer[posDst++] = '\n';
         buffer[posDst++] = ' ';
         System.arraycopy( orig, posSrc, buffer, posDst, remaining == 0 ? charsPerLine : remaining );
-        
+
         return new String( buffer );
     }
 
 
     /**
-     * Build a new Attributes instance from a LDIF list of lines. The values can be 
-     * either a complete AVA, or a couple of AttributeType ID and a value (a String or 
+     * Build a new Attributes instance from a LDIF list of lines. The values can be
+     * either a complete AVA, or a couple of AttributeType ID and a value (a String or
      * a byte[]). The following sample shows the three cases :
-     * 
+     *
      * <pre>
      * Attribute attr = AttributeUtils.createAttributes(
      *     "objectclass: top",
      *     "cn", "My name",
      *     "jpegPhoto", new byte[]{0x01, 0x02} );
      * </pre>
-     * 
-     * @param avas The AttributeType and Values, using a ldif format, or a couple of 
+     *
+     * @param avas The AttributeType and Values, using a ldif format, or a couple of
      * Attribute ID/Value
      * @return An Attributes instance
      * @throws LdapException If the data are invalid
-     * @throws LdapLdifException 
+     * @throws LdapLdifException
      */
     public static Attributes createAttributes( Object... avas ) throws LdapException, LdapLdifException
     {
         StringBuilder sb = new StringBuilder();
         int pos = 0;
         boolean valueExpected = false;
-        
+
         for ( Object ava : avas)
         {
             if ( !valueExpected )
@@ -661,10 +662,10 @@ public class LdifUtils
                 {
                     throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_12085, (pos+1) ) );
                 }
-                
+
                 String attribute = (String)ava;
                 sb.append( attribute );
-                
+
                 if ( attribute.indexOf( ':' ) != -1 )
                 {
                     sb.append( '\n' );
@@ -690,16 +691,16 @@ public class LdifUtils
                 {
                     throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_12086, (pos+1) ) );
                 }
-                
+
                 valueExpected = false;
             }
         }
-        
+
         if ( valueExpected )
         {
             throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_12087 ) );
         }
-        
+
         LdifAttributesReader reader = new LdifAttributesReader();
         Attributes attributes = AttributeUtils.toAttributes( reader.parseEntry( sb.toString() ) );
 
@@ -708,29 +709,53 @@ public class LdifUtils
 
 
     /**
-     * Build a new Attributes instance from a LDIF list of lines. The values can be 
-     * either a complete AVA, or a couple of AttributeType ID and a value (a String or 
+     * Build a new Attributes instance from a LDIF list of lines. The values can be
+     * either a complete AVA, or a couple of AttributeType ID and a value (a String or
      * a byte[]). The following sample shows the three cases :
-     * 
+     *
      * <pre>
      * Attribute attr = AttributeUtils.createAttributes(
      *     "objectclass: top",
      *     "cn", "My name",
      *     "jpegPhoto", new byte[]{0x01, 0x02} );
      * </pre>
-     * 
-     * @param avas The AttributeType and Values, using a ldif format, or a couple of 
+     *
+     * @param avas The AttributeType and Values, using a ldif format, or a couple of
      * Attribute ID/Value
      * @return An Attributes instance
      * @throws LdapException If the data are invalid
-     * @throws LdapLdifException 
+     * @throws LdapLdifException
      */
     public static Entry createEntry( DN dn, Object... avas ) throws LdapException, LdapLdifException
     {
+        return createEntry( null, dn, avas );
+    }
+
+
+    /**
+     * Build a new Attributes instance from a LDIF list of lines. The values can be
+     * either a complete AVA, or a couple of AttributeType ID and a value (a String or
+     * a byte[]). The following sample shows the three cases :
+     *
+     * <pre>
+     * Attribute attr = AttributeUtils.createAttributes(
+     *     "objectclass: top",
+     *     "cn", "My name",
+     *     "jpegPhoto", new byte[]{0x01, 0x02} );
+     * </pre>
+     *
+     * @param avas The AttributeType and Values, using a ldif format, or a couple of
+     * Attribute ID/Value
+     * @return An Attributes instance
+     * @throws LdapException If the data are invalid
+     * @throws LdapLdifException
+     */
+    public static Entry createEntry( SchemaManager schemaManager, DN dn, Object... avas ) throws LdapException, LdapLdifException
+    {
         StringBuilder sb = new StringBuilder();
         int pos = 0;
         boolean valueExpected = false;
-        
+
         for ( Object ava : avas)
         {
             if ( !valueExpected )
@@ -739,10 +764,10 @@ public class LdifUtils
                 {
                     throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_12085, (pos+1) ) );
                 }
-                
+
                 String attribute = (String)ava;
                 sb.append( attribute );
-                
+
                 if ( attribute.indexOf( ':' ) != -1 )
                 {
                     sb.append( '\n' );
@@ -768,18 +793,18 @@ public class LdifUtils
                 {
                     throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_12086, (pos+1) ) );
                 }
-                
+
                 valueExpected = false;
             }
         }
-        
+
         if ( valueExpected )
         {
             throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( I18n.ERR_12087 ) );
         }
-        
+
         LdifAttributesReader reader = new LdifAttributesReader();
-        Entry entry = reader.parseEntry( sb.toString() );
+        Entry entry = reader.parseEntry( schemaManager, sb.toString() );
         entry.setDn( dn );
 
         return entry;