/**
*
*/
package com.salesmanager.core.business.modules.cms.content.local;
import java.io.IOException;
import java.net.URLConnection;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.salesmanager.core.business.constants.Constants;
import com.salesmanager.core.business.exception.ServiceException;
import com.salesmanager.core.business.modules.cms.content.FileGet;
import com.salesmanager.core.business.modules.cms.content.FilePut;
import com.salesmanager.core.business.modules.cms.content.FileRemove;
import com.salesmanager.core.business.modules.cms.impl.LocalCacheManagerImpl;
import com.salesmanager.core.model.content.FileContentType;
import com.salesmanager.core.model.content.InputContentFile;
import com.salesmanager.core.model.content.OutputContentFile;
/**
* Manages
* - Images
* - Files (js, pdf, css...) on a local web server
* @author Carl Samson
* @since 1.0.3
*
*/
public class CmsStaticContentFileManagerImpl implements FilePut,FileGet,FileRemove
{
private static final Logger LOGGER = LoggerFactory.getLogger( CmsStaticContentFileManagerImpl.class );
private static CmsStaticContentFileManagerImpl fileManager = null;
private static final String ROOT_NAME="static";
private static final String ROOT_CONTAINER = "files";
private String rootName = ROOT_NAME;
private LocalCacheManagerImpl cacheManager;
public static CmsStaticContentFileManagerImpl getInstance()
{
if ( fileManager == null )
{
fileManager = new CmsStaticContentFileManagerImpl();
}
return fileManager;
}
/**
* <p>Method to add static content data for given merchant.Static content data can be of following type
* <pre>
* 1. CSS and JS files
* 2. Digital Data like audio or video
* </pre>
* </p>
* <p>
* Merchant store code will be used to create cache node where merchant data will be stored,input data will
* contain name, file as well type of data being stored.
* @see FileContentType
* </p>
*
* @param merchantStoreCode merchant store for whom data is being stored
* @param inputStaticContentData data object being stored
* @throws ServiceException
*
*/
@Override
public void addFile( final String merchantStoreCode, final InputContentFile inputStaticContentData )
throws ServiceException
{
/* if ( cacheManager.getTreeCache() == null )
{
LOGGER.error( "Unable to find cacheManager.getTreeCache() in Infinispan.." );
throw new ServiceException( "CmsStaticContentFileManagerInfinispanImpl has a null cacheManager.getTreeCache()" );
}*/
try
{
//base path
String rootPath = this.buildRootPath();
Path confDir = Paths.get(rootPath);
this.createDirectoryIfNorExist(confDir);
//node path
StringBuilder nodePath = new StringBuilder();
nodePath
.append(rootPath)
.append(merchantStoreCode);
Path merchantPath = Paths.get(nodePath.toString());
this.createDirectoryIfNorExist(merchantPath);
//file path
nodePath.append(Constants.SLASH).append( inputStaticContentData.getFileContentType()).append(Constants.SLASH);
Path dirPath = Paths.get(nodePath.toString());
this.createDirectoryIfNorExist(dirPath);
//file creation
nodePath.append(inputStaticContentData.getFileName());
Path path = Paths.get(nodePath.toString());
//file creation
//nodePath.append(Constants.SLASH).append(contentImage.getFileName());
//Path path = Paths.get(nodePath.toString());
Files.copy(inputStaticContentData.getFile(), path, StandardCopyOption.REPLACE_EXISTING);
//String nodePath = this.getNodePath(merchantStoreCode, inputStaticContentData.getFileContentType());
//final Node<String, Object> merchantNode = this.getNode(nodePath);
//merchantNode.put(inputStaticContentData.getFileName(), IOUtils.toByteArray( inputStaticContentData.getFile() ));
LOGGER.info( "Content data added successfully." );
}
catch ( final Exception e )
{
LOGGER.error( "Error while saving static content data", e );
throw new ServiceException( e );
}
}
/**
* <p>
* Method to add files for given store.Files will be stored in Infinispan and will be retrieved based on
* the storeID. Following steps will be performed to store static content files
* </p>
* <li>Merchant Node will be retrieved from the cacheTree if it exists else new node will be created.</li> <li>
* Files will be stored in StaticContentCacheAttribute , which eventually will be stored in Infinispan</li>
*
* @param merchantStoreCode Merchant store for which files are getting stored in Infinispan.
* @param inputStaticContentDataList input static content file list which will get {@link InputContentImage} stored
* @throws ServiceException if content file storing process fail.
* @see InputStaticContentData
* @see StaticContentCacheAttribute
*/
@Override
public void addFiles( final String merchantStoreCode, final List<InputContentFile> inputStaticContentDataList )
throws ServiceException
{
/* if ( cacheManager.getTreeCache() == null )
{
LOGGER.error( "Unable to find cacheManager.getTreeCache() in Infinispan.." );
throw new ServiceException( "CmsStaticContentFileManagerInfinispanImpl has a null cacheManager.getTreeCache()" );
}*/
try
{
//base path
String rootPath = this.buildRootPath();
Path confDir = Paths.get(rootPath);
this.createDirectoryIfNorExist(confDir);
//node path
StringBuilder nodePath = new StringBuilder();
nodePath
.append(rootPath)
.append(merchantStoreCode);
Path merchantPath = Paths.get(nodePath.toString());
this.createDirectoryIfNorExist(merchantPath);
for(final InputContentFile inputStaticContentData:inputStaticContentDataList){
//file path
nodePath.append(Constants.SLASH).append( inputStaticContentData.getFileContentType()).append(Constants.SLASH);
Path dirPath = Paths.get(nodePath.toString());
this.createDirectoryIfNorExist(dirPath);
//file creation
nodePath.append(Constants.SLASH).append(inputStaticContentData.getFileName());
Path path = Paths.get(nodePath.toString());
Files.copy(inputStaticContentData.getFile(), path, StandardCopyOption.REPLACE_EXISTING);
//String nodePath = this.getNodePath(merchantStoreCode, inputStaticContentData.getFileContentType());
//final Node<String, Object> merchantNode = this.getNode(nodePath);
//merchantNode.put(inputStaticContentData.getFileName(), IOUtils.toByteArray( inputStaticContentData.getFile() ));
}
LOGGER.info( "Total {} files added successfully.",inputStaticContentDataList.size() );
}
catch ( final Exception e )
{
LOGGER.error( "Error while saving content image", e );
throw new ServiceException( e );
}
}
/**
* Method to return static data for given Merchant store based on the file name. Content data will be searched
* in underlying Infinispan cache tree and {@link OutputStaticContentData} will be returned on finding an associated
* file. In case of no file, null be returned.
*
* @param store Merchant store
* @param contentFileName name of file being requested
* @return {@link OutputStaticContentData}
* @throws ServiceException
*/
@Override
public OutputContentFile getFile( final String merchantStoreCode, final FileContentType fileContentType, final String contentFileName )
throws ServiceException
{
/* if ( cacheManager.getTreeCache() == null )
{
throw new ServiceException( "CmsStaticContentFileManagerInfinispan has a null cacheManager.getTreeCache()" );
}
OutputContentFile outputStaticContentData=null;
InputStream input = null;
try
{
String nodePath = this.getNodePath(merchantStoreCode, fileContentType);
final Node<String, Object> merchantNode = this.getNode(nodePath);
final byte[] fileBytes= (byte[]) merchantNode.get( contentFileName );
if ( fileBytes == null )
{
LOGGER.warn( "file byte is null, no file found" );
return null;
}
input=new ByteArrayInputStream( fileBytes );
final ByteArrayOutputStream output = new ByteArrayOutputStream();
IOUtils.copy( input, output );
outputStaticContentData=new OutputContentFile();
outputStaticContentData.setFile( output );
outputStaticContentData.setMimeType( URLConnection.getFileNameMap().getContentTypeFor(contentFileName) );
outputStaticContentData.setFileName( contentFileName );
outputStaticContentData.setFileContentType( fileContentType );
}
catch ( final Exception e )
{
LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
throw new ServiceException( e );
}
return outputStaticContentData != null ? outputStaticContentData : null;*/
return null;
}
@Override
public List<OutputContentFile> getFiles(
final String merchantStoreCode, final FileContentType staticContentType) throws ServiceException {
/*
if ( cacheManager.getTreeCache() == null )
{
throw new ServiceException( "CmsStaticContentFileManagerInfinispan has a null cacheManager.getTreeCache()" );
}
List<OutputContentFile> images = new ArrayList<OutputContentFile>();
try
{
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String nodePath = this.getNodePath(merchantStoreCode, staticContentType);
final Node<String, Object> merchantNode = this.getNode(nodePath);
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 ( final Exception e )
{
LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
throw new ServiceException( e );
}
return images;*/
return null;
}
@Override
public void removeFile( final String merchantStoreCode, final FileContentType staticContentType, final String fileName )
throws ServiceException
{
try
{
StringBuilder merchantPath = new StringBuilder();
merchantPath.append(buildRootPath())
.append(Constants.SLASH)
.append(merchantStoreCode)
.append(Constants.SLASH)
.append(staticContentType)
.append(Constants.SLASH)
.append(fileName);
Path path = Paths.get(merchantPath.toString());
Files.deleteIfExists(path);
}
catch ( final Exception e )
{
LOGGER.error( "Error while deleting files for {} merchant ", merchantStoreCode);
throw new ServiceException( e );
}
}
/**
* Removes the data in a given merchant node
*/
@SuppressWarnings("unchecked")
@Override
public void removeFiles( final String merchantStoreCode )
throws ServiceException
{
LOGGER.debug( "Removing all images for {} merchant ",merchantStoreCode);
try
{
StringBuilder merchantPath = new StringBuilder();
merchantPath.append(buildRootPath())
.append(Constants.SLASH)
.append(merchantStoreCode);
Path path = Paths.get(merchantPath.toString());
Files.deleteIfExists(path);
}
catch ( final Exception e )
{
LOGGER.error( "Error while deleting content image for {} merchant ", merchantStoreCode);
throw new ServiceException( e );
}
}
/**
* Queries the CMS to retrieve all static content files. Only the name of the file will be returned to the client
* @param merchantStoreCode
* @return
* @throws ServiceException
*/
@Override
public List<String> getFileNames(final String merchantStoreCode, final FileContentType staticContentType)
throws ServiceException {
try
{
StringBuilder merchantPath = new StringBuilder();
merchantPath.append(buildRootPath())
.append(merchantStoreCode)
.append(Constants.SLASH)
.append(staticContentType);
Path path = Paths.get(merchantPath.toString());
List<String> fileNames = null;
if(Files.exists(path)) {
fileNames = new ArrayList<String>();
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
for (Path dirPath : directoryStream) {
String fileName = dirPath.getFileName().toString();
if(staticContentType.name().equals(FileContentType.IMAGE.name())) {
//File f = new File(fileName);
String mimetype = URLConnection.guessContentTypeFromName(fileName);
//String mimetype= new MimetypesFileTypeMap().getContentType(f);
if(!StringUtils.isBlank(mimetype)) {
String type = mimetype.split("/")[0];
if(type.equals("image")) {
fileNames.add(fileName);
}
}
//fileNames.add(fileName);
} else {
fileNames.add(fileName);
}
}
}
return fileNames;
} catch ( final Exception e ) {
LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
throw new ServiceException( e );
}
}
public void setRootName(String rootName) {
this.rootName = rootName;
}
public String getRootName() {
return rootName;
}
private String buildRootPath() {
return new StringBuilder().append(getRootName()).append(Constants.SLASH).append(ROOT_CONTAINER).append(Constants.SLASH).toString();
}
private void createDirectoryIfNorExist(Path path) throws IOException {
if (Files.notExists(path)) {
Files.createDirectory(path);
}
}
public LocalCacheManagerImpl getCacheManager() {
return cacheManager;
}
public void setCacheManager(LocalCacheManagerImpl cacheManager) {
this.cacheManager = cacheManager;
}
}