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