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 2016/02/18 21:35:56 UTC
svn commit: r1731136 - in /directory/shared/trunk/ldap:
client/api/src/test/java/org/apache/directory/ldap/client/api/
model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/
Author: elecharny
Date: Thu Feb 18 20:35:55 2016
New Revision: 1731136
URL: http://svn.apache.org/viewvc?rev=1731136&view=rev
Log:
o Changed the way we anonymize values : we don't anymore pick random chars, the collision risk is way to high
o Added a case sensitive String anonymizer
o Added some more accurate tests
Added:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java
Removed:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/DefaultAnonymizer.java
Modified:
directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java
Modified: directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java (original)
+++ directory/shared/trunk/ldap/client/api/src/test/java/org/apache/directory/ldap/client/api/LdifAnonymizerTest.java Thu Feb 18 20:35:55 2016
@@ -27,16 +27,17 @@ import java.util.List;
import java.util.Set;
import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Modification;
import org.apache.directory.api.ldap.model.entry.ModificationOperation;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
import org.apache.directory.api.ldap.model.ldif.LdifEntry;
import org.apache.directory.api.ldap.model.ldif.LdifReader;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.ldap.schema.manager.impl.DefaultSchemaManager;
-import org.junit.BeforeClass;
+import org.apache.directory.api.util.Strings;
+import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -53,13 +54,13 @@ import static org.junit.Assert.assertNot
*/
public class LdifAnonymizerTest
{
- private static SchemaManager schemaManager;
+ private SchemaManager schemaManager;
- private static LdifReader ldifReader;
+ private LdifReader ldifReader;
- @BeforeClass
- public static void setup()
+ @Before
+ public void setup()
{
schemaManager = null;
@@ -91,7 +92,7 @@ public class LdifAnonymizerTest
"ObjectClass: top\n" +
"objectClass: person\n" +
"cn: emmanuel\n" +
- "sn: elecharny\n"+
+ "sn: lecharnye\n"+
"\n" +
"dn: cn=emmanuel,dc=test,dc=example,dc=com\n" +
"ObjectClass: top\n" +
@@ -118,7 +119,59 @@ public class LdifAnonymizerTest
anonymizer.addNamingContext( "dc=acme,dc=com" );
anonymizer.removeAnonAttributeType( schemaManager.getAttributeType( "sn" ) );
- anonymizer.anonymize( ldif );
+ String result = anonymizer.anonymize( ldif );
+
+ List<LdifEntry> entries = ldifReader.parseLdif( result );
+
+ assertEquals( 3, entries.size() );
+
+ // First entry
+ LdifEntry ldifEntry = entries.get( 0 );
+ assertTrue( ldifEntry.isEntry() );
+
+ Entry entry = ldifEntry.getEntry();
+ assertEquals( 3, entry.size() );
+
+ assertEquals( "cn=AAAA,dc=example,dc=com", entry.getDn().toString() );
+
+ Attribute cn = entry.get( "cn" );
+ assertEquals( "AAAA", cn.getString() );
+
+ Attribute sn = entry.get( "sn" );
+ assertEquals( "AAAA", sn.getString() );
+
+ // Second entry
+ ldifEntry = entries.get( 1 );
+ assertTrue( ldifEntry.isEntry() );
+
+ entry = ldifEntry.getEntry();
+ assertEquals( 3, entry.size() );
+
+ assertEquals( "cn=AAAAAAAA,dc=acme,dc=com", entry.getDn().toString() );
+
+ cn = entry.get( "cn" );
+ assertEquals( "AAAAAAAA", cn.getString() );
+
+ sn = entry.get( "sn" );
+ assertEquals( "AAAAAAAAA", sn.getString() );
+
+ // Third entry
+ ldifEntry = entries.get( 2 );
+ assertTrue( ldifEntry.isEntry() );
+
+ entry = ldifEntry.getEntry();
+ assertEquals( 4, entry.size() );
+
+ assertEquals( "cn=AAAAAAAA,dc=AAAA,dc=example,dc=com", entry.getDn().toString() );
+
+ cn = entry.get( "cn" );
+ assertEquals( "AAAAAAAA", cn.getString() );
+
+ sn = entry.get( "sn" );
+ assertEquals( "AAAAAAAAB", sn.getString() );
+
+ Attribute seeAlso = entry.get( "seeAlso" );
+ assertEquals( "cn=AAAAAAAA,dc=acme,dc=com", seeAlso.getString() );
}
@@ -137,7 +190,31 @@ public class LdifAnonymizerTest
LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
anonymizer.addNamingContext( "dc=example,dc=com" );
- anonymizer.anonymize( ldif );
+ String result = anonymizer.anonymize( ldif );
+
+ List<LdifEntry> entries = ldifReader.parseLdif( result );
+
+ assertEquals( 1, entries.size() );
+
+ // Check the entry
+ LdifEntry ldifEntry = entries.get( 0 );
+ assertTrue( ldifEntry.isEntry() );
+
+ Entry entry = ldifEntry.getEntry();
+ assertEquals( 4, entry.size() );
+
+ // Here, we expect cn2 to be translated to AAA, because it was encountered in teh DN first
+ assertEquals( "cn=AAA+sn=AAAAAAAAA,dc=example,dc=com", entry.getDn().toString() );
+
+ Attribute cn = entry.get( "cn" );
+ assertEquals( 3, cn.size() );
+ assertTrue( cn.contains( "AAA", "AAB", "AAC" ) );
+
+ Attribute sn = entry.get( "sn" );
+ assertEquals( "AAAAAAAAA", sn.getString() );
+
+ Attribute givenname = entry.get( "givenname" );
+ assertEquals( "AAAA", givenname.getString() );
}
@@ -152,12 +229,42 @@ public class LdifAnonymizerTest
"cn: cn2\n" +
"cn: cn3\n" +
"userPassword: test\n" +
+ "userPassword: tesu\n" +
"sn: elecharny\n" +
"givenname: test\n";
LdifAnonymizer anonymizer = new LdifAnonymizer( schemaManager );
anonymizer.addNamingContext( "dc=example,dc=com" );
- anonymizer.anonymize( ldif );
+ String result = anonymizer.anonymize( ldif );
+
+ List<LdifEntry> entries = ldifReader.parseLdif( result );
+
+ assertEquals( 1, entries.size() );
+
+ // Check the entry
+ LdifEntry ldifEntry = entries.get( 0 );
+ assertTrue( ldifEntry.isEntry() );
+
+ Entry entry = ldifEntry.getEntry();
+ assertEquals( 5, entry.size() );
+
+ // Here, we expect cn2 to be translated to AAA, because it was encountered in teh DN first
+ assertEquals( "cn=AAA+sn=AAAAAAAAA,dc=example,dc=com", entry.getDn().toString() );
+
+ Attribute cn = entry.get( "cn" );
+ assertEquals( 3, cn.size() );
+ assertTrue( cn.contains( "AAA", "AAB", "AAC" ) );
+
+ Attribute sn = entry.get( "sn" );
+ assertEquals( "AAAAAAAAA", sn.getString() );
+
+ Attribute givenname = entry.get( "givenname" );
+ assertEquals( "AAAA", givenname.getString() );
+
+ Attribute userPassword = entry.get( "userPassword" );
+ assertEquals( 2, userPassword.size() );
+ assertTrue( userPassword.contains( Strings.getBytesUtf8( "AAAA" ) ) );
+ assertTrue( userPassword.contains( Strings.getBytesUtf8( "AAAB" ) ) );
}
@@ -193,19 +300,18 @@ public class LdifAnonymizerTest
assertEquals( "member", attribute.getUpId() );
assertEquals( 4, attribute.size() );
- Set<String> originalValues = new HashSet<String>();
- originalValues.add( "cn=acme1.com,ou=Servers,o=acme,dc=com" );
- originalValues.add( "uid=john.doe@acme.com,ou=People,o=acme,dc=com" );
- originalValues.add( "uid=jack.doe@acme.com,ou=People,o=acme,dc=com" );
- originalValues.add( "uid=jim.gonzales@acme.com,ou=People,o=acme,dc=com" );
+ Set<String> values = new HashSet<String>();
+ values.add( "cn=AAAAAAAAA,ou=AAAAAAA,o=acme,dc=com" );
+ values.add( "uid=AAAAAAAAAAAAAAAAA,ou=AAAAAB,o=acme,dc=com" );
+ values.add( "uid=AAAAAAAAAAAAAAAAB,ou=AAAAAB,o=acme,dc=com" );
+ values.add( "uid=AAAAAAAAAAAAAAAAAAAAA,ou=AAAAAB,o=acme,dc=com" );
for ( Value<?> value : attribute )
{
String str = value.getString();
// We can only test the length and teh fact teh values are not equal (as the vale has been anonymized)
- assertNotSame( 0, value.length() );
- assertFalse( originalValues.contains( str ) );
+ assertTrue( values.contains( str ) );
assertTrue( str.endsWith( ",o=acme,dc=com" ) );
}
}
@@ -241,9 +347,9 @@ public class LdifAnonymizerTest
String value = attribute.getString();
- // We can only test the length and teh fact teh values are not equal (as the vale has been anonymized)
- assertEquals( "ACME Inc. Legal Team".length(), value.length() );
- assertNotEquals( "ACME Inc. Legal Team", value );
+ // We can only test the length and the fact the values are not equal (as the vale has been anonymized)
+ assertEquals( "AAAAAAAAAAAAAAAAAAAA".length(), value.length() );
+ assertEquals( "AAAAAAAAAAAAAAAAAAAA", value );
}
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/AbstractAnonymizer.java Thu Feb 18 20:35:55 2016
@@ -20,6 +20,7 @@
package org.apache.directory.api.ldap.model.ldif.anonymizer;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -37,6 +38,50 @@ public abstract class AbstractAnonymizer
/** The map of AttributeType'sOID we want to anonymize. They are all associated with anonymizers */
protected Map<String, Anonymizer> attributeAnonymizers = new HashMap<String, Anonymizer>();
+
+ /** A flag set to <tt>true</tt> if the AttributeType is case sensitive */
+ protected boolean caseSensitive = false;
+
+ /** Map of chars to use in the anonymized values 0 5 10 15 20 25 30 35 40*/
+ private static final char[] NOT_SENSITIVE_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()-./".toCharArray();
+ private static final char[] SENSITIVE_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'()-./abcdefghijklmnopqrstuvwxyz".toCharArray();
+
+ /** A table containing booleans when the corresponding char is printable */
+ private static final int[] CHAR_MAP =
+ {
+ // ---, ---, ---, ---, ---, ---, ---, ---
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ // ---, ---, ---, ---, ---, ---, ---, ---
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ // ---, ---, ---, ---, ---, ---, ---, ---
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ // ---, ---, ---, ---, ---, ---, ---, ---
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ // ---, ---, ---, ---, ---, ---, ---, "'"
+ 0, 0, 0, 0, 0, 0, 0, 36,
+ // '(', ')', ---, '+', ',', '-', '.', '/'
+ 37, 38, 0, 0, 0, 39, 40, 41,
+ // '0', '1', '2', '3', '4', '5', '6', '7',
+ 26, 27, 28, 29, 30, 31, 32, 33,
+ // '8', '9', ':', ---, ---, '=', ---, '?'
+ 34, 35, 0, 0, 0, 0, 0, 26,
+ // ---, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 0, 0, 1, 2, 3, 4, 5, 6,
+ // 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ // 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ // 'X', 'Y', 'Z', ---, ---, ---, ---, ---
+ 23, 24, 25, 0, 0, 0, 0, 0,
+ // ---, 'a', 'b', 'c', 'd', 'e', 'f', 'g'
+ 0, 42, 43, 44, 45, 46, 47, 48,
+ // 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
+ 49, 50, 51, 52, 53, 54, 55, 56,
+ // 'p', 'q', 'r', 's', 't', 'u', 'v', 'w'
+ 57, 58, 59, 60, 61, 62, 63, 64,
+ // 'x', 'y', 'z', ---, ---, ---, ---, ---
+ 65, 66, 67, 0, 0, 0, 0, 0,
+ };
/**
* {@inheritDoc}
@@ -56,4 +101,162 @@ public abstract class AbstractAnonymizer
{
this.attributeAnonymizers = attributeAnonymizers;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Integer, String> getLatestStringMap()
+ {
+ return null;
+ }
+
+
+ /**
+ * @param latestValueMap The latest String anonymized value map
+ */
+ public void setLatestStringMap( Map<Integer, String> latestStringMap )
+ {
+ // Do nothing
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Integer, byte[]> getLatestBytesMap()
+ {
+ return null;
+ }
+
+
+ /**
+ * @param latestBytesMap The latest byte[] anonymized value map
+ */
+ public void setLatestBytesMap( Map<Integer, byte[]> latestBytesMap )
+ {
+ // Do nothing
+ }
+
+
+ /**
+ * Compute the next String value
+ *
+ * @param valStr The original value
+ * @return The anonymized value
+ */
+ protected String computeNewValue( String valStr )
+ {
+ int length = valStr.length();
+ String latestString = getLatestStringMap().get( length );
+ char[] charMap;
+
+ if ( caseSensitive )
+ {
+ charMap = SENSITIVE_MAP;
+ }
+ else
+ {
+ charMap = NOT_SENSITIVE_MAP;
+ }
+
+ int lastMapChar = charMap.length - 1;
+
+ if ( latestString == null )
+ {
+ // No previous value : create a new one
+ char[] newValue = new char[length];
+
+ Arrays.fill( newValue, charMap[0] );
+
+ String anonymizedValue = new String( newValue );
+ getLatestStringMap().put( length, anonymizedValue );
+
+ return anonymizedValue;
+ }
+ else
+ {
+ // Compute a new value
+ char[] latest = latestString.toCharArray();
+ boolean overflow = true;
+
+ for ( int i = length - 1; i >= 0; i-- )
+ {
+ if ( latest[i] == charMap[lastMapChar] )
+ {
+ latest[i] = charMap[0];
+ }
+ else
+ {
+ latest[i] = charMap[CHAR_MAP[latest[i]] + 1];
+ overflow = false;
+ break;
+ }
+ }
+
+ String anonymizedValue = new String( latest );
+
+ if ( overflow )
+ {
+ // We have exhausted all the possible values...
+ throw new RuntimeException( "Cannot compute a new value for " + anonymizedValue );
+ }
+
+ getLatestStringMap().put( length, anonymizedValue );
+
+ return anonymizedValue;
+ }
+ }
+
+
+ /**
+ * Compute the next byte[] value
+ *
+ * @param valBytes The original value
+ * @return The anonymized value
+ */
+ protected byte[] computeNewValue( byte[] valBytes )
+ {
+ int length = valBytes.length;
+ byte[] latestBytes = getLatestBytesMap().get( length );
+
+ if ( latestBytes == null )
+ {
+ // No previous value : create a new one
+ byte[] newValue = new byte[length];
+
+ Arrays.fill( newValue, ( byte ) 'A' );
+
+ getLatestBytesMap().put( length, newValue );
+
+ return newValue;
+ }
+ else
+ {
+ // Compute a new value
+ boolean overflow = true;
+
+ for ( int i = length - 1; i >= 0; i-- )
+ {
+ if ( latestBytes[i] == ( byte ) 'Z' )
+ {
+ latestBytes[i] = ( byte ) 'A';
+ }
+ else
+ {
+ latestBytes[i]++;
+ overflow = false;
+ break;
+ }
+ }
+
+ if ( overflow )
+ {
+ // We have exhausted all the possible values...
+ throw new RuntimeException( "Cannot compute a new value for " + latestBytes );
+ }
+
+ return latestBytes;
+ }
+ }
}
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/Anonymizer.java Thu Feb 18 20:35:55 2016
@@ -61,4 +61,28 @@ public interface Anonymizer<K>
* @param attributeAnonymizers The list of existing anonymizers
*/
void setAnonymizers( Map<String, Anonymizer> attributeAnonymizers );
+
+
+ /**
+ * @return The latest String anonymized value map
+ */
+ Map<Integer, String> getLatestStringMap();
+
+
+ /**
+ * @param latestValueMap The latest String anonymized value map
+ */
+ void setLatestStringMap( Map<Integer, String> latestStringMap );
+
+
+ /**
+ * @return The latest byte[] anonymized value map
+ */
+ Map<Integer, byte[]> getLatestBytesMap();
+
+
+ /**
+ * @param latestBytesMap The latest byte[] anonymized value map
+ */
+ void setLatestBytesMap( Map<Integer, byte[]> latestBytesMap );
}
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/BinaryAnonymizer.java Thu Feb 18 20:35:55 2016
@@ -21,8 +21,8 @@
package org.apache.directory.api.ldap.model.ldif.anonymizer;
+import java.util.HashMap;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import org.apache.directory.api.ldap.model.entry.Attribute;
@@ -39,9 +39,34 @@ import org.apache.directory.api.ldap.mod
*/
public class BinaryAnonymizer extends AbstractAnonymizer<byte[]>
{
- /** Create a random generator */
- Random random = new Random( System.currentTimeMillis() );
+ /** The latest anonymized byte[] value map */
+ protected Map<Integer, byte[]> latestBytesMap = new HashMap<Integer, byte[]>();
+ /**
+ * Creates a new instance of BinaryAnonymizer.
+ */
+ public BinaryAnonymizer()
+ {
+ latestBytesMap = new HashMap<Integer, byte[]>();
+ }
+
+
+ /**
+ * Creates a new instance of BinaryAnonymizer.
+ *
+ * @param latestBytesMap The map containing the latest value for each length
+ */
+ public BinaryAnonymizer( Map<Integer, byte[]> latestBytesMap )
+ {
+ if ( latestBytesMap == null )
+ {
+ this.latestBytesMap = new HashMap<Integer, byte[]>();
+ }
+ else
+ {
+ this.latestBytesMap = latestBytesMap;
+ }
+ }
/**
* Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
@@ -49,56 +74,44 @@ public class BinaryAnonymizer extends Ab
public Attribute anonymize( Map<Value<byte[]>, Value<byte[]>> valueMap, Set<Value<byte[]>> valueSet, Attribute attribute )
{
Attribute result = new DefaultAttribute( attribute.getAttributeType() );
- random.setSeed( System.nanoTime() );
for ( Value<?> value : attribute )
{
- if ( value instanceof BinaryValue )
+ byte[] bytesValue = ( byte[] ) value.getNormValue();
+ byte[] newValue = computeNewValue( bytesValue );
+
+ try
{
- byte[] bytesValue = value.getBytes();
-
- int length = bytesValue.length;
-
- // Same size
- byte[] newValue = new byte[length];
-
- for ( int i = 0; i < length; i++ )
- {
- newValue[i] = ( byte ) ( random.nextInt( 'Z' - 'A' ) + 'A' );
- }
-
- try
- {
- result.add( newValue );
- }
- catch ( LdapInvalidAttributeValueException e )
- {
- // TODO : handle that
- }
+ result.add( newValue );
+ Value<byte[]> anonValue = new BinaryValue( attribute.getAttributeType(), newValue );
+ valueMap.put( ( Value<byte[]> ) value, anonValue );
+ valueSet.add( anonValue );
}
- else
+ catch ( LdapInvalidAttributeValueException e )
{
- byte[] byteValue = value.getBytes();
-
- // Same size
- byte[] newValue = new byte[byteValue.length];
-
- for ( int i = 0; i < byteValue.length; i++ )
- {
- newValue[i] = ( byte ) random.nextInt();
- }
-
- try
- {
- result.add( newValue );
- }
- catch ( LdapInvalidAttributeValueException e )
- {
- // TODO : handle that
- }
+ // TODO Auto-generated catch block
+ throw new RuntimeException( "Error while anonymizing the value" + value );
}
}
return result;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Integer, byte[]> getLatestBytesMap()
+ {
+ return latestBytesMap;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLatestBytesgMap( Map<Integer, byte[]> latestBytesMap )
+ {
+ this.latestBytesMap = latestBytesMap;
+ }
}
Added: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java?rev=1731136&view=auto
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java (added)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/CaseSensitiveStringAnonymizer.java Thu Feb 18 20:35:55 2016
@@ -0,0 +1,142 @@
+/*
+ * 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.directory.api.ldap.model.ldif.anonymizer;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
+import org.apache.directory.api.ldap.model.entry.StringValue;
+import org.apache.directory.api.ldap.model.entry.Value;
+import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
+
+
+/**
+ * A default anonymizer for attributes that are HR. It covers DirectoryString, Ia5String, ...
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CaseSensitiveStringAnonymizer extends AbstractAnonymizer<String>
+{
+ /** The latest anonymized String value map */
+ private Map<Integer, String> latestStringMap;
+
+ /**
+ * Creates a new instance of StringAnonymizer.
+ */
+ public CaseSensitiveStringAnonymizer()
+ {
+ latestStringMap = new HashMap<Integer, String>();
+ caseSensitive = true;
+ }
+
+
+ /**
+ * Creates a new instance of StringAnonymizer.
+ *
+ * @param latestStringMap The map containing the latest value for each length
+ */
+ public CaseSensitiveStringAnonymizer( Map<Integer, String> latestStringMap )
+ {
+ if ( latestStringMap == null )
+ {
+ this.latestStringMap = new HashMap<Integer, String>();
+ }
+ else
+ {
+ this.latestStringMap = latestStringMap;
+ }
+
+ caseSensitive = true ;
+ }
+
+
+ /**
+ * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+ */
+ public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
+ {
+ AttributeType attributeType = attribute.getAttributeType();
+ Attribute result = new DefaultAttribute( attributeType );
+
+ for ( Value<?> value : attribute )
+ {
+ if ( value instanceof StringValue )
+ {
+ Value<String> anonymized = valueMap.get( value );
+
+ if ( anonymized != null )
+ {
+ try
+ {
+ result.add( anonymized );
+ }
+ catch ( LdapInvalidAttributeValueException e )
+ {
+ // TODO : handle that
+ }
+ }
+ else
+ {
+ String strValue = value.getNormValue().toString();
+ String newValue = computeNewValue( strValue );
+
+ try
+ {
+ result.add( newValue );
+ Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValue );
+ valueMap.put( ( Value<String> ) value, anonValue );
+ valueSet.add( anonValue );
+ }
+ catch ( LdapInvalidAttributeValueException e )
+ {
+ // TODO Auto-generated catch block
+ throw new RuntimeException( "Error while anonymizing the value" + strValue );
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Integer, String> getLatestStringMap()
+ {
+ return latestStringMap;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLatestStringMap( Map<Integer, String> latestStringMap )
+ {
+ this.latestStringMap = latestStringMap;
+ }
+}
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/IntegerAnonymizer.java Thu Feb 18 20:35:55 2016
@@ -21,8 +21,9 @@
package org.apache.directory.api.ldap.model.ldif.anonymizer;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import org.apache.directory.api.ldap.model.entry.Attribute;
@@ -39,9 +40,34 @@ import org.apache.directory.api.ldap.mod
*/
public class IntegerAnonymizer extends AbstractAnonymizer<String>
{
- /** Create a random generator */
- Random random = new Random( System.currentTimeMillis() );
+ /** The latest anonymized Integer value map */
+ private Map<Integer, String> latestIntegerMap;
+ /**
+ * Creates a new instance of IntegerAnonymizer.
+ */
+ public IntegerAnonymizer()
+ {
+ latestIntegerMap = new HashMap<Integer, String>();
+ }
+
+
+ /**
+ * Creates a new instance of IntegerAnonymizer.
+ *
+ * @param latestIntegerMap The map containing the latest integer value for each length
+ */
+ public IntegerAnonymizer( Map<Integer, String> latestIntegerMap )
+ {
+ if ( latestIntegerMap == null )
+ {
+ this.latestIntegerMap = new HashMap<Integer, String>();
+ }
+ else
+ {
+ this.latestIntegerMap = latestIntegerMap;
+ }
+ }
/**
* Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
@@ -49,46 +75,126 @@ public class IntegerAnonymizer extends A
public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
{
Attribute result = new DefaultAttribute( attribute.getAttributeType() );
- random.setSeed( System.nanoTime() );
for ( Value<?> value : attribute )
{
if ( value instanceof StringValue )
{
- String strValue = value.getString();
-
- int length = strValue.length();
-
- // Same size
- char[] newValue = new char[length];
-
- boolean isFirst = true;
+ Value<String> anonymized = valueMap.get( value );
- for ( int i = 0; i < length; i++ )
+ if ( anonymized != null )
{
- if ( isFirst && length > 1 )
+ try
{
- newValue[i] = ( char ) ( random.nextInt( 9 ) + '1' );
+ result.add( anonymized );
}
- else
+ catch ( LdapInvalidAttributeValueException e )
{
- newValue[i] = ( char ) ( random.nextInt( 10 ) + '0' );
+ // Handle me...
}
-
- isFirst = false;
- }
-
- try
- {
- result.add( new String( newValue ) );
}
- catch ( LdapInvalidAttributeValueException e )
+ else
{
- // TODO : handle that
+ String strValue = value.getNormValue().toString();
+ String newValue = computeNewIntegerValue( strValue );
+
+ try
+ {
+ result.add( newValue );
+ Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValue );
+ valueMap.put( ( Value<String> ) value, anonValue );
+ valueSet.add( anonValue );
+ }
+ catch ( LdapInvalidAttributeValueException e )
+ {
+ // TODO : handle that
+ }
}
}
}
return result;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Integer, String> getLatestIntegerMap()
+ {
+ return latestIntegerMap;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLatestIntegerMap( Map<Integer, String> latestIntegerMap )
+ {
+ this.latestIntegerMap = latestIntegerMap;
+ }
+
+
+ /**
+ * Compute the next Integer value
+ *
+ * @param valStr The original value
+ * @return The anonymized value
+ */
+ private String computeNewIntegerValue( String valStr )
+ {
+ int length = valStr.length();
+ String latestInteger = latestIntegerMap.get( length );
+
+ if ( latestInteger == null )
+ {
+ // No previous value : create a new one
+ char[] newValue = new char[length];
+
+ Arrays.fill( newValue, '9' );
+
+ String anonymizedValue = new String( newValue );
+ latestIntegerMap.put( length, anonymizedValue );
+
+ return anonymizedValue;
+ }
+ else
+ {
+ // Compute a new value
+ char[] latest = latestInteger.toCharArray();
+ boolean overflow = true;
+
+ for ( int i = length - 1; i >= 0; i-- )
+ {
+ if ( latest[i] == '0' )
+ {
+ latest[i] = '9';
+ }
+ else
+ {
+ latest[i]--;
+ overflow = false;
+ break;
+ }
+ }
+
+ // Corner case : we can't have a value starting with '0' unless its length is 1
+ if ( ( length > 1 ) && ( latest[0] == '0' ) )
+ {
+ throw new RuntimeException( "Overflow for " + valStr );
+ }
+
+ String anonymizedValue = new String( latest );
+
+ if ( overflow )
+ {
+ // We have exhausted all the possible values...
+ throw new RuntimeException( "Cannot compute a new value for " + anonymizedValue );
+ }
+
+ latestIntegerMap.put( length, anonymizedValue );
+
+ return anonymizedValue;
+ }
+ }
}
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/StringAnonymizer.java Thu Feb 18 20:35:55 2016
@@ -21,8 +21,8 @@
package org.apache.directory.api.ldap.model.ldif.anonymizer;
+import java.util.HashMap;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import org.apache.directory.api.ldap.model.entry.Attribute;
@@ -30,6 +30,7 @@ import org.apache.directory.api.ldap.mod
import org.apache.directory.api.ldap.model.entry.StringValue;
import org.apache.directory.api.ldap.model.entry.Value;
import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
/**
@@ -39,99 +40,80 @@ import org.apache.directory.api.ldap.mod
*/
public class StringAnonymizer extends AbstractAnonymizer<String>
{
- /** Create a random generator */
- Random random = new Random( System.currentTimeMillis() );
+ /** The latest anonymized String value map */
+ private Map<Integer, String> latestStringMap;
+ /**
+ * Creates a new instance of StringAnonymizer.
+ */
+ public StringAnonymizer()
+ {
+ latestStringMap = new HashMap<Integer, String>();
+ caseSensitive = false;
+ }
+
+ /**
+ * Creates a new instance of StringAnonymizer.
+ *
+ * @param latestStringMap The map containing the latest value for each length
+ */
+ public StringAnonymizer( Map<Integer, String> latestStringMap )
+ {
+ if ( latestStringMap == null )
+ {
+ this.latestStringMap = new HashMap<Integer, String>();
+ }
+ else
+ {
+ this.latestStringMap = latestStringMap;
+ }
+
+ caseSensitive = false;
+ }
+
+
/**
* Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
*/
public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
{
- Attribute result = new DefaultAttribute( attribute.getAttributeType() );
- random.setSeed( System.nanoTime() );
+ AttributeType attributeType = attribute.getAttributeType();
+ Attribute result = new DefaultAttribute( attributeType );
for ( Value<?> value : attribute )
{
- Value<String> anonymized = valueMap.get( value );
-
- if ( anonymized != null )
- {
- try
- {
- result.add( anonymized.getString() );
- }
- catch ( LdapInvalidAttributeValueException e )
- {
- // TODO : handle that
- }
- }
- else
+ if ( value instanceof StringValue )
{
- if ( value instanceof StringValue )
+ Value<String> anonymized = valueMap.get( value );
+
+ if ( anonymized != null )
{
- String strValue = value.getNormValue().toString();
- int length = strValue.length();
-
- // Same size
- char[] newValue = new char[length];
-
- int count = 1000;
-
- while ( count > 0 )
+ try
{
- for ( int i = 0; i < length; i++ )
- {
- newValue[i] = ( char ) ( random.nextInt( 'Z' - 'A' ) + 'A' );
- }
-
- try
- {
- String newValueStr = new String( newValue );
-
- Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValueStr );
-
- if ( valueSet.contains( anonValue ) )
- {
- count--;
- continue;
- }
-
- result.add( newValueStr );
- valueMap.put( ( Value<String> ) value, anonValue );
- valueSet.add( anonValue );
- break;
- }
- catch ( LdapInvalidAttributeValueException e )
- {
- // TODO : handle that
- }
+ result.add( anonymized );
}
-
- if ( count == 0 )
+ catch ( LdapInvalidAttributeValueException e )
{
- throw new RuntimeException( "Error : too many collisions" );
+ // TODO : handle that
}
}
else
{
- byte[] byteValue = value.getBytes();
-
- // Same size
- byte[] newValue = new byte[byteValue.length];
-
- for ( int i = 0; i < byteValue.length; i++ )
- {
- newValue[i] = ( byte ) random.nextInt();
- }
-
+ String strValue = value.getNormValue().toString();
+ String newValue = computeNewValue( strValue );
+
try
{
result.add( newValue );
+ Value<String> anonValue = new StringValue( attribute.getAttributeType(), newValue );
+ valueMap.put( ( Value<String> ) value, anonValue );
+ valueSet.add( anonValue );
}
catch ( LdapInvalidAttributeValueException e )
{
- // TODO : handle that
+ // TODO Auto-generated catch block
+ throw new RuntimeException( "Error while anonymizing the value" + strValue );
}
}
}
@@ -139,4 +121,22 @@ public class StringAnonymizer extends Ab
return result;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Integer, String> getLatestStringMap()
+ {
+ return latestStringMap;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setLatestStringMap( Map<Integer, String> latestStringMap )
+ {
+ this.latestStringMap = latestStringMap;
+ }
}
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java?rev=1731136&r1=1731135&r2=1731136&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/ldif/anonymizer/TelephoneNumberAnonymizer.java Thu Feb 18 20:35:55 2016
@@ -22,14 +22,6 @@ package org.apache.directory.api.ldap.mo
import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
-import org.apache.directory.api.ldap.model.entry.Attribute;
-import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
-import org.apache.directory.api.ldap.model.entry.StringValue;
-import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
/**
@@ -37,19 +29,34 @@ import org.apache.directory.api.ldap.mod
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public class TelephoneNumberAnonymizer extends AbstractAnonymizer<String>
+public class TelephoneNumberAnonymizer extends IntegerAnonymizer
{
- /** Create a random generator */
- Random random = new Random( System.currentTimeMillis() );
+ /**
+ * Creates a new instance of TelephoneNumberAnonymizer.
+ */
+ public TelephoneNumberAnonymizer()
+ {
+ super();
+ }
+
/**
- * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+ * Creates a new instance of TelephoneNumberAnonymizer.
+ *
+ * @param latestIntegerMap The map containing the latest integer value for each length
*/
+ public TelephoneNumberAnonymizer( Map<Integer, String> latestIntegerMap )
+ {
+ super( latestIntegerMap );
+ }
+
+ /**
+ * Anonymize an attribute using pure random values (either chars of bytes, depending on the Attribute type)
+ *
public Attribute anonymize( Map<Value<String>, Value<String>> valueMap, Set<Value<String>> valueSet, Attribute attribute )
{
Attribute result = new DefaultAttribute( attribute.getAttributeType() );
- random.setSeed( System.nanoTime() );
for ( Value<?> value : attribute )
{
@@ -128,5 +135,5 @@ public class TelephoneNumberAnonymizer e
}
return result;
- }
+ }*/
}