@Override
  public void removeProductImage(ProductImage productImage) throws ServiceException {

    if (cacheManager.getTreeCache() == null) {
      throw new ServiceException(
          "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()");
    }

    try {

      StringBuilder nodePath = new StringBuilder();
      nodePath
          .append(productImage.getProduct().getMerchantStore().getCode())
          .append(Constants.SLASH)
          .append(productImage.getProduct().getSku());

      Node<String, Object> productNode = this.getNode(nodePath.toString());
      productNode.remove(productImage.getProductImage());

    } catch (Exception e) {
      throw new ServiceException(e);
    } finally {

    }
  }
  /** Requires to stop the engine when image servlet un-deploys */
  public void stopFileManager() {

    try {
      cacheManager.getManager().stop();
      LOGGER.info("Stopping CMS");
    } catch (Exception e) {
      LOGGER.error("Error while stopping CmsImageFileManager", e);
    }
  }
  @SuppressWarnings("unchecked")
  private Node<String, Object> getNode(final String node) {
    LOGGER.debug("Fetching node for store {} from Infinispan", node);
    final StringBuilder merchantPath = new StringBuilder();
    merchantPath.append(getRootName()).append(node);

    Fqn contentFilesFqn = Fqn.fromString(merchantPath.toString());

    Node<String, Object> nd = cacheManager.getTreeCache().getRoot().getChild(contentFilesFqn);

    if (nd == null) {

      cacheManager.getTreeCache().getRoot().addChild(contentFilesFqn);
      nd = cacheManager.getTreeCache().getRoot().getChild(contentFilesFqn);
    }

    return nd;
  }
  @SuppressWarnings("unchecked")
  @Override
  public void removeImages(final String merchantStoreCode) throws ServiceException {
    if (cacheManager.getTreeCache() == null) {
      throw new ServiceException(
          "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()");
    }

    try {

      final StringBuilder merchantPath = new StringBuilder();
      merchantPath.append(getRootName()).append(merchantStoreCode);
      cacheManager.getTreeCache().getRoot().remove(merchantPath.toString());

    } catch (Exception e) {
      throw new ServiceException(e);
    } finally {

    }
  }
  @Override
  public List<OutputContentFile> getImages(
      final String merchantStoreCode, FileContentType imageContentType) throws ServiceException {
    if (cacheManager.getTreeCache() == null) {
      throw new ServiceException(
          "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()");
    }
    List<OutputContentFile> images = new ArrayList<OutputContentFile>();
    FileNameMap fileNameMap = URLConnection.getFileNameMap();

    try {

      StringBuilder nodePath = new StringBuilder();
      nodePath.append(merchantStoreCode);

      Node<String, Object> merchantNode = this.getNode(nodePath.toString());

      Set<Node<String, Object>> childs = merchantNode.getChildren();

      Iterator<Node<String, Object>> iterator = childs.iterator();
      // TODO image sizes
      while (iterator.hasNext()) {

        Node<String, Object> node = iterator.next();

        for (String key : node.getKeys()) {

          byte[] imageBytes = (byte[]) merchantNode.get(key);

          OutputContentFile contentImage = new OutputContentFile();

          InputStream input = new ByteArrayInputStream(imageBytes);
          ByteArrayOutputStream output = new ByteArrayOutputStream();
          IOUtils.copy(input, output);

          String contentType = fileNameMap.getContentTypeFor(key);

          contentImage.setFile(output);
          contentImage.setMimeType(contentType);
          contentImage.setFileName(key);

          images.add(contentImage);
        }
      }

    } catch (Exception e) {
      throw new ServiceException(e);
    } finally {

    }

    return images;
  }
  private OutputContentFile getProductImage(
      String merchantStoreCode, String productCode, String imageName, String size)
      throws ServiceException {

    if (cacheManager.getTreeCache() == null) {
      throw new ServiceException(
          "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()");
    }
    InputStream input = null;
    OutputContentFile contentImage = new OutputContentFile();
    try {

      FileNameMap fileNameMap = URLConnection.getFileNameMap();

      // SMALL by default
      StringBuilder nodePath = new StringBuilder();
      nodePath
          .append(merchantStoreCode)
          .append(Constants.SLASH)
          .append(productCode)
          .append(Constants.SLASH)
          .append(size);

      Node<String, Object> productNode = this.getNode(nodePath.toString());

      byte[] imageBytes = (byte[]) productNode.get(imageName);

      input = new ByteArrayInputStream(imageBytes);
      ByteArrayOutputStream output = new ByteArrayOutputStream();
      IOUtils.copy(input, output);

      String contentType = fileNameMap.getContentTypeFor(imageName);

      contentImage.setFile(output);
      contentImage.setMimeType(contentType);
      contentImage.setFileName(imageName);

    } catch (Exception e) {
      throw new ServiceException(e);
    } finally {
      if (input != null) {
        try {
          input.close();
        } catch (Exception ignore) {
        }
      }
    }

    return contentImage;
  }
  @Override
  public List<OutputContentFile> getImages(Product product) throws ServiceException {

    if (cacheManager.getTreeCache() == null) {
      throw new ServiceException(
          "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()");
    }

    List<OutputContentFile> images = new ArrayList<OutputContentFile>();

    try {

      FileNameMap fileNameMap = URLConnection.getFileNameMap();
      StringBuilder nodePath = new StringBuilder();
      nodePath.append(product.getMerchantStore().getCode());

      Node<String, Object> merchantNode = this.getNode(nodePath.toString());

      if (merchantNode == null) {
        return null;
      }

      for (String key : merchantNode.getKeys()) {

        byte[] imageBytes = (byte[]) merchantNode.get(key);

        OutputContentFile contentImage = new OutputContentFile();

        InputStream input = new ByteArrayInputStream(imageBytes);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        IOUtils.copy(input, output);

        String contentType = fileNameMap.getContentTypeFor(key);

        contentImage.setFile(output);
        contentImage.setMimeType(contentType);
        contentImage.setFileName(key);

        images.add(contentImage);
      }

    } catch (Exception e) {
      throw new ServiceException(e);
    } finally {

    }

    return images;
  }
  /**
   * root -productFiles -merchant-id PRODUCT-ID(key) -> CacheAttribute(value) - image 1 - image 2 -
   * image 3
   */
  @Override
  public void addProductImage(ProductImage productImage, ImageContentFile contentImage)
      throws ServiceException {

    if (cacheManager.getTreeCache() == null) {
      throw new ServiceException(
          "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()");
    }

    try {

      // node
      StringBuilder nodePath = new StringBuilder();
      nodePath
          .append(productImage.getProduct().getMerchantStore().getCode())
          .append(Constants.SLASH)
          .append(productImage.getProduct().getSku())
          .append(Constants.SLASH);

      if (contentImage.getFileContentType().name().equals(FileContentType.PRODUCT.name())) {
        nodePath.append(SMALL);
      } else if (contentImage
          .getFileContentType()
          .name()
          .equals(FileContentType.PRODUCTLG.name())) {
        nodePath.append(LARGE);
      }

      Node<String, Object> productNode = this.getNode(nodePath.toString());

      InputStream isFile = contentImage.getFile();

      ByteArrayOutputStream output = new ByteArrayOutputStream();
      IOUtils.copy(isFile, output);

      // object for a given product containing all images
      productNode.put(contentImage.getFileName(), output.toByteArray());

    } catch (Exception e) {

      throw new ServiceException(e);
    }
  }