/**
* Copyright (c) 2014, the Railo Company Ltd.
* Copyright (c) 2015, Lucee Assosication Switzerland
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lucee.runtime.config;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import lucee.commons.io.IOUtil;
import lucee.commons.io.SystemUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.lang.ExceptionUtil;
import lucee.commons.lang.SystemOut;
import lucee.loader.engine.CFMLEngine;
import lucee.runtime.engine.InfoImpl;
import lucee.runtime.osgi.OSGiUtil;
import lucee.runtime.text.xml.XMLUtil;
import org.osgi.framework.Version;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public abstract class XMLConfigFactory {
public static final int NEW_NONE=0;
public static final int NEW_MINOR=1;
public static final int NEW_FRESH=2;
public static final int NEW_FROM4=3;
public static UpdateInfo doNew(CFMLEngine engine, Resource contextDir, boolean readOnly) {
lucee.Info info = engine.getInfo();
try {
String strOldVersion;
final Resource resOldVersion = contextDir.getRealResource("version");
String strNewVersion = info.getVersion() + "-" + info.getRealeaseTime();
// fresh install
if (!resOldVersion.exists()) {
if(!readOnly) {
resOldVersion.createNewFile();
IOUtil.write(resOldVersion, strNewVersion, SystemUtil.getCharset(), false);
}
return UpdateInfo.NEW_FRESH;
}
// changed version
else if (!(strOldVersion=IOUtil.toString(resOldVersion, SystemUtil.getCharset())).equals(strNewVersion)) {
if(!readOnly) IOUtil.write(resOldVersion, strNewVersion, SystemUtil.getCharset(), false);
Version oldVersion = OSGiUtil.toVersion(strOldVersion);
return new UpdateInfo(oldVersion,oldVersion.getMajor()<5?NEW_FROM4:NEW_MINOR);
}
}
catch(Throwable t) {ExceptionUtil.rethrowIfNecessary(t);}
return UpdateInfo.NEW_NONE;
}
public static class UpdateInfo {
public static final UpdateInfo NEW_NONE = new UpdateInfo(XMLConfigWebFactory.NEW_NONE);
public static final UpdateInfo NEW_FRESH = new UpdateInfo(XMLConfigWebFactory.NEW_FRESH);
public final Version oldVersion;
public final int updateType;
public UpdateInfo(int updateType) {
this.oldVersion=null;
this.updateType=updateType;
}
public UpdateInfo(Version oldVersion, int updateType) {
this.oldVersion=oldVersion;
this.updateType=updateType;
}
}
public static void updateRequiredExtension(CFMLEngine engine, Resource contextDir) {
lucee.Info info = engine.getInfo();
try {
Resource res = contextDir.getRealResource("required-extension");
String str = info.getVersion() + "-" + info.getRealeaseTime();
if(!res.exists())res.createNewFile();
IOUtil.write(res, str, SystemUtil.getCharset(), false);
}
catch(Throwable t) {ExceptionUtil.rethrowIfNecessary(t);}
}
public static boolean isRequiredExtension(CFMLEngine engine, Resource contextDir) {
lucee.Info info = engine.getInfo();
try {
Resource res = contextDir.getRealResource("required-extension");
if(!res.exists()) return false;
String writtenVersion=IOUtil.toString(res,SystemUtil.getCharset());
String currVersion = info.getVersion() + "-" + info.getRealeaseTime();
return writtenVersion.equals(currVersion);
}
catch(Throwable t) {ExceptionUtil.rethrowIfNecessary(t);}
return false;
}
/**
* load XML Document from XML File
*
* @param xmlFile
* XML File to read
* @return returns the Document
* @throws SAXException
* @throws IOException
*/
static Document loadDocument(Resource xmlFile) throws SAXException, IOException {
InputStream is = null;
try {
return _loadDocument(is = IOUtil.toBufferedInputStream(xmlFile.getInputStream()));
}
finally {
IOUtil.closeEL(is);
}
}
static Document loadDocumentCreateIfFails(Resource configFile, String type) throws SAXException, IOException {
try {
InputStream is = null;
try {
return _loadDocument(is = IOUtil.toBufferedInputStream(configFile.getInputStream()));
}
finally {
IOUtil.closeEL(is);
}
}
catch (Exception e) {
// rename buggy config files
if (configFile.exists()) {
SystemOut.printDate(SystemUtil.getPrintWriter(SystemUtil.OUT), "config file " + configFile + " was not valid and has been replaced");
int count = 1;
Resource bugFile;
Resource configDir = configFile.getParentResource();
while ((bugFile = configDir.getRealResource("lucee-"+type+"." + (count++) + ".buggy")).exists()) {
}
IOUtil.copy(configFile, bugFile);
configFile.delete();
}
createConfigFile(type, configFile);
return loadDocument(configFile);
}
}
/**
* creates the Config File, if File not exist
*
* @param xmlName
* @param configFile
* @throws IOException
*/
static void createConfigFile(String xmlName, Resource configFile) throws IOException {
configFile.createFile(true);
createFileFromResource("/resource/config/" + xmlName + ".xml", configFile.getAbsoluteResource());
}
/**
* load XML Document from XML File
*
* @param is
* InoutStream to read
* @return returns the Document
* @throws SAXException
* @throws IOException
*/
private static Document _loadDocument(InputStream is) throws SAXException, IOException {
InputSource source = new InputSource(is);
return XMLUtil.parse(source, null, false);
}
/**
* return first direct child Elements of a Element with given Name
*
* @param parent
* @param nodeName
* @return matching children
*/
static Element getChildByName(Node parent, String nodeName) {
return getChildByName(parent, nodeName, false);
}
static Element getChildByName(Node parent, String nodeName, boolean insertBefore) {
return getChildByName(parent, nodeName, insertBefore, false);
}
static Element getChildByName(Node parent, String nodeName, boolean insertBefore, boolean doNotCreate) {
if (parent == null)
return null;
NodeList list = parent.getChildNodes();
int len = list.getLength();
for (int i = 0; i < len; i++) {
Node node = list.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equalsIgnoreCase(nodeName)) {
return (Element) node;
}
}
if (doNotCreate)
return null;
Element newEl = parent.getOwnerDocument().createElement(nodeName);
if (insertBefore)
parent.insertBefore(newEl, parent.getFirstChild());
else
parent.appendChild(newEl);
return newEl;
}
/**
* return all direct child Elements of a Element with given Name
*
* @param parent
* @param nodeName
* @return matching children
*/
static Element[] getChildren(Node parent, String nodeName) {
if (parent == null)
return new Element[0];
NodeList list = parent.getChildNodes();
int len = list.getLength();
ArrayList<Element> rtn = new ArrayList<Element>();
for (int i = 0; i < len; i++) {
Node node = list.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equalsIgnoreCase(nodeName)) {
rtn.add((Element)node);
}
}
return rtn.toArray(new Element[rtn.size()]);
}
/**
* creates a File and his content froma a resurce
*
* @param resource
* @param file
* @param password
* @throws IOException
*/
static void createFileFromResource(String resource, Resource file, String password) throws IOException {
SystemOut.printDate(SystemUtil.getPrintWriter(SystemUtil.OUT), "write file:" + file);
file.delete();
InputStream is = InfoImpl.class.getResourceAsStream(resource);
if(is==null) throw new IOException("file ["+resource+"] does not exist.");
file.createNewFile();
IOUtil.copy(is, file, true);
}
/**
* creates a File and his content froma a resurce
*
* @param resource
* @param file
* @throws IOException
*/
static void createFileFromResource(String resource, Resource file) throws IOException {
createFileFromResource(resource, file, null);
}
public static void createFileFromResourceEL(String resource, Resource file) {
try {
createFileFromResource(resource, file, null);
}
catch (Throwable e) {
ExceptionUtil.rethrowIfNecessary(e);
SystemOut.printDate(ExceptionUtil.getStacktrace(e, true), SystemUtil.ERR);
}
}
static void create(String srcPath, String[] names, Resource dir, boolean doNew) {
for(int i=0;i<names.length;i++){
create(srcPath, names[i], dir, doNew);
}
}
static Resource create(String srcPath, String name, Resource dir, boolean doNew) {
if(!dir.exists())dir.mkdirs();
Resource f = dir.getRealResource(name);
if (!f.exists() || doNew)
XMLConfigFactory.createFileFromResourceEL(srcPath+name, f);
return f;
}
static void delete(Resource dbDir, String[] names) {
for(int i=0;i<names.length;i++){
delete(dbDir, names[i]);
}
}
static void delete(Resource dbDir, String name) {
Resource f = dbDir.getRealResource(name);
if (f.exists()) {
SystemOut.printDate(SystemUtil.getPrintWriter(SystemUtil.OUT), "delete file:" + f);
f.delete();
}
}
}