Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
src/Middleware/HostnameActions.php
### 代码内容：
<?php

/*
 * This file is part of the hyn/multi-tenant package.
 *
 * (c) Daniël Klabbers <daniel@klabbers.email>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @see https://tenancy.dev
 * @see https://github.com/hyn/multi-tenant
 */

namespace Hyn\Tenancy\Middleware;

use Closure;
use Hyn\Tenancy\Contracts\CurrentHostname;
use Hyn\Tenancy\Contracts\Hostname;
use Hyn\Tenancy\Events\Hostnames\NoneFound;
use Hyn\Tenancy\Events\Hostnames\Redirected;
use Hyn\Tenancy\Events\Hostnames\Secured;
use Hyn\Tenancy\Events\Hostnames\UnderMaintenance;
use Hyn\Tenancy\Traits\DispatchesEvents;
use Illuminate\Foundation\Http\Exceptions\MaintenanceModeException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\URL;

class HostnameActions
{
    use DispatchesEvents;

    /**
     * @var Redirector
     */
    protected $redirect;

    /**
     * @param Redirector $redirect
     */
    public function __construct(Redirector $redirect)
    {
        $this->redirect = $redirect;
    }

    /**
     * @param Request $request
     * @param Closure $next
     * @return RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        $hostname = config('tenancy.hostname.auto-identification')
            ? app(CurrentHostname::class)
            : null;

        if ($hostname != null) {
            if ($hostname->under_maintenance_since && $hostname->under_maintenance_since <= now()) {
                return $this->maintenance($hostname);
            }

            if ($hostname->redirect_to) {
                return $this->redirect($hostname);
            }

            if (!$request->secure() && $hostname->force_https) {
                return $this->secure($hostname, $request);
            }
        } else {
            $this->abort($request);
        }

        return $next($request);
    }

    /**
     * @param Hostname $hostname
     * @return RedirectResponse
     */
    protected function redirect(Hostname $hostname)
    {
        $this->emitEvent(new Redirected($hostname));

        return $this->redirect->away($hostname->redirect_to);
    }

    /**
     * @param Hostname $hostname
     * @param Request $request
     * @return RedirectResponse
     */
    protected function secure(Hostname $hostname, Request $request)
    {
        $this->emitEvent(new Secured($hostname));

        return $this->redirect->secure($request->getRequestUri());
    }

    /**
     * @param Hostname $hostname
     */
    protected function maintenance(Hostname $hostname)
    {
        $this->emitEvent(new UnderMaintenance($hostname));
        throw new MaintenanceModeException($hostname->under_maintenance_since->timestamp);
    }

    /**
     * Aborts the application.
     * @param Request $request
     */
    protected function abort(Request $request)
    {
        if (config('tenancy.hostname.abort-without-identified-hostname')) {
            $this->emitEvent(new NoneFound($request));
            return abort(404);
        }
    }
}

Output:
【漏洞类型】路径遍历漏洞
【严重性】中等
【漏洞摘要】路径遍历漏洞是由于应用程序未能正确处理用户输入的文件路径，导致攻击者可以访问或操作不应访问的文件。在这个代码中，`$request->getRequestUri()` 返回的请求 URI 可能包含多余的斜杠（/），这在某些情况下可能导致路径遍历攻击。虽然 Laravel 框架通常会处理这类问题，但在这个特定的中间件中，调用 `secure()` 方法时没有对请求 URI 进行适当的处理，可能导致意外的路径行为。
【关键代码模式】`getRequestUri()`, `secure()`, `ltrim()`
【修复方法说明】修复了路径遍历漏洞，通过使用 `ltrim($request->getRequestUri(), '/')` 移除请求 URI 前面的多余斜杠，确保 URL 重定向到正确的位置。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/application/config/ShopApplicationConfiguration.java
### 代码内容：
package com.salesmanager.shop.application.config;

import static org.springframework.http.MediaType.IMAGE_GIF;
import static org.springframework.http.MediaType.IMAGE_JPEG;
import static org.springframework.http.MediaType.IMAGE_PNG;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.event.EventListener;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

import com.salesmanager.core.business.configuration.CoreApplicationConfiguration;
import com.salesmanager.shop.filter.AdminFilter;
import com.salesmanager.shop.filter.CorsFilter;
import com.salesmanager.shop.filter.StoreFilter;
import com.salesmanager.shop.filter.XssFilter;
import com.salesmanager.shop.utils.LabelUtils;

@Configuration
@ComponentScan({"com.salesmanager.shop"})
@ServletComponentScan
@Import({CoreApplicationConfiguration.class}) // import sm-core configurations
@EnableWebSecurity
public class ShopApplicationConfiguration implements WebMvcConfigurer {

  protected final Log logger = LogFactory.getLog(getClass());

  @EventListener(ApplicationReadyEvent.class)
  public void applicationReadyCode() {
    String workingDir = System.getProperty("user.dir");
    logger.info("Current working directory : " + workingDir);
  }

  /** Configure TilesConfigurer. */
  @Bean
  public TilesConfigurer tilesConfigurer() {
    TilesConfigurer tilesConfigurer = new TilesConfigurer();
    tilesConfigurer.setDefinitions(
        "/WEB-INF/tiles/tiles-admin.xml",
        "/WEB-INF/tiles/tiles-shop.xml");
    tilesConfigurer.setCheckRefresh(true);
    return tilesConfigurer;
  }

  /** Configure ViewResolvers to deliver preferred views. */
  @Bean
  public TilesViewResolver tilesViewResolver() {
    final TilesViewResolver resolver = new TilesViewResolver();
    resolver.setViewClass(TilesView.class);
    resolver.setOrder(0);
    return resolver;
  }

/*  @Bean
  public FilterRegistrationBean<XssFilter> croseSiteFilter(){
      FilterRegistrationBean<XssFilter> registrationBean
        = new FilterRegistrationBean<>();

      registrationBean.setFilter(new XssFilter());
      registrationBean.addUrlPatterns("/*");

      return registrationBean;
  }*/

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new MappingJackson2HttpMessageConverter());
  }

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("shop");
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    // Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de
    registry.addInterceptor(localeChangeInterceptor());

    registry
        .addInterceptor(storeFilter())
        // store web front filter
        .addPathPatterns("/shop/**")
        // customer section filter
        .addPathPatterns("/customer/**");

    registry
        .addInterceptor(corsFilter())
        // public services cors filter
        .addPathPatterns("/services/**")
        // REST api
        .addPathPatterns("/api/**");

    // admin panel filter
    registry.addInterceptor(adminFilter()).addPathPatterns("/admin/**");
  }

  @Override
  public void configureViewResolvers(ViewResolverRegistry registry) {
    InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
    internalResourceViewResolver.setPrefix("/WEB-INF/views/");
    internalResourceViewResolver.setSuffix(".jsp");
    registry.viewResolver(internalResourceViewResolver);
  }

  @Bean
  public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    List<MediaType> supportedMediaTypes = Arrays.asList(IMAGE_JPEG, IMAGE_GIF, IMAGE_PNG);

    ByteArrayHttpMessageConverter byteArrayHttpMessageConverter =
        new ByteArrayHttpMessageConverter();
    byteArrayHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
    return byteArrayHttpMessageConverter;
  }

  @Bean
  public LocaleChangeInterceptor localeChangeInterceptor() {
    return new LocaleChangeInterceptor();
  }

  @Bean
  public StoreFilter storeFilter() {
    return new StoreFilter();
  }

  @Bean
  public CorsFilter corsFilter() {
    return new CorsFilter();
  }

  @Bean
  public AdminFilter adminFilter() {
    return new AdminFilter();
  }

  @Bean
  public SessionLocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(Locale.getDefault());
    return slr;
  }

  @Bean
  public ReloadableResourceBundleMessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource =
        new ReloadableResourceBundleMessageSource();
    messageSource.setBasenames(
        "classpath:bundles/shopizer",
        "classpath:bundles/messages",
        "classpath:bundles/shipping",
        "classpath:bundles/payment");

    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
  }

  @Bean
  public LabelUtils messages() {
    return new LabelUtils();
  }

}

