View Javadoc
1   /*
2    * Copyright 2001-2005 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * Reads the catalog from the local file system.
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 }