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

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

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * 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());
        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy