001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.jsonwebservice;
016    
017    import com.liferay.portal.kernel.bean.BeanLocator;
018    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
019    import com.liferay.portal.kernel.bean.PortletBeanLocatorUtil;
020    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceAction;
021    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionMapping;
022    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceActionsManager;
023    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceNaming;
024    import com.liferay.portal.kernel.jsonwebservice.JSONWebServiceRegistrator;
025    import com.liferay.portal.kernel.jsonwebservice.NoSuchJSONWebServiceException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
029    import com.liferay.portal.kernel.servlet.HttpMethods;
030    import com.liferay.portal.kernel.util.CharPool;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.MethodParameter;
033    import com.liferay.portal.kernel.util.StringBundler;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.StringUtil;
036    import com.liferay.portal.kernel.util.Validator;
037    import com.liferay.portal.service.ServiceContextThreadLocal;
038    import com.liferay.portal.spring.context.PortalContextLoaderListener;
039    import com.liferay.portal.util.PortalUtil;
040    import com.liferay.portal.util.PropsValues;
041    
042    import java.lang.reflect.Method;
043    
044    import java.util.ArrayList;
045    import java.util.Collections;
046    import java.util.List;
047    import java.util.Map;
048    import java.util.Set;
049    import java.util.TreeSet;
050    import java.util.concurrent.ConcurrentHashMap;
051    import java.util.concurrent.ConcurrentMap;
052    import java.util.concurrent.CopyOnWriteArrayList;
053    
054    import javax.servlet.ServletContext;
055    import javax.servlet.http.HttpServletRequest;
056    
057    /**
058     * @author Igor Spasic
059     * @author Raymond Aug??
060     */
061    @DoPrivileged
062    public class JSONWebServiceActionsManagerImpl
063            implements JSONWebServiceActionsManager {
064    
065            @Override
066            public Set<String> getContextNames() {
067                    return new TreeSet<>(
068                            _contextNameIndexedJSONWebServiceActionConfigs.keySet());
069            }
070    
071            @Override
072            public JSONWebServiceAction getJSONWebServiceAction(
073                            HttpServletRequest request)
074                    throws NoSuchJSONWebServiceException {
075    
076                    String path = GetterUtil.getString(request.getPathInfo());
077    
078                    String method = GetterUtil.getString(request.getMethod());
079    
080                    String parameterPath = null;
081    
082                    JSONRPCRequest jsonRPCRequest = null;
083    
084                    int parameterPathIndex = _getParameterPathIndex(path);
085    
086                    if (parameterPathIndex != -1) {
087                            parameterPath = path.substring(parameterPathIndex);
088    
089                            path = path.substring(0, parameterPathIndex);
090                    }
091                    else {
092                            if (method.equals(HttpMethods.POST) &&
093                                    !PortalUtil.isMultipartRequest(request)) {
094    
095                                    jsonRPCRequest = JSONRPCRequest.detectJSONRPCRequest(request);
096    
097                                    if (jsonRPCRequest != null) {
098                                            path += StringPool.SLASH + jsonRPCRequest.getMethod();
099    
100                                            method = null;
101                                    }
102                            }
103                    }
104    
105                    JSONWebServiceActionParameters jsonWebServiceActionParameters =
106                            new JSONWebServiceActionParameters();
107    
108                    jsonWebServiceActionParameters.collectAll(
109                            request, parameterPath, jsonRPCRequest, null);
110    
111                    if (jsonWebServiceActionParameters.getServiceContext() != null) {
112                            ServiceContextThreadLocal.pushServiceContext(
113                                    jsonWebServiceActionParameters.getServiceContext());
114                    }
115    
116                    JSONWebServiceActionConfig jsonWebServiceActionConfig =
117                            _findJSONWebServiceAction(
118                                    request, path, method, jsonWebServiceActionParameters);
119    
120                    return new JSONWebServiceActionImpl(
121                            jsonWebServiceActionConfig, jsonWebServiceActionParameters,
122                            _jsonWebServiceNaming);
123            }
124    
125            @Override
126            public JSONWebServiceAction getJSONWebServiceAction(
127                            HttpServletRequest request, String path, String method,
128                            Map<String, Object> parameterMap)
129                    throws NoSuchJSONWebServiceException {
130    
131                    JSONWebServiceActionParameters jsonWebServiceActionParameters =
132                            new JSONWebServiceActionParameters();
133    
134                    jsonWebServiceActionParameters.collectAll(
135                            request, null, null, parameterMap);
136    
137                    JSONWebServiceActionConfig jsonWebServiceActionConfig =
138                            _findJSONWebServiceAction(
139                                    request, path, method, jsonWebServiceActionParameters);
140    
141                    return new JSONWebServiceActionImpl(
142                            jsonWebServiceActionConfig, jsonWebServiceActionParameters,
143                            _jsonWebServiceNaming);
144            }
145    
146            @Override
147            public JSONWebServiceActionMapping getJSONWebServiceActionMapping(
148                    String signature) {
149    
150                    return _signatureIndexedJSONWebServiceActionConfigs.get(signature);
151            }
152    
153            @Override
154            public List<JSONWebServiceActionMapping> getJSONWebServiceActionMappings(
155                    String contextName) {
156    
157                    List<JSONWebServiceActionConfig> jsonWebServiceActionConfigs =
158                            _contextNameIndexedJSONWebServiceActionConfigs.get(contextName);
159    
160                    if (jsonWebServiceActionConfigs == null) {
161                            return Collections.emptyList();
162                    }
163    
164                    return new ArrayList<JSONWebServiceActionMapping>(
165                            jsonWebServiceActionConfigs);
166            }
167    
168            @Override
169            public int getJSONWebServiceActionsCount(String contextName) {
170                    List<JSONWebServiceActionConfig> jsonWebServiceActionConfigs =
171                            _contextNameIndexedJSONWebServiceActionConfigs.get(contextName);
172    
173                    if (jsonWebServiceActionConfigs == null) {
174                            return 0;
175                    }
176    
177                    return jsonWebServiceActionConfigs.size();
178            }
179    
180            @Override
181            public JSONWebServiceNaming getJSONWebServiceNaming() {
182                    return _jsonWebServiceNaming;
183            }
184    
185            @Override
186            public synchronized void registerJSONWebServiceAction(
187                    String contextName, String contextPath, Class<?> actionClass,
188                    Method actionMethod, String path, String method) {
189    
190                    try {
191                            if (!_addJSONWebServiceActionConfig(
192                                            new JSONWebServiceActionConfig(
193                                                    contextName, contextPath, actionClass, actionMethod,
194                                                    path, method))) {
195    
196                                    if (_log.isDebugEnabled()) {
197                                            _log.debug(
198                                                    "A JSON web service action is already registered at " +
199                                                            path);
200                                    }
201                            }
202                    }
203                    catch (Exception e) {
204                            if (_log.isWarnEnabled()) {
205                                    StringBundler sb = new StringBundler(14);
206    
207                                    sb.append("Unable to register service method {actionClass=");
208                                    sb.append(actionClass);
209                                    sb.append(", actionMethod=");
210                                    sb.append(actionMethod);
211                                    sb.append(", contextName=");
212                                    sb.append(contextName);
213                                    sb.append(", contextPath=");
214                                    sb.append(contextPath);
215                                    sb.append(", method=");
216                                    sb.append(method);
217                                    sb.append(", path=");
218                                    sb.append(path);
219                                    sb.append("} due to ");
220                                    sb.append(e.getMessage());
221    
222                                    _log.warn(sb.toString());
223                            }
224                    }
225            }
226    
227            @Override
228            public synchronized void registerJSONWebServiceAction(
229                    String contextName, String contextPath, Object actionObject,
230                    Class<?> actionClass, Method actionMethod, String path, String method) {
231    
232                    try {
233                            if (!_addJSONWebServiceActionConfig(
234                                            new JSONWebServiceActionConfig(
235                                                    contextName, contextPath, actionObject, actionClass,
236                                                    actionMethod, path, method))) {
237    
238                                    if (_log.isWarnEnabled()) {
239                                            _log.warn(
240                                                    "A JSON web service action is already registered at " +
241                                                            path);
242                                    }
243                            }
244                    }
245                    catch (Exception e) {
246                            StringBundler sb = new StringBundler(17);
247    
248                            sb.append("Something went wrong attempting to register service ");
249                            sb.append("method {contextName=");
250                            sb.append(contextName);
251                            sb.append(",contextPath=");
252                            sb.append(contextPath);
253                            sb.append(",actionObject=");
254                            sb.append(actionObject);
255                            sb.append(",actionClass=");
256                            sb.append(actionClass);
257                            sb.append(",actionMethod=");
258                            sb.append(actionMethod);
259                            sb.append(",path=");
260                            sb.append(path);
261                            sb.append(",method=");
262                            sb.append(method);
263                            sb.append("} due to ");
264                            sb.append(e.getMessage());
265    
266                            _log.warn(sb.toString());
267                    }
268            }
269    
270            @Override
271            public int registerService(String contextPath, Object service) {
272                    return registerService(StringPool.BLANK, contextPath, service);
273            }
274    
275            @Override
276            public int registerService(
277                    String contextName, String contextPath, Object service) {
278    
279                    JSONWebServiceRegistrator jsonWebServiceRegistrator =
280                            new DefaultJSONWebServiceRegistrator();
281    
282                    return registerService(
283                            contextName, contextPath, service, jsonWebServiceRegistrator);
284            }
285    
286            @Override
287            public int registerService(
288                    String contextName, String contextPath, Object service,
289                    JSONWebServiceRegistrator jsonWebServiceRegistrator) {
290    
291                    jsonWebServiceRegistrator.processBean(
292                            contextName, contextPath, service);
293    
294                    int count = getJSONWebServiceActionsCount(contextPath);
295    
296                    if (_log.isInfoEnabled()) {
297                            _log.info("Configured " + count + " actions for " + contextPath);
298                    }
299    
300                    return count;
301            }
302    
303            @Override
304            public int registerServletContext(ServletContext servletContext) {
305                    BeanLocator beanLocator = null;
306    
307                    String contextName = servletContext.getServletContextName();
308                    String contextPath = servletContext.getContextPath();
309    
310                    if (contextPath.equals(
311                                    PortalContextLoaderListener.getPortalServletContextPath()) ||
312                            contextPath.isEmpty()) {
313    
314                            beanLocator = PortalBeanLocatorUtil.getBeanLocator();
315                    }
316                    else {
317                            beanLocator = PortletBeanLocatorUtil.getBeanLocator(contextName);
318                    }
319    
320                    if (beanLocator == null) {
321                            if (_log.isInfoEnabled()) {
322                                    _log.info("Bean locator not available for " + contextPath);
323                            }
324    
325                            return -1;
326                    }
327    
328                    DefaultJSONWebServiceRegistrator defaultJSONWebServiceRegistrator =
329                            new DefaultJSONWebServiceRegistrator();
330    
331                    defaultJSONWebServiceRegistrator.processAllBeans(
332                            contextName, contextPath, beanLocator);
333    
334                    int count = getJSONWebServiceActionsCount(contextPath);
335    
336                    if (_log.isInfoEnabled()) {
337                            _log.info("Configured " + count + " actions for " + contextPath);
338                    }
339    
340                    return count;
341            }
342    
343            @Override
344            public synchronized int unregisterJSONWebServiceActions(
345                    Object actionObject) {
346    
347                    int count = 0;
348    
349                    for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
350                                    _signatureIndexedJSONWebServiceActionConfigs.values()) {
351    
352                            if (actionObject.equals(
353                                            jsonWebServiceActionConfig.getActionObject()) &&
354                                    _removeJSONWebServiceActionConfig(jsonWebServiceActionConfig)) {
355    
356                                    count++;
357                            }
358                    }
359    
360                    return count;
361            }
362    
363            @Override
364            public synchronized int unregisterJSONWebServiceActions(
365                    String contextPath) {
366    
367                    int count = 0;
368    
369                    for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
370                                    _signatureIndexedJSONWebServiceActionConfigs.values()) {
371    
372                            if (contextPath.equals(
373                                            jsonWebServiceActionConfig.getContextPath()) &&
374                                    _removeJSONWebServiceActionConfig(jsonWebServiceActionConfig)) {
375    
376                                    count++;
377                            }
378                    }
379    
380                    return count;
381            }
382    
383            @Override
384            public int unregisterServletContext(ServletContext servletContext) {
385                    String contextPath = servletContext.getContextPath();
386    
387                    return unregisterJSONWebServiceActions(contextPath);
388            }
389    
390            private boolean _addJSONWebServiceActionConfig(
391                    JSONWebServiceActionConfig jsonWebServiceActionConfig) {
392    
393                    JSONWebServiceActionConfig oldJSONWebServiceActionConfig =
394                            _signatureIndexedJSONWebServiceActionConfigs.putIfAbsent(
395                                    jsonWebServiceActionConfig.getSignature(),
396                                    jsonWebServiceActionConfig);
397    
398                    if (oldJSONWebServiceActionConfig != null) {
399                            return false;
400                    }
401    
402                    String contextName = jsonWebServiceActionConfig.getContextName();
403    
404                    List<JSONWebServiceActionConfig> jsonWebServiceActionConfigs =
405                            _contextNameIndexedJSONWebServiceActionConfigs.get(contextName);
406    
407                    if (jsonWebServiceActionConfigs == null) {
408                            jsonWebServiceActionConfigs = new CopyOnWriteArrayList<>();
409    
410                            _contextNameIndexedJSONWebServiceActionConfigs.put(
411                                    contextName, jsonWebServiceActionConfigs);
412                    }
413    
414                    jsonWebServiceActionConfigs.add(jsonWebServiceActionConfig);
415    
416                    jsonWebServiceActionConfigs =
417                            _pathIndexedJSONWebServiceActionConfigs.get(
418                                    jsonWebServiceActionConfig.getPath());
419    
420                    if (jsonWebServiceActionConfigs == null) {
421                            jsonWebServiceActionConfigs = new CopyOnWriteArrayList<>();
422    
423                            _pathIndexedJSONWebServiceActionConfigs.put(
424                                    jsonWebServiceActionConfig.getPath(),
425                                    jsonWebServiceActionConfigs);
426                    }
427    
428                    jsonWebServiceActionConfigs.add(jsonWebServiceActionConfig);
429    
430                    return true;
431            }
432    
433            private int _countMatchedParameters(
434                    String[] parameterNames, MethodParameter[] methodParameters) {
435    
436                    int matched = 0;
437    
438                    for (MethodParameter methodParameter : methodParameters) {
439                            String methodParameterName = methodParameter.getName();
440    
441                            methodParameterName = StringUtil.toLowerCase(methodParameterName);
442    
443                            for (String parameterName : parameterNames) {
444                                    if (StringUtil.equalsIgnoreCase(
445                                                    parameterName, methodParameterName)) {
446    
447                                            matched++;
448                                    }
449                            }
450                    }
451    
452                    return matched;
453            }
454    
455            private JSONWebServiceActionConfig _findJSONWebServiceAction(
456                            HttpServletRequest request, String path, String method,
457                            JSONWebServiceActionParameters jsonWebServiceActionParameters)
458                    throws NoSuchJSONWebServiceException {
459    
460                    String[] paths = _resolvePaths(request, path);
461    
462                    String contextName = paths[0];
463    
464                    path = paths[1];
465    
466                    if (_log.isDebugEnabled()) {
467                            _log.debug(
468                                    "Request JSON web service action with path " + path +
469                                            " and method " + method + " for " + contextName);
470                    }
471    
472                    String[] parameterNames =
473                            jsonWebServiceActionParameters.getParameterNames();
474    
475                    JSONWebServiceActionConfig jsonWebServiceActionConfig =
476                            _getJSONWebServiceActionConfig(
477                                    contextName, path, method, parameterNames);
478    
479                    if (jsonWebServiceActionConfig == null) {
480                            if (jsonWebServiceActionParameters.includeDefaultParameters()) {
481                                    parameterNames =
482                                            jsonWebServiceActionParameters.getParameterNames();
483    
484                                    jsonWebServiceActionConfig = _getJSONWebServiceActionConfig(
485                                            contextName, path, method, parameterNames);
486                            }
487                    }
488    
489                    if (jsonWebServiceActionConfig == null) {
490                            throw new NoSuchJSONWebServiceException(
491                                    "No JSON web service action with path " + path +
492                                            " and method " + method + " for " + contextName);
493                    }
494    
495                    return jsonWebServiceActionConfig;
496            }
497    
498            private JSONWebServiceActionConfig _getJSONWebServiceActionConfig(
499                    String contextName, String path, String method,
500                    String[] parameterNames) {
501    
502                    int hint = -1;
503    
504                    int offset = 0;
505    
506                    if (Validator.isNotNull(contextName)) {
507                            String pathPrefix = StringPool.SLASH.concat(contextName).concat(
508                                    StringPool.PERIOD);
509    
510                            if (path.startsWith(pathPrefix)) {
511                                    offset = pathPrefix.length();
512                            }
513                    }
514    
515                    int dotIndex = path.indexOf(CharPool.PERIOD, offset);
516    
517                    if (dotIndex != -1) {
518                            hint = GetterUtil.getInteger(path.substring(dotIndex + 1), -1);
519    
520                            if (hint != -1) {
521                                    path = path.substring(0, dotIndex);
522                            }
523                    }
524    
525                    List<JSONWebServiceActionConfig> jsonWebServiceActionConfigs =
526                            _pathIndexedJSONWebServiceActionConfigs.get(path);
527    
528                    if ((jsonWebServiceActionConfigs == null) ||
529                            jsonWebServiceActionConfigs.isEmpty()) {
530    
531                            if (_log.isDebugEnabled()) {
532                                    _log.debug(
533                                            "Unable to find JSON web service actions with path " +
534                                                    path + " for " + contextName);
535                            }
536    
537                            return null;
538                    }
539    
540                    if (_log.isDebugEnabled()) {
541                            _log.debug(
542                                    "Found " + jsonWebServiceActionConfigs.size() +
543                                            " JSON web service actions with path " + path + " for " +
544                                                    contextName);
545                    }
546    
547                    jsonWebServiceActionConfigs = new ArrayList<>(
548                            jsonWebServiceActionConfigs);
549    
550                    Collections.sort(jsonWebServiceActionConfigs);
551    
552                    int max = -1;
553    
554                    JSONWebServiceActionConfig matchedJSONWebServiceActionConfig = null;
555    
556                    for (JSONWebServiceActionConfig jsonWebServiceActionConfig :
557                                    jsonWebServiceActionConfigs) {
558    
559                            String jsonWebServiceActionConfigMethod =
560                                    jsonWebServiceActionConfig.getMethod();
561    
562                            if (PropsValues.JSONWS_WEB_SERVICE_STRICT_HTTP_METHOD &&
563                                    (method != null)) {
564    
565                                    if ((jsonWebServiceActionConfigMethod != null) &&
566                                            !jsonWebServiceActionConfigMethod.equals(method)) {
567    
568                                            continue;
569                                    }
570                            }
571    
572                            MethodParameter[] jsonWebServiceActionConfigMethodParameters =
573                                    jsonWebServiceActionConfig.getMethodParameters();
574    
575                            int methodParametersCount =
576                                    jsonWebServiceActionConfigMethodParameters.length;
577    
578                            if ((hint != -1) && (methodParametersCount != hint)) {
579                                    continue;
580                            }
581    
582                            int count = _countMatchedParameters(
583                                    parameterNames, jsonWebServiceActionConfigMethodParameters);
584    
585                            if (count > max) {
586                                    if ((hint != -1) || (count >= methodParametersCount)) {
587                                            max = count;
588    
589                                            matchedJSONWebServiceActionConfig =
590                                                    jsonWebServiceActionConfig;
591                                    }
592                            }
593                    }
594    
595                    if (_log.isDebugEnabled()) {
596                            if (matchedJSONWebServiceActionConfig == null) {
597                                    _log.debug(
598                                            "Unable to match parameters to a JSON web service " +
599                                                    "action with path " + path + " for " + contextName);
600                            }
601                            else {
602                                    _log.debug(
603                                            "Matched parameters to a JSON web service action with " +
604                                                    "path " + path + " for " + contextName);
605                            }
606                    }
607    
608                    return matchedJSONWebServiceActionConfig;
609            }
610    
611            private int _getParameterPathIndex(String path) {
612                    int index = path.indexOf(CharPool.SLASH, 1);
613    
614                    if (index != -1) {
615                            index = path.indexOf(CharPool.SLASH, index + 1);
616                    }
617    
618                    return index;
619            }
620    
621            private boolean _removeJSONWebServiceActionConfig(
622                    JSONWebServiceActionConfig jsonWebServiceActionConfig) {
623    
624                    if (!_signatureIndexedJSONWebServiceActionConfigs.remove(
625                                    jsonWebServiceActionConfig.getSignature(),
626                                    jsonWebServiceActionConfig)) {
627    
628                            return false;
629                    }
630    
631                    String contextName = jsonWebServiceActionConfig.getContextName();
632    
633                    List<JSONWebServiceActionConfig> jsonWebServiceActionConfigs =
634                            _contextNameIndexedJSONWebServiceActionConfigs.get(contextName);
635    
636                    jsonWebServiceActionConfigs.remove(jsonWebServiceActionConfig);
637    
638                    if (jsonWebServiceActionConfigs.isEmpty()) {
639                            _contextNameIndexedJSONWebServiceActionConfigs.remove(contextName);
640                    }
641    
642                    jsonWebServiceActionConfigs =
643                            _pathIndexedJSONWebServiceActionConfigs.get(
644                                    jsonWebServiceActionConfig.getPath());
645    
646                    jsonWebServiceActionConfigs.remove(jsonWebServiceActionConfig);
647    
648                    if (jsonWebServiceActionConfigs.isEmpty()) {
649                            _pathIndexedJSONWebServiceActionConfigs.remove(
650                                    jsonWebServiceActionConfig.getPath());
651                    }
652    
653                    return true;
654            }
655    
656            private String[] _resolvePaths(HttpServletRequest request, String path) {
657                    String contextName = null;
658    
659                    int index = path.indexOf(CharPool.FORWARD_SLASH, 1);
660    
661                    if (index != -1) {
662                            index = path.lastIndexOf(CharPool.PERIOD, index);
663    
664                            if (index != -1) {
665                                    contextName = path.substring(1, index);
666                            }
667                    }
668    
669                    if (contextName == null) {
670                            ServletContext servletContext = request.getServletContext();
671    
672                            contextName = servletContext.getServletContextName();
673    
674                            if (Validator.isNotNull(contextName)) {
675                                    path = StringPool.SLASH.concat(contextName).concat(
676                                            StringPool.PERIOD).concat(path.substring(1));
677                            }
678                    }
679    
680                    return new String[] {contextName, path};
681            }
682    
683            private static final Log _log = LogFactoryUtil.getLog(
684                    JSONWebServiceActionsManagerImpl.class);
685    
686            private final Map<String, List<JSONWebServiceActionConfig>>
687                    _contextNameIndexedJSONWebServiceActionConfigs =
688                            new ConcurrentHashMap<>();
689            private final JSONWebServiceNaming _jsonWebServiceNaming =
690                    new JSONWebServiceNaming();
691            private final Map<String, List<JSONWebServiceActionConfig>>
692                    _pathIndexedJSONWebServiceActionConfigs = new ConcurrentHashMap<>();
693            private final ConcurrentMap<String, JSONWebServiceActionConfig>
694                    _signatureIndexedJSONWebServiceActionConfigs =
695                            new ConcurrentHashMap<>();
696    
697    }