You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2013/10/16 19:54:16 UTC

svn commit: r1532831 - in /directory/escimo/trunk: client/src/main/java/org/apache/directory/scim/ client/src/main/resources/ common/src/main/java/org/apache/directory/scim/ common/src/main/java/org/apache/directory/scim/util/ ldap/src/main/java/org/ap...

Author: kayyagari
Date: Wed Oct 16 17:54:15 2013
New Revision: 1532831

URL: http://svn.apache.org/r1532831
Log:
o test harness
o modified attribute handlers to handle PATCH operation

Added:
    directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/JettyServer.java
      - copied, changed from r1531583, directory/escimo/trunk/tests/src/main/java/org/apache/directory/scim/JettyServer.java
Removed:
    directory/escimo/trunk/tests/src/main/java/org/apache/directory/scim/JettyServer.java
Modified:
    directory/escimo/trunk/client/src/main/java/org/apache/directory/scim/EscimoClient.java
    directory/escimo/trunk/client/src/main/resources/example-user.json
    directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/AttributeHandler.java
    directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/ProviderService.java
    directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/util/ResourceUtil.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapUtil.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/ActiveAttributeHandler.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/GroupsAttributeHandler.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MembersAttributeHandler.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MetaAttributeHandler.java
    directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/PhotosAttributeHandler.java
    directory/escimo/trunk/ldap/src/main/resources/escimo-ldap-mapping.xml
    directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/GroupService.java
    directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/UserService.java
    directory/escimo/trunk/tests/pom.xml
    directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/UserResourceTest.java

Modified: directory/escimo/trunk/client/src/main/java/org/apache/directory/scim/EscimoClient.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/client/src/main/java/org/apache/directory/scim/EscimoClient.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/client/src/main/java/org/apache/directory/scim/EscimoClient.java (original)
+++ directory/escimo/trunk/client/src/main/java/org/apache/directory/scim/EscimoClient.java Wed Oct 16 17:54:15 2013
@@ -21,12 +21,16 @@ package org.apache.directory.scim;
 
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.directory.scim.schema.CoreResource;
 import org.apache.http.HttpResponse;
 import org.apache.http.StatusLine;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
@@ -37,6 +41,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
@@ -57,15 +62,19 @@ public class EscimoClient
 
     private Gson serializer;
 
+    private Map<String,Class<? extends CoreResource>> uriClassMap;
+    
     private static final Logger LOG = LoggerFactory.getLogger( EscimoClient.class );
 
 
-    public EscimoClient( String providerUrl )
+    public EscimoClient( String providerUrl, Map<String,Class<? extends CoreResource>> uriClassMap )
     {
         this.providerUrl = providerUrl;
+        this.uriClassMap = uriClassMap;
+        
         GsonBuilder gb = new GsonBuilder();
         gb.setExclusionStrategies( new FieldExclusionStrategy() );
-        //        gb.setDateFormat( pattern );
+        gb.setDateFormat( "yyyy-MM-dd'T'HH:mm:ss'Z'" );
         serializer = gb.create();
     }
 
@@ -74,6 +83,103 @@ public class EscimoClient
         return addResource( resource, USERS_URI );
     }
 
+    
+    public CoreResource addGroup( CoreResource resource ) throws Exception
+    {
+        return addResource( resource, GROUPS_URI );
+    }
+
+    
+    public CoreResource getUser( String id ) throws Exception
+    {
+        return getResource( id, USERS_URI );
+    }
+
+    
+    public CoreResource getGroup( String id ) throws Exception
+    {
+        return getResource( id, GROUPS_URI );
+    }
+
+    public boolean deleteUser( String id ) throws Exception
+    {
+        return deleteResource( id, USERS_URI );
+    }
+
+    public boolean deleteGroup( String id ) throws Exception
+    {
+        return deleteResource( id, GROUPS_URI );
+    }
+
+    private boolean deleteResource( String id, String uri ) throws Exception
+    {
+
+        if ( id == null )
+        {
+            throw new IllegalArgumentException( "resource ID cannot be null" );
+        }
+
+        HttpDelete get = new HttpDelete( providerUrl + uri + "/" + id );
+        
+        LOG.debug( "Trying to delete resource with ID {} at URI {}", id, uri );
+
+        HttpClient client = HttpClients.createDefault();
+
+        try
+        {
+            HttpResponse resp = client.execute( get );
+            StatusLine sl = resp.getStatusLine();
+            
+            if ( sl.getStatusCode() == 200 )
+            {
+                return true;
+            }
+        }
+        catch ( Exception e )
+        {
+            LOG.warn( "", e );
+            throw e;
+        }
+        
+        return false;
+    }
+    
+    
+    private CoreResource getResource( String id, String uri ) throws Exception
+    {
+        if ( id == null )
+        {
+            throw new IllegalArgumentException( "resource ID cannot be null" );
+        }
+
+        HttpGet get = new HttpGet( providerUrl + uri + "/" + id );
+        
+        LOG.debug( "Trying to retrieve resource with ID {} at URI {}", id, uri );
+
+        HttpClient client = HttpClients.createDefault();
+
+        try
+        {
+            HttpResponse resp = client.execute( get );
+            StatusLine sl = resp.getStatusLine();
+            
+            if ( sl.getStatusCode() == 200 )
+            {
+                String retVal = EntityUtils.toString( resp.getEntity() );
+                
+                return deserialize( retVal );
+            }
+        }
+        catch ( Exception e )
+        {
+            LOG.warn( "", e );
+            throw e;
+        }
+        
+        return null;
+    }
+
+    
     private CoreResource addResource( CoreResource resource, String uri ) throws Exception
     {
         if ( resource == null )
@@ -96,7 +202,7 @@ public class EscimoClient
             HttpResponse resp = client.execute( post );
             StatusLine sl = resp.getStatusLine();
             
-            if ( sl.getStatusCode() == 200 )
+            if ( sl.getStatusCode() == 201 )
             {
                 String retVal = EntityUtils.toString( resp.getEntity() );
                 
@@ -118,19 +224,35 @@ public class EscimoClient
         JsonParser parser = new JsonParser();
         JsonObject obj = ( JsonObject ) parser.parse( json );
 
-        CoreResource top = serializer.fromJson( obj, CoreResource.class );
-
-        for ( java.util.Map.Entry<String, JsonElement> e : obj.entrySet() )
+        JsonArray schemas = obj.get( "schemas" ).getAsJsonArray();
+        
+        CoreResource top = null;
+        
+        List<CoreResource> extList = new ArrayList<CoreResource>();
+        
+        for( JsonElement je : schemas )
         {
-            String key = e.getKey();
-
-            if ( key.startsWith( "urn:scim:schemas:" ) )
+            String sch = je.getAsString();
+            
+            JsonObject subres = obj.getAsJsonObject( sch );
+            
+            // this is the top/core schema object
+            if( subres == null )
+            {
+                top = serializer.fromJson( obj, uriClassMap.get( sch ) );
+            }
+            else
             {
-                CoreResource ext = serializer.fromJson( e.getValue(), CoreResource.class );
-                top.addExtendedResource( ext );
+                CoreResource ext = serializer.fromJson( subres, uriClassMap.get( sch ) );
+                extList.add( ext );
             }
         }
 
+        if( !extList.isEmpty() )
+        {
+            top.setExtResources( extList );
+        }
+        
         return top;
     }
 
@@ -153,14 +275,23 @@ public class EscimoClient
         return json;
     }
 
