KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > groovy > lang > Closure


1 /*
2  $Id: Closure.java,v 1.50 2005/06/12 17:31:09 dierk Exp $
3
4  Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5
6  Redistribution and use of this software and associated documentation
7  ("Software"), with or without modification, are permitted provided
8  that the following conditions are met:
9
10  1. Redistributions of source code must retain copyright
11     statements and notices. Redistributions must also contain a
12     copy of this document.
13
14  2. Redistributions in binary form must reproduce the
15     above copyright notice, this list of conditions and the
16     following disclaimer in the documentation and/or other
17     materials provided with the distribution.
18
19  3. The name "groovy" must not be used to endorse or promote
20     products derived from this Software without prior written
21     permission of The Codehaus. For written permission,
22     please contact info@codehaus.org.
23
24  4. Products derived from this Software may not be called "groovy"
25     nor may "groovy" appear in their names without prior written
26     permission of The Codehaus. "groovy" is a registered
27     trademark of The Codehaus.
28
29  5. Due credit should be given to The Codehaus -
30     http://groovy.codehaus.org/
31
32  THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
36  THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43  OF THE POSSIBILITY OF SUCH DAMAGE.
44
45  */

46 package groovy.lang;
47
48 import org.codehaus.groovy.runtime.InvokerHelper;
49 import org.codehaus.groovy.runtime.InvokerInvocationException;
50
51 import java.util.*;
52 import java.io.IOException JavaDoc;
53 import java.io.StringWriter JavaDoc;
54 import java.io.Writer JavaDoc;
55 import java.lang.reflect.InvocationTargetException JavaDoc;
56 import java.lang.reflect.Method JavaDoc;
57 import java.security.AccessController JavaDoc;
58 import java.security.PrivilegedAction JavaDoc;
59
60 /**
61  * Represents any closure object in Groovy.
62  *
63  * @author <a HREF="mailto:james@coredevelopers.net">James Strachan</a>
64  * @author <a HREF="mailto:tug@wilson.co.uk">John Wilson</a>
65  * @version $Revision: 1.50 $
66  */

67 public abstract class Closure extends GroovyObjectSupport implements Cloneable JavaDoc, Runnable JavaDoc {
68
69     private static final Object JavaDoc noParameters[] = new Object JavaDoc[]{null};
70     private static final Object JavaDoc emptyArray[] = new Object JavaDoc[0];
71     private static final Object JavaDoc emptyArrayParameter[] = new Object JavaDoc[]{emptyArray};
72
73     private Object JavaDoc delegate;
74     private final Object JavaDoc owner;
75     private final Method JavaDoc doCallMethod;
76     private final HashMap callsMap;
77     private final boolean supportsVarargs;
78     private final Class JavaDoc[] parameterTypes;
79     private final int numberOfParameters;
80     private Object JavaDoc curriedParams[] = emptyArray;
81
82
83     private int directive = 0;
84     public static int DONE = 1;
85     public static int SKIP = 2;
86
87     public Closure(Object JavaDoc delegate) {
88         this.delegate = delegate;
89         this.owner = delegate;
90
91         Class JavaDoc closureClass = this.getClass();
92         callsMap = new HashMap();
93         int paramLenTemp = -1;
94         Method JavaDoc doCallTemp = null;
95
96         while (true) {
97             final Method JavaDoc methods[] = closureClass.getDeclaredMethods();
98
99             int i = 0;
100
101             for (int j = 0; j < methods.length; j++) {
102                  if ("doCall".equals(methods[j].getName())) {
103                      callsMap.put(new Integer JavaDoc(methods[j].getParameterTypes().length), methods[j]);
104                      if (methods[j].getParameterTypes().length > paramLenTemp) {
105                          doCallTemp = methods[j];
106                          paramLenTemp = methods[j].getParameterTypes().length;
107                      }
108                  }
109             }
110
111             if (!callsMap.isEmpty()) {
112                 break;
113             }
114
115             closureClass = closureClass.getSuperclass();
116         }
117
118         this.doCallMethod = doCallTemp;
119
120         AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
121             public Object JavaDoc run() {
122                 for (Iterator iter = callsMap.values().iterator(); iter.hasNext(); ) {
123                    ((Method JavaDoc) iter.next()).setAccessible(true);
124                 }
125                 return null;
126             }
127         });
128
129         this.parameterTypes = this.doCallMethod.getParameterTypes();
130         this.numberOfParameters = this.parameterTypes.length;
131
132         if (this.numberOfParameters > 0) {
133             this.supportsVarargs = this.parameterTypes[this.numberOfParameters - 1].equals(Object JavaDoc[].class);
134         } else {
135             this.supportsVarargs = false;
136         }
137     }
138
139     public Object JavaDoc invokeMethod(String JavaDoc method, Object JavaDoc arguments) {
140         if ("doCall".equals(method) || "call".equals(method)) {
141             if (arguments instanceof Object JavaDoc[]) {
142                 Object JavaDoc[] objs = (Object JavaDoc[]) arguments;
143                 if ((objs != null) && (objs.length > 1) && (objs[0] instanceof Object JavaDoc[])) {
144                    boolean allNull = true;
145                    for (int j = 1; j < objs.length; j++) {
146                        if (objs[j] != null) {
147                            allNull = false;
148                            break;
149                        }
150                    }
151                    if (allNull)
152                        return callViaReflection((Object JavaDoc[]) (objs[0]));
153                 }
154             }
155             return callSpecial(arguments);
156         } else if ("curry".equals(method)) {
157             return curry((Object JavaDoc[]) arguments);
158         } else {
159             try {
160                 return getMetaClass().invokeMethod(this, method, arguments);
161             } catch (MissingMethodException e) {
162                 if (owner != this) {
163                     try {
164                         // lets try invoke method on the owner
165
return InvokerHelper.invokeMethod(this.owner, method, arguments);
166                     } catch (InvokerInvocationException iie) {
167                         throw iie;
168                     } catch (GroovyRuntimeException e1) {
169                         if (this.delegate != null && this.delegate != this && this.delegate != this.owner) {
170                             // lets try invoke method on the delegate
171
try {
172                                 return InvokerHelper.invokeMethod(this.delegate, method, arguments);
173                             } catch (MissingMethodException mme) {
174                                 throw new InvokerInvocationException(mme);
175                             } catch (GroovyRuntimeException gre) {
176                                 throw new InvokerInvocationException(gre.getCause());
177                             }
178                         }
179                     }
180                 }
181                 throw e;
182             }
183         }
184
185     }
186
187     public Object JavaDoc getProperty(String JavaDoc property) {
188         if ("delegate".equals(property)) {
189             return getDelegate();
190         } else if ("owner".equals(property)) {
191             return getOwner();
192         } else if ("method".equals(property)) {
193             return getMethod();
194         } else if ("parameterTypes".equals(property)) {
195             return getParameterTypes();
196         } else if ("metaClass".equals(property)) {
197             return getMetaClass();
198         } else if ("class".equals(property)) {
199             return getClass();
200         } else {
201             try {
202 // lets try getting the property on the owner
203
return InvokerHelper.getProperty(this.owner, property);
204             } catch (GroovyRuntimeException e1) {
205                 if (this.delegate != null && this.delegate != this && this.delegate != this.owner) {
206                     try {
207 // lets try getting the property on the delegate
208
return InvokerHelper.getProperty(this.delegate, property);
209                     } catch (GroovyRuntimeException e2) {
210 // ignore, we'll throw e1
211
}
212                 }
213
214                 throw e1;
215             }
216         }
217     }
218
219     public void setProperty(String JavaDoc property, Object JavaDoc newValue) {
220         if ("delegate".equals(property)) {
221             setDelegate(newValue);
222         } else if ("metaClass".equals(property)) {
223             setMetaClass((MetaClass) newValue);
224         } else {
225             try {
226 // lets try setting the property on the owner
227
InvokerHelper.setProperty(this.owner, property, newValue);
228                 return;
229             } catch (GroovyRuntimeException e1) {
230                 if (this.delegate != null && this.delegate != this && this.delegate != this.owner) {
231                     try {
232 // lets try setting the property on the delegate
233
InvokerHelper.setProperty(this.delegate, property, newValue);
234                         return;
235                     } catch (GroovyRuntimeException e2) {
236 // ignore, we'll throw e1
237
}
238                 }
239
240                 throw e1;
241             }
242         }
243     }
244
245     public boolean isCase(Object JavaDoc candidate){
246         return InvokerHelper.asBool(call(candidate));
247     }
248
249     /**
250      * Invokes the closure without any parameters, returning any value if applicable.
251      *
252      * @return the value if applicable or null if there is no return statement in the closure
253      */

