Java tutorial
/* * Copyright 2015 Shashank Tulsyan <shashaank at neembuu.com>. * * 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 neembuu.uploader.zip.generator; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import neembuu.uploader.utils.HashUtil; import org.apache.commons.io.FilenameUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import shashaank.smallmodule.SmallModule; /** * Make operations to create the zip files. * @author davidepastore */ public class NUZipFileGenerator { private final Path[] uploadersDirectories; private final Path outputDirectory; private final Index index; private final URLClassLoader classLoader; private final Environment env; /*public NUZipFileGenerator(File gitDirectory, File outputDirectory,String[]modules, String[]uploaderModuleName) {*/ public NUZipFileGenerator(Environment env) { this.env = env; uploadersDirectories = new Path[env.modulesToCheckForExportibles().length]; Path gitDirectory = Paths.get(env.gitDirectory()); for (int i = 0; i < env.modulesToCheckForExportibles().length; i++) { String uploadermod = env.modulesToCheckForExportibles()[i]; uploadersDirectories[i] = gitDirectory.resolve("modules/" + uploadermod + "/build/"); } this.outputDirectory = Paths.get(env.outputDirectory()); classLoader = l(env.sortedListOfModulesToCompile(), gitDirectory); index = new Index(this.outputDirectory.resolve("index.json"), env); } private static URLClassLoader l(String[] modules, Path pth) { try { URL[] u = new URL[modules.length]; for (int i = 0; i < u.length; i++) { u[i] = pth.resolve("modules/" + modules[i] + "/build/").toUri().toURL(); } return new URLClassLoader(u); } catch (Exception a) { throw new IllegalStateException(a); } } public void createZipFiles() { Logger.getLogger(NUZipFileGenerator.class.getName()).log(Level.INFO, "Create the zip files"); try { index.intialize(); walkOverAllFiles(); index.complete(); } catch (Exception ex) { Logger.getLogger(NUZipFileGenerator.class.getName()).log(Level.SEVERE, null, ex); } } private void walkOverAllFiles() throws IOException { for (final Path uploadersDirectory : uploadersDirectories) { Files.walkFileTree(uploadersDirectory, new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { exc.printStackTrace(); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.getFileName().toString().endsWith(".class")) { visitClassFile(file, attrs, uploadersDirectory); } return FileVisitResult.CONTINUE; } }); } } private Class load(Path f, Path uploadersDirectory) throws Exception { String p = uploadersDirectory.normalize().relativize(f.normalize()).toString(); p = p.replace(File.separatorChar, '.'); p = p.substring(0, p.lastIndexOf('.'));//to remove .class return classLoader.loadClass(p); } private void visitClassFile(Path file, BasicFileAttributes attrs, Path uploadersDirectory) throws IOException { Class c; try { c = load(file, uploadersDirectory); } catch (Throwable a) { System.err.println("skipping " + file); a.printStackTrace(); return; } SmallModule moduleDescription = (SmallModule) c.getAnnotation(SmallModule.class); if (moduleDescription == null) { System.out.println("not a small module" + file); return; } if (moduleDescription.ignore()) { Logger.getLogger(NUZipFileGenerator.class.getName()).log(Level.INFO, "Ignoring : {0}", FilenameUtils.removeExtension(c.getName())); return; } handleSmallModule(moduleDescription, c, uploadersDirectory); } private void handleSmallModule(SmallModule moduleDescription, Class clzz, Path uploadersDirectory) throws IOException { Logger.getLogger(NUZipFileGenerator.class.getName()).log(Level.INFO, "Create zip for: {0}", clzz.getName()); Path outputModulePath = outputDirectory.resolve("sm").resolve(moduleDescription.name() + ".zip"); Files.createDirectories(outputModulePath.getParent()); while (Files.exists(outputModulePath)) { try { Files.deleteIfExists(outputModulePath); } catch (Exception a) { a.printStackTrace(); } } Map<String, String> env = new HashMap<>(); env.put("create", "true"); boolean destroyZipIsCorrupt = false; URI uri = URI.create("jar:" + outputModulePath.toUri()); try (FileSystem fs = FileSystems.newFileSystem(uri, env)) { smallModuleCreateZip(fs, moduleDescription, clzz, uploadersDirectory); } catch (Exception e) { e.printStackTrace(); destroyZipIsCorrupt = true; } if (destroyZipIsCorrupt) { Files.delete(outputModulePath); } else { String hash = HashUtil.hashFile(outputModulePath.toFile(), index.getHashalgorithm()); try { index.addSmallModule(moduleDescription, hash); } catch (Exception a) { a.printStackTrace();//ignore } } } private void smallModuleCreateZip(FileSystem fs, SmallModule moduleDescription, Class clzz, Path uploadersDirectory) throws IOException, JSONException { JSONObject metaData = makeMetaData(moduleDescription); Files.write(fs.getPath("SmallModule.json"), metaData.toString(3).getBytes()); //zip(fs, moduleDescription.interfaces()); these are already //in the classpath of NU, so we need not repackage them in zip zip(fs, moduleDescription.exports(), uploadersDirectory); zip(fs, moduleDescription.dependsOn(), uploadersDirectory); if (moduleDescription.jarsRequired() != null && moduleDescription.jarsRequired().length > 0) { throw new IllegalStateException("jars not supported as of now"); /*Path extraJarRequiredPath = outputDirectory.resolve("jarsRequired"); Files.createDirectories(extraJarRequiredPath);*/ } } private void zip(FileSystem fs, Class[] z, Path uploadersDirectory) throws IOException { for (Class c : z) { String relClassPath = c.getName().replace('.', File.separatorChar); Path pathInZip = fs.getPath(relClassPath).getParent(); Files.createDirectories(pathInZip);//creates all directory entires if required. handleClassEntry(pathInZip, c, fs, uploadersDirectory); } } private void handleClassEntry(Path pathInZip, final Class c, FileSystem fs, Path uploadersDirectory) throws IOException { Path classLocationOnDisk = uploadersDirectory.resolve(pathInZip.toString()); DirectoryStream<Path> ds = Files.newDirectoryStream(classLocationOnDisk, new DirectoryStream.Filter<Path>() { @Override public boolean accept(Path entry) throws IOException { String fn = entry.getFileName().toString(); String cn = c.getSimpleName(); return fn.equals(cn + ".class") || fn.startsWith(cn + "$"); } }); for (Path p : ds) { byte[] b = Files.readAllBytes(p); Files.write(pathInZip.resolve(p.getFileName().toString()), b); } // say we want to zie SomeClass.class // then we also need to zip SomeClass$1.class // That is, we also need to zip inner classes and inner annoymous classes // into the zip as well } private JSONObject makeMetaData(SmallModule moduleDescription) throws JSONException { JSONObject metaData = new JSONObject(); metaData.put("name", moduleDescription.name()); JSONArray exports = new JSONArray(); assert moduleDescription.exports().length != moduleDescription.interfaces().length; for (int j = 0; j < moduleDescription.exports().length; j++) { JSONObject exportableItem = new JSONObject(); exportableItem.put("implementation", moduleDescription.exports()[j].getName()); exportableItem.put("interface", moduleDescription.interfaces()[j].getName()); exports.put(exportableItem); } metaData.put("exports", exports); return metaData; } }