-
-    public static void main( String[] args )
+    private Map<String, Class<? extends CoreResource>> getUriClassMap( CoreResource resource )
     {
-        EscimoClient ec = new EscimoClient( "http://example.com" );
-        String json = ec.serializer.toJson( ec );
-        System.out.println( json );
-
-        EscimoClient clone = ec.serializer.fromJson( json, EscimoClient.class );
-        System.out.println( clone );
+        String topUri = resource.getSchemaId();
+        Map<String, Class<? extends CoreResource>> map = new HashMap<String, Class<? extends CoreResource>>();
+        map.put( topUri, resource.getClass() );
+        
+        List<CoreResource> ext = resource.getExtResources();
+        
+        if( ext != null )
+        {
+            for( CoreResource c : ext )
+            {
+                map.put( c.getSchemaId(), c.getClass() );
+            }
+        }
+        
+        return map;
     }
+
 }

Modified: directory/escimo/trunk/client/src/main/resources/example-user.json
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/client/src/main/resources/example-user.json?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/client/src/main/resources/example-user.json (original)
+++ directory/escimo/trunk/client/src/main/resources/example-user.json Wed Oct 16 17:54:15 2013
@@ -64,12 +64,8 @@
      ],
      "photos": [
        {
-         "value": "https://photos.example.com/profilephoto/72930000000Ccne/F",
+         "value": "file:///Users/dbugger/myphotos/23.jpg",
          "type": "photo"
-       },
-       {
-         "value": "https://photos.example.com/profilephoto/72930000000Ccne/T",
-         "type": "thumbnail"
        }
      ],
      "userType": "Employee",

Modified: directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/AttributeHandler.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/AttributeHandler.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/AttributeHandler.java (original)
+++ directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/AttributeHandler.java Wed Oct 16 17:54:15 2013
@@ -34,8 +34,7 @@ public abstract class AttributeHandler
 {
     public abstract void read( BaseType bt, Object srcResource, RequestContext ctx );
     
-    public void write( BaseType atType, JsonElement jsonData, Object targetEntry, RequestContext ctx )
-    {
-        
-    }
+    public abstract void write( BaseType atType, JsonElement jsonData, Object targetEntry, RequestContext ctx ) throws Exception;
+    
+    public abstract void patch( BaseType atType, JsonElement jsonData, Object targetEntry, RequestContext ctx, Object patchCtx ) throws Exception;
 }

Modified: directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/ProviderService.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/ProviderService.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/ProviderService.java (original)
+++ directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/ProviderService.java Wed Oct 16 17:54:15 2013
@@ -43,4 +43,16 @@ public interface ProviderService 
     UserResource addUser( String jsonData, RequestContext ctx ) throws Exception;
     
     GroupResource addGroup( String jsonData, RequestContext ctx ) throws Exception;
+    
+    void deleteUser( String id ) throws Exception;
+    
+    void deleteGroup( String id ) throws Exception;
+    
+    /*UserResource putUser( String jsonData, RequestContext ctx ) throws Exception;
+    
+    GroupResource putGroup( String jsonData, RequestContext ctx ) throws Exception;
+
+    UserResource patchUser( String jsonData, RequestContext ctx ) throws Exception;
+    
+    GroupResource patchGroup( String jsonData, RequestContext ctx ) throws Exception;*/
 }

Modified: directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/util/ResourceUtil.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/util/ResourceUtil.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/util/ResourceUtil.java (original)
+++ directory/escimo/trunk/common/src/main/java/org/apache/directory/scim/util/ResourceUtil.java Wed Oct 16 17:54:15 2013
@@ -43,8 +43,7 @@ public class ResourceUtil
 
         start = end;
         end += 2;
