You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2020/03/23 16:05:30 UTC

[sling-org-apache-sling-scripting-bundle-tracker] branch master updated (ea6a8c4 -> 55d52a8)

This is an automated email from the ASF dual-hosted git repository.

radu pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git.


    from ea6a8c4  SLING-9216 - Allow capabilities to provide lists of resource types
     new 303a979  SLING-9233 - Skip registering the Dispatcher servlet if the resource types are not versioned
     new 55d52a8  SLING-9216 - Allow capabilities to provide lists of resource types

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../scripting/bundle/tracker/ResourceType.java     | 20 ++++--
 .../tracker/internal/BundledScriptFinder.java      |  9 ++-
 .../tracker/internal/BundledScriptServlet.java     | 77 +++++++---------------
 .../tracker/internal/BundledScriptTracker.java     | 58 ++++++++--------
 .../bundle/tracker/internal/RequestWrapper.java    | 12 ++--
 .../bundle/tracker/internal/TypeProvider.java      |  5 ++
 6 files changed, 89 insertions(+), 92 deletions(-)


[sling-org-apache-sling-scripting-bundle-tracker] 01/02: SLING-9233 - Skip registering the Dispatcher servlet if the resource types are not versioned

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git

commit 303a979195ab2eb9fc30bca13c0fe3c88b8e332b
Author: Karl Pauls <pa...@apache.org>
AuthorDate: Mon Mar 23 17:01:43 2020 +0100

    SLING-9233 - Skip registering the Dispatcher servlet if the resource types are not versioned
---
 .../scripting/bundle/tracker/ResourceType.java     | 20 ++++--
 .../tracker/internal/BundledScriptServlet.java     | 77 +++++++---------------
 .../tracker/internal/BundledScriptTracker.java     | 58 ++++++++--------
 .../bundle/tracker/internal/RequestWrapper.java    | 12 ++--
 4 files changed, 76 insertions(+), 91 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/ResourceType.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/ResourceType.java
index 263879b..b1399f1 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/ResourceType.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/ResourceType.java
@@ -19,6 +19,7 @@
 package org.apache.sling.scripting.bundle.tracker;
 
 import java.util.Objects;
+import java.util.regex.Pattern;
 
 import org.apache.commons.lang3.StringUtils;
 import org.jetbrains.annotations.NotNull;
