KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > core > ApplicationHttpRequest


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.core;
20
21
22 import java.io.IOException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.NoSuchElementException JavaDoc;
29
30 import javax.servlet.RequestDispatcher JavaDoc;
31 import javax.servlet.http.HttpServletRequest JavaDoc;
32 import javax.servlet.http.HttpServletRequestWrapper JavaDoc;
33 import javax.servlet.http.HttpSession JavaDoc;
34
35 import org.apache.catalina.Context;
36 import org.apache.catalina.Globals;
37 import org.apache.catalina.Session;
38 import org.apache.catalina.Manager;
39 import org.apache.catalina.util.Enumerator;
40 import org.apache.catalina.util.RequestUtil;
41 import org.apache.catalina.util.StringManager;
42
43
44 /**
45  * Wrapper around a <code>javax.servlet.http.HttpServletRequest</code>
46  * that transforms an application request object (which might be the original
47  * one passed to a servlet, or might be based on the 2.3
48  * <code>javax.servlet.http.HttpServletRequestWrapper</code> class)
49  * back into an internal <code>org.apache.catalina.HttpRequest</code>.
50  * <p>
51  * <strong>WARNING</strong>: Due to Java's lack of support for multiple
52  * inheritance, all of the logic in <code>ApplicationRequest</code> is
53  * duplicated in <code>ApplicationHttpRequest</code>. Make sure that you
54  * keep these two classes in synchronization when making changes!
55  *
56  * @author Craig R. McClanahan
57  * @author Remy Maucherat
58  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
59  */

60
61 class ApplicationHttpRequest extends HttpServletRequestWrapper JavaDoc {
62
63
64     // ------------------------------------------------------- Static Variables
65

66
67     /**
68      * The set of attribute names that are special for request dispatchers.
69      */

70     protected static final String JavaDoc specials[] =
71     { Globals.INCLUDE_REQUEST_URI_ATTR, Globals.INCLUDE_CONTEXT_PATH_ATTR,
72       Globals.INCLUDE_SERVLET_PATH_ATTR, Globals.INCLUDE_PATH_INFO_ATTR,
73       Globals.INCLUDE_QUERY_STRING_ATTR, Globals.FORWARD_REQUEST_URI_ATTR,
74       Globals.FORWARD_CONTEXT_PATH_ATTR, Globals.FORWARD_SERVLET_PATH_ATTR,
75       Globals.FORWARD_PATH_INFO_ATTR, Globals.FORWARD_QUERY_STRING_ATTR };
76
77
78     /**
79      * The string manager for this package.
80      */

81     protected static StringManager sm =
82         StringManager.getManager(Constants.Package);
83
84
85     // ----------------------------------------------------------- Constructors
86

87
88     /**
89      * Construct a new wrapped request around the specified servlet request.
90      *
91      * @param request The servlet request being wrapped
92      */

93     public ApplicationHttpRequest(HttpServletRequest JavaDoc request, Context context,
94                                   boolean crossContext) {
95
96         super(request);
97         this.context = context;
98         this.crossContext = crossContext;
99         setRequest(request);
100
101     }
102
103
104     // ----------------------------------------------------- Instance Variables
105

106
107     /**
108      * The context for this request.
109      */

110     protected Context context = null;
111
112
113     /**
114      * The context path for this request.
115      */

116     protected String JavaDoc contextPath = null;
117
118
119     /**
120      * If this request is cross context, since this changes session accesss
121      * behavior.
122      */

123     protected boolean crossContext = false;
124
125
126     /**
127      * The current dispatcher type.
128      */

129     protected Object JavaDoc dispatcherType = null;
130
131
132     /**
133      * Descriptive information about this implementation.
134      */

135     protected static final String JavaDoc info =
136         "org.apache.catalina.core.ApplicationHttpRequest/1.0";
137
138
139     /**
140      * The request parameters for this request. This is initialized from the
141      * wrapped request, but updates are allowed.
142      */

143     protected Map JavaDoc parameters = null;
144
145
146     /**
147      * Have the parameters for this request already been parsed?
148      */

149     private boolean parsedParams = false;
150
151
152     /**
153      * The path information for this request.
154      */

155     protected String JavaDoc pathInfo = null;
156
157
158     /**
159      * The query parameters for the current request.
160      */

161     private String JavaDoc queryParamString = null;
162
163
164     /**
165      * The query string for this request.
166      */

167     protected String JavaDoc queryString = null;
168
169
170     /**
171      * The current request dispatcher path.
172      */

173     protected Object JavaDoc requestDispatcherPath = null;
174
175
176     /**
177      * The request URI for this request.
178      */

179     protected String JavaDoc requestURI = null;
180
181
182     /**
183      * The servlet path for this request.
184      */

185     protected String JavaDoc servletPath = null;
186
187
188     /**
189      * The currently active session for this request.
190      */

191     protected Session JavaDoc session = null;
192
193
194     /**
195      * Special attributes.
196      */

197     protected Object JavaDoc[] specialAttributes = new Object JavaDoc[specials.length];
198
199
200     // ------------------------------------------------- ServletRequest Methods
201

202
203     /**
204      * Override the <code>getAttribute()</code> method of the wrapped request.
205      *
206      * @param name Name of the attribute to retrieve
207      */

208     public Object JavaDoc getAttribute(String JavaDoc name) {
209
210         if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
211             return dispatcherType;
212         } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
213             if ( requestDispatcherPath != null ){
214                 return requestDispatcherPath.toString();
215             } else {
216                 return null;
217             }
218         }
219
220         int pos = getSpecial(name);
221         if (pos == -1) {
222             return getRequest().getAttribute(name);
223         } else {
224             if ((specialAttributes[pos] == null)
225                 && (specialAttributes[5] == null) && (pos >= 5)) {
226                 // If it's a forward special attribute, and null, it means this
227
// is an include, so we check the wrapped request since
228
// the request could have been forwarded before the include
229
return getRequest().getAttribute(name);
230             } else {
231                 return specialAttributes[pos];
232             }
233         }
234
235     }
236
237
238     /**
239      * Override the <code>getAttributeNames()</code> method of the wrapped
240      * request.
241      */

