| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.felix.scrplugin.processing; |
| |
| import java.util.List; |
| |
| import org.apache.felix.scr.annotations.sling.SlingFilter; |
| import org.apache.felix.scr.annotations.sling.SlingFilterScope; |
| import org.apache.felix.scr.annotations.sling.SlingServlet; |
| import org.apache.felix.scrplugin.SCRDescriptorException; |
| import org.apache.felix.scrplugin.SCRDescriptorFailureException; |
| import org.apache.felix.scrplugin.annotations.AnnotationProcessor; |
| import org.apache.felix.scrplugin.annotations.ClassAnnotation; |
| import org.apache.felix.scrplugin.annotations.ScannedClass; |
| import org.apache.felix.scrplugin.description.ClassDescription; |
| import org.apache.felix.scrplugin.description.ComponentConfigurationPolicy; |
| import org.apache.felix.scrplugin.description.ComponentDescription; |
| import org.apache.felix.scrplugin.description.PropertyDescription; |
| import org.apache.felix.scrplugin.description.PropertyType; |
| import org.apache.felix.scrplugin.description.ServiceDescription; |
| import org.apache.felix.scrplugin.helper.StringUtils; |
| |
| /** |
| * This is the processor for the Apache Felix Sling annotations. |
| */ |
| public class SlingAnnotationProcessor implements AnnotationProcessor { |
| |
| /** |
| * @see org.apache.felix.scrplugin.annotations.AnnotationProcessor#getName() |
| */ |
| @Override |
| public String getName() { |
| return "Apache Sling Annotation Processor"; |
| } |
| |
| /** |
| * @see org.apache.felix.scrplugin.annotations.AnnotationProcessor#process(org.apache.felix.scrplugin.annotations.ScannedClass, org.apache.felix.scrplugin.description.ClassDescription) |
| */ |
| @Override |
| public void process(final ScannedClass scannedClass, |
| final ClassDescription describedClass) |
| throws SCRDescriptorFailureException, SCRDescriptorException { |
| |
| final List<ClassAnnotation> servlets = scannedClass.getClassAnnotations(SlingServlet.class.getName()); |
| scannedClass.processed(servlets); |
| |
| for(final ClassAnnotation cad : servlets) { |
| processSlingServlet(cad, describedClass); |
| } |
| |
| final List<ClassAnnotation> filters = scannedClass.getClassAnnotations(SlingFilter.class.getName()); |
| scannedClass.processed(filters); |
| |
| for(final ClassAnnotation cad : filters) { |
| processSlingFilter(cad, describedClass); |
| } |
| |
| } |
| |
| /** |
| * @see org.apache.felix.scrplugin.annotations.AnnotationProcessor#getRanking() |
| */ |
| @Override |
| public int getRanking() { |
| return 500; |
| } |
| |
| /** |
| * Process SlingServlet |
| */ |
| private void processSlingServlet(final ClassAnnotation cad, final ClassDescription classDescription) { |
| // generate ComponentDescription if required |
| final boolean generateComponent = cad.getBooleanValue("generateComponent", true); |
| final boolean metatype = cad.getBooleanValue("metatype", !generateComponent); |
| |
| if (generateComponent) { |
| final ComponentDescription cd = new ComponentDescription(cad); |
| cd.setName(cad.getStringValue("name", classDescription.getDescribedClass().getName())); |
| cd.setConfigurationPolicy(ComponentConfigurationPolicy.OPTIONAL); |
| |
| cd.setLabel(cad.getStringValue("label", null)); |
| cd.setDescription(cad.getStringValue("description", null)); |
| |
| cd.setCreateMetatype(metatype); |
| |
| cd.setCreatePid(false); // always set to false |
| |
| classDescription.add(cd); |
| } |
| |
| // generate ServiceDescription if required |
| final boolean generateService = cad.getBooleanValue("generateService", true); |
| if (generateService) { |
| final ServiceDescription sd = new ServiceDescription(cad); |
| sd.addInterface("javax.servlet.Servlet"); |
| classDescription.add(sd); |
| } |
| |
| // generate PropertyDescriptions |
| |
| // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_PATHS} |
| generateStringPropertyDescriptor(cad, classDescription, metatype, "paths", "sling.servlet.paths"); |
| |
| // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES} |
| generateStringPropertyDescriptor(cad, classDescription, metatype, "resourceTypes", |
| "sling.servlet.resourceTypes"); |
| |
| // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_SELECTORS} |
| generateStringPropertyDescriptor(cad, classDescription, metatype, "selectors", "sling.servlet.selectors"); |
| |
| // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_EXTENSIONS} |
| generateStringPropertyDescriptor(cad, classDescription, metatype, "extensions", "sling.servlet.extensions"); |
| |
| // {@see org.apache.sling.servlets.resolver.internal.ServletResolverConstants.SLING_SERVLET_METHODS} |
| generateStringPropertyDescriptor(cad, classDescription, metatype, "methods", "sling.servlet.methods"); |
| } |
| |
| /** |
| * Generates a property descriptor of type {@link PropertyType#String} |
| */ |
| private void generateStringPropertyDescriptor(final ClassAnnotation cad, final ClassDescription classDescription, |
| final boolean metatype, String annotationName, String propertyDescriptorName) { |
| |
| final String[] values = (String[]) cad.getValue(annotationName); |
| if (values == null) { |
| return; |
| } |
| |
| final PropertyDescription pd = new PropertyDescription(cad); |
| pd.setName(propertyDescriptorName); |
| pd.setMultiValue(values); |
| pd.setType(PropertyType.String); |
| if (metatype) { |
| pd.setPrivate(true); |
| } |
| classDescription.add(pd); |
| } |
| |
| /** |
| * Process SlingFilter |
| */ |
| private void processSlingFilter(final ClassAnnotation cad, final ClassDescription classDescription) { |
| // generate ComponentDescription if required |
| final boolean generateComponent = cad.getBooleanValue("generateComponent", true); |
| final boolean metatype = cad.getBooleanValue("metatype", !generateComponent); |
| |
| if (generateComponent) { |
| final ComponentDescription cd = new ComponentDescription(cad); |
| cd.setName(cad.getStringValue("name", classDescription.getDescribedClass().getName())); |
| cd.setConfigurationPolicy(ComponentConfigurationPolicy.OPTIONAL); |
| |
| cd.setLabel(cad.getStringValue("label", null)); |
| cd.setDescription(cad.getStringValue("description", null)); |
| |
| cd.setCreateMetatype(metatype); |
| |
| classDescription.add(cd); |
| } |
| |
| // generate ServiceDescription if required |
| final boolean generateService = cad.getBooleanValue("generateService", true); |
| if (generateService) { |
| final ServiceDescription sd = new ServiceDescription(cad); |
| sd.addInterface("javax.servlet.Filter"); |
| classDescription.add(sd); |
| } |
| |
| // generate PropertyDescriptions |
| // property order = service.ranking |
| final int order = cad.getIntegerValue("order", 0); |
| final PropertyDescription pd = new PropertyDescription(cad); |
| pd.setName("service.ranking"); |
| pd.setValue(String.valueOf(order)); |
| pd.setType(PropertyType.Integer); |
| if (metatype) { |
| pd.setPrivate(true); |
| } |
| classDescription.add(pd); |
| |
| // property pattern = sling.filter.pattern |
| final String pattern = cad.getStringValue("pattern", ""); |
| if(!StringUtils.isEmpty(pattern)) { |
| final PropertyDescription pdPattern = new PropertyDescription(cad); |
| pdPattern.setName("sling.filter.pattern"); |
| pdPattern.setValue(pattern); |
| pdPattern.setType(PropertyType.String); |
| if (metatype) { |
| pdPattern.setPrivate(true); |
| } |
| classDescription.add(pdPattern); |
| } |
| |
| // property scope |
| final String[] scopes; |
| final Object val = cad.getValue("scope"); |
| if ( val != null ) { |
| if ( val instanceof String[] ) { |
| final String[] arr = (String[])val; |
| scopes = new String[arr.length / 2]; |
| int i = 0; |
| int index = 0; |
| while ( i < arr.length) { |
| scopes[index] = arr[i]; |
| i+=2; |
| index++; |
| } |
| } else if ( val instanceof String[][] ) { |
| final String[][] arr = (String[][])val; |
| scopes = new String[arr.length]; |
| int index = 0; |
| while ( index < arr.length) { |
| scopes[index] = arr[index][1]; |
| index++; |
| } |
| } else { |
| scopes = new String[] { val.toString()}; |
| } |
| } else { |
| scopes = new String[] {SlingFilterScope.REQUEST.getScope()}; |
| } |
| |
| final PropertyDescription pd2 = new PropertyDescription(cad); |
| pd2.setName("sling.filter.scope"); |
| if ( scopes.length == 1 ) { |
| pd2.setValue(scopes[0]); |
| } else { |
| pd2.setMultiValue(scopes); |
| } |
| pd2.setType(PropertyType.String); |
| if (metatype) { |
| pd2.setPrivate(true); |
| } |
| classDescription.add(pd2); |
| } |
| } |