    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 java.util.HashMap;
    021import java.util.List;
    022import java.util.Map;
    023import java.util.Vector;
    024
    025/**
    026 * This class produces instances of the Verifier class. Its purpose is to make sure that they are singleton instances
    027 * with respect to the class name they operate on. That means, for every class (represented by a unique fully qualified
    028 * class name) there is exactly one Verifier.
    029 *
    030 * @see Verifier
    031 */
    032public class VerifierFactory {
    033
    034    /**
    035     * The HashMap that holds the data about the already-constructed Verifier instances.
    036     */
    037    private static final Map<String, Verifier> MAP = new HashMap<>();
    038
    039    /**
    040     * The VerifierFactoryObserver instances that observe the VerifierFactory.
    041     */
    042    private static final List<VerifierFactoryObserver> OBSVERVERS = new Vector<>();
    043
    044    /**
    045     * Adds the VerifierFactoryObserver o to the list of observers.
    046     */
    047    public static void attach(final VerifierFactoryObserver o) {
    048        OBSVERVERS.add(o);
    049    }
    050
    051    /**
    052     * Removes the VerifierFactoryObserver o from the list of observers.
    053     */
    054    public static void detach(final VerifierFactoryObserver o) {
    055        OBSVERVERS.remove(o);
    056    }
    057
    058    /**
    059     * Returns the (only) verifier responsible for the class with the given name. Possibly a new Verifier object is
    060     * transparently created.
    061     *
    062     * @return the (only) verifier responsible for the class with the given name.
    063     */
    064    public static Verifier getVerifier(final String fullyQualifiedClassName) {
    065        return MAP.computeIfAbsent(fullyQualifiedClassName, k -> {
    066            final Verifier v = new Verifier(k);
    067            notify(k);
    068            return v;
    069        });
    070    }
    071
    072    /**
    073     * Returns all Verifier instances created so far. This is useful when a Verifier recursively lets the VerifierFactory
    074     * create other Verifier instances and if you want to verify the transitive hull of referenced class files.
    075     */
    076    public static Verifier[] getVerifiers() {
    077        return MAP.values().toArray(Verifier.EMPTY_ARRAY);
    078    }
    079
    080    /**
    081     * Notifies the observers of a newly generated Verifier.
    082     */
    083    private static void notify(final String fullyQualifiedClassName) {
    084        // notify the observers
    085        OBSVERVERS.forEach(vfo -> vfo.update(fullyQualifiedClassName));
    086    }
    087
    088    /**
    089     * The VerifierFactory is not instantiable.
    090     */
    091    private VerifierFactory() {
    092    }
    093}