com.sun.enterprise.tools.verifier.apiscan.classfile.BCELClosureCompilerImpl Maven / Gradle / Ivy
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2011 Oracle and/or its affiliates. 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_1_1.html
* or packager/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 packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [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.
*/
package com.sun.enterprise.tools.verifier.apiscan.classfile;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
/**
* An implementation of {@link ClosureCompilerImplBase} based on
* BCEL.
*
* @author [email protected]
*/
public class BCELClosureCompilerImpl extends ClosureCompilerImplBase {
/*
* Earlier this class used to be called as ClosureCompilerImpl.
* So to get the history of this file, use above name in CVS
*/
private Stack callStack = new Stack();
private HashSet closure = new HashSet();
private HashSet nativeMethods = new HashSet();
//map of refencing path to list of not found classes.
private Map> failed = new HashMap>();
private static final String myClassName = "BCELClosureCompilerImpl"; // NOI18N
/**
* @param loader the ClassFileLoader that is used to load the referenced
* classes.
*/
public BCELClosureCompilerImpl(ClassFileLoader loader) {
super(loader);
}
//See corresponding method of ClosureCompiler for javadocs
public boolean buildClosure(String className) {
logger.entering(myClassName, "buildClosure", className); // NOI18N
ClassFile cf;
if (!needToBuildClosure(className))
return true;
try {
cf = loader.load(className);
} catch (IOException e) {
handleFailure(className);
return false;
}
return buildClosure(cf);
}
/**
* @param cf class file whose closure needs to be computed. The behavior is
* same as the other buildClosure() method.
*/
private boolean buildClosure(ClassFile cf) {
boolean result = true;
callStack.push(cf);
if (needToBuildClosure(cf.getName())) {
visitedClasses.add(cf.getName());
Collection names = cf.getAllReferencedClassNames();
closure.addAll(names);
// TODO: We should not be doing this here. Its just a quick &
// dirty solution.
for(Method m : cf.getMethods()) {
if(m.isNative()) {
final String methodDesc =
m.getOwningClass().getName()+ "." + m.getName(); // NOI18N
nativeMethods.add(methodDesc);
}
}
for (Iterator i = names.iterator(); i.hasNext();) {
String nextExternalName = (String) i.next();
if (!needToBuildClosure(nextExternalName)) continue;
ClassFile next;
try {
next = loader.load(nextExternalName);
} catch (IOException e) {
result = false;
handleFailure(nextExternalName);
continue;
}
boolean newresult = buildClosure(next);//recurssive call
result = newresult && result;
}
}
callStack.pop();
return result;
}
private void handleFailure(String referencedClass) {
String referencingPath = "";
try {
StringBuilder referencingPathBuffer = new StringBuilder();
for (Iterator i = callStack.iterator(); i.hasNext();) {
if (referencingPathBuffer.length() != 0)
referencingPathBuffer.append(File.separator);
referencingPathBuffer.append(((ClassFile) i.next()).getName());
}
referencingPath = referencingPathBuffer.toString();
} catch (EmptyStackException e) {
}
logger.finer(
"Could not locate " + referencingPath + File.separator + // NOI18N
referencedClass);
List failedList = failed.get(referencingPath);
if (failedList == null) {
failedList = new ArrayList();
failed.put(referencingPath, failedList);
}
failedList.add(referencedClass);
}
//See corresponding method of ClosureCompiler for javadocs
public Collection getClosure() {
return Collections.unmodifiableCollection(closure);
}
//See corresponding method of ClosureCompiler for javadocs
public Map getFailed() {
return Collections.unmodifiableMap(failed);
}
/**
* Reset the closure for next closure computation.
* Clear the internal cache. It includes the result it has collected since
* last reset(). But it does not clear the excludedd list. If you want to
* reset the excluded list, create a new ClosureCompiler.
*/
public void reset() {
closure.clear();
visitedClasses.clear();
failed.clear();
nativeMethods.clear();
}
public Collection getNativeMethods() {
return Collections.unmodifiableCollection(nativeMethods);
}
public String toString() {
StringBuilder sb=new StringBuilder();
if(logger.isLoggable(Level.FINER)){
sb.append("\n"); // NOI18N
sb.append("\n\t"); // NOI18N
for(Iterator i=excludedClasses.iterator(); i.hasNext();) {
sb.append("\n\t\t"); // NOI18N
sb.append((String)i.next());
}
sb.append("\n\t "); // NOI18N
sb.append("\n\t"); // NOI18N
for(Iterator i=excludedPackages.iterator(); i.hasNext();){
sb.append("\n\t\t"); // NOI18N
sb.append((String)i.next());
}
sb.append("\n\t "); // NOI18N
sb.append("\n\t"); // NOI18N
for(Iterator i=excludedPatterns.iterator(); i.hasNext();){
sb.append("\n\t\t"); // NOI18N
sb.append((String)i.next());
}
sb.append("\n\t "); // NOI18N
sb.append("\n\t"); // NOI18N
for(Iterator i=closure.iterator(); i.hasNext();){
sb.append("\n\t\t"); // NOI18N
sb.append((String)i.next());
}
sb.append("\n\t "); // NOI18N
}
sb.append("\n\t"); // NOI18N
for(Iterator i=failed.entrySet().iterator(); i.hasNext();) {
Map.Entry referencingPathToFailedList=(Map.Entry)i.next();
sb.append("\n\t\t"); // NOI18N
sb.append(""); // NOI18N
sb.append("\n\t\t\t"); // NOI18N
sb.append(referencingPathToFailedList.getKey());
sb.append("\n\t\t"); // NOI18N
sb.append(" "); // NOI18N
sb.append("\n\t\t"); // NOI18N
sb.append(""); // NOI18N
for(Iterator iii=((List)referencingPathToFailedList.getValue()).iterator(); iii.hasNext();){
sb.append("\n\t\t\t"); // NOI18N
sb.append((String)iii.next());
}
sb.append("\n\t\t"); // NOI18N
sb.append(" "); // NOI18N
}
sb.append("\n\t "); // NOI18N
sb.append("\n\t"); // NOI18N
for(String s : nativeMethods) {
sb.append("\n\t\t"); // NOI18N
sb.append(s);
}
sb.append("\n\t "); // NOI18N
if(logger.isLoggable(Level.FINER)){
sb.append("\n "); // NOI18N
}
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy