0

Init project

This commit is contained in:
2015-12-01 22:39:00 +00:00
commit 0478fac0da
35 changed files with 1239 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
package kinosearch.core;
public class Kino {
private String name;
private String url;
public Kino(String name, String url) {
this.name = name;
this.url = url;
}
public String getName() {
return name;
}
public String getUrl() {
return url;
}
}

View File

@@ -0,0 +1,60 @@
package kinosearch.core;
import kinosearch.core.browser.Browser;
import kinosearch.core.browser.SimpleBrowser;
import kinosearch.core.warez.Hdrezka;
import kinosearch.core.warez.KinoWarez;
import kinosearch.core.warez.Onlinelife;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashSet;
import java.util.Set;
public class Tools {
public static final String VERSION = "2.0.1-SNAPSHOT";
private static Set<KinoWarez> kinoWarezSet;
public static Browser createBrowser() {
return new SimpleBrowser();
}
public static String SafeUrlEncode(String string, String encode) {
try {
return URLEncoder.encode(string, encode);
} catch (UnsupportedEncodingException e) {
return string;
}
}
public static String getFileFromURI(String uri, String context) {
if (context == null || context.isEmpty()) {
return uri;
} else {
String[] strArr = uri.split(context);
if (strArr.length < 2) {
return uri;
} else {
return strArr[1];
}
}
}
public static Set<KinoWarez> getKinoWarezSet() {
if (kinoWarezSet == null) {
kinoWarezSet = new HashSet<>();
kinoWarezSet.add(new Onlinelife());
kinoWarezSet.add(new Hdrezka());
}
return kinoWarezSet;
}
public static void SafeSleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException ignore) {
}
}
}

View File

@@ -0,0 +1,8 @@
package kinosearch.core.browser;
public interface Browser {
Browser setHeader(String name, String value);
String get(String url);
String post(String url, String data);
void setEncoding(String encoding);
}

View File

@@ -0,0 +1,99 @@
package kinosearch.core.browser;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class SimpleBrowser implements Browser {
private Map<String, String> headers = new HashMap<>();
private String encoding = "UTF-8";
@Override
public Browser setHeader(String name, String value) {
headers.put(name, value);
return this;
}
@Override
public String get(String url) {
String result = "";
try {
HttpURLConnection connection = create_connection(url);
connection.setRequestMethod("GET");
if (connection.getResponseCode() != 200) {
return result;
}
result = readOutput(connection.getInputStream());
connection.disconnect();
} catch (IOException ignore) {
// ignore
}
return result;
}
@Override
public String post(String url, String data) {
String result = "";
try {
HttpURLConnection connection = create_connection(url);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", String.valueOf(data.length()));
connection.setDoOutput(true);
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
dos.writeBytes(data);
dos.flush();
dos.close();
if (connection.getResponseCode() != 200) {
return "";
}
result = readOutput(connection.getInputStream());
connection.disconnect();
} catch (IOException ignore) {
// ignore
}
return result;
}
@Override
public void setEncoding(String encoding) {
this.encoding = encoding;
}
private HttpURLConnection create_connection(String strUrl) throws IOException {
URL url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(false); //TODO а надо ли?
connection.setRequestProperty("Connection", "close");
connection.setRequestProperty("Accept-Encoding", "deflate");
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; Android 4.2.2; GT-I9505 Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36");
for (Map.Entry<String, String> entry : headers.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
return connection;
}
private String readOutput(InputStream in) throws IOException {
StringBuilder sb = new StringBuilder();
String str;
BufferedReader br = new BufferedReader(new InputStreamReader(in, encoding));
while ((str = br.readLine()) != null) {
sb.append(str).append('\n');
}
br.close();
return sb.toString();
}
}

View File

@@ -0,0 +1,42 @@
package kinosearch.core.warez;
import kinosearch.core.Kino;
import kinosearch.core.Tools;
import kinosearch.core.browser.Browser;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.List;
public class Hdrezka implements KinoWarez {
private static final String DOMAIN = "http://hdrezka.me";
@Override
public void search(String nameKino, List<Kino> outList) {
Browser browser = Tools.createBrowser();
browser.setEncoding("UTF-8");
String html = browser.get(DOMAIN + "/?do=search&subaction=search&q=" + Tools.SafeUrlEncode(nameKino, "UTF-8"));
if (html.isEmpty()) return;
Document document = Jsoup.parse(html);
Elements elements = document.getElementsByClass("b-content__inline_item-cover");
for (Element element : elements) {
Element childElement = element.child(0);
String url = childElement.attr("href");
childElement = childElement.child(0);
String name = childElement.attr("alt");
outList.add(new Kino("[HDREZKA] " + name, url));
}
}
@Override
public void player(String page) {
//TODO ignore
}
}

View File

@@ -0,0 +1,10 @@
package kinosearch.core.warez;
import kinosearch.core.Kino;
import java.util.List;
public interface KinoWarez {
void search(String nameKino, List<Kino> outList);
void player(String page);
}

View File

@@ -0,0 +1,45 @@
package kinosearch.core.warez;
import kinosearch.core.browser.Browser;
import kinosearch.core.Kino;
import kinosearch.core.Tools;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.List;
public class Onlinelife implements KinoWarez {
private static final String DOMAIN = "http://www.online-life.cc";
@Override
public void search(String nameKino, List<Kino> outList) {
Browser browser = Tools.createBrowser();
browser.setEncoding("windows-1251");
String postData = "do=search&subaction=search&mode=simple&story=" + Tools.SafeUrlEncode(nameKino, "windows-1251");
String html = browser.post(DOMAIN + "/?do=search", postData);
if (html.isEmpty()) return;
Document document = Jsoup.parse(html);
// ничего не найдено?
Elements elements = document.getElementsByClass("info");
if (elements.size() > 0) return;
elements = document.getElementsByClass("custom-poster");
for (Element element : elements) {
Element childElement = element.child(0);
String name = childElement.text();
String url = childElement.attr("href");
outList.add(new Kino("[OnlineLife] "+name, url));
}
}
@Override
public void player(String page) {
//TODO some code...
}
}

View File

@@ -0,0 +1,29 @@
package kinosearch.webapp;
import kinosearch.webapp.template.FreemakerProcessor;
import kinosearch.webapp.template.TemplateProcessor;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class WebApp implements ServletContextListener {
private static boolean _init = false;
private static TemplateProcessor templateProcessor;
public static TemplateProcessor getTemplateProcessor() {
return (_init ? templateProcessor : null);
}
@Override
public void contextInitialized(ServletContextEvent sce) {
templateProcessor = new FreemakerProcessor();
_init = true;
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
_init = false;
}
}

View File

@@ -0,0 +1,74 @@
package kinosearch.webapp.servlets;
import kinosearch.core.Kino;
import kinosearch.core.Tools;
import kinosearch.webapp.WebApp;
import kinosearch.webapp.template.TemplateProcessor;
import kinosearch.core.warez.KinoWarez;
import kinosearch.core.warez.Onlinelife;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 3242992839104315456L;
private TemplateProcessor template;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
template = WebApp.getTemplateProcessor();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, Object> model = new HashMap<>();
model.put(".templatedir", getServletContext().getRealPath("WEB-INF"));
model.put("basedir", getServletContext().getContextPath());
model.put("version", Tools.VERSION);
model.put("rutext", "Поиск кино по пиратским кинотеатрам");
if (request.getParameter("search") != null && !request.getParameter("search").trim().isEmpty()) {
search(request.getParameter("search"), model);
}
response.setCharacterEncoding("UTF-8");
try {
template.process("index.html", model, response.getWriter());
} catch (IOException e) {
log("Error process template", e);
response.sendError(500);
}
}
private void search(String search, Map<String, Object> model) {
List<Kino> list = Collections.synchronizedList(new LinkedList<>());
Set<KinoWarez> kinoWarezSet = Tools.getKinoWarezSet();
ThreadGroup threadGroup = new ThreadGroup("");
for (KinoWarez kinoWarez : kinoWarezSet) { //TODO на будущее надо ограничить количество одновременных потоков
new Thread(threadGroup, () -> {
kinoWarez.search(search, list);
}).start();
}
// ждем максимум 15 секунд
//FIXME надо бы убивать потоки, которые не успели найти контент
for (int i = 0; i < 15 && threadGroup.activeCount() > 0; i++) {
// System.err.println("wait("+(i+1)+")..."); //DEBUG
Tools.SafeSleep(1000);
}
model.put("searchtext", search);
model.put("resultsearch", list);
}
@Override
public void log(String message, Throwable t) {
super.log(message, t);
}
}

View File

@@ -0,0 +1,58 @@
package kinosearch.webapp.servlets;
import kinosearch.core.Tools;
import kinosearch.webapp.WebApp;
import kinosearch.webapp.template.TemplateProcessor;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class TemplateServlet extends HttpServlet {
private static final long serialVersionUID = 5334243553000329769L;
private TemplateProcessor template;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
template = WebApp.getTemplateProcessor();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//TODO оптимизировать
String fileName = Tools.getFileFromURI(req.getRequestURI(), req.getContextPath());
Path path = Paths.get(getServletContext().getRealPath("WEB-INF/simple_template" + fileName));
if (Files.exists(path)) {
Map<String, Object> model = new HashMap<>();
model.put(".templatedir", getServletContext().getRealPath("WEB-INF"));
model.put("basedir", getServletContext().getContextPath());
model.put("version", Tools.VERSION);
model.put("rutext", "Поиск кино по пиратским кинотеатрам");
resp.setCharacterEncoding("UTF-8");
try {
template.process("simple_template" + fileName, model, resp.getWriter());
} catch (IOException e) {
log("Error process template", e);
resp.sendError(500);
}
} else {
resp.setContentType("text/plain"); //TODO доработать
resp.getWriter().write("not support");
}
}
@Override
public void log(String message, Throwable t) {
super.log(message, t);
}
}

View File

@@ -0,0 +1,42 @@
package kinosearch.webapp.template;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
public class FreemakerProcessor implements TemplateProcessor {
private Configuration config;
@Override
public void process(String templateName, Map<String, Object> model, Writer writer) throws IOException {
try {
if (config == null) {
if (model.containsKey(".templatedir")) {
init((String) model.get(".templatedir"));
} else {
init();
}
}
Template template = config.getTemplate(templateName);
template.process(model, writer);
} catch (TemplateException e) {
throw new IOException(e);
}
}
private void init(String templateDir) throws IOException {
config = new Configuration(Configuration.VERSION_2_3_23);
config.setDirectoryForTemplateLoading(new File(templateDir));
}
private void init() {
config = new Configuration(Configuration.VERSION_2_3_23);
config.setClassForTemplateLoading(getClass(), "/");
}
}

View File

@@ -0,0 +1,9 @@
package kinosearch.webapp.template;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
public interface TemplateProcessor {
void process(String templateName, Map<String, Object> model, Writer writer) throws IOException;
}

View File

@@ -0,0 +1,63 @@
package test.core;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import kinosearch.core.browser.Browser;
import kinosearch.core.browser.SimpleBrowser;
import static org.junit.Assert.*;
import org.junit.Test;
import java.io.IOException;
public class TestBrowser {
private final Gson gson = new Gson();
private final String data = "login=123&password=456";
private final String header_name = "Mytestheader";
private Browser getBrowser() {
return new SimpleBrowser();
}
private void setup_headers(Browser browser) {
browser.setHeader(header_name, "true");
}
private void assert_headers(JsonObject resultAsJson) {
JsonObject headers = resultAsJson.get("headers").getAsJsonObject();
assertEquals("true", headers.get(header_name).getAsString());
}
@Test
public void testGet() throws IOException {
Browser browser = getBrowser();
setup_headers(browser);
String result = browser.get("https://httpbin.org/get?" + data);
// System.out.println(result); //DEBUG
JsonObject jObj = gson.fromJson(result, JsonObject.class);
assert_headers(jObj);
JsonObject args = jObj.get("args").getAsJsonObject();
assertEquals("123", args.get("login").getAsString());
assertEquals("456", args.get("password").getAsString());
}
@Test
public void testPost() throws IOException {
Browser browser = getBrowser();
setup_headers(browser);
String result = browser.post("https://httpbin.org/post", data);
// System.out.println(result); //DEBUG
JsonObject jObj = gson.fromJson(result, JsonObject.class);
assert_headers(jObj);
JsonObject form = jObj.get("form").getAsJsonObject();
assertEquals("123", form.get("login").getAsString());
assertEquals("456", form.get("password").getAsString());
}
}

View File

@@ -0,0 +1,51 @@
package test.core;
import kinosearch.core.Kino;
import kinosearch.core.Tools;
import kinosearch.core.warez.KinoWarez;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.*;
public class TestCore {
@Test
public void test() {
Set<KinoWarez> set = Tools.getKinoWarezSet();
assertNotNull(set);
assertFalse(set.isEmpty());
List<Kino> list = Collections.synchronizedList(new ArrayList<>());
String kinoName = "бэтмен";
ThreadGroup threadGroup = new ThreadGroup("Search Threads Group");
int i = 0;
for(KinoWarez kinoWarez : set) {
new Thread(threadGroup, () -> {
System.err.println(Thread.currentThread().getName() + " :: start"); //DEBUG
kinoWarez.search(kinoName, list);
System.err.println(Thread.currentThread().getName() + " :: stop"); //DEBUG
}, "THR-" + (++i)).start();
}
i = 0;
while (threadGroup.activeCount() > 0) {
System.err.println("wait("+(++i)+")..."); //DEBUG
Tools.SafeSleep(1000);
}
assertFalse(list.isEmpty());
for (Kino kino : list) {
System.out.printf("\"%s\" (%s)\n", kino.getName(), kino.getUrl()); //DEBUG
assertTrue(kino.getName().toLowerCase().contains(kinoName.toLowerCase()));
}
}
}

View File

@@ -0,0 +1,28 @@
package test.core.warez;
import kinosearch.core.Kino;
import kinosearch.core.warez.Hdrezka;
import kinosearch.core.warez.KinoWarez;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertTrue;
public class TestHdrezka {
@Test
public void test() {
KinoWarez kinoWarez = new Hdrezka();
List<Kino> kinoList = new ArrayList<>();
String titleKino = "рик и морти";
kinoWarez.search(titleKino, kinoList);
assertTrue(kinoList.size() > 0);
Kino kino = kinoList.get(0);
System.out.printf("\"%s\" (%s)", kino.getName(), kino.getUrl()); //DEBUG
assertTrue(kino.getName().toLowerCase().contains(titleKino.toLowerCase()));
}
}

View File

@@ -0,0 +1,28 @@
package test.core.warez;
import kinosearch.core.Kino;
import kinosearch.core.warez.KinoWarez;
import kinosearch.core.warez.Onlinelife;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
public class TestOnlinelife {
@Test
public void test() {
KinoWarez kinoWarez = new Onlinelife();
List<Kino> kinoList = new ArrayList<>();
String titleKino = "рик и морти";
kinoWarez.search(titleKino, kinoList);
assertTrue(kinoList.size() > 0);
Kino kino = kinoList.get(0);
// System.out.printf("\"%s\" (%s)", kino.getName(), kino.getUrl()); //DEBUG
assertTrue(kino.getName().toLowerCase().contains(titleKino.toLowerCase()));
}
}

View File

@@ -0,0 +1,61 @@
package test.webapp;
import kinosearch.webapp.template.FreemakerProcessor;
import kinosearch.webapp.template.TemplateProcessor;
import org.junit.Before;
import org.junit.Test;
import java.io.*;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.*;
public class TestTemplateProcessor {
private ByteArrayOutputStream baos;
private Map<String, Object> model;
public class SimpleClass {
public String getVal1() {
return "Java is cool";
}
public int getVal2() {
return 8;
}
}
@Before
public void beforeTest() {
model = new HashMap<>();
model.put("message", "hello world");
model.put("ru_message", "привет мир");
model.put("obj", new SimpleClass());
baos = new ByteArrayOutputStream();
}
@Test
public void test() throws IOException {
System.err.println(System.getProperty("user.dir"));
TemplateProcessor templateProcessor = new FreemakerProcessor();
OutputStreamWriter writer = new OutputStreamWriter(baos);
templateProcessor.process("test_template.ftl", model, writer);
String result = baos.toString();
assertNotNull(result);
assertFalse(result.isEmpty());
// System.out.println(result); //DEBUG
String[] lines = result.split("\n");
assertNotNull(lines);
assertTrue(lines.length == 2);
assertEquals("String: "+model.get("message")+" :: "+model.get("ru_message"), lines[0]);
assertEquals("Object: "+((SimpleClass)model.get("obj")).getVal1()+" :: "+((SimpleClass)model.get("obj")).getVal2(), lines[1]);
}
}

View File

@@ -0,0 +1,2 @@
String: ${message} :: ${ru_message}
Object: ${obj.val1} :: ${obj.val2}