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.cli.completers;
020    
021    import org.crsh.cli.descriptor.ParameterDescriptor;
022    import org.crsh.cli.spi.Completer;
023    import org.crsh.cli.spi.Completion;
024    import org.crsh.cli.type.ValueType;
025    
026    import javax.management.MBeanServer;
027    import javax.management.ObjectName;
028    import java.lang.management.ManagementFactory;
029    import java.util.HashSet;
030    import java.util.Hashtable;
031    import java.util.LinkedHashSet;
032    import java.util.Set;
033    
034    /**
035     * @author Julien Viet
036     */
037    public class ObjectNameCompleter implements Completer {
038    
039      private static String[] parseKeyValue(String s) {
040        int eq = s.indexOf('=');
041        if (eq == -1) {
042          return new String[]{s, null};
043        } else {
044          return new String[]{s.substring(0, eq), s.substring(eq + 1, s.length())};
045        }
046      }
047    
048      @Override
049      public Completion complete(ParameterDescriptor parameter, String prefix) throws Exception {
050        if (parameter.getType() == ValueType.OBJECT_NAME) {
051          MBeanServer server = ManagementFactory.getPlatformMBeanServer();
052          int colon = prefix.indexOf(':');
053          if (colon == -1) {
054            Completion.Builder b = new Completion.Builder(prefix);
055            LinkedHashSet<String> domains = new LinkedHashSet<String>();
056            for (ObjectName name : server.queryNames(null, null)) {
057              domains.add(name.getDomain());
058            }
059            for (String domain : domains) {
060              if (domain.startsWith(prefix)) {
061                b.add(domain.substring(prefix.length()) + ":", false);
062              }
063            }
064            return b.build();
065          } else {
066            String domain = prefix.substring(0, colon);
067            String rest = prefix.substring(colon + 1);
068            int prev = 0;
069            Hashtable<String, String> keyValues = new Hashtable<String, String>();
070            while (true) {
071              int next = rest.indexOf(',', prev);
072              if (next == -1) {
073                String[] keyValue = parseKeyValue(rest.substring(prev));
074                Set<ObjectName> completions = new HashSet<ObjectName>();
075                for (ObjectName name : server.queryNames(null, null)) {
076                  if (name.getDomain().equals(domain) && name.getKeyPropertyList().entrySet().containsAll(keyValues.entrySet())) {
077                    completions.add(name);
078                  }
079                }
080                if (keyValue[1] == null) {
081                  Completion.Builder b = new Completion.Builder(keyValue[0]);
082                  for (ObjectName name : completions) {
083                    for (String key : name.getKeyPropertyList().keySet()) {
084                      if (!keyValues.containsKey(key) && key.startsWith(keyValue[0])) {
085                        b.add(key.substring(keyValue[0].length()) + "=", false);
086                      }
087                    }
088                  }
089                  return b.build();
090                } else {
091                  Completion.Builder b = new Completion.Builder(keyValue[1]);
092                  for (ObjectName completion : completions) {
093                    String value = completion.getKeyProperty(keyValue[0]);
094                    if (value != null && value.startsWith(keyValue[1])) {
095                      Hashtable<String, String> a = completion.getKeyPropertyList();
096                      a.remove(keyValue[0]);
097                      a.keySet().removeAll(keyValues.keySet());
098                      if (a.isEmpty()) {
099                        b.add(value.substring(keyValue[1].length()), true);
100                      } else {
101                        b.add(value.substring(keyValue[1].length()) + ",", false);
102                      }
103                    }
104                  }
105                  return b.build();
106                }
107              } else {
108                String[] keyValue = parseKeyValue(rest.substring(prev, next));
109                keyValues.put(keyValue[0], keyValue[1]);
110                prev = next + 1;
111              }
112            }
113          }
114        } else {
115          return Completion.create();
116        }
117      }
118    }