1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  
21  package org.apache.directory.server.core.trigger;
22  
23  
24  import org.apache.directory.server.core.DirectoryService;
25  import org.apache.directory.server.core.integ.CiRunner;
26  import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext;
27  import static org.apache.directory.server.core.integ.IntegrationUtils.injectEntries;
28  import org.apache.directory.shared.ldap.sp.JavaStoredProcUtils;
29  import org.apache.directory.shared.ldap.trigger.TriggerUtils;
30  import org.apache.directory.shared.ldap.util.AttributeUtils;
31  import static org.junit.Assert.assertNotNull;
32  import static org.junit.Assert.assertTrue;
33  
34  import org.junit.Ignore;
35  import org.junit.Test;
36  import org.junit.runner.RunWith;
37  
38  import javax.naming.NamingException;
39  import javax.naming.directory.Attributes;
40  import javax.naming.directory.BasicAttributes;
41  import javax.naming.ldap.LdapContext;
42  
43  
44  /**
45   * Integration tests for TriggerInterceptor.
46   *
47   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
48   * @version $Rev:$
49   */
50  @RunWith ( CiRunner.class )
51  @Ignore
52  public class TriggerInterceptorIT
53  {
54      public static DirectoryService service;
55  
56      LdapContext spCtx;
57  
58  
59      /*
60       * @todo replace this with an ldif annotation
61       */
62      public void createData( LdapContext ctx ) throws NamingException
63      {
64          Attributes spContainer = new BasicAttributes( "objectClass", "top", true );
65          spContainer.get( "objectClass" ).add( "organizationalUnit" );
66          spContainer.put( "ou", "Stored Procedures" );
67          spCtx = ( LdapContext ) ctx.createSubcontext( "ou=Stored Procedures", spContainer );
68      }
69      
70  
71      @Test
72      public void testAfterDeleteBackupDeletedEntryEntryTrigger() throws Exception
73      {
74          String ldif  = 
75              "version: 1\n" +
76              "\n" +
77              "dn: ou=backupContext, ou=system\n"+
78              "objectClass: top\n" +
79              "objectClass: organizationalUnit\n" +
80              "ou: backupContext\n" +
81              "\n" +
82              "dn: ou=testEntry, ou=system\n" +
83              "objectClass: top\n" +
84              "objectClass: organizationalUnit\n" +
85              "ou: testEntry\n";
86  
87          LdapContext sysRoot = getSystemContext( service );
88          createData( sysRoot );
89  
90          // Inject the ldif file into the server.
91          injectEntries( service, ldif );
92          
93          // Load the stored procedure unit which has the stored procedure to be triggered.
94          JavaStoredProcUtils.loadStoredProcedureClass( spCtx, BackupUtilitiesSP.class );
95          
96          // Create the Entry Trigger Specification.
97          TriggerUtils.defineTriggerExecutionSpecificPoint( sysRoot );
98          LdapContext entry = ( LdapContext ) sysRoot.lookup( "ou=testEntry" );
99          
100         // TODO - change the spec to make this pass
101         
102         String triggerSpec = "AFTER Delete CALL \"" + BackupUtilitiesSP.class.getName() +
103             ":backupDeleted\" ( $ldapContext \"\", $name, $operationPrincipal, $deletedEntry );";
104         TriggerUtils.loadEntryTriggerSpecification( entry, triggerSpec );
105         
106         // Delete the test entry in order to fire the Trigger.
107         sysRoot.destroySubcontext( "ou=testEntry" );
108         
109         // ------------------------------------------
110         // The trigger should be fired at this point.
111         // ------------------------------------------
112         
113         // Check if the Trigger really worked (backed up the deleted entry).
114         assertNotNull( sysRoot.lookup( "ou=testEntry,ou=backupContext" ) );
115     }
116     
117     
118     public void testAfterDeleteBackupDeletedEntryPrescriptiveTrigger() throws Exception
119     {
120         LdapContext sysRoot = getSystemContext( service );
121         createData( sysRoot );
122 
123         // Load the stored procedure unit which has the stored procedure to be triggered.
124         JavaStoredProcUtils.loadStoredProcedureClass( spCtx, BackupUtilitiesSP.class );
125         
126         // Create a container for backing up deleted entries.
127         String ldif  = 
128             "version: 1\n" +
129             "\n" +
130             "dn: ou=backupContext, ou=system\n"+
131             "objectClass: top\n" +
132             "objectClass: organizationalUnit\n" +
133             "ou: backupContext\n";
134         
135         // Inject the ldif file into the server.
136         injectEntries( service, ldif );
137         
138         // Create the Trigger Specification within a Trigger Subentry.
139         TriggerUtils.defineTriggerExecutionSpecificPoint( sysRoot );
140         TriggerUtils.createTriggerExecutionSubentry( sysRoot,
141                                                      "triggerSubentry1",
142                                                      "{}",
143                                                      "AFTER Delete " +
144                                                          "CALL \"" + BackupUtilitiesSP.class.getName() + ":backupDeleted\" " +
145                                                              " ( $ldapContext \"\", $name, $operationPrincipal, $deletedEntry );" );        
146 
147         /**
148          * The Trigger Specification without Java clutter:
149          * 
150          * AFTER Delete
151          *     CALL "BackupUtilitiesSP.backupDeleted" ( $ldapContext "", $name, $operationPrincipal, $deletedEntry );
152          * 
153          */   
154         
155         // Create a test entry which is selected by the Trigger Subentry.
156         String ldif2  = 
157             "version: 1\n" +
158             "\n" +
159             "dn: ou=testou, ou=system\n" +
160             "objectClass: top\n" +
161             "objectClass: organizationalUnit\n" +
162             "ou: testou\n";
163         
164         // Inject the ldif file into the server.
165         injectEntries( service, ldif2 );
166         
167         // Delete the test entry in order to fire the Trigger.
168         sysRoot.destroySubcontext( "ou=testou" );
169         
170         // ------------------------------------------
171         // The trigger should be fired at this point.
172         // ------------------------------------------
173         
174         // Check if the Trigger really worked (backed up the deleted entry).
175         assertNotNull( sysRoot.lookup( "ou=testou,ou=backupContext" ) );
176     }
177     
178     
179     public void testAfterAddSubscribeUserToSomeGroupsPrescriptiveTrigger() throws Exception
180     {
181         LdapContext sysRoot = getSystemContext( service );
182         createData( sysRoot );
183 
184         // Create two groups to be subscribed to : staff and teachers.
185         String ldif  = 
186             "version: 1\n" +
187             "\n" +
188             "dn: cn=staff, ou=system\n"+
189             "objectClass: top\n" +
190             "objectClass: groupOfUniqueNames\n" +
191             "uniqueMember: cn=dummy\n"+
192             "cn: staff\n" +
193             "\n" +
194             "dn: cn=teachers, ou=system\n"+
195             "objectClass: top\n" +
196             "objectClass: groupOfUniqueNames\n" +
197             "uniqueMember: cn=dummy\n"+
198             "cn: teachers\n";
199         
200         // Load the stored procedure unit which has the stored procedure to be triggered.
201         JavaStoredProcUtils.loadStoredProcedureClass( spCtx, ListUtilsSP.class );
202 
203         // Inject the ldif file into the server
204         injectEntries( service, ldif );
205             
206         // Create the Trigger Specification within a Trigger Subentry.
207         String staffDN = "cn=staff, ou=system";
208         String teachersDN = "cn=teachers, ou=system";
209 
210         
211         // Create the Triger Specification within a Trigger Subentry.
212         TriggerUtils.defineTriggerExecutionSpecificPoint( sysRoot );
213         TriggerUtils.createTriggerExecutionSubentry( sysRoot,
214                                                      "triggerSubentry1",
215                                                      "{}",
216                                                      "AFTER Add " +
217                                                          "CALL \"" + ListUtilsSP.class.getName() + ":subscribeToGroup\" ( $entry , $ldapContext \"" + staffDN + "\" ); " +
218                                                          "CALL \"" + ListUtilsSP.class.getName() + ":subscribeToGroup\" ( $entry , $ldapContext \"" + teachersDN + "\" );" );
219         
220         /**
221          * The Trigger Specification without Java clutter:
222          * 
223          * AFTER Add
224          *     CALL "ListUtilsSP:subscribeToGroup" ( $entry , $ldapContext "cn=staff, ou=system" );
225          *     CALL "ListUtilsSP:subscribeToGroup" ( $entry , $ldapContext "cn=teachers, ou=system" );
226          * 
227          */
228 
229         // Create a test entry which is selected by the Trigger Subentry.
230         String testEntry  = 
231             "version: 1\n" +
232             "\n" +
233             "dn: cn=The Teacher of All Times, ou=system\n"+
234             "objectClass: top\n" +
235             "objectClass: inetOrgPerson\n" +
236             "cn: The Teacher of All Times\n" +
237             "sn: TheTeacher";
238 
239         // Inject the entry into the server
240         injectEntries( service, testEntry );
241 
242         // ------------------------------------------
243         // The trigger should be fired at this point.
244         // ------------------------------------------
245         
246         // Check if the Trigger really worked (subscribed the user to the groups).
247         Attributes staff = sysRoot.getAttributes( "cn=staff" );
248         Attributes teachers = sysRoot.getAttributes( "cn=teachers" );
249         String testEntryName = ( ( LdapContext )sysRoot.lookup( "cn=The Teacher of All Times" ) ).getNameInNamespace();
250         assertTrue( AttributeUtils.containsValueCaseIgnore( staff.get( "uniqueMember" ), testEntryName ) );
251         assertTrue( AttributeUtils.containsValueCaseIgnore( teachers.get( "uniqueMember" ), testEntryName ) );
252     }
253  
254 }