242     public Enumeration JavaDoc getAttributeNames() {
243         return (new AttributeNamesEnumerator());
244     }
245
246
247     /**
248      * Override the <code>removeAttribute()</code> method of the
249      * wrapped request.
250      *
251      * @param name Name of the attribute to remove
252      */

253     public void removeAttribute(String JavaDoc name) {
254
255         if (!removeSpecial(name))
256             getRequest().removeAttribute(name);
257
258     }
259
260
261     /**
262      * Override the <code>setAttribute()</code> method of the
263      * wrapped request.
264      *
265      * @param name Name of the attribute to set
266      * @param value Value of the attribute to set
267      */

268     public void setAttribute(String JavaDoc name, Object JavaDoc value) {
269
270         if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
271             dispatcherType = value;
272             return;
273         } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
274             requestDispatcherPath = value;
275             return;
276         }
277
278         if (!setSpecial(name, value)) {
279             getRequest().setAttribute(name, value);
280         }
281
282     }
283
284
285     /**
286      * Return a RequestDispatcher that wraps the resource at the specified
287      * path, which may be interpreted as relative to the current request path.
288      *
289      * @param path Path of the resource to be wrapped
290      */

291     public RequestDispatcher JavaDoc getRequestDispatcher(String JavaDoc path) {
292
293         if (context == null)
294             return (null);
295
296         // If the path is already context-relative, just pass it through
297
if (path == null)
298             return (null);
299         else if (path.startsWith("/"))
300             return (context.getServletContext().getRequestDispatcher(path));
301
302         // Convert a request-relative path to a context-relative one
303
String JavaDoc servletPath =
304             (String JavaDoc) getAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR);
305         if (servletPath == null)
306             servletPath = getServletPath();
307
308         // Add the path info, if there is any
309
String JavaDoc pathInfo = getPathInfo();
310         String JavaDoc requestPath = null;
311
312         if (pathInfo == null) {
313             requestPath = servletPath;
314         } else {
315             requestPath = servletPath + pathInfo;
316         }
317
318         int pos = requestPath.lastIndexOf('/');
319         String JavaDoc relative = null;
320         if (pos >= 0) {
321             relative = RequestUtil.normalize
322                 (requestPath.substring(0, pos + 1) + path);
323         } else {
324             relative = RequestUtil.normalize(requestPath + path);
325         }
326
327         return (context.getServletContext().getRequestDispatcher(relative));
328
329     }
330
331
332     // --------------------------------------------- HttpServletRequest Methods
333

334
335     /**
336      * Override the <code>getContextPath()</code> method of the wrapped
337      * request.
338      */

339     public String JavaDoc getContextPath() {
340
341         return (this.contextPath);
342
343     }
344
345
346     /**
347      * Override the <code>getParameter()</code> method of the wrapped request.
348      *
349      * @param name Name of the requested parameter
350      */

351     public String JavaDoc getParameter(String JavaDoc name) {
352
353     parseParameters();
354
355         Object JavaDoc value = parameters.get(name);
356         if (value == null)
357             return (null);
358         else if (value instanceof String JavaDoc[])
359             return (((String JavaDoc[]) value)[0]);
360         else if (value instanceof String JavaDoc)
361             return ((String JavaDoc) value);
362         else
363             return (value.toString());
364
365     }
366
367
368     /**
369      * Override the <code>getParameterMap()</code> method of the
370      * wrapped request.
371      */

372     public Map JavaDoc getParameterMap() {
373
374     parseParameters();
375         return (parameters);
376
377     }
378
379
380     /**
381      * Override the <code>getParameterNames()</code> method of the
382      * wrapped request.
383      */

384     public Enumeration JavaDoc getParameterNames() {
385
386     parseParameters();
387         return (new Enumerator(parameters.keySet()));
388
389     }
390
391
392     /**
393      * Override the <code>getParameterValues()</code> method of the
394      * wrapped request.
395      *
396      * @param name Name of the requested parameter
397      */

398     public String JavaDoc[] getParameterValues(String JavaDoc name) {
399
400     parseParameters();
401         Object JavaDoc value = parameters.get(name);
402         if (value == null)
403             return ((String JavaDoc[]) null);
404         else if (value instanceof String JavaDoc[])
405             return ((String JavaDoc[]) value);
406         else if (value instanceof String JavaDoc) {
407             String JavaDoc values[] = new String JavaDoc[1];
408             values[0] = (String JavaDoc) value;
409             return (values);
410         } else {
411             String JavaDoc values[] = new String JavaDoc[1];
412             values[0] = value.toString();
413             return (values);
414         }
415
416     }
417
418
419     /**
420      * Override the <code>getPathInfo()</code> method of the wrapped request.
421      */

422     public String JavaDoc getPathInfo() {
423
424         return (this.pathInfo);
425
426     }
427
428
429     /**
430      * Override the <code>getQueryString()</code> method of the wrapped
431      * request.
432      */

433     public String JavaDoc getQueryString() {
434
435         return (this.queryString);
436
437     }
438
439
440     /**
441      * Override the <code>getRequestURI()</code> method of the wrapped
442      * request.
443      */

444     public String JavaDoc getRequestURI() {
445
446         return (this.requestURI);
447
448     }
449
450
451     /**
452      * Override the <code>getRequestURL()</code> method of the wrapped
453      * request.
454      */

455     public StringBuffer JavaDoc getRequestURL() {
456
457         StringBuffer JavaDoc url = new StringBuffer JavaDoc();
458         String JavaDoc scheme = getScheme();
459         int port = getServerPort();
460         if (port < 0)
461             port = 80; // Work around java.net.URL bug
462

463         url.append(scheme);
464         url.append("://");
465         url.append(getServerName());
466         if ((scheme.equals("http") && (port != 80))
467             || (scheme.equals("https") && (port != 443))) {
468             url.append(':');
469             url.append(port);
470         }
471         url.append(getRequestURI());
472
473         return (url);
474
475     }
476
477
478     /**
479      * Override the <code>getServletPath()</code> method of the wrapped
480      * request.
481      */

482     public String JavaDoc getServletPath() {
483
484         return (this.servletPath);
485
486     }
487
488
489     /**
490      * Return the session associated with this Request, creating one
491      * if necessary.
492      */

493     public HttpSession JavaDoc getSession() {
494         return (getSession(true));
495     }
496
497
498     /**
499      * Return the session associated with this Request, creating one
500      * if necessary and requested.
501      *
502      * @param create Create a new session if one does not exist
503      */

504     public HttpSession JavaDoc getSession(boolean create) {
505
506         if (crossContext) {
507             
508             // There cannot be a session if no context has been assigned yet
509
if (context == null)
510                 return (null);
511
512             // Return the current session if it exists and is valid
513
if (session != null && session.isValid()) {
514                 return (session.getSession());
515             }
516
517             HttpSession JavaDoc other = super.getSession(false);
518             if (create && (other == null)) {
519                 // First create a session in the first context: the problem is
520
// that the top level request is the only one which can
521
// create the cookie safely
522
other = super.getSession(true);
523             }
524             if (other != null) {
525                 Session JavaDoc localSession = null;
526                 try {
527                     localSession =
528                         context.getManager().findSession(other.getId());
529                 } catch (IOException JavaDoc e) {
530                     // Ignore
531
}
532                 if (localSession == null && create) {
533                     localSession =
534                         context.getManager().createSession(other.getId());
535                 }
536                 if (localSession != null) {
537                     localSession.access();
538                     session = localSession;
539                     return session.getSession();
540                 }
541             }
542             return null;
543
544         } else {
545             return super.getSession(create);
546         }
547
548     }
549
550
551     /**
552      * Returns true if the request specifies a JSESSIONID that is valid within
553      * the context of this ApplicationHttpRequest, false otherwise.
554      *
555      * @return true if the request specifies a JSESSIONID that is valid within
556      * the context of this ApplicationHttpRequest, false otherwise.
557      */

558     public boolean isRequestedSessionIdValid() {
559
560         if (crossContext) {
561
562             String JavaDoc requestedSessionId = getRequestedSessionId();
563             if (requestedSessionId == null)
564                 return (false);
565             if (context == null)
566                 return (false);
567             Manager manager = context.getManager();
568             if (manager == null)
569                 return (false);
570             Session JavaDoc session = null;
571             try {
572                 session = manager.findSession(requestedSessionId);
573             } catch (IOException JavaDoc e) {
574                 session = null;
575             }
576             if ((session != null) && session.isValid()) {
577                 return (true);
578             } else {
579                 return (false);
580             }
581
582         } else {
583             return super.isRequestedSessionIdValid();
584         }
585     }
586
587
588     // -------------------------------------------------------- Package Methods
589

590
591     /**
592      * Recycle this request
593      */

594     public void recycle() {
595         if (session != null) {
596             session.endAccess();
597         }
598     }
599
600
601     /**
602      * Return descriptive information about this implementation.
603      */

604     public String JavaDoc getInfo() {
605
606         return (info);
607
608     }
609
610
611     /**
612      * Perform a shallow copy of the specified Map, and return the result.
613      *
614      * @param orig Origin Map to be copied
615      */

616     Map JavaDoc copyMap(Map JavaDoc orig) {
617
618         if (orig == null)
619             return (new HashMap JavaDoc());
620         HashMap JavaDoc dest = new HashMap JavaDoc();
621         Iterator JavaDoc keys = orig.keySet().iterator();
622         while (keys.hasNext()) {
623             String JavaDoc key = (String JavaDoc) keys.next();
624             dest.put(key, orig.get(key));
625         }
626         return (dest);
627
628     }
629
630
631     /**
632      * Set the context path for this request.
633      *
634      * @param contextPath The new context path
635      */

636     void setContextPath(String JavaDoc contextPath) {
637
638         this.contextPath = contextPath;
639
640     }
641
642
643     /**
644      * Set the path information for this request.
645      *
646      * @param pathInfo The new path info
647      */

648     void setPathInfo(String JavaDoc pathInfo) {
649
650         this.pathInfo = pathInfo;
651
652     }
653
654
655     /**
656      * Set the query string for this request.
657      *
658      * @param queryString The new query string
659      */

660     void setQueryString(String JavaDoc queryString) {
661
662         this.queryString = queryString;
663
664     }
665
666
667     /**
668      * Set the request that we are wrapping.
669      *
670      * @param request The new wrapped request
671      */

672     void setRequest(HttpServletRequest JavaDoc request) {
673
674         super.setRequest(request);
675
676         // Initialize the attributes for this request
677
dispatcherType = request.getAttribute(Globals.DISPATCHER_TYPE_ATTR);
678         requestDispatcherPath =
679             request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR);
680
681         // Initialize the path elements for this request
682
contextPath = request.getContextPath();
683         pathInfo = request.getPathInfo();
684         queryString = request.getQueryString();
685         requestURI = request.getRequestURI();
686         servletPath = request.getServletPath();
687
688     }
689
690
691     /**
692      * Set the request URI for this request.
693      *
694      * @param requestURI The new request URI
695      */

696     void setRequestURI(String JavaDoc requestURI) {
697
698         this.requestURI = requestURI;
699
700     }
701
702
703     /**
704      * Set the servlet path for this request.
705      *
706      * @param servletPath The new servlet path
707      */

708     void setServletPath(String JavaDoc servletPath) {
709
710         this.servletPath = servletPath;
711
712     }
713
714
715     /**
716      * Parses the parameters of this request.
717      *
718      * If parameters are present in both the query string and the request
719      * content, they are merged.
720      */

721     void parseParameters() {
722
723     if (parsedParams) {
724         return;
725     }
726
727         parameters = new HashMap JavaDoc();
728         parameters = copyMap(getRequest().getParameterMap());
729         mergeParameters();
730         parsedParams = true;
731     }
732
733
734     /**
735      * Save query parameters for this request.
736      *
737      * @param queryString The query string containing parameters for this
738      * request
739      */

740     void setQueryParams(String JavaDoc queryString) {
741         this.queryParamString = queryString;
742     }
743
744
745     // ------------------------------------------------------ Protected Methods
746

747
748     /**
749      * Is this attribute name one of the special ones that is added only for
750      * included servlets?
751      *
752      * @param name Attribute name to be tested
753      */

754     protected boolean isSpecial(String JavaDoc name) {
755
756         for (int i = 0; i < specials.length; i++) {
757             if (specials[i].equals(name))
758                 return (true);
759         }
760         return (false);
761
762     }
763
764
765     /**
766      * Get a special attribute.
767      *
768      * @return the special attribute pos, or -1 if it is not a special
769      * attribute
770      */

771     protected int getSpecial(String JavaDoc name) {
772         for (int i = 0; i < specials.length; i++) {
773             if (specials[i].equals(name)) {
774                 return (i);
775             }
776         }
777         return (-1);
778     }
779
780
781     /**
782      * Set a special attribute.
783      *
784      * @return true if the attribute was a special attribute, false otherwise
785      */

786     protected boolean setSpecial(String JavaDoc name, Object JavaDoc value) {
787         for (int i = 0; i < specials.length; i++) {
788             if (specials[i].equals(name)) {
789                 specialAttributes[i] = value;
790                 return (true);
791             }
792         }
793         return (false);
794     }
795
796
797     /**
798      * Remove a special attribute.
799      *
800      * @return true if the attribute was a special attribute, false otherwise
801      */

802     protected boolean removeSpecial(String JavaDoc name) {
803         for (int i = 0; i < specials.length; i++) {
804             if (specials[i].equals(name)) {
805                 specialAttributes[i] = null;
806                 return (true);
807             }
808         }
809         return (false);
810     }
811
812
813     /**
814      * Merge the two sets of parameter values into a single String array.
815      *
816      * @param values1 First set of values
817      * @param values2 Second set of values
818      */

819     protected String JavaDoc[] mergeValues(Object JavaDoc values1, Object JavaDoc values2) {
820
821         ArrayList JavaDoc results = new ArrayList JavaDoc();
822
823         if (values1 == null)
824             ;
825         else if (values1 instanceof String JavaDoc)
826             results.add(values1);
827         else if (values1 instanceof String JavaDoc[]) {
828             String JavaDoc values[] = (String JavaDoc[]) values1;
829             for (int i = 0; i < values.length; i++)
830                 results.add(values[i]);
831         } else
832             results.add(values1.toString());
833
834         if (values2 == null)
835             ;
836         else if (values2 instanceof String JavaDoc)
837             results.add(values2);
838         else if (values2 instanceof String JavaDoc[]) {
839             String JavaDoc values[] = (String JavaDoc[]) values2;
840             for (int i = 0; i < values.length; i++)
841                 results.add(values[i]);
842         } else
843             results.add(values2.toString());
844
845         String JavaDoc values[] = new String JavaDoc[results.size()];
846         return ((String JavaDoc[]) results.toArray(values));
847
848     }
849
850
851     // ------------------------------------------------------ Private Methods
852

853
854     /**
855      * Merge the parameters from the saved query parameter string (if any), and
856      * the parameters already present on this request (if any), such that the
857      * parameter values from the query string show up first if there are
858      * duplicate parameter names.
859      */

860     private void mergeParameters() {
861
862         if ((queryParamString == null) || (queryParamString.length() < 1))
863             return;
864
865         HashMap JavaDoc queryParameters = new HashMap JavaDoc();
866         String JavaDoc encoding = getCharacterEncoding();
867         if (encoding == null)
868             encoding = "ISO-8859-1";
869         try {
870             RequestUtil.parseParameters
871                 (queryParameters, queryParamString, encoding);
872         } catch (Exception JavaDoc e) {
873             ;
874         }
875         Iterator JavaDoc keys = parameters.keySet().iterator();
876         while (keys.hasNext()) {
877             String JavaDoc key = (String JavaDoc) keys.next();
878             Object JavaDoc value = queryParameters.get(key);
879             if (value == null) {
880                 queryParameters.put(key, parameters.get(key));
881                 continue;
882             }
883             queryParameters.put
884                 (key, mergeValues(value, parameters.get(key)));
885         }
886         parameters = queryParameters;
887
888     }
889
890
891     // ----------------------------------- AttributeNamesEnumerator Inner Class
892

893
894     /**
895      * Utility class used to expose the special attributes as being available
896      * as request attributes.
897      */

898     protected class AttributeNamesEnumerator implements Enumeration JavaDoc {
899
900         protected int pos = -1;
901         protected int last = -1;
902         protected Enumeration JavaDoc parentEnumeration = null;
903         protected String JavaDoc next = null;
904
905         public AttributeNamesEnumerator() {
906             parentEnumeration = getRequest().getAttributeNames();
907             for (int i = 0; i < specialAttributes.length; i++) {
908                 if (getAttribute(specials[i]) != null) {
909                     last = i;
910                 }
911             }
912         }
913
914         public boolean hasMoreElements() {
915             return ((pos != last) || (next != null)
916                     || ((next = findNext()) != null));
917         }
918
919         public Object JavaDoc nextElement() {
920             if (pos != last) {
921                 for (int i = pos + 1; i <= last; i++) {
922                     if (getAttribute(specials[i]) != null) {
923                         pos = i;
924                         return (specials[i]);
925                     }
926                 }
927             }
928             String JavaDoc result = next;
929             if (next != null) {
930                 next = findNext();
931             } else {
932                 throw new NoSuchElementException JavaDoc();
933             }
934             return result;
935         }
936
937         protected String JavaDoc findNext() {
938             String JavaDoc result = null;
939             while ((result == null) && (parentEnumeration.hasMoreElements())) {
940                 String JavaDoc current = (String JavaDoc) parentEnumeration.nextElement();
941                 if (!isSpecial(current)) {
942                     result = current;
943                 }
944             }
945             return result;
946         }
947
948     }
949
950
951 }
952
Popular Tags