docs: private InternalWsResource resolveSymbols(final String originalPath, final String path, int recurse) {
          if (recurse > RECURSE_LIMIT)
              throw new IllegalStateException("Exceeded recursion limit (orig=" + originalPath + ",path=" + path + ")");
  
          Matcher m = SymbolRegistry.SYMBOL_DEF.matcher(path);
          if (m.find()) {
              String symbol = m.group(1);
              String fullMatch = m.group();
  
              SymRegEntry entry = stringToEntry.get(symbol);
  
              if (entry != null) {
                  if (path.equals(fullMatch)) {
                      // If the resourcePath and the symbol are the same,
                      // get the associated entry, and either return directly
                      // or perform substitution and recurse
                      switch (entry.type) {
                          case RESOURCE:
                          case ROOT:
                              return (InternalWsResource) entry.value;
                          case STRING:
                              return resolveSymbols(originalPath, (String) entry.value, recurse + 1);
                      }
                  } else {
                      int start = m.start();
                      int end = m.end();
  
                      String relativePath = null;
  
                      switch (entry.type) {
                          case RESOURCE:
                          case ROOT:
                              WsResource ar = (WsResource) entry.value;
                              if (ar.isType(WsResource.Type.FILE) && end != path.length())
                                  throw new MalformedLocationException("Can not resolve additional path parameters against file resource");
  
                              relativePath = getRelativePath(originalPath, path, start, end, recurse);
                              return (InternalWsResource) ar.resolveRelative(relativePath);
                          case STRING:
                              String value = (String) entry.value;
  
                              StringBuilder sb = new StringBuilder(start + value.length() + (path.length() - end));
  
                              sb.append(path.substring(0, start));
                              sb.append(entry.value);
                              sb.append(path.substring(end));
  
                              return resolveSymbols(originalPath, sb.toString(), recurse + 1);
                      }
                  }
              } else {
                  String value = OsgiPropertyUtils.getProperty(symbol, null);
                  if (value != null) {
                      int start = m.start();
                      int end = m.end();
  
                      StringBuilder sb = new StringBuilder(start + value.length() + (path.length() - end));
  
                      sb.append(path.substring(0, start));
                      sb.append(value);
                      sb.append(path.substring(end));
  
                      String newPath = sb.toString();
  
                      return WsLocationAdminImpl.getInstance().resolveResource(newPath);
                  }
  
              }
          } // end if m.find()
          throw new MalformedLocationException("Unable to resolve symbolic path (path=" + path + ")");
      }