1   package org.mortbay.jetty.plus.naming;
2   
3   
4   
5   
6   import java.util.ArrayList;
7   import java.util.List;
8   
9   import javax.naming.Context;
10  import javax.naming.InitialContext;
11  
12  import javax.naming.Binding;
13  import javax.naming.LinkRef;
14  import javax.naming.Name;
15  import javax.naming.NameNotFoundException;
16  import javax.naming.NameParser;
17  import javax.naming.NamingEnumeration;
18  
19  import javax.naming.NamingException;
20  
21  import org.mortbay.log.Log;
22  import org.mortbay.naming.NamingUtil;
23  
24  
25  public class NamingEntryUtil
26  {
27   
28      /**
29       * Check to see if there is a mapping for a local resource name from
30       * web.xml. A mapping links up a name as referenced in web.xml
31       * with a name in the environment, represented as an 
32       * org.mortbay.jetty.plus.naming.Link object, stored in jndi.
33       * 
34       * @param localName
35       * @return
36       * @throws NamingException
37       */
38      public static String getMappedName (String localName)
39      throws NamingException
40      {
41          if (localName==null||"".equals(localName))
42              return null;
43          
44         NamingEntry ne = lookupNamingEntry(localName);
45         if (ne==null)
46             return null;
47         
48         if (ne instanceof Link)
49             return (String)((Link)ne).getObjectToBind();
50         
51         return null;
52      }
53      
54      /**
55       * Link a name in a webapps java:/comp/evn namespace to a pre-existing
56       * resource. The pre-existing resource can be either in the webapp's
57       * namespace, or in the container's namespace. Webapp's namespace takes
58       * precedence over the global namespace (to allow for overriding).
59       * 
60       * @param asName the name to bind as
61       * @param mappedName the name from the environment to link to asName
62       * @param namingEntryType
63       * @throws NamingException
64       */
65      public static void bindToENC (String asName, String mappedName)
66      throws NamingException
67      {  
68          if (asName==null||asName.trim().equals(""))
69              throw new NamingException ("No name for NamingEntry");
70  
71          if (mappedName==null || "".equals(mappedName))
72              mappedName=asName;
73          
74          //locally scoped entries take precedence over globally scoped entries of the same name
75          NamingEntry entry = lookupNamingEntry (mappedName);
76          
77          if (entry!=null)
78              entry.bindToENC(asName);
79          else
80          {
81              //No NamingEntry configured in environment, perhaps there is just an Object bound into this webapp's java:comp/env we can
82              //link to
83              try
84              {
85                  InitialContext ic = new InitialContext();
86                  Context envContext = (Context)ic.lookup("java:comp/env");
87                  envContext.lookup(mappedName);
88  
89                  if (!mappedName.equals(asName))
90                      NamingUtil.bind(envContext, asName, new LinkRef("."+mappedName));   
91              }
92              catch (NamingException e)
93              {
94                  throw new NameNotFoundException("No resource to bind matching name="+mappedName);
95              }
96          }
97      }
98  
99      
100     
101  
102     
103     /**
104      * Find a NamingEntry instance. 
105      * 
106      * First the webapp's naming space is searched, and then
107      * the container's.
108      * 
109      * @param jndiName name to lookup
110      * @return
111      * @throws NamingException
112      */
113     public static NamingEntry lookupNamingEntry (String jndiName)
114     throws NamingException
115     {
116         //locally scoped entries take precedence over globally scoped entries of the same name
117         NamingEntry entry = null;
118         InitialContext ic = new InitialContext();
119         try
120         {
121             entry = (NamingEntry)lookupNamingEntry ((Context)ic.lookup("java:comp/env"), jndiName);
122         }
123         catch (NameNotFoundException e)
124         {
125             try
126             {
127                 entry = (NamingEntry)lookupNamingEntry (ic, jndiName);
128             }
129             catch (NameNotFoundException ee)
130             {
131             }
132         }
133 
134         return entry;
135     }
136 
137     
138 
139   
140   
141     
142     /**
143      * Find a NamingEntry.
144      * 
145      * @param context the context to search
146      * @param clazz the type of the entry (ie subclass of NamingEntry)
147      * @param jndiName the name of the class instance
148      * @return
149      * @throws NamingException
150      */
151     public static Object lookupNamingEntry (Context context,  String jndiName)
152     throws NamingException
153     {
154         NameParser parser = context.getNameParser("");    
155         Name namingEntryName = NamingEntry.makeNamingEntryName(parser, jndiName);
156         
157         return context.lookup(namingEntryName.toString());
158     }
159     
160     
161     
162     /** 
163      * Get all NameEntries of a certain type in either the local or global
164      * namespace.
165      * 
166      * @param scopeType local or global
167      * @param clazz the type of the entry
168      * @return
169      * @throws NamingException
170      */
171     public static List lookupNamingEntries (int scopeType, Class clazz)
172     throws NamingException
173     {
174         ArrayList list = new ArrayList();
175         switch (scopeType)
176         {
177             case NamingEntry.SCOPE_CONTAINER:
178             {
179                 lookupNamingEntries(list, new InitialContext(), EnvEntry.class);
180                 break;
181             }
182             case NamingEntry.SCOPE_WEBAPP:
183             {
184                 //WARNING: you can only look up local scope if you are indeed in the scope
185                 InitialContext ic = new InitialContext();
186                 lookupNamingEntries(list, (Context)ic.lookup("java:comp/env"), EnvEntry.class);
187                 break;
188             }
189         }
190         return list;
191     }
192     
193     
194     
195     /**
196      * Build up a list of NamingEntry objects that are of a specific type.
197      * 
198      * @param list
199      * @param context
200      * @param clazz
201      * @return
202      * @throws NamingException
203      */
204     private static List lookupNamingEntries (List list, Context context, Class clazz)
205     throws NamingException
206     {
207         try
208         {
209             NamingEnumeration nenum = context.listBindings("");
210             while (nenum.hasMoreElements())
211             {
212                 Binding binding = (Binding)nenum.next();
213                 if (binding.getObject() instanceof Context)
214                     lookupNamingEntries (list, (Context)binding.getObject(), clazz);
215                 else if (clazz.isInstance(binding.getObject()))
216                   list.add(binding.getObject());
217             }
218         }
219         catch (NameNotFoundException e)
220         {
221             Log.debug("No entries of type "+clazz.getName()+" in context="+context);
222         }
223 
224         return list;
225     }
226 
227 }