001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.monitoring.reporting.web.plugin.jmx;
018
019 import org.apache.commons.codec.binary.Base64;
020 import org.apache.commons.lang3.StringEscapeUtils;
021
022 import java.util.Collection;
023 import java.util.Collections;
024 import java.util.Comparator;
025 import java.util.Map;
026 import java.util.TreeMap;
027
028 public class JMXNode {
029 private final String name;
030 private final Map<Key, JMXNode> children = new TreeMap<Key, JMXNode>();
031 private String base64 = null;
032
033 public JMXNode(final String name) {
034 this.name = name;
035 }
036
037 public static void addNode(final JMXNode rootNode, final String domain, final String props) {
038 final Map<String, String> properties = new TreeMap<String, String>(new JMXPropertiesComparator(props));
039 for (final String k : props.split(",")) {
040 final String[] kv = k.split("=");
041 if (kv.length < 2) {
042 properties.put(StringEscapeUtils.escapeHtml4(kv[0]), "");
043 } else {
044 properties.put(StringEscapeUtils.escapeHtml4(kv[0]), StringEscapeUtils.escapeHtml4(kv[1]));
045 }
046 }
047
048 final Key rootKey = new Key("domain", domain);
049 JMXNode node = rootNode.children.get(rootKey);
050 if (node == null) {
051 node = new JMXNode(domain);
052 rootNode.children.put(rootKey, node);
053 }
054
055 for (final Map.Entry<String, String> entry : properties.entrySet()) {
056 final Key key = new Key(entry.getKey(), entry.getValue());
057 final String value = entry.getValue();
058
059 JMXNode child = node.children.get(key);
060 if (child == null) {
061 child = new JMXNode(value);
062 node.children.put(key, child);
063 }
064
065 node = child;
066 }
067
068 node.base64 = Base64.encodeBase64String((domain + ":" + props).getBytes());
069 }
070
071 public String getName() {
072 return name;
073 }
074
075 public boolean isLeaf() {
076 return base64 != null;
077 }
078
079 public String getBase64() {
080 return base64;
081 }
082
083 public Collection<JMXNode> getChildren() {
084 return Collections.unmodifiableCollection(children.values());
085 }
086
087 protected static class Key implements Comparable<Key> {
088 private final String key;
089 private final String value;
090
091 public Key(final String key, final String value) {
092 this.key = key;
093 this.value = value;
094 }
095
096 @Override
097 public boolean equals(final Object o) {
098 if (this == o) {
099 return true;
100 }
101 if (o == null || Key.class != o.getClass()) {
102 return false;
103 }
104
105 final Key key1 = Key.class.cast(o);
106 return key.equals(key1.key) && value.equals(key1.value);
107 }
108
109 @Override
110 public int hashCode() {
111 int result = key.hashCode();
112 result = 31 * result + value.hashCode();
113 return result;
114 }
115
116 @Override
117 public int compareTo(final Key o) {
118 if (equals(o)) {
119 return 0;
120 }
121
122 final int keys = key.compareTo(o.key);
123 if (keys != 0) {
124 return keys;
125 }
126 return value.compareTo(o.value);
127 }
128
129 @Override
130 public String toString() {
131 return "{" + key + " = " + value + '}';
132 }
133 }
134
135 protected static class JMXPropertiesComparator implements Comparator<String> {
136 private final String properties;
137
138 protected JMXPropertiesComparator(final String props) {
139 properties = props;
140 }
141
142 @Override
143 public int compare(final String o1, final String o2) {
144 if (o1.equals(o2)) {
145 return 0;
146 }
147
148 if ("type".equals(o1)) {
149 return -1;
150 }
151 if ("type".equals(o2)) {
152 return 1;
153 }
154 if ("j2eeType".equals(o1)) {
155 return -1;
156 }
157 if ("j2eeType".equals(o2)) {
158 return 1;
159 }
160
161 return properties.indexOf(o1 + "=") - properties.indexOf(o2 + "=");
162 }
163 }
164 }