    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one
    003 * or more contributor license agreements.  See the NOTICE file
    004 * distributed with this work for additional information
    005 * regarding copyright ownership.  The ASF licenses this file
    006 * to you under the Apache License, Version 2.0 (the
    007 * "License"); you may not use this file except in compliance
    008 * with the License.  You may obtain a copy of the License at
    009 *
    010 *   https://www.apache.org/licenses/LICENSE-2.0
    011 *
    012 * Unless required by applicable law or agreed to in writing,
    013 * software distributed under the License is distributed on an
    014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015 * KIND, either express or implied.  See the License for the
    016 * specific language governing permissions and limitations
    017 * under the License.
    018 */
    019package org.apache.bcel.verifier;
    020
    021import org.apache.bcel.Repository;
    022import org.apache.bcel.classfile.JavaClass;
    023import org.apache.bcel.classfile.Utility;
    024
    025/**
    026 * This class has a main method implementing a demonstration program of how to use the VerifierFactoryObserver. It
    027 * transitively verifies all class files encountered; this may take up a lot of time and, more notably, memory.
    028 */
    029public class TransitiveHull implements VerifierFactoryObserver {
    030
    031    /**
    032     * This method implements a demonstration program of how to use the VerifierFactoryObserver. It transitively verifies
    033     * all class files encountered; this may take up a lot of time and, more notably, memory.
    034     */
    035    public static void main(final String[] args) {
    036        if (args.length != 1) {
    037            System.out.println("Need exactly one argument: The root class to verify.");
    038            System.exit(1);
    039        }
    040        final int dotclasspos = args[0].lastIndexOf(JavaClass.EXTENSION);
    041        if (dotclasspos != -1) {
    042            args[0] = args[0].substring(0, dotclasspos);
    043        }
    044        args[0] = Utility.pathToPackage(args[0]);
    045        final TransitiveHull th = new TransitiveHull();
    046        VerifierFactory.attach(th);
    047        VerifierFactory.getVerifier(args[0]); // the observer is called back and does the actual trick.
    048        VerifierFactory.detach(th);
    049    }
    050
    051    /** Used for indentation. */
    052    private int indent;
    053
    054    /** Not publicly instantiable. */
    055    private TransitiveHull() {
    056    }
    057
    058    /* Implementing VerifierFactoryObserver. */
    059    @Override
    060    public void update(final String className) {
    061        System.gc(); // avoid swapping if possible.
    062        for (int i = 0; i < indent; i++) {
    063            System.out.print(" ");
    064        }
    065        System.out.println(className);
    066        indent += 1;
    067        final Verifier v = VerifierFactory.getVerifier(className);
    068        VerificationResult vr;
    069        vr = v.doPass1();
    070        if (vr != VerificationResult.VR_OK) {
    071            System.out.println("Pass 1:\n" + vr);
    072        }
    073        vr = v.doPass2();
    074        if (vr != VerificationResult.VR_OK) {
    075            System.out.println("Pass 2:\n" + vr);
    076        }
    077        if (vr == VerificationResult.VR_OK) {
    078            try {
    079                final JavaClass jc = Repository.lookupClass(v.getClassName());
    080                for (int i = 0; i < jc.getMethods().length; i++) {
    081                    vr = v.doPass3a(i);
    082                    if (vr != VerificationResult.VR_OK) {
    083                        System.out.println(v.getClassName() + ", Pass 3a, method " + i + " ['" + jc.getMethods()[i] + "']:\n" + vr);
    084                    }
    085                    vr = v.doPass3b(i);
    086                    if (vr != VerificationResult.VR_OK) {
    087                        System.out.println(v.getClassName() + ", Pass 3b, method " + i + " ['" + jc.getMethods()[i] + "']:\n" + vr);
    088                    }
    089                }
    090            } catch (final ClassNotFoundException e) {
    091                System.err.println("Could not find class " + v.getClassName() + " in Repository");
    092            }
    093        }
    094        indent -= 1;
    095    }
    096}