1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.logging.log4j.catalog.api.dao;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URL;
23 import java.net.URLConnection;
24 import java.time.Instant;
25 import java.time.LocalDateTime;
26 import java.time.ZoneId;
27 import java.util.Collection;
28 import java.util.Map;
29
30 import com.fasterxml.jackson.core.JsonFactory;
31 import com.fasterxml.jackson.core.JsonParser;
32 import com.fasterxml.jackson.databind.ObjectMapper;
33 import org.apache.logging.log4j.LogManager;
34 import org.apache.logging.log4j.Logger;
35 import org.apache.logging.log4j.catalog.api.CatalogData;
36 import org.apache.logging.log4j.util.LoaderUtil;
37
38
39
40
41 public class ClassPathCatalogReader extends AbstractCatalogReader {
42
43 private static final Logger LOGGER = LogManager.getLogger(ClassPathCatalogReader.class);
44 private static final String BASEDIR = "baseDir";
45
46 private static final String CATALOG_ATTRIBUTE_NAME = "catalogFile";
47 private static final String DEFAULT_CATALOG_FILE = "catalog.json";
48
49 private final String catalog;
50 private final LocalDateTime lastUpdated;
51
52 public ClassPathCatalogReader(Map<String, String> attributes) throws IOException {
53 String catalogFile = attributes != null ?
54 attributes.getOrDefault(CATALOG_ATTRIBUTE_NAME, DEFAULT_CATALOG_FILE) : DEFAULT_CATALOG_FILE;
55 Collection<URL> catalogs = LoaderUtil.findResources(catalogFile);
56 URL catalogURL;
57 if (catalogs.size() == 0) {
58 LOGGER.error("No catalog named {} could be found on the class path", catalogFile);
59 throw new FileNotFoundException("No catalog named " + catalogFile + " could be found");
60 } else if (catalogs.size() > 1) {
61 catalogURL = catalogs.stream().findFirst().get();
62 LOGGER.warn("Multiple catalogs named {} were found. Using {}", catalogFile, catalogURL.toString());
63 } else {
64 catalogURL = catalogs.stream().findFirst().get();
65 }
66
67 catalog = readCatalog(catalogURL);
68 LocalDateTime localDateTime = null;
69 try {
70 URLConnection connection = catalogURL.openConnection();
71 localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(connection.getLastModified()),
72 ZoneId.systemDefault());
73 } catch (IOException ioe) {
74 LOGGER.warn("Unable to open connection to {}", catalogURL.toString());
75 }
76 lastUpdated = localDateTime;
77 JsonFactory factory = new JsonFactory();
78 factory.enable(JsonParser.Feature.ALLOW_COMMENTS);
79 ObjectMapper objectMapper = new ObjectMapper(factory);
80 catalogData = objectMapper.readValue(catalog, CatalogData.class);
81 }
82
83 private String readCatalog(URL catalogUrl) throws IOException {
84 try (InputStream is = catalogUrl.openStream()) {
85 ByteArrayOutputStream baos = new ByteArrayOutputStream();
86 byte[] buffer = new byte[1024];
87 int length;
88 while ((length = is.read(buffer)) != -1) {
89 baos.write(buffer, 0, length);
90 }
91 return baos.toString("UTF-8");
92 }
93 }
94
95 public ClassPathCatalogReader() throws IOException {
96 this(null);
97 }
98
99 @Override
100 public String readCatalog() {
101 return catalog;
102 }
103
104 @Override
105 public LocalDateTime getLastUpdated() {
106 return lastUpdated;
107 }
108 }