/**
* Logback: the reliable, generic, fast and flexible logging framework.
*
* Copyright (C) 1999-2006, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
package ch.qos.logback.core.joran.action;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.xml.sax.Attributes;
import ch.qos.logback.core.joran.event.SaxEvent;
import ch.qos.logback.core.joran.event.SaxEventRecorder;
import ch.qos.logback.core.joran.spi.ActionException;
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.Loader;
import ch.qos.logback.core.util.OptionHelper;
public class IncludeAction extends Action {
private static final String INCLUDED_TAG = "included";
private static final String FILE_ATTR = "file";
private static final String URL_ATTR = "url";
private static final String RESOURCE_ATTR = "resource";
private String attributeInUse;
@Override
public void begin(InterpretationContext ec, String name, Attributes attributes)
throws ActionException {
SaxEventRecorder recorder = new SaxEventRecorder();
this.attributeInUse = null;
if (!checkAttributes(attributes)) {
return;
}
InputStream in = getInputStream(ec, attributes);
try {
if (in != null) {
parseAndRecord(in, recorder);
in.close();
}
} catch (JoranException e) {
addError("Error while parsing " + attributeInUse, e);
} catch (IOException e) {
// called if in.close did not work
}
// remove the <included> tag from the beginning and </included> from the end
trimHeadAndTail(recorder);
ec.getJoranInterpreter().addEventsDynamically(recorder.saxEventList);
}
private boolean checkAttributes(Attributes attributes) {
String fileAttribute = attributes.getValue(FILE_ATTR);
String urlAttribute = attributes.getValue(URL_ATTR);
String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
int count = 0;
if (!OptionHelper.isEmpty(fileAttribute)) {
count++;
}
if (!OptionHelper.isEmpty(urlAttribute)) {
count++;
}
if (!OptionHelper.isEmpty(resourceAttribute)) {
count++;
}
if (count == 0) {
addError("One of \"path\", \"resource\" or \"url\" attributes must be set.");
return false;
} else if (count > 1) {
addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set.");
return false;
} else if (count == 1) {
return true;
}
throw new IllegalStateException("Count value [" + count
+ "] is not expected");
}
private InputStream getInputStreamByFilePath(String pathToFile) {
try {
return new FileInputStream(pathToFile);
} catch (IOException ioe) {
String errMsg = "File [" + pathToFile + "] does not exist.";
addError(errMsg, ioe);
return null;
}
}
private InputStream getInputStreamByUrl(String urlAttribute) {
URL url;
try {
url = new URL(urlAttribute);
} catch (MalformedURLException mue) {
String errMsg = "URL [" + urlAttribute + "] is not well formed.";
addError(errMsg, mue);
return null;
}
return openURL(url);
}
InputStream openURL(URL url) {
try {
return url.openStream();
} catch (IOException e) {
String errMsg = "Failed to open [" + url.toString() + "]";
addError(errMsg, e);
return null;
}
}
private InputStream getInputStreamByResource(String resourceAttribute) {
URL url = Loader.getResourceBySelfClassLoader(resourceAttribute);
if (url == null) {
String errMsg = "Could not find resource corresponding to ["
+ resourceAttribute + "]";
addError(errMsg);
return null;
}
return openURL(url);
}
InputStream getInputStream(InterpretationContext ec, Attributes attributes) {
String fileAttribute = attributes.getValue(FILE_ATTR);
String urlAttribute = attributes.getValue(URL_ATTR);
String resourceAttribute = attributes.getValue(RESOURCE_ATTR);
if (!OptionHelper.isEmpty(fileAttribute)) {
attributeInUse = ec.subst(fileAttribute);
return getInputStreamByFilePath(attributeInUse);
}
if (!OptionHelper.isEmpty(urlAttribute)) {
attributeInUse = ec.subst(urlAttribute);
return getInputStreamByUrl(attributeInUse);
}
if (!OptionHelper.isEmpty(resourceAttribute)) {
attributeInUse = ec.subst(resourceAttribute);
return getInputStreamByResource(attributeInUse);
}
// given previous checkAttributes() check we cannot reach this line
throw new IllegalStateException("A input stream should have been returned");
}
private void trimHeadAndTail(SaxEventRecorder recorder) {
// Let's remove the two <included> events before
// adding the events to the player.
List<SaxEvent> saxEventList = recorder.saxEventList;
if (saxEventList.size() == 0) {
return;
}
SaxEvent first = saxEventList.get(0);
if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) {
saxEventList.remove(0);
}
SaxEvent last = saxEventList.get(recorder.saxEventList.size() - 1);
if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) {
saxEventList.remove(recorder.saxEventList.size() - 1);
}
}
private void parseAndRecord(InputStream inputSource, SaxEventRecorder recorder) throws JoranException {
recorder.setContext(context);
recorder.recordEvents(inputSource);
}
@Override
public void end(InterpretationContext ec, String name) throws ActionException {
// do nothing
}
}