View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, 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 java.io.File;
17  import java.io.FileInputStream;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.net.URL;
21  import java.net.URLConnection;
22  import java.util.List;
23  
24  import static ch.qos.logback.core.CoreConstants.SAFE_JORAN_CONFIGURATION;
25  
26  import ch.qos.logback.core.Context;
27  import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil;
28  import ch.qos.logback.core.status.StatusChecker;
29  import org.xml.sax.InputSource;
30  
31  import ch.qos.logback.core.joran.event.SaxEvent;
32  import ch.qos.logback.core.joran.event.SaxEventRecorder;
33  import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
34  import ch.qos.logback.core.joran.spi.InterpretationContext;
35  import ch.qos.logback.core.joran.spi.Interpreter;
36  import ch.qos.logback.core.joran.spi.JoranException;
37  import ch.qos.logback.core.joran.spi.Pattern;
38  import ch.qos.logback.core.joran.spi.RuleStore;
39  import ch.qos.logback.core.joran.spi.SimpleRuleStore;
40  import ch.qos.logback.core.spi.ContextAwareBase;
41  
42  public abstract class GenericConfigurator extends ContextAwareBase {
43  
44    protected Interpreter interpreter;
45  
46    public final void doConfigure(URL url) throws JoranException {
47      try {
48        informContextOfURLUsedForConfiguration(getContext(), url);
49        URLConnection urlConnection = url.openConnection();
50        // per http://jira.qos.ch/browse/LBCORE-105
51        // per http://jira.qos.ch/browse/LBCORE-127
52        urlConnection.setUseCaches(false);
53  
54        InputStream in = urlConnection.getInputStream();
55        doConfigure(in);
56        in.close();
57      } catch (IOException ioe) {
58        String errMsg = "Could not open URL [" + url + "].";
59        addError(errMsg, ioe);
60        throw new JoranException(errMsg, ioe);
61      }
62    }
63  
64    public final void doConfigure(String filename) throws JoranException {
65      doConfigure(new File(filename));
66    }
67  
68    public final void doConfigure(File file) throws JoranException {
69      FileInputStream fis = null;
70      try {
71        informContextOfURLUsedForConfiguration(getContext(), file.toURI().toURL());
72        fis = new FileInputStream(file);
73        doConfigure(fis);
74      } catch (IOException ioe) {
75        String errMsg = "Could not open [" + file.getPath() + "].";
76        addError(errMsg, ioe);
77        throw new JoranException(errMsg, ioe);
78      } finally {
79        if (fis != null) {
80          try {
81            fis.close();
82          } catch (java.io.IOException ioe) {
83            String errMsg = "Could not close [" + file.getName() + "].";
84            addError(errMsg, ioe);
85            throw new JoranException(errMsg, ioe);
86          }
87        }
88      }
89    }
90  
91    public static void informContextOfURLUsedForConfiguration(Context context, URL url) {
92      ConfigurationWatchListUtil.setMainWatchURL(context, url);
93    }
94  
95    public final void doConfigure(InputStream inputStream) throws JoranException {
96      doConfigure(new InputSource(inputStream));
97    }
98  
99    protected abstract void addInstanceRules(RuleStore rs);
100 
101   protected abstract void addImplicitRules(Interpreter interpreter);
102 
103   protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {
104 
105   }
106 
107   protected Pattern initialPattern() {
108     return new Pattern();
109   }
110 
111   protected void buildInterpreter() {
112     RuleStore rs = new SimpleRuleStore(context);
113     addInstanceRules(rs);
114     this.interpreter = new Interpreter(context, rs, initialPattern());
115     InterpretationContext ec = interpreter.getInterpretationContext();
116     ec.setContext(context);
117     addImplicitRules(interpreter);
118     addDefaultNestedComponentRegistryRules(ec.getDefaultNestedComponentRegistry());
119   }
120 
121   // this is the most inner form of doConfigure whereto other doConfigure
122   // methods ultimately delegate
123   public final void doConfigure(final InputSource inputSource)
124           throws JoranException {
125 
126     long threshold = System.currentTimeMillis();
127     if (!ConfigurationWatchListUtil.wasConfigurationWatchListReset(context)) {
128       informContextOfURLUsedForConfiguration(getContext(), null);
129     }
130     SaxEventRecorder recorder = new SaxEventRecorder();
131     recorder.setContext(context);
132     recorder.recordEvents(inputSource);
133     doConfigure(recorder.saxEventList);
134     // no exceptions a this level
135     StatusChecker statusChecker = new StatusChecker(context);
136     if(statusChecker.noXMLParsingErrorsOccurred(threshold)) {
137       addInfo("Registering current configuration as safe fallback point");
138       registerSafeConfiguration();
139     }
140   }
141 
142   public void doConfigure(final List<SaxEvent> eventList)
143           throws JoranException {
144     buildInterpreter();
145     // disallow simultaneous configurations of the same context
146     synchronized (context.getConfigurationLock()) {
147       interpreter.getEventPlayer().play(eventList);
148     }
149   }
150 
151   /**
152    * Register the current event list in currently in the interpreter as a safe
153    * configuration point.
154    *
155    * @since 0.9.30
156    */
157   public void registerSafeConfiguration() {
158     context.putObject(SAFE_JORAN_CONFIGURATION, interpreter.getEventPlayer().getCopyOfPlayerEventList());
159   }
160 
161   /**
162    * Recall the event list previously registered as a safe point.
163    */
164   public List<SaxEvent> recallSafeConfiguration() {
165     return (List<SaxEvent>) context.getObject(SAFE_JORAN_CONFIGURATION);
166   }
167 }