/**
* Copyright (C) 2015 Envidatec GmbH <info@envidatec.com>
*
* This file is part of JECommons.
*
* JECommons 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 in version 3.
*
* JECommons 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
* JECommons. If not, see <http://www.gnu.org/licenses/>.
*
* JECommons is part of the OpenJEVis project, further project information are
* published at <http://www.OpenJEVis.org/>.
*/
package org.jevis.commons.driver;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpException;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.jevis.api.JEVisObject;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
/**
*
* @author Broder
*/
public class DataSourceHelper {
public static void test() {
}
static public void doTrustToCertificates() throws Exception {
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
if (!urlHostName.equalsIgnoreCase(session.getPeerHost())) {
System.out.println("Warning: URL host '" + urlHostName + "' is different to SSLSession host '" + session.getPeerHost() + "'.");
}
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
public static List<String> getFTPMatchedFileNames(FTPClient fc, DateTime lastReadout, String filePath) {
filePath = filePath.replace("\\", "/");
String[] pathStream = getPathTokens(filePath);
String startPath = "";
if (filePath.startsWith("/")) {
startPath = "/";
}
List<String> folderPathes = getMatchingPathes(startPath, pathStream, new ArrayList<String>(), fc, lastReadout, new DateTimeFormatterBuilder());
// System.out.println("foldersize,"+folderPathes.size());
List<String> fileNames = new ArrayList<String>();
if (folderPathes.isEmpty()) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Cant find suitable folder on the device");
return fileNames;
}
// String fileName = null;
String fileNameScheme = pathStream[pathStream.length - 1];
String currentfolder = null;
try {
for (String folder : folderPathes) {
// fc.changeWorkingDirectory(folder);
// System.out.println("currentFolder,"+folder);
currentfolder = folder;
// for (FTPFile file : fc.listFiles(folder)) {
// System.out.println(file.getName());
// }
fc.changeWorkingDirectory(folder);
for (FTPFile file : fc.listFiles()) {
// org.apache.log4j.Logger.getLogger(Launcher.class.getName()).log(org.apache.log4j.Level.ALL, "CurrentFileName: " + fileName);
// fileName = removeFoler(fileName, folder);
DateTimeFormatter dateFormat = DateTimeFormat.forPattern("yyyyMMddHHmmss");
String fileName = file.getName();
String timePart = fc.getModificationTime(folder + fileName).split(" ")[1].trim();
DateTime modificationTime = dateFormat.parseDateTime(timePart);
if (modificationTime.isBefore(lastReadout)) {
continue;
}
boolean match = false;
System.out.println(file.getName());
if (DataSourceHelper.containsTokens(fileNameScheme)) {
boolean matchDate = matchDateString(file.getName(), fileNameScheme);
DateTime folderTime = getFileTime(folder + file.getName(), pathStream);
boolean isLater = folderTime.isAfter(lastReadout);
if (matchDate && isLater) {
match = true;
}
} else {
Pattern p = Pattern.compile(fileNameScheme);
Matcher m = p.matcher(file.getName());
match = m.matches();
}
if (match) {
fileNames.add(folder + file.getName());
}
}
}
} catch (IOException ex) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, ex.getMessage());
} catch (Exception ex) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Error while searching a matching file");
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Folder: " + currentfolder);
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "FileName: " + fileNameScheme);
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, ex.getMessage());
}
if (folderPathes.isEmpty()) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Cant find suitable files on the device");
}
// System.out.println("filenamesize"+fileNames.size());
return fileNames;
}
private static DateTime getFileTime(String name, String[] pathStream) {
String compactDateString = getCompactDateString(name, pathStream);
String compactDataFormatString = getCompactDateFormatString(name, pathStream);
DateTimeFormatter dtf = DateTimeFormat.forPattern(compactDataFormatString);
DateTime parseDateTime = dtf.parseDateTime(compactDateString);
return parseDateTime;
}
private static String getCompactDateString(String name, String[] pathStream) {
String[] realTokens = StringUtils.split(name, "/");
String compactDateString = null;
for (int i = 0; i < realTokens.length; i++) {
String currentString = pathStream[i];
if (currentString.contains("${D:")) {
int startindex = currentString.indexOf("${D:");
int endindex = currentString.indexOf("}");
if (compactDateString == null) {
compactDateString = realTokens[i].substring(startindex, endindex - 4);
} else {
compactDateString += " " + realTokens[i].substring(startindex, endindex - 4);
}
}
}
return compactDateString;
}
private static String getCompactDateFormatString(String name, String[] pathStream) {
String[] realTokens = StringUtils.split(name, "/");
String compactDateString = null;
//contains more than one date token?
for (int i = 0; i < realTokens.length; i++) {
String currentString = pathStream[i];
if (currentString.contains("${")) {
int startindex = currentString.indexOf("${");
int endindex = currentString.indexOf("}");
if (compactDateString == null) {
compactDateString = currentString.substring(startindex + 4, endindex);
} else {
compactDateString += " " + currentString.substring(startindex + 4, endindex);
}
}
}
return compactDateString;
}
private static String removeFoler(String fileName, String folder) {
if (fileName.startsWith(folder)) {
return fileName.substring(folder.length(), fileName.length());
}
return fileName;
}
private static boolean matchDateString(String currentFolder, String nextToken) {
String[] substringsBetween = StringUtils.substringsBetween(nextToken, "${D:", "}");
for (int i = 0; i < substringsBetween.length; i++) {
nextToken = nextToken.replace("${D:" + substringsBetween[i] + "}", ".{" + substringsBetween[i].length() + "}");
}
Pattern p = Pattern.compile(nextToken);
Matcher m = p.matcher(currentFolder);
return m.matches();
}
private static List<String> getMatchingPathes(String path, String[] pathStream, ArrayList<String> arrayList, FTPClient fc, DateTime lastReadout, DateTimeFormatterBuilder dtfbuilder) {
int nextTokenPos = getPathTokens(path).length;
if (nextTokenPos == pathStream.length - 1) {
arrayList.add(path);
return arrayList;
}
String nextToken = pathStream[nextTokenPos];
String nextFolder = null;
try {
if (containsDateToken(nextToken)) {
FTPFile[] listDirectories = fc.listFiles(path);
// DateTimeFormatter ftmTemp = getDateFormatter(nextToken);
for (FTPFile folder : listDirectories) {
if (!matchDateString(folder.getName(), nextToken)) {
continue;
}
// System.out.println("listdir," + folder.getName());
// if (containsDate(folder.getName(), ftmTemp)) {
DateTime folderTime = getFolderTime(path + folder.getName() + "/", pathStream);
if (folderTime.isAfter(lastReadout)) {
nextFolder = folder.getName();
// System.out.println("dateFolder," + nextFolder);
getMatchingPathes(path + nextFolder + "/", pathStream, arrayList, fc, lastReadout, dtfbuilder);
}
// }
}
} else {
nextFolder = nextToken;
// System.out.println("normalFolder," + nextFolder);
getMatchingPathes(path + nextFolder + "/", pathStream, arrayList, fc, lastReadout, dtfbuilder);
}
} catch (IOException ex) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, ex.getMessage());
}
return arrayList;
}
private static boolean containsDateToken(String string) {
if (string.contains("${D:")) {
return true;
} else {
return false;
}
}
public static String[] getPathTokens(String filePath) {
// List<String> tokens = new ArrayList<String>();
// filePath.substring("\\$\\{","\\}");
String[] tokens = StringUtils.split(filePath, "/");
// String[] tokens = filePath.trim().split("\\%");
for (int i = 0; i < tokens.length; i++) {
System.out.println(tokens[i]);
}
return tokens;
}
public static String replaceDateFrom(String template, DateTime date) {
DateTimeFormatter dtf = getFromDateFormat(template);
int startindex = template.indexOf("${DF:");
int endindex = template.indexOf("}") + 1;
String first = template.substring(0, startindex);
String last = template.substring(endindex, template.length());
return first + date.toString(dtf) + last;
}
public static String replaceDateUntil(String template, DateTime date) {
DateTimeFormatter dtf = getUntilDateFormat(template);
int startindex = template.indexOf("${DU:");
int endindex = template.indexOf("}") + 1;
String first = template.substring(0, startindex);
String last = template.substring(endindex, template.length());
return first + date.toString(dtf) + last;
}
public static String replaceDateFromUntil(DateTime from, DateTime until, String filePath) {
// String replacedString = null;
while (filePath.indexOf("${DF:") != -1 || filePath.indexOf("${DF:") != -1) {
int fromstartindex = filePath.indexOf("${DF:");
int untilstartindex = filePath.indexOf("${DU:");
if (fromstartindex < untilstartindex) {
filePath = replaceDateFrom(filePath, from);
filePath = replaceDateUntil(filePath, until);
} else {
filePath = replaceDateUntil(filePath, until);
filePath = replaceDateFrom(filePath, from);
}
}
return filePath;
}
private static DateTime getFolderTime(String name, String[] pathStream) {
String compactDateString = getCompactDateString(name, pathStream);
String compactDataFormatString = getCompactDateFormatString(name, pathStream);
DateTimeFormatter dtf = DateTimeFormat.forPattern(compactDataFormatString);
DateTime parseDateTime = dtf.parseDateTime(compactDateString);
if (parseDateTime.year().get() == parseDateTime.year().getMinimumValue()) {
parseDateTime = parseDateTime.year().withMaximumValue();
}
if (parseDateTime.monthOfYear().get() == parseDateTime.monthOfYear().getMinimumValue()) {
parseDateTime = parseDateTime.monthOfYear().withMaximumValue();
}
if (parseDateTime.dayOfMonth().get() == parseDateTime.dayOfMonth().getMinimumValue()) {
parseDateTime = parseDateTime.dayOfMonth().withMaximumValue();
}
if (parseDateTime.hourOfDay().get() == parseDateTime.hourOfDay().getMinimumValue()) {
parseDateTime = parseDateTime.hourOfDay().withMaximumValue();
}
if (parseDateTime.minuteOfHour().get() == parseDateTime.minuteOfHour().getMinimumValue()) {
parseDateTime = parseDateTime.minuteOfHour().withMaximumValue();
}
if (parseDateTime.secondOfMinute().get() == parseDateTime.secondOfMinute().getMinimumValue()) {
parseDateTime = parseDateTime.secondOfMinute().withMaximumValue();
}
if (parseDateTime.millisOfSecond().get() == parseDateTime.millisOfSecond().getMinimumValue()) {
parseDateTime = parseDateTime.millisOfSecond().withMaximumValue();
}
return parseDateTime;
}
public static DateTimeFormatter getFromDateFormat(String stringWithDate) {
int startindex = stringWithDate.indexOf("${DF:");
int endindex = stringWithDate.indexOf("}");
String date = stringWithDate.substring(startindex + 5, endindex);
DateTimeFormatter dtf = DateTimeFormat.forPattern(date);
return dtf;
}
public static DateTimeFormatter getUntilDateFormat(String stringWithDate) {
int startindex = stringWithDate.indexOf("${DU:");
int endindex = stringWithDate.indexOf("}");
String date = stringWithDate.substring(startindex + 5, endindex);
DateTimeFormatter dtf = DateTimeFormat.forPattern(date);
return dtf;
}
public static Boolean containsTokens(String path) {
if (path.contains("${")) {
return true;
} else {
return false;
}
}
public static List<String> getSFTPMatchedFileNames(ChannelSftp _channel, DateTime lastReadout, String filePath) {
filePath = filePath.replace("\\", "/");
String[] pathStream = getPathTokens(filePath);
String startPath = "";
if (filePath.startsWith("/")) {
startPath = "/";
}
List<String> folderPathes = getSFTPMatchingPathes(startPath, pathStream, new ArrayList<String>(), _channel, lastReadout, new DateTimeFormatterBuilder());
// System.out.println("foldersize,"+folderPathes.size());
List<String> fileNames = new ArrayList<String>();
if (folderPathes.isEmpty()) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Cant find suitable folder on the device");
return fileNames;
}
if (folderPathes.isEmpty()) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Cant find suitable folder on the device");
return fileNames;
}
String fileNameScheme = pathStream[pathStream.length - 1];
String currentfolder = null;
try {
for (String folder : folderPathes) {
// fc.changeWorkingDirectory(folder);
// System.out.println("currentFolder,"+folder);
currentfolder = folder;
// for (FTPFile file : fc.listFiles(folder)) {
// System.out.println(file.getName());
// }
// Vector ls = _channel.ls(folder);
for (Object fileName : _channel.ls(folder)) {
LsEntry currentFile = (LsEntry) fileName;
String currentFileName = currentFile.getFilename();
currentFileName = removeFoler(currentFileName, folder);
boolean match = false;
System.out.println(currentFileName);
if (DataSourceHelper.containsTokens(fileNameScheme)) {
boolean matchDate = matchDateString(currentFileName, fileNameScheme);
DateTime folderTime = getFileTime(folder + currentFileName, pathStream);
boolean isLater = folderTime.isAfter(lastReadout);
if (matchDate && isLater) {
match = true;
}
} else {
Pattern p = Pattern.compile(fileNameScheme);
Matcher m = p.matcher(currentFileName);
match = m.matches();
}
if (match) {
fileNames.add(folder + currentFileName);
}
}
}
} catch (Exception ex) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Error while searching a matching file");
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Folder: " + currentfolder);
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "FileName: " + fileNameScheme);
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, ex.getMessage());
}
if (folderPathes.isEmpty()) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Cant find suitable files on the device");
}
// System.out.println("filenamesize"+fileNames.size());
return fileNames;
}
private static List<String> getSFTPMatchingPathes(String path, String[] pathStream, ArrayList<String> arrayList, ChannelSftp fc, DateTime lastReadout, DateTimeFormatterBuilder dtfbuilder) {
int nextTokenPos = getPathTokens(path).length;
if (nextTokenPos == pathStream.length - 1) {
arrayList.add(path);
return arrayList;
}
String nextToken = pathStream[nextTokenPos];
String nextFolder = null;
try {
if (containsDateToken(nextToken)) {
Vector listDirectories = fc.ls(path);
for (Object folder : listDirectories) {
LsEntry currentFolder = (LsEntry) folder;
if (!matchDateString(currentFolder.getFilename(), nextToken)) {
continue;
}
DateTime folderTime = getFolderTime(path + currentFolder.getFilename() + "/", pathStream);
if (folderTime.isAfter(lastReadout)) {
nextFolder = currentFolder.getFilename();
getSFTPMatchingPathes(path + nextFolder + "/", pathStream, arrayList, fc, lastReadout, dtfbuilder);
}
// }
}
} else {
nextFolder = nextToken;
getSFTPMatchingPathes(path + nextFolder + "/", pathStream, arrayList, fc, lastReadout, dtfbuilder);
}
} catch (SftpException ex) {
org.apache.log4j.Logger.getLogger(DataSourceHelper.class).log(org.apache.log4j.Level.ERROR, "Cant find suitable files on the device");
}
return arrayList;
}
public static void setLastReadout(JEVisObject channel, Object latestDatapoint) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}