View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * 
4    * Copyright (C) 1999-2006, QOS.ch
5    * 
6    * This library is free software, you can redistribute it and/or modify it under
7    * the terms of the GNU Lesser General Public License as published by the Free
8    * Software Foundation.
9    */
10  package ch.qos.logback.core.joran.action;
11  
12  import java.io.FileInputStream;
13  import java.io.IOException;
14  import java.io.InputStream;
15  import java.net.MalformedURLException;
16  import java.net.URL;
17  import java.util.List;
18  
19  import org.xml.sax.Attributes;
20  
21  import ch.qos.logback.core.joran.event.SaxEvent;
22  import ch.qos.logback.core.joran.event.SaxEventRecorder;
23  import ch.qos.logback.core.joran.spi.ActionException;
24  import ch.qos.logback.core.joran.spi.InterpretationContext;
25  import ch.qos.logback.core.joran.spi.JoranException;
26  import ch.qos.logback.core.util.Loader;
27  import ch.qos.logback.core.util.OptionHelper;
28  
29  public class IncludeAction extends Action {
30  
31    private static final String INCLUDED_TAG = "included";
32    private static final String FILE_ATTR = "file";
33    private static final String URL_ATTR = "url";
34    private static final String RESOURCE_ATTR = "resource";
35    
36  
37    private String attributeInUse;
38  
39    @Override
40    public void begin(InterpretationContext ec, String name, Attributes attributes)
41        throws ActionException {
42  
43      SaxEventRecorder recorder = new SaxEventRecorder();
44      
45      this.attributeInUse = null;
46  
47      if (!checkAttributes(attributes)) {
48        return;
49      }
50  
51      InputStream in = getInputStream(ec, attributes);
52  
53      try {
54        if (in != null) {
55          parseAndRecord(in, recorder);
56          in.close();
57        }
58      } catch (JoranException e) {
59        addError("Error while parsing  " + attributeInUse, e);
60      } catch (IOException e) {
61        // called if in.close did not work
62      }
63  
64      // remove the <included> tag from the beginning and </included> from the end
65      trimHeadAndTail(recorder);
66      
67      ec.getJoranInterpreter().addEventsDynamically(recorder.saxEventList);
68    }
69  
70    private boolean checkAttributes(Attributes attributes) {
71      String fileAttribute = attributes.getValue(FILE_ATTR);
72      String urlAttribute = attributes.getValue(URL_ATTR);
73      String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
74  
75      int count = 0;
76  
77      if (!OptionHelper.isEmpty(fileAttribute)) {
78        count++;
79      }
80      if (!OptionHelper.isEmpty(urlAttribute)) {
81        count++;
82      }
83      if (!OptionHelper.isEmpty(resourceAttribute)) {
84        count++;
85      }
86  
87      if (count == 0) {
88        addError("One of \"path\", \"resource\" or \"url\" attributes must be set.");
89        return false;
90      } else if (count > 1) {
91        addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set.");
92        return false;
93      } else if (count == 1) {
94        return true;
95      }
96      throw new IllegalStateException("Count value [" + count
97          + "] is not expected");
98    }
99  
100   private InputStream getInputStreamByFilePath(String pathToFile) {
101     try {
102       return new FileInputStream(pathToFile);
103     } catch (IOException ioe) {
104       String errMsg = "File [" + pathToFile + "] does not exist.";
105       addError(errMsg, ioe);
106       return null;
107     }
108   }
109 
110   private InputStream getInputStreamByUrl(String urlAttribute) {
111     URL url;
112     try {
113       url = new URL(urlAttribute);
114     } catch (MalformedURLException mue) {
115       String errMsg = "URL [" + urlAttribute + "] is not well formed.";
116       addError(errMsg, mue);
117       return null;
118     }
119     return openURL(url);
120   }
121 
122   InputStream openURL(URL url) {
123     try {
124       return url.openStream();
125     } catch (IOException e) {
126       String errMsg = "Failed to open [" + url.toString() + "]";
127       addError(errMsg, e);
128       return null;
129     }
130   }
131 
132   private InputStream getInputStreamByResource(String resourceAttribute) {
133     URL url = Loader.getResourceBySelfClassLoader(resourceAttribute);
134     if (url == null) {
135       String errMsg = "Could not find resource corresponding to ["
136           + resourceAttribute + "]";
137       addError(errMsg);
138       return null;
139     }
140     return openURL(url);
141   }
142 
143   InputStream getInputStream(InterpretationContext ec, Attributes attributes) {
144     String fileAttribute = attributes.getValue(FILE_ATTR);
145     String urlAttribute = attributes.getValue(URL_ATTR);
146     String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
147 
148     if (!OptionHelper.isEmpty(fileAttribute)) {
149       attributeInUse = ec.subst(fileAttribute);
150       return getInputStreamByFilePath(attributeInUse);
151     }
152 
153     if (!OptionHelper.isEmpty(urlAttribute)) {
154       attributeInUse = ec.subst(urlAttribute);
155       return getInputStreamByUrl(attributeInUse);
156     }
157 
158     if (!OptionHelper.isEmpty(resourceAttribute)) {
159       attributeInUse = ec.subst(resourceAttribute);
160       return getInputStreamByResource(attributeInUse);
161     }
162     // given previous checkAttributes() check we cannot reach this line
163     throw new IllegalStateException("A input stream should have been returned");
164   }
165 
166   private void trimHeadAndTail(SaxEventRecorder recorder) {
167     // Let's remove the two <included> events before
168     // adding the events to the player.
169     
170     List<SaxEvent> saxEventList = recorder.saxEventList;
171     
172     if (saxEventList.size() == 0) {
173       return;
174     }
175     
176     SaxEvent first = saxEventList.get(0);
177     if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) {
178       saxEventList.remove(0);
179     }
180 
181     SaxEvent last = saxEventList.get(recorder.saxEventList.size() - 1);
182     if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) {
183       saxEventList.remove(recorder.saxEventList.size() - 1);
184     }
185   }
186 
187   private void parseAndRecord(InputStream inputSource, SaxEventRecorder recorder) throws JoranException {
188     recorder.setContext(context);
189     recorder.recordEvents(inputSource);
190   }
191 
192   @Override
193   public void end(InterpretationContext ec, String name) throws ActionException {
194     // do nothing
195   }
196 
197 }