254     public Object JavaDoc call() {
255         return call(emptyArray);
256     }
257     
258     /**
259      * Invokes the closure, returning any value if applicable.
260      *
261      * @param arguments could be a single value or a List of values
262      * @return the value if applicable or null if there is no return statement in the closure
263      */

264     public Object JavaDoc call(final Object JavaDoc arguments) {
265         final Object JavaDoc params[];
266
267         if (this.curriedParams.length != 0) {
268             final Object JavaDoc args[];
269
270             if (arguments instanceof Object JavaDoc[]) {
271                 args = (Object JavaDoc[]) arguments;
272             } else {
273                 args = new Object JavaDoc[]{arguments};
274             }
275
276             params = new Object JavaDoc[this.curriedParams.length + args.length];
277
278             System.arraycopy(this.curriedParams, 0, params, 0, this.curriedParams.length);
279             System.arraycopy(args, 0, params, this.curriedParams.length, args.length);
280         } else {
281             if (arguments instanceof Object JavaDoc[]) {
282                 params = (Object JavaDoc[]) arguments;
283             } else {
284                 return doCall(arguments);
285             }
286         }
287
288         final int lastParam = this.numberOfParameters - 1;
289
290         if (this.supportsVarargs && !(this.numberOfParameters == params.length && (params[lastParam] == null || params[lastParam].getClass() == Object JavaDoc[].class))) {
291             final Object JavaDoc actualParameters[] = new Object JavaDoc[this.numberOfParameters];
292
293             //
294
// We have a closure which supports variable arguments and we haven't got actual
295
// parameters which have exactly the right number of parameters and ends with a null or an Object[]
296
//
297
if (params.length < lastParam) {
298                 //
299
// Not enough parameters throw exception
300
//
301
// Note we allow there to be one fewer actual parameter than the number of formal parameters
302
// in this case we pass an zero length Object[] as the last parameter
303
//
304
throw new IncorrectClosureArgumentsException(this, params, this.parameterTypes);
305             } else {
306                 final Object JavaDoc rest[] = new Object JavaDoc[params.length - lastParam]; // array used to pass the rest of the paraters
307

308                 // fill the parameter array up to but not including the last one
309
System.arraycopy(params, 0, actualParameters, 0, lastParam);
310
311                 // put the rest of the parameters in the overflow araay
312
System.arraycopy(params, lastParam, rest, 0, rest.length);
313
314                 // pass the overflow array as the last parameter
315
actualParameters[lastParam] = rest;
316
317                 return callViaReflection(actualParameters);
318             }
319         }
320
321         if (params.length == 0) {
322             return doCall();
323         } else if (params.length == 1) {
324             return doCall(params[0]);
325         } else if (params.length == 2) {
326             return doCall(params[0], params[1]);
327         } else {
328             return callViaReflection(params);
329         }
330     }
331
332     public Object JavaDoc callSpecial(final Object JavaDoc arguments) {
333         final Object JavaDoc params[];
334
335         if (this.curriedParams.length > 0) {
336             final Object JavaDoc args[];
337
338             if (arguments instanceof Object JavaDoc[]) {
339                 args = (Object JavaDoc[]) arguments;
340             } else {
341                 args = new Object JavaDoc[]{arguments};
342             }
343
344             params = new Object JavaDoc[this.curriedParams.length + args.length];
345
346             System.arraycopy(this.curriedParams, 0, params, 0, this.curriedParams.length);
347             System.arraycopy(args, 0, params, this.curriedParams.length, args.length);
348         } else {
349             Object JavaDoc[] tmpParams = null;
350             if (arguments instanceof Object JavaDoc[]) {
351                 tmpParams = (Object JavaDoc[]) arguments;
352
353                 if ((tmpParams != null) && (tmpParams.length > 1)) {
354                     boolean allNull = true;
355                     for (int j = 1; j < tmpParams.length; j++) {
356                         if (tmpParams[j] != null) {
357                             allNull = false;
358                             break;
359                         }
360                     }
361                     if (allNull) {
362                         if (tmpParams[0] instanceof Object JavaDoc[])
363                             tmpParams = (Object JavaDoc[]) (tmpParams[0]);
364                         else
365                             throw new IncorrectClosureArgumentsException(this, new Object JavaDoc[] { tmpParams[0] }, this.parameterTypes);
366                     }
367                 }
368                 params = tmpParams;
369
370             } else {
371                 return doCall(arguments);
372             }
373         }
374
375         final int lastParam = this.numberOfParameters - 1;
376
377         if (this.supportsVarargs && !(this.numberOfParameters == params.length && (params.length > lastParam) && (params[lastParam] == null || params[lastParam].getClass() == Object JavaDoc[].class))) {
378             final Object JavaDoc actualParameters[] = new Object JavaDoc[this.numberOfParameters];
379
380             //
381
// We have a closure which supports variable arguments and we haven't got actual
382
// parameters which have exactly the right number of parameters and ends with a null or an Object[]
383
//
384
if (params.length < lastParam) {
385                 //
386
// Not enough parameters throw exception
387
//
388
// Note we allow there to be one fewer actual parameter than the number of formal parameters
389
// in this case we pass an zero length Object[] as the last parameter
390
//
391
throw new IncorrectClosureArgumentsException(this, params, this.parameterTypes);
392             } else {
393                 final Object JavaDoc rest[] = new Object JavaDoc[params.length - lastParam]; // array used to pass the rest of the paraters
394

395                 // fill the parameter array up to but not including the last one
396
System.arraycopy(params, 0, actualParameters, 0, lastParam);
397
398                 // put the rest of the parameters in the overflow araay
399
System.arraycopy(params, lastParam, rest, 0, rest.length);
400
401                 // pass the overflow array as the last parameter
402
actualParameters[lastParam] = rest;
403
404                 return callViaReflection(actualParameters);
405             }
406         }
407
408         if (params.length == 0) {
409             return doCall();
410         } else if (params.length == 1) {
411             return doCall(params[0]);
412         } else if (params.length == 2) {
413             return doCall(params[0], params[1]);
414         } else {
415             return callViaReflection(params);
416         }
417     }
418
419     protected static Object JavaDoc throwRuntimeException(Throwable JavaDoc throwable) {
420         if (throwable instanceof RuntimeException JavaDoc) {
421             throw (RuntimeException JavaDoc) throwable;
422         } else {
423             throw new GroovyRuntimeException(throwable.getMessage(), throwable);
424         }
425     }
426
427     /**
428      * An attempt to optimise calling closures with one parameter
429      * If the closure has one untyped parameter then it will overload this function
430      * If not this will be called ans will use reflection to deal with the case of a
431      * single typed parameter
432      *
433      * @param p1
434      * @return the result of calling the closure
435      */