@@ -39,9 +40,12 @@ import org.osgi.framework.Version;
  */
 public final class ResourceType {
 
+    private static final Pattern versionPattern = Pattern.compile("[\\d\\.]+(-.*)*$");
+
     private final String type;
     private final String version;
     private final String resourceLabel;
+    private final String toString;
 
     private ResourceType(@NotNull String type, @Nullable String version) {
         this.type = type;
@@ -53,6 +57,7 @@ public final class ResourceType {
         } else {
             resourceLabel = type;
         }
+        toString = type + (version == null ? "" : "/" + version);
     }
 
     /**
@@ -90,7 +95,7 @@ public final class ResourceType {
 
     @Override
     public String toString() {
-        return type + (version == null ? "" : "/" + version);
+        return toString;
     }
 
     /**
@@ -115,10 +120,15 @@ public final class ResourceType {
         if (StringUtils.isNotEmpty(resourceTypeString)) {
             int lastSlash = resourceTypeString.lastIndexOf('/');
             if (lastSlash != -1 && !resourceTypeString.endsWith("/")) {
-                try {
-                    version = Version.parseVersion(resourceTypeString.substring(lastSlash + 1)).toString();
-                    type = resourceTypeString.substring(0, lastSlash);
-                } catch (IllegalArgumentException e) {
+                String versionString = resourceTypeString.substring(lastSlash + 1);
+                if (versionPattern.matcher(versionString).matches()) {
+                    try {
+                        version = Version.parseVersion(versionString).toString();
+                        type = resourceTypeString.substring(0, lastSlash);
+                    } catch (IllegalArgumentException e) {
+                        type = resourceTypeString;
+                    }
+                } else {
                     type = resourceTypeString;
                 }
             } else {
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
index 2cf4be3..0516ece 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
@@ -19,13 +19,12 @@
 package org.apache.sling.scripting.bundle.tracker.internal;
 
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.Collection;
 import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
 
 import javax.script.Bindings;
 import javax.script.ScriptContext;
@@ -42,7 +41,6 @@ import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.request.RequestPathInfo;
 import org.apache.sling.api.scripting.ScriptEvaluationException;
 import org.apache.sling.api.scripting.SlingBindings;
-import org.apache.sling.scripting.bundle.tracker.ResourceType;
 import org.apache.sling.scripting.core.ScriptHelper;
 
 class BundledScriptServlet extends GenericServlet {
@@ -53,8 +51,7 @@ class BundledScriptServlet extends GenericServlet {
     private final LinkedHashSet<TypeProvider> m_wiredTypeProviders;
     private final boolean m_precompiledScripts;
 
-    private Map<String, Executable> scriptsMap = new HashMap<>();
-    private ReadWriteLock lock = new ReentrantReadWriteLock();
+    private ConcurrentMap<String, Optional<Executable>> scriptsMap = new ConcurrentHashMap<>();
 
 
 
@@ -83,55 +80,27 @@ class BundledScriptServlet extends GenericServlet {
             }
 
             String scriptsMapKey = getScriptsMapKey(request);
-            Executable executable;
-            lock.readLock().lock();
+            Executable executable = scriptsMap.computeIfAbsent(scriptsMapKey,
+                key -> Optional.ofNullable(m_bundledScriptFinder.getScript(request, m_wiredTypeProviders, m_precompiledScripts))
+            ).orElseThrow(() -> new ServletException("Unable to locate a " + (m_precompiledScripts ? "class" : "script") + " for rendering."));
+
+            RequestWrapper requestWrapper = new RequestWrapper(request,
+                    m_wiredTypeProviders.stream().map(TypeProvider::getResourceTypes).flatMap(Collection::stream).collect(Collectors.toSet()));
+            ScriptContext scriptContext = m_scriptContextProvider.prepareScriptContext(requestWrapper, response, executable);
             try {
-                executable = scriptsMap.get(scriptsMapKey);
-                if (executable == null) {
-                    lock.readLock().unlock();
-                    lock.writeLock().lock();
-                    try {
-                        executable = scriptsMap.get(scriptsMapKey);
-                        if (executable == null) {
-                            executable = m_bundledScriptFinder.getScript(request, m_wiredTypeProviders, m_precompiledScripts);
-                            if (executable != null) {
-                                scriptsMap.put(scriptsMapKey, executable);
-                            }
-                        }
-                    } finally {
-                        lock.readLock().lock();
-                        lock.writeLock().unlock();
-                    }
-                }
+                executable.eval(scriptContext);
+            } catch (ScriptException se) {
+                Throwable cause = (se.getCause() == null) ? se : se.getCause();
+                throw new ScriptEvaluationException(executable.getName(), se.getMessage(), cause);
             } finally {
-                lock.readLock().unlock();
-            }
-            if (executable != null) {
-                Set<String> wiredResourceTypes = new HashSet<>();
-                for (TypeProvider typeProvider : m_wiredTypeProviders) {
-                    for (ResourceType resourceType : typeProvider.getResourceTypes()) {
-                        wiredResourceTypes.add(resourceType.toString());
-                    }
-                }
-                RequestWrapper requestWrapper = new RequestWrapper(request, wiredResourceTypes);
-                ScriptContext scriptContext = m_scriptContextProvider.prepareScriptContext(requestWrapper, response, executable);
-                try {
-                    executable.eval(scriptContext);
-                } catch (ScriptException se) {
-                    Throwable cause = (se.getCause() == null) ? se : se.getCause();
-                    throw new ScriptEvaluationException(executable.getName(), se.getMessage(), cause);
-                } finally {
-                    Bindings engineBindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
-                    if (engineBindings != null && engineBindings.containsKey(SlingBindings.SLING)) {
-                        Object scriptHelper = engineBindings.get(SlingBindings.SLING);
-                        if (scriptHelper instanceof ScriptHelper) {
-                            ((ScriptHelper) scriptHelper).cleanup();
-                        }
+                Bindings engineBindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
+                if (engineBindings != null && engineBindings.containsKey(SlingBindings.SLING)) {
+                    Object scriptHelper = engineBindings.get(SlingBindings.SLING);
+                    if (scriptHelper instanceof ScriptHelper) {
+                        ((ScriptHelper) scriptHelper).cleanup();
                     }
-                    executable.releaseDependencies();
                 }
-            } else {
-                throw new ServletException("Unable to locate a " + (m_precompiledScripts ? "class" : "script") + " for rendering.");
+                executable.releaseDependencies();
             }
         } else {
             throw new ServletException("Not a Sling HTTP request/response");
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
index bbe4d15..6c8bd63 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
@@ -99,7 +99,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
 
     private volatile BundleContext m_context;
     private volatile BundleTracker<List<ServiceRegistration<Servlet>>> m_tracker;
-    private volatile Map<String, ServiceRegistration<Servlet>> m_dispatchers = new HashMap<>();
+    private volatile Map<Set<String>, ServiceRegistration<Servlet>> m_dispatchers = new HashMap<>();
 
     @Activate
     protected void activate(BundleContext context) {
@@ -126,7 +126,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                 {
                     Hashtable<String, Object> properties = new Hashtable<>();
                     properties.put(ServletResolverConstants.SLING_SERVLET_NAME, BundledScriptServlet.class.getName());
-                    properties.put(Constants.SERVICE_DESCRIPTION, cap.toString());
+                    properties.put(Constants.SERVICE_DESCRIPTION, BundledScriptServlet.class.getName() + cap.getAttributes());
                     ResourceTypeCapability resourceTypeCapability = ResourceTypeCapability.fromBundleCapability(cap);
                     String[] resourceTypesRegistrationValue = new String[resourceTypeCapability.getResourceTypes().size()];
                     int rtIndex = 0;
@@ -220,12 +220,14 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
     }
 
     private void refreshDispatcher(List<ServiceRegistration<Servlet>> regs) {
-        Map<String, ServiceRegistration<Servlet>> dispatchers = new HashMap<>();
-        Stream.concat(m_tracker.getTracked().values().stream(), Stream.of(regs)).flatMap(List::stream).map(this::toProperties).collect(
-                Collectors.groupingBy(this::getResourceType)).forEach((rt, propList) -> {
+        Map<Set<String>, ServiceRegistration<Servlet>> dispatchers = new HashMap<>();
+        Stream.concat(m_tracker.getTracked().values().stream(), Stream.of(regs)).flatMap(List::stream)
+            .filter(ref -> getResourceTypeVersion(ref.getReference()) != null)
+            .map(this::toProperties)
+            .collect(Collectors.groupingBy(BundledScriptTracker::getResourceTypes)).forEach((rt, propList) -> {
             Hashtable<String, Object> properties = new Hashtable<>();
             properties.put(ServletResolverConstants.SLING_SERVLET_NAME, DispatcherServlet.class.getName());
-            properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, rt);
+            properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES, rt.toArray());
             Set<String> methods = propList.stream()
                     .map(props -> props.getOrDefault(ServletResolverConstants.SLING_SERVLET_METHODS, new String[]{"GET", "HEAD"}))
                     .map(PropertiesUtil::toStringArray).map(Arrays::asList).flatMap(List::stream).collect(Collectors.toSet());
@@ -245,9 +247,11 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                     }
                     return null;
                 }).findFirst();
-                properties.put(Constants.SERVICE_DESCRIPTION, ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + rt + "; " +
+                properties.put(Constants.SERVICE_DESCRIPTION,
+                        DispatcherServlet.class.getName() + "{" + ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES +
+                        "=" + rt + "; " +
                         ServletResolverConstants.SLING_SERVLET_EXTENSIONS + "=" + extensions + "; " +
-                        ServletResolverConstants.SLING_SERVLET_METHODS + "=" + methods);
+                        ServletResolverConstants.SLING_SERVLET_METHODS + "=" + methods  + "}");
                 reg = registeringBundle.orElse(m_context).registerService(Servlet.class, new DispatcherServlet(rt), properties);
             } else {
                 if (!new HashSet<>(Arrays.asList(PropertiesUtil
@@ -275,13 +279,6 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
         return result;
     }
 
-    private String getResourceType(Hashtable<String, Object> props) {
-        String[] values = PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
-        String resourceTypeValue = values[0];
-        ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
-        return resourceType.getType();
-    }
-
     private void set(String key, ServiceReference<?> ref, Hashtable<String, Object> props) {
         Object value = ref.getProperty(key);
         if (value != null) {
@@ -302,9 +299,9 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
     }
 
     private class DispatcherServlet extends GenericServlet {
-        private final String m_rt;
+        private final Set<String> m_rt;
 
-        DispatcherServlet(String rt) {
+        DispatcherServlet(Set<String> rt) {
             m_rt = rt;
         }
 
@@ -322,7 +319,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                     .filter(reg ->
                     {
                         Hashtable<String, Object> props = toProperties(reg);
-                        return getResourceType(props).equals(m_rt) &&
+                        return getResourceTypes(props).equals(m_rt) &&
                                 Arrays.asList(PropertiesUtil
                                         .toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_METHODS),
                                                 new String[]{"GET", "HEAD"}))
@@ -331,8 +328,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                                         .toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_EXTENSIONS), new String[]{"html"}))
                                         .contains(slingRequest.getRequestPathInfo().getExtension() == null ? "html" :
                                                 slingRequest.getRequestPathInfo().getExtension());
-                    })
-                    .sorted((left, right) ->
+                    }).min((left, right) ->
                     {
                         boolean la = Arrays.asList(PropertiesUtil
                                 .toStringArray(toProperties(left).get(ServletResolverConstants.SLING_SERVLET_SELECTORS), new String[0]))
@@ -349,8 +345,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                             return 1;
                         }
 
-                    })
-                    .findFirst();
+                    });
 
             if (target.isPresent()) {
                 String[] targetRT =
@@ -382,12 +377,21 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                 ((SlingHttpServletResponse) res).sendError(HttpServletResponse.SC_NOT_FOUND);
             }
         }
+    }
 
-        private String getResourceTypeVersion(ServiceReference<?> ref) {
-            String[] values = PropertiesUtil.toStringArray(ref.getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
-            String resourceTypeValue = values[0];
-            ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
-            return resourceType.getVersion();
+    private static String getResourceTypeVersion(ServiceReference<?> ref) {
+        String[] values = PropertiesUtil.toStringArray(ref.getProperty(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
+        String resourceTypeValue = values[0];
+        ResourceType resourceType = ResourceType.parseResourceType(resourceTypeValue);
+        return resourceType.getVersion();
+    }
+
+    private static Set<String> getResourceTypes(Hashtable<String, Object> props) {
+        Set<String> resourceTypes = new HashSet<>();
+        String[] values = PropertiesUtil.toStringArray(props.get(ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES));
+        for (String resourceTypeValue : values) {
+            resourceTypes.add(ResourceType.parseResourceType(resourceTypeValue).getType());
         }
+        return resourceTypes;
     }
 }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/RequestWrapper.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/RequestWrapper.java
index 7a9da1f..57ebfea 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/RequestWrapper.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/RequestWrapper.java
@@ -27,12 +27,13 @@ import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.request.RequestDispatcherOptions;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
+import org.apache.sling.scripting.bundle.tracker.ResourceType;
 
 class RequestWrapper extends SlingHttpServletRequestWrapper {
 
-    private final Set<String> wiredResourceTypes;
+    private final Set<ResourceType> wiredResourceTypes;
 
-    RequestWrapper(SlingHttpServletRequest wrappedRequest, Set<String> wiredResourceTypes) {
+    RequestWrapper(SlingHttpServletRequest wrappedRequest, Set<ResourceType> wiredResourceTypes) {
         super(wrappedRequest);
         this.wiredResourceTypes = wiredResourceTypes;
     }
@@ -67,9 +68,10 @@ class RequestWrapper extends SlingHttpServletRequestWrapper {
             requestDispatcherOptions.setReplaceSuffix(options.getReplaceSuffix());
             String forcedResourceType = options.getForceResourceType();
             if (StringUtils.isNotEmpty(forcedResourceType)) {
-                for (String wiredResourceType : wiredResourceTypes) {
-                    if (wiredResourceType.startsWith(forcedResourceType + "/")) {
-                        requestDispatcherOptions.setForceResourceType(wiredResourceType);
+                for (ResourceType wiredResourceType : wiredResourceTypes) {
+                    String type = wiredResourceType.getType();
+                    if (type.startsWith(forcedResourceType + "/")) {
+                        requestDispatcherOptions.setForceResourceType(type);
                         break;
                     }
                 }


[sling-org-apache-sling-scripting-bundle-tracker] 02/02: SLING-9216 - Allow capabilities to provide lists of resource types

Posted by ra...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git

commit 55d52a8293f1238e45613f73b0923b4ac324a8f5
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Mar 23 17:05:13 2020 +0100

    SLING-9216 - Allow capabilities to provide lists of resource types
---
 .../scripting/bundle/tracker/internal/BundledScriptFinder.java   | 9 ++++++++-
 .../sling/scripting/bundle/tracker/internal/TypeProvider.java    | 5 +++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index 162c89d..bbe9973 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -40,12 +40,15 @@ import org.osgi.framework.wiring.BundleCapability;
 import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Component(
         service = BundledScriptFinder.class
 )
 public class BundledScriptFinder {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(BundledScriptFinder.class);
     private static final String NS_JAVAX_SCRIPT_CAPABILITY = "javax.script";
     private static final String SLASH = "/";
     private static final String DOT = ".";
@@ -79,14 +82,18 @@ public class BundledScriptFinder {
                             } else {
                                 bundledScriptURL =
                                         provider.getBundle()
-                                                .getEntry(NS_JAVAX_SCRIPT_CAPABILITY + SLASH + match + DOT + scriptEngineExtension);
+                                                .getEntry(NS_JAVAX_SCRIPT_CAPABILITY + (match.startsWith("/") ? "" : SLASH) + match + DOT + scriptEngineExtension);
                                 if (bundledScriptURL != null) {
                                     return new Script(provider.getBundle(), bundledScriptURL, scriptEngine);
                                 }
                             }
                         }
                     }
+                } else {
+                    LOGGER.error("Cannot find a script engine for short name {}.", scriptEngineName);
                 }
+            } else {
+                LOGGER.error("Cannot find a script engine name for {}.", provider);
             }
         }
         return null;
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
index 7332102..c8cda53 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
@@ -77,4 +77,9 @@ public class TypeProvider {
         }
         return false;
     }
+
+    @Override
+    public String toString() {
+        return String.format("TypeProvider{ resourceTypes=%s; bundle=%s }", resourceTypes, bundle.getSymbolicName());
+    }
 }