package org.azzyzt.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class VersionBumper {
private static final String DOTTED_VERSION_EXPR = "\\d+(\\.\\d+){2}";
private static final String VERSION_SUFFIX_GENERIC = "qualifier";
private static final String VERSION_SUFFIX_FQ_EXPR = "\\.(\\d{12}|qualifier)";
private static final String VERSION_SUFFIX_GENERIC_EXPR = "\\."+VERSION_SUFFIX_GENERIC;
private static final String SITE_TARGET_XPATH = "/site/feature";
private static final String[] SITE_TARGET_ATTRIBUTES = {
"url",
"version",
};
private static final String FEATURE_TARGET_XPATH = "/feature";
private static final String[] FEATURE_TARGET_ATTRIBUTES = {
"version",
};
private static final String MANIFEST_LINE_PREFIX = "Bundle-Version: ";
private static final String MANIFEST_LINE_REGEXP = "^"+MANIFEST_LINE_PREFIX+DOTTED_VERSION_EXPR+"."+VERSION_SUFFIX_GENERIC;
private static final String VIKI_LINE_PREFIX = "#VAR: version=";
private static final String VIKI_LINE_REGEXP = "^"+VIKI_LINE_PREFIX+DOTTED_VERSION_EXPR;
private static final String AZZYZT_RELEASE_LINE_PREFIX = "public static final String AZZYZT_RELEASE = \"";
private static final String AZZYZT_RELEASE_LINE_REGEXP = "^\\s*"+AZZYZT_RELEASE_LINE_PREFIX+DOTTED_VERSION_EXPR+"\";";
private static final String[] SITES = {
"azzyzt_generic/site.xml",
};
private static final String[] FEATURES = {
"org.azzyzt.jee.mwe.generic.feature/feature.xml",
};
private static final String[] MANIFESTS = {
"org.azzyzt.jee.runtime.site.generic.fragment/META-INF/MANIFEST.MF",
"org.azzyzt.jee.tools.common.plugin/META-INF/MANIFEST.MF",
"org.azzyzt.jee.tools.mwe.projectgen.plugin/META-INF/MANIFEST.MF",
"org.azzyzt.jee.tools.project.plugin/META-INF/MANIFEST.MF",
};
private static final String VIKI_DIR = "doc";
private static final String VIKI_EXT = ".viki";
private static final String AZZYZT_RELEASE_JAVA_SOURCE =
"org.azzyzt.jee.tools.mwe.projectgen.plugin/src/org/azzyzt/jee/tools/mwe/projectgen/ProjectGen.java";
private static final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
public static void main(String[] args) {
if (args.length != 1) {
usageAndExit();
}
String newVersion = args[0];
if (!newVersion.matches("^"+DOTTED_VERSION_EXPR+"$")) {
usageAndExit();
}
bumpTo(newVersion);
}
private static void bumpTo(String newVersion) {
String qualifiedVersion = newVersion+"."+VERSION_SUFFIX_GENERIC;
for (String site : SITES) {
bumpXMLTo(site, SITE_TARGET_XPATH, SITE_TARGET_ATTRIBUTES, VERSION_SUFFIX_FQ_EXPR, qualifiedVersion);
}
for (String feature : FEATURES) {
bumpXMLTo(feature, FEATURE_TARGET_XPATH, FEATURE_TARGET_ATTRIBUTES, VERSION_SUFFIX_GENERIC_EXPR, qualifiedVersion);
}
for (String manifest : MANIFESTS) {
bumpTextTo(manifest, MANIFEST_LINE_REGEXP, MANIFEST_LINE_PREFIX+qualifiedVersion, 1);
}
bumpTextsTo(VIKI_DIR, VIKI_EXT, VIKI_LINE_REGEXP, VIKI_LINE_PREFIX+newVersion, 1);
bumpTextTo(AZZYZT_RELEASE_JAVA_SOURCE, AZZYZT_RELEASE_LINE_REGEXP, " "+AZZYZT_RELEASE_LINE_PREFIX+newVersion+"\";", 1);
}
private static void bumpXMLTo(String filename, String xpathExpression, String[] targetAttributes, String suffix, String newVersion) {
try {
Document doc = openAsDOM(filename);
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList) xpath.evaluate(
xpathExpression, doc, XPathConstants.NODESET
);
int nodeCount = nodes.getLength();
for (int i = 0; i < nodeCount; i++) {
Node node = nodes.item(i);
NamedNodeMap attributes = node.getAttributes();
for (String attributeName : targetAttributes) {
Node attribute = attributes.getNamedItem(attributeName);
replaceFqVersion(attribute, newVersion, suffix);
}
}
writeAsXML(doc, filename);
} catch (Exception e) {
reportError(filename, newVersion, e);
}
}
private static void bumpTextTo(String filename, String regexp, String replacement, int numberOfMatchesNeeded)
{
StringBuffer sb = new StringBuffer();
try {
BufferedReader reader =
new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
String line;
int matches = 0;
while ((line = reader.readLine()) != null) {
if (matches < numberOfMatchesNeeded && line.matches(regexp)) {
matches++;
line = line.replaceFirst(regexp, replacement);
}
sb.append(line);
sb.append("\n");
}
reader.close();
writeFile(sb, filename);
} catch (IOException e) {
reportError(filename, regexp, e);
}
}
private static void bumpTextsTo(String dirname, String extension, String regexp, String replacement, int i) {
File dir = new File(dirname);
String[] filenames = dir.list();
for (String filename : filenames) {
if (filename.endsWith(extension)) {
bumpTextTo(dirname+File.separator+filename, regexp, replacement, i);
}
}
}
private static void replaceFqVersion(Node n, String version, String suffix) {
String value = n.getNodeValue().toString();
value = value.replaceFirst(DOTTED_VERSION_EXPR + suffix, version);
n.setNodeValue(value);
}
private static Document openAsDOM(String filename)
throws SAXException, IOException, ParserConfigurationException
{
File fXmlFile = new File(filename);
DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
Document doc = docBuilder.parse(fXmlFile);
return doc;
}
private static void writeAsXML(Document doc, String filename)
throws TransformerException, FileNotFoundException
{
System.out.println("Writing "+filename);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new FileOutputStream(filename));
transformer.transform(source, result);
System.out.println("Done");
}
private static void writeFile(StringBuffer sb, String filename)
throws IOException
{
System.out.println("Writing "+filename);
FileWriter writer = new FileWriter(filename);
writer.write(sb.toString());
writer.close();
System.out.println("Done");
}
private static void usageAndExit() {
System.err.println("usage: VersionBumper <x.y.z>");
System.exit(1);
}
private static void reportError(String filename, String newVersion, Exception e) {
e.printStackTrace();
System.err.println("Bumping failed: "+filename+" "+newVersion);
}
}