expanddeploycontroller.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 619 行
JAVA
619 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source 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. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.server.deploy;import com.caucho.config.types.FileSetType;import com.caucho.git.GitCommit;import com.caucho.git.GitRepository;import com.caucho.git.GitTree;import com.caucho.loader.DynamicClassLoader;import com.caucho.loader.Environment;import com.caucho.util.L10N;import com.caucho.util.Log;import com.caucho.vfs.Depend;import com.caucho.vfs.Path;import com.caucho.vfs.ReadStream;import com.caucho.vfs.Vfs;import com.caucho.vfs.WriteStream;import java.io.IOException;import java.util.*;import java.util.jar.Attributes;import java.util.jar.Manifest;import java.util.logging.Level;import java.util.logging.Logger;import java.util.zip.ZipEntry;import java.util.zip.ZipInputStream;/** * A deployment entry that expands from an archive (Jar/Zip) file. */abstract public class ExpandDeployController<I extends DeployInstance> extends DeployController<I> { private static final L10N L = new L10N(ExpandDeployController.class); private static final Logger log = Log.open(ExpandDeployController.class); private Object _archiveExpandLock = new Object(); private Path _rootDirectory; private Path _archivePath; private GitRepository _git; private Path _gitRefPath; private FileSetType _expandCleanupFileSet; // classloader for the manifest entries private DynamicClassLoader _manifestLoader; private Manifest _manifest; protected ExpandDeployController(String id) { this(id, null, null); } protected ExpandDeployController(String id, ClassLoader loader, Path rootDirectory) { super(id, loader); if (rootDirectory == null) rootDirectory = Vfs.getPwd(getParentClassLoader()); _rootDirectory = rootDirectory; } /** * Gets the root directory */ public Path getRootDirectory() { return _rootDirectory; } /** * Sets the root directory */ protected void setRootDirectory(Path rootDirectory) { _rootDirectory = rootDirectory; } /** * Gets the archive path. */ public Path getArchivePath() { return _archivePath; } /** * Sets the archive path. */ public void setArchivePath(Path path) { _archivePath = path; } /** * The Git repository */ public GitRepository getGit() { return _git; } /** * The Git repository */ public void setGit(GitRepository git) { _git = git; } /** * The Git ref path */ public Path getGitRefPath() { return _gitRefPath; } /** * The Git ref path */ public void setGitRefPath(Path path) { _gitRefPath = path; } /** * Returns the manifest. */ public Manifest getManifest() { return _manifest; } /** * Returns the manifest as an attribute map */ public Map<String,String> getManifestAttributes() { if (_manifest == null) return null; Map<String,String> map = new TreeMap<String,String>(); Attributes attr = _manifest.getMainAttributes(); if (attr != null) { for (Map.Entry entry : attr.entrySet()) { map.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue())); } } return map; } /** * Sets the manifest class loader. */ public void setManifestClassLoader(DynamicClassLoader loader) { _manifestLoader = loader; } /** * Sets the archive auto-remove file set. */ public void setExpandCleanupFileSet(FileSetType fileSet) { _expandCleanupFileSet = fileSet; } /** * Merges with the old controller. */ @Override protected void mergeController(DeployController oldControllerV) { super.mergeController(oldControllerV); ExpandDeployController<I> oldController; oldController = (ExpandDeployController<I>) oldControllerV; if (oldController._expandCleanupFileSet != null) _expandCleanupFileSet = oldController._expandCleanupFileSet; if (oldController.getArchivePath() != null) setArchivePath(oldController.getArchivePath()); if (oldController.getGitRefPath() != null) setGitRefPath(oldController.getGitRefPath()); } /** * Expand an archive file. The _archiveExpandLock must be obtained * before the expansion. */ protected void expandArchive() throws IOException { synchronized (_archiveExpandLock) { if (expandRepositoryImpl()) { } else if (expandArchiveImpl()) { } else { try { Thread.sleep(2000); } catch (InterruptedException e) { } if (expandRepositoryImpl()) { } else expandArchiveImpl(); } Path path = getRootDirectory().lookup("META-INF/MANIFEST.MF"); if (path.canRead()) { ReadStream is = path.openRead(); try { _manifest = new Manifest(is); } catch (IOException e) { log.warning(L.l("Manifest file cannot be read for '{0}'.\n{1}", getRootDirectory(), e)); log.log(Level.FINE, e.toString(), e); } finally { is.close(); } } } } /** * Adds any class path from the manifest. */ protected void addManifestClassPath() throws IOException { DynamicClassLoader loader = Environment.getDynamicClassLoader(); if (loader == null) return; Manifest manifest = getManifest(); if (manifest == null) return; Attributes main = manifest.getMainAttributes(); if (main == null) return; String classPath = main.getValue("Class-Path"); Path pwd = null; if (getArchivePath() != null) pwd = getArchivePath().getParent(); else pwd = getRootDirectory(); if (classPath == null) { } else if (_manifestLoader != null) _manifestLoader.addManifestClassPath(classPath, pwd); else loader.addManifestClassPath(classPath, pwd); } /** * Expand an archive. The _archiveExpandLock must be obtained before the * expansion. */ private boolean expandRepositoryImpl() throws IOException { Path gitRefPath = getGitRefPath(); if (gitRefPath == null || ! gitRefPath.canRead()) return false; try { String sha1 = null; ReadStream is = null; try { is = gitRefPath.openRead(); sha1 = is.readLine(); if (sha1 != null) sha1 = sha1.trim(); GitCommit commit = _git.parseCommit(sha1); String tree = commit.getTree(); Path pwd = getRootDirectory(); pwd.mkdirs(); expandRepositoryTree(pwd, tree); return false; } finally { if (is != null) is.close(); } } catch (IOException e) { log.log(Level.FINE, e.toString(), e); return false; } } private void expandRepositoryTree(Path pwd, String treeDigest) throws IOException { GitTree tree = _git.parseTree(treeDigest); for (GitTree.Entry entry : tree.entries()) { String name = entry.getName(); String sha1 = entry.getSha1(); Path subPath = pwd.lookup(name); if (entry.isDir()) { subPath.mkdirs(); expandRepositoryTree(subPath, sha1); } else if (entry.isFile()) { _git.copyToFile(subPath, sha1); } else { log.warning(this + " unknown entry " + entry); } } } /** * Expand an archive. The _archiveExpandLock must be obtained before the * expansion. */ private boolean expandArchiveImpl() throws IOException { Path archivePath = getArchivePath(); if (archivePath == null) return true; if (! archivePath.canRead()) return true; Path expandDir = getRootDirectory(); Path parent = expandDir.getParent(); try { parent.mkdirs(); } catch (Throwable e) { } Path dependPath = expandDir.lookup("META-INF/resin-war.digest"); Depend depend = null; // XXX: change to a hash if (dependPath.canRead()) { ReadStream is = null; try { is = dependPath.openRead(); String line = is.readLine(); long digest; if (line != null) { digest = Long.parseLong(line.trim()); depend = new Depend(archivePath, digest); if (! depend.isModified()) return true; } } catch (Throwable e) { log.log(Level.FINE, e.toString(), e); } finally { if (is != null) is.close(); } } if (depend == null) depend = new Depend(archivePath); try { if (log.isLoggable(Level.INFO)) getLog().info("expanding " + archivePath + " to " + expandDir); removeExpandDirectory(expandDir); expandDir.mkdirs(); ReadStream rs = archivePath.openRead(); ZipInputStream zis = new ZipInputStream(rs); try { ZipEntry entry = zis.getNextEntry(); byte []buffer = new byte[1024]; while (entry != null) { String name = entry.getName(); Path path = expandDir.lookup(name); if (entry.isDirectory()) path.mkdirs(); else { long entryLength = entry.getSize(); long length = entryLength; // XXX: avoids unexpected end of ZLIB input stream. // XXX: This should be a really temp. workaround. int bufferLen = buffer.length; // XXX: avoids unexpected end of ZLIB input stream. if (length < 0) { // bufferLen = 1; length = Long.MAX_VALUE / 2; } else if (length < bufferLen) { bufferLen = (int) length; } long lastModified = entry.getTime(); path.getParent().mkdirs(); WriteStream os = path.openWrite(); int len = 0; try { if (bufferLen == 1) { for (int ch = zis.read(); ch != -1; ch = zis.read()) os.write(ch); } else { while ((len = zis.read(buffer, 0, bufferLen)) > 0) { os.write(buffer, 0, len); // XXX: avoids unexpected end of ZLIB input stream. /* if (len < bufferLen) { for (int ch = zis.read(); ch != -1; ch = zis.read()) os.write(ch); break; } */ length -= len; if (length < bufferLen) { bufferLen = (int) length; } } } } catch (IOException e) { Exception ex = new Exception("IOException when expanding entry "+entry+" in "+archivePath+", entry.length: "+entryLength+" entry.compressed: "+entry.getCompressedSize()+", bufferLen: "+bufferLen+", read len: "+len+", remaining: "+length,e); log.log(Level.FINE, ex.toString(), ex); } finally { os.close(); } if (lastModified > 0) path.setLastModified(lastModified); } try { entry = zis.getNextEntry(); } catch (IOException e) { log.log(Level.FINE, e.toString(), e); // XXX: avoids unexpected end of ZLIB input stream. break; } } } finally { try { zis.close(); } catch (IOException e) { } rs.close(); } } catch (IOException e) { log.log(Level.WARNING, e.toString(), e); // If the jar is incomplete, it should throw an exception here. return false; } try { dependPath.getParent().mkdirs(); WriteStream os = dependPath.openWrite(); os.println(depend.getDigest()); os.close(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } return true; } /** * Recursively remove all files in a directory. Used for wars when * they change. * * @param path root directory to start removal */ protected void removeExpandDirectory(Path path) { String prefix = path.getPath(); if (! prefix.endsWith("/")) prefix = prefix + "/"; removeExpandDirectory(path, prefix); } /** * Recursively remove all files in a directory. Used for wars when * they change. * * @param dir root directory to start removal */ protected void removeExpandDirectory(Path path, String prefix) { try { if (path.isDirectory()) { String []list = path.list(); for (int i = 0; list != null && i < list.length; i++) { removeExpandDirectory(path.lookup(list[i]), prefix); } } removeExpandFile(path, prefix); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } } /** * Removes an expanded file. */ protected void removeExpandFile(Path path, String prefix) throws IOException { if (_expandCleanupFileSet == null || _expandCleanupFileSet.isMatch(path, prefix)) path.remove(); } /** * Returns the hash code. */ public int hashCode() { return getId().hashCode(); } /** * Returns equality. */ public boolean equals(Object o) { // server/125g if (o == null || ! getClass().equals(o.getClass())) return false; DeployController controller = (DeployController) o; // XXX: s/b getRootDirectory? return getId().equals(controller.getId()); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?