KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > directory > ldapstudio > dsmlv2 > engine > Dsmlv2Engine


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.ldapstudio.dsmlv2.engine;
22
23
24 import java.io.FileNotFoundException JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.InputStream JavaDoc;
27 import java.net.InetSocketAddress JavaDoc;
28 import java.net.SocketAddress JavaDoc;
29 import java.net.UnknownHostException JavaDoc;
30 import java.nio.ByteBuffer JavaDoc;
31 import java.nio.channels.SocketChannel JavaDoc;
32
33 import javax.naming.NamingException JavaDoc;
34
35 import org.apache.directory.ldapstudio.dsmlv2.Dsmlv2Parser;
36 import org.apache.directory.ldapstudio.dsmlv2.reponse.AddResponseDsml;
37 import org.apache.directory.ldapstudio.dsmlv2.reponse.AuthResponseDsml;
38 import org.apache.directory.ldapstudio.dsmlv2.reponse.BatchResponseDsml;
39 import org.apache.directory.ldapstudio.dsmlv2.reponse.CompareResponseDsml;
40 import org.apache.directory.ldapstudio.dsmlv2.reponse.DelResponseDsml;
41 import org.apache.directory.ldapstudio.dsmlv2.reponse.ErrorResponse;
42 import org.apache.directory.ldapstudio.dsmlv2.reponse.ExtendedResponseDsml;
43 import org.apache.directory.ldapstudio.dsmlv2.reponse.ModDNResponseDsml;
44 import org.apache.directory.ldapstudio.dsmlv2.reponse.ModifyResponseDsml;
45 import org.apache.directory.ldapstudio.dsmlv2.reponse.SearchResponseDsml;
46 import org.apache.directory.ldapstudio.dsmlv2.reponse.SearchResultDoneDsml;
47 import org.apache.directory.ldapstudio.dsmlv2.reponse.SearchResultEntryDsml;
48 import org.apache.directory.ldapstudio.dsmlv2.reponse.SearchResultReferenceDsml;
49 import org.apache.directory.ldapstudio.dsmlv2.reponse.ErrorResponse.ErrorResponseType;
50 import org.apache.directory.ldapstudio.dsmlv2.request.BatchRequest;
51 import org.apache.directory.ldapstudio.dsmlv2.request.BatchRequest.OnError;
52 import org.apache.directory.ldapstudio.dsmlv2.request.BatchRequest.Processing;
53 import org.apache.directory.ldapstudio.dsmlv2.request.BatchRequest.ResponseOrder;
54 import org.apache.directory.shared.asn1.ber.Asn1Decoder;
55 import org.apache.directory.shared.asn1.ber.IAsn1Container;
56 import org.apache.directory.shared.asn1.ber.tlv.TLVStateEnum;
57 import org.apache.directory.shared.asn1.codec.DecoderException;
58 import org.apache.directory.shared.asn1.codec.EncoderException;
59 import org.apache.directory.shared.ldap.codec.Control;
60 import org.apache.directory.shared.ldap.codec.LdapConstants;
61 import org.apache.directory.shared.ldap.codec.LdapDecoder;
62 import org.apache.directory.shared.ldap.codec.LdapMessage;
63 import org.apache.directory.shared.ldap.codec.LdapMessageContainer;
64 import org.apache.directory.shared.ldap.codec.LdapResponse;
65 import org.apache.directory.shared.ldap.codec.add.AddResponse;
66 import org.apache.directory.shared.ldap.codec.bind.BindRequest;
67 import org.apache.directory.shared.ldap.codec.bind.BindResponse;
68 import org.apache.directory.shared.ldap.codec.bind.LdapAuthentication;
69 import org.apache.directory.shared.ldap.codec.bind.SimpleAuthentication;
70 import org.apache.directory.shared.ldap.codec.compare.CompareResponse;
71 import org.apache.directory.shared.ldap.codec.del.DelResponse;
72 import org.apache.directory.shared.ldap.codec.extended.ExtendedResponse;
73 import org.apache.directory.shared.ldap.codec.modify.ModifyResponse;
74 import org.apache.directory.shared.ldap.codec.modifyDn.ModifyDNResponse;
75 import org.apache.directory.shared.ldap.codec.search.SearchResultDone;
76 import org.apache.directory.shared.ldap.codec.search.SearchResultEntry;
77 import org.apache.directory.shared.ldap.codec.search.SearchResultReference;
78 import org.apache.directory.shared.ldap.message.ResultCodeEnum;
79 import org.apache.directory.shared.ldap.name.LdapDN;
80 import org.apache.directory.shared.ldap.util.StringTools;
81 import org.xmlpull.v1.XmlPullParserException;
82
83
84 /**
85  * This is the DSMLv2Engine. It can be use to execute operations on a LDAP Server and get the results of these operations.
86  * The format used for request and responses is the DSMLv2 format.
87  *
88  * @author <a HREF="mailto:dev@directory.apache.org">Apache Directory Project</a>
89  * @version $Rev$, $Date$
90  */

91 public class Dsmlv2Engine
92 {
93     /** Socket used to connect to the server */
94     private SocketChannel JavaDoc channel;
95     private SocketAddress JavaDoc serverAddress;
96
97     // server configuration
98
private int port;
99     private String JavaDoc host;
100     private String JavaDoc user;
101     private String JavaDoc password;
102
103     private Asn1Decoder ldapDecoder = new LdapDecoder();
104
105     private IAsn1Container ldapMessageContainer = new LdapMessageContainer();
106
107     private Dsmlv2Parser parser;
108
109     private boolean continueOnError;
110     private boolean exit = false;
111
112     private int bbLimit;
113
114     private int bbposition;
115     private BatchRequest batchRequest;
116     private BatchResponseDsml batchResponse;
117
118
119     /**
120      * Creates a new instance of Dsmlv2Engine.
121      *
122      * @param host
123      * the server host
124      * @param port
125      * the server port
126      * @param user
127      * the server admin DN
128      * @param password
129      * the server admin's password
130      */

131     public Dsmlv2Engine( String JavaDoc host, int port, String JavaDoc user, String JavaDoc password )
132     {
133         this.host = host;
134         this.port = port;
135         this.user = user;
136         this.password = password;
137     }
138
139
140     /**
141      * Processes the file given and return the result of the operations
142      *
143      * @param dsmlInput
144      * the DSMLv2 formatted request input
145      * @return
146      * the XML response in DSMLv2 Format
147      * @throws XmlPullParserException
148      * if an error occurs in the parser
149      */

150     public String JavaDoc processDSML( String JavaDoc dsmlInput ) throws XmlPullParserException
151     {
152         parser = new Dsmlv2Parser();
153         parser.setInput( dsmlInput );
154         return processDSML();
155     }
156
157
158     /**
159      * Processes the file given and return the result of the operations
160      *
161      * @param fileName
162      * the path to the file
163      * @return
164      * the XML response in DSMLv2 Format
165      * @throws XmlPullParserException
166      * if an error occurs in the parser
167      * @throws FileNotFoundException
168      * if the file does not exist
169      */

170     public String JavaDoc processDSMLFile( String JavaDoc fileName ) throws XmlPullParserException, FileNotFoundException JavaDoc
171     {
172         parser = new Dsmlv2Parser();
173         parser.setInputFile( fileName );
174         return processDSML();
175     }
176
177
178     /**
179      * Processes the file given and return the result of the operations
180      *
181      * @param inputStream
182      * contains a raw byte input stream of possibly unknown encoding (when inputEncoding is null).
183      * @param inputEncoding
184      * if not null it MUST be used as encoding for inputStream
185      * @return
186      * the XML response in DSMLv2 Format
187      * @throws XmlPullParserException
188      * if an error occurs in the parser
189      */

190     public String JavaDoc processDSML( InputStream JavaDoc inputStream, String JavaDoc inputEncoding ) throws XmlPullParserException
191     {
192         parser = new Dsmlv2Parser();
193         parser.setInput( inputStream, inputEncoding );
194         return processDSML();
195     }
196
197
198     /**
199      * Processes the Request document
200      *
201      * @return
202      * the XML response in DSMLv2 Format
203      */

204     private String JavaDoc processDSML()
205     {
206         batchResponse = new BatchResponseDsml();
207
208         // Binding to LDAP Server
209
try
210         {
211             bind( 1 );
212         }
213         catch ( Exception JavaDoc e )
214         {
215             // Unable to connect to server
216
// We create a new ErrorResponse and return the XML response.
217
ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.COULD_NOT_CONNECT, e.getMessage() );
218             batchResponse.addResponse( errorResponse );
219             return batchResponse.toDsml();
220         }
221
222         // Processing BatchRequest:
223
// - Parsing and Getting BatchRequest
224
// - Getting and registering options from BatchRequest
225
try
226         {
227             processBatchRequest();
228         }
229         catch ( XmlPullParserException e )
230         {
231             // We create a new ErrorResponse and return the XML response.
232
ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, e.getMessage()
233                 + " - Line " + e.getLineNumber() + " - Column " + e.getColumnNumber() );
234             batchResponse.addResponse( errorResponse );
235             return batchResponse.toDsml();
236         }
237
238         // Processing each request:
239
// - Getting a new request
240
// - Checking if the request is well formed
241
// - Sending the request to the server
242
// - Getting and converting reponse(s) as XML
243
// - Looping until last request
244
LdapMessage request = null;
245         try
246         {
247             request = parser.getNextRequest();
248         }
249         catch ( XmlPullParserException e )
250         {
251             // We create a new ErrorResponse and return the XML response.
252
ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, e.getMessage()
253                 + " - Line " + e.getLineNumber() + " - Column " + e.getColumnNumber() );
254             batchResponse.addResponse( errorResponse );
255             return batchResponse.toDsml();
256         }
257
258         while ( request != null ) // (Request == null when there's no more request to process)
259
{
260             // Checking the request has a requestID attribute if Processing = Parallel and ResponseOrder = Unordered
261
if ( ( batchRequest.getProcessing().equals( Processing.PARALLEL ) )
262                 && ( batchRequest.getResponseOrder().equals( ResponseOrder.UNORDERED ) )
263                 && ( request.getMessageId() == 0 ) )
264             {
265                 // Then we have to send an errorResponse
266
ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST,
267                     "A requestID must be specified to each request when Processing is Parallel and ReponseOrder is Unordered." );
268                 batchResponse.addResponse( errorResponse );
269                 return batchResponse.toDsml();
270             }
271
272             try
273             {
274                 processRequest( request );
275             }
276             catch ( Exception JavaDoc e )
277             {
278                 // We create a new ErrorResponse and return the XML response.
279
ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.GATEWAY_INTERNAL_ERROR,
280                     "Internal Error: " + e.getMessage() );
281                 batchResponse.addResponse( errorResponse );
282                 return batchResponse.toDsml();
283             }
284
285             // Checking if we need to exit processing (if an error has ocurred if onError == Exit)
286
if ( exit )
287             {
288                 break;
289             }
290
291             // Getting next request
292
try
293             {
294                 request = parser.getNextRequest();
295             }
296             catch ( XmlPullParserException e )
297             {
298                 // We create a new ErrorResponse and return the XML response.
299
ErrorResponse errorResponse = new ErrorResponse( 0, ErrorResponseType.MALFORMED_REQUEST, e.getMessage()
300                     + " - Line " + e.getLineNumber() + " - Column " + e.getColumnNumber() );
301                 batchResponse.addResponse( errorResponse );
302                 return batchResponse.toDsml();
303             }
304         }
305
306         return batchResponse.toDsml();
307     }
308
309
310     /**
311      * Processes a single request
312      *
313      * @param request
314      * the request to process
315      * @throws EncoderException
316      * @throws IOException
317      * @throws NamingException
318      * @throws DecoderException
319      */

320     private void processRequest( LdapMessage request ) throws EncoderException, IOException JavaDoc, DecoderException,
321         NamingException JavaDoc
322     {
323         LdapMessage message = new LdapMessage();
324
325         message.setProtocolOP( request );
326
327         message.setMessageId( request.getMessageId() );
328
329         ByteBuffer JavaDoc bb = null;
330
331         bb = message.encode( null );
332
333         bb.flip();
334
335         sendMessage( bb );
336
337         bb.clear();
338         bb.position( bb.capacity() );
339         // Get the response
340
LdapMessage response = null;
341
342         response = readResponse( bb );
343
344         if ( LdapConstants.ADD_RESPONSE == response.getMessageType() )
345         {
346             AddResponse addResponse = response.getAddResponse();
347             copyMessageIdAndControls( response, addResponse );
348
349             AddResponseDsml addResponseDsml = new AddResponseDsml( addResponse );
350             batchResponse.addResponse( addResponseDsml );
351         }
352         else if ( LdapConstants.BIND_RESPONSE == response.getMessageType() )
353         {
354             BindResponse bindResponse = response.getBindResponse();
355             copyMessageIdAndControls( response, bindResponse );
356
357             AuthResponseDsml authResponseDsml = new AuthResponseDsml( bindResponse );
358             batchResponse.addResponse( authResponseDsml );
359         }
360         else if ( LdapConstants.COMPARE_RESPONSE == response.getMessageType() )
361         {
362             CompareResponse compareResponse = response.getCompareResponse();
363             copyMessageIdAndControls( response, compareResponse );
364
365             CompareResponseDsml authResponseDsml = new CompareResponseDsml( compareResponse );
366             batchResponse.addResponse( authResponseDsml );
367         }
368         else if ( LdapConstants.DEL_RESPONSE == response.getMessageType() )
369         {
370             DelResponse delResponse = response.getDelResponse();
371             copyMessageIdAndControls( response, delResponse );
372
373             DelResponseDsml delResponseDsml = new DelResponseDsml( delResponse );
374             batchResponse.addResponse( delResponseDsml );
375         }
376         else if ( LdapConstants.MODIFY_RESPONSE == response.getMessageType() )
377         {
378             ModifyResponse modifyResponse = response.getModifyResponse();
379             copyMessageIdAndControls( response, modifyResponse );
380
381             ModifyResponseDsml modifyResponseDsml = new ModifyResponseDsml( modifyResponse );
382             batchResponse.addResponse( modifyResponseDsml );
383         }
384         else if ( LdapConstants.MODIFYDN_RESPONSE == response.getMessageType() )
385         {
386             ModifyDNResponse modifyDNResponse = response.getModifyDNResponse();
387             copyMessageIdAndControls( response, modifyDNResponse );
388
389             ModDNResponseDsml modDNResponseDsml = new ModDNResponseDsml( modifyDNResponse );
390             batchResponse.addResponse( modDNResponseDsml );
391         }
392         else if ( LdapConstants.EXTENDED_RESPONSE == response.getMessageType() )
393         {
394             ExtendedResponse extendedResponse = response.getExtendedResponse();
395             copyMessageIdAndControls( response, extendedResponse );
396
397             ExtendedResponseDsml extendedResponseDsml = new ExtendedResponseDsml( extendedResponse );
398             batchResponse.addResponse( extendedResponseDsml );
399         }
400         else if ( ( LdapConstants.SEARCH_RESULT_ENTRY == response.getMessageType() )
401             || ( LdapConstants.SEARCH_RESULT_REFERENCE == response.getMessageType() )
402             || ( LdapConstants.SEARCH_RESULT_DONE == response.getMessageType() ) )
403         {
404             // A SearchResponse can contains multiple responses of 3 types:
405
// - 0 to n SearchResultEntry
406
// - O to n SearchResultReference
407
// - 1 (only) SearchResultDone
408
// So we have to include those individual reponses in a "General" SearchResponse
409
// Element searchResponse = xmlResponse.getRootElement().addElement( "searchResponse" );
410
SearchResponseDsml searchResponseDsml = new SearchResponseDsml();
411
412             // RequestID
413
int requestID = response.getMessageId();
414             if ( requestID != 0 )
415             {
416                 searchResponseDsml.setMessageId( requestID );
417             }
418
419             while ( LdapConstants.SEARCH_RESULT_DONE != response.getMessageType() )
420             {
421                 if ( LdapConstants.SEARCH_RESULT_ENTRY == response.getMessageType() )
422                 {
423                     SearchResultEntry sre = response.getSearchResultEntry();
424                     copyMessageIdAndControls( response, sre );
425
426                     SearchResultEntryDsml searchResultEntryDsml = new SearchResultEntryDsml( sre );
427                     searchResponseDsml.addResponse( searchResultEntryDsml );
428                 }
429                 else if ( LdapConstants.SEARCH_RESULT_REFERENCE == response.getMessageType() )
430                 {
431                     SearchResultReference srr = response.getSearchResultReference();
432                     copyMessageIdAndControls( response, srr );
433
434                     SearchResultReferenceDsml searchResultReferenceDsml = new SearchResultReferenceDsml( srr );
435                     searchResponseDsml.addResponse( searchResultReferenceDsml );
436                 }
437
438                 response = readResponse( bb );
439             }
440
441             SearchResultDone srd = response.getSearchResultDone();
442             copyMessageIdAndControls( response, srd );
443
444             SearchResultDoneDsml searchResultDoneDsml = new SearchResultDoneDsml( response );
445             searchResponseDsml.addResponse( searchResultDoneDsml );
446         }
447
448         LdapResponse realResponse = response.getLdapResponse();
449
450         if ( !continueOnError )
451         {
452             if ( ( realResponse.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
453                 && ( realResponse.getLdapResult().getResultCode() != ResultCodeEnum.COMPARE_TRUE )
454                 && ( realResponse.getLdapResult().getResultCode() != ResultCodeEnum.COMPARE_FALSE )
455                 && ( realResponse.getLdapResult().getResultCode() != ResultCodeEnum.REFERRAL ) )
456             {
457                 // Turning on Exit flag
458
exit = true;
459             }
460         }
461
462     }
463
464
465     private void copyMessageIdAndControls( LdapMessage from, LdapMessage to )
466     {
467         to.setMessageId( from.getMessageId() );
468         for ( Control control : from.getControls() )
469         {
470             to.addControl( control );
471         }
472     }
473
474
475     /**
476      * Processes the BatchRequest
477      * <ul>
478      * <li>Parsing and Getting BatchRequest</li>
479      * <li>Getting and registering options from BatchRequest</li>
480      * </ul>
481      *
482      * @throws XmlPullParserException
483      * if an error occurs in the parser
484      */

485     private void processBatchRequest() throws XmlPullParserException
486     {
487         // Parsing BatchRequest
488
parser.parseBatchRequest();
489
490         // Getting BatchRequest
491
batchRequest = parser.getBatchRequest();
492
493         if ( OnError.RESUME.equals( batchRequest.getOnError() ) )
494         {
495             continueOnError = true;
496         }
497         else if ( OnError.EXIT.equals( batchRequest.getOnError() ) )
498         {
499             continueOnError = false;
500         }
501
502         if ( batchRequest.getRequestID() != 0 )
503         {
504             batchResponse.setRequestID( batchRequest.getRequestID() );
505         }
506     }
507
508
509     /**
510      * Connect to the LDAP server through a socket and establish the Input and
511      * Output Streams. All the required information for the connection should be
512      * in the options from the command line, or the default values.
513      *
514      * @throws UnknownHostException
515      * if the hostname or the Address of server could not be found
516      * @throws IOException
517      * if there was a error opening or establishing the socket
518      */

519     private void connect() throws UnknownHostException JavaDoc, IOException JavaDoc
520     {
521         serverAddress = new InetSocketAddress JavaDoc( host, port );
522         channel = SocketChannel.open( serverAddress );
523         channel.configureBlocking( true );
524     }
525
526
527     /**
528      * Sends a message
529      *
530      * @param bb
531      * the message as a byte buffer
532      * @throws IOException
533      * if the message could not be sent
534      */

535     private void sendMessage( ByteBuffer JavaDoc bb ) throws IOException JavaDoc
536     {
537         channel.write( bb );
538         bb.clear();
539     }
540
541
542     /**
543      * Reads the response to a request
544      *
545      * @param bb
546      * the response as a byte buffer
547      * @return the response
548      * the response as a LDAP message
549      * @throws IOException
550      * @throws DecoderException
551      * @throws NamingException
552      */

553     private LdapMessage readResponse( ByteBuffer JavaDoc bb ) throws IOException JavaDoc, DecoderException, NamingException JavaDoc
554     {
555
556         LdapMessage messageResp = null;
557
558         if ( bb.hasRemaining() )
559         {
560             bb.position( bbposition );
561             bb.limit( bbLimit );
562             ldapDecoder.decode( bb, ldapMessageContainer );
563             bbposition = bb.position();
564             bbLimit = bb.limit();
565         }
566         bb.flip();
567         while ( ldapMessageContainer.getState() != TLVStateEnum.PDU_DECODED )
568         {
569
570             int nbRead = channel.read( bb );
571
572             if ( nbRead == -1 )
573             {
574                 System.err.println( "fsdfsdfsdfsd" );
575             }
576
577             bb.flip();
578             ldapDecoder.decode( bb, ldapMessageContainer );
579             bbposition = bb.position();
580             bbLimit = bb.limit();
581             bb.flip();
582         }
583
584         messageResp = ( ( LdapMessageContainer ) ldapMessageContainer ).getLdapMessage();
585
586         if ( messageResp instanceof BindResponse )
587         {
588             BindResponse resp = ( ( LdapMessageContainer ) ldapMessageContainer ).getLdapMessage().getBindResponse();
589
590             if ( resp.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
591             {
592                 System.err.println( "Error : " + resp.getLdapResult().getErrorMessage() );
593             }
594         }
595         else if ( messageResp instanceof ExtendedResponse )
596         {
597             ExtendedResponse resp = ( ( LdapMessageContainer ) ldapMessageContainer ).getLdapMessage()
598                 .getExtendedResponse();
599
600             if ( resp.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
601             {
602                 System.err.println( "Error : " + resp.getLdapResult().getErrorMessage() );
603             }
604         }
605
606         ( ( LdapMessageContainer ) ldapMessageContainer ).clean();
607
608         return messageResp;
609     }
610
611
612     /**
613      * Binds to the ldap server
614      *
615      * @param messageId
616      * the message Id
617      * @throws EncoderException
618      * @throws DecoderException
619      * @throws IOException
620      * @throws NamingException
621      */

622     private void bind( int messageId ) throws EncoderException, DecoderException, IOException JavaDoc, NamingException JavaDoc
623     {
624         BindRequest bindRequest = new BindRequest();
625         LdapMessage message = new LdapMessage();
626         LdapAuthentication authentication = new SimpleAuthentication();
627         ( ( SimpleAuthentication ) authentication ).setSimple( StringTools.getBytesUtf8( password ) );
628
629         bindRequest.setAuthentication( authentication );
630         bindRequest.setName( new LdapDN( user ) );
631         bindRequest.setVersion( 3 );
632
633         message.setProtocolOP( bindRequest );
634         message.setMessageId( messageId );
635
636         // Encode and send the bind request
637
ByteBuffer JavaDoc bb = message.encode( null );
638         bb.flip();
639
640         connect();
641         sendMessage( bb );
642
643         bb.clear();
644
645         bb.position( bb.limit() );
646
647         readResponse( bb );
648     }
649 }
650
Popular Tags