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 }