1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * https://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.bcel.verifier;
20
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Vector;
25
26 /**
27 * This class produces instances of the Verifier class. Its purpose is to make sure that they are singleton instances
28 * with respect to the class name they operate on. That means, for every class (represented by a unique fully qualified
29 * class name) there is exactly one Verifier.
30 *
31 * @see Verifier
32 */
33 public class VerifierFactory {
34
35 /**
36 * The HashMap that holds the data about the already-constructed Verifier instances.
37 */
38 private static final Map<String, Verifier> MAP = new HashMap<>();
39
40 /**
41 * The VerifierFactoryObserver instances that observe the VerifierFactory.
42 */
43 private static final List<VerifierFactoryObserver> OBSVERVERS = new Vector<>();
44
45 /**
46 * Adds the VerifierFactoryObserver o to the list of observers.
47 */
48 public static void attach(final VerifierFactoryObserver o) {
49 OBSVERVERS.add(o);
50 }
51
52 /**
53 * Clears the factory.
54 *
55 * @since 6.6.2
56 */
57 public static void clear() {
58 MAP.clear();
59 OBSVERVERS.clear();
60 }
61
62 /**
63 * Removes the VerifierFactoryObserver o from the list of observers.
64 */
65 public static void detach(final VerifierFactoryObserver o) {
66 OBSVERVERS.remove(o);
67 }
68
69 /**
70 * Returns the (only) verifier responsible for the class with the given name. Possibly a new Verifier object is
71 * transparently created.
72 *
73 * @return the (only) verifier responsible for the class with the given name.
74 */
75 public static Verifier getVerifier(final String fullyQualifiedClassName) {
76 return MAP.computeIfAbsent(fullyQualifiedClassName, k -> {
77 final Verifier v = new Verifier(k);
78 notify(k);
79 return v;
80 });
81 }
82
83 /**
84 * Returns all Verifier instances created so far. This is useful when a Verifier recursively lets the VerifierFactory
85 * create other Verifier instances and if you want to verify the transitive hull of referenced class files.
86 */
87 public static Verifier[] getVerifiers() {
88 return MAP.values().toArray(Verifier.EMPTY_ARRAY);
89 }
90
91 /**
92 * Notifies the observers of a newly generated Verifier.
93 */
94 private static void notify(final String fullyQualifiedClassName) {
95 // notify the observers
96 OBSVERVERS.forEach(vfo -> vfo.update(fullyQualifiedClassName));
97 }
98
99 /**
100 * The VerifierFactory is not instantiable.
101 */
102 private VerifierFactory() {
103 }
104 }