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.syncope.client.enduser.init;
20  
21  import java.io.Serializable;
22  import java.lang.reflect.Modifier;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.List;
26  import java.util.Objects;
27  import org.apache.commons.lang3.ArrayUtils;
28  import org.apache.syncope.client.enduser.pages.BaseExtPage;
29  import org.apache.syncope.client.enduser.pages.BasePage;
30  import org.apache.syncope.client.ui.commons.annotations.BinaryPreview;
31  import org.apache.syncope.client.ui.commons.annotations.ExtPage;
32  import org.apache.syncope.client.ui.commons.markup.html.form.preview.BinaryPreviewer;
33  import org.apache.syncope.client.ui.commons.panels.BaseSSOLoginFormPanel;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  import org.springframework.beans.factory.config.BeanDefinition;
37  import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
38  import org.springframework.core.type.filter.AssignableTypeFilter;
39  import org.springframework.util.ClassUtils;
40  
41  public class ClassPathScanImplementationLookup implements Serializable {
42  
43      private static final long serialVersionUID = -4944986595429290116L;
44  
45      private static final Logger LOG = LoggerFactory.getLogger(ClassPathScanImplementationLookup.class);
46  
47      private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope";
48  
49      private List<Class<? extends BaseSSOLoginFormPanel>> ssoLoginFormPanels;
50  
51      private List<Class<? extends BasePage>> extPages;
52  
53      private List<Class<? extends BinaryPreviewer>> previewers;
54  
55      /**
56       * This method can be overridden by subclasses to customize classpath scan.
57       *
58       * @return basePackage for classpath scanning
59       */
60      protected static String getBasePackage() {
61          return DEFAULT_BASE_PACKAGE;
62      }
63  
64      @SuppressWarnings("unchecked")
65      public void load() {
66          extPages = new ArrayList<>();
67          ssoLoginFormPanels = new ArrayList<>();
68          previewers = new ArrayList<>();
69  
70          ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
71          scanner.addIncludeFilter(new AssignableTypeFilter(BasePage.class));
72          scanner.addIncludeFilter(new AssignableTypeFilter(BaseSSOLoginFormPanel.class));
73          scanner.addIncludeFilter(new AssignableTypeFilter(BinaryPreviewer.class));
74  
75          for (BeanDefinition bd : scanner.findCandidateComponents(getBasePackage())) {
76              try {
77                  Class<?> clazz = ClassUtils.resolveClassName(Objects.requireNonNull(bd.getBeanClassName()),
78                          ClassUtils.getDefaultClassLoader());
79                  if (Modifier.isAbstract(clazz.getModifiers())) {
80                      continue;
81                  }
82  
83                  if (BaseExtPage.class.isAssignableFrom(clazz)) {
84                      if (clazz.isAnnotationPresent(ExtPage.class)) {
85                          extPages.add((Class<? extends BasePage>) clazz);
86                      } else {
87                          LOG.error("Could not find annotation {} in {}, ignoring",
88                                  ExtPage.class.getName(), clazz.getName());
89                      }
90                  } else if (BaseSSOLoginFormPanel.class.isAssignableFrom(clazz)) {
91                      ssoLoginFormPanels.add((Class<? extends BaseSSOLoginFormPanel>) clazz);
92                  } else if (BinaryPreviewer.class.isAssignableFrom(clazz)) {
93                      previewers.add((Class<? extends BinaryPreviewer>) clazz);
94                  }
95              } catch (Throwable t) {
96                  LOG.warn("Could not inspect class {}", bd.getBeanClassName(), t);
97              }
98          }
99  
100         ssoLoginFormPanels = Collections.unmodifiableList(ssoLoginFormPanels);
101 
102         LOG.debug("Extension pages found: {}", extPages);
103         LOG.debug("SSO Login pages found: {}", ssoLoginFormPanels);
104         LOG.debug("Binary previewers found: {}", previewers);
105     }
106 
107     public List<Class<? extends BaseSSOLoginFormPanel>> getSSOLoginFormPanels() {
108         return this.ssoLoginFormPanels;
109     }
110 
111     public List<Class<? extends BasePage>> getExtPageClasses() {
112         return extPages;
113     }
114 
115     public Class<? extends BinaryPreviewer> getPreviewerClass(final String mimeType) {
116         LOG.debug("Searching for previewer class for MIME type: {}", mimeType);
117         Class<? extends BinaryPreviewer> previewer = null;
118         for (Class<? extends BinaryPreviewer> candidate : previewers) {
119             LOG.debug("Evaluating previewer class {} for MIME type {}", candidate.getName(), mimeType);
120             if (candidate.isAnnotationPresent(BinaryPreview.class)
121                     && ArrayUtils.contains(candidate.getAnnotation(BinaryPreview.class).mimeTypes(), mimeType)) {
122                 LOG.debug("Found existing previewer for MIME type {}: {}", mimeType, candidate.getName());
123                 previewer = candidate;
124             }
125         }
126         return previewer;
127     }
128 }