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}