/* * $Id$ * * Copyright 2006 University of Dundee. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.dsl; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.Target; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Mkdir; import org.apache.tools.ant.types.FileSet; import org.springframework.util.ResourceUtils; /** * An ant task for generating artifacts from the dsl. * * Example: * * <project ...> <taskdef name="dsl" classname="DSLTask" /> <property * name="dest.dir" value="${basedir}/gen-src/mappings"/> <target * name="generate"> <mkdir dir="${dest.dir}" /> <dsl outputdir="${dest.dir}"> * <fileset dir="${mapping.dir}"> <include name="*.xml" /> </fileset> </dsl> * </target> </project> */ public class DSLTask extends Task { public final static String PKG_PLACEHOLDER = "{package-dir}"; public final static String CLS_PLACEHOLDER = "{class-name}"; private final List<FileSet> _fileSets = new ArrayList<FileSet>(); private String _filepattern; private String _template; private String _profile; private boolean singleType = false; public void setFilepattern(String filepattern) { _filepattern = filepattern; if (_filepattern.contains(CLS_PLACEHOLDER)) { singleType = true; } } public void setTemplate(String template) { _template = template; if (_template == null) { throw new BuildException("Template cannot be null"); } } public void setProfile(String profile) { _profile = profile; } public void addFileset(FileSet fileSet) { _fileSets.add(fileSet); } @Override public void execute() throws BuildException { if (_profile == null) { throw new BuildException("No profile specified."); } if (_fileSets.isEmpty()) { throw new BuildException("No fileset specified"); } List<SemanticType> types; DSLHandler handler = new DSLHandler(_profile); java.util.Iterator<FileSet> p = _fileSets.iterator(); while (p.hasNext()) { FileSet fileset = p.next(); DirectoryScanner scanner = fileset .getDirectoryScanner(getProject()); scanner.scan(); String[] files = scanner.getIncludedFiles(); if (files.length == 0) { continue; } log("Parsing " + files.length + " file(s)."); for (int i = 0; i < files.length; i++) { String filename = fileset.getDir(getProject()) + File.separator + files[i]; File file = new File(filename); if (!file.exists()) { log("File " + file + " not found."); } else { SaxReader sr = new SaxReader(file, handler); sr.parse(); } } } types = handler.process(); if (types.size() == 0) { return; // Skip when no files, otherwise we overwrite. } if (singleType) { for (Iterator<SemanticType> it = types.iterator(); it.hasNext();) { SemanticType st = it.next(); try { VelocityHelper vh = new VelocityHelper(); vh.put("type", st); String className = st.getShortname(); String packageName = st.getId(); packageName = packageName.substring(0, packageName .lastIndexOf(".")); // What silliness! String sep = File.separator.replaceAll("\\\\", "\\\\\\\\"); packageName = packageName.replaceAll("[.]", sep); String target = _filepattern; target = target.replace(CLS_PLACEHOLDER, className); target = target.replace(PKG_PLACEHOLDER, packageName); writeToFile(vh, new File(target), _template); } catch (Exception e) { throw new BuildException("Error while writing type:" + st, e); } } } else { java.util.Collections.sort(types, new java.util.Comparator<SemanticType>() { @Override public int compare(SemanticType lhs, SemanticType rhs) { return lhs.getShortname().compareTo(rhs.getShortname()); } }); VelocityHelper vhData = new VelocityHelper(); vhData.put("types", types); try { writeToFile(vhData, new File(_filepattern), _template); } catch (Exception e) { throw new BuildException("Error while generating for template:" + _template, e); } } } @SuppressWarnings("resource") public static InputStream getStream(String str) { InputStream in = null; try { in = DSLTask.class.getClassLoader().getResourceAsStream(str); } catch (Exception e) { // ok } if (in == null) { try { File file = new File(str); in = new FileInputStream(file); } catch (Exception e) { // ignore } } if (in == null) { try { URL url = ResourceUtils.getURL(str); in = url.openStream(); } catch (Exception e) { // ok } } // That didn't work. Then let's try to call ourself again with a // "classpath prefix if (in == null && !str.startsWith("classpath:")) { in = getStream("classpath:" + str); } return in; } private void writeToFile(VelocityHelper vh, File file, String template) throws IOException { InputStream in; in = getStream(template); if (in == null) { throw new BuildException("Cannot resolve template:" + template); } BufferedWriter fw = null; try { mkdir(file); fw = new BufferedWriter (new OutputStreamWriter(new FileOutputStream(file),"UTF-8")); vh.invoke(in, fw); } finally { try { if (fw != null) { fw.flush(); fw.close(); } } finally { if (in != null) { in.close(); } } } } void mkdir(File file) { Mkdir mkdir = new Mkdir(); mkdir.setProject(new Project()); mkdir.setOwningTarget(new Target()); mkdir.setDir(new File(file.getParent())); mkdir.execute(); } static String fileAsString(File file) { StringBuffer contents = new StringBuffer(); BufferedReader input = null; try { input = new BufferedReader (new InputStreamReader(new FileInputStream(file),"UTF-8")); String line = null; while ((line = input.readLine()) != null) { contents.append(line); contents.append(System.getProperty("line.separator")); } } catch (Exception ex) { throw new BuildException("Failed to get file contents", ex); } finally { try { if (input != null) { input.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return contents.toString(); } }