/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.tools.ant;
import org.apache.tools.ant.BuildException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.hyperic.util.StringUtil;
/**
* An ant task to combine multiple DBSetup XML files into
* a single file.
*/
public class DBSetupCombiner extends BaseFileSetTask {
private File destFile = null;
private String order = null;
private String name = null;
private String notice = null;
private boolean debug = false;
public DBSetupCombiner() {}
public void setDebug(boolean debug) {
this.debug = debug;
}
public void setDestfile(File destFile) {
this.destFile = destFile;
}
public void setOrder(String order) {
this.order = order;
}
public void setName(String name) {
this.name = name;
}
public void setNotice(String notice) {
this.notice = notice;
}
public void execute() throws BuildException {
validateAttributes();
List filesToCombine;
PrintWriter pw = null;
// First get all the files, unsorted
filesToCombine = getAllFiles();
// Reorder according to user-specified order
if ( order != null ) {
List orderList = StringUtil.explode(order, ", \n\r\t");
Collections.sort(filesToCombine,
new OrderComparator(orderList));
}
try {
// Open the destFile
pw = new PrintWriter(new FileWriter(destFile));
// Write the prefix
writePrefix(pw);
// Concatenate the files
catFiles(filesToCombine, pw);
// Write the suffix
writeSuffix(pw);
} catch ( IOException ioe ) {
throw new BuildException("Error combining files: " + ioe);
} finally {
if ( pw != null ) {
try { pw.close(); } catch ( Exception e ) {}
}
}
}
/**
* This method concatenates a series of files to a single
* destination, stripping out XML prefixes and top-level elements.
*
* @param files A list of the files to be concatenated
* @param pw Destination for writes.
*/
private void catFiles(List files,
PrintWriter pw) throws IOException {
BufferedReader in = null;
try {
for (int i=0; i<files.size(); i++) {
File currentFile = (File) files.get(i);
String filename = currentFile.getName();
in = new BufferedReader
(new InputStreamReader
(new FileInputStream(currentFile)));
if (debug) pw.println("<!-- BEGIN: " + filename + " -->");
String line;
String tline;
while ((line = in.readLine()) != null) {
tline = line.trim();
// Skip XML directive lines, and top-level element lines
if ( tline.startsWith("<?") ||
tline.startsWith("</Covalent.DBSetup>") ) {
continue;
} else if ( tline.startsWith("<Covalent.DBSetup") ) {
while ( tline.indexOf(">") == -1 ) {
tline = in.readLine();
if ( tline == null ) break;
}
continue;
}
pw.println(line);
}
in.close();
in = null;
if (debug) pw.println("<!-- END: " + filename + " -->");
}
} finally {
// Close resources.
if (in != null) {
try { in.close(); } catch (Exception e) {}
}
}
}
protected void validateAttributes () throws BuildException {
super.validateAttributes();
if (destFile == null) {
throw new BuildException("DBSetupCombiner: No 'destFile' attribute "
+ "specified.");
}
if (name == null) {
throw new BuildException("DBSetupCombiner: No 'name' attribute "
+ "specified.");
}
if (notice == null) {
throw new BuildException("DBSetupCombiner: No 'notice' attribute "
+ "specified.");
}
}
public static final String XML_PREFIX
= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
private void writePrefix ( PrintWriter pw ) throws IOException {
pw.println(XML_PREFIX);
pw.println("<Covalent.DBSetup "
+ "name=\"" + this.name + "\" "
+ "notice=\"" + this.notice + "\">");
}
private void writeSuffix ( PrintWriter pw ) throws IOException {
pw.println("</Covalent.DBSetup>");
}
class OrderComparator implements Comparator {
public List order;
public OrderComparator (List order) {this.order = order;}
public int compare (Object o1, Object o2) {
// Make sure they are both files, otherwise we'll just say they're
// always "equal"
if ( o1 instanceof File && o2 instanceof File ) {
// Get basenames for files
String f1 = ((File) o1).getName();
String f2 = ((File) o2).getName();
// Find the index at which this basename occurs in the order
int idx1 = findIndex(f1);
int idx2 = findIndex(f2);
// If one was found and the other was not, the one
// that was found is automatically "less than" the one
// that was not.
if (idx1 == -1 && idx2 != -1) {
return Integer.MAX_VALUE;
} else if (idx2 == -1 && idx1 != -1) {
return Integer.MIN_VALUE;
} else {
// If they were both found, or if they were both -1,
// just return the difference
return (idx1 - idx2);
}
}
return 0;
}
private int findIndex ( String fname ) {
int indexOfLongestMatch = -1;
int lengthOfLongestMatch = 0;
String possibleMatch;
int possibleMatchLen;
for ( int i=0; i<order.size(); i++ ) {
possibleMatch = order.get(i).toString();
possibleMatchLen = possibleMatch.length();
if (fname.startsWith(possibleMatch) &&
possibleMatchLen > lengthOfLongestMatch) {
indexOfLongestMatch = i;
lengthOfLongestMatch = possibleMatchLen;
}
}
return indexOfLongestMatch;
}
public boolean equals(Object o) {
if (o instanceof OrderComparator) {
OrderComparator oc = (OrderComparator) o;
return (this.order == null && oc.order == null) ||
this.order.equals(oc.order);
}
return false;
}
}
}