/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.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.gnu.org/licenses/agpl.txt * * 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 syncbundles; /* * Copyright 2009-2010 Streamsource AB * * 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. */ import org.qi4j.api.io.Input; import org.qi4j.api.io.Output; import org.qi4j.api.io.Receiver; import org.qi4j.api.io.Sender; import org.qi4j.api.io.Transforms; import org.qi4j.api.specification.Specification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.OutputStream; import java.io.OutputStreamWriter; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /** * When executed, this tool will find all properties files that are ResourceBundles and try to locate * an Enum class that has the same name. If one is found, check all properties to see if they exist * in the Enum. If no, then remove them. * <p/> * Invoke without parameters to do a "dry run", without making changes. This will just log what changes * that should be done. If you add the parameter "fix", then the changes will be written back. */ public class SyncEnumBundles { private static File base; private static Logger logger; private static boolean fix = false; public static void main(String[] args) throws IOException, ClassNotFoundException { if (args.length > 0 && args[0].equals("fix")) fix = true; base = new File("."); logger = LoggerFactory.getLogger(SyncEnumBundles.class); logger.info("Checking resources at:" + base.getAbsolutePath()); if (fix) logger.info("Changes will be written to resource files"); else logger.info("Changes will only be logged"); check(base); } private static void check(File resources) throws IOException, ClassNotFoundException { for (File file : resources.listFiles()) { if (file.isDirectory()) check(file); else { if (file.getName().endsWith(".properties")) { // TODO I'm sure there's a fancy regex that could do this instead // Get a file on the form /src/main/resources/foo/bar/resources/Some_sv.properties // to the form foo.bar.Some String enumName = file.getPath(); enumName = enumName.substring(enumName.indexOf("resources/") + "resources/".length()); enumName = enumName.replace(File.separatorChar, '.'); enumName = enumName.substring(0, enumName.indexOf(".properties")); enumName = enumName.replace(".resources", ""); enumName = enumName.split("_")[0]; final Class enumClass; try { enumClass = SyncEnumBundles.class.getClassLoader().loadClass(enumName); if (!enumClass.isEnum()) continue; } catch (ClassNotFoundException e) { continue; } logger.info("Checking bundle at:" + file.getName() + ", classname:" + enumName); File output = File.createTempFile("fixed", ".properties"); textInput(file).transferTo(Transforms.filter(new Specification<String>() { public boolean satisfiedBy(String item) { if (!item.contains("=")) return true; String[] property = item.split("="); String name = property[0]; try { enumClass.getField(name); return true; } catch (NoSuchFieldException e) { logger.info(" Property " + name + " has been removed"); return false; } } }, text(output))); if (fix) { if (output.renameTo(file)) logger.debug("Fixed " + file); else logger.warn("Could not overwrite fixed file " + file); } else { if (!output.delete()) logger.warn("Could not delete temporary file"); } } } } } public static Output<String, IOException> text(final File file) { return new Output<String, IOException>() { public <SenderThrowableType extends Throwable> void receiveFrom(Sender<? extends String, SenderThrowableType> sender) throws IOException, SenderThrowableType { OutputStream stream = new FileOutputStream(file); // If file should be gzipped, do that automatically if (file.getName().endsWith(".gz")) stream = new GZIPOutputStream(stream); final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stream, "ISO-8859-1")); try { sender.sendTo(new Receiver<String, IOException>() { public void receive(String item) throws IOException { writer.append(item).append('\n'); } }); writer.close(); } catch (IOException e) { // We failed writing - close and delete writer.close(); file.delete(); } catch (Throwable senderThrowableType) { // We failed writing - close and delete writer.close(); file.delete(); throw (SenderThrowableType) senderThrowableType; } } }; } public static Input<String, IOException> textInput(final File source) { return new Input<String, IOException>() { public <ReceiverThrowableType extends Throwable> void transferTo(Output<? super String, ReceiverThrowableType> output) throws IOException, ReceiverThrowableType { InputStream stream = new FileInputStream(source); // If file is gzipped, unzip it automatically if (source.getName().endsWith(".gz")) stream = new GZIPInputStream(stream); final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "ISO-8859-1")); try { output.receiveFrom(new Sender<String, IOException>() { public <ReceiverThrowableType extends Throwable> void sendTo(Receiver<? super String, ReceiverThrowableType> receiver) throws ReceiverThrowableType, IOException { String line; while ((line = reader.readLine()) != null) { receiver.receive(line); } } }); } finally { reader.close(); } } }; } }