436     protected Object JavaDoc doCall(final Object JavaDoc p1) {
437         return callViaReflection(new Object JavaDoc[]{p1});
438     }
439     
440     /**
441      * An attempt to optimise calling closures with no parameter
442      * This method only calls doCall(Object) and will be called by call(Object)
443      * if the parameter given to call is an empty Object array
444      *
445      * @return the result of calling the closure
446      */

447     protected Object JavaDoc doCall() {
448         return doCall((Object JavaDoc)null);
449     }
450     
451
452     /**
453      * An attempt to optimise calling closures with two parameters
454      * If the closure has two untyped parameters then it will overload this function
455      * If not this will be called ans will use reflection to deal with the case of one
456      * or two typed parameters
457      *
458      * @param p1
459      * @return the result of calling the closure
460      */

461     protected Object JavaDoc doCall(final Object JavaDoc p1, final Object JavaDoc p2) {
462          return callViaReflection(new Object JavaDoc[]{p1, p2});
463     }
464
465     private Object JavaDoc callViaReflection(final Object JavaDoc params[]) {
466         try {
467             // invoke the closure
468
return ((Method JavaDoc) callsMap.get(new Integer JavaDoc(params.length))).invoke(this, params);
469         } catch (final IllegalArgumentException JavaDoc e) {
470             throw new IncorrectClosureArgumentsException(this, params, this.parameterTypes);
471         } catch (final IllegalAccessException JavaDoc e) {
472             final Throwable JavaDoc cause = e.getCause();
473
474             return throwRuntimeException((cause == null) ? e : cause);
475         } catch (final InvocationTargetException JavaDoc e) {
476             final Throwable JavaDoc cause = e.getCause();
477
478             return throwRuntimeException((cause == null) ? e : cause);
479         }
480     }
481
482     /**
483      * Used when a closure wraps a method on a class
484      *
485      * @return empty string
486      */

487     public String JavaDoc getMethod() {
488         return "";
489     }
490
491     /**
492      * @return the owner Object to which method calls will go which is
493      * typically the outer class when the closure is constructed
494      */

495     public Object JavaDoc getOwner() {
496         return this.owner;
497     }
498
499     /**
500      * @return the delegate Object to which method calls will go which is
501      * typically the outer class when the closure is constructed
502      */

503     public Object JavaDoc getDelegate() {
504         return this.delegate;
505     }
506
507     /**
508      * Allows the delegate to be changed such as when performing markup building
509      *
510      * @param delegate
511      */

512     public void setDelegate(Object JavaDoc delegate) {
513         this.delegate = delegate;
514     }
515
516     /**
517      * @return the parameter types of this closure
518      */

519     public Class JavaDoc[] getParameterTypes() {
520         return this.parameterTypes;
521     }
522
523     /**
524      * @return a version of this closure which implements Writable
525      */

526     public Closure asWritable() {
527         return new WritableClosure();
528     }
529
530     /* (non-Javadoc)
531      * @see java.lang.Runnable#run()
532      */

533     public void run() {
534         call();
535     }
536
537     /**
538      * Support for closure currying
539      *
540      * @param arguments
541      */

542     public Closure curry(final Object JavaDoc arguments[]) {
543         final Closure curriedClosure = (Closure) this.clone();
544         final Object JavaDoc newCurriedParams[] = new Object JavaDoc[curriedClosure.curriedParams.length + arguments.length];
545
546         System.arraycopy(curriedClosure.curriedParams, 0, newCurriedParams, 0, curriedClosure.curriedParams.length);
547         System.arraycopy(arguments, 0, newCurriedParams, curriedClosure.curriedParams.length, arguments.length);
548
549         curriedClosure.curriedParams = newCurriedParams;
550
551         return curriedClosure;
552     }
553
554     /* (non-Javadoc)
555      * @see java.lang.Object#clone()
556      */

