/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
/*
* Archive.java
*
* Created on September 6, 2004, 9:10 AM
*/
package com.sun.enterprise.tools.verifier.apiscan.packaging;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Sanjeeb.Sahoo@Sun.COM
*/
public class Archive {
private Manifest manifest;
private File path;
private static String resourceBundleName = "com.sun.enterprise.tools.verifier.apiscan.LocalStrings";
private static Logger logger = Logger.getLogger("apiscan.archive", resourceBundleName); // NOI18N
private static final String myClassName = "Archive"; // NOI18N
private static Archive[] allOptPkgsInstalledInJRE;//note this is per JVM. It is lazily instantiated
private static String thisClassName = "com.sun.enterprise.tools.verifier.apiscan.packaging.Archive"; // NOI18N
//returns a unmodifiable collection of installed optional packages.
//once the method is called, for subsequent calls it retuns the same list
//even if new pkg is installed in JVM lib ext dir. This is in line with JVM operations.
public static Archive[] getAllOptPkgsInstalledInJRE() {
if (allOptPkgsInstalledInJRE != null) return allOptPkgsInstalledInJRE;
final ArrayList<Archive> allPkgs = new ArrayList<Archive>();
synchronized (Archive.class) {
if (allOptPkgsInstalledInJRE == null) {//double if check to avoid race condition
List ext_dirs = listAllExtDirs();
for (Iterator iter = ext_dirs.iterator(); iter.hasNext();) {
File ext_dir = new File((String) iter.next());
ext_dir.listFiles(new FileFilter() {
public boolean accept(File f) {
if (!f.isDirectory()) {
try {
allPkgs.add(new Archive(new JarFile(f)));
logger.logp(Level.FINE, myClassName,
"getAllOptPkgsInstalledInJRE", // NOI18N
"Found an installed opt pkg " + // NOI18N
f.getAbsolutePath());
return true;
} catch (Exception e) {
logger.logp(Level.INFO, myClassName,
"getAllOptPkgsInstalledInJRE", // NOI18N
thisClassName + ".exception1", new Object[]{f.toString()});
logger.log(Level.INFO, "", e);
}
}
return false;
}//accept()
});
}
}//if null
allOptPkgsInstalledInJRE = new Archive[allPkgs.size()];
allPkgs.toArray(allOptPkgsInstalledInJRE);
}//synchronized
return allOptPkgsInstalledInJRE;
}
private static List listAllExtDirs() {
String ext_dirStr = new String(System.getProperty("java.ext.dirs"));
logger.fine("Extension Dir Path is " + ext_dirStr); // NOI18N
ArrayList<String> ext_dirs = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(ext_dirStr,
File.pathSeparator);
while (st.hasMoreTokens()) {
String next = st.nextToken();
ext_dirs.add(next);
}
return ext_dirs;
}
/**
* Creates a new instance of Archive
*/
public Archive(JarFile jar) throws IOException {
manifest = jar.getManifest();
path = new File(jar.getName());
}
//path represnets either a dir or a jar file path
public Archive(File path) throws IOException {
this.path = path.getCanonicalFile();
}
public String getClassPath() throws IOException {
String cp = getManifest().getMainAttributes().getValue(
Attributes.Name.CLASS_PATH);
if (cp != null)
return cp;
else
return "";
}
//lazy initialisation
public synchronized Manifest getManifest() throws IOException {
if (manifest == null) {
if (path.isDirectory()) {
File file = new File(
path.getPath() + File.separator + JarFile.MANIFEST_NAME);
if (file.exists()) {
InputStream mis = new FileInputStream(file);
manifest = new Manifest(mis);
mis.close();
}
} else {
JarFile jar = new JarFile(path);
try {
manifest = jar.getManifest();
} finally {
jar.close();
}
}
if (manifest == null)
manifest = new Manifest();
}
return manifest;
}
/**
* @return the absolute path of this package. Depdnding on whether it was
* constructed from a dir or a jar file, the returned path
* represents either a file or a dir.
*/
public String getPath() {
return path.getAbsolutePath();
}
public Archive[] getBundledArchives() throws IOException {
ArrayList<Archive> list = new ArrayList<Archive>();
String parent = path.getParent() + File.separator;
for (StringTokenizer st = new StringTokenizer(getClassPath());
st.hasMoreTokens();) {
String nextEntry = st.nextToken();
String entryPath = parent + nextEntry;
if (!new File(entryPath).exists()) {
logger.logp(Level.FINE, myClassName, "getBundledArchives", // NOI18N
entryPath +
" does not exist, will try to see if this is a module whose name has been changed when archive was exploded."); // NOI18N
String newNextEntry;
//account for the fact that Class-Path may be specified as ./a.jar
if (nextEntry.startsWith("./") && nextEntry.length() > 2) // NOI18N
newNextEntry =
nextEntry.substring("./".length()).replaceAll( // NOI18N
"\\.", "_"); // NOI18N
else
newNextEntry = nextEntry.replaceAll("\\.", "_"); // NOI18N
if (new File(parent, newNextEntry).exists()) {
logger.logp(Level.FINE, myClassName, "getBundledArchives", // NOI18N
"Using " + newNextEntry + " instead of " + nextEntry); // NOI18N
entryPath = parent + newNextEntry;
list.add(new Archive(new File(entryPath)));
} else {
logger.logp(Level.WARNING, myClassName,
"getBundledArchives", // NOI18N
thisClassName + ".error1", new Object[]{getPath(), nextEntry});
}
}
list.add(new Archive(new File(entryPath)));
}
return (Archive[]) list.toArray(new Archive[0]);
}
/**
* @return the list of installed optional packages that this package depends
* on.
*/
public ExtensionRef[] getExtensionRefs() throws IOException {
ExtensionRef[] refs = new ExtensionRef[0];
Manifest manifest = getManifest();
String extensions = manifest.getMainAttributes().getValue(
Attributes.Name.EXTENSION_LIST);
ArrayList<ExtensionRef> extensionList = new ArrayList<ExtensionRef>();
if (extensions != null) {
for (StringTokenizer st = new StringTokenizer(extensions);
st.hasMoreTokens();) {
String extName = st.nextToken();
ExtensionRef ref = new ExtensionRef(manifest, extName);
extensionList.add(ref);
}
}
refs = (ExtensionRef[]) extensionList.toArray(refs);
return refs;
}
public String toString() {
return getPath();
}
}
|