/* * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /*****************************************************************************//* Copyright (c) IBM Corporation 1998 *//* *//* (C) Copyright IBM Corp. 1998 *//* *//*****************************************************************************/ package sun.rmi.rmic; import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.util.Collection;import java.util.Enumeration;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.StringTokenizer;import java.util.Vector;import java.util.jar.JarFile;import java.util.jar.Manifest;import java.util.jar.Attributes;import sun.tools.java.ClassPath; /** * BatchEnvironment for rmic extends javac's version in four ways: * 1. It overrides errorString() to handle looking for rmic-specific * error messages in rmic's resource bundle * 2. It provides a mechanism for recording intermediate generated * files so that they can be deleted later. * 3. It holds a reference to the Main instance so that generators * can refer to it. * 4. It provides access to the ClassPath passed to the constructor. * * WARNING: The contents of this source file are not part of any * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */ public class BatchEnvironment extends sun.tools.javac.BatchEnvironment { /** instance of Main which created this environment */ private Main main; /** * Create a ClassPath object for rmic from a class path string. */ public static ClassPath createClassPath(String classPathString) { ClassPath[] paths = classPaths(null, classPathString, null, null); return paths[1]; } /** * Create a ClassPath object for rmic from the relevant command line * options for class path, boot class path, and extension directories. */ public static ClassPath createClassPath(String classPathString, String sysClassPathString, String extDirsString) { /** * Previously, this method delegated to the * sun.tools.javac.BatchEnvironment.classPaths method in order * to supply default values for paths not specified on the * command line, expand extensions directories into specific * JAR files, and construct the ClassPath object-- but as part * of the fix for 6473331, which adds support for Class-Path * manifest entries in JAR files, those steps are now handled * here directly, with the help of a Path utility class copied * from the new javac implementation (see below). */ Path path = new Path(); if (sysClassPathString == null) { sysClassPathString = System.getProperty("sun.boot.class.path"); } if (sysClassPathString != null) { path.addFiles(sysClassPathString); } /* * Class-Path manifest entries are supported for JAR files * everywhere except in the boot class path. */ path.expandJarClassPaths(true); if (extDirsString == null) { extDirsString = System.getProperty("java.ext.dirs"); } if (extDirsString != null) { path.addDirectories(extDirsString); } /* * In the application class path, an empty element means * the current working directory. */ path.emptyPathDefault("."); if (classPathString == null) { // The env.class.path property is the user's CLASSPATH // environment variable, and it set by the wrapper (ie, // javac.exe). classPathString = System.getProperty("env.class.path"); if (classPathString == null) { classPathString = "."; } } path.addFiles(classPathString); return new ClassPath(path.toArray(new String[path.size()])); } /** * Create a BatchEnvironment for rmic with the given class path, * stream for messages and Main. */ public BatchEnvironment(OutputStream out, ClassPath path, Main main) { super(out, new ClassPath(""), path); // use empty "sourcePath" (see 4666958) this.main = main; } /** * Get the instance of Main which created this environment. */ public Main getMain() { return main; } /** * Get the ClassPath. */ public ClassPath getClassPath() { return binaryPath; } /** list of generated source files created in this environment */ private Vector generatedFiles = new Vector(); /** * Remember a generated source file generated so that it * can be removed later, if appropriate. */ public void addGeneratedFile(File file) { generatedFiles.addElement(file); } /** * Delete all the generated source files made during the execution * of this environment (those that have been registered with the * "addGeneratedFile" method). */ public void deleteGeneratedFiles() { synchronized(generatedFiles) { Enumeration enumeration = generatedFiles.elements(); while (enumeration.hasMoreElements()) { File file = (File) enumeration.nextElement(); file.delete(); } generatedFiles.removeAllElements(); } } /** * Release resources, if any. */ public void shutdown() { main = null; generatedFiles = null; super.shutdown(); } /** * Return the formatted, localized string for a named error message * and supplied arguments. For rmic error messages, with names that * being with "rmic.", look up the error message in rmic's resource * bundle; otherwise, defer to java's superclass method. */ public String errorString(String err, Object arg0, Object arg1, Object arg2) { if (err.startsWith("rmic.") || err.startsWith("warn.rmic.")) { String result = Main.getText(err, (arg0 != null ? arg0.toString() : null), (arg1 != null ? arg1.toString() : null), (arg2 != null ? arg2.toString() : null)); if (err.startsWith("warn.")) { result = "warning: " + result; } return result; } else { return super.errorString(err, arg0, arg1, arg2); } } public void reset() { } /** * Utility for building paths of directories and JAR files. This * class was copied from com.sun.tools.javac.util.Paths as part of * the fix for 6473331, which adds support for Class-Path manifest * entries in JAR files. Diagnostic code is simply commented out * because rmic silently ignored these conditions historically. */ private static class Path extends LinkedHashSet<String> { private static final long serialVersionUID = 0; private static final boolean warn = false; private static class PathIterator implements Collection<String> { private int pos = 0; private final String path; private final String emptyPathDefault; public PathIterator(String path, String emptyPathDefault) { this.path = path; this.emptyPathDefault = emptyPathDefault; } public PathIterator(String path) { this(path, null); } public Iterator<String> iterator() { return new Iterator<String>() { public boolean hasNext() { return pos <= path.length(); } public String next() { int beg = pos; int end = path.indexOf(File.pathSeparator, beg); if (end == -1) end = path.length(); pos = end + 1; if (beg == end && emptyPathDefault != null) return emptyPathDefault; else return path.substring(beg, end); } public void remove() { throw new UnsupportedOperationException(); } }; } // required for Collection. public int size() { throw new UnsupportedOperationException(); } public boolean isEmpty() { throw new UnsupportedOperationException(); } public boolean contains(Object o) { throw new UnsupportedOperationException(); } public Object[] toArray() { throw new UnsupportedOperationException(); } public <T> T[] toArray(T[] a) { throw new UnsupportedOperationException(); } public boolean add(String o) { throw new UnsupportedOperationException(); } public boolean remove(Object o) { throw new UnsupportedOperationException(); } public boolean containsAll(Collection<?> c) { throw new UnsupportedOperationException(); } public boolean addAll(Collection<? extends String> c) { throw new UnsupportedOperationException(); } public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } public void clear() { throw new UnsupportedOperationException(); } public boolean equals(Object o) { throw new UnsupportedOperationException(); } public int hashCode() { throw new UnsupportedOperationException(); } } /** Is this the name of a zip file? */ private static boolean isZip(String name) { return new File(name).isFile(); } private boolean expandJarClassPaths = false; public Path expandJarClassPaths(boolean x) { expandJarClassPaths = x; return this; } /** What to use when path element is the empty string */ private String emptyPathDefault = null; public Path emptyPathDefault(String x) { emptyPathDefault = x; return this; } public Path() { super(); } public Path addDirectories(String dirs, boolean warn) { if (dirs != null) for (String dir : new PathIterator(dirs)) addDirectory(dir, warn); return this; } public Path addDirectories(String dirs) { return addDirectories(dirs, warn); } private void addDirectory(String dir, boolean warn) { if (! new File(dir).isDirectory()) {// if (warn)// log.warning(Position.NOPOS,// "dir.path.element.not.found", dir); return; } for (String direntry : new File(dir).list()) { String canonicalized = direntry.toLowerCase(); if (canonicalized.endsWith(".jar") || canonicalized.endsWith(".zip")) addFile(dir + File.separator + direntry, warn); } } public Path addFiles(String files, boolean warn) { if (files != null) for (String file : new PathIterator(files, emptyPathDefault)) addFile(file, warn); return this; } public Path addFiles(String files) { return addFiles(files, warn); } private void addFile(String file, boolean warn) { if (contains(file)) { /* Discard duplicates and avoid infinite recursion */ return; } File ele = new File(file); if (! ele.exists()) { /* No such file or directory exist */ if (warn)// log.warning(Position.NOPOS,// "path.element.not.found", file); return; } if (ele.isFile()) { /* File is an ordinay file */ String arcname = file.toLowerCase(); if (! (arcname.endsWith(".zip") || arcname.endsWith(".jar"))) { /* File name don't have right extension */// if (warn)// log.warning(Position.NOPOS,// "invalid.archive.file", file); return; } } /* Now what we have left is either a directory or a file name confirming to archive naming convention */ super.add(file); if (expandJarClassPaths && isZip(file)) addJarClassPath(file, warn); } // Adds referenced classpath elements from a jar's Class-Path // Manifest entry. In some future release, we may want to // update this code to recognize URLs rather than simple // filenames, but if we do, we should redo all path-related code. private void addJarClassPath(String jarFileName, boolean warn) { try { String jarParent = new File(jarFileName).getParent(); JarFile jar = new JarFile(jarFileName); try { Manifest man = jar.getManifest(); if (man == null) return; Attributes attr = man.getMainAttributes(); if (attr == null) return; String path = attr.getValue(Attributes.Name.CLASS_PATH); if (path == null) return; for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens();) { String elt = st.nextToken(); if (jarParent != null) elt = new File(jarParent, elt).getCanonicalPath(); addFile(elt, warn); } } finally { jar.close(); } } catch (IOException e) {// log.error(Position.NOPOS,// "error.reading.file", jarFileName,// e.getLocalizedMessage()); } } }}
/*
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*****************************************************************************/
/* Copyright (c) IBM Corporation 1998 */
/* */
/* (C) Copyright IBM Corp. 1998 */
/* */
/*****************************************************************************/
package sun.rmi.rmic;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import sun.tools.java.ClassPath;
/**
* BatchEnvironment for rmic extends javac's version in four ways:
* 1. It overrides errorString() to handle looking for rmic-specific
* error messages in rmic's resource bundle
* 2. It provides a mechanism for recording intermediate generated
* files so that they can be deleted later.
* 3. It holds a reference to the Main instance so that generators
* can refer to it.
* 4. It provides access to the ClassPath passed to the constructor.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public class BatchEnvironment extends sun.tools.javac.BatchEnvironment {
/** instance of Main which created this environment */
private Main main;
/**
* Create a ClassPath object for rmic from a class path string.
*/
public static ClassPath createClassPath(String classPathString) {
ClassPath[] paths = classPaths(null, classPathString, null, null);
return paths[1];
}
/**
* Create a ClassPath object for rmic from the relevant command line
* options for class path, boot class path, and extension directories.
*/
public static ClassPath createClassPath(String classPathString,
String sysClassPathString,
String extDirsString)
{
/**
* Previously, this method delegated to the
* sun.tools.javac.BatchEnvironment.classPaths method in order
* to supply default values for paths not specified on the
* command line, expand extensions directories into specific
* JAR files, and construct the ClassPath object-- but as part
* of the fix for 6473331, which adds support for Class-Path
* manifest entries in JAR files, those steps are now handled
* here directly, with the help of a Path utility class copied
* from the new javac implementation (see below).
*/
Path path = new Path();
if (sysClassPathString == null) {
sysClassPathString = System.getProperty("sun.boot.class.path");
}
if (sysClassPathString != null) {
path.addFiles(sysClassPathString);
}
/*
* Class-Path manifest entries are supported for JAR files
* everywhere except in the boot class path.
*/
path.expandJarClassPaths(true);
if (extDirsString == null) {
extDirsString = System.getProperty("java.ext.dirs");
}
if (extDirsString != null) {
path.addDirectories(extDirsString);
}
/*
* In the application class path, an empty element means
* the current working directory.
*/
path.emptyPathDefault(".");
if (classPathString == null) {
// The env.class.path property is the user's CLASSPATH
// environment variable, and it set by the wrapper (ie,
// javac.exe).
classPathString = System.getProperty("env.class.path");
if (classPathString == null) {
classPathString = ".";
}
}
path.addFiles(classPathString);
return new ClassPath(path.toArray(new String[path.size()]));
}
/**
* Create a BatchEnvironment for rmic with the given class path,
* stream for messages and Main.
*/
public BatchEnvironment(OutputStream out, ClassPath path, Main main) {
super(out, new ClassPath(""), path);
// use empty "sourcePath" (see 4666958)
this.main = main;
}
/**
* Get the instance of Main which created this environment.
*/
public Main getMain() {
return main;
}
/**
* Get the ClassPath.
*/
public ClassPath getClassPath() {
return binaryPath;
}
/** list of generated source files created in this environment */
private Vector generatedFiles = new Vector();
/**
* Remember a generated source file generated so that it
* can be removed later, if appropriate.
*/
public void addGeneratedFile(File file) {
generatedFiles.addElement(file);
}
/**
* Delete all the generated source files made during the execution
* of this environment (those that have been registered with the
* "addGeneratedFile" method).
*/
public void deleteGeneratedFiles() {
synchronized(generatedFiles) {
Enumeration enumeration = generatedFiles.elements();
while (enumeration.hasMoreElements()) {
File file = (File) enumeration.nextElement();
file.delete();
}
generatedFiles.removeAllElements();
}
}
/**
* Release resources, if any.
*/
public void shutdown() {
main = null;
generatedFiles = null;
super.shutdown();
}
/**
* Return the formatted, localized string for a named error message
* and supplied arguments. For rmic error messages, with names that
* being with "rmic.", look up the error message in rmic's resource
* bundle; otherwise, defer to java's superclass method.
*/
public String errorString(String err,
Object arg0, Object arg1, Object arg2)
{
if (err.startsWith("rmic.") || err.startsWith("warn.rmic.")) {
String result = Main.getText(err,
(arg0 != null ? arg0.toString() : null),
(arg1 != null ? arg1.toString() : null),
(arg2 != null ? arg2.toString() : null));
if (err.startsWith("warn.")) {
result = "warning: " + result;
}
return result;
} else {
return super.errorString(err, arg0, arg1, arg2);
}
}
public void reset() {
}
/**
* Utility for building paths of directories and JAR files. This
* class was copied from com.sun.tools.javac.util.Paths as part of
* the fix for 6473331, which adds support for Class-Path manifest
* entries in JAR files. Diagnostic code is simply commented out
* because rmic silently ignored these conditions historically.
*/
private static class Path extends LinkedHashSet<String> {
private static final long serialVersionUID = 0;
private static final boolean warn = false;
private static class PathIterator implements Collection<String> {
private int pos = 0;
private final String path;
private final String emptyPathDefault;
public PathIterator(String path, String emptyPathDefault) {
this.path = path;
this.emptyPathDefault = emptyPathDefault;
}
public PathIterator(String path) { this(path, null); }
public Iterator<String> iterator() {
return new Iterator<String>() {
public boolean hasNext() {
return pos <= path.length();
}
public String next() {
int beg = pos;
int end = path.indexOf(File.pathSeparator, beg);
if (end == -1)
end = path.length();
pos = end + 1;
if (beg == end && emptyPathDefault != null)
return emptyPathDefault;
else
return path.substring(beg, end);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
// required for Collection.
public int size() {
throw new UnsupportedOperationException();
}
public boolean isEmpty() {
throw new UnsupportedOperationException();
}
public boolean contains(Object o) {
throw new UnsupportedOperationException();
}
public Object[] toArray() {
throw new UnsupportedOperationException();
}
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
public boolean add(String o) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean containsAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection<? extends String> c) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean equals(Object o) {
throw new UnsupportedOperationException();
}
public int hashCode() {
throw new UnsupportedOperationException();
}
}
/** Is this the name of a zip file? */
private static boolean isZip(String name) {
return new File(name).isFile();
}
private boolean expandJarClassPaths = false;
public Path expandJarClassPaths(boolean x) {
expandJarClassPaths = x;
return this;
}
/** What to use when path element is the empty string */
private String emptyPathDefault = null;
public Path emptyPathDefault(String x) {
emptyPathDefault = x;
return this;
}
public Path() { super(); }
public Path addDirectories(String dirs, boolean warn) {
if (dirs != null)
for (String dir : new PathIterator(dirs))
addDirectory(dir, warn);
return this;
}
public Path addDirectories(String dirs) {
return addDirectories(dirs, warn);
}
private void addDirectory(String dir, boolean warn) {
if (! new File(dir).isDirectory()) {
// if (warn)
// log.warning(Position.NOPOS,
// "dir.path.element.not.found", dir);
return;
}
for (String direntry : new File(dir).list()) {
String canonicalized = direntry.toLowerCase();
if (canonicalized.endsWith(".jar") ||
canonicalized.endsWith(".zip"))
addFile(dir + File.separator + direntry, warn);
}
}
public Path addFiles(String files, boolean warn) {
if (files != null)
for (String file : new PathIterator(files, emptyPathDefault))
addFile(file, warn);
return this;
}
public Path addFiles(String files) {
return addFiles(files, warn);
}
private void addFile(String file, boolean warn) {
if (contains(file)) {
/* Discard duplicates and avoid infinite recursion */
return;
}
File ele = new File(file);
if (! ele.exists()) {
/* No such file or directory exist */
if (warn)
// log.warning(Position.NOPOS,
// "path.element.not.found", file);
return;
}
if (ele.isFile()) {
/* File is an ordinay file */
String arcname = file.toLowerCase();
if (! (arcname.endsWith(".zip") ||
arcname.endsWith(".jar"))) {
/* File name don't have right extension */
// if (warn)
// log.warning(Position.NOPOS,
// "invalid.archive.file", file);
return;
}
}
/* Now what we have left is either a directory or a file name
confirming to archive naming convention */
super.add(file);
if (expandJarClassPaths && isZip(file))
addJarClassPath(file, warn);
}
// Adds referenced classpath elements from a jar's Class-Path
// Manifest entry. In some future release, we may want to
// update this code to recognize URLs rather than simple
// filenames, but if we do, we should redo all path-related code.
private void addJarClassPath(String jarFileName, boolean warn) {
try {
String jarParent = new File(jarFileName).getParent();
JarFile jar = new JarFile(jarFileName);
try {
Manifest man = jar.getManifest();
if (man == null) return;
Attributes attr = man.getMainAttributes();
if (attr == null) return;
String path = attr.getValue(Attributes.Name.CLASS_PATH);
if (path == null) return;
for (StringTokenizer st = new StringTokenizer(path);
st.hasMoreTokens();) {
String elt = st.nextToken();
if (jarParent != null)
elt = new File(jarParent, elt).getCanonicalPath();
addFile(elt, warn);
}
} finally {
jar.close();
}
} catch (IOException e) {
// log.error(Position.NOPOS,
// "error.reading.file", jarFileName,
// e.getLocalizedMessage());
}
}
}
}