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 */
019package org.crsh.cli.completers;
020
021import org.crsh.cli.descriptor.ParameterDescriptor;
022import org.crsh.cli.spi.Completer;
023import org.crsh.cli.spi.Completion;
024import org.crsh.cli.type.ValueType;
025
026import javax.management.MBeanServer;
027import javax.management.ObjectName;
028import java.lang.management.ManagementFactory;
029import java.util.HashSet;
030import java.util.Hashtable;
031import java.util.LinkedHashSet;
032import java.util.Set;
033
034/**
035 * @author Julien Viet
036 */
037public 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}