/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* This file is part of CATS.
*
* CATS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CATS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CATS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.comcast.cats.service.util;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.comcast.cats.info.DiskSpaceUsage;
import com.comcast.cats.info.VideoRecorderServiceConstants;
import com.comcast.cats.info.VideoRecordingOptions;
/**
* Common utility methods used in video recording.
*
* @author SSugun00c
*
*/
public final class VideoRecorderUtil
{
/**
* Regular expression for IP address.
*/
private static final String IP_ADDR_REGEX = "^(([0-9]|[1-9][0-9]"
+ "|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|"
+ "[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
/**
* Regular expression for positive and valid timeout.
*/
private static final String NUMBER_REGEX = "^[0-9]+$";
/**
* Regular expression for STB mac address.
*/
private static final String MAC_ADDR_REGEX = "^([0-9a-fA-F][0-9a-fA-F]:){5}([0-9a-fA-F][0-9a-fA-F])$";
/**
* Please note ':' is an illegal character in Windows file name.
*/
private static final String TIME_FORMAT = "HH-mm-ss-zzz";
private static final String MEDIA_URL_PREFIX = "rtsp://";
private static final String MEDIA_URL_SUFFIX = "/axis-media/media.amp?videocodec=h264&camera=";
private static final Logger LOGGER = LoggerFactory.getLogger( VideoRecorderUtil.class );
private VideoRecorderUtil()
{
// TODO Auto-generated constructor stub
}
public static boolean isValidIp( final String ip )
{
boolean retVal = false;
if ( null != ip && !ip.isEmpty() )
{
retVal = Pattern.compile( IP_ADDR_REGEX ).matcher( ip ).matches();
}
return retVal;
}
public static boolean isValidNumber( final String input )
{
boolean retVal = false;
if ( null != input && !input.isEmpty() )
{
retVal = Pattern.compile( NUMBER_REGEX ).matcher( input ).matches();
}
return retVal;
}
/**
* check whether valid macId.
*
* @param macId
* macID of the STB.
* @return boolean status
*/
public static boolean isValidMacId( final String macId )
{
boolean retVal = false;
if ( null != macId && !macId.isEmpty() )
{
retVal = Pattern.compile( MAC_ADDR_REGEX ).matcher( macId ).matches();
}
return retVal;
}
/**
* "C:" or "c:" or "D:" or "d:" for windows "/volume" for Linux.
*
* @param partition
* @return
*/
public static DiskSpaceUsage getDiskSpaceUsage( final File partition )
{
DiskSpaceUsage diskSpaceUsage = new DiskSpaceUsage( partition );
return diskSpaceUsage;
}
/**
*
* @return
*/
public static List< DiskSpaceUsage > getDiskSpaceUsage()
{
File[] roots = File.listRoots();
List< DiskSpaceUsage > diskSpaceUsageList = new ArrayList< DiskSpaceUsage >();
for ( File file : roots )
{
diskSpaceUsageList.add( new DiskSpaceUsage( file ) );
}
return diskSpaceUsageList;
}
public static String getMrl( String macId, String videoServerIp, Integer port )
{
String mediaUrl = MEDIA_URL_PREFIX + videoServerIp + MEDIA_URL_SUFFIX + port;
LOGGER.info( "Media Resource Locator for [" + macId + "][" + videoServerIp + "][" + port + "] is [" + mediaUrl
+ "]." );
return mediaUrl;
}
private static synchronized File getTargetFile( String macId, String videoServerIp, Integer port, String alias,
int fileCount )
{
File targetFile = null;
Calendar calendar = Calendar.getInstance();
Date now = new Date();
calendar.setTime( now );
File baseDirectory = null;
if ( null != macId )
{
alias = validateAndFixAlias( alias );
macId = macId.replaceAll( ":", VideoRecorderServiceConstants.DEFAULT_FILE_NAME_SEPERATOR );
baseDirectory = new File(
System.getProperty( VideoRecorderServiceConstants.SYSTEM_PROPERTY_CATS_PVR_FILE_SERVER_BASE_PATH ),
( calendar.get( Calendar.YEAR ) + System.getProperty( "file.separator" )
+ ( calendar.get( Calendar.MONTH ) + 1 ) + System.getProperty( "file.separator" )
+ calendar.get( Calendar.DAY_OF_MONTH ) + System.getProperty( "file.separator" ) + macId ) );
baseDirectory.mkdirs();
// If alias is not there, fileCount is also ignored
if ( ( null == alias ) || ( alias.isEmpty() ) )
{
targetFile = new File( baseDirectory.getAbsolutePath() + System.getProperty( "file.separator" )
+ new SimpleDateFormat( TIME_FORMAT ).format( now )
+ VideoRecordingOptions.DEFAULT_FILE_EXTENSION );
}
else
{
targetFile = new File( baseDirectory.getAbsolutePath() + System.getProperty( "file.separator" ) + alias
+ VideoRecorderServiceConstants.DEFAULT_FILE_NAME_SEPERATOR
+ new SimpleDateFormat( TIME_FORMAT ).format( now )
+ VideoRecorderServiceConstants.DEFAULT_FILE_NAME_SEPERATOR + roundOffFileCount( fileCount )
+ VideoRecordingOptions.DEFAULT_FILE_EXTENSION );
}
}
if ( ( null != targetFile ) && ( targetFile.isFile() ) && ( targetFile.exists() ) )
{
LOGGER.info( "targetFile created [" + targetFile + "]" );
}
return targetFile;
}
public static synchronized File getSubsequentFile( String initialFilePath, int fileCount )
{
String subsequentFilePath = null;
String folderPath = VideoRecorderUtil.getFolderPathFromFilePath( initialFilePath );
String initialFileName = VideoRecorderUtil.getFilePathFromFilePath( initialFilePath );
String newFileName = initialFileName.substring( 0, initialFileName.lastIndexOf( "-" ) + 1 );
newFileName = newFileName + roundOffFileCount( fileCount ) + VideoRecordingOptions.DEFAULT_FILE_EXTENSION;
subsequentFilePath = folderPath + System.getProperty( "file.separator" ) + newFileName;
File targetFile = new File( subsequentFilePath );
return targetFile;
}
private static String roundOffFileCount( int fileCount )
{
String fileCountStr = String.valueOf( fileCount );
if ( fileCountStr.length() == 1 )
{
fileCountStr = "0" + fileCountStr;
}
return fileCountStr;
}
public static synchronized String getHttpPath( String absoluteFilePath )
{
String fileBasePath = System
.getProperty( VideoRecorderServiceConstants.SYSTEM_PROPERTY_CATS_PVR_FILE_SERVER_BASE_PATH );
String httpPath = System.getProperty(
VideoRecorderServiceConstants.SYSTEM_PROPERTY_CATS_PVR_HTTP_SERVER_BASE_PATH ).trim()
+ absoluteFilePath.substring( absoluteFilePath.indexOf( fileBasePath ) + fileBasePath.length(),
absoluteFilePath.length() );
httpPath = httpPath.replace( '\\', '/' );
LOGGER.trace( "HttpPath from [" + absoluteFilePath + "] is [" + httpPath + "]" );
return httpPath;
}
public static synchronized String getFilePath( String macId, String videoServerIp, Integer port, String alias,
int fileCount )
{
String absoluteFilePath = getTargetFile( macId, videoServerIp, port, alias, fileCount ).getAbsolutePath()
.trim();
LOGGER.info( "filePath for [" + macId + "][" + videoServerIp + "][" + port + "] is [" + absoluteFilePath + "]" );
return absoluteFilePath;
}
/**
* Truncate hour to the next hour.
*
* @param now
* @return
*/
public static Date getScheduledStartTime( Date now )
{
Calendar calendar = Calendar.getInstance();
calendar.setTime( DateUtils.truncate( now, Calendar.HOUR_OF_DAY ) );
calendar.add( Calendar.HOUR_OF_DAY, 1 );
Date scheduledStartTime = calendar.getTime();
LOGGER.info( "Calculated scheduledStartTime [" + scheduledStartTime + "]" );
return scheduledStartTime;
}
/**
* Return file size in bytes.
*
* @param filePath
* @return
*/
public static synchronized double getFileSize( String filePath )
{
double sizeInBytes = 0L;
File file = new File( filePath );
if ( !file.exists() || !file.isFile() )
{
sizeInBytes = -1;
}
else
{
sizeInBytes = file.length();
}
return sizeInBytes;
}
/**
* Return folder size in bytes.
*
* @param folder
* @return
*/
public static double getFolderSize( File folder )
{
double foldersize = 0;
File[] filelist = folder.listFiles();
if ( null != filelist )
{
for ( int i = 0; i < filelist.length; i++ )
{
if ( filelist[ i ].isDirectory() )
{
foldersize += getFolderSize( filelist[ i ] );
}
else
{
foldersize += filelist[ i ].length();
}
}
}
return foldersize;
}
/**
* Checks if the file can be opened in s write mode.
*
* Tested on RHEL 6 and Windows.
*
* @param filePath
* @return
*/
public static boolean isPlayable( String filePath )
{
boolean isPlayable = false;
String os = System.getProperty( "os.name" ).toLowerCase();
if ( ( os.indexOf( "nix" ) >= 0 ) || ( os.indexOf( "nux" ) >= 0 ) || ( os.indexOf( "aix" ) > 0 ) )
{
isPlayable = isPlayableInLinux( filePath );
}
else
// ( ( os.indexOf( "win" ) >= 0 ) || ( os.indexOf( "mac" ) >= 0 ) || (
// os.indexOf( "sunos" ) >= 0 ) )
{
try
{
File file = new File( filePath );
if ( file.isFile() )
{
// Will always return true in Linux as Linux allows multiple
// process to access file at the same time.
FileUtils.touch( file );
isPlayable = true;
}
}
catch ( IOException e )
{
isPlayable = false;
}
}
return isPlayable;
}
private static boolean isPlayableInLinux( String filePath )
{
boolean playableInLinux = false;
/*
* InputStream inputStream = null; InputStreamReader inputStreamReader =
* null; BufferedReader bufferedReader = null;
*
* try { // lsof (list open files) utility String command = "lsof " +
* filePath;
*
* LOGGER.trace( "[LSOF] [" + command + "]" );
*
* Process process = Runtime.getRuntime().exec( command );
*
* inputStream = process.getInputStream();
*
* StringBuilder result = new StringBuilder();
*
* inputStreamReader = new InputStreamReader( inputStream,
* VideoRecorderServiceConstants.UTF ); bufferedReader = new
* BufferedReader( inputStreamReader );
*
* String data = null;
*
* while ( ( data = bufferedReader.readLine() ) != null ) {
* result.append( data ); }
*
* if ( result.toString().isEmpty() ) { playableInLinux = true; } else {
* LOGGER.trace( "[FILE IN USE][" + filePath + "] by [" +
* result.toString() + "]" ); playableInLinux = false; }
*
* } catch ( IOException e ) { playableInLinux = false; }
*
* cleanUp( bufferedReader, inputStreamReader, inputStream );
*/
return playableInLinux;
}
/*
* private static void cleanUp( BufferedReader bufferedReader,
* InputStreamReader inputStreamReader, InputStream inputStream ) { if (
* bufferedReader != null ) { try { bufferedReader.close(); } catch (
* IOException e ) { LOGGER.error(
* "Exception caught trying to close bufferedReader: " + e.getMessage() ); }
* } if ( inputStreamReader != null ) { try { inputStreamReader.close(); }
* catch ( IOException e ) { LOGGER.error(
* "Exception caught trying to close inputStreamReader: " + e.getMessage()
* ); } } if ( inputStream != null ) { try { inputStream.close(); } catch (
* IOException e ) { LOGGER.error(
* "Exception caught trying to close inputStream: " + e.getMessage() ); } }
* }
*/
public static boolean isExists( String filePath )
{
boolean exists = false;
File file = new File( filePath );
if ( file.exists() )
{
exists = true;
}
return exists;
}
public static String validateAndFixAlias( String alias )
{
if ( ( null != alias ) && !( alias.isEmpty() ) )
{
alias = alias.trim();
alias = alias.replaceAll( "[^\\dA-Za-z ]", VideoRecorderServiceConstants.DEFAULT_FILE_NAME_SEPERATOR )
.replaceAll( "\\s+", VideoRecorderServiceConstants.DEFAULT_FILE_NAME_SEPERATOR );
}
return alias;
}
public static String getFolderPathFromFilePath( String filePath )
{
if ( ( null != filePath ) && !( filePath.isEmpty() ) )
{
filePath = filePath.trim();
filePath = filePath.substring( 0, filePath.lastIndexOf( System.getProperty( "file.separator" ) ) );
}
return filePath;
}
public static String getFilePathFromFilePath( String filePath )
{
String fileName = null;
if ( ( null != filePath ) && !( filePath.isEmpty() ) )
{
filePath = filePath.trim();
fileName = filePath.substring( filePath.lastIndexOf( System.getProperty( "file.separator" ) ) + 1,
filePath.length() );
}
return fileName;
}
public static String listVlcProcess()
{
String command = null;
String os = System.getProperty( "os.name" ).toLowerCase();
if ( os.indexOf( "win" ) >= 0 )
{
command = "TASKLIST /FI \"IMAGENAME eq vlc.exe\"";
}
else
{
command = "ps -ef | grep vlc | grep -v grep | awk '{print $2}'";
}
// FIXME
return command;// execcuteCommand( command );
}
// FIXME
/*
* public static String execcuteCommand( String command ) { StringBuilder
* result = new StringBuilder();
*
* InputStream inputStream = null; InputStreamReader inputStreamReader =
* null; BufferedReader bufferedReader = null;
*
* try { LOGGER.trace( "[COMMAND] [" + command + "]" );
*
* Process process = Runtime.getRuntime().exec( command );
*
* inputStream = process.getInputStream();
*
* inputStreamReader = new InputStreamReader( inputStream,
* VideoRecorderServiceConstants.UTF ); bufferedReader = new BufferedReader(
* inputStreamReader );
*
* String data = null;
*
* while ( ( data = bufferedReader.readLine() ) != null ) { result.append(
* data ); result.append( "\n" ); }
*
* } catch ( IOException e ) { LOGGER.trace( "[COMMAND] IOException [" +
* e.getMessage() + "]" ); }
*
* cleanUp( bufferedReader, inputStreamReader, inputStream );
*
* return result.toString(); }
*/
}