Author: mfortun Date: 2011-07-07 14:30:41 +0200 (Thu, 07 Jul 2011) New Revision: 1067 Url: http://nuiton.org/repositories/revision/wikitty/1067 Log: * JarUtil based on zip util but used to handle jar with manifest Added: trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/JarUtil.java Modified: trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyPublicationExternalize.java trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyServiceJarLoader.java Added: trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/JarUtil.java =================================================================== --- trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/JarUtil.java (rev 0) +++ trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/JarUtil.java 2011-07-07 12:30:41 UTC (rev 1067) @@ -0,0 +1,584 @@ +package org.nuiton.wikitty.publication.externalize; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.FileUtil; +import org.nuiton.util.MD5OutputStream; +import org.nuiton.util.StringUtil; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +/** + * Opérations sur des fichiers Jar. Compression et décompression avec ou sans + * filtres, scan des fichiers créés ou écrasés lors de la décompression... + * + * Créée à partir de org.nuiton.util.ZipUtil + * <p/> + * + * @author mfortun + */ +public class JarUtil { + + /** Class logger. */ + private static Log log = LogFactory.getLog(JarUtil.class); + + /** Taille du buffer pour les lectures/écritures. */ + private static final int BUFFER_SIZE = 8 * 1024; + + /** Le séparateur de fichier en local. */ + private static final String LOCAL_SEP = File.separator; + + private static final String LOCAL_SEP_PATTERN = "\\".equals(LOCAL_SEP) ? LOCAL_SEP + + LOCAL_SEP + : LOCAL_SEP; + + /** Le séparateur jar. */ + private static final String JAR_SEP = "/"; + + private static final String ZIP_SEP_PATTERN = "/"; + + /** Accept all file pattern. */ + protected static FileFilter ALL_FILE_FILTER = new FileFilter() { + public boolean accept(File pathname) { + return true; + } + }; + + /** + * Uncompress jarped file in targetDir. + * + * @param file + * the jar source file + * @param targetDir + * the destination directory + * @return return last entry name + * @throws IOException + * if any problem while uncompressing + */ + public static String uncompress(File file, File targetDir) + throws IOException { + String result; + result = uncompressAndRename(file, targetDir, null, null); + return result; + } + + /** + * Uncompress jarped file in targetDir, and rename uncompressed file if + * necessary. If renameFrom or renameTo is null no renaming is done + * <p/> + * file in jar use / to separate directory and not begin with / each + * directory ended with / + * + * @param file + * the jar source file + * @param targetDir + * the destination directory + * @param renameFrom + * pattern to permit rename file before uncompress it + * @param renameTo + * new name for file if renameFrom is applicable to it you can + * use $1, $2, ... if you have '(' ')' in renameFrom + * @return return last entry name + * @throws IOException + * if any problem while uncompressing + */ + public static String uncompressAndRename(File file, File targetDir, + String renameFrom, String renameTo) throws IOException { + String result = ""; + JarInputStream in = new JarInputStream(new FileInputStream(file)); + JarEntry entry; + while ((entry = in.getNextJarEntry()) != null) { + String name = entry.getName(); + if (renameFrom != null && renameTo != null) { + name = name.replaceAll(renameFrom, renameTo); + if (log.isDebugEnabled()) { + log.debug("rename " + entry.getName() + " -> " + name); + } + } + result = name; + File target = new File(targetDir, name); + if (entry.isDirectory()) { + target.mkdirs(); + } else { + target.getParentFile().mkdirs(); + OutputStream out = new BufferedOutputStream( + new FileOutputStream(target)); + try { + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) { + out.write(buffer, 0, len); + } + } finally { + out.close(); + } + } + } + in.close(); + return result; + } + + public static void compressFiles(File jarFile, File fileOrDirectory) + throws IOException { + + FileFilter filter = ALL_FILE_FILTER; + + List<File> files = new ArrayList<File>(); + if (fileOrDirectory.isDirectory()) { + files = FileUtil.getFilteredElements(fileOrDirectory, filter, true); + } else if (filter.accept(fileOrDirectory)) { + files.add(fileOrDirectory); + } + + compressFiles(jarFile, fileOrDirectory, null, files, false); + + } + + /** + * Compress 'includes' files in jarFile. If file in includes is directory + * only the directory is put in jarFile, not the file contained in directory + * + * @param jarFile + * the destination jar file + * @param root + * for all file in includes that is in this directory, then we + * remove this directory in jar entry name (aka -C for tar), can + * be null; + * @param includes + * the files to include in jar + * @throws IOException + * if any problem while compressing + */ + public static void compressFiles(File jarFile, File root, + Collection<File> includes) throws IOException { + compressFiles(jarFile, root, null, includes, false); + } + + /** + * Compress 'includes' files in jarFile. If file in includes is directory + * only the directory is put in jarFile, not the file contained in directory + * + * @param jarFile + * the destination jar file + * @param root + * for all file in includes that is in this directory, then we + * remove this directory in jar entry name (aka -C for tar), can + * be null; + * @param includes + * the files to include in jar + * @param createMD5 + * also create a MD5 file (jar name + .md5). MD5 file is created + * after jar. + * @throws IOException + * if any problem while compressing + */ + public static void compressFiles(File jarFile, File root, Manifest mf, + Collection<File> includes, boolean createMD5) throws IOException { + + if (mf == null) { + mf = new Manifest(); + } + + OutputStream oStream = new FileOutputStream(jarFile); + + // if md5 creation flag + if (createMD5) { + oStream = new MD5OutputStream(oStream); + } + try { + JarOutputStream jarOStream = new JarOutputStream(oStream, mf); + + for (File file : includes) { + String entryName = toJarEntryName(root, file); + + // Création d'une nouvelle entrée dans le jar + JarEntry entry = new JarEntry(entryName); + entry.setTime(file.lastModified()); + jarOStream.putNextEntry(entry); + + if (file.isFile() && file.canRead()) { + byte[] readBuffer = new byte[BUFFER_SIZE]; + int bytesIn; + BufferedInputStream bis = new BufferedInputStream( + new FileInputStream(file), BUFFER_SIZE); + try { + while ((bytesIn = bis.read(readBuffer, 0, BUFFER_SIZE)) != -1) { + jarOStream.write(readBuffer, 0, bytesIn); + } + } finally { + bis.close(); + } + } + jarOStream.closeEntry(); + } + jarOStream.close(); + + // if md5 creation flag + if (createMD5) { + String md5hash = StringUtil.asHex(((MD5OutputStream) oStream) + .hash()); + File md5File = new File(jarFile.getAbsoluteFile() + ".md5"); + FileUtil.writeString(md5File, md5hash); + } + } finally { + oStream.close(); + } + } + + /** + * If fileOrDirectory is directory Compress recursively all file in this + * directory, else if is just file compress one file. + * <p/> + * Entry result name in jar start at fileOrDirectory. example: if we + * compress /etc/apache, entry will be apache/http.conf, ... + * + * @param jarFile + * the target jar file + * @param fileOrDirectory + * the file or directory to compress + * @throws IOException + * if any problem while compressing + */ + public static void compress(File jarFile, File fileOrDirectory) + throws IOException { + compress(jarFile, fileOrDirectory, null, null, false); + } + + public static void compress(File jarFile, File fileOrDirectory, Manifest mf) + throws IOException { + compress(jarFile, fileOrDirectory, mf, null, false); + } + + /** + * If fileOrDirectory is directory Compress recursively all file in this + * directory, else if is just file compress one file. + * <p/> + * Entry result name in jar start at fileOrDirectory. example: if we + * compress /etc/apache, entry will be apache/http.conf, ... + * + * @param jarFile + * the target jar file + * @param fileOrDirectory + * the file or directory to compress + * @param filter + * used to accept file, if null, all file is accepted + * @throws IOException + * if any problem while compressing + */ + public static void compress(File jarFile, File fileOrDirectory, + FileFilter filter) throws IOException { + compress(jarFile, fileOrDirectory, null, filter, false); + } + + /** + * If fileOrDirectory is directory Compress recursively all file in this + * directory, else if is just file compress one file. + * <p/> + * Entry result name in jar start at fileOrDirectory. example: if we + * compress /etc/apache, entry will be apache/http.conf, ... + * + * @param jarFile + * the target jar file + * @param fileOrDirectory + * the file or directory to compress + * @param filter + * used to accept file, if null, all file is accepted + * @param createMD5 + * also create a MD5 file (jar name + .md5). MD5 file is created + * after jar. + * @throws IOException + * if any problem while compressing + */ + public static void compress(File jarFile, File fileOrDirectory, + Manifest mf, FileFilter filter, boolean createMD5) + throws IOException { + + if (filter == null) { + filter = ALL_FILE_FILTER; + } + List<File> files = new ArrayList<File>(); + if (fileOrDirectory.isDirectory()) { + files = FileUtil.getFilteredElements(fileOrDirectory, filter, true); + } else if (filter.accept(fileOrDirectory)) { + files.add(fileOrDirectory); + } + + compressFiles(jarFile, fileOrDirectory.getParentFile(), mf, files, + createMD5); + } + + /** + * <li>supprime le root du fichier <li>Converti les '\' en '/' car les jar + * entry utilise des '/' <li>ajoute un '/' a la fin pour les repertoires <li> + * supprime le premier '/' si la chaine commence par un '/' + * + * @param root + * the root directory + * @param file + * the file to treate + * @return the jar entry name corresponding to the given <code>file</code> + * from <code>root</code> dir. + */ + private static String toJarEntryName(File root, File file) { + String result = file.getPath(); + + if (root != null) { + String rootPath = root.getPath(); + if (result.startsWith(rootPath)) { + result = result.substring(rootPath.length()); + } + } + + result = result.replace('\\', '/'); + if (file.isDirectory()) { + result += '/'; + } + while (result.startsWith("/")) { + result = result.substring(1); + } + return result; + } + + /** + * Scan a jarFile, and fill two lists of relative paths corresponding of jar + * entries. First list contains all entries to be added while a uncompress + * operation on the destination directory </code>targetDir</code>. Second + * list contains all entries to be overwritten while a uncompress operation + * on the destination directory <code>targetDir</code>. <br> + * If <code>targetDir</code> is <code>null</code> we don't fill + * <cide>existingFiles<code/> list. + * + * @param jarFile + * location of the jar to scanJar + * @param targetDir + * location of destination for a uncompress operation. If + * <code>null</code> we don't test to find overwritten files. + * @param newFiles + * list of files to be added while a uncompress + * @param existingFiles + * list of files to be overwritten while a uncompress if the + * <code>targetDir</code>, (only use if <code>targetDir</code> is + * not <code>null</code>) + * @param excludeFilter + * used to exclude some files + * @param renameFrom + * {@link #uncompressAndRename(File, File, String, String)} + * @param renameTo + * {@link #uncompressAndRename(File, File, String, String)} + * @throws IOException + * if any exception while dealing with jarfile + */ + public static void scan(File jarFile, File targetDir, + List<String> newFiles, List<String> existingFiles, + FileFilter excludeFilter, String renameFrom, String renameTo) + throws IOException { + JarFile jar = null; + try { + jar = new JarFile(jarFile); + boolean findExisting = targetDir != null && targetDir.exists(); + boolean filter = findExisting && excludeFilter != null; + boolean rename = renameFrom != null && renameTo != null; + Enumeration<? extends JarEntry> entries = jar.entries(); + while (entries.hasMoreElements()) { + String entryName = entries.nextElement().getName(); + if (rename) { + entryName = entryName.replaceAll(renameFrom, renameTo); + } + String name = convertToLocalEntryName(entryName); + if (findExisting || filter) { + File file = new File(targetDir, name); + if (filter && excludeFilter.accept(file)) + continue; + if (file.exists()) { + existingFiles.add(name); + continue; + } + } + newFiles.add(name); + } + } finally { + if (jar != null) { + jar.close(); + } + } + } + + @SuppressWarnings({ "unchecked" }) + public static List<String>[] scanAndExplodeJar(File source, File root, + FileFilter excludeFilter) throws IOException { + + List<String> overwrittenFiles = new ArrayList<String>(); + List<String> newFiles = new ArrayList<String>(); + + // obtain list of relative paths (to add or overwrite) + scan(source, root, newFiles, overwrittenFiles, excludeFilter, null, + null); + + return new List[] { newFiles, overwrittenFiles }; + } + + /** + * uncompress jarped file in targetDir. + * <p/> + * If <code>toTreate</code> if not null nor empty, we use it to filter + * entries to uncompress : it contains a list of relative local path of + * files to uncompress. Otherwise just delegate to + * {@link JarUtil#uncompress(File,File)}. + * + * @param file + * location of jar file + * @param targetDir + * destination directory + * @param toTreate + * list of relative local path of entries to treate + * @param renameFrom + * {@link #uncompressAndRename(File, File, String, String)} + * @param renameTo + * {@link #uncompressAndRename(File, File, String, String)} + * @return return last entry name + * @throws IOException + * if nay exception while operation + */ + public static String uncompress(File file, File targetDir, + List<String> toTreate, String renameFrom, String renameTo) + throws IOException { + if (toTreate == null || toTreate.isEmpty()) { + return uncompressAndRename(file, targetDir, renameFrom, renameTo); + } + + boolean rename = renameFrom != null && renameTo != null; + + String result = ""; + JarEntry entry; + JarInputStream in = new JarInputStream(new FileInputStream(file)); + + try { + while ((entry = in.getNextJarEntry()) != null) { + String name = entry.getName(); + if (rename) { + result = convertToLocalEntryName(name.replaceAll( + renameFrom, renameTo)); + } else { + result = convertToLocalEntryName(name); + } + + if (log.isDebugEnabled()) { + log.debug("open [" + name + "] : " + result); + } + if (!toTreate.contains(result)) { + continue; + } + + if (log.isDebugEnabled()) { + log.debug("copy [" + name + "] : " + result); + } + File target = new File(targetDir, result); + if (entry.isDirectory()) { + target.mkdirs(); + } else { + target.getParentFile().mkdirs(); + OutputStream out = new BufferedOutputStream( + new FileOutputStream(target)); + try { + byte[] buffer = new byte[BUFFER_SIZE]; + int len; + while ((len = in.read(buffer, 0, BUFFER_SIZE)) != -1) { + out.write(buffer, 0, len); + } + } finally { + out.close(); + } + } + } + } finally { + in.close(); + } + return result; + } + + /** + * Unjar compressed archive and keep non excluded patterns. + * + * @param file + * archive file + * @param targetDir + * destination file + * @param excludes + * excludes pattern (pattern must match complete entry name + * including root folder) + * @throws IOException + */ + public static void uncompressFiltred(File file, File targetDir, + String... excludes) throws IOException { + + JarFile jarFile = new JarFile(file); + + Enumeration<? extends JarEntry> entries = jarFile.entries(); + + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + + String name = entry.getName(); + // add continue to break loop + boolean excludeEntry = false; + if (excludes != null) { + for (String exclude : excludes) { + if (name.matches(exclude)) { + excludeEntry = true; + } + } + } + + if (!excludeEntry) { + File target = new File(targetDir, name); + if (entry.isDirectory()) { + target.mkdirs(); + } else { + // get inputstream only here + target.getParentFile().mkdirs(); + InputStream in = jarFile.getInputStream(entry); + try { + OutputStream out = new BufferedOutputStream( + new FileOutputStream(target)); + try { + byte[] buffer = new byte[8 * 1024]; + int len; + + while ((len = in.read(buffer, 0, 8 * 1024)) != -1) { + out.write(buffer, 0, len); + } + } finally { + out.close(); + } + } finally { + in.close(); + } + } + } + } + } + + protected static String convertToLocalEntryName(String txt) { + String s = txt.replaceAll(ZIP_SEP_PATTERN, LOCAL_SEP_PATTERN); + if (s.endsWith(JAR_SEP)) { + s = s.substring(0, s.length() - 1); + } + return s; + } +} Property changes on: trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/JarUtil.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyPublicationExternalize.java =================================================================== --- trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyPublicationExternalize.java 2011-07-07 09:04:00 UTC (rev 1066) +++ trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyPublicationExternalize.java 2011-07-07 12:30:41 UTC (rev 1067) @@ -1,12 +1,27 @@ package org.nuiton.wikitty.publication.externalize; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + import org.nuiton.util.ApplicationConfig; import org.nuiton.util.ArgumentsParserException; +import org.nuiton.util.FileUtil; +import org.nuiton.util.ZipUtil; import org.nuiton.wikitty.WikittyConfigOption; import org.nuiton.wikitty.WikittyProxy; import org.nuiton.wikitty.WikittyServiceFactory; +import org.nuiton.wikitty.entities.Wikitty; +import org.nuiton.wikitty.publication.entities.WikittyPubData; +import org.nuiton.wikitty.publication.entities.WikittyPubText; import org.nuiton.wikitty.publication.synchro.WikittyPublicationFileSystem; +import org.nuiton.wikitty.search.Criteria; +import org.nuiton.wikitty.search.PagedResult; import org.nuiton.wikitty.search.Search; /** @@ -17,57 +32,81 @@ */ public class WikittyPublicationExternalize { + public static String TEMPORARY_FILE_NAME = "tempBeforeJar"; + public static String DEFAULT_JAR_NAME = "pub-externalized"; + /* * Class don't have to be instantiate */ private WikittyPublicationExternalize() { - } - static public void main(String[] args) throws ArgumentsParserException { + static public void main(String[] args) throws ArgumentsParserException, IOException { ApplicationConfig appconfig = new ApplicationConfig(); - - - appconfig.parse(args); + // Set the correct service use to parse local file + appconfig.setOption( + WikittyConfigOption.WIKITTY_WIKITTYSERVICE_COMPONENTS.getKey(), + WikittyPublicationFileSystem.class.getName()); - appconfig - .setOption( - WikittyConfigOption.WIKITTY_WIKITTYSERVICE_COMPONENTS - .getKey(), - WikittyPublicationFileSystem.class.getName()); - + // construct the url for local repo File currentFile = new File("."); - currentFile = new File(currentFile.getAbsolutePath()).getParentFile(); - + // currentFile = new + // File(currentFile.getAbsolutePath()).getParentFile(); + currentFile = new File("/home/Manou/testWP"); String Label = currentFile.getName(); - String urlFileSystem = "file:///home/Manou/testWP#wp"; - //currentFile.getParent() + "#" + Label; + String urlFileSystem = "file:///home/Manou/testWP#wp"; + // String urlFileSystem = currentFile.getParent() + "#" + Label; System.out.println(urlFileSystem); - - appconfig.setOption(WikittyConfigOption.WIKITTY_SERVER_URL.getKey(), urlFileSystem); - - - WikittyProxy proxy = new WikittyProxy( WikittyServiceFactory.buildWikittyService(appconfig)); + // Found all wikity on the file System + Criteria findAllCrit = Search.query().keyword("*").criteria(); + PagedResult<Wikitty> allWikittyOnFS = proxy + .findAllByCriteria(findAllCrit); + + // make tempfile + File tempDirectory = new File(currentFile + File.separator + + TEMPORARY_FILE_NAME); + tempDirectory.mkdir(); + + + // iterate wikitty + // - write file + // - write property + // - write + for (Wikitty wikit : allWikittyOnFS) { + + + if (wikit.hasExtension(WikittyPubText.EXT_WIKITTYPUBTEXT)) { + + } else if (wikit.hasExtension(WikittyPubData.EXT_WIKITTYPUBDATA)) { + + } + } - System.out.println(proxy.findAllByCriteria(Search.query().keyword("*").criteria()).size()); + // construct jar + File jarFile = new File(currentFile + File.separator+DEFAULT_JAR_NAME+".jar"); + //JarUtil.compressFiles(jarFile, tempDirectory ); + JarUtil.compressFiles(jarFile, new File("/home/Manou/testWP/wp/") ); + + // delete tempfile + FileUtil.deleteRecursively(tempDirectory); } /* @@ -90,21 +129,17 @@ * Une fois tout les wikitty traité on va packager le dossier tempJar en jar * et on va supprimer le dossier tempJar */ - - - + /* * Format des propriétés: * - * id.property - * 18114-1811-181-18=/bob/truc/nuiton/Script + * id.property 18114-1811-181-18=/bob/truc/nuiton/Script * - * metadata - * 18114-1811-181-18.version=1.0 - * 18114-1811-181-18.exention=js + * metadata 18114-1811-181-18.version=1.0 18114-1811-181-18.exention=js */ + + public static String getWikittyPubLocalName(Wikitty w) { + return null; + } - - - } Modified: trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyServiceJarLoader.java =================================================================== --- trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyServiceJarLoader.java 2011-07-07 09:04:00 UTC (rev 1066) +++ trunk/wikitty-publication/src/main/java/org/nuiton/wikitty/publication/externalize/WikittyServiceJarLoader.java 2011-07-07 12:30:41 UTC (rev 1067) @@ -2,10 +2,9 @@ import java.util.Collection; import java.util.List; - -import org.nuiton.wikitty.WikittyService; import org.nuiton.wikitty.entities.Wikitty; import org.nuiton.wikitty.entities.WikittyExtension; +import org.nuiton.wikitty.publication.synchro.AbstractWikittyFileService; import org.nuiton.wikitty.search.Criteria; import org.nuiton.wikitty.search.PagedResult; import org.nuiton.wikitty.search.TreeNodeResult; @@ -18,8 +17,7 @@ * @author mfortun * */ -public class WikittyServiceJarLoader implements WikittyService { - +public class WikittyServiceJarLoader extends AbstractWikittyFileService { /*