-        sb.append( zTime.substring( start, end ) )
-            .append( "-" );
+        sb.append( zTime.substring( start, end ) );
 
         sb.append( "T" );
 

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java Wed Oct 16 17:54:15 2013
@@ -42,14 +42,12 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.entry.Entry;
 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.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
 import org.apache.directory.api.ldap.model.message.ModifyRequest;
 import org.apache.directory.api.ldap.model.message.ModifyRequestImpl;
 import org.apache.directory.api.ldap.model.message.ModifyResponse;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.message.controls.ManageDsaITImpl;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
@@ -73,8 +71,8 @@ import org.apache.directory.scim.Missing
 import org.apache.directory.scim.MultiValAttribute;
 import org.apache.directory.scim.ProviderService;
 import org.apache.directory.scim.RequestContext;
-import org.apache.directory.scim.ServerResource;
 import org.apache.directory.scim.ResourceNotFoundException;
+import org.apache.directory.scim.ServerResource;
 import org.apache.directory.scim.SimpleAttribute;
 import org.apache.directory.scim.SimpleAttributeGroup;
 import org.apache.directory.scim.UserResource;
@@ -293,8 +291,10 @@ public class LdapResourceProvider implem
     }
 
     
-    private void addAttributes( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema ) throws LdapException
+    private void addAttributes( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema ) throws Exception
     {
+        //obj.remove( "schemas" );
+        
         for( java.util.Map.Entry<String, JsonElement> e : obj.entrySet() )
         {
             String name = e.getKey();
@@ -308,7 +308,8 @@ public class LdapResourceProvider implem
             
             if( bt == null )
             {
-                throw new IllegalArgumentException( "Unknown attribute name "  + name + " is present in the JSON payload that has no corresponding mapping in the escimo-ldap-mapping.xml file" );
+                LOG.debug( "Unknown attribute name "  + name + " is present in the JSON payload that has no corresponding mapping in the escimo-ldap-mapping.xml file" );
+                continue;
             }
             
             if( bt.isReadOnly() )
@@ -646,28 +647,29 @@ public class LdapResourceProvider implem
 
         Entry entry = new DefaultEntry( ldapSchema );
         
-        _resourceToEntry( entry, obj, ctx, resourceSchema, "" );
+        LdapUtil.patchAttributes( entry, obj, ctx, resourceSchema, modReq );
+        
 
-        for( Attribute ldapAt : entry )
-        {
-            AttributeType type = ldapAt.getAttributeType();
-            
-            if( deleteModAtOids.contains( type.getOid() ) )
-            {
-                modReq.add( ldapAt );
-            }
-            else if( existingEntry.containsAttribute( type ) )
-            {
-                if( type.isSingleValued() )
-                {
-                    modReq.replace( ldapAt );
-                }
-                else
-                {
-                    modReq.add( ldapAt );
-                }
-            }
-        }
+//        for( Attribute ldapAt : entry )
+//        {
+//            AttributeType type = ldapAt.getAttributeType();
+//            
+//            if( deleteModAtOids.contains( type.getOid() ) )
+//            {
+//                modReq.add( ldapAt );
+//            }
+//            else if( existingEntry.containsAttribute( type ) )
+//            {
+//                if( type.isSingleValued() )
+//                {
+//                    modReq.replace( ldapAt );
+//                }
+//                else
+//                {
+//                    modReq.add( ldapAt );
+//                }
+//            }
+//        }
     }
     
     public UserResource toUser( RequestContext ctx, Entry entry ) throws Exception
@@ -681,6 +683,23 @@ public class LdapResourceProvider implem
         return user;
     }
 
+    
+    public void deleteUser( String id ) throws Exception
+    {
+        deleteResource( id, userSchema );
+    }
+    
+    public void deleteGroup( String id ) throws Exception
+    {
+        deleteResource( id, groupSchema );
+    }
+    
+    
+    private void deleteResource( String id, ResourceSchema schema ) throws LdapException
+    {
+        Entry entry = fetchEntryById( id, schema );
+        connection.delete( entry.getDn() );
+    }
 
     public GroupResource toGroup( RequestContext ctx, Entry entry ) throws Exception
     {
@@ -1029,7 +1048,8 @@ public class LdapResourceProvider implem
     {
         return ldapSchema;
     }
-
+    
+    private static String HPD_PROVIDER_DN = "m-oid=1.3.6.1.4.1.19376.1.2.4.1,ou=objectClasses,cn=hpd,ou=schema";
 
     public static void main( String[] args ) throws Exception
     {
@@ -1043,25 +1063,24 @@ public class LdapResourceProvider implem
 
         LdapNetworkConnection c = new LdapNetworkConnection( "localhost", 10389 );
         c.setTimeOut( Long.MAX_VALUE );
-        c.bind( "cn=mta,dc=example,dc=com", "secret" );
-        c.loadSchema();
+        c.bind( "uid=admin,ou=system", "secret" );
+//        c.loadSchema();
         //c.loadSchema( new JarLdifSchemaLoader() );
 
-        ManageDsaITImpl managedsa = new ManageDsaITImpl();
-        SearchRequest req = new SearchRequestImpl();
-        req.addControl( managedsa );
-
-        //EntryCursor cursor = c.search( "", "(entryUUID=7ca31977-ba2d-4cdc-a86d-ba9fba06cd15)", SearchScope.SUBTREE, "*" );
-        EntryCursor cursor = c.search( "dc=example,dc=com", "(objectClass=*)", SearchScope.SUBTREE, "*" );
-        System.out.println("searching");
-
-        while ( cursor.next() )
-        {
-            Entry entry = cursor.get();
-            System.out.println( entry );
-        }
-
-        cursor.close();
+        Entry hpdProviderEntry = c.lookup(HPD_PROVIDER_DN);
+        boolean hasBeenApplied = hpdProviderEntry.contains( "m-may", "hpdProviderLegalAddress1");
+        System.out.println(hasBeenApplied);
+        String ldif = "dn: m-oid=1.3.6.1.4.1.19376.1.2.4.1,ou=objectClasses,cn=hpd,ou=schema\n"+
+                      "changetype: modify\n"+
+                      "delete: m-may\n" +
+                      "m-may: hpdProviderLegalAddress\n" +
+                      "-\n";
+        LdifReader reader = new LdifReader( ldif );
+        
+        LdifEntry entry = reader.next();
+        
+        c.add( entry.getEntry() );
+        
         c.close();
     }
 }

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapUtil.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapUtil.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapUtil.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapUtil.java Wed Oct 16 17:54:15 2013
@@ -22,14 +22,18 @@ package org.apache.directory.scim.ldap;
 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.Entry;
