ExportManager.java
package sk.iway.iwcm.sync.export;
import java.beans.XMLEncoder;
import java.io.File;
import java.io.IOException;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import sk.iway.iwcm.Adminlog;
import sk.iway.iwcm.Constants;
import sk.iway.iwcm.DBPool;
import sk.iway.iwcm.FileTools;
import sk.iway.iwcm.Identity;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.common.FileBrowserTools;
import sk.iway.iwcm.doc.DocDB;
import sk.iway.iwcm.doc.DocDetails;
import sk.iway.iwcm.doc.GroupDetails;
import sk.iway.iwcm.doc.GroupsDB;
import sk.iway.iwcm.doc.PerexGroupBean;
import sk.iway.iwcm.doc.TemplateDetails;
import sk.iway.iwcm.doc.TemplatesDB;
import sk.iway.iwcm.editor.DocNoteBean;
import sk.iway.iwcm.editor.DocNoteDB;
import sk.iway.iwcm.io.IwcmFile;
import sk.iway.iwcm.io.IwcmInputStream;
import sk.iway.iwcm.io.IwcmOutputStream;
import sk.iway.iwcm.system.multidomain.MultiDomainFilter;
import sk.iway.iwcm.system.zip.ZipEntry;
import sk.iway.iwcm.system.zip.ZipOutputStream;
import sk.iway.iwcm.users.UserGroupDetails;
import sk.iway.iwcm.users.UserGroupsDB;
import sk.iway.spirit.MediaDB;
import sk.iway.spirit.model.Media;
/**
* Export stranok.
* Pouzitie:
* <pre>
* ExportManager export = ExportManager.create(request, session);
* export.exportGroup(groupId); // linku na vystup ulozi do ${zipfile}
* </pre>
*
*@Title webjet7
*@Company Interway s.r.o. (www.interway.sk)
*@Copyright Interway s.r.o. (c) 2001-2012
*@author $Author: jeeff vbur $
*@version $Revision: 1.3 $
*@created Date: 8.6.2012 19:13:50
*@modified $Date: 2004/08/16 06:26:11 $
*/
public class ExportManager
{
private HttpServletRequest _request; //NOSONAR
private HttpSession _session; //NOSONAR
private String virtualBase; // virtualny adresar na export
private String realBase; // realny adresar na export
private Identity user;
private GroupsDB groupsDB = GroupsDB.getInstance();
private List<ArchiveEntry> entries = new ArrayList<>();
private JspWriter out = null;
public static ExportManager create(HttpServletRequest request, HttpSession session)
{
ExportManager manager = new ExportManager();
manager.init(request, session);
return manager;
}
private ExportManager(){
// nepouzivat priamo; instancie vytvarame cez ExportManazer.create
}
private void init(HttpServletRequest request, HttpSession session)
{
_request = request;
_session = session;
user = (Identity) _session.getAttribute(Constants.USER_KEY);
initFolders(-1);
}
private void initFolders(int rootGroupId)
{
String groupIdAppend = "";
if (rootGroupId > 0)
{
groupIdAppend = rootGroupId+"/";
}
virtualBase = Constants.getBoolean("multiDomainEnabled")
? ("/files/" + MultiDomainFilter.getDomainAlias(DocDB.getDomain(_request)) + "/protected/backup/"+groupIdAppend)
: "/files/protected/backup/"+groupIdAppend;
virtualBase = Tools.replace(virtualBase, "//", "/");
realBase = realPath(virtualBase);
if (!new IwcmFile(realBase).exists())
{
new IwcmFile(realBase).mkdirs();
}
}
/**
* Exportuje vsetko v danom adresari.
*
* @param groupId identifikator adresara
* @throws IOException chyba pri zapisovani na disk alebo zipovani
*/
public void exportGroup(int groupId) throws IOException
{
if (null == user) return; // neprihlaseny pouzivatel nemoze exportovat
writeOut("Export id: "+groupId);
initFolders(groupId);
String zipFilename = DocDB.getDomain(_request) + "-" + new SimpleDateFormat("yyyy-MM-dd-HHmm").format(new Date()) + ".zip";
//pre cloud cachujeme uz raz exportovane ZIP subory za dany den
if ("cloud".equals(Constants.getInstallName()))
{
zipFilename = Constants.getInstallName() + "-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + "-"+groupId+".zip";
if (FileTools.isFile(virtualBase+zipFilename))
{
Logger.debug(ExportManager.class, "Returning ZIP from cache: "+zipFilename);
_request.setAttribute("zipfile", virtualBase + zipFilename);
return;
}
}
writeOut("Zip: "+virtualBase+"/"+zipFilename);
// exportuj uzivatelske skupiny
List<UserGroupDetails> userGroups = UserGroupsDB.getInstance().getUserGroups();
if (null != userGroups)
{
write("usergroups.xml", userGroups);
}
writeOut("usergroups.xml");
// exportuj perex skupiny
List<PerexGroupBean> perexGroups = DocDB.getInstance().getPerexGroups();
if (null != perexGroups)
{
write("perexgroups.xml", perexGroups);
}
writeOut("perexgroups.xml");
// exportuj sablony
List<TemplateDetails> templates = TemplatesDB.getInstance().getTemplates();
if (null != templates)
{
write("temps.xml", templates);
}
writeOut("temps.xml");
// exportuj adresare
List<GroupDetails> groups = groupsDB.getGroupsTree(groupId, true, true);
if (null != groups)
{
write("groups.xml", groups);
}
writeOut("groups.xml");
//exportuj poznamky pre redaktorov
List<DocNoteBean> docNotes = DocNoteDB.getInstance().getCurrentDocNotes();
if (null != docNotes)
{
write("notes.xml", docNotes);
}
writeOut("notes.xml");
// exportuj stranky
List<DocDetails> docs = getAllDocs(groupId);
if (!docs.isEmpty()) {
write("docs.xml", docs);
}
writeOut("docs.xml");
Content content = new Content();
ContentBuilder callback = new ContentBuilder(content, _request);
int counter = 0;
for (DocDetails doc : docs)
{
counter++;
DocExporter.export(doc, callback);
if (counter % 10 == 0) writeOut("doc "+counter+"/"+docs.size());
}
writeOut("content.xml");
//pridaj subory ak je definovany adresar
String[] addDirs = _request.getParameterValues("adddir");
if (addDirs != null && addDirs.length>0)
{
for (String dir : addDirs)
{
if (FileBrowserTools.hasForbiddenSymbol(dir)) continue;
addCustomFiles(dir, callback, docs, 0);
}
}
writeOut("customfiles");
List<Content.File> contentFiles = content.getFiles();
counter = 0;
for (Content.File contentFile : contentFiles)
{
counter++;
Logger.debug(ExportManager.class, "Adding file:"+contentFile.getVirtualPath());
String realFile = realPath(contentFile.getVirtualPath());
String zipFile = "content/" + contentFile.getZipPath();
IwcmFile iFile = new IwcmFile(realFile);
contentFile.setSize(iFile.length());
contentFile.setTime(iFile.lastModified());
entries.add(new ArchiveEntry(zipFile, realFile));
if (counter % 10 == 0) writeOut("files "+counter+"/"+contentFiles.size());
}
write("content.xml", content);
writeOut("content.xml");
//exportuj media
List<Media> media = MediaDB.getMedia(_session, "documents", -1, null, 0, false);
write("media.xml", media);
writeOut("media.xml");
IwcmFile exportFile = new IwcmFile(realBase, zipFilename);
writeOut("Export ZIP: "+exportFile.getVirtualPath());
IwcmOutputStream output = new IwcmOutputStream(exportFile);
ZipOutputStream zipOut = new ZipOutputStream(output);
counter = 0;
for (ArchiveEntry entry : entries)
{
counter++;
addToZipArchive(zipOut, entry.entryPath, entry.filePath);
if (counter % 10 == 0) writeOut("zipping "+counter+"/"+entries.size());
}
zipOut.close();
writeOut("ZIP OK");
for (String filename : new String[]{ "docs.xml", "groups.xml", "temps.xml", "usergroups.xml", "content.xml" })
{
new IwcmFile(filename).delete();
}
//zapis do auditu cestu k suboru
Adminlog.add(Adminlog.TYPE_EXPORT_WEBJET, "Exporting web pages, group="+groupId+" exported ZIP="+exportFile.getVirtualPath(), groupId, -1);
_request.setAttribute("zipfile", virtualBase + zipFilename);
}
/**
* Prida do exportu custom adresare (subory) volane parametrom adddir (pouziva sa v cloude)
* @param dir - URL adresa adresara, napr. /images/template/common, alebo /images/template/temp48
* @param callback
* @param docs
* @param failsafeCounter - failsafe counter, na zaciatku 0, potom sa pri rekurzii zvysuje, max hlbka je 10
*/
private void addCustomFiles(String dir, ContentBuilder callback, List<DocDetails> docs, int failsafeCounter)
{
if (failsafeCounter > 10) return;
if (dir.startsWith("/images") || dir.startsWith("/files"))
{
IwcmFile fDir = new IwcmFile(Tools.getRealPath(dir));
if (fDir.isDirectory())
{
IwcmFile[] files = fDir.listFiles();
for (IwcmFile file : files)
{
if (file.isDirectory())
{
addCustomFiles(dir + "/" + file.getName(), callback, docs, failsafeCounter+1);
}
else if (file.canRead())
{
callback.setDoc(docs.get(0));
Logger.debug(ExportManager.class, "Adddir, file="+file.getVirtualPath());
callback.addLink(file.getVirtualPath());
}
}
}
}
}
private List<DocDetails> getAllDocs(int rootGroupId)
{
List<DocDetails> docs = new ArrayList<>();
List<GroupDetails> groups = groupsDB.getGroupsTree(rootGroupId, true, true);
for (GroupDetails group : groups)
{
List<DocDetails> groupDocs = getDocByGroup(group.getGroupId()); //DocDB.getInstance().getDocByGroup(group.getGroupId());
docs.addAll(groupDocs);
}
return docs;
}
/**
* Pouzite priamo tu citanie z DB pretoze sa maju exportovat aj not available stranky, co standarde DocDB nevie kvoli tomu aby to nahodou niekto nepouzil ;-)
* @param groupId
* @return
*/
private List<DocDetails> getDocByGroup(int groupId)
{
List<DocDetails> ret = new ArrayList<>();
java.sql.Connection db_conn = null;
java.sql.PreparedStatement ps = null;
ResultSet rs = null;
try
{
db_conn = DBPool.getConnectionReadUncommited();
//read user permissions for every org struct
StringBuilder order = new StringBuilder("d.title");
order.append(" ASC");
String sql;
DocDetails doc;
String usersTablePrefix = Constants.getString("usersTablePrefix");
if (Constants.DB_TYPE == Constants.DB_ORACLE)
{
sql = "SELECT u.title as u_title, u.first_name, u.last_name, u.email, u.photo, d.* FROM documents d, "+usersTablePrefix+"users u WHERE d.author_id=u.user_id(+) AND group_id=" + groupId + " ORDER BY " + order.toString();
}
else
{
sql = "SELECT u.title as u_title, u.first_name, u.last_name, u.email, u.photo, d.* FROM documents d LEFT JOIN "+usersTablePrefix+"users u ON d.author_id=u.user_id WHERE group_id=" + groupId + " ORDER BY " + order.toString();
}
ps = db_conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next())
{
doc = DocDB.getDocDetails(rs, false);
ret.add(doc);
}
rs.close();
ps.close();
db_conn.close();
db_conn = null;
ps = null;
rs = null;
}
catch (Exception ex){sk.iway.iwcm.Logger.error(ex);}
finally{
try{
if (rs != null) rs.close();
if (ps != null) ps.close();
if (db_conn != null) db_conn.close();
}catch (Exception e) {sk.iway.iwcm.Logger.error(e);}
}
return (ret);
}
/**
* Ulozi objekt do suboru vo formate XML.
*
* @param filename retazec s nazvom suboru
* @param object objekt, ktory ideme serializovat
* @throws IOException
*/
private void write(String filename, Object object) throws IOException
{
IwcmOutputStream output = new IwcmOutputStream(new IwcmFile(realBase, filename));
XMLEncoder encoder = new XMLEncoder(output);
encoder.writeObject(object);
encoder.close();
output.close();
entries.add(new ArchiveEntry(filename, realBase + File.separator + filename));
}
static void addToZipArchive(ZipOutputStream zipOut, String entryPath, String filePath)
{
try
{
ZipEntry entry = new ZipEntry(entryPath);
IwcmFile inFile = new IwcmFile(filePath);
entry.setSize(inFile.length());
entry.setTime(inFile.lastModified());
zipOut.putNextEntry(entry);
IwcmInputStream in = new IwcmInputStream(inFile);
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) != -1)
{
zipOut.write(buffer, 0, bytesRead);
}
in.close();
zipOut.closeEntry();
}
catch (Exception ex)
{
sk.iway.iwcm.Logger.error(ex);
}
}
private static String realPath(String virtualPath)
{
return Tools.getRealPath(virtualPath);
}
static class ArchiveEntry
{
public final String entryPath;
public final String filePath; // real
public ArchiveEntry(String entryPath, String filePath)
{
this.entryPath = entryPath;
this.filePath = filePath;
}
}
public void setOut(JspWriter out) {
this.out = out;
}
private void writeOut(String text) {
if (out == null) return;
try {
out.println("<p>"+Tools.formatDateTimeSeconds(Tools.getNow())+" "+text+"</p>");
out.println("<script type='text/javascript'>window.scrollBy(0,1000);</script>");
out.flush();
}
catch (Exception ex) {
}
}
}