View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.util;
18  
19  import java.lang.reflect.Constructor;
20  import java.lang.reflect.InvocationTargetException;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Objects;
24  
25  import org.apache.logging.log4j.Logger;
26  import org.apache.logging.log4j.core.config.Configuration;
27  import org.apache.logging.log4j.core.config.ConfigurationFileWatcher;
28  import org.apache.logging.log4j.core.config.ConfigurationListener;
29  import org.apache.logging.log4j.core.config.Reconfigurable;
30  import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
31  import org.apache.logging.log4j.core.config.plugins.util.PluginType;
32  import org.apache.logging.log4j.status.StatusLogger;
33  
34  /**
35   * Creates Watchers of various types.
36   */
37  public class WatcherFactory {
38  
39      private static Logger LOGGER = StatusLogger.getLogger();
40      private static PluginManager pluginManager = new PluginManager(Watcher.CATEGORY);
41  
42      private static volatile WatcherFactory factory = null;
43  
44      private final Map<String, PluginType<?>> plugins;
45  
46      private WatcherFactory(List<String> packages) {
47          pluginManager.collectPlugins(packages);
48          plugins = pluginManager.getPlugins();
49      }
50  
51      public static WatcherFactory getInstance(List<String> packages) {
52          if (factory == null) {
53              synchronized (pluginManager) {
54                  if (factory == null) {
55                      factory = new WatcherFactory(packages);
56                  }
57              }
58          }
59          return factory;
60      }
61  
62      @SuppressWarnings("unchecked")
63      public Watcher newWatcher(Source source, final Configuration configuration, final Reconfigurable reconfigurable,
64          final List<ConfigurationListener> configurationListeners, long lastModifiedMillis) {
65          if (source.getFile() != null) {
66              return new ConfigurationFileWatcher(configuration, reconfigurable, configurationListeners,
67                  lastModifiedMillis);
68          } else {
69              String name = source.getURI().getScheme();
70              PluginType<?> pluginType = plugins.get(name);
71              if (pluginType != null) {
72                  return instantiate(name, (Class<? extends Watcher>) pluginType.getPluginClass(), configuration,
73                      reconfigurable, configurationListeners, lastModifiedMillis);
74              }
75              LOGGER.info("No Watcher plugin is available for protocol '{}'", name);
76              return null;
77          }
78      }
79  
80      public static <T extends Watcher> T instantiate(String name, final Class<T> clazz,
81          final Configuration configuration, final Reconfigurable reconfigurable,
82          final List<ConfigurationListener> listeners, long lastModifiedMillis) {
83          Objects.requireNonNull(clazz, "No class provided");
84          try {
85              Constructor<T> constructor = clazz
86                  .getConstructor(Configuration.class, Reconfigurable.class, List.class, long.class);
87              return constructor.newInstance(configuration, reconfigurable, listeners, lastModifiedMillis);
88          } catch (NoSuchMethodException ex) {
89              throw new IllegalArgumentException("No valid constructor for Watcher plugin " + name, ex);
90          } catch (final LinkageError | InstantiationException e) {
91              // LOG4J2-1051
92              // On platforms like Google App Engine and Android, some JRE classes are not supported: JMX, JNDI, etc.
93              throw new IllegalArgumentException(e);
94          } catch (final IllegalAccessException e) {
95              throw new IllegalStateException(e);
96          } catch (final InvocationTargetException e) {
97              Throwables.rethrow(e.getCause());
98              throw new InternalError("Unreachable");
99          }
100     }
101 }