/*******************************************************************************
* Copyright 2010 Simon Mieth
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.kabeja.ant;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Ant;
public class BlockTask extends Ant {
protected final static String SEPARATOR = ",";
protected String blockDirectory;
protected String target = "dist";
public void setBlockDir(String blockdir) {
this.blockDirectory = blockdir;
}
public void setTarget(String target) {
this.target = target;
}
public void execute() throws BuildException {
File f = new File(this.blockDirectory);
if (!f.isAbsolute()) {
f = new File(this.getProject().getBaseDir(), this.blockDirectory);
}
File[] dirs = f.listFiles();
Map blocks = new HashMap();
for (int i = 0; i < dirs.length; i++) {
if (dirs[i].isDirectory()) {
File buildFile = new File(dirs[i], "build.xml");
if (buildFile.exists()) {
log("Setup block:" + dirs[i].getName());
Block b = setupBlock(dirs[i], buildFile);
blocks.put(b.getName(), b);
} else {
log("Omit module dir:" + dirs[i].getName()
+ " not build.xml found");
}
}
}
// setup the properties
getProject().setUserProperty("kabeja.home",
getProject().getBaseDir().getAbsolutePath());
List buildOrder = resolveDependency(blocks);
log("Build " + buildOrder.size() + " blocks in the following order");
Iterator i = buildOrder.iterator();
while (i.hasNext()) {
Block b = (Block) i.next();
log("Block:" + b);
}
buildBlocks(buildOrder);
// log(this.getProject().getBaseDir().getAbsolutePath());
}
public String getTaskName() {
return super.getTaskName();
}
protected Block setupBlock(File dir, File buildFile) throws BuildException {
Hashtable props = getProject().getProperties();
Block b = new Block(dir.getName(), buildFile.getAbsolutePath());
if (props.containsKey(("block." + dir.getName() + ".dependency"))) {
String dep = (String) props.get("block." + dir.getName()
+ ".dependency");
handleDependency(dep, b);
}
if (props.containsKey("block." + dir.getName())) {
b.setEnabled(Boolean.valueOf(
(((String) props.get("block." + dir.getName())).trim()))
.booleanValue());
} else {
log("Block:" + dir.getName() + " not configured.");
}
return b;
}
protected void handleDependency(String dependency, Block block) {
if (dependency.length() > 0) {
StringTokenizer st = new StringTokenizer(dependency, SEPARATOR);
while (st.hasMoreTokens()) {
String dep = st.nextToken();
block.addDependency(dep.trim());
}
}
}
protected List resolveDependency(Map blocks) {
List buildOrder = new ArrayList();
Set inserted = new HashSet();
Iterator i = blocks.values().iterator();
while (i.hasNext()) {
Block b = (Block) i.next();
if (b.isEnabled()) {
Iterator di = resolveDependency(b, blocks).iterator();
while (di.hasNext()) {
String block = (String) di.next();
if (inserted.contains(block)) {
log("omit Block:" + block + " inserted berfore");
} else {
buildOrder.add(blocks.get(block));
inserted.add(block);
log("Add block:" + block + " for dependency of "
+ b.getName());
}
}
if (!inserted.contains(b.getName())) {
buildOrder.add(b);
inserted.add(b.getName());
}
}
}
return buildOrder;
}
protected List resolveDependency(Block b, Map blocks) {
List list = new ArrayList();
log("Resolve dependency for:" + b.getName());
Iterator i = b.getDependencies().iterator();
while (i.hasNext()) {
String dependency = ((String) i.next()).trim();
Block dep = (Block) blocks.get(dependency.trim());
List blocksBefore = resolveDependency(dep, blocks);
Iterator di = blocksBefore.iterator();
while (di.hasNext()) {
String name = (String) di.next();
if (name.equals(b.getName())) {
throw new BuildException("Unresolved Dependency Block:"
+ b.getName() + " depends on:" + dependency
+ " which depends on:" + b.getName()
+ ", fix the dependency");
} else {
list.add(name);
}
}
list.add(dependency);
}
return list;
}
protected void buildBlocks(List blocks) {
Iterator i = blocks.iterator();
while (i.hasNext()) {
Block b = (Block) i.next();
if (b.isEnabled()) {
File f = new File(b.getBuildFile());
setAntfile(b.getBuildFile());
setDir(f.getParentFile());
super.setTarget(this.target);
log("Process block:" + b.getName() + " Target:" + this.target);
super.execute();
} else {
log("Omit block:" + b.getName());
}
}
}
private class Block {
String name;
String buildFile;
Set dependency = new HashSet();
boolean build;
public Block(String name, String buildfile) {
this.name = name;
this.buildFile = buildfile;
}
public void addDependency(String dep) {
this.dependency.add(dep);
}
public boolean dependsOn(String name) {
return this.dependency.contains(name);
}
public boolean hasDependency() {
return this.dependency.size() > 0;
}
public String getName() {
return name;
}
public String getBuildFile() {
return buildFile;
}
public boolean isEnabled() {
return this.build;
}
public void setEnabled(boolean b) {
this.build = b;
}
public Set getDependencies() {
return this.dependency;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(this.name);
if (this.dependency.size() > 0) {
buf.append("[depends on:");
Iterator i = dependency.iterator();
while (i.hasNext()) {
buf.append(i.next());
if (i.hasNext()) {
buf.append(",");
}
}
buf.append("]");
}
return buf.toString();
}
}
}