001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    package org.crsh.cmdline.completers;
020    
021    import java.util.HashSet;
022    import java.util.Set;
023    
024    import javax.naming.InitialContext;
025    import javax.naming.NameClassPair;
026    import javax.naming.NamingEnumeration;
027    import javax.naming.NamingException;
028    
029    import org.crsh.cmdline.ParameterDescriptor;
030    import org.crsh.cmdline.spi.Completer;
031    import org.crsh.cmdline.spi.ValueCompletion;
032    
033    public class JNDICompleter implements Completer {
034            
035            /**
036             * Create a list of context name to search in JNDI, e.g :contextName ["java:jboss/datasources", "",...]
037       * This list contains standard names to help search.
038             */
039            private static HashSet<String> initJndicontextNames() {
040        HashSet<String> contextNames = new HashSet<String>();
041                    contextNames.add("java:jboss/");
042                    contextNames.add("java:comp/env/jdbc");
043                    contextNames.add("java:/");
044                    contextNames.add("");
045        return contextNames;
046            }       
047            
048            
049            public ValueCompletion complete(ParameterDescriptor<?> parameter,
050                            String prefix) throws Exception {
051                    if (null == prefix) {
052                            prefix = "";
053                    }
054                    return getJndiList(prefix);
055            }
056    
057            /**
058             * Search JNDI Path in Context and put the result in ValueCompletion.
059             * 
060             * @return ValueCompletion
061             */
062            ValueCompletion getJndiList(String prefix) {
063        HashSet<String> contextNames = initJndicontextNames();
064        if (prefix != null) {
065          contextNames.add(prefix);
066        }
067        ValueCompletion completions = new ValueCompletion();
068        for (String contextName : contextNames) {
069    
070                            if (!contextName.endsWith("/")) {
071                                    contextName = contextName + "/";
072                            }
073    
074                            try {
075                                    InitialContext ctx = new InitialContext();
076                                    NamingEnumeration<NameClassPair> list = ctx.list(contextName);
077                                    while (list.hasMore()) {
078                                            NameClassPair nc = list.next();
079                                            if (null == nc) {
080                                                    continue;
081                                            }
082                                            String jndiPath = getJndiPath(contextName, nc.getName(), prefix);
083                                            if (jndiPath != null) {
084                                                    completions.put(jndiPath, false);
085                                            }
086    
087                                    }
088                            } catch (NamingException e1) {
089                                    // We display nothing if there is no data source
090                            }
091                    }
092                    return completions;
093            }
094    
095            /**
096             * Make JndiPath String.
097             * 
098             * @param contextName String (e.g:java:jboss/)
099             * @param ncName (e.g:datasources)
100             * @return String (e.g:java:jboss/datasources)
101             */
102            public String getJndiPath(String contextName, String ncName, String prefix) {
103                    String result;
104                    if ((null == contextName) || (null == ncName) || (null == prefix)) {
105                            throw new IllegalArgumentException("Argument(s) must not be null");
106                    }
107    
108                    if (ncName.isEmpty()) {
109                            result = contextName;
110                    } else {
111                            result = contextName + ncName;
112                    }
113    
114                    if (!prefix.isEmpty()) {
115                            final int prefixSize = prefix.length();
116                            final int resultSize = result.length();
117                            String str = null;
118    
119                            if (result.startsWith(prefix)) {
120                                    if ((prefixSize > 0) && (resultSize > prefixSize)) {
121                                            str = result.substring(prefixSize);
122                                    }
123                            } else if (prefix.startsWith(result)) {
124                                    if ((resultSize > 0) && (prefixSize < resultSize)) {
125                                            str = prefix.substring(resultSize);
126                                    }
127                            } else {
128                                    str = null;
129                            }
130                            result = str;
131                    }
132                    return result;
133            }       
134    }