All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.deployment.common.ClassDependencyBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.deployment.common;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 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());
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy