Commit | Line | Data |
---|---|---|
c0e418b5 | 1 | /* |
c0c0989a | 2 | * SPDX-License-Identifier: LGPL-2.1-only |
c0e418b5 | 3 | * |
c0c0989a MJ |
4 | * Copyright (C) 2017 EfficiOS Inc. |
5 | * Copyright (C) 2017 Philippe Proulx <pproulx@efficios.com> | |
c0e418b5 AM |
6 | */ |
7 | ||
8 | package org.lttng.ust.agent; | |
9 | ||
10 | import java.util.regex.Pattern; | |
11 | ||
12 | /** | |
13 | * Class encapsulating an event name from the session daemon, and its | |
14 | * corresponding {@link Pattern}. This allows referring back to the original | |
15 | * event name, for example when we receive a disable command. | |
16 | * | |
17 | * @author Philippe Proulx | |
18 | * @author Alexandre Montplaisir | |
19 | */ | |
20 | class EventNamePattern { | |
21 | ||
22 | private final String originalEventName; | |
23 | ||
24 | /* | |
25 | * Note that two Patterns coming from the exact same String will not be | |
26 | * equals()! As such, it would be confusing to make the pattern part of this | |
27 | * class's equals/hashCode | |
28 | */ | |
29 | private final transient Pattern pattern; | |
30 | ||
31 | public EventNamePattern(String eventName) { | |
32 | if (eventName == null) { | |
33 | throw new IllegalArgumentException(); | |
34 | } | |
35 | ||
36 | originalEventName = eventName; | |
37 | pattern = patternFromEventName(eventName); | |
38 | } | |
39 | ||
40 | public String getEventName() { | |
41 | return originalEventName; | |
42 | } | |
43 | ||
44 | public Pattern getPattern() { | |
45 | return pattern; | |
46 | } | |
47 | ||
48 | @Override | |
49 | public int hashCode() { | |
50 | final int prime = 31; | |
51 | int result = 1; | |
52 | result = prime * result + originalEventName.hashCode(); | |
53 | return result; | |
54 | } | |
55 | ||
56 | @Override | |
57 | public boolean equals(Object obj) { | |
58 | if (this == obj) { | |
59 | return true; | |
60 | } | |
61 | if (obj == null) { | |
62 | return false; | |
63 | } | |
64 | if (getClass() != obj.getClass()) { | |
65 | return false; | |
66 | } | |
67 | EventNamePattern other = (EventNamePattern) obj; | |
68 | if (!originalEventName.equals(other.originalEventName)) { | |
69 | return false; | |
70 | } | |
71 | return true; | |
72 | } | |
73 | ||
74 | private static Pattern patternFromEventName(String eventName) { | |
75 | /* | |
76 | * The situation here is that `\*` means a literal `*` in the event | |
77 | * name, and `*` is a wildcard star. We check the event name one | |
78 | * character at a time and create a list of tokens to be converter to | |
79 | * partial patterns. | |
80 | */ | |
81 | StringBuilder bigBuilder = new StringBuilder("^"); | |
82 | StringBuilder smallBuilder = new StringBuilder(); | |
83 | ||
84 | for (int i = 0; i < eventName.length(); i++) { | |
85 | char c = eventName.charAt(i); | |
86 | ||
87 | switch (c) { | |
88 | case '*': | |
89 | /* Add current quoted builder's string if not empty. */ | |
90 | if (smallBuilder.length() > 0) { | |
91 | bigBuilder.append(Pattern.quote(smallBuilder.toString())); | |
92 | smallBuilder.setLength(0); | |
93 | } | |
94 | ||
95 | /* Append the equivalent regex which is `.*`. */ | |
96 | bigBuilder.append(".*"); | |
97 | continue; | |
98 | ||
99 | case '\\': | |
100 | /* We only escape `*` and `\` here. */ | |
101 | if (i < (eventName.length() - 1)) { | |
102 | char nextChar = eventName.charAt(i + 1); | |
103 | ||
104 | if (nextChar == '*' || nextChar == '\\') { | |
105 | smallBuilder.append(nextChar); | |
106 | } else { | |
107 | smallBuilder.append(c); | |
108 | smallBuilder.append(nextChar); | |
109 | } | |
110 | ||
111 | i++; | |
112 | continue; | |
113 | } | |
114 | break; | |
115 | ||
116 | default: | |
117 | break; | |
118 | } | |
119 | ||
120 | smallBuilder.append(c); | |
121 | } | |
122 | ||
123 | /* Add current quoted builder's string if not empty. */ | |
124 | if (smallBuilder.length() > 0) { | |
125 | bigBuilder.append(Pattern.quote(smallBuilder.toString())); | |
126 | } | |
127 | ||
128 | bigBuilder.append("$"); | |
129 | ||
130 | return Pattern.compile(bigBuilder.toString()); | |
131 | } | |
132 | } |