/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2013, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.core.joran.action;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import org.xml.sax.Attributes;
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 abstract class AbstractIncludeAction extends Action {
private static final String FILE_ATTR = "file";
private static final String URL_ATTR = "url";
private static final String RESOURCE_ATTR = "resource";
private static final String OPTIONAL_ATTR = "optional";
private String attributeInUse;
private boolean optional;
private URL urlInUse;
public URL getUrl() {
return urlInUse;
}
abstract protected void processInclude(InterpretationContext ic, URL url) throws JoranException;
protected void handleError(String message, Exception e) {
addError(message, e);
}
@Override
public void begin(InterpretationContext ec, String name, Attributes attributes)
throws ActionException {
this.attributeInUse = null;
this.optional = OptionHelper.toBoolean(attributes.getValue(OPTIONAL_ATTR), false);
if (!checkAttributes(attributes)) {
return;
}
try {
URL url = getInputURL(ec, attributes);
if (url != null) {
processInclude(ec, url);
}
} catch (JoranException e) {
handleError("Error while parsing " + attributeInUse, e);
}
}
protected void close(InputStream in) {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
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) {
handleError(String.format("One of \"%1$s\", \"%2$s\" or \"%3$s\" attributes must be set.", FILE_ATTR, RESOURCE_ATTR, URL_ATTR), null);
return false;
} else if (count > 1) {
handleError(String.format("Only one of \"%1$s\", \"%2$s\" or \"%3$s\" attributes should be set.", FILE_ATTR, RESOURCE_ATTR, URL_ATTR), null);
return false;
} else if (count == 1) {
return true;
}
throw new IllegalStateException("Count value [" + count
+ "] is not expected");
}
private URL attributeToURL(String urlAttribute) {
try {
URL url = new URL(urlAttribute);
// Test URL connection to make sure it points to something real.
// If it fails, we'll hit the IOException.
InputStream stream = url.openStream();
stream.close();
stream = null;
return url;
} catch (MalformedURLException mue) {
if (!optional) {
String errMsg = "URL [" + urlAttribute + "] is not well formed.";
handleError(errMsg, mue);
}
} catch (IOException e) {
if (!optional) {
String errMsg = "URL [" + urlAttribute + "] cannot be opened.";
handleError(errMsg, e);
}
}
return null;
}
private URL resourceAsURL(String resourceAttribute) {
URL url = Loader.getResourceBySelfClassLoader(resourceAttribute);
if (url == null) {
if (!optional) {
String errMsg = "Could not find resource corresponding to ["
+ resourceAttribute + "]";
handleError(errMsg, null);
}
return null;
} else
return url;
}
private URL filePathAsURL(String path) {
File file = new File(path);
if (!file.exists() || !file.isFile()) {
if (!optional) {
handleError("File does not exist [" + path + "]", new FileNotFoundException(path));
}
return null;
}
URI uri = file.toURI();
try {
return uri.toURL();
} catch (MalformedURLException e) {
// impossible to get here
e.printStackTrace();
return null;
}
}
protected String getAttributeInUse() {
return this.attributeInUse;
}
protected boolean isOptional() {
return this.optional;
}
private URL getInputURL(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)) {
this.attributeInUse = ec.subst(fileAttribute);
return filePathAsURL(attributeInUse);
}
if (!OptionHelper.isEmpty(urlAttribute)) {
this.attributeInUse = ec.subst(urlAttribute);
return attributeToURL(attributeInUse);
}
if (!OptionHelper.isEmpty(resourceAttribute)) {
this.attributeInUse = ec.subst(resourceAttribute);
return resourceAsURL(attributeInUse);
}
// given previous checkAttributes() check we cannot reach this line
throw new IllegalStateException("A URL stream should have been returned");
}
@Override
public void end(InterpretationContext ec, String name) throws ActionException {
// do nothing
}
}