/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.glowroot.common.config;
import java.util.List;
import java.util.ListIterator;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
public class PermissionParser {
private String permission;
private int index;
private boolean inAgentRollupId;
private boolean inQuotedAgentRollupId;
private final StringBuilder currAgentRollupId = new StringBuilder();
private final List<String> agentRollupIds = Lists.newArrayList();
public PermissionParser(String permission) {
this.permission = permission;
}
public void parse() {
if (permission.equals("agent")) {
return;
}
if (permission.equals("agent:")) {
permission = "agent";
return;
}
if (!permission.startsWith("agent:")) {
return;
}
index = "agent:".length();
while (index < permission.length()) {
readNextChar();
if (!inAgentRollupId && permission.charAt(index - 1) == ':') {
break;
}
}
if (inAgentRollupId) {
// add the last value
agentRollupIds.add(currAgentRollupId.toString());
}
if (permission.length() == index) {
permission = "agent";
} else {
permission = "agent:" + permission.substring(index);
}
}
public List<String> getAgentRollupIds() {
return agentRollupIds;
}
public String getPermission() {
return permission;
}
private void readNextChar() {
char c = permission.charAt(index++);
if (isStartOfValue(c)) {
startValue(c);
} else if (isEndOfValue(c)) {
endValue();
} else if (inQuotedAgentRollupId && c == '\\') {
currAgentRollupId.append(permission.charAt(index++));
} else if (inAgentRollupId) {
currAgentRollupId.append(c);
}
}
private boolean isStartOfValue(char c) {
return !inAgentRollupId && c != ',' && c != ':';
}
private void startValue(char c) {
inAgentRollupId = true;
if (c == '"') {
inQuotedAgentRollupId = true;
} else {
currAgentRollupId.append(c);
}
}
private boolean isEndOfValue(char c) {
return isEndOfQuotedValue(c) || isEndOfNonQuotedValue(c);
}
private void endValue() {
agentRollupIds.add(currAgentRollupId.toString());
inAgentRollupId = false;
inQuotedAgentRollupId = false;
currAgentRollupId.setLength(0);
}
private boolean isEndOfQuotedValue(char c) {
return inQuotedAgentRollupId && c == '"';
}
private boolean isEndOfNonQuotedValue(char c) {
return inAgentRollupId && !inQuotedAgentRollupId && (c == ',' || c == ':');
}
public static String quoteIfNeededAndJoin(List<String> agentRollupIds) {
List<String> quotedIfNeededAgentRollupIds = Lists.newArrayList();
for (String agentRollupId : agentRollupIds) {
if (agentRollupId.indexOf(',') != -1 || agentRollupId.indexOf(':') != -1) {
quotedIfNeededAgentRollupIds.add(
"\"" + agentRollupId.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
} else {
quotedIfNeededAgentRollupIds.add(agentRollupId);
}
}
return Joiner.on(',').join(quotedIfNeededAgentRollupIds);
}
public static boolean upgradeAgentPermissions(List<String> perms) {
boolean hasAgentJvmAll = perms.contains("agent:tool");
boolean upgrade = false;
ListIterator<String> i = perms.listIterator();
while (i.hasNext()) {
String perm = i.next();
if (perm.equals("agent:view")) {
i.set("agent:transaction");
i.add("agent:error");
if (!hasAgentJvmAll) {
// in 0.9.1, agent:view gave access to JVM gauges and environment
i.add("agent:jvm:gauges");
i.add("agent:jvm:environment");
}
upgrade = true;
} else if (perm.equals("agent:tool")) {
i.set("agent:jvm");
upgrade = true;
} else if (perm.startsWith("agent:tool:")) {
i.set("agent:jvm:" + perm.substring("agent:tool:".length()));
upgrade = true;
}
}
if (!upgrade) {
return false;
}
// only apply below updates if upgrading from 0.9.1 to 0.9.2
int configViewIndex = perms.indexOf("agent:config:view");
int configEditIndex = perms.indexOf("agent:config:edit");
if (configViewIndex != -1 && configEditIndex != -1) {
perms.set(configViewIndex, "agent:config");
perms.remove(configEditIndex);
}
return true;
}
}