package de.cinovo.cloudconductor.server.web.impl;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import de.cinovo.cloudconductor.server.dao.IFileDAO;
import de.cinovo.cloudconductor.server.dao.IFileDataDAO;
import de.cinovo.cloudconductor.server.dao.IFileTagsDAO;
import de.cinovo.cloudconductor.server.dao.IPackageDAO;
import de.cinovo.cloudconductor.server.dao.IServiceDAO;
import de.cinovo.cloudconductor.server.dao.ITemplateDAO;
import de.cinovo.cloudconductor.server.model.EFile;
import de.cinovo.cloudconductor.server.model.EFileData;
import de.cinovo.cloudconductor.server.model.EFileTag;
import de.cinovo.cloudconductor.server.model.EPackage;
import de.cinovo.cloudconductor.server.model.EService;
import de.cinovo.cloudconductor.server.model.ETemplate;
import de.cinovo.cloudconductor.server.util.exception.FormErrorException;
import de.cinovo.cloudconductor.server.web.CSViewModel;
import de.cinovo.cloudconductor.server.web.helper.AWebPage;
import de.cinovo.cloudconductor.server.web.helper.AjaxAnswer;
import de.cinovo.cloudconductor.server.web.helper.NavbarHardLinks;
import de.cinovo.cloudconductor.server.web.helper.SidebarType;
import de.cinovo.cloudconductor.server.web.interfaces.IFiles;
import de.cinovo.cloudconductor.server.web.interfaces.IWebPath;
import de.taimos.cxf_renderer.model.RenderedUI;
import de.taimos.restutils.RESTAssert;
/**
* Copyright 2014 Cinovo AG<br>
* <br>
*
* @author psigloch
*
*/
public class FilesImpl extends AWebPage implements IFiles {
@Autowired
protected IFileDAO dFile;
@Autowired
protected ITemplateDAO dTemplate;
@Autowired
protected IPackageDAO dPackage;
@Autowired
private IServiceDAO dService;
@Autowired
private IFileDataDAO dFileData;
@Autowired
private IFileTagsDAO dFileTags;
@Override
protected String getTemplateFolder() {
return "files";
}
@Override
protected void init() {
this.navRegistry.registerSubMenu(NavbarHardLinks.config, this.getNavElementName(), IFiles.ROOT);
this.addBreadCrumb(IWebPath.WEBROOT + IFiles.ROOT, this.getNavElementName());
this.addTopAction(IWebPath.WEBROOT + IFiles.ROOT + IWebPath.ACTION_ADD, "Create new File");
this.addViewType("default", "Default", true);
this.addViewType("template", "by Template", false);
}
@Override
protected SidebarType getSidebarType() {
return SidebarType.ALPHABETICAL;
}
@Override
protected String getNavElementName() {
return "Files";
}
@Override
@Transactional
public RenderedUI view(String viewtype, String[] filter) {
this.clearFilter();
if ((viewtype != null) && viewtype.equals(IFiles.TEMPLATE_FILTER)) {
return this.templateView();
}
return this.defaultView(filter);
}
@Transactional
private RenderedUI defaultView(String[] filter) {
for (EFileTag t : this.dFileTags.findList()) {
this.addFilter(String.valueOf(t.getId()), t.getName(), false);
}
List<EFileTag> tags = new ArrayList<>();
for (String f : filter) {
EFileTag tag = this.dFileTags.findById(Long.valueOf(f));
if (tag != null) {
tags.add(tag);
}
}
List<EFile> daofiles = this.dFile.findList();
List<EFile> files = new ArrayList<>();
for (EFile f : daofiles) {
if (!tags.isEmpty()) {
if (!Collections.disjoint(f.getTags(), tags)) {
this.addSidebarElement(f.getName());
files.add(f);
}
} else {
this.addSidebarElement(f.getName());
files.add(f);
}
}
this.addSidebarElements(files);
List<ETemplate> templates = this.dTemplate.findList();
this.sortNamedList(files);
CSViewModel view = this.createView();
view.addModel("FILES", files);
view.addModel("TEMPLATES", templates);
return view.render();
}
@Transactional
private RenderedUI templateView() {
List<EFile> files = this.dFile.findList();
for (EFile f : files) {
this.addSidebarElement(f.getName());
}
this.addSidebarElements(files);
List<ETemplate> templates = this.dTemplate.findList();
this.sortNamedList(files);
CSViewModel view;
view = this.createView("viewTemplate");
view.addModel("SIDEBARTYPE", null);
view.addModel("FILES", files);
view.addModel("TEMPLATES", templates);
return view.render();
}
@Override
@Transactional
public RenderedUI newFileView() {
List<EPackage> packages = this.dPackage.findList();
this.sortNamedList(packages);
List<EService> services = this.dService.findList();
this.sortNamedList(services);
List<ETemplate> templates = this.dTemplate.findList();
this.sortNamedList(templates);
CSViewModel modal = this.createModal("mModFile");
modal.addModel("PACKAGES", packages);
modal.addModel("SERVICES", services);
modal.addModel("TEMPLATES", templates);
return modal.render();
}
@Override
@Transactional
public RenderedUI editFileView(String name) {
RESTAssert.assertNotEmpty(name);
EFile oldFile = this.dFile.findByName(name);
EFileData fileData = this.dFileData.findDataByFile(oldFile);
List<EPackage> packages = this.dPackage.findList();
List<EService> services = this.dService.findList();
this.sortNamedList(services);
this.sortNamedList(packages);
List<ETemplate> templates = this.dTemplate.findList();
this.sortNamedList(templates);
CSViewModel modal = this.createModal("mModFile");
modal.addModel("FILE", oldFile);
modal.addModel("FILEDATA", StringEscapeUtils.escapeHtml(fileData.getData()));
modal.addModel("PACKAGES", packages);
modal.addModel("SERVICES", services);
modal.addModel("TEMPLATES", templates);
return modal.render();
}
@Override
public RenderedUI deleteFileView(String name) {
RESTAssert.assertNotEmpty(name);
EFile file = this.dFile.findByName(name);
CSViewModel modal = this.createModal("mDeleteFile");
modal.addModel("FILE", file);
return modal.render();
}
@Override
@Transactional
public RenderedUI deleteFileFromTemplateView(String name, String template) {
RESTAssert.assertNotEmpty(name);
RESTAssert.assertNotEmpty(template);
ETemplate t = this.dTemplate.findByName(template);
RESTAssert.assertNotNull(t);
EFile file = this.dFile.findByName(name);
RESTAssert.assertNotNull(file);
CSViewModel modal = this.createModal("mDeleteFileFromTemplate");
modal.addModel("FILE", file);
modal.addModel("TEMPLATE", t);
return modal.render();
}
@Override
@Transactional
public RenderedUI addFileToTemplateView(String template) {
RESTAssert.assertNotEmpty(template);
ETemplate t = this.dTemplate.findByName(template);
RESTAssert.assertNotNull(t);
CSViewModel modal = this.createModal("mAddFile");
List<EFile> files = this.dFile.findList();
modal.addModel("FILES", files);
modal.addModel("TEMPLATE", t);
return modal.render();
}
@Override
@Transactional
public RenderedUI addTemplateToFileView(String file) {
RESTAssert.assertNotEmpty(file);
EFile f = this.dFile.findByName(file);
RESTAssert.assertNotNull(f);
CSViewModel modal = this.createModal("mAddTemplate");
List<ETemplate> templates = this.dTemplate.findList();
modal.addModel("FILE", f);
modal.addModel("TEMPLATES", templates);
return modal.render();
}
@Override
@Transactional
public AjaxAnswer saveFile(String oldname, String newname, String owner, String group, String mode, String targetPath, String content, Boolean isTemplate, String depPackage, String[] depServices, String[] templates) throws FormErrorException {
RESTAssert.assertNotEmpty(oldname);
EFile cf = this.dFile.findByName(oldname);
// Form error handling
FormErrorException error = null;
error = this.assertNotEmpty(newname, error, "name");
error = this.assertNotEmpty(owner, error, "owner");
error = this.assertNotEmpty(group, error, "group");
error = this.assertNotEmpty(mode, error, "mode");
error = this.assertNotEmpty(targetPath, error, "targetPath");
error = this.assertNotEmpty(content, error, "file_content");
error = this.assertNotEmpty(owner, error, "owner");
if (!oldname.equals(newname) && (this.dFile.findByName(newname) != null)) {
error = error == null ? this.createError("The service name already exists.") : error;
error.addElementError("name", true);
}
if ((newname != null) && !newname.isEmpty() && newname.contains(" ")) {
error = error == null ? this.createError("The service name may not contain spaces.") : error;
error.addElementError("name", true);
}
if (error != null) {
// add the currently entered values to the answer
error.addFormParam("name", newname);
error.addFormParam("owner", owner);
error.addFormParam("group", group);
error.addFormParam("mode", mode);
error.addFormParam("targetPath", targetPath);
error.addFormParam("file_content", content);
error.addFormParam("isTemplate", isTemplate);
error.addFormParam("depPackage", depPackage);
error.addFormParam("depServices", Arrays.asList(depServices));
error.addFormParam("templates", templates);
if (oldname.equals("0")) {
error.setParentUrl(IFiles.ROOT, IWebPath.ACTION_ADD);
} else {
error.setParentUrl(IFiles.ROOT, oldname, IWebPath.ACTION_EDIT);
}
throw error;
}
// save process
if (cf == null) {
cf = new EFile();
cf.setDependentServices(new ArrayList<EService>());
}
cf.setName(newname);
cf.setOwner(owner);
cf.setGroup(group);
cf.setFileMode(mode);
cf.setTargetPath(targetPath);
cf.setTemplate(isTemplate == null ? false : true);
cf.setPkg(this.dPackage.findByName(depPackage));
if (depServices.length > 0) {
cf.setReloadable(true);
Set<EService> notfound = new HashSet<>(cf.getDependentServices());
for (String service : depServices) {
EService eservice = this.dService.findByName(service);
if (!cf.getDependentServices().contains(eservice)) {
cf.getDependentServices().add(eservice);
}
notfound.remove(eservice);
}
cf.getDependentServices().removeAll(notfound);
} else {
cf.setReloadable(false);
cf.getDependentServices().clear();
}
try {
byte[] array = MessageDigest.getInstance("MD5").digest(content.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < array.length; ++i) {
sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
}
cf.setChecksum(sb.toString());
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
// should never happen, if it does-> leave checksum empty
}
cf = this.dFile.save(cf);
EFileData data = this.dFileData.findDataByFile(cf);
if (data == null) {
data = new EFileData();
data.setParent(cf);
}
data.setData(content);
data = this.dFileData.save(data);
List<ETemplate> notfound = this.dTemplate.findList();
for (String template : templates) {
ETemplate temp = this.dTemplate.findByName(template);
if (!temp.getConfigFiles().contains(cf)) {
temp.getConfigFiles().add(cf);
this.dTemplate.save(temp);
}
notfound.remove(temp);
}
for (ETemplate template : notfound) {
if (template.getConfigFiles().contains(cf)) {
template.getConfigFiles().remove(cf);
this.dTemplate.save(template);
}
}
return new AjaxAnswer(IWebPath.WEBROOT + IFiles.ROOT, this.getCurrentViewType());
}
@Override
@Transactional
public AjaxAnswer deleteFile(String name) {
RESTAssert.assertNotEmpty(name);
EFile cf = this.dFile.findByName(name);
if (cf == null) {
return new AjaxAnswer(IWebPath.WEBROOT + IFiles.ROOT);
}
EFileData data = this.dFileData.findDataByFile(cf);
this.dFile.delete(cf);
this.dFileData.delete(data);
this.removeSidebarElement(name);
return new AjaxAnswer(IWebPath.WEBROOT + IFiles.ROOT);
}
@Override
@Transactional
public AjaxAnswer deleteFileFromTemplate(String name, String template) {
RESTAssert.assertNotEmpty(template);
RESTAssert.assertNotEmpty(name);
ETemplate t = this.dTemplate.findByName(template);
EFile file = this.dFile.findByName(name);
if (t.getConfigFiles().contains(file)) {
t.getConfigFiles().remove(file);
this.dTemplate.save(t);
}
// Fill template with models and return.
return new AjaxAnswer(IWebPath.WEBROOT + IFiles.ROOT, IFiles.TEMPLATE_FILTER + "#" + template);
}
@Override
@Transactional
public AjaxAnswer addFileToTemplate(String[] name, String template) {
RESTAssert.assertNotEmpty(template);
ETemplate t = this.dTemplate.findByName(template);
for (String file : name) {
EFile f = this.dFile.findByName(file);
t.getConfigFiles().add(f);
this.dTemplate.save(t);
}
return new AjaxAnswer(IWebPath.WEBROOT + IFiles.ROOT, IFiles.TEMPLATE_FILTER + "#" + template);
}
@Override
@Transactional
public AjaxAnswer addTemplateToFile(String[] template, String name) {
RESTAssert.assertNotEmpty(name);
EFile f = this.dFile.findByName(name);
for (String temp : template) {
ETemplate t = this.dTemplate.findByName(temp);
t.getConfigFiles().add(f);
this.dTemplate.save(t);
}
return new AjaxAnswer(IWebPath.WEBROOT + IFiles.ROOT, IFiles.TEMPLATE_FILTER + "#" + template);
}
}