557     public Object JavaDoc clone() {
558         try {
559             return super.clone();
560         } catch (final CloneNotSupportedException JavaDoc e) {
561             return null;
562         }
563     }
564
565     private class WritableClosure extends Closure implements Writable {
566         public WritableClosure() {
567             super(null);
568         }
569
570         /* (non-Javadoc)
571      * @see groovy.lang.Writable#writeTo(java.io.Writer)
572      */

573         public Writer JavaDoc writeTo(Writer JavaDoc out) throws IOException JavaDoc {
574             Closure.this.call(out);
575
576             return out;
577         }
578
579         /* (non-Javadoc)
580          * @see groovy.lang.GroovyObject#invokeMethod(java.lang.String, java.lang.Object)
581          */

582         public Object JavaDoc invokeMethod(String JavaDoc method, Object JavaDoc arguments) {
583             if ("clone".equals(method)) {
584                 return clone();
585             } else if ("curry".equals(method)) {
586                 return curry((Object JavaDoc[]) arguments);
587             } else if ("asWritable".equals(method)) {
588                 return asWritable();
589             } else {
590                 return Closure.this.invokeMethod(method, arguments);
591             }
592         }
593
594         /* (non-Javadoc)
595          * @see groovy.lang.GroovyObject#getProperty(java.lang.String)
596          */

597         public Object JavaDoc getProperty(String JavaDoc property) {
598             return Closure.this.getProperty(property);
599         }
600
601         /* (non-Javadoc)
602          * @see groovy.lang.GroovyObject#setProperty(java.lang.String, java.lang.Object)
603          */

604         public void setProperty(String JavaDoc property, Object JavaDoc newValue) {
605             Closure.this.setProperty(property, newValue);
606         }
607
608         /* (non-Javadoc)
609          * @see groovy.lang.Closure#call()
610          */

611         public Object JavaDoc call() {
612             return Closure.this.call();
613         }
614
615         /* (non-Javadoc)
616          * @see groovy.lang.Closure#call(java.lang.Object)
617          */

618         public Object JavaDoc call(Object JavaDoc arguments) {
619             return Closure.this.call(arguments);
620         }
621
622         /* (non-Javadoc)
623          * @see groovy.lang.Closure#doCall(java.lang.Object)
624          */

625         protected Object JavaDoc doCall(Object JavaDoc p1) {
626             return Closure.this.doCall(p1);
627         }
628
629         /* (non-Javadoc)
630          * @see groovy.lang.Closure#doCall(java.lang.Object, java.lang.Object)
631          */

632         protected Object JavaDoc doCall(Object JavaDoc p1, Object JavaDoc p2) {
633             return Closure.this.doCall(p1, p2);
634         }
635
636         /* (non-Javadoc)
637          * @see groovy.lang.Closure#getDelegate()
638          */

639         public Object JavaDoc getDelegate() {
640             return Closure.this.getDelegate();
641         }
642
643         /* (non-Javadoc)
644          * @see groovy.lang.Closure#setDelegate(java.lang.Object)
645          */

646         public void setDelegate(Object JavaDoc delegate) {
647             Closure.this.setDelegate(delegate);
648         }
649
650         /* (non-Javadoc)
651          * @see groovy.lang.Closure#getParameterTypes()
652          */

653         public Class JavaDoc[] getParameterTypes() {
654             return Closure.this.getParameterTypes();
655         }
656
657         /* (non-Javadoc)
658          * @see groovy.lang.Closure#asWritable()
659          */

660         public Closure asWritable() {
661             return this;
662         }
663
664         /* (non-Javadoc)
665          * @see java.lang.Runnable#run()
666          */

667         public void run() {
668             Closure.this.run();
669         }
670
671         /* (non-Javadoc)
672          * @see groovy.lang.Closure#curry(java.lang.Object[])
673          */

674         public Closure curry(Object JavaDoc[] arguments) {
675             return Closure.this.curry(arguments).asWritable();
676         }
677
678         /* (non-Javadoc)
679          * @see java.lang.Object#clone()
680          */

681         public Object JavaDoc clone() {
682             return ((Closure) Closure.this.clone()).asWritable();
683         }
684
685         /* (non-Javadoc)
686          * @see java.lang.Object#hashCode()
687          */

688         public int hashCode() {
689             return Closure.this.hashCode();
690         }
691
692         /* (non-Javadoc)
693          * @see java.lang.Object#equals(java.lang.Object)
694          */

695         public boolean equals(Object JavaDoc arg0) {
696             return Closure.this.equals(arg0);
697         }
698
699         /* (non-Javadoc)
700          * @see java.lang.Object#toString()
701          */

702         public String JavaDoc toString() {
703             final StringWriter JavaDoc writer = new StringWriter JavaDoc();
704
705             try {
706                 writeTo(writer);
707             } catch (IOException JavaDoc e) {
708                 return null;
709             }
710
711             return writer.toString();
712         }
713     }
714
715     /**
716      * @return Returns the directive.
717      */

718     public int getDirective() {
719         return directive;
720     }
721
722     /**
723      * @param directive The directive to set.
724      */

725     public void setDirective(int directive) {
726         this.directive = directive;
727     }
728 }
729
Popular Tags