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