📄 zip.java
字号:
* archive, but at the same time, there are no resources * known to us that would need to be added. Only the * subclass seems to know what's going on. * * This happens if <jar> detects that the manifest has changed, * for example. The manifest is not part of any resources * because of our support for inline <manifest>s. * * If we invoke createEmptyZip like Ant 1.5.2 did, * we'll loose all stuff that has been in the original * archive (bugzilla report 17780). */ return new ArchiveState(true, initialResources); } if (emptyBehavior.equals("skip")) { if (doUpdate) { log(archiveType + " archive " + zipFile + " not updated because no new files were included.", Project.MSG_VERBOSE); } else { log("Warning: skipping " + archiveType + " archive " + zipFile + " because no files were included.", Project.MSG_WARN); } } else if (emptyBehavior.equals("fail")) { throw new BuildException("Cannot create " + archiveType + " archive " + zipFile + ": no files were included.", getLocation()); } else { // Create. if (!zipFile.exists()) { needsUpdate = true; } } return new ArchiveState(needsUpdate, initialResources); } // initialResources is not empty if (!zipFile.exists()) { return new ArchiveState(true, initialResources); } if (needsUpdate && !doUpdate) { // we are recreating the archive, need all resources return new ArchiveState(true, initialResources); } Resource[][] newerResources = new Resource[filesets.length][]; for (int i = 0; i < filesets.length; i++) { if (!(fileset instanceof ZipFileSet) || ((ZipFileSet) fileset).getSrc(getProject()) == null) { File base = filesets[i].getDir(getProject()); for (int j = 0; j < initialResources[i].length; j++) { File resourceAsFile = FILE_UTILS.resolveFile(base, initialResources[i][j].getName()); if (resourceAsFile.equals(zipFile)) { throw new BuildException("A zip file cannot include " + "itself", getLocation()); } } } } for (int i = 0; i < filesets.length; i++) { if (initialResources[i].length == 0) { newerResources[i] = new Resource[] {}; continue; } FileNameMapper myMapper = new IdentityMapper(); if (filesets[i] instanceof ZipFileSet) { ZipFileSet zfs = (ZipFileSet) filesets[i]; if (zfs.getFullpath(getProject()) != null && !zfs.getFullpath(getProject()).equals("")) { // in this case all files from origin map to // the fullPath attribute of the zipfileset at // destination MergingMapper fm = new MergingMapper(); fm.setTo(zfs.getFullpath(getProject())); myMapper = fm; } else if (zfs.getPrefix(getProject()) != null && !zfs.getPrefix(getProject()).equals("")) { GlobPatternMapper gm = new GlobPatternMapper(); gm.setFrom("*"); String prefix = zfs.getPrefix(getProject()); if (!prefix.endsWith("/") && !prefix.endsWith("\\")) { prefix += "/"; } gm.setTo(prefix + "*"); myMapper = gm; } } Resource[] resources = initialResources[i]; if (doFilesonly) { resources = selectFileResources(resources); } newerResources[i] = ResourceUtils.selectOutOfDateSources(this, resources, myMapper, getZipScanner()); needsUpdate = needsUpdate || (newerResources[i].length > 0); if (needsUpdate && !doUpdate) { // we will return initialResources anyway, no reason // to scan further. break; } } if (needsUpdate && !doUpdate) { // we are recreating the archive, need all resources return new ArchiveState(true, initialResources); } return new ArchiveState(needsUpdate, newerResources); } /** * Collect the resources that are newer than the corresponding * entries (or missing) in the original archive. * * <p>If we are going to recreate the archive instead of updating * it, all resources should be considered as new, if a single one * is. Because of this, subclasses overriding this method must * call <code>super.getResourcesToAdd</code> and indicate with the * third arg if they already know that the archive is * out-of-date.</p> * * @param rcs The filesets to grab resources from * @param zipFile intended archive file (may or may not exist) * @param needsUpdate whether we already know that the archive is * out-of-date. Subclasses overriding this method are supposed to * set this value correctly in their call to * <code>super.getResourcesToAdd</code>. * @return an array of resources to add for each fileset passed in as well * as a flag that indicates whether the archive is uptodate. * * @exception BuildException if it likes */ protected ArchiveState getNonFileSetResourcesToAdd(ResourceCollection[] rcs, File zipFile, boolean needsUpdate) throws BuildException { /* * Backwards compatibility forces us to repeat the logic of * getResourcesToAdd(FileSet[], ...) here once again. */ Resource[][] initialResources = grabNonFileSetResources(rcs); if (isEmpty(initialResources)) { // no emptyBehavior handling since the FileSet version // will take care of it. return new ArchiveState(needsUpdate, initialResources); } // initialResources is not empty if (!zipFile.exists()) { return new ArchiveState(true, initialResources); } if (needsUpdate && !doUpdate) { // we are recreating the archive, need all resources return new ArchiveState(true, initialResources); } Resource[][] newerResources = new Resource[rcs.length][]; for (int i = 0; i < rcs.length; i++) { if (initialResources[i].length == 0) { newerResources[i] = new Resource[] {}; continue; } for (int j = 0; j < initialResources[i].length; j++) { if (initialResources[i][j] instanceof FileResource && zipFile.equals(((FileResource) initialResources[i][j]).getFile())) { throw new BuildException("A zip file cannot include " + "itself", getLocation()); } } Resource[] rs = initialResources[i]; if (doFilesonly) { rs = selectFileResources(rs); } newerResources[i] = ResourceUtils.selectOutOfDateSources(this, rs, new IdentityMapper(), getZipScanner()); needsUpdate = needsUpdate || (newerResources[i].length > 0); if (needsUpdate && !doUpdate) { // we will return initialResources anyway, no reason // to scan further. break; } } if (needsUpdate && !doUpdate) { // we are recreating the archive, need all resources return new ArchiveState(true, initialResources); } return new ArchiveState(needsUpdate, newerResources); } /** * Fetch all included and not excluded resources from the sets. * * <p>Included directories will precede included files.</p> * @param filesets an array of filesets * @return the resources included * @since Ant 1.5.2 */ protected Resource[][] grabResources(FileSet[] filesets) { Resource[][] result = new Resource[filesets.length][]; for (int i = 0; i < filesets.length; i++) { boolean skipEmptyNames = true; if (filesets[i] instanceof ZipFileSet) { ZipFileSet zfs = (ZipFileSet) filesets[i]; skipEmptyNames = zfs.getPrefix(getProject()).equals("") && zfs.getFullpath(getProject()).equals(""); } DirectoryScanner rs = filesets[i].getDirectoryScanner(getProject()); if (rs instanceof ZipScanner) { ((ZipScanner) rs).setEncoding(encoding); } Vector resources = new Vector(); if (!doFilesonly) { String[] directories = rs.getIncludedDirectories(); for (int j = 0; j < directories.length; j++) { if (!"".equals(directories[j]) || !skipEmptyNames) { resources.addElement(rs.getResource(directories[j])); } } } String[] files = rs.getIncludedFiles(); for (int j = 0; j < files.length; j++) { if (!"".equals(files[j]) || !skipEmptyNames) { resources.addElement(rs.getResource(files[j])); } } result[i] = new Resource[resources.size()]; resources.copyInto(result[i]); } return result; } /** * Fetch all included and not excluded resources from the collections. * * <p>Included directories will precede included files.</p> * @param rcs an array of resource collections * @return the resources included * @since Ant 1.7 */ protected Resource[][] grabNonFileSetResources(ResourceCollection[] rcs) { Resource[][] result = new Resource[rcs.length][]; for (int i = 0; i < rcs.length; i++) { Iterator iter = rcs[i].iterator(); ArrayList rs = new ArrayList(); int lastDir = 0; while (iter.hasNext()) { Resource r = (Resource) iter.next(); if (r.isExists()) { if (r.isDirectory()) { rs.add(lastDir++, r); } else { rs.add(r); } } } result[i] = (Resource[]) rs.toArray(new Resource[rs.size()]); } return result; } /** * Add a directory to the zip stream. * @param dir the directort to add to the archive * @param zOut the stream to write to * @param vPath the name this entry shall have in the archive * @param mode the Unix permissions to set. * @throws IOException on error * @since Ant 1.5.2 */ protected void zipDir(File dir, ZipOutputStream zOut, String vPath, int mode) throws IOException { zipDir(dir, zOut, vPath, mode, null); } /** * Add a directory to the zip stream. * @param dir the directort to add to the archive * @param zOut the stream to write to * @param vPath the name this entry shall have in the archive * @param mode the Unix permissions to set. * @param extra ZipExtraFields to add * @throws IOException on error * @since Ant 1.6.3 */ protected void zipDir(File dir, ZipOutputStream zOut, String vPath, int mode, ZipExtraField[] extra) throws IOException { if (doFilesonly) { log("skipping directory " + vPath + " for file-only archive", Project.MSG_VERBOSE); return; } if (addedDirs.get(vPath) != null) { // don't add directories we've already added. // no warning if we try, it is harmless in and of itself return; } log("adding directory " + vPath, Project.MSG_VERBOSE); addedDirs.put(vPath, vPath); if (!skipWriting) { ZipEntry ze = new ZipEntry (vPath); if (dir != null && dir.exists()) { // ZIPs store time with a granularity of 2 seconds, round up ze.setTime(dir.lastModified() + (roundUp ? 1999 : 0)); } else { // ZIPs store time with a granularity of 2 seconds, round up ze.setTime(System.currentTimeMillis() + (roundUp ? 1999 : 0)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -