View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.joran;
15  
16  import ch.qos.logback.core.Context;
17  import ch.qos.logback.core.joran.event.SaxEvent;
18  import ch.qos.logback.core.joran.event.SaxEventRecorder;
19  import ch.qos.logback.core.joran.spi.*;
20  import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
21  import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache;
22  import ch.qos.logback.core.spi.ContextAwareBase;
23  import ch.qos.logback.core.status.StatusUtil;
24  
25  import org.xml.sax.InputSource;
26  
27  import java.io.File;
28  import java.io.FileInputStream;
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.net.URL;
32  import java.net.URLConnection;
33  import java.util.List;
34  
35  import static ch.qos.logback.core.CoreConstants.SAFE_JORAN_CONFIGURATION;
36  
37  public abstract class GenericConfigurator extends ContextAwareBase {
38  
39      private BeanDescriptionCache beanDescriptionCache;
40  
41      protected Interpreter interpreter;
42  
43      public final void doConfigure(URL url) throws JoranException {
44          InputStream in = null;
45          try {
46              informContextOfURLUsedForConfiguration(getContext(), url);
47              URLConnection urlConnection = url.openConnection();
48              // per http://jira.qos.ch/browse/LBCORE-105
49              // per http://jira.qos.ch/browse/LBCORE-127
50              urlConnection.setUseCaches(false);
51  
52              in = urlConnection.getInputStream();
53              doConfigure(in, url.toExternalForm());
54          } catch (IOException ioe) {
55              String errMsg = "Could not open URL [" + url + "].";
56              addError(errMsg, ioe);
57              throw new JoranException(errMsg, ioe);
58          } finally {
59              if (in != null) {
60                  try {
61                      in.close();
62                  } catch (IOException ioe) {
63                      String errMsg = "Could not close input stream";
64                      addError(errMsg, ioe);
65                      throw new JoranException(errMsg, ioe);
66                  }
67              }
68          }
69      }
70  
71      public final void doConfigure(String filename) throws JoranException {
72          doConfigure(new File(filename));
73      }
74  
75      public final void doConfigure(File file) throws JoranException {
76          FileInputStream fis = null;
77          try {
78              URL url = file.toURI().toURL();
79              informContextOfURLUsedForConfiguration(getContext(), url);
80              fis = new FileInputStream(file);
81              doConfigure(fis, url.toExternalForm());
82          } catch (IOException ioe) {
83              String errMsg = "Could not open [" + file.getPath() + "].";
84              addError(errMsg, ioe);
85              throw new JoranException(errMsg, ioe);
86          } finally {
87              if (fis != null) {
88                  try {
89                      fis.close();
90                  } catch (java.io.IOException ioe) {
91                      String errMsg = "Could not close [" + file.getName() + "].";
92                      addError(errMsg, ioe);
93                      throw new JoranException(errMsg, ioe);
94                  }
95              }
96          }
97      }
98  
99      public static void informContextOfURLUsedForConfiguration(Context context, URL url) {
100         ConfigurationWatchListUtil.setMainWatchURL(context, url);
101     }
102 
103     public final void doConfigure(InputStream inputStream) throws JoranException {
104         doConfigure(new InputSource(inputStream));
105     }
106 
107     public final void doConfigure(InputStream inputStream, String systemId) throws JoranException {
108         InputSource inputSource = new InputSource(inputStream);
109         inputSource.setSystemId(systemId);
110         doConfigure(inputSource);
111     }
112 
113     protected BeanDescriptionCache getBeanDescriptionCache() {
114         if (beanDescriptionCache == null) {
115             beanDescriptionCache = new BeanDescriptionCache(getContext());
116         }
117         return beanDescriptionCache;
118     }
119 
120     protected abstract void addInstanceRules(RuleStore rs);
121 
122     protected abstract void addImplicitRules(Interpreter interpreter);
123 
124     protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {
125 
126     }
127 
128     protected ElementPath initialElementPath() {
129         return new ElementPath();
130     }
131 
132     protected void buildInterpreter() {
133         RuleStore rs = new SimpleRuleStore(context);
134         addInstanceRules(rs);
135         this.interpreter = new Interpreter(context, rs, initialElementPath());
136         InterpretationContext interpretationContext = interpreter.getInterpretationContext();
137         interpretationContext.setContext(context);
138         addImplicitRules(interpreter);
139         addDefaultNestedComponentRegistryRules(interpretationContext.getDefaultNestedComponentRegistry());
140     }
141 
142     // this is the most inner form of doConfigure whereto other doConfigure
143     // methods ultimately delegate
144     public final void doConfigure(final InputSource inputSource) throws JoranException {
145 
146         long threshold = System.currentTimeMillis();
147         // if (!ConfigurationWatchListUtil.wasConfigurationWatchListReset(context)) {
148         // informContextOfURLUsedForConfiguration(getContext(), null);
149         // }
150         SaxEventRecorder recorder = new SaxEventRecorder(context);
151         recorder.recordEvents(inputSource);
152         doConfigure(recorder.saxEventList);
153         // no exceptions a this level
154         StatusUtil statusUtil = new StatusUtil(context);
155         if (statusUtil.noXMLParsingErrorsOccurred(threshold)) {
156             addInfo("Registering current configuration as safe fallback point");
157             registerSafeConfiguration(recorder.saxEventList);
158         }
159     }
160 
161     public void doConfigure(final List<SaxEvent> eventList) throws JoranException {
162         buildInterpreter();
163         // disallow simultaneous configurations of the same context
164         synchronized (context.getConfigurationLock()) {
165             interpreter.getEventPlayer().play(eventList);
166         }
167     }
168 
169     /**
170      * Register the current event list in currently in the interpreter as a safe
171      * configuration point.
172      *
173      * @since 0.9.30
174      */
175     public void registerSafeConfiguration(List<SaxEvent> eventList) {
176         context.putObject(SAFE_JORAN_CONFIGURATION, eventList);
177     }
178 
179     /**
180      * Recall the event list previously registered as a safe point.
181      */
182     @SuppressWarnings("unchecked")
183     public List<SaxEvent> recallSafeConfiguration() {
184         return (List<SaxEvent>) context.getObject(SAFE_JORAN_CONFIGURATION);
185     }
186 }