1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.audit.catalog;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.concurrent.ConcurrentHashMap;
24
25 import com.fasterxml.jackson.core.JsonFactory;
26 import com.fasterxml.jackson.core.JsonParser;
27 import com.fasterxml.jackson.databind.ObjectMapper;
28
29 import org.apache.logging.log4j.LogManager;
30 import org.apache.logging.log4j.Logger;
31 import org.apache.logging.log4j.audit.exception.AuditException;
32 import org.apache.logging.log4j.audit.util.NamingUtils;
33 import org.apache.logging.log4j.catalog.api.Attribute;
34 import org.apache.logging.log4j.catalog.api.CatalogData;
35 import org.apache.logging.log4j.catalog.api.Event;
36 import org.apache.logging.log4j.catalog.api.CatalogReader;
37 import org.apache.logging.log4j.catalog.api.EventAttribute;
38
39 import static java.util.Collections.emptyList;
40 import static org.apache.logging.log4j.catalog.api.constant.Constants.DEFAULT_CATALOG;
41
42
43
44
45 public class CatalogManagerImpl implements CatalogManager {
46
47 private static Logger logger = LogManager.getLogger(CatalogManagerImpl.class);
48
49 private volatile Map<String, Map<String, CatalogInfo>> infoMap;
50
51 private Map<String, Attribute> requestContextAttributes = new HashMap<>();
52
53 protected final Map<String, Map<String, Attribute>> attributeMap = new ConcurrentHashMap<>();
54
55 private static final String REQCTX = "ReqCtx_";
56
57 protected CatalogData catalogData;
58
59 public CatalogManagerImpl(CatalogReader catalogReader) {
60 try {
61 infoMap = initializeData(catalogReader);
62 } catch (Exception ex) {
63 throw new AuditException("Unable to initialize catalog data", ex);
64 }
65 }
66
67 protected Map<String, Map<String, CatalogInfo>> getInfoMap() {
68 return infoMap;
69 }
70
71 @Override
72 public Event getEvent(String eventName, String catalogId) {
73 CatalogInfo info = getCatalogInfo(eventName, catalogId);
74 return info != null ? info.event : null;
75 }
76
77 @Override
78 public List<String> getRequiredContextAttributes(String eventName, String catalogId) {
79 Map<String, CatalogInfo> catalogMap = infoMap.get(catalogId == null ? DEFAULT_CATALOG : catalogId);
80 return catalogMap != null ? catalogMap.get(eventName).requiredContextAttributes : null;
81 }
82
83 @Override
84 public Map<String, Attribute> getAttributes(String eventName, String catalogId) {
85 Event event = getEvent(eventName, catalogId);
86 if (event == null) {
87 logger.warn("The event named {} could not be found in catalog {}", eventName, catalogId);
88 return null;
89 }
90 List<EventAttribute> eventAttributes = event.getAttributes() == null ? emptyList() : event.getAttributes();
91 Map<String, Attribute> attributes = new HashMap<>(eventAttributes.size());
92 for (EventAttribute eventAttribute : eventAttributes) {
93 Attribute attr = getAttribute(eventAttribute.getName(), event.getCatalogId());
94 if (attr != null) {
95 attributes.put(attr.getName(), attr);
96 }
97 }
98 return attributes;
99 }
100
101 @Override
102 public List<String> getAttributeNames(String eventName, String catalogId) {
103 return infoMap.get(catalogId == null ? DEFAULT_CATALOG : catalogId).get(eventName).attributeNames;
104 }
105
106 @Override
107 public Attribute getAttribute(String name) {
108 Map<String, Attribute> attrMap = attributeMap.get(DEFAULT_CATALOG);
109 return attrMap != null ? attrMap.get(name) : null;
110 }
111
112 public Attribute getAttribute(String name, String catalogId) {
113 Map<String, Attribute> attrMap = attributeMap.get(catalogId);
114 if (attrMap == null || !attrMap.containsKey(name)) {
115 attrMap = attributeMap.get(DEFAULT_CATALOG);
116 }
117 return attrMap != null ? attrMap.get(name) : null;
118 }
119
120 @Override
121 public Map<String, Attribute> getRequestContextAttributes() {
122 return requestContextAttributes;
123 }
124
125 private CatalogInfo getCatalogInfo(String eventName, String catalogId) {
126 Map<String, CatalogInfo> defaultCatalog = infoMap.get(DEFAULT_CATALOG);
127 Map<String, CatalogInfo> catalog = catalogId != null ? infoMap.get(catalogId) : null;
128 return catalog != null && catalog.containsKey(eventName) ? catalog.get(eventName) :
129 defaultCatalog.get(eventName);
130 }
131
132 private Map<String, Map<String, CatalogInfo>> initializeData(CatalogReader catalogReader) throws Exception {
133 JsonFactory factory = new JsonFactory();
134 factory.enable(JsonParser.Feature.ALLOW_COMMENTS);
135 ObjectMapper mapper = new ObjectMapper(factory);
136
137 String catalog = catalogReader.readCatalog();
138 catalogData = mapper.readValue(catalog, CatalogData.class);
139
140 if (catalogData.getAttributes() != null) {
141 for (Attribute attr : catalogData.getAttributes()) {
142 if (attr.isRequestContext()) {
143 requestContextAttributes.put(attr.getName(), attr);
144 }
145 Map<String, Attribute> attrMap = attributeMap.get(attr.getCatalogId());
146 if (attrMap == null) {
147 attrMap = new HashMap<>();
148 attributeMap.put(attr.getCatalogId(), attrMap);
149 }
150 attrMap.put(attr.getName(), attr);
151 }
152 }
153
154 Map<String, Map<String, CatalogInfo>> map = new HashMap<>();
155 map.put(DEFAULT_CATALOG, new HashMap<>());
156 for (Event event : catalogData.getEvents()) {
157 addEntry(map, event);
158 }
159 return map;
160 }
161
162 protected void addEntry(Map<String, Map<String, CatalogInfo>> map, Event event) {
163 CatalogInfo info = new CatalogInfo();
164 info.event = event;
165 String catalogId = event.getCatalogId();
166 if (catalogId != null && catalogId.length() > 0 && !map.containsKey(catalogId)) {
167 map.put(catalogId, new HashMap<>());
168 }
169 List<String> required = new ArrayList<>();
170 List<String> names = new ArrayList<>();
171 info.attributes = new HashMap<>(names.size());
172 if (event.getAttributes() != null) {
173 for (EventAttribute eventAttribute : event.getAttributes()) {
174 String name = eventAttribute.getName();
175 Attribute attribute = getAttribute(name, event.getCatalogId());
176 if (attribute != null) {
177 info.attributes.put(name, attribute);
178 if (name.indexOf('.') != -1) {
179 name = name.replaceAll("\\.", "");
180 }
181 if (name.indexOf('/') != -1) {
182 name = name.replaceAll("/", "");
183 }
184 if (attribute.isRequestContext()) {
185 if (attribute.isRequired()) {
186 if (name.startsWith(REQCTX)) {
187 name = name.substring(REQCTX.length());
188 }
189 required.add(name);
190 }
191 } else {
192 names.add(name);
193 }
194 } else {
195 throw new IllegalStateException("Attribute " + name + " is not defined");
196 }
197 }
198 }
199 info.requiredContextAttributes = required;
200 info.attributeNames = names;
201 Map<String, CatalogInfo> catalogMap = catalogId == null ?
202 map.get(DEFAULT_CATALOG) : map.get(catalogId);
203 catalogMap.put(NamingUtils.getFieldName(event.getName()), info);
204 }
205
206 protected class CatalogInfo {
207 private Event event;
208
209 private List<String> requiredContextAttributes;
210
211 private List<String> attributeNames;
212
213 private Map<String, Attribute> attributes;
214 }
215 }