import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* The singleton manager of {@link IContextInfoRetriever} objects.
private static final String SHARED_LIBRARY_NAME = "lttng-ust-context-jni";
+ private static final Pattern VALID_CONTEXT_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_\\.]+$");
+
private static ContextInfoManager instance;
private final Map<String, IContextInfoRetriever> contextInfoRetrievers = new ConcurrentHashMap<String, IContextInfoRetriever>();
private final Map<String, Long> contextInforRetrieverRefs = new HashMap<String, Long>();
+ /**
+ * Lock used to keep the two maps above in sync when retrievers are
+ * registered or unregistered.
+ */
private final Object retrieverLock = new Object();
/** Singleton class, constructor should not be accessed directly */
*/
public boolean registerContextInfoRetriever(String retrieverName, IContextInfoRetriever contextInfoRetriever) {
synchronized (retrieverLock) {
+ if (!validateRetrieverName(retrieverName)) {
+ return false;
+ }
+
if (contextInfoRetrievers.containsKey(retrieverName)) {
/*
* There is already a retriever registered with that name,
* was none
*/
public IContextInfoRetriever getContextInfoRetriever(String retrieverName) {
+ /*
+ * Note that this method does not take the retrieverLock, it lets
+ * concurrent threads access the ConcurrentHashMap directly.
+ *
+ * It's fine for a get() to happen during a registration or
+ * unregistration, it's first-come-first-serve.
+ */
return contextInfoRetrievers.get(retrieverName);
}
+
+ /**
+ * Validate that the given retriever name contains only the allowed
+ * characters, which are alphanumerical characters, period "." and
+ * underscore "_". The name must also not start with a number.
+ */
+ private static boolean validateRetrieverName(String contextName) {
+ if (contextName.isEmpty()) {
+ return false;
+ }
+
+ /* First character must not be a number */
+ if (Character.isDigit(contextName.charAt(0))) {
+ return false;
+ }
+
+ /* Validate the other characters of the string */
+ Matcher matcher = VALID_CONTEXT_NAME_PATTERN.matcher(contextName);
+ return matcher.matches();
+ }
}