org.glassfish.deployment.common.ClassDependencyBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009-2010 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 org.glassfish.deployment.common;
import java.util.*;
/**
* A class that can answer the following queries WITHOUT loading any classes
*
* Given a class C
* 1. Find out all sub classes of C
*
* 2. Find out all classes that implemetns OR extends C
*
* 3. Find out all classes that are annotated with C
*
*
* Usage:
*
* ClassDependencyBuilder cdb = new GraphBuilder();
* cdb.loadClassData(c1);
* cdb.loadClassData(c2);
* cdb.loadClassData(c3);
* ...
* ...
*
* cdb.computeResult(c); // c can be any fully qualified class name (internal format or java format)
*
* @author Mahesh Kannan
*/
public class ClassDependencyBuilder {
private Map mappings = new HashMap();
public ClassDependencyBuilder() {
}
public Set computeResult(String name) {
name = name.replace('.', '/');
NodeInfo ni = mappings.get(name);
if (ni != null) {
if (ni.isAnnotation()) {
return getAnnotatedClasses(ni);
} else if (ni.isClass() || ni.isInterface()) {
return getSubClasses(ni, ni.isInterface());
} else {
//System.out.println("????");
}
} else {
//System.out.println("No info about: " + name);
}
return new HashSet();
}
private Set getAnnotatedClasses(NodeInfo ni) {
Set annotatedClasses = new HashSet();
if (ni != null) {
Set nInfos = ni.getDirectImplementors();
if ((nInfos != null) && (nInfos.size() > 0)) {
for (NodeInfo n : nInfos) {
annotatedClasses.add(n.getClassName());
}
}
}
return annotatedClasses;
}
private Set getSubClasses(NodeInfo node, boolean addImplementors) {
Set assignables = new HashSet();
if (node != null) {
List list = new LinkedList();
while (true) {
Set set = node.getDirectSubClass();
if ((set != null) && (set.size() > 0)) {
for (NodeInfo n : set) {
list.add(n);
}
}
if (addImplementors) {
Set intfs = node.getDirectImplementors();
if ((intfs != null) && (intfs.size() > 0)) {
for (NodeInfo n : intfs) {
list.add(n);
}
}
}
if (list.size() > 0) {
node = list.remove(0);
String name = node.getClassName();
if (!assignables.contains(name)) {
assignables.add(name);
}
} else {
break;
}
}
}
return assignables;
}
public void loadClassData(byte[] classData)
throws Exception {
NodeInfo node = new NodeInfo(classData);
String cname = node.getClassName();
NodeInfo nodeInfo = mappings.get(cname);
if ((nodeInfo == null) || (!nodeInfo.isParsed())) {
if (nodeInfo == null) {
mappings.put(cname, node);
nodeInfo = node;
} else {
nodeInfo.load(classData);
}
populateMapping(nodeInfo);
}
}
public int size() {
return mappings.size();
}
private void populateMapping(NodeInfo nodeInfo) {
String superName = nodeInfo.getSuperClassName();
if (superName != null) {
NodeInfo superNodeInfo = mappings.get(superName);
if (superNodeInfo == null) {
superNodeInfo = new NodeInfo(superName);
if (nodeInfo.isClass()) {
superNodeInfo.markAsClassType();
} else {
superNodeInfo.markAsInterfaceType();
}
mappings.put(superName, superNodeInfo);
}
superNodeInfo.addDirectSubClass(nodeInfo);
}
String[] interfaces = nodeInfo.getInterfaces();
if ((interfaces != null) && (interfaces.length > 0)) {
for (String interf : interfaces) {
NodeInfo interfNodeInfo = mappings.get(interf);
if (interfNodeInfo == null) {
interfNodeInfo = new NodeInfo(interf);
interfNodeInfo.markAsInterfaceType();
mappings.put(interf, interfNodeInfo);
}
interfNodeInfo.addDirectImplementor(nodeInfo);
}
}
List anns = nodeInfo.getClassLevelAnnotations();
if ((anns != null) && (anns.size() > 0)) {
for (String ann : anns) {
NodeInfo annNode = mappings.get(ann);
if (annNode == null) {
annNode = new NodeInfo(ann);
annNode.markAsAnnotaionType();
mappings.put(ann, annNode);
}
annNode.addDirectImplementor(nodeInfo);
}
}
}
void printInfo() {
for (NodeInfo node : mappings.values()) {
System.out.println(node.toString());
}
}
}