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.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.lang.reflect.Constructor;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.Hashtable;
30 import java.util.Iterator;
31 import java.util.StringTokenizer;
32
33 import javax.management.MalformedObjectNameException;
34 import javax.management.ObjectName;
35 import javax.naming.NameAlreadyBoundException;
36 import javax.naming.NamingException;
37 import javax.naming.Reference;
38 import javax.naming.StringRefAddr;
39
40 import org.apache.catalina.ContainerEvent;
41 import org.apache.catalina.ContainerListener;
42 import org.apache.catalina.Context;
43 import org.apache.catalina.Engine;
44 import org.apache.catalina.Host;
45 import org.apache.catalina.Lifecycle;
46 import org.apache.catalina.LifecycleEvent;
47 import org.apache.catalina.LifecycleListener;
48 import org.apache.catalina.Server;
49 import org.apache.catalina.deploy.NamingResourcesImpl;
50 import org.apache.juli.logging.Log;
51 import org.apache.juli.logging.LogFactory;
52 import org.apache.naming.ContextAccessController;
53 import org.apache.naming.ContextBindings;
54 import org.apache.naming.EjbRef;
55 import org.apache.naming.HandlerRef;
56 import org.apache.naming.LookupRef;
57 import org.apache.naming.NamingContext;
58 import org.apache.naming.ResourceEnvRef;
59 import org.apache.naming.ResourceLinkRef;
60 import org.apache.naming.ResourceRef;
61 import org.apache.naming.ServiceRef;
62 import org.apache.naming.TransactionRef;
63 import org.apache.naming.factory.Constants;
64 import org.apache.naming.factory.ResourceLinkFactory;
65 import org.apache.tomcat.util.descriptor.web.ContextEjb;
66 import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
67 import org.apache.tomcat.util.descriptor.web.ContextHandler;
68 import org.apache.tomcat.util.descriptor.web.ContextLocalEjb;
69 import org.apache.tomcat.util.descriptor.web.ContextResource;
70 import org.apache.tomcat.util.descriptor.web.ContextResourceEnvRef;
71 import org.apache.tomcat.util.descriptor.web.ContextResourceLink;
72 import org.apache.tomcat.util.descriptor.web.ContextService;
73 import org.apache.tomcat.util.descriptor.web.ContextTransaction;
74 import org.apache.tomcat.util.descriptor.web.MessageDestinationRef;
75 import org.apache.tomcat.util.descriptor.web.ResourceBase;
76 import org.apache.tomcat.util.modeler.Registry;
77 import org.apache.tomcat.util.res.StringManager;
78
79
80 /**
81  * Helper class used to initialize and populate the JNDI context associated
82  * with each context and server.
83  *
84  * @author Remy Maucherat
85  */

86 public class NamingContextListener
87         implements LifecycleListener, ContainerListener, PropertyChangeListener {
88
89     private static final Log log = LogFactory.getLog(NamingContextListener.class);
90
91
92     // ----------------------------------------------------- Instance Variables
93
94     /**
95      * Name of the associated naming context.
96      */

97     protected String name = "/";
98
99
100     /**
101      * Associated container.
102      */

103     protected Object container = null;
104
105     /**
106      * Token for configuring associated JNDI context.
107      */

108     private Object token = null;
109
110     /**
111      * Initialized flag.
112      */

113     protected boolean initialized = false;
114
115
116     /**
117      * Associated naming resources.
118      */

119     protected NamingResourcesImpl namingResources = null;
120
121
122     /**
123      * Associated JNDI context.
124      */

125     protected NamingContext namingContext = null;
126
127
128     /**
129      * Comp context.
130      */

131     protected javax.naming.Context compCtx = null;
132
133
134     /**
135      * Env context.
136      */

137     protected javax.naming.Context envCtx = null;
138
139
140     /**
141      * Objectnames hashtable.
142      */

143     protected HashMap<String, ObjectName> objectNames = new HashMap<>();
144
145
146     /**
147      * Determines if an attempt to write to a read-only context results in an
148      * exception or if the request is ignored.
149      */

150     private boolean exceptionOnFailedWrite = true;
151
152
153     /**
154      * The string manager for this package.
155      */

156     protected static final StringManager sm =
157         StringManager.getManager(Constants.Package);
158
159
160     // ------------------------------------------------------------- Properties
161
162     /**
163      * @return whether or not an attempt to modify the JNDI context will trigger
164      * an exception or if the request will be ignored.
165      */

166     public boolean getExceptionOnFailedWrite() {
167         return exceptionOnFailedWrite;
168     }
169
170
171     /**
172      * Controls whether or not an attempt to modify the JNDI context will
173      * trigger an exception or if the request will be ignored.
174      *
175      * @param exceptionOnFailedWrite    The new value
176      */

177     public void setExceptionOnFailedWrite(boolean exceptionOnFailedWrite) {
178         this.exceptionOnFailedWrite = exceptionOnFailedWrite;
179     }
180
181
182     /**
183      * @return the "name" property.
184      */

185     public String getName() {
186         return this.name;
187     }
188
189
190     /**
191      * Set the "name" property.
192      *
193      * @param name The new name
194      */

195     public void setName(String name) {
196         this.name = name;
197     }
198
199
200     /**
201      * @return the naming environment context.
202      */

203     public javax.naming.Context getEnvContext() {
204         return this.envCtx;
205     }
206
207
208     // ---------------------------------------------- LifecycleListener Methods
209
210     /**
211      * Acknowledge the occurrence of the specified event.
212      *
213      * @param event LifecycleEvent that has occurred
214      */

215     @Override
216     public void lifecycleEvent(LifecycleEvent event) {
217
218         container = event.getLifecycle();
219
220         if (container instanceof Context) {
221             namingResources = ((Context) container).getNamingResources();
222             token = ((Context) container).getNamingToken();
223         } else if (container instanceof Server) {
224             namingResources = ((Server) container).getGlobalNamingResources();
225             token = ((Server) container).getNamingToken();
226         } else {
227             return;
228         }
229
230         if (Lifecycle.CONFIGURE_START_EVENT.equals(event.getType())) {
231
232             if (initialized)
233                 return;
234
235             try {
236                 Hashtable<String, Object> contextEnv = new Hashtable<>();
237                 namingContext = new NamingContext(contextEnv, getName());
238                 ContextAccessController.setSecurityToken(getName(), token);
239                 ContextAccessController.setSecurityToken(container, token);
240                 ContextBindings.bindContext(container, namingContext, token);
241                 if( log.isDebugEnabled() ) {
242                     log.debug("Bound " + container );
243                 }
244
245                 // Configure write when read-only behaviour
246                 namingContext.setExceptionOnFailedWrite(
247                         getExceptionOnFailedWrite());
248
249                 // Setting the context in read/write mode
250                 ContextAccessController.setWritable(getName(), token);
251
252                 try {
253                     createNamingContext();
254                 } catch (NamingException e) {
255                     log.error
256                         (sm.getString("naming.namingContextCreationFailed", e));
257                 }
258
259                 namingResources.addPropertyChangeListener(this);
260
261                 // Binding the naming context to the class loader
262                 if (container instanceof Context) {
263                     // Setting the context in read only mode
264                     ContextAccessController.setReadOnly(getName());
265                     try {
266                         ContextBindings.bindClassLoader(container, token,
267                                 ((Context) container).getLoader().getClassLoader());
268                     } catch (NamingException e) {
269                         log.error(sm.getString("naming.bindFailed", e));
270                     }
271                 }
272
273                 if (container instanceof Server) {
274                     org.apache.naming.factory.ResourceLinkFactory.setGlobalContext
275                         (namingContext);
276                     try {
277                         ContextBindings.bindClassLoader(container, token,
278                                 this.getClass().getClassLoader());
279                     } catch (NamingException e) {
280                         log.error(sm.getString("naming.bindFailed", e));
281                     }
282                     if (container instanceof StandardServer) {
283                         ((StandardServer) container).setGlobalNamingContext
284                             (namingContext);
285                     }
286                 }
287
288             } finally {
289                 // Regardless of success, so that we can do cleanup on configure_stop
290                 initialized = true;
291             }
292
293         } else if (Lifecycle.CONFIGURE_STOP_EVENT.equals(event.getType())) {
294
295             if (!initialized)
296                 return;
297
298             try {
299                 // Setting the context in read/write mode
300                 ContextAccessController.setWritable(getName(), token);
301                 ContextBindings.unbindContext(container, token);
302
303                 if (container instanceof Context) {
304                     ContextBindings.unbindClassLoader(container, token,
305                             ((Context) container).getLoader().getClassLoader());
306                 }
307
308                 if (container instanceof Server) {
309                     ContextBindings.unbindClassLoader(container, token,
310                             this.getClass().getClassLoader());
311                 }
312
313                 namingResources.removePropertyChangeListener(this);
314
315                 ContextAccessController.unsetSecurityToken(getName(), token);
316                 ContextAccessController.unsetSecurityToken(container, token);
317
318                 // unregister mbeans.
319                 if (!objectNames.isEmpty()) {
320                     Collection<ObjectName> names = objectNames.values();
321                     Registry registry = Registry.getRegistry(nullnull);
322                     for (ObjectName objectName : names) {
323                         registry.unregisterComponent(objectName);
324                     }
325                 }
326
327                 javax.naming.Context global = getGlobalNamingContext();
328                 if (global != null) {
329                     ResourceLinkFactory.deregisterGlobalResourceAccess(global);
330                 }
331             } finally {
332                 objectNames.clear();
333
334                 namingContext = null;
335                 envCtx = null;
336                 compCtx = null;
337                 initialized = false;
338             }
339
340         }
341
342     }
343
344
345     // ---------------------------------------------- ContainerListener Methods
346
347     /**
348      * NO-OP.
349      *
350      * @param event ContainerEvent that has occurred
351      *
352      * @deprecated The {@link ContainerListener} interface and implementing
353      *             methods will be removed from this class for Tomcat 10
354      *             onwards.
355      */

356     @Deprecated
357     @Override
358     public void containerEvent(ContainerEvent event) {
359         // NO-OP
360     }
361
362
363     // ----------------------------------------- PropertyChangeListener Methods
364
365
366     /**
367      * Process property change events.
368      *
369      * @param event The property change event that has occurred
370      */

371     @Override
372     public void propertyChange(PropertyChangeEvent event) {
373
374         if (!initialized)
375             return;
376
377         Object source = event.getSource();
378         if (source == namingResources) {
379
380             // Setting the context in read/write mode
381             ContextAccessController.setWritable(getName(), token);
382
383             processGlobalResourcesChange(event.getPropertyName(),
384                                          event.getOldValue(),
385                                          event.getNewValue());
386
387             // Setting the context in read only mode
388             ContextAccessController.setReadOnly(getName());
389
390         }
391
392     }
393
394
395     // -------------------------------------------------------- Private Methods
396
397
398     /**
399      * Process a property change on the naming resources, by making the
400      * corresponding addition or removal to the associated JNDI context.
401      *
402      * @param name Property name of the change to be processed
403      * @param oldValue The old value (or <code>null</code> if adding)
404      * @param newValue The new value (or <code>null</code> if removing)
405      */

406     private void processGlobalResourcesChange(String name,
407                                               Object oldValue,
408                                               Object newValue) {
409
410         if (name.equals("ejb")) {
411             if (oldValue != null) {
412                 ContextEjb ejb = (ContextEjb) oldValue;
413                 if (ejb.getName() != null) {
414                     removeEjb(ejb.getName());
415                 }
416             }
417             if (newValue != null) {
418                 ContextEjb ejb = (ContextEjb) newValue;
419                 if (ejb.getName() != null) {
420                     addEjb(ejb);
421                 }
422             }
423         } else if (name.equals("environment")) {
424             if (oldValue != null) {
425                 ContextEnvironment env = (ContextEnvironment) oldValue;
426                 if (env.getName() != null) {
427                     removeEnvironment(env.getName());
428                 }
429             }
430             if (newValue != null) {
431                 ContextEnvironment env = (ContextEnvironment) newValue;
432                 if (env.getName() != null) {
433                     addEnvironment(env);
434                 }
435             }
436         } else if (name.equals("localEjb")) {
437             if (oldValue != null) {
438                 ContextLocalEjb ejb = (ContextLocalEjb) oldValue;
439                 if (ejb.getName() != null) {
440                     removeLocalEjb(ejb.getName());
441                 }
442             }
443             if (newValue != null) {
444                 ContextLocalEjb ejb = (ContextLocalEjb) newValue;
445                 if (ejb.getName() != null) {
446                     addLocalEjb(ejb);
447                 }
448             }
449         } else if (name.equals("messageDestinationRef")) {
450             if (oldValue != null) {
451                 MessageDestinationRef mdr = (MessageDestinationRef) oldValue;
452                 if (mdr.getName() != null) {
453                     removeMessageDestinationRef(mdr.getName());
454                 }
455             }
456             if (newValue != null) {
457                 MessageDestinationRef mdr = (MessageDestinationRef) newValue;
458                 if (mdr.getName() != null) {
459                     addMessageDestinationRef(mdr);
460                 }
461             }
462         } else if (name.equals("resource")) {
463             if (oldValue != null) {
464                 ContextResource resource = (ContextResource) oldValue;
465                 if (resource.getName() != null) {
466                     removeResource(resource.getName());
467                 }
468             }
469             if (newValue != null) {
470                 ContextResource resource = (ContextResource) newValue;
471                 if (resource.getName() != null) {
472                     addResource(resource);
473                 }
474             }
475         } else if (name.equals("resourceEnvRef")) {
476             if (oldValue != null) {
477                 ContextResourceEnvRef resourceEnvRef =
478                     (ContextResourceEnvRef) oldValue;
479                 if (resourceEnvRef.getName() != null) {
480                     removeResourceEnvRef(resourceEnvRef.getName());
481                 }
482             }
483             if (newValue != null) {
484                 ContextResourceEnvRef resourceEnvRef =
485                     (ContextResourceEnvRef) newValue;
486                 if (resourceEnvRef.getName() != null) {
487                     addResourceEnvRef(resourceEnvRef);
488                 }
489             }
490         } else if (name.equals("resourceLink")) {
491             if (oldValue != null) {
492                 ContextResourceLink rl = (ContextResourceLink) oldValue;
493                 if (rl.getName() != null) {
494                     removeResourceLink(rl.getName());
495                 }
496             }
497             if (newValue != null) {
498                 ContextResourceLink rl = (ContextResourceLink) newValue;
499                 if (rl.getName() != null) {
500                     addResourceLink(rl);
501                 }
502             }
503         } else if (name.equals("service")) {
504             if (oldValue != null) {
505                 ContextService service = (ContextService) oldValue;
506                 if (service.getName() != null) {
507                     removeService(service.getName());
508                 }
509             }
510             if (newValue != null) {
511                 ContextService service = (ContextService) newValue;
512                 if (service.getName() != null) {
513                     addService(service);
514                 }
515             }
516         }
517
518
519     }
520
521
522     /**
523      * Create and initialize the JNDI naming context.
524      */

525     private void createNamingContext()
526         throws NamingException {
527
528         // Creating the comp subcontext
529         if (container instanceof Server) {
530             compCtx = namingContext;
531             envCtx = namingContext;
532         } else {
533             compCtx = namingContext.createSubcontext("comp");
534             envCtx = compCtx.createSubcontext("env");
535         }
536
537         int i;
538
539         if (log.isDebugEnabled())
540             log.debug("Creating JNDI naming context");
541
542         if (namingResources == null) {
543             namingResources = new NamingResourcesImpl();
544             namingResources.setContainer(container);
545         }
546
547         // Resource links
548         ContextResourceLink[] resourceLinks =
549             namingResources.findResourceLinks();
550         for (i = 0; i < resourceLinks.length; i++) {
551             addResourceLink(resourceLinks[i]);
552         }
553
554         // Resources
555         ContextResource[] resources = namingResources.findResources();
556         for (i = 0; i < resources.length; i++) {
557             addResource(resources[i]);
558         }
559
560         // Resources Env
561         ContextResourceEnvRef[] resourceEnvRefs = namingResources.findResourceEnvRefs();
562         for (i = 0; i < resourceEnvRefs.length; i++) {
563             addResourceEnvRef(resourceEnvRefs[i]);
564         }
565
566         // Environment entries
567         ContextEnvironment[] contextEnvironments =
568             namingResources.findEnvironments();
569         for (i = 0; i < contextEnvironments.length; i++) {
570             addEnvironment(contextEnvironments[i]);
571         }
572
573         // EJB references
574         ContextEjb[] ejbs = namingResources.findEjbs();
575         for (i = 0; i < ejbs.length; i++) {
576             addEjb(ejbs[i]);
577         }
578
579         // Message Destination References
580         MessageDestinationRef[] mdrs = namingResources.findMessageDestinationRefs();
581         for (i = 0; i < mdrs.length; i++) {
582             addMessageDestinationRef(mdrs[i]);
583         }
584
585         // WebServices references
586         ContextService[] services = namingResources.findServices();
587         for (i = 0; i < services.length; i++) {
588             addService(services[i]);
589         }
590
591         // Binding a User Transaction reference
592         if (container instanceof Context) {
593             try {
594                 Reference ref = new TransactionRef();
595                 compCtx.bind("UserTransaction", ref);
596                 ContextTransaction transaction = namingResources.getTransaction();
597                 if (transaction != null) {
598                     Iterator<String> params = transaction.listProperties();
599                     while (params.hasNext()) {
600                         String paramName = params.next();
601                         String paramValue = (String) transaction.getProperty(paramName);
602                         StringRefAddr refAddr = new StringRefAddr(paramName, paramValue);
603                         ref.add(refAddr);
604                     }
605                 }
606             } catch (NameAlreadyBoundException e) {
607                 // Ignore because UserTransaction was obviously
608                 // added via ResourceLink
609             } catch (NamingException e) {
610                 log.error(sm.getString("naming.bindFailed", e));
611             }
612         }
613
614         // Binding the resources directory context
615         if (container instanceof Context) {
616             try {
617                 compCtx.bind("Resources",
618                              ((Context) container).getResources());
619             } catch (NamingException e) {
620                 log.error(sm.getString("naming.bindFailed", e));
621             }
622         }
623
624     }
625
626
627     /**
628      * Create an <code>ObjectName</code> for this
629      * <code>ContextResource</code> object.
630      *
631      * @param resource The resource
632      * @return ObjectName The object name
633      * @exception MalformedObjectNameException if a name cannot be created
634      */

635     protected ObjectName createObjectName(ContextResource resource)
636         throws MalformedObjectNameException {
637
638         String domain = null;
639         if (container instanceof StandardServer) {
640             domain = ((StandardServer) container).getDomain();
641         } else if (container instanceof ContainerBase) {
642             domain = ((ContainerBase) container).getDomain();
643         }
644         if (domain == null) {
645             domain = "Catalina";
646         }
647
648         ObjectName name = null;
649         String quotedResourceName = ObjectName.quote(resource.getName());
650         if (container instanceof Server) {
651             name = new ObjectName(domain + ":type=DataSource" +
652                         ",class=" + resource.getType() +
653                         ",name=" + quotedResourceName);
654         } else if (container instanceof Context) {
655             String contextName = ((Context)container).getName();
656             if (!contextName.startsWith("/"))
657                 contextName = "/" + contextName;
658             Host host = (Host) ((Context)container).getParent();
659             name = new ObjectName(domain + ":type=DataSource" +
660                     ",host=" + host.getName() +
661                     ",context=" + contextName +
662                     ",class=" + resource.getType() +
663                     ",name=" + quotedResourceName);
664         }
665
666         return name;
667
668     }
669
670
671     /**
672      * Set the specified EJBs in the naming context.
673      *
674      * @param ejb the EJB descriptor
675      */

676     public void addEjb(ContextEjb ejb) {
677
678         Reference ref = lookForLookupRef(ejb);
679
680         if (ref == null) {
681             // Create a reference to the EJB.
682             ref = new EjbRef(ejb.getType(), ejb.getHome(), ejb.getRemote(), ejb.getLink());
683             // Adding the additional parameters, if any
684             Iterator<String> params = ejb.listProperties();
685             while (params.hasNext()) {
686                 String paramName = params.next();
687                 String paramValue = (String) ejb.getProperty(paramName);
688                 StringRefAddr refAddr = new StringRefAddr(paramName, paramValue);
689                 ref.add(refAddr);
690             }
691         }
692
693         try {
694             createSubcontexts(envCtx, ejb.getName());
695             envCtx.bind(ejb.getName(), ref);
696         } catch (NamingException e) {
697             log.error(sm.getString("naming.bindFailed", e));
698         }
699     }
700
701
702     /**
703      * Set the specified environment entries in the naming context.
704      *
705      * @param env the environment entry
706      */

707     public void addEnvironment(ContextEnvironment env) {
708
709         Object value = lookForLookupRef(env);
710
711         if (value == null) {
712             // Instantiating a new instance of the correct object type, and
713             // initializing it.
714             String type = env.getType();
715             try {
716                 if (type.equals("java.lang.String")) {
717                     value = env.getValue();
718                 } else if (type.equals("java.lang.Byte")) {
719                     if (env.getValue() == null) {
720                         value = Byte.valueOf((byte) 0);
721                     } else {
722                         value = Byte.decode(env.getValue());
723                     }
724                 } else if (type.equals("java.lang.Short")) {
725                     if (env.getValue() == null) {
726                         value = Short.valueOf((short) 0);
727                     } else {
728                         value = Short.decode(env.getValue());
729                     }
730                 } else if (type.equals("java.lang.Integer")) {
731                     if (env.getValue() == null) {
732                         value = Integer.valueOf(0);
733                     } else {
734                         value = Integer.decode(env.getValue());
735                     }
736                 } else if (type.equals("java.lang.Long")) {
737                     if (env.getValue() == null) {
738                         value = Long.valueOf(0);
739                     } else {
740                         value = Long.decode(env.getValue());
741                     }
742                 } else if (type.equals("java.lang.Boolean")) {
743                     value = Boolean.valueOf(env.getValue());
744                 } else if (type.equals("java.lang.Double")) {
745                     if (env.getValue() == null) {
746                         value = Double.valueOf(0);
747                     } else {
748                         value = Double.valueOf(env.getValue());
749                     }
750                 } else if (type.equals("java.lang.Float")) {
751                     if (env.getValue() == null) {
752                         value = Float.valueOf(0);
753                     } else {
754                         value = Float.valueOf(env.getValue());
755                     }
756                 } else if (type.equals("java.lang.Character")) {
757                     if (env.getValue() == null) {
758                         value = Character.valueOf((char) 0);
759                     } else {
760                         if (env.getValue().length() == 1) {
761                             value = Character.valueOf(env.getValue().charAt(0));
762                         } else {
763                             throw new IllegalArgumentException();
764                         }
765                     }
766                 } else {
767                     value = constructEnvEntry(env.getType(), env.getValue());
768                     if (value == null) {
769                         log.error(sm.getString(
770                                 "naming.invalidEnvEntryType", env.getName()));
771                     }
772                 }
773             } catch (NumberFormatException e) {
774                 log.error(sm.getString("naming.invalidEnvEntryValue", env.getName()));
775             } catch (IllegalArgumentException e) {
776                 log.error(sm.getString("naming.invalidEnvEntryValue", env.getName()));
777             }
778         }
779
780         // Binding the object to the appropriate name
781         if (value != null) {
782             try {
783                 if (log.isDebugEnabled()) {
784                     log.debug(sm.getString("naming.addEnvEntry", env.getName()));
785                 }
786                 createSubcontexts(envCtx, env.getName());
787                 envCtx.bind(env.getName(), value);
788             } catch (NamingException e) {
789                 log.error(sm.getString("naming.invalidEnvEntryValue", e));
790             }
791         }
792     }
793
794
795     private Object constructEnvEntry(String type, String value) {
796         try {
797             Class<?> clazz = Class.forName(type);
798             Constructor<?> c = null;
799             try {
800                  c = clazz.getConstructor(String.class);
801                  return c.newInstance(value);
802             } catch (NoSuchMethodException e) {
803                 // Ignore
804             }
805
806             if (value.length() != 1) {
807                 return null;
808             }
809
810             try {
811                 c = clazz.getConstructor(char.class);
812                 return c.newInstance(Character.valueOf(value.charAt(0)));
813             } catch (NoSuchMethodException e) {
814                 // Ignore
815             }
816         } catch (Exception e) {
817             // Ignore
818         }
819         return null;
820     }
821
822     /**
823      * Set the specified local EJBs in the naming context.
824      *
825      * @param localEjb the local EJB descriptor (unused)
826      */

827     public void addLocalEjb(ContextLocalEjb localEjb) {
828         // NO-OP
829         // No factory in org.apache.naming.factory
830         // No reference in org.apache.naming
831     }
832
833
834     /**
835      * Set the specified message destination refs in the naming context.
836      *
837      * @param mdr the message destination ref descriptor (unused)
838      */

839     public void addMessageDestinationRef(MessageDestinationRef mdr) {
840         // NO-OP
841         // No factory in org.apache.naming.factory
842         // No reference in org.apache.naming
843     }
844
845
846     /**
847      * Set the specified web service in the naming context.
848      *
849      * @param service the web service descriptor
850      */

851     public void addService(ContextService service) {
852
853         Reference ref = lookForLookupRef(service);
854
855         if (ref == null) {
856
857             if (service.getWsdlfile() != null) {
858                 URL wsdlURL = null;
859
860                 try {
861                     wsdlURL = new URL(service.getWsdlfile());
862                 } catch (MalformedURLException e) {
863                     // Ignore and carry on
864                 }
865                 if (wsdlURL == null) {
866                     try {
867                         wsdlURL = ((Context) container).getServletContext().getResource(
868                                 service.getWsdlfile());
869                     } catch (MalformedURLException e) {
870                         // Ignore and carry on
871                     }
872                 }
873                 if (wsdlURL == null) {
874                     try {
875                         wsdlURL = ((Context) container).getServletContext().getResource(
876                                 "/" + service.getWsdlfile());
877                         log.debug("  Changing service ref wsdl file for /"
878                                     + service.getWsdlfile());
879                     } catch (MalformedURLException e) {
880                         log.error(sm.getString("naming.wsdlFailed", e));
881                     }
882                 }
883                 if (wsdlURL == null)
884                     service.setWsdlfile(null);
885                 else
886                     service.setWsdlfile(wsdlURL.toString());
887             }
888
889             if (service.getJaxrpcmappingfile() != null) {
890                 URL jaxrpcURL = null;
891
892                 try {
893                     jaxrpcURL = new URL(service.getJaxrpcmappingfile());
894                 } catch (MalformedURLException e) {
895                     // Ignore and carry on
896                 }
897                 if (jaxrpcURL == null) {
898                     try {
899                         jaxrpcURL = ((Context) container).getServletContext().getResource(
900                                 service.getJaxrpcmappingfile());
901                     } catch (MalformedURLException e) {
902                         // Ignore and carry on
903                     }
904                 }
905                 if (jaxrpcURL == null) {
906                     try {
907                         jaxrpcURL = ((Context) container).getServletContext().getResource(
908                                 "/" + service.getJaxrpcmappingfile());
909                         log.debug("  Changing service ref jaxrpc file for /"
910                                     + service.getJaxrpcmappingfile());
911                     } catch (MalformedURLException e) {
912                         log.error(sm.getString("naming.wsdlFailed", e));
913                     }
914                 }
915                 if (jaxrpcURL == null)
916                     service.setJaxrpcmappingfile(null);
917                 else
918                     service.setJaxrpcmappingfile(jaxrpcURL.toString());
919             }
920
921             // Create a reference to the resource.
922             ref = new ServiceRef(service.getName(), service.getInterface(),
923                     service.getServiceqname(), service.getWsdlfile(),
924                     service.getJaxrpcmappingfile());
925
926             // Adding the additional port-component-ref, if any
927             Iterator<String> portcomponent = service.getServiceendpoints();
928             while (portcomponent.hasNext()) {
929                 String serviceendpoint = portcomponent.next();
930                 StringRefAddr refAddr = new StringRefAddr(ServiceRef.SERVICEENDPOINTINTERFACE, serviceendpoint);
931                 ref.add(refAddr);
932                 String portlink = service.getPortlink(serviceendpoint);
933                 refAddr = new StringRefAddr(ServiceRef.PORTCOMPONENTLINK, portlink);
934                 ref.add(refAddr);
935             }
936             // Adding the additional parameters, if any
937             Iterator<String> handlers = service.getHandlers();
938             while (handlers.hasNext()) {
939                 String handlername = handlers.next();
940                 ContextHandler handler = service.getHandler(handlername);
941                 HandlerRef handlerRef = new HandlerRef(handlername, handler.getHandlerclass());
942                 Iterator<String> localParts = handler.getLocalparts();
943                 while (localParts.hasNext()) {
944                     String localPart = localParts.next();
945                     String namespaceURI = handler.getNamespaceuri(localPart);
946                     handlerRef.add(new StringRefAddr(HandlerRef.HANDLER_LOCALPART, localPart));
947                     handlerRef.add(new StringRefAddr(HandlerRef.HANDLER_NAMESPACE, namespaceURI));
948                 }
949                 Iterator<String> params = handler.listProperties();
950                 while (params.hasNext()) {
951                     String paramName = params.next();
952                     String paramValue = (String) handler.getProperty(paramName);
953                     handlerRef.add(new StringRefAddr(HandlerRef.HANDLER_PARAMNAME, paramName));
954                     handlerRef.add(new StringRefAddr(HandlerRef.HANDLER_PARAMVALUE, paramValue));
955                 }
956                 for (int i = 0; i < handler.getSoapRolesSize(); i++) {
957                     handlerRef.add(new StringRefAddr(HandlerRef.HANDLER_SOAPROLE, handler.getSoapRole(i)));
958                 }
959                 for (int i = 0; i < handler.getPortNamesSize(); i++) {
960                     handlerRef.add(new StringRefAddr(HandlerRef.HANDLER_PORTNAME, handler.getPortName(i)));
961                 }
962                 ((ServiceRef) ref).addHandler(handlerRef);
963             }
964         }
965
966         try {
967             if (log.isDebugEnabled()) {
968                 log.debug("  Adding service ref " + service.getName() + "  " + ref);
969             }
970             createSubcontexts(envCtx, service.getName());
971             envCtx.bind(service.getName(), ref);
972         } catch (NamingException e) {
973             log.error(sm.getString("naming.bindFailed", e));
974         }
975     }
976
977
978     /**
979      * Set the specified resources in the naming context.
980      *
981      * @param resource the resource descriptor
982      */

983     public void addResource(ContextResource resource) {
984
985         Reference ref = lookForLookupRef(resource);
986
987         if (ref == null) {
988             // Create a reference to the resource.
989             ref = new ResourceRef(resource.getType(), resource.getDescription(),
990                     resource.getScope(), resource.getAuth(), resource.getSingleton());
991             // Adding the additional parameters, if any
992             Iterator<String> params = resource.listProperties();
993             while (params.hasNext()) {
994                 String paramName = params.next();
995                 String paramValue = (String) resource.getProperty(paramName);
996                 StringRefAddr refAddr = new StringRefAddr(paramName, paramValue);
997                 ref.add(refAddr);
998             }
999         }
1000
1001         try {
1002             if (log.isDebugEnabled()) {
1003                 log.debug("  Adding resource ref " + resource.getName() + "  " + ref);
1004             }
1005             createSubcontexts(envCtx, resource.getName());
1006             envCtx.bind(resource.getName(), ref);
1007         } catch (NamingException e) {
1008             log.error(sm.getString("naming.bindFailed", e));
1009         }
1010
1011         if (("javax.sql.DataSource".equals(ref.getClassName())  ||
1012             "javax.sql.XADataSource".equals(ref.getClassName())) &&
1013                 resource.getSingleton()) {
1014             Object actualResource = null;
1015             try {
1016                 ObjectName on = createObjectName(resource);
1017                 actualResource = envCtx.lookup(resource.getName());
1018                 Registry.getRegistry(nullnull).registerComponent(actualResource, on, null);
1019                 objectNames.put(resource.getName(), on);
1020             } catch (Exception e) {
1021                 log.warn(sm.getString("naming.jmxRegistrationFailed", e));
1022             }
1023             // Bug 63210. DBCP2 DataSources require an explicit close. This goes
1024             // further and cleans up and AutoCloseable DataSource by default.
1025             if (actualResource instanceof AutoCloseable && !resource.getCloseMethodConfigured()) {
1026                 resource.setCloseMethod("close");
1027             }
1028         }
1029     }
1030
1031
1032     /**
1033      * Set the specified resources in the naming context.
1034      *
1035      * @param resourceEnvRef the resource reference
1036      */

1037     public void addResourceEnvRef(ContextResourceEnvRef resourceEnvRef) {
1038
1039         Reference ref = lookForLookupRef(resourceEnvRef);
1040
1041         if (ref == null) {
1042             // Create a reference to the resource env.
1043             ref = new ResourceEnvRef(resourceEnvRef.getType());
1044             // Adding the additional parameters, if any
1045             Iterator<String> params = resourceEnvRef.listProperties();
1046             while (params.hasNext()) {
1047                 String paramName = params.next();
1048                 String paramValue = (String) resourceEnvRef.getProperty(paramName);
1049                 StringRefAddr refAddr = new StringRefAddr(paramName, paramValue);
1050                 ref.add(refAddr);
1051             }
1052         }
1053
1054         try {
1055             if (log.isDebugEnabled()) {
1056                 log.debug(sm.getString("naming.addResourceEnvRef", resourceEnvRef.getName()));
1057             }
1058             createSubcontexts(envCtx, resourceEnvRef.getName());
1059             envCtx.bind(resourceEnvRef.getName(), ref);
1060         } catch (NamingException e) {
1061             log.error(sm.getString("naming.bindFailed", e));
1062         }
1063     }
1064
1065
1066     /**
1067      * Set the specified resource link in the naming context.
1068      *
1069      * @param resourceLink the resource link
1070      */

1071     public void addResourceLink(ContextResourceLink resourceLink) {
1072
1073         // Create a reference to the resource.
1074         Reference ref = new ResourceLinkRef
1075             (resourceLink.getType(), resourceLink.getGlobal(), resourceLink.getFactory(), null);
1076         Iterator<String> i = resourceLink.listProperties();
1077         while (i.hasNext()) {
1078             String key = i.next();
1079             Object val = resourceLink.getProperty(key);
1080             if (val!=null) {
1081                 StringRefAddr refAddr = new StringRefAddr(key, val.toString());
1082                 ref.add(refAddr);
1083             }
1084         }
1085         javax.naming.Context ctx =
1086             "UserTransaction".equals(resourceLink.getName())
1087             ? compCtx : envCtx;
1088         try {
1089             if (log.isDebugEnabled())
1090                 log.debug("  Adding resource link " + resourceLink.getName());
1091             createSubcontexts(envCtx, resourceLink.getName());
1092             ctx.bind(resourceLink.getName(), ref);
1093         } catch (NamingException e) {
1094             log.error(sm.getString("naming.bindFailed", e));
1095         }
1096
1097         ResourceLinkFactory.registerGlobalResourceAccess(
1098                 getGlobalNamingContext(), resourceLink.getName(), resourceLink.getGlobal());
1099     }
1100
1101
1102     private javax.naming.Context getGlobalNamingContext() {
1103         if (container instanceof Context) {
1104             Engine e = (Engine) ((Context) container).getParent().getParent();
1105             Server s = e.getService().getServer();
1106             // When the Service is an embedded Service, there is no Server
1107             if (s != null) {
1108                 return s.getGlobalNamingContext();
1109             }
1110         }
1111         return null;
1112     }
1113
1114
1115     /**
1116      * Remove the specified EJB from the naming context.
1117      *
1118      * @param name the name of the EJB which should be removed
1119      */

1120     public void removeEjb(String name) {
1121
1122         try {
1123             envCtx.unbind(name);
1124         } catch (NamingException e) {
1125             log.error(sm.getString("naming.unbindFailed", name), e);
1126         }
1127
1128     }
1129
1130
1131     /**
1132      * Remove the specified environment entry from the naming context.
1133      *
1134      * @param name the name of the environment entry which should be removed
1135      */

1136     public void removeEnvironment(String name) {
1137
1138         try {
1139             envCtx.unbind(name);
1140         } catch (NamingException e) {
1141             log.error(sm.getString("naming.unbindFailed", name), e);
1142         }
1143
1144     }
1145
1146
1147     /**
1148      * Remove the specified local EJB from the naming context.
1149      *
1150      * @param name the name of the EJB which should be removed
1151      */

1152     public void removeLocalEjb(String name) {
1153
1154         try {
1155             envCtx.unbind(name);
1156         } catch (NamingException e) {
1157             log.error(sm.getString("naming.unbindFailed", name), e);
1158         }
1159
1160     }
1161
1162
1163     /**
1164      * Remove the specified message destination ref from the naming context.
1165      *
1166      * @param name the name of the message destination ref which should be
1167      *             removed
1168      */

1169     public void removeMessageDestinationRef(String name) {
1170
1171         try {
1172             envCtx.unbind(name);
1173         } catch (NamingException e) {
1174             log.error(sm.getString("naming.unbindFailed", name), e);
1175         }
1176
1177     }
1178
1179
1180     /**
1181      * Remove the specified web service from the naming context.
1182      *
1183      * @param name the name of the web service which should be removed
1184      */

1185     public void removeService(String name) {
1186
1187         try {
1188             envCtx.unbind(name);
1189         } catch (NamingException e) {
1190             log.error(sm.getString("naming.unbindFailed", name), e);
1191         }
1192
1193     }
1194
1195
1196     /**
1197      * Remove the specified resource from the naming context.
1198      *
1199      * @param name the name of the resource which should be removed
1200      */

1201     public void removeResource(String name) {
1202
1203         try {
1204             envCtx.unbind(name);
1205         } catch (NamingException e) {
1206             log.error(sm.getString("naming.unbindFailed", name), e);
1207         }
1208
1209         ObjectName on = objectNames.get(name);
1210         if (on != null) {
1211             Registry.getRegistry(nullnull).unregisterComponent(on);
1212         }
1213
1214     }
1215
1216
1217     /**
1218      * Remove the specified resource environment reference from the naming
1219      * context.
1220      *
1221      * @param name the name of the resource environment reference which should
1222      *             be removed
1223      */

1224     public void removeResourceEnvRef(String name) {
1225
1226         try {
1227             envCtx.unbind(name);
1228         } catch (NamingException e) {
1229             log.error(sm.getString("naming.unbindFailed", name), e);
1230         }
1231
1232     }
1233
1234
1235     /**
1236      * Remove the specified resource link from the naming context.
1237      *
1238      * @param name the name of the resource link which should be removed
1239      */

1240     public void removeResourceLink(String name) {
1241
1242         try {
1243             envCtx.unbind(name);
1244         } catch (NamingException e) {
1245             log.error(sm.getString("naming.unbindFailed", name), e);
1246         }
1247
1248         ResourceLinkFactory.deregisterGlobalResourceAccess(getGlobalNamingContext(), name);
1249     }
1250
1251
1252     /**
1253      * Create all intermediate subcontexts.
1254      */

1255     private void createSubcontexts(javax.naming.Context ctx, String name)
1256         throws NamingException {
1257         javax.naming.Context currentContext = ctx;
1258         StringTokenizer tokenizer = new StringTokenizer(name, "/");
1259         while (tokenizer.hasMoreTokens()) {
1260             String token = tokenizer.nextToken();
1261             if ((!token.equals("")) && (tokenizer.hasMoreTokens())) {
1262                 try {
1263                     currentContext = currentContext.createSubcontext(token);
1264                 } catch (NamingException e) {
1265                     // Silent catch. Probably an object is already bound in
1266                     // the context.
1267                     currentContext =
1268                         (javax.naming.Context) currentContext.lookup(token);
1269                 }
1270             }
1271         }
1272     }
1273
1274
1275     /**
1276      * Gets look up reference from resource if exist.
1277      *
1278      * @param resourceBase resource base object
1279      * @return lookup ref
1280      */

1281     private LookupRef lookForLookupRef(ResourceBase resourceBase) {
1282         String lookupName = resourceBase.getLookupName();
1283         if ((lookupName != null && !lookupName.equals(""))) {
1284             return new LookupRef(resourceBase.getType(), lookupName);
1285         }
1286         return null;
1287     }
1288 }
1289