+import org.apache.directory.api.ldap.model.entry.ModificationOperation;
 import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.ModifyRequest;
 import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.schema.SchemaManager;
 import org.apache.directory.api.util.Base64;
 import org.apache.directory.api.util.Strings;
+import org.apache.directory.scim.AttributeHandler;
 import org.apache.directory.scim.RequestContext;
 import org.apache.directory.scim.ldap.schema.ComplexType;
 import org.apache.directory.scim.ldap.schema.MultiValType;
+import org.apache.directory.scim.ldap.schema.ResourceSchema;
 import org.apache.directory.scim.ldap.schema.SimpleType;
 import org.apache.directory.scim.ldap.schema.SimpleTypeGroup;
 import org.apache.directory.scim.schema.BaseType;
@@ -121,9 +125,14 @@ public class LdapUtil
             }
         }
     }
-    
+
     public static void storeSimpleAttribute( SimpleType st, JsonElement el, Entry entry, SchemaManager ldapSschema ) throws LdapException
     {
+        storeSimpleAttribute( st, el.getAsString(), entry, ldapSschema );
+    }
+    
+    private static void storeSimpleAttribute( SimpleType st, String encodedOrPlainStrVal, Entry entry, SchemaManager ldapSschema ) throws LdapException
+    {
         if( st.isReadOnly() )
         {
             return;
@@ -147,12 +156,193 @@ public class LdapUtil
         
         if( !ldapType.getSyntax().isHumanReadable() )
         {
-            byte[] value = Base64.decode( el.getAsString().toCharArray() );
+            byte[] value = Base64.decode( encodedOrPlainStrVal.toCharArray() );
             ldapAt.add( value );
         }
         else
         {
-            ldapAt.add( el.getAsString() );
+            ldapAt.add( encodedOrPlainStrVal );
+        }
+    }
+
+    
+    
+    //================ PATCH ========
+    
+    public static void patchAttributes( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema, ModifyRequest modReq ) throws Exception
+    {
+        for( java.util.Map.Entry<String, JsonElement> e : obj.entrySet() )
+        {
+            String name = e.getKey();
+            
+            if( name.startsWith( "urn:scim:schemas:" ) )
+            {
+                continue;
+            }
+            
+            BaseType bt = resourceSchema.getAttribute( name );
+            
+            if( bt == null )
+            {
+                throw new IllegalArgumentException( "Unknown attribute name "  + name + " is present in the JSON payload that has no corresponding mapping in the escimo-ldap-mapping.xml file" );
+            }
+            
+            if( bt.isReadOnly() )
+            {
+                continue;
+            }
+
+            AttributeHandler handler = resourceSchema.getHandler( bt.getAtHandlerName() );
+            
+            if( handler != null )
+            {
+                handler.patch( bt, e.getValue(), entry, ctx, modReq );
+            }
+            else
+            {
+                patchLdapAttribute( bt, e.getValue(), entry, ctx, modReq );
+            }
+        }
+    }
+
+    
+    public static void patchLdapAttribute( BaseType bt, JsonElement el, Entry entry, RequestContext ctx, ModifyRequest modReq ) throws LdapException
+    {
+        if( bt.isReadOnly() )
+        {
+            return;
+        }
+        
+        SchemaManager ldapSchema = ( ( LdapResourceProvider ) ctx.getProviderService() ).getLdapSchema();
+        
+        if( bt instanceof ComplexType )
+        {
+            ComplexType ct = ( ComplexType ) bt;
+            SimpleTypeGroup complexStg = ct.getAtGroup();
+            
+            JsonObject jo = ( JsonObject ) el;
+            patchSimpleTypeGroup( complexStg, jo, entry, ldapSchema, ct.getName(), modReq );
+        }
+        else if( bt instanceof MultiValType )
+        {
+            MultiValType mt = ( MultiValType ) bt;
+            SimpleTypeGroup multiStg = mt.getAtGroup();
+            
+            JsonArray valArray = el.getAsJsonArray();
+            
+            for( JsonElement je : valArray )
+            {
+                // for the cases where multivalued attribute comes as an array of primitives
+                // e.x "emails":['elecharny@apache.org', 'pajbam@apache.org']
+                if( je.isJsonPrimitive() )
+                {
+                    patchSimpleAttribute( multiStg.getValueType(), je, entry, ldapSchema, modReq, ModificationOperation.REPLACE_ATTRIBUTE );
+                }
+                else
+                {
+                    JsonObject jo = ( JsonObject ) je;
+                    patchSimpleTypeGroup( multiStg, jo, entry, ldapSchema, mt.getName(), modReq );
+                }
+            }
+        }
+        else
+        {
+            patchSimpleAttribute( ( SimpleType ) bt, el, entry, ldapSchema, modReq, ModificationOperation.REPLACE_ATTRIBUTE );
+        }
+    }
+
+
+    // BaseType atType, JsonElement jsonData, Object targetEntry, Object patchCtx 
+    private static void patchSimpleTypeGroup( SimpleTypeGroup stg, JsonObject jo, Entry entry, SchemaManager ldapSchema, String scimComplexAtName, ModifyRequest modReq ) throws LdapException
+    {
+        ModificationOperation operation = ModificationOperation.REPLACE_ATTRIBUTE; // the default
+        
+        JsonElement atOperation = jo.get( "operation" );
+        if( atOperation != null )
+        {
+            if( atOperation.getAsString().equalsIgnoreCase( "delete" ) )
+            {
+                operation = ModificationOperation.REMOVE_ATTRIBUTE;
+            }
+            
+            jo.remove( "operation" );
+        }
+        
+        for( java.util.Map.Entry<String, JsonElement> e : jo.entrySet() )
+        {
+            String scimAtName = e.getKey();
+            
+            SimpleType st = null;
+            
+            for( SimpleType temp : stg.getSubTypes() )
+            {
+                if( scimAtName.equals( temp.getName() ) )
+                {
+                    st = temp;
+                    break;
+                }
+            }
+            
+            if( st != null )
+            {
+                patchSimpleAttribute( st, e.getValue(), entry, ldapSchema, modReq, operation );
+            }
+            else
+            {
+                LOG.warn( "No LDAP mapping found for the sub attribute " + scimAtName + " of the complex attribute " + scimComplexAtName );
+            }
+        }
+    }
+    
+    public static void patchSimpleAttribute( SimpleType st, JsonElement el, Entry entry, SchemaManager ldapSschema, ModifyRequest modReq, ModificationOperation operation ) throws LdapException
+    {
+        if( st.isReadOnly() )
+        {
+            return;
+        }
+        
+        String ldapAtName = st.getMappedTo();
+        
+        if( Strings.isEmpty( ldapAtName ) )
+        {
+            throw new IllegalArgumentException( "Attribute " + st.getName() + " is not mapped to any LDAP attribute in the config" );
+        }
+        
+        AttributeType ldapType = ldapSschema.getAttributeType( ldapAtName );
+        
+        if( !ldapType.getSyntax().isHumanReadable() )
+        {
+            byte[] value = Base64.decode( el.getAsString().toCharArray() );
+            
+            if( operation == ModificationOperation.REPLACE_ATTRIBUTE )
+            {
+                modReq.replace( ldapAtName, value );
+            }
+            if( operation == ModificationOperation.REMOVE_ATTRIBUTE )
+            {
+                modReq.remove( ldapAtName, value );
+            }
+            else
+            {
+                modReq.add( ldapAtName, value );
+            }
+        }
+        else
+        {
+            String value = el.getAsString();
+            
+            if( operation == ModificationOperation.REPLACE_ATTRIBUTE )
+            {
+                modReq.replace( ldapAtName, value );
+            }
+            if( operation == ModificationOperation.REMOVE_ATTRIBUTE )
+            {
+                modReq.remove( ldapAtName, value );
+            }
+            else
+            {
+                modReq.add( ldapAtName, value );
+            }
         }
     }
 

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/ActiveAttributeHandler.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/ActiveAttributeHandler.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/ActiveAttributeHandler.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/ActiveAttributeHandler.java Wed Oct 16 17:54:15 2013
@@ -23,7 +23,6 @@ import org.apache.directory.api.ldap.mod
 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.exception.LdapException;
-import org.apache.directory.scim.AttributeHandler;
 import org.apache.directory.scim.RequestContext;
 import org.apache.directory.scim.SimpleAttribute;
 import org.apache.directory.scim.schema.BaseType;
@@ -35,7 +34,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class ActiveAttributeHandler extends AttributeHandler
+public class ActiveAttributeHandler extends LdapAttributeHandler
 {
 
     private static final Logger LOG = LoggerFactory.getLogger( ActiveAttributeHandler.class );

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/GroupsAttributeHandler.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/GroupsAttributeHandler.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/GroupsAttributeHandler.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/GroupsAttributeHandler.java Wed Oct 16 17:54:15 2013
@@ -39,7 +39,6 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.filter.SimpleNode;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.util.Strings;
-import org.apache.directory.scim.AttributeHandler;
 import org.apache.directory.scim.MultiValAttribute;
 import org.apache.directory.scim.RequestContext;
 import org.apache.directory.scim.SimpleAttribute;
@@ -56,7 +55,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class GroupsAttributeHandler extends AttributeHandler
+public class GroupsAttributeHandler extends LdapAttributeHandler
 {
 
     private static final Logger LOG = LoggerFactory.getLogger( GroupsAttributeHandler.class );

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MembersAttributeHandler.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MembersAttributeHandler.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MembersAttributeHandler.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MembersAttributeHandler.java Wed Oct 16 17:54:15 2013
@@ -39,7 +39,6 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.filter.SimpleNode;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.util.Strings;
-import org.apache.directory.scim.AttributeHandler;
 import org.apache.directory.scim.MultiValAttribute;
 import org.apache.directory.scim.RequestContext;
 import org.apache.directory.scim.SimpleAttribute;
@@ -55,7 +54,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class MembersAttributeHandler extends AttributeHandler
+public class MembersAttributeHandler extends LdapAttributeHandler
 {
 
     private static final Logger LOG = LoggerFactory.getLogger( MembersAttributeHandler.class );

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MetaAttributeHandler.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MetaAttributeHandler.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MetaAttributeHandler.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/MetaAttributeHandler.java Wed Oct 16 17:54:15 2013
@@ -26,11 +26,10 @@ import org.apache.directory.api.ldap.mod
 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.exception.LdapException;
-import org.apache.directory.scim.AttributeHandler;
 import org.apache.directory.scim.ComplexAttribute;
-import org.apache.directory.scim.ServerResource;
 import org.apache.directory.scim.GroupResource;
 import org.apache.directory.scim.RequestContext;
+import org.apache.directory.scim.ServerResource;
 import org.apache.directory.scim.SimpleAttribute;
 import org.apache.directory.scim.schema.BaseType;
 import org.apache.directory.scim.util.ResourceUtil;
@@ -42,7 +41,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class MetaAttributeHandler extends AttributeHandler
+public class MetaAttributeHandler extends LdapAttributeHandler
 {
 
     private static final Logger LOG = LoggerFactory.getLogger( ActiveAttributeHandler.class );

Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/PhotosAttributeHandler.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/PhotosAttributeHandler.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/PhotosAttributeHandler.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/handlers/PhotosAttributeHandler.java Wed Oct 16 17:54:15 2013
@@ -20,34 +20,39 @@
 package org.apache.directory.scim.ldap.handlers;
 
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
 import java.net.URLEncoder;
-import java.util.List;
 
 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.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.scim.AttributeHandler;
-import org.apache.directory.scim.ServerResource;
 import org.apache.directory.scim.MultiValAttribute;
 import org.apache.directory.scim.RequestContext;
+import org.apache.directory.scim.ServerResource;
 import org.apache.directory.scim.SimpleAttribute;
 import org.apache.directory.scim.SimpleAttributeGroup;
-import org.apache.directory.scim.UserResource;
 import org.apache.directory.scim.ldap.schema.MultiValType;
 import org.apache.directory.scim.ldap.schema.SimpleType;
 import org.apache.directory.scim.ldap.schema.SimpleTypeGroup;
-import org.apache.directory.scim.ldap.schema.TypedType;
 import org.apache.directory.scim.schema.BaseType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
 
 /**
  * TODO PhotosAttributeHandler.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class PhotosAttributeHandler extends AttributeHandler
+public class PhotosAttributeHandler extends LdapAttributeHandler
 {
 
     private static final Logger LOG = LoggerFactory.getLogger( PhotosAttributeHandler.class );
@@ -56,12 +61,7 @@ public class PhotosAttributeHandler exte
     @Override
     public void read( BaseType bt, Object srcResource, RequestContext ctx )
     {
-        if ( !bt.getName().equals( "photos" ) )
-        {
-            LOG.debug( "PhotosAttributeHandler can  only be called on the photos attribute, invalid attribute name {}",
-                bt.getName() );
-            return;
-        }
+        checkHandler( bt, "photos", this );
 
         ServerResource user = ctx.getCoreResource();
 
@@ -131,4 +131,87 @@ public class PhotosAttributeHandler exte
         }
     }
 
+
+    @Override
+    public void write( BaseType atType, JsonElement jsonData, Object targetEntry, RequestContext ctx ) throws Exception
+    {
+        checkHandler( atType, "photos", this );
+        
+        MultiValType mt = ( MultiValType ) atType;
+        
+        SimpleType st = mt.getAtGroup().getValueType();
+        
+        JsonArray photos = ( JsonArray ) jsonData;
+        
+        Entry entry = ( Entry ) targetEntry;
+        
+        Attribute ldapAt = entry.get( st.getMappedTo() );
+        
+        // fetch the URL and insert the photo
+        for( JsonElement je : photos )
+        {
+            String url = null;
+            
+            // for the cases where multivalued attribute comes as an array of primitives
+            // e.x "photos":['http://example.com/p1', 'http://example.com/p2']
+            if( je.isJsonPrimitive() )
+            {
+                url = je.getAsString();
+            }
+            else
+            {
+                JsonObject jo = ( JsonObject ) je;
+                url = jo.get( "value" ).getAsString();
+            }
+            
+            byte[] data = fetchPhoto( url );
+            
+            
+            if( ldapAt == null )
+            {
+                ldapAt = new DefaultAttribute( st.getMappedTo(), data );
+                entry.add( ldapAt );
+            }
+            else
+            {
+                ldapAt.add( data );
+            }
+        }
+    }
+
+    
+    private byte[] fetchPhoto( String url ) throws IOException
+    {
+        InputStream in = null;
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+
+        try
+        {
+            in = new URL( url ).openStream();
+            byte[] buf = new byte[1024];
+            
+            while( true )
+            {
+                int read = in.read( buf );
+                
+                if( read <= 0 )
+                {
+                    break;
+                }
+                
+                bout.write( buf, 0, read );
+            }
+            
+            return bout.toByteArray();
+        }
+        finally
+        {
+            if( in != null )
+            {
+                in.close();
+            }
+
+            bout.close();
+        }
+    }
 }

Modified: directory/escimo/trunk/ldap/src/main/resources/escimo-ldap-mapping.xml
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/resources/escimo-ldap-mapping.xml?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/resources/escimo-ldap-mapping.xml (original)
+++ directory/escimo/trunk/ldap/src/main/resources/escimo-ldap-mapping.xml Wed Oct 16 17:54:15 2013
@@ -51,7 +51,7 @@
             <at-group>
                 <attribute name="streetAddress" mappedTo="street" />
                 <attribute name="locality" mappedTo="l" />
-                <attribute name="region" mappedTo="region" />
+                <attribute name="region" mappedTo="" />
                 <attribute name="postalCode" mappedTo="postalCode" />
                 <attribute name="country" mappedTo="" />
                 <formatted format="$streetAddress $locality" />

Modified: directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/GroupService.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/GroupService.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/GroupService.java (original)
+++ directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/GroupService.java Wed Oct 16 17:54:15 2013
@@ -22,6 +22,7 @@ package org.apache.directory.scim.rest;
 
 import java.net.URI;
 
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -81,6 +82,26 @@ public class GroupService
         return rb.build();
     }
 
+    
+    @DELETE
+    @Path("{id}")
+    public Response deleteGroup( @PathParam("id") String userId, @Context UriInfo uriInfo, @Context HttpHeaders headers )
+    {
+        ResponseBuilder rb = Response.ok();
+        
+        try
+        {
+            provider.deleteGroup( userId );
+        }
+        catch( Exception e )
+        {
+            rb = Response.status( Status.INTERNAL_SERVER_ERROR ).entity( exceptionToStr( e ) );
+        }
+        
+        return rb.build();
+    }
+
+    
     @POST
     @Produces({MediaType.APPLICATION_JSON})
     public Response addGroup( String jsonData, @Context UriInfo uriInfo, @Context HttpHeaders headers )

Modified: directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/UserService.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/UserService.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/UserService.java (original)
+++ directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/UserService.java Wed Oct 16 17:54:15 2013
@@ -25,6 +25,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
 
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -86,6 +87,25 @@ public class UserService
         return rb.build();
     }
     
+
+    @DELETE
+    @Path("{id}")
+    public Response deleteUser( @PathParam("id") String userId, @Context UriInfo uriInfo, @Context HttpHeaders headers )
+    {
+        ResponseBuilder rb = Response.ok();
+        
+        try
+        {
+            provider.deleteUser( userId );
+        }
+        catch( Exception e )
+        {
+            rb = Response.status( Status.INTERNAL_SERVER_ERROR ).entity( exceptionToStr( e ) );
+        }
+        
+        return rb.build();
+    }
+    
     
     @POST
     @Produces({MediaType.APPLICATION_JSON})

Modified: directory/escimo/trunk/tests/pom.xml
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/tests/pom.xml?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/tests/pom.xml (original)
+++ directory/escimo/trunk/tests/pom.xml Wed Oct 16 17:54:15 2013
@@ -80,7 +80,7 @@
       <version>4.10</version>
       <scope>test</scope>
     </dependency>
-<!-- 
+
     <dependency>
       <groupId>org.apache.directory.server</groupId>
       <artifactId>apacheds-core-annotations</artifactId>
@@ -100,7 +100,7 @@
       <artifactId>apacheds-test-framework</artifactId>
       <version>${apacheds.version}</version>
       <scope>test</scope>
-    </dependency>-->
+    </dependency>
   </dependencies>
 
   <build>

Copied: directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/JettyServer.java (from r1531583, directory/escimo/trunk/tests/src/main/java/org/apache/directory/scim/JettyServer.java)
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/JettyServer.java?p2=directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/JettyServer.java&p1=directory/escimo/trunk/tests/src/main/java/org/apache/directory/scim/JettyServer.java&r1=1531583&r2=1532831&rev=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/tests/src/main/java/org/apache/directory/scim/JettyServer.java (original)
+++ directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/JettyServer.java Wed Oct 16 17:54:15 2013
@@ -5,9 +5,23 @@ import java.io.File;
 import java.io.FilenameFilter;
 import java.io.InputStream;
 import java.util.Enumeration;
+import java.util.concurrent.CountDownLatch;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
+import org.apache.directory.api.ldap.model.schema.SchemaManager;
+import org.apache.directory.server.annotations.CreateLdapServer;
+import org.apache.directory.server.annotations.CreateTransport;
+import org.apache.directory.server.core.annotations.ContextEntry;
+import org.apache.directory.server.core.annotations.CreateDS;
+import org.apache.directory.server.core.annotations.CreateIndex;
+import org.apache.directory.server.core.annotations.CreatePartition;
+import org.apache.directory.server.core.api.CoreSession;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.factory.DSAnnotationProcessor;
+import org.apache.directory.server.factory.ServerAnnotationProcessor;
+import org.apache.directory.server.ldap.LdapServer;
+import org.apache.directory.server.ldap.replication.provider.SyncReplRequestHandler;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.webapp.WebAppContext;
 
@@ -18,7 +32,10 @@ public class JettyServer
 {
     private static Server server;
 
+    private static LdapServer ldapServer;
 
+    private static CoreSession adminSession;
+    
     public static void start() throws Exception
     {
         if ( ( server != null ) && server.isRunning() )
@@ -26,13 +43,15 @@ public class JettyServer
             return;
         }
         
+        startLdapServer();
+        
         WebAppContext webapp = new WebAppContext();
         webapp.setContextPath( "/" );
         webapp.setWar( getEscimoWar().getAbsolutePath() );
         webapp.setParentLoaderPriority( true );
         String cpath = System.getProperty("java.class.path");
         
-        checkForJdk6Compliance( cpath );
+        //checkForJdk6Compliance( cpath );
         
         cpath = cpath.replaceAll( ":", ";" );
 //        webapp.setExtraClasspath( cpath );
@@ -40,7 +59,6 @@ public class JettyServer
         server = new Server( 8080 );
         server.setHandler( webapp );
         server.start();
-        server.join();
     }
 
 
@@ -57,6 +75,11 @@ public class JettyServer
                 e.printStackTrace();
             }
         }
+        
+        if( ldapServer != null )
+        {
+            ldapServer.stop();
+        }
     }
 
 
@@ -109,6 +132,60 @@ public class JettyServer
         return warFile;
     }
 
+    
+    
+    @CreateDS(
+        allowAnonAccess = true,
+        name = "provider-replication",
+        enableChangeLog = false,
+        partitions =
+            {
+                @CreatePartition(
+                    name = "example",
+                    suffix = "dc=example,dc=com",
+                    indexes =
+                        {
+                            @CreateIndex(attribute = "objectClass"),
+                            @CreateIndex(attribute = "dc"),
+                            @CreateIndex(attribute = "ou")
+                    },
+                    contextEntry = @ContextEntry(entryLdif =
+                        "dn: dc=example,dc=com\n" +
+                            "objectClass: domain\n" +
+                            "dc: example"))
+        })
+    @CreateLdapServer(transports =
+        { @CreateTransport(port = 10389, protocol = "LDAP") })
+    public static void startLdapServer() throws Exception
+    {
+        DirectoryService provDirService = DSAnnotationProcessor.getDirectoryService();
+
+        ldapServer = ServerAnnotationProcessor.getLdapServer( provDirService );
+        ldapServer.setReplicationReqHandler( new SyncReplRequestHandler() );
+        ldapServer.startReplicationProducer();
+
+        Runnable r = new Runnable()
+        {
+
+            public void run()
+            {
+                try
+                {
+                    adminSession = ldapServer.getDirectoryService().getAdminSession();
+                }
+                catch ( Exception e )
+                {
+                    throw new RuntimeException( e );
+                }
+            }
+        };
+
+        Thread t = new Thread( r );
+        t.setDaemon( true );
+        t.start();
+        t.join();
+    }
+    
     private static void checkForJdk6Compliance( String classpath ) throws Exception
     {
         String[] files = classpath.split( ":" );

Modified: directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/UserResourceTest.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/UserResourceTest.java?rev=1532831&r1=1532830&r2=1532831&view=diff
==============================================================================
--- directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/UserResourceTest.java (original)
+++ directory/escimo/trunk/tests/src/test/java/org/apache/directory/scim/UserResourceTest.java Wed Oct 16 17:54:15 2013
@@ -23,10 +23,15 @@ import static org.junit.Assert.assertEqu
 import static org.junit.Assert.assertNotNull;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.directory.scim.User.Email;
 import org.apache.directory.scim.User.Name;
+import org.apache.directory.scim.schema.CoreResource;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 /**
@@ -34,12 +39,51 @@ import org.junit.Test;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
+//@ApplyLdifs(
+//    {
+//        "dn: uid=user1,ou=users,ou=system",
+//        "objectClass: inetOrgPerson",
+//        "sn: user1 sn",
+//        "cn: user One",
+//        "uid: user1",
+//
+//        "dn: uid=user2,ou=users,ou=system",
+//        "objectClass: inetOrgPerson",
+//        "sn: User Two",
+//        "cn: user2",
+//        "uid: user2",
+//
+//        "dn: uid=elecharny,ou=users,ou=system",
+//        "objectClass: inetOrgPerson",
+//        "sn:: RW1tYW51ZWwgTMOpY2hhcm55",
+//        "cn: elecharny",
+//        "uid: elecharny"
+//})
 public class UserResourceTest
 {
-    private EscimoClient client = new EscimoClient( "http://localhost:8080/v2" );
+    private static EscimoClient client;
+    
+    @BeforeClass
+    public static void startJetty() throws Exception
+    {
+        Map<String,Class<? extends CoreResource>> uriClassMap = new HashMap<String, Class<? extends CoreResource>>();
+        uriClassMap.put( User.SCHEMA_ID, User.class );
+        uriClassMap.put( Group.SCHEMA_ID, Group.class );
+        uriClassMap.put( EnterpriseUser.SCHEMA_ID, EnterpriseUser.class );
+        
+        client = new EscimoClient( "http://localhost:8080/v2", uriClassMap );
+        
+        JettyServer.start();
+    }
+    
+    @AfterClass
+    public static void stopJetty() throws Exception
+    {
+        JettyServer.stop();
+    }
     
     @Test
-    public void testAddUser() throws Exception
+    public void testAddGetAndDeleteUser() throws Exception
     {
         User user = new User();
         user.setUserName( "test2" );
@@ -63,5 +107,12 @@ public class UserResourceTest
         assertNotNull( addedUser );
         
         assertEquals( user.getUserName(), addedUser.getUserName() );
+        
+        User fetchedUser = ( User ) client.getUser( addedUser.getId() );
+        
+        assertEquals( addedUser.getUserName(), fetchedUser.getUserName() );
+        assertEquals( addedUser.getId(), fetchedUser.getId() );
+        
+//        client.
     }
 }