/* * This file is part of DrFTPD, Distributed FTP Daemon. * * DrFTPD is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * DrFTPD 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 DrFTPD; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.drftpd.tools.ant; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.StringReader; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.MissingResourceException; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import java.util.TreeSet; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; /** * @author djb61 * @version $Id$ */ public class ThemeTask extends Task { private File _baseDir; private File _pluginDir; private HashMap<String,String> _themes = new HashMap<String,String>(); private final String themedir = "conf" + File.separator + "themes"; /** * @param aBaseDir base directory for project */ public final void setBaseDir(final File aBaseDir) { _baseDir = aBaseDir; } /** * @param aPluginDir base directory for plugin */ public final void setPluginDir(final File aPluginDir) { _pluginDir = aPluginDir; } /** * @see org.apache.tools.ant.Task#execute() */ @Override public void execute() throws BuildException { // Get the build start time as long SimpleDateFormat simpleBuildDate = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS"); Date buildDate = null; try { buildDate = simpleBuildDate.parse(getProject().getProperty("build.plugins.start")); } catch (ParseException e) { throw new BuildException("Plugin build timestamp not set correctly"); } long longDate = buildDate.getTime(); findProperties(_pluginDir); // Check all theme files we touched and write them to disk for (String theme : _themes.keySet()) { File themeFile = new File( _baseDir+File.separator+themedir+File.separator+theme+File.separator+"core.theme.default"); // Check we have a dir for this theme, if not make it if (!themeFile.getParentFile().exists()) { themeFile.getParentFile().mkdirs(); } boolean newFile = false; // Delete stale file if needed if (themeFile.lastModified() == 0L || themeFile.lastModified() < longDate) { // Safe to try a delete even if the file doesn't exist themeFile.delete(); newFile = true; } FileOutputStream fos = null; OutputStreamWriter output = null; try { fos = new FileOutputStream(themeFile,true); output = new OutputStreamWriter(fos,"8859_1"); if (newFile) { // Since this is the first entry in the file during this build // session add the comment block at the top of the file ResourceBundle commentBundle = ResourceBundle.getBundle(this.getClass().getName()); try { for (int i = 1;; i++) { output.write(commentBundle.getString("comment."+i)+"\n"); } } catch (MissingResourceException e) { // Means we reached the end of the comment block output.write("\n"); } } // Append new theme data to file output.write(_themes.get(theme)); output.flush(); } catch (FileNotFoundException e) { log("Cannot write theme file to: " + themeFile.getParent(),Project.MSG_ERR); } catch (IOException e) { log("Error writing theme file: " + themeFile.getName(),Project.MSG_ERR); } finally { if (output != null) { try { output.close(); } catch (IOException e) { // Just means it doesn't need closing } } if (fos != null) { try { fos.close(); } catch (IOException e) { // Just means it doesn't need closing } } } } } /** * Recursively scans a directory for properties files * and adds their entries to their respective theme * file. * * @param dir directory to search for properties * @throws BuildException */ private void findProperties(File dir) throws BuildException { if (!dir.isDirectory()) throw new BuildException(dir.getPath() + " is not a directory"); for (File file : dir.listFiles()) { if (file.getName().startsWith(".")) { continue; } else if (file.isFile() && file.getName().endsWith(".properties")) { loadProperties(file); } else if (file.isDirectory()){ findProperties(file); } } } /** * Read a properties file and add the keys to the respective * theme properties * * @param file properties file to be read */ private void loadProperties(File file) { String dirPrefix = file.getParent().substring(_pluginDir.getPath().length()+1); dirPrefix = dirPrefix.replace(File.separatorChar,'.'); String[] parts = file.getName().split("\\."); if (parts.length != 3) { log("Skipping invalid filename: " + file.getName(),Project.MSG_INFO); } else { String keyPrefix = dirPrefix + "." + parts[0] + "."; FileInputStream fis = null; InputStreamReader input = null; try { // Create a BufferedReader to read the file fis = new FileInputStream(file); input = new InputStreamReader(fis,"8859_1"); PropertyResourceBundle inputBundle = new PropertyResourceBundle(input); // Retrieve string object for the theme this // this file belongs to, if we don't have one // yet then create one String existing = _themes.get(parts[1]); StringBuilder output = null; if (existing == null) { output = new StringBuilder(); } else { output = new StringBuilder(existing); } // Add a new line to ease readability output.append("\n"); // Copy all properties from file into theme // adding the correct namespace prefix TreeSet<String> sortedProps = new TreeSet<String>(inputBundle.keySet()); for (String propKey : sortedProps) { output.append(keyPrefix); output.append(propKey); output.append("="); String propValue = inputBundle.getString(propKey); if (propValue.indexOf('\n') != -1) { output.append("\\\n"); } BufferedReader valueReader = new BufferedReader( new StringReader(propValue)); try { String valueLine; int lineCount = 0; while ((valueLine = valueReader.readLine()) != null) { if (lineCount > 0) { output.append("\\n\\"); } output.append(valueLine); lineCount++; } } catch(IOException e) { // As this is a string being read from this shouldn't happen } output.append("\n"); } // Put modified theme back in the map _themes.put(parts[1], output.toString()); } catch (FileNotFoundException e) { log("File appears to have been deleted, skipping: " + file.getName(),Project.MSG_ERR); } catch (IOException e) { log("Failed to load properties from: " + file.getName(),Project.MSG_ERR); } finally { try { input.close(); } catch (IOException e) { // already closed } try { fis.close(); } catch (IOException e) { // already closed } } } } }