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