001    package org.crsh.util;
002    
003    import org.crsh.cli.completers.AbstractPathCompleter;
004    import org.crsh.text.formatter.BindingRenderable;
005    
006    import javax.naming.Binding;
007    import javax.naming.Context;
008    import javax.naming.InitialContext;
009    import javax.naming.NamingEnumeration;
010    import java.util.*;
011    import java.util.regex.Pattern;
012    
013    /** @author <a href="mailto:alain.defrance@exoplatform.com">Alain Defrance</a> */
014    public class JNDIHandler {
015    
016      public static List<BindingRenderable.BindingData> lookup(List<String> filters, String name, Boolean verbose) {
017    
018        Pattern pattern = null;
019        if (name != null) {
020          pattern = Pattern.compile("^" + Utils.globexToRegex(name) + "$");
021        }
022    
023        List<BindingRenderable.BindingData> data = new ArrayList<BindingRenderable.BindingData>();
024    
025        data.addAll(get(filters, pattern, verbose, ""));
026        data.addAll(get(filters, pattern, verbose, "java:/"));
027        data.addAll(get(filters, pattern, verbose, "java:comp/env/jdbc"));
028        data.addAll(get(filters, pattern, verbose, "java:jboss"));
029        data.addAll(get(filters, pattern, verbose, "java:global"));
030        data.addAll(get(filters, pattern, verbose, "java:app"));
031        data.addAll(get(filters, pattern, verbose, "java:module"));
032    
033        return data;
034    
035      }
036    
037      static List<BindingRenderable.BindingData> get(
038          List<String> filters,
039          Pattern pattern,
040          Boolean verbose,
041          String path) {
042    
043        return get(filters, pattern, verbose, path, path, null);
044      }
045    
046      static List<BindingRenderable.BindingData> get(
047          List<String> filters,
048          Pattern pattern,
049          Boolean verbose,
050          String path,
051          String search,
052          Context ctx) {
053    
054        List<BindingRenderable.BindingData> data = new ArrayList<BindingRenderable.BindingData>();
055    
056        try {
057          if (ctx == null) {
058            ctx = new InitialContext();
059          }
060          if (path.length() > 0) {
061            path += "/";
062          }
063    
064          NamingEnumeration<Binding> e = ctx.listBindings(search);
065          while (e.hasMoreElements()) {
066            Binding instance = e.next();
067    
068            String fullName = path + instance.getName();
069    
070            if (
071                filters == null ||
072                    filters.size() == 0 ||
073                    TypeResolver.instanceOf(instance.getObject().getClass(), filters)) {
074              if (pattern == null || pattern.matcher(fullName).find()) {
075                data.add(new BindingRenderable.BindingData(fullName, instance.getClassName(), instance, verbose));
076              }
077            }
078            if (instance.getObject() instanceof Context) {
079              data.addAll(get(filters, pattern, verbose, fullName, "", (Context) instance.getObject()));
080            }
081    
082          }
083    
084        }
085        catch (Exception e) {
086        }
087    
088        return data;
089      }
090    
091      public static class JNDICompleter extends AbstractPathCompleter<String> {
092    
093        private final String[] filters;
094        private List<BindingRenderable.BindingData> bindings;
095    
096        public JNDICompleter(String... filters) {
097          this.filters = filters;
098          bindings = JNDIHandler.lookup(Arrays.asList(filters), null, true);
099        }
100    
101        @Override
102        protected String getCurrentPath() {
103          return "";
104        }
105    
106        @Override
107        protected String getPath(String path) {
108          return path;
109        }
110    
111        @Override
112        protected boolean exists(String path) {
113          if (path.equals("/") || path.endsWith("/")) {
114            return true;
115          } else {
116            for (BindingRenderable.BindingData binding : bindings) {
117              if (binding.name.startsWith(path.substring(1) + "/")) {
118                return true;
119              }
120            }
121          }
122          return false;
123        }
124    
125        @Override
126        protected boolean isDirectory(String path) {
127          if (path.equals("/")) {
128            return true;
129          }
130          if (path.startsWith("/")) {
131            path = path.substring(1);
132          }
133          for (BindingRenderable.BindingData binding : bindings) {
134            if (binding.name.startsWith(path + "/")) {
135              return true;
136            }
137          }
138          return false;
139        }
140    
141        @Override
142        protected boolean isFile(String path) {
143          if (path.equals("/")) {
144            return false;
145          }
146          if (path.startsWith("/")) {
147            path = path.substring(1);
148          }
149          if (path.endsWith("/")) {
150            for (BindingRenderable.BindingData binding : bindings) {
151              if (binding.name.equals(path.substring(0, path.length() - 1))) {
152                return true;
153              }
154            }
155          }
156          return false;
157        }
158    
159        @Override
160        protected Collection<String> getChilren(String path) {
161          List<String> l = new ArrayList<String>();
162          for (BindingRenderable.BindingData binding : bindings) {
163            if (path.equals("/") || binding.name.startsWith(path.substring(1))) {
164              String completion = binding.name.substring(path.substring(1).length());
165              if (completion.startsWith("/")) {
166                completion = completion.substring(1);
167              }
168              l.add(completion);
169            }
170          }
171          return l;
172        }
173    
174        @Override
175        protected String getName(String path) {
176          return path;
177        }
178      }
179    
180    }