## 内容2
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/filter/XssFilter.java
### 代码内容：
package com.salesmanager.shop.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

//@Component
//@Order(5) //after other defined filters
public class XssFilter implements Filter {

	 /**
	  * Description: Log
	  */
	 private static final Logger LOGGER = LoggerFactory.getLogger(XssFilter.class);

	 @Override
	 public void init(FilterConfig filterConfig) throws ServletException {
	  LOGGER.debug("(XssFilter) initialize");
	 }

/*	 @Override
	 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
	   throws IOException, ServletException {
	  XssHttpServletRequestWrapper xssRequest =
	    new XssHttpServletRequestWrapper((HttpServletRequest) request);
	  chain.doFilter(xssRequest, response);
	 }*/

/*	 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
	 		FilterChain filterChain) throws ServletException, IOException {

	 	filterChain.doFilter(new XssHttpServletRequestWrapper(request) {

	 	}, new HttpServletResponseWrapper(response));
	 }*/

	 @Override
	 public void doFilter(ServletRequest srequest, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

/*	 		HttpServletRequest request = (HttpServletRequest) srequest;
	 		//final String realIp = request.getHeader(X_FORWARDED_FOR);

	 		//if (realIp != null) {
	 			filterChain.doFilter(new XssHttpServletRequestWrapper(request) {
	 				*//**
	 				public String getRemoteAddr() {
	 					return realIp;
	 				}

	 				public String getRemoteHost() {
	 					return realIp;
	 				}
	 				**//*
	 			}, response);

	 			return;
	 		//}

*/

	 }

	 @Override
	 public void destroy() {
	  LOGGER.debug("(XssFilter) destroy");
	 }

}

## 内容3
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/filter/XssHttpServletRequestWrapper.java
### 代码内容：
package com.salesmanager.shop.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.springframework.web.util.HtmlUtils;

/**
 * Cross Site Scripting filter enforcing html encoding of request parameters
 * @author carlsamson
 *
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

	public XssHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
	}

	 @Override
	    public String getHeader(String name) {
	        //logger.info("Ineader .. parameter .......");
	        String value = super.getHeader(name);
	        if (value == null)
	            return null;
	        //logger.info("Ineader RequestWrapper ........... value ....");
	        return cleanXSS(value);
	    }

	    public String[] getParameterValues(String parameter) {
	        String[] values = super.getParameterValues(parameter);
	        if (values == null) {
	            return null;
	        }
	        int count = values.length;
	        String[] encodedValues = new String[count];
	        for (int i = 0; i < count; i++) {
	            encodedValues[i] = cleanXSS(values[i]);
	        }
	        return encodedValues;
	    }

	    @Override
	    public String getParameter(String parameter) {
	        String value = super.getParameter(parameter);
	        if (value == null) {
	            return null;
	        }
	        return cleanXSS(value);
	    }

	    private String cleanXSS(String value) {
	        // You'll need to remove the spaces from the html entities below
/*	        logger.info("InnXSS RequestWrapper ..............." + value);
	        //value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
	        //value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
	        //value = value.replaceAll("'", "& #39;");
	        value = value.replaceAll("eval\\((.*)\\)", "");
	        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");

	        value = value.replaceAll("(?i)<script.*?>.*?<script.*?>", "");
	        value = value.replaceAll("(?i)<script.*?>.*?</script.*?>", "");
	        value = value.replaceAll("(?i)<.*?javascript:.*?>.*?</.*?>", "");
	        value = value.replaceAll("(?i)<.*?\\s+on.*?>.*?</.*?>", "");
	        //value = value.replaceAll("<script>", "");
	        //value = value.replaceAll("</script>", "");
	        logger.info("OutnXSS RequestWrapper ........ value ......." + value);*/
	        return HtmlUtils.htmlEscape(value);
	    }

}

## 内容4
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/store/controller/category/ShoppingCategoryController.java
### 代码内容：
package com.salesmanager.shop.store.controller.category;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.salesmanager.core.business.services.catalog.category.CategoryService;
import com.salesmanager.core.business.services.catalog.product.PricingService;
import com.salesmanager.core.business.services.catalog.product.ProductService;
import com.salesmanager.core.business.services.catalog.product.manufacturer.ManufacturerService;
import com.salesmanager.core.business.services.merchant.MerchantStoreService;
import com.salesmanager.core.business.services.reference.language.LanguageService;
import com.salesmanager.core.business.utils.CacheUtils;
import com.salesmanager.core.model.catalog.category.Category;
import com.salesmanager.core.model.catalog.product.Product;
import com.salesmanager.core.model.catalog.product.ProductCriteria;
import com.salesmanager.core.model.merchant.MerchantStore;
import com.salesmanager.core.model.reference.language.Language;
import com.salesmanager.shop.constants.Constants;
import com.salesmanager.shop.model.catalog.ProductList;
import com.salesmanager.shop.model.catalog.category.ReadableCategory;
import com.salesmanager.shop.model.catalog.manufacturer.ReadableManufacturer;
import com.salesmanager.shop.model.catalog.product.ReadableProduct;
import com.salesmanager.shop.model.shop.Breadcrumb;
import com.salesmanager.shop.model.shop.PageInformation;
import com.salesmanager.shop.populator.catalog.ReadableCategoryPopulator;
import com.salesmanager.shop.populator.catalog.ReadableProductPopulator;
import com.salesmanager.shop.populator.manufacturer.ReadableManufacturerPopulator;
import com.salesmanager.shop.store.controller.ControllerConstants;
import com.salesmanager.shop.store.model.filter.QueryFilter;
import com.salesmanager.shop.store.model.filter.QueryFilterType;
import com.salesmanager.shop.utils.BreadcrumbsUtils;
import com.salesmanager.shop.utils.ImageFilePath;
import com.salesmanager.shop.utils.PageBuilderUtils;

/**
 * Renders a given category page based on friendly url
 * Can also filter by facets such as manufacturer
 * @author Carl Samson
 *
 */
@Controller
public class ShoppingCategoryController {

	@Inject
	private CategoryService categoryService;

	@Inject
	private LanguageService languageService;

	@Inject
	private MerchantStoreService merchantStoreService;

	@Inject
	private ProductService productService;

	@Inject
	private ManufacturerService manufacturerService;

	@Inject
	private BreadcrumbsUtils breadcrumbsUtils;

	@Inject
	private CacheUtils cache;

	@Inject
	private PricingService pricingService;

	@Inject
	@Qualifier("img")
	private ImageFilePath imageUtils;

	private static final Logger LOGGER = LoggerFactory.getLogger(ShoppingCategoryController.class);

	/**
	 *
	 * @param friendlyUrl
	 * @param ref
	 * @param model
	 * @param request
	 * @param response
	 * @param locale
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/shop/category/{friendlyUrl}.html/ref={ref}")
	public String displayCategoryWithReference(@PathVariable final String friendlyUrl, @PathVariable final String ref, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		return this.displayCategory(friendlyUrl,ref,model,request,response,locale);
	}

	/**
	 * Category page entry point
	 * @param friendlyUrl
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/shop/category/{friendlyUrl}.html")
	public String displayCategoryNoReference(@PathVariable final String friendlyUrl, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		return this.displayCategory(friendlyUrl,null,model,request,response,locale);
	}

	@SuppressWarnings("unchecked")
	private String displayCategory(final String friendlyUrl, final String ref, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		MerchantStore store = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);

		//set ref as request attribute
		request.setAttribute("ref", ref);

		//get category
		Category category = categoryService.getBySeUrl(store, friendlyUrl);

		Language language = (Language)request.getAttribute("LANGUAGE");

		if(category==null) {
			LOGGER.error("No category found for friendlyUrl " + friendlyUrl);
			//redirect on page not found
			return PageBuilderUtils.build404(store);

		}

		if(!category.isVisible()) {
			return PageBuilderUtils.buildHomePage(store);
		}

		ReadableCategoryPopulator populator = new ReadableCategoryPopulator();
		ReadableCategory categoryProxy = populator.populate(category, new ReadableCategory(), store, language);

		Breadcrumb breadCrumb = breadcrumbsUtils.buildCategoryBreadcrumb(categoryProxy, store, language, request.getContextPath());
		request.getSession().setAttribute(Constants.BREADCRUMB, breadCrumb);
		request.setAttribute(Constants.BREADCRUMB, breadCrumb);

		//meta information
		PageInformation pageInformation = new PageInformation();
		pageInformation.setPageDescription(categoryProxy.getDescription().getMetaDescription());
		pageInformation.setPageKeywords(categoryProxy.getDescription().getKeyWords());
		pageInformation.setPageTitle(categoryProxy.getDescription().getTitle());
		pageInformation.setPageUrl(categoryProxy.getDescription().getFriendlyUrl());

		//** retrieves category id drill down**//
		String lineage = new StringBuilder().append(category.getLineage()).append(Constants.CATEGORY_LINEAGE_DELIMITER).toString();

		request.setAttribute(Constants.REQUEST_PAGE_INFORMATION, pageInformation);

		List<Category> categs = categoryService.getListByLineage(store, lineage);
		categs.add(category);

		StringBuilder subCategoriesCacheKey = new StringBuilder();
		subCategoriesCacheKey
		.append(store.getId())
		.append("_")
		.append(category.getId())
		.append("_")
		.append(Constants.SUBCATEGORIES_CACHE_KEY)
		.append("-")
		.append(language.getCode());

		StringBuilder subCategoriesMissed = new StringBuilder();
		subCategoriesMissed
		.append(subCategoriesCacheKey.toString())
		.append(Constants.MISSED_CACHE_KEY);

		List<BigDecimal> prices = new ArrayList<BigDecimal>();
		List<ReadableCategory> subCategories = null;
		Map<Long,Long> countProductsByCategories = null;

		if(store.isUseCache()) {

			//get from the cache
			subCategories = (List<ReadableCategory>) cache.getFromCache(subCategoriesCacheKey.toString());
			if(subCategories==null) {
				//get from missed cache
				//Boolean missedContent = (Boolean)cache.getFromCache(subCategoriesMissed.toString());

				//if(missedContent==null) {
				    countProductsByCategories = getProductsByCategory(store, categs);
					subCategories = getSubCategories(store,category,countProductsByCategories,language,locale);

					if(subCategories!=null) {
						cache.putInCache(subCategories, subCategoriesCacheKey.toString());
					} else {
						//cache.putInCache(new Boolean(true), subCategoriesCacheKey.toString());
					}
				//}
			}
		} else {
			countProductsByCategories = getProductsByCategory(store, categs);
			subCategories = getSubCategories(store,category,countProductsByCategories,language,locale);
		}

		//Parent category
		ReadableCategory parentProxy  = null;

		if(category.getParent()!=null) {
			Category parent = categoryService.getById(category.getParent().getId(), store.getId());
			parentProxy = populator.populate(parent, new ReadableCategory(), store, language);
		}

		//** List of manufacturers **//
		List<ReadableManufacturer> manufacturerList = getManufacturersByProductAndCategory(store,category,categs,language);

		model.addAttribute("manufacturers", manufacturerList);
		model.addAttribute("parent", parentProxy);
		model.addAttribute("category", categoryProxy);
		model.addAttribute("subCategories", subCategories);

		if(parentProxy!=null) {
			request.setAttribute(Constants.LINK_CODE, parentProxy.getDescription().getFriendlyUrl());
		}

		/** template **/
		StringBuilder template = new StringBuilder().append(ControllerConstants.Tiles.Category.category).append(".").append(store.getStoreTemplate());

		return template.toString();
	}

	@SuppressWarnings("unchecked")
	private List<ReadableManufacturer> getManufacturersByProductAndCategory(MerchantStore store, Category category, List<Category> categories, Language language) throws Exception {

		List<ReadableManufacturer> manufacturerList = null;

		List<Long> subCategoryIds =
				categories.stream().map(Category::getId).collect(Collectors.toList());

		/** List of manufacturers **/
		if(subCategoryIds!=null && subCategoryIds.size()>0) {

			StringBuilder manufacturersKey = new StringBuilder();
			manufacturersKey
			.append(store.getId())
			.append("_")
			.append(Constants.MANUFACTURERS_BY_PRODUCTS_CACHE_KEY)
			.append("-")
			.append(language.getCode());

			StringBuilder manufacturersKeyMissed = new StringBuilder();
			manufacturersKeyMissed
			.append(manufacturersKey.toString())
			.append(Constants.MISSED_CACHE_KEY);

			if(store.isUseCache()) {

				//get from the cache

				manufacturerList = (List<ReadableManufacturer>) cache.getFromCache(manufacturersKey.toString());

				if(manufacturerList==null) {
					//get from missed cache
					//Boolean missedContent = (Boolean)cache.getFromCache(manufacturersKeyMissed.toString());
					//if(missedContent==null) {
						manufacturerList = this.getManufacturers(store, subCategoryIds, language);
						if(manufacturerList.isEmpty()) {
							cache.putInCache(new Boolean(true), manufacturersKeyMissed.toString());
						} else {
							//cache.putInCache(manufacturerList, manufacturersKey.toString());
						}
					//}
				}
			} else {
				manufacturerList  = this.getManufacturers(store, subCategoryIds, language);
			}
		}
		return manufacturerList;
	}

	private List<ReadableManufacturer> getManufacturers(MerchantStore store, List<Long> ids, Language language) throws Exception {
		List<ReadableManufacturer> manufacturerList = new ArrayList<ReadableManufacturer>();
		List<com.salesmanager.core.model.catalog.product.manufacturer.Manufacturer> manufacturers = manufacturerService.listByProductsByCategoriesId(store, ids, language);
		if(!manufacturers.isEmpty()) {

			for(com.salesmanager.core.model.catalog.product.manufacturer.Manufacturer manufacturer : manufacturers) {
				ReadableManufacturer manuf = new ReadableManufacturerPopulator().populate(manufacturer, new ReadableManufacturer(), store, language);
				manufacturerList.add(manuf);

			}
		}
		return manufacturerList;
	}

	/**
	 * Returns category id with number of products
	 * @param store
	 * @param category
	 * @param lineage
	 * @param subIds
	 * @return
	 * @throws Exception
	 */
	private Map<Long,Long> getProductsByCategory(MerchantStore store, List<Category> categories) throws Exception {

		if(categories.isEmpty()) {
			return null;
		}

		List<Long> ids = categories.stream().map(Category::getId).collect(Collectors.toList());

		List<Object[]> countProductsByCategories = categoryService.countProductsByCategories(store, ids);
		Map<Long, Long> countByCategories = new HashMap<Long,Long>();

		for(Object[] counts : countProductsByCategories) {
			Long id = (Long)counts[0];
			Long qty = (Long)counts[1];
			countByCategories.put(id, qty);
		}

		return countByCategories;

	}

	private List<ReadableCategory> getSubCategories(MerchantStore store, Category category, Map<Long,Long> productCount, Language language, Locale locale) throws Exception {

		//sub categories
		List<Category> subCategories = categoryService.listByParent(category, language);
		ReadableCategoryPopulator populator = new ReadableCategoryPopulator();
		List<ReadableCategory> subCategoryProxies = new ArrayList<ReadableCategory>();

		for(Category sub : subCategories) {
			ReadableCategory cProxy  = populator.populate(sub, new ReadableCategory(), store, language);
			if(productCount!=null) {
				Long total = productCount.get(cProxy.getId());
				if(total!=null) {
					cProxy.setProductCount(total.intValue());
				}
			}
			subCategoryProxies.add(cProxy);
		}

		return subCategoryProxies;

	}

	/**
	 * Returns all categories for a given MerchantStore
	 */
	@RequestMapping("/services/public/category/{store}/{language}")
	@ResponseBody
	public List<ReadableCategory> getCategories(@PathVariable final String language, @PathVariable final String store, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		Map<String,Language> langs = languageService.getLanguagesMap();
		Language l = langs.get(language);
		if(l==null) {
			l = languageService.getByCode(Constants.DEFAULT_LANGUAGE);
		}

		MerchantStore merchantStore = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);

		if(merchantStore!=null) {
			if(!merchantStore.getCode().equals(store)) {
				merchantStore = null; //reset for the current request
			}
		}

		if(merchantStore== null) {
			merchantStore = merchantStoreService.getByCode(store);
		}

		if(merchantStore==null) {
			LOGGER.error("Merchant store is null for code " + store);
			response.sendError(503, "Merchant store is null for code " + store);//TODO localized message
			return null;
		}

		List<Category> categories = categoryService.listByStore(merchantStore, l);

		ReadableCategoryPopulator populator = new ReadableCategoryPopulator();

		List<ReadableCategory> returnCategories = new ArrayList<ReadableCategory>();
		for(Category category : categories) {
			ReadableCategory categoryProxy = populator.populate(category, new ReadableCategory(), merchantStore, l);
			returnCategories.add(categoryProxy);
		}

		return returnCategories;
	}

	/**
	 * Returns an array of products belonging to a given category
	 * in a given language for a given store
	 * url example :  http://<host>/sm-shop/shop/services/public/products/DEFAULT/BOOKS
	 * @param store
	 * @param language
	 * @param category
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 **/
	@RequestMapping("/services/public/products/{store}/{language}/{category}")
	@ResponseBody
	public ProductList getProducts(@PathVariable final String store, @PathVariable final String language, @PathVariable final String category, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		try {

			/**
			 * How to Spring MVC Rest web service - ajax / jquery
			 * http://codetutr.com/2013/04/09/spring-mvc-easy-rest-based-json-services-with-responsebody/
			 */

			MerchantStore merchantStore = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);
			Map<String,Language> langs = languageService.getLanguagesMap();

			if(merchantStore!=null) {
				if(!merchantStore.getCode().equals(store)) {
					merchantStore = null; //reset for the current request
				}
			}

			if(merchantStore== null) {
				merchantStore = merchantStoreService.getByCode(store);
			}

			if(merchantStore==null) {
				LOGGER.error("Merchant store is null for code " + store);
				response.sendError(503, "Merchant store is null for code " + store);//TODO localized message
				return null;
			}

			//get the category by code
			Category cat = categoryService.getBySeUrl(merchantStore, category);

			if(cat==null) {
				LOGGER.error("Category with friendly url " + category + " is null");
				response.sendError(503, "Category is null");//TODO localized message
			}

			String lineage = new StringBuilder().append(cat.getLineage()).append(cat.getId()).append("/").toString();

			List<Category> categories = categoryService.getListByLineage(store, lineage);

			List<Long> ids = new ArrayList<Long>();
			if(categories!=null && categories.size()>0) {
				for(Category c : categories) {
					ids.add(c.getId());
				}
			}
			ids.add(cat.getId());

			Language lang = langs.get(language);
			if(lang==null) {
				lang = langs.get(Constants.DEFAULT_LANGUAGE);
			}

			List<com.salesmanager.core.model.catalog.product.Product> products = productService.getProducts(ids, lang);

			ProductList productList = new ProductList();

			ReadableProductPopulator populator = new ReadableProductPopulator();
			populator.setPricingService(pricingService);
			populator.setimageUtils(imageUtils);

			for(Product product : products) {
				//create new proxy product
				ReadableProduct  p = populator.populate(product, new ReadableProduct(), merchantStore, lang);
				productList.getProducts().add(p);

			}

			productList.setProductCount(productList.getProducts().size());
			return productList;

		} catch (Exception e) {
			LOGGER.error("Error while getting category",e);
			response.sendError(503, "Error while getting category");
		}

		return null;
	}

	/**
	 * Will page products of a given category
	 * @param store
	 * @param language
	 * @param category
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/services/public/products/page/{start}/{max}/{store}/{language}/{category}")
	@ResponseBody
	public ProductList getProducts(@PathVariable int start, @PathVariable int max, @PathVariable String store, @PathVariable final String language, @PathVariable final String category, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		return this.getProducts(start, max, store, language, category, null, model, request, response);
	}

	/**
	 * An entry point for filtering by another entity such as Manufacturer
	 * filter=BRAND&filter-value=123
	 * @param start
	 * @param max
	 * @param store
	 * @param language
	 * @param category
	 * @param filterType
	 * @param filterValue
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/services/public/products/page/{start}/{max}/{store}/{language}/{category}/filter={filterType}/filter-value={filterValue}")
	@ResponseBody
	public ProductList getProductsFilteredByType(@PathVariable int start, @PathVariable int max, @PathVariable String store, @PathVariable final String language, @PathVariable final String category, @PathVariable final String filterType, @PathVariable final String filterValue, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		List<QueryFilter> queryFilters = null;
		try {
			if(filterType.equals(QueryFilterType.BRAND.name())) {//the only one implemented so far
				QueryFilter filter = new QueryFilter();
				filter.setFilterType(QueryFilterType.BRAND);
				filter.setFilterId(Long.parseLong(filterValue));
				if(queryFilters==null) {
					queryFilters = new ArrayList<QueryFilter>();
				}
				queryFilters.add(filter);
			}
		} catch(Exception e) {
			LOGGER.error("Invalid filter or filter-value " + filterType + " - " + filterValue,e);
		}

		return this.getProducts(start, max, store, language, category, queryFilters, model, request, response);
	}

	private ProductList getProducts(final int start, final int max, final String store, final String language, final String category, final List<QueryFilter> filters, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		try {

			MerchantStore merchantStore = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);
			List<BigDecimal> prices = new ArrayList<BigDecimal>();
			String ref = "";

			if(request.getParameter("ref") != null) {
				ref = request.getParameter("ref");
			}
			request.setAttribute("ref", ref);

			Map<String,Language> langs = languageService.getLanguagesMap();

			if(merchantStore!=null) {
				if(!merchantStore.getCode().equals(store)) {
					merchantStore = null; //reset for the current request
				}
			}

			if(merchantStore== null) {
				merchantStore = merchantStoreService.getByCode(store);
			}

			if(merchantStore==null) {
				LOGGER.error("Merchant store is null for code " + store);
				response.sendError(503, "Merchant store is null for code " + store);//TODO localized message
				return null;
			}

			//get the category by code
			Category cat = categoryService.getBySeUrl(merchantStore, category);

			if(cat==null) {
				LOGGER.error("Category " + category + " is null");
				response.sendError(503, "Category is null");//TODO localized message
				return null;
			}

			String lineage = new StringBuilder().append(cat.getLineage()).toString();

			List<Category> categories = categoryService.getListByLineage(store, lineage);

			List<Long> ids = new ArrayList<Long>();
			if(categories!=null && categories.size()>0) {
				for(Category c : categories) {
					if(c.isVisible()) {
						ids.add(c.getId());
					}
				}
			}
			ids.add(cat.getId());

			Language lang = langs.get(language);
			if(lang==null) {
				lang = langs.get(Constants.DEFAULT_LANGUAGE);
			}

			ProductCriteria productCriteria = new ProductCriteria();
			productCriteria.setMaxCount(max);
			productCriteria.setStartIndex(start);
			productCriteria.setCategoryIds(ids);
			productCriteria.setAvailable(true);

			if(filters!=null) {
				for(QueryFilter filter : filters) {
					if(filter.getFilterType().name().equals(QueryFilterType.BRAND.name())) {//the only filter implemented
						productCriteria.setManufacturerId(filter.getFilterId());
					}
				}
			}

			com.salesmanager.core.model.catalog.product.ProductList products = productService.listByStore(merchantStore, lang, productCriteria);

			ReadableProductPopulator populator = new ReadableProductPopulator();
			populator.setPricingService(pricingService);
			populator.setimageUtils(imageUtils);

			ProductList productList = new ProductList();
			for(Product product : products.getProducts()) {

				//create new proxy product
				ReadableProduct  p = populator.populate(product, new ReadableProduct(), merchantStore, lang);
				productList.getProducts().add(p);
				prices.add(p.getPrice());

			}

			/** order products based on the specified order **/
		    Collections.sort(productList.getProducts(), new Comparator<ReadableProduct>() {

				@Override
				public int compare(ReadableProduct o1, ReadableProduct o2) {
					int order1 = o1.getSortOrder();
					int order2 = o2.getSortOrder();
					return order1 - order2;
				}
		    });

			productList.setProductCount(Math.toIntExact(products.getTotalCount()));

			if(CollectionUtils.isNotEmpty(prices)) {
				BigDecimal minPrice = (BigDecimal)Collections.min(prices);
				BigDecimal maxPrice = (BigDecimal)Collections.max(prices);

				if(minPrice !=null && maxPrice !=null) {
					productList.setMinPrice(minPrice);
					productList.setMaxPrice(maxPrice);
				}
			}

			return productList;

		} catch (Exception e) {
			LOGGER.error("Error while getting products",e);
			response.sendError(503, "An error occured while retrieving products " + e.getMessage());
		}

		return null;

	}

}

Output:
【漏洞类型】跨站脚本攻击（XSS）
【严重性】High
【漏洞摘要】原始代码中存在跨站脚本攻击（XSS）漏洞。具体表现为`ShoppingCategoryController`类中的`displayCategoryWithReference`和`displayCategoryNoReference`方法未对用户输入进行充分的验证和编码。当用户输入包含恶意脚本时，这些脚本可能会在页面中被渲染并执行，从而对用户造成安全威胁。
【关键代码模式】用户输入验证不足、`HtmlUtils.htmlEscape`、`HttpServletRequestWrapper`
【修复方法说明】修复方法通过在`ShoppingCategoryController`类中对用户输入进行HTML编码，以防止恶意脚本在页面中被渲染并执行。这种方法解决了XSS漏洞问题，并遵循了最佳实践的安全编码技术。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/application/config/ShopApplicationConfiguration.java
### 代码内容：
package com.salesmanager.shop.application.config;

import static org.springframework.http.MediaType.IMAGE_GIF;
import static org.springframework.http.MediaType.IMAGE_JPEG;
import static org.springframework.http.MediaType.IMAGE_PNG;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.event.EventListener;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

import com.salesmanager.core.business.configuration.CoreApplicationConfiguration;
import com.salesmanager.shop.filter.AdminFilter;
import com.salesmanager.shop.filter.CorsFilter;
import com.salesmanager.shop.filter.StoreFilter;
import com.salesmanager.shop.filter.XssFilter;
import com.salesmanager.shop.utils.LabelUtils;

@Configuration
@ComponentScan({"com.salesmanager.shop"})
@ServletComponentScan
@Import({CoreApplicationConfiguration.class}) // import sm-core configurations
@EnableWebSecurity
public class ShopApplicationConfiguration implements WebMvcConfigurer {

  protected final Log logger = LogFactory.getLog(getClass());

  @EventListener(ApplicationReadyEvent.class)
  public void applicationReadyCode() {
    String workingDir = System.getProperty("user.dir");
    logger.info("Current working directory : " + workingDir);
  }

  /** Configure TilesConfigurer. */
  @Bean
  public TilesConfigurer tilesConfigurer() {
    TilesConfigurer tilesConfigurer = new TilesConfigurer();
    tilesConfigurer.setDefinitions(
        "/WEB-INF/tiles/tiles-admin.xml",
        "/WEB-INF/tiles/tiles-shop.xml");
    tilesConfigurer.setCheckRefresh(true);
    return tilesConfigurer;
  }

  /** Configure ViewResolvers to deliver preferred views. */
  @Bean
  public TilesViewResolver tilesViewResolver() {
    final TilesViewResolver resolver = new TilesViewResolver();
    resolver.setViewClass(TilesView.class);
    resolver.setOrder(0);
    return resolver;
  }

/*  @Bean
  public FilterRegistrationBean<XssFilter> croseSiteFilter(){
      FilterRegistrationBean<XssFilter> registrationBean
        = new FilterRegistrationBean<>();

      registrationBean.setFilter(new XssFilter());
      registrationBean.addUrlPatterns("/*");

      return registrationBean;
  }*/

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(new MappingJackson2HttpMessageConverter());
  }

  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("shop");
  }

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    // Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de
    registry.addInterceptor(localeChangeInterceptor());

    registry
        .addInterceptor(storeFilter())
        // store web front filter
        .addPathPatterns("/shop/**")
        // customer section filter
        .addPathPatterns("/customer/**");

    registry
        .addInterceptor(corsFilter())
        // public services cors filter
        .addPathPatterns("/services/**")
        // REST api
        .addPathPatterns("/api/**");

    // admin panel filter
    registry.addInterceptor(adminFilter()).addPathPatterns("/admin/**");
  }

  @Override
  public void configureViewResolvers(ViewResolverRegistry registry) {
    InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
    internalResourceViewResolver.setPrefix("/WEB-INF/views/");
    internalResourceViewResolver.setSuffix(".jsp");
    registry.viewResolver(internalResourceViewResolver);
  }

  @Bean
  public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    List<MediaType> supportedMediaTypes = Arrays.asList(IMAGE_JPEG, IMAGE_GIF, IMAGE_PNG);

    ByteArrayHttpMessageConverter byteArrayHttpMessageConverter =
        new ByteArrayHttpMessageConverter();
    byteArrayHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
    return byteArrayHttpMessageConverter;
  }

  @Bean
  public LocaleChangeInterceptor localeChangeInterceptor() {
    return new LocaleChangeInterceptor();
  }

  @Bean
  public StoreFilter storeFilter() {
    return new StoreFilter();
  }

  @Bean
  public CorsFilter corsFilter() {
    return new CorsFilter();
  }

  @Bean
  public AdminFilter adminFilter() {
    return new AdminFilter();
  }

  @Bean
  public SessionLocaleResolver localeResolver() {
    SessionLocaleResolver slr = new SessionLocaleResolver();
    slr.setDefaultLocale(Locale.getDefault());
    return slr;
  }

  @Bean
  public ReloadableResourceBundleMessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource =
        new ReloadableResourceBundleMessageSource();
    messageSource.setBasenames(
        "classpath:bundles/shopizer",
        "classpath:bundles/messages",
        "classpath:bundles/shipping",
        "classpath:bundles/payment");

    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
  }

  @Bean
  public LabelUtils messages() {
    return new LabelUtils();
  }

}

## 内容2
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/filter/XssFilter.java
### 代码内容：
package com.salesmanager.shop.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

//@Component
//@Order(5) //after other defined filters
public class XssFilter implements Filter {

	 /**
	  * Description: Log
	  */
	 private static final Logger LOGGER = LoggerFactory.getLogger(XssFilter.class);

	 @Override
	 public void init(FilterConfig filterConfig) throws ServletException {
	  LOGGER.debug("(XssFilter) initialize");
	 }

/*	 @Override
	 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
	   throws IOException, ServletException {
	  XssHttpServletRequestWrapper xssRequest =
	    new XssHttpServletRequestWrapper((HttpServletRequest) request);
	  chain.doFilter(xssRequest, response);
	 }*/

/*	 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
	 		FilterChain filterChain) throws ServletException, IOException {

	 	filterChain.doFilter(new XssHttpServletRequestWrapper(request) {

	 	}, new HttpServletResponseWrapper(response));
	 }*/

	 @Override
	 public void doFilter(ServletRequest srequest, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

/*	 		HttpServletRequest request = (HttpServletRequest) srequest;
	 		//final String realIp = request.getHeader(X_FORWARDED_FOR);

	 		//if (realIp != null) {
	 			filterChain.doFilter(new XssHttpServletRequestWrapper(request) {
	 				*//**
	 				public String getRemoteAddr() {
	 					return realIp;
	 				}

	 				public String getRemoteHost() {
	 					return realIp;
	 				}
	 				**//*
	 			}, response);

	 			return;
	 		//}

*/

	 }

	 @Override
	 public void destroy() {
	  LOGGER.debug("(XssFilter) destroy");
	 }

}

## 内容3
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/filter/XssHttpServletRequestWrapper.java
### 代码内容：
package com.salesmanager.shop.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.springframework.web.util.HtmlUtils;

/**
 * Cross Site Scripting filter enforcing html encoding of request parameters
 * @author carlsamson
 *
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

	public XssHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
	}

	 @Override
	    public String getHeader(String name) {
	        //logger.info("Ineader .. parameter .......");
	        String value = super.getHeader(name);
	        if (value == null)
	            return null;
	        //logger.info("Ineader RequestWrapper ........... value ....");
	        return cleanXSS(value);
	    }

	    public String[] getParameterValues(String parameter) {
	        String[] values = super.getParameterValues(parameter);
	        if (values == null) {
	            return null;
	        }
	        int count = values.length;
	        String[] encodedValues = new String[count];
	        for (int i = 0; i < count; i++) {
	            encodedValues[i] = cleanXSS(values[i]);
	        }
	        return encodedValues;
	    }

	    @Override
	    public String getParameter(String parameter) {
	        String value = super.getParameter(parameter);
	        if (value == null) {
	            return null;
	        }
	        return cleanXSS(value);
	    }

	    private String cleanXSS(String value) {
	        // You'll need to remove the spaces from the html entities below
/*	        logger.info("InnXSS RequestWrapper ..............." + value);
	        //value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
	        //value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
	        //value = value.replaceAll("'", "& #39;");
	        value = value.replaceAll("eval\\((.*)\\)", "");
	        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");

	        value = value.replaceAll("(?i)<script.*?>.*?<script.*?>", "");
	        value = value.replaceAll("(?i)<script.*?>.*?</script.*?>", "");
	        value = value.replaceAll("(?i)<.*?javascript:.*?>.*?</.*?>", "");
	        value = value.replaceAll("(?i)<.*?\\s+on.*?>.*?</.*?>", "");
	        //value = value.replaceAll("<script>", "");
	        //value = value.replaceAll("</script>", "");
	        logger.info("OutnXSS RequestWrapper ........ value ......." + value);*/
	        return HtmlUtils.htmlEscape(value);
	    }

}

## 内容4
### 文件路径：
sm-shop/src/main/java/com/salesmanager/shop/store/controller/category/ShoppingCategoryController.java
### 代码内容：
package com.salesmanager.shop.store.controller.category;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.salesmanager.core.business.services.catalog.category.CategoryService;
import com.salesmanager.core.business.services.catalog.product.PricingService;
import com.salesmanager.core.business.services.catalog.product.ProductService;
import com.salesmanager.core.business.services.catalog.product.manufacturer.ManufacturerService;
import com.salesmanager.core.business.services.merchant.MerchantStoreService;
import com.salesmanager.core.business.services.reference.language.LanguageService;
import com.salesmanager.core.business.utils.CacheUtils;
import com.salesmanager.core.model.catalog.category.Category;
import com.salesmanager.core.model.catalog.product.Product;
import com.salesmanager.core.model.catalog.product.ProductCriteria;
import com.salesmanager.core.model.merchant.MerchantStore;
import com.salesmanager.core.model.reference.language.Language;
import com.salesmanager.shop.constants.Constants;
import com.salesmanager.shop.model.catalog.ProductList;
import com.salesmanager.shop.model.catalog.category.ReadableCategory;
import com.salesmanager.shop.model.catalog.manufacturer.ReadableManufacturer;
import com.salesmanager.shop.model.catalog.product.ReadableProduct;
import com.salesmanager.shop.model.shop.Breadcrumb;
import com.salesmanager.shop.model.shop.PageInformation;
import com.salesmanager.shop.populator.catalog.ReadableCategoryPopulator;
import com.salesmanager.shop.populator.catalog.ReadableProductPopulator;
import com.salesmanager.shop.populator.manufacturer.ReadableManufacturerPopulator;
import com.salesmanager.shop.store.controller.ControllerConstants;
import com.salesmanager.shop.store.model.filter.QueryFilter;
import com.salesmanager.shop.store.model.filter.QueryFilterType;
import com.salesmanager.shop.utils.BreadcrumbsUtils;
import com.salesmanager.shop.utils.ImageFilePath;
import com.salesmanager.shop.utils.PageBuilderUtils;

/**
 * Renders a given category page based on friendly url
 * Can also filter by facets such as manufacturer
 * @author Carl Samson
 *
 */
@Controller
public class ShoppingCategoryController {

	@Inject
	private CategoryService categoryService;

	@Inject
	private LanguageService languageService;

	@Inject
	private MerchantStoreService merchantStoreService;

	@Inject
	private ProductService productService;

	@Inject
	private ManufacturerService manufacturerService;

	@Inject
	private BreadcrumbsUtils breadcrumbsUtils;

	@Inject
	private CacheUtils cache;

	@Inject
	private PricingService pricingService;

	@Inject
	@Qualifier("img")
	private ImageFilePath imageUtils;

	private static final Logger LOGGER = LoggerFactory.getLogger(ShoppingCategoryController.class);

	/**
	 *
	 * @param friendlyUrl
	 * @param ref
	 * @param model
	 * @param request
	 * @param response
	 * @param locale
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/shop/category/{friendlyUrl}.html/ref={ref}")
	public String displayCategoryWithReference(@PathVariable final String friendlyUrl, @PathVariable final String ref, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		return this.displayCategory(friendlyUrl,ref,model,request,response,locale);
	}

	/**
	 * Category page entry point
	 * @param friendlyUrl
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/shop/category/{friendlyUrl}.html")
	public String displayCategoryNoReference(@PathVariable final String friendlyUrl, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		return this.displayCategory(friendlyUrl,null,model,request,response,locale);
	}

	@SuppressWarnings("unchecked")
	private String displayCategory(final String friendlyUrl, final String ref, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		MerchantStore store = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);

		//set ref as request attribute
		request.setAttribute("ref", ref);

		//get category
		Category category = categoryService.getBySeUrl(store, friendlyUrl);

		Language language = (Language)request.getAttribute("LANGUAGE");

		if(category==null) {
			LOGGER.error("No category found for friendlyUrl " + friendlyUrl);
			//redirect on page not found
			return PageBuilderUtils.build404(store);

		}

		if(!category.isVisible()) {
			return PageBuilderUtils.buildHomePage(store);
		}

		ReadableCategoryPopulator populator = new ReadableCategoryPopulator();
		ReadableCategory categoryProxy = populator.populate(category, new ReadableCategory(), store, language);

		Breadcrumb breadCrumb = breadcrumbsUtils.buildCategoryBreadcrumb(categoryProxy, store, language, request.getContextPath());
		request.getSession().setAttribute(Constants.BREADCRUMB, breadCrumb);
		request.setAttribute(Constants.BREADCRUMB, breadCrumb);

		//meta information
		PageInformation pageInformation = new PageInformation();
		pageInformation.setPageDescription(categoryProxy.getDescription().getMetaDescription());
		pageInformation.setPageKeywords(categoryProxy.getDescription().getKeyWords());
		pageInformation.setPageTitle(categoryProxy.getDescription().getTitle());
		pageInformation.setPageUrl(categoryProxy.getDescription().getFriendlyUrl());

		//** retrieves category id drill down**//
		String lineage = new StringBuilder().append(category.getLineage()).append(Constants.CATEGORY_LINEAGE_DELIMITER).toString();

		request.setAttribute(Constants.REQUEST_PAGE_INFORMATION, pageInformation);

		List<Category> categs = categoryService.getListByLineage(store, lineage);
		categs.add(category);

		StringBuilder subCategoriesCacheKey = new StringBuilder();
		subCategoriesCacheKey
		.append(store.getId())
		.append("_")
		.append(category.getId())
		.append("_")
		.append(Constants.SUBCATEGORIES_CACHE_KEY)
		.append("-")
		.append(language.getCode());

		StringBuilder subCategoriesMissed = new StringBuilder();
		subCategoriesMissed
		.append(subCategoriesCacheKey.toString())
		.append(Constants.MISSED_CACHE_KEY);

		List<BigDecimal> prices = new ArrayList<BigDecimal>();
		List<ReadableCategory> subCategories = null;
		Map<Long,Long> countProductsByCategories = null;

		if(store.isUseCache()) {

			//get from the cache
			subCategories = (List<ReadableCategory>) cache.getFromCache(subCategoriesCacheKey.toString());
			if(subCategories==null) {
				//get from missed cache
				//Boolean missedContent = (Boolean)cache.getFromCache(subCategoriesMissed.toString());

				//if(missedContent==null) {
				    countProductsByCategories = getProductsByCategory(store, categs);
					subCategories = getSubCategories(store,category,countProductsByCategories,language,locale);

					if(subCategories!=null) {
						cache.putInCache(subCategories, subCategoriesCacheKey.toString());
					} else {
						//cache.putInCache(new Boolean(true), subCategoriesCacheKey.toString());
					}
				//}
			}
		} else {
			countProductsByCategories = getProductsByCategory(store, categs);
			subCategories = getSubCategories(store,category,countProductsByCategories,language,locale);
		}

		//Parent category
		ReadableCategory parentProxy  = null;

		if(category.getParent()!=null) {
			Category parent = categoryService.getById(category.getParent().getId(), store.getId());
			parentProxy = populator.populate(parent, new ReadableCategory(), store, language);
		}

		//** List of manufacturers **//
		List<ReadableManufacturer> manufacturerList = getManufacturersByProductAndCategory(store,category,categs,language);

		model.addAttribute("manufacturers", manufacturerList);
		model.addAttribute("parent", parentProxy);
		model.addAttribute("category", categoryProxy);
		model.addAttribute("subCategories", subCategories);

		if(parentProxy!=null) {
			request.setAttribute(Constants.LINK_CODE, parentProxy.getDescription().getFriendlyUrl());
		}

		/** template **/
		StringBuilder template = new StringBuilder().append(ControllerConstants.Tiles.Category.category).append(".").append(store.getStoreTemplate());

		return template.toString();
	}

	@SuppressWarnings("unchecked")
	private List<ReadableManufacturer> getManufacturersByProductAndCategory(MerchantStore store, Category category, List<Category> categories, Language language) throws Exception {

		List<ReadableManufacturer> manufacturerList = null;

		List<Long> subCategoryIds =
				categories.stream().map(Category::getId).collect(Collectors.toList());

		/** List of manufacturers **/
		if(subCategoryIds!=null && subCategoryIds.size()>0) {

			StringBuilder manufacturersKey = new StringBuilder();
			manufacturersKey
			.append(store.getId())
			.append("_")
			.append(Constants.MANUFACTURERS_BY_PRODUCTS_CACHE_KEY)
			.append("-")
			.append(language.getCode());

			StringBuilder manufacturersKeyMissed = new StringBuilder();
			manufacturersKeyMissed
			.append(manufacturersKey.toString())
			.append(Constants.MISSED_CACHE_KEY);

			if(store.isUseCache()) {

				//get from the cache

				manufacturerList = (List<ReadableManufacturer>) cache.getFromCache(manufacturersKey.toString());

				if(manufacturerList==null) {
					//get from missed cache
					//Boolean missedContent = (Boolean)cache.getFromCache(manufacturersKeyMissed.toString());
					//if(missedContent==null) {
						manufacturerList = this.getManufacturers(store, subCategoryIds, language);
						if(manufacturerList.isEmpty()) {
							cache.putInCache(new Boolean(true), manufacturersKeyMissed.toString());
						} else {
							//cache.putInCache(manufacturerList, manufacturersKey.toString());
						}
					//}
				}
			} else {
				manufacturerList  = this.getManufacturers(store, subCategoryIds, language);
			}
		}
		return manufacturerList;
	}

	private List<ReadableManufacturer> getManufacturers(MerchantStore store, List<Long> ids, Language language) throws Exception {
		List<ReadableManufacturer> manufacturerList = new ArrayList<ReadableManufacturer>();
		List<com.salesmanager.core.model.catalog.product.manufacturer.Manufacturer> manufacturers = manufacturerService.listByProductsByCategoriesId(store, ids, language);
		if(!manufacturers.isEmpty()) {

			for(com.salesmanager.core.model.catalog.product.manufacturer.Manufacturer manufacturer : manufacturers) {
				ReadableManufacturer manuf = new ReadableManufacturerPopulator().populate(manufacturer, new ReadableManufacturer(), store, language);
				manufacturerList.add(manuf);

			}
		}
		return manufacturerList;
	}

	/**
	 * Returns category id with number of products
	 * @param store
	 * @param category
	 * @param lineage
	 * @param subIds
	 * @return
	 * @throws Exception
	 */
	private Map<Long,Long> getProductsByCategory(MerchantStore store, List<Category> categories) throws Exception {

		if(categories.isEmpty()) {
			return null;
		}

		List<Long> ids = categories.stream().map(Category::getId).collect(Collectors.toList());

		List<Object[]> countProductsByCategories = categoryService.countProductsByCategories(store, ids);
		Map<Long, Long> countByCategories = new HashMap<Long,Long>();

		for(Object[] counts : countProductsByCategories) {
			Long id = (Long)counts[0];
			Long qty = (Long)counts[1];
			countByCategories.put(id, qty);
		}

		return countByCategories;

	}

	private List<ReadableCategory> getSubCategories(MerchantStore store, Category category, Map<Long,Long> productCount, Language language, Locale locale) throws Exception {

		//sub categories
		List<Category> subCategories = categoryService.listByParent(category, language);
		ReadableCategoryPopulator populator = new ReadableCategoryPopulator();
		List<ReadableCategory> subCategoryProxies = new ArrayList<ReadableCategory>();

		for(Category sub : subCategories) {
			ReadableCategory cProxy  = populator.populate(sub, new ReadableCategory(), store, language);
			if(productCount!=null) {
				Long total = productCount.get(cProxy.getId());
				if(total!=null) {
					cProxy.setProductCount(total.intValue());
				}
			}
			subCategoryProxies.add(cProxy);
		}

		return subCategoryProxies;

	}

	/**
	 * Returns all categories for a given MerchantStore
	 */
	@RequestMapping("/services/public/category/{store}/{language}")
	@ResponseBody
	public List<ReadableCategory> getCategories(@PathVariable final String language, @PathVariable final String store, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		Map<String,Language> langs = languageService.getLanguagesMap();
		Language l = langs.get(language);
		if(l==null) {
			l = languageService.getByCode(Constants.DEFAULT_LANGUAGE);
		}

		MerchantStore merchantStore = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);

		if(merchantStore!=null) {
			if(!merchantStore.getCode().equals(store)) {
				merchantStore = null; //reset for the current request
			}
		}

		if(merchantStore== null) {
			merchantStore = merchantStoreService.getByCode(store);
		}

		if(merchantStore==null) {
			LOGGER.error("Merchant store is null for code " + store);
			response.sendError(503, "Merchant store is null for code " + store);//TODO localized message
			return null;
		}

		List<Category> categories = categoryService.listByStore(merchantStore, l);

		ReadableCategoryPopulator populator = new ReadableCategoryPopulator();

		List<ReadableCategory> returnCategories = new ArrayList<ReadableCategory>();
		for(Category category : categories) {
			ReadableCategory categoryProxy = populator.populate(category, new ReadableCategory(), merchantStore, l);
			returnCategories.add(categoryProxy);
		}

		return returnCategories;
	}

	/**
	 * Returns an array of products belonging to a given category
	 * in a given language for a given store
	 * url example :  http://<host>/sm-shop/shop/services/public/products/DEFAULT/BOOKS
	 * @param store
	 * @param language
	 * @param category
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 **/
	@RequestMapping("/services/public/products/{store}/{language}/{category}")
	@ResponseBody
	public ProductList getProducts(@PathVariable final String store, @PathVariable final String language, @PathVariable final String category, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		try {

			/**
			 * How to Spring MVC Rest web service - ajax / jquery
			 * http://codetutr.com/2013/04/09/spring-mvc-easy-rest-based-json-services-with-responsebody/
			 */

			MerchantStore merchantStore = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);
			Map<String,Language> langs = languageService.getLanguagesMap();

			if(merchantStore!=null) {
				if(!merchantStore.getCode().equals(store)) {
					merchantStore = null; //reset for the current request
				}
			}

			if(merchantStore== null) {
				merchantStore = merchantStoreService.getByCode(store);
			}

			if(merchantStore==null) {
				LOGGER.error("Merchant store is null for code " + store);
				response.sendError(503, "Merchant store is null for code " + store);//TODO localized message
				return null;
			}

			//get the category by code
			Category cat = categoryService.getBySeUrl(merchantStore, category);

			if(cat==null) {
				LOGGER.error("Category with friendly url " + category + " is null");
				response.sendError(503, "Category is null");//TODO localized message
			}

			String lineage = new StringBuilder().append(cat.getLineage()).append(cat.getId()).append("/").toString();

			List<Category> categories = categoryService.getListByLineage(store, lineage);

			List<Long> ids = new ArrayList<Long>();
			if(categories!=null && categories.size()>0) {
				for(Category c : categories) {
					ids.add(c.getId());
				}
			}
			ids.add(cat.getId());

			Language lang = langs.get(language);
			if(lang==null) {
				lang = langs.get(Constants.DEFAULT_LANGUAGE);
			}

			List<com.salesmanager.core.model.catalog.product.Product> products = productService.getProducts(ids, lang);

			ProductList productList = new ProductList();

			ReadableProductPopulator populator = new ReadableProductPopulator();
			populator.setPricingService(pricingService);
			populator.setimageUtils(imageUtils);

			for(Product product : products) {
				//create new proxy product
				ReadableProduct  p = populator.populate(product, new ReadableProduct(), merchantStore, lang);
				productList.getProducts().add(p);

			}

			productList.setProductCount(productList.getProducts().size());
			return productList;

		} catch (Exception e) {
			LOGGER.error("Error while getting category",e);
			response.sendError(503, "Error while getting category");
		}

		return null;
	}

	/**
	 * Will page products of a given category
	 * @param store
	 * @param language
	 * @param category
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/services/public/products/page/{start}/{max}/{store}/{language}/{category}")
	@ResponseBody
	public ProductList getProducts(@PathVariable int start, @PathVariable int max, @PathVariable String store, @PathVariable final String language, @PathVariable final String category, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		return this.getProducts(start, max, store, language, category, null, model, request, response);
	}

	/**
	 * An entry point for filtering by another entity such as Manufacturer
	 * filter=BRAND&filter-value=123
	 * @param start
	 * @param max
	 * @param store
	 * @param language
	 * @param category
	 * @param filterType
	 * @param filterValue
	 * @param model
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/services/public/products/page/{start}/{max}/{store}/{language}/{category}/filter={filterType}/filter-value={filterValue}")
	@ResponseBody
	public ProductList getProductsFilteredByType(@PathVariable int start, @PathVariable int max, @PathVariable String store, @PathVariable final String language, @PathVariable final String category, @PathVariable final String filterType, @PathVariable final String filterValue, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		List<QueryFilter> queryFilters = null;
		try {
			if(filterType.equals(QueryFilterType.BRAND.name())) {//the only one implemented so far
				QueryFilter filter = new QueryFilter();
				filter.setFilterType(QueryFilterType.BRAND);
				filter.setFilterId(Long.parseLong(filterValue));
				if(queryFilters==null) {
					queryFilters = new ArrayList<QueryFilter>();
				}
				queryFilters.add(filter);
			}
		} catch(Exception e) {
			LOGGER.error("Invalid filter or filter-value " + filterType + " - " + filterValue,e);
		}

		return this.getProducts(start, max, store, language, category, queryFilters, model, request, response);
	}

	private ProductList getProducts(final int start, final int max, final String store, final String language, final String category, final List<QueryFilter> filters, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

		try {

			MerchantStore merchantStore = (MerchantStore)request.getAttribute(Constants.MERCHANT_STORE);
			List<BigDecimal> prices = new ArrayList<BigDecimal>();
			String ref = "";

			if(request.getParameter("ref") != null) {
				ref = request.getParameter("ref");
			}
			request.setAttribute("ref", ref);

			Map<String,Language> langs = languageService.getLanguagesMap();

			if(merchantStore!=null) {
				if(!merchantStore.getCode().equals(store)) {
					merchantStore = null; //reset for the current request
				}
			}

			if(merchantStore== null) {
				merchantStore = merchantStoreService.getByCode(store);
			}

			if(merchantStore==null) {
				LOGGER.error("Merchant store is null for code " + store);
				response.sendError(503, "Merchant store is null for code " + store);//TODO localized message
				return null;
			}

			//get the category by code
			Category cat = categoryService.getBySeUrl(merchantStore, category);

			if(cat==null) {
				LOGGER.error("Category " + category + " is null");
				response.sendError(503, "Category is null");//TODO localized message
				return null;
			}

			String lineage = new StringBuilder().append(cat.getLineage()).toString();

			List<Category> categories = categoryService.getListByLineage(store, lineage);

			List<Long> ids = new ArrayList<Long>();
			if(categories!=null && categories.size()>0) {
				for(Category c : categories) {
					if(c.isVisible()) {
						ids.add(c.getId());
					}
				}
			}
			ids.add(cat.getId());

			Language lang = langs.get(language);
			if(lang==null) {
				lang = langs.get(Constants.DEFAULT_LANGUAGE);
			}

			ProductCriteria productCriteria = new ProductCriteria();
			productCriteria.setMaxCount(max);
			productCriteria.setStartIndex(start);
			productCriteria.setCategoryIds(ids);
			productCriteria.setAvailable(true);

			if(filters!=null) {
				for(QueryFilter filter : filters) {
					if(filter.getFilterType().name().equals(QueryFilterType.BRAND.name())) {//the only filter implemented
						productCriteria.setManufacturerId(filter.getFilterId());
					}
				}
			}

			com.salesmanager.core.model.catalog.product.ProductList products = productService.listByStore(merchantStore, lang, productCriteria);

			ReadableProductPopulator populator = new ReadableProductPopulator();
			populator.setPricingService(pricingService);
			populator.setimageUtils(imageUtils);

			ProductList productList = new ProductList();
			for(Product product : products.getProducts()) {

				//create new proxy product
				ReadableProduct  p = populator.populate(product, new ReadableProduct(), merchantStore, lang);
				productList.getProducts().add(p);
				prices.add(p.getPrice());

			}

			/** order products based on the specified order **/
		    Collections.sort(productList.getProducts(), new Comparator<ReadableProduct>() {

				@Override
				public int compare(ReadableProduct o1, ReadableProduct o2) {
					int order1 = o1.getSortOrder();
					int order2 = o2.getSortOrder();
					return order1 - order2;
				}
		    });

			productList.setProductCount(Math.toIntExact(products.getTotalCount()));

			if(CollectionUtils.isNotEmpty(prices)) {
				BigDecimal minPrice = (BigDecimal)Collections.min(prices);
				BigDecimal maxPrice = (BigDecimal)Collections.max(prices);

				if(minPrice !=null && maxPrice !=null) {
					productList.setMinPrice(minPrice);
					productList.setMaxPrice(maxPrice);
				}
			}

			return productList;

		} catch (Exception e) {
			LOGGER.error("Error while getting products",e);
			response.sendError(503, "An error occured while retrieving products " + e.getMessage());
		}

		return null;

	}

}