View Javadoc
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   * http://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.commons.weaver.privilizer;
20  
21  import java.lang.annotation.ElementType;
22  import java.util.LinkedHashSet;
23  import java.util.Set;
24  
25  import org.apache.commons.lang3.Validate;
26  import org.apache.commons.weaver.model.ScanRequest;
27  import org.apache.commons.weaver.model.Scanner;
28  import org.apache.commons.weaver.model.WeavableClass;
29  import org.apache.commons.weaver.model.WeaveEnvironment;
30  import org.apache.commons.weaver.model.WeaveInterest;
31  import org.apache.commons.weaver.spi.Weaver;
32  
33  /**
34   * Privilizer {@link Weaver} implementation.
35   */
36  public class PrivilizerWeaver implements Weaver {
37      @Override
38      public boolean process(final WeaveEnvironment weaveEnvironment, final Scanner scanner) {
39          final Privilizer privilizer = new Privilizer(weaveEnvironment);
40  
41          final Set<Class<?>> privilizedTypes = new LinkedHashSet<>();
42  
43          // handle blueprints:
44          for (final WeavableClass<?> type : scanner.scan(
45              new ScanRequest().add(WeaveInterest.of(Privilizing.class, ElementType.TYPE))).getClasses()) {
46  
47              final Class<?> target = type.getTarget();
48              if (privilizedTypes.add(target) && validateRequest(privilizer, type)) {
49                  privilizer.blueprint(target, type.getAnnotation(Privilizing.class));
50              }
51          }
52  
53          // handle remaining classes declaring @Privileged methods:
54  
55          for (final WeavableClass<?> type : scanner.scan(
56              new ScanRequest().add(WeaveInterest.of(Privileged.class, ElementType.METHOD))).getClasses()) {
57              final Class<?> target = type.getTarget();
58              if (privilizedTypes.add(target) && validateRequest(privilizer, type)) {
59                  privilizer.privilize(target);
60              }
61          }
62          return !privilizedTypes.isEmpty();
63      }
64  
65      /**
66       * Validate a weaving request for a given target type.
67       * @param privilizer whose configuration to consult
68       * @param type target
69       * @return whether weaving should proceed
70       * @throws IllegalStateException if class has already been woven with some other policy
71       */
72      private boolean validateRequest(final Privilizer privilizer, final WeavableClass<?> type) {
73          final Privilized marker = type.getAnnotation(Privilized.class);
74          if (marker == null) {
75              return privilizer.policy != Policy.NEVER;
76          }
77          Validate.validState(privilizer.policy.name().equals(marker.value()), "%s already privilized with policy %s",
78              type.getTarget().getName(), marker.value());
79  
80          return false;
81      }
82  }