package com.smash.revolance.ui.server.controller; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ui-monitoring-server * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Copyright (C) 2012 - 2014 RevoLance * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * This program 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. * * This program 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 this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ import com.smash.revolance.ui.database.IStorage; import com.smash.revolance.ui.database.StorageException; import com.smash.revolance.ui.explorer.ExplorationConfiguration; import com.smash.revolance.ui.explorer.IExplorer; import com.smash.revolance.ui.materials.JsonHelper; import com.smash.revolance.ui.model.element.ElementNotFound; import com.smash.revolance.ui.model.element.api.ElementBean; import com.smash.revolance.ui.model.page.api.PageBean; import com.smash.revolance.ui.model.sitemap.SiteMap; import com.smash.revolance.ui.server.model.Application; import com.smash.revolance.ui.server.model.Exploration; import com.smash.revolance.ui.server.renderable.ApplicationDetailsRenderable; import org.rendersnake.HtmlCanvas; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import javax.validation.Valid; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * Created by wsmash on 27/10/13. */ @Controller public class ApplicationController { private IStorage logs; @Autowired public void setLogs(IStorage logs) { this.logs = logs; } private IStorage applications; @Autowired public void setApplications(IStorage applications) { this.applications = applications; } IExplorer explorer; @Autowired public void setExplorer(IExplorer explorer) { this.explorer = explorer; } @RequestMapping(value = "/applications", method = RequestMethod.POST) public ModelAndView declareApplication(@Valid Exploration exploration, BindingResult result, @ModelAttribute("model") ModelMap model) throws IOException, StorageException { if ( result.hasErrors() ) { return displayApplicationForm(model); } else { final ExplorationConfiguration cfg = new ExplorationConfiguration(); File log = new File(logs.getLocation(), exploration.getTag()); log.createNewFile(); cfg.setLogFile(log); File report = new File(applications.getLocation(), exploration.getTag()); cfg.setReportFile(report); cfg.setLogin(exploration.getLogin()); // This is mandatory in both cases if(exploration.isSecured()) { cfg.setPassword(exploration.getPassword()); cfg.setApplication(exploration.getApplicationModel().getBytes()); cfg.setApplicationSecured(true); cfg.setApplicationClassName(exploration.getApplicationClassName()); } cfg.setBrowserHeight(exploration.getHeight()); cfg.setBrowserWidth(exploration.getWidth()); Map<String, Object> settings = (Map<String, Object>) JsonHelper.getInstance().map(Map.class, new File(System.getProperty("settings", ""))); List<Map<String, String>> browsers = (List<Map<String, String>>) settings.get("browsers"); boolean found = false; for(Map<String, String> browser : browsers) { if(browser.get("name").contentEquals(exploration.getBrowserType())) { cfg.setBrowserType(browser.get("name")); cfg.setDriverPath(browser.get("driverPath")); cfg.setBrowserPath(browser.get("browserPath")); found = true; } if(found) { break; } } cfg.setDomain(exploration.getDomain()); cfg.setUrl(exploration.getUrl()); cfg.setFollowButtons(exploration.isFollowButtons()); cfg.setFollowLinks(exploration.isFollowLinks()); cfg.setId(exploration.getTag()); cfg.setTimeout(exploration.getTimeout()); cfg.setPageScreenshotEnabled(true); cfg.setPageElementScreenshotEnabled(true); new Thread(new Runnable() { @Override public void run() { try { explorer.explore(cfg); } catch (Exception e) { e.printStackTrace(); } } }).start(); return new ModelAndView("ApplicationLogs", "applicationId", exploration.getTag()); } } @RequestMapping(value = "/applications/declare", method = RequestMethod.GET) public ModelAndView displayApplicationForm(@ModelAttribute("model") ModelMap model) throws IOException { Map<String, Object> settings = (Map<String, Object>) JsonHelper.getInstance().map(Map.class, new File(System.getProperty("settings", ""))); model.addAttribute("browsers", settings.get("browsers")); model.addAttribute("resolutions", settings.get("resolutions")); return new ModelAndView( "ApplicationForm", model ); } @RequestMapping(value = "/applications/{applicationId}", method = RequestMethod.DELETE) public ModelAndView removeApplication(@PathVariable String applicationId) throws StorageException, IOException { applications.delete(applicationId); logs.delete(applicationId); return new ModelAndView( "ApplicationList", "applications", getApplications() ); } @ResponseBody @RequestMapping(value = "/applications/{applicationId}/pages/{pageId}/elements/${elementId}", method = RequestMethod.GET, headers="Accept=application/json") public ElementBean retrievePageElement(@PathVariable String applicationId, @PathVariable String pageId, @PathVariable String elementId) throws StorageException, IOException, ElementNotFound { PageBean refPage = getSiteMap(applicationId).findPageByInternalId(pageId); for(ElementBean element : refPage.getContent()) { if(element.getId().contentEquals(elementId)) { return element; } } throw new ElementNotFound("Element with id: '"+elementId+"' could not be found."); } @RequestMapping(value = "/applications", method = RequestMethod.GET) public ModelAndView displayApplications(@ModelAttribute("model") ModelMap model) throws IOException, StorageException { model.addAttribute("applications", getApplications()); return new ModelAndView( "ApplicationList", model ); } @RequestMapping(value = "/", method = RequestMethod.GET) public ModelAndView displayRoot(@ModelAttribute("model") ModelMap model) throws IOException, StorageException { return displayApplications(model); } @RequestMapping(value = "/applications/{contentTag}", method = RequestMethod.GET) public ModelAndView displayContentDetails(@RequestParam(value="reviewId", defaultValue = "") String reviewId, @PathVariable String contentTag, @ModelAttribute("model") ModelMap model) throws StorageException, IOException { List<PageBean> pages = new ArrayList<PageBean>(); for ( PageBean page : getSiteMap(contentTag).getPages() ) { pages.add(page); if ( page.hasVariants() ) { pages.addAll(page.getVariants()); } } model.addAttribute( "applicationId", contentTag ); model.addAttribute("pagesCount", pages.size()); HtmlCanvas canvas = new HtmlCanvas(); new ApplicationDetailsRenderable(reviewId, pages).renderOn(canvas); model.addAttribute( "pages", canvas.toHtml() ); return new ModelAndView( "ApplicationDetail", model ); } @RequestMapping(value = "/applications/{applicationId}/logs", method = RequestMethod.GET) public ModelAndView renderLogs(@PathVariable String applicationId) { return new ModelAndView( "ApplicationLogs", "applicationId", applicationId ); } @ResponseBody @RequestMapping(value = "/applications/{applicationId}/logs", method = RequestMethod.GET, headers="Accept=application/json") public String updateExplorationLogs(@PathVariable String applicationId, @RequestParam(value = "fromLine", defaultValue = "0") int fromLine) throws IOException, StorageException { List<String> logs = new ArrayList(); if(!this.logs.isKeyUsed(applicationId)) { logs = Arrays.asList(new String[]{"Undefined explorationId: " + applicationId}); } else { List<String> content = new ArrayList<>(); content.addAll(Arrays.asList(this.logs.retrieve(applicationId).split("\\n"))); if(!content.isEmpty()) { while(fromLine>0 && !content.isEmpty()) { content.remove(0); fromLine --; } logs.addAll(content); } } return JsonHelper.getInstance().map(logs); } //-- Private methods private List<Application> getApplications() throws StorageException, IOException { List<Application> applications = new ArrayList<>(); for ( String key : this.applications.retrieveAll().keySet() ) { Application app = new Application(); app.setTag( key ); SiteMap sitemap = getSiteMap(key); app.setSitemap( sitemap ); app.setUser( sitemap.getUser() ); app.setPagesCount( sitemap.getPagesCount() ); applications.add( app ); } return applications; } private SiteMap getSiteMap(String applicationId) throws IOException, StorageException { return SiteMap.fromJson(applications.retrieve(applicationId)); } }