/* =============================================================================== * * Part of the InfoGlue Content Management Platform (www.infoglue.org) * * =============================================================================== * * Copyright (C) * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 2, as published by the * Free Software Foundation. See the file LICENSE.html for more information. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY, including 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, write to the Free Software Foundation, Inc. / 59 Temple * Place, Suite 330 / Boston, MA 02111-1307 / USA. * * =============================================================================== */ package org.infoglue.cms.applications.managementtool.actions; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.exolab.castor.mapping.Mapping; import org.exolab.castor.xml.Marshaller; import org.infoglue.cms.applications.common.VisualFormatter; import org.infoglue.cms.applications.common.actions.InfoGlueAbstractAction; import org.infoglue.cms.applications.databeans.ProcessBean; import org.infoglue.cms.controllers.kernel.impl.simple.AccessRightController; import org.infoglue.cms.controllers.kernel.impl.simple.CastorDatabaseService; import org.infoglue.cms.controllers.kernel.impl.simple.CategoryController; import org.infoglue.cms.controllers.kernel.impl.simple.ContentController; import org.infoglue.cms.controllers.kernel.impl.simple.ContentTypeDefinitionController; import org.infoglue.cms.controllers.kernel.impl.simple.CopyRepositoryController; import org.infoglue.cms.controllers.kernel.impl.simple.ImportController; import org.infoglue.cms.controllers.kernel.impl.simple.OptimizedImportController; import org.infoglue.cms.controllers.kernel.impl.simple.RepositoryController; import org.infoglue.cms.entities.content.Content; import org.infoglue.cms.entities.management.RepositoryVO; import org.infoglue.cms.exception.SystemException; import org.infoglue.cms.util.CmsPropertyHandler; import org.infoglue.cms.util.FileUploadHelper; import webwork.action.ActionContext; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.reflect.TypeToken; /** * This class handles Exporting of a repository to an XML-file. * * @author mattias */ public class ImportRepositoryAction extends InfoGlueAbstractAction { public final static Logger logger = Logger.getLogger(ImportRepositoryAction.class.getName()); private Integer repositoryId = null; private String onlyLatestVersions = "false"; private String standardReplacement = null; private String replacements = null; private Boolean mergeExistingRepositories = false; private String processId = null; private String exportFormat = "2"; private VisualFormatter visualFormatter = new VisualFormatter(); /** * This deletes a process info bean and related files etc. * @return * @throws Exception */ public String doDeleteProcessBean() throws Exception { if(this.processId != null) { ProcessBean pb = ProcessBean.getProcessBean(ImportRepositoryAction.class.getName(), processId); if(pb != null) pb.removeProcess(); } return "successRedirectToProcesses"; } /** * This refreshes the view. * @return * @throws Exception */ public String doShowProcesses() throws Exception { return "successShowProcesses"; } public String doShowProcessesAsJSON() throws Exception { // TODO it would be nice we could write JSON to the OutputStream but we get a content already transmitted exception then. return "successShowProcessesAsJSON"; } /** * This shows the dialog before export. * @return * @throws Exception */ public String doInput() throws Exception { standardReplacement = "stateYourOldSiteName=stateYourNewSiteName"; return "input"; } public String doInputCopy() throws Exception { RepositoryVO repositoryVO = RepositoryController.getController().getRepositoryVOWithId(repositoryId); standardReplacement = repositoryVO.getName() + "=" + repositoryVO.getName() + " copy"; return "inputCopy"; } /** * This handles the actual importing. */ protected String doExecute() throws SystemException { Database db = CastorDatabaseService.getDatabase(); try { //now restore the value and list what we get File file = FileUploadHelper.getUploadedFile(ActionContext.getContext().getMultiPartRequest()); if(file == null || !file.exists()) { String filePath = ActionContext.getContext().getMultiPartRequest().getParameter("filePath"); logger.info("filePath:" + filePath); if(filePath != null) { file = new File(filePath); } else throw new SystemException("The file upload must have gone bad as no file reached the import utility."); } if(file.getName().endsWith(".zip")) return importV3(file); String encoding = "UTF-8"; int version = 1; //Looking up what kind of dialect this is. FileInputStream fisTemp = new FileInputStream(file); InputStreamReader readerTemp = new InputStreamReader(fisTemp, encoding); BufferedReader bufferedReaderTemp = new BufferedReader(readerTemp); String line = bufferedReaderTemp.readLine(); int index = 0; while(line != null && index < 50) { logger.info("line:" + line + '\n'); if(line.indexOf("contentTypeDefinitionId") > -1) { logger.info("This was a new export..."); version = 2; break; } line = bufferedReaderTemp.readLine(); index++; } bufferedReaderTemp.close(); readerTemp.close(); fisTemp.close(); Mapping map = new Mapping(); if(version == 1) { logger.info("MappingFile:" + CastorDatabaseService.class.getResource("/xml_mapping_site.xml").toString()); map.loadMapping(CastorDatabaseService.class.getResource("/xml_mapping_site.xml").toString()); } else if(version == 2) { logger.info("MappingFile:" + CastorDatabaseService.class.getResource("/xml_mapping_site_2.5.xml").toString()); map.loadMapping(CastorDatabaseService.class.getResource("/xml_mapping_site_2.5.xml").toString()); } // All ODMG database access requires a transaction db.begin(); Map contentIdMap = new HashMap(); Map siteNodeIdMap = new HashMap(); List allContentIds = new ArrayList(); Map<String,String> replaceMap = new HashMap<String,String>(); try { boolean isUTF8 = false; boolean hasUnicodeChars = false; if(replacements.indexOf((char)65533) > -1) isUTF8 = true; for(int i=0; i<replacements.length(); i++) { int c = (int)replacements.charAt(i); if(c > 255 && c < 65533) hasUnicodeChars = true; } if(!isUTF8 && !hasUnicodeChars) { String fromEncoding = CmsPropertyHandler.getUploadFromEncoding(); if(fromEncoding == null) fromEncoding = "iso-8859-1"; String toEncoding = CmsPropertyHandler.getUploadToEncoding(); if(toEncoding == null) toEncoding = "utf-8"; if(replacements.indexOf("å") == -1 && replacements.indexOf("ä") == -1 && replacements.indexOf("ö") == -1 && replacements.indexOf("Å") == -1 && replacements.indexOf("Ä") == -1 && replacements.indexOf("Ö") == -1) { replacements = new String(replacements.getBytes(fromEncoding), toEncoding); } } } catch(Exception e) { e.printStackTrace(); } Properties properties = new Properties(); try { properties.load(new ByteArrayInputStream(replacements.getBytes("ISO-8859-1"))); Iterator propertySetIterator = properties.keySet().iterator(); while(propertySetIterator.hasNext()) { String key = (String)propertySetIterator.next(); String value = properties.getProperty(key); replaceMap.put(key, value); } } catch(Exception e) { logger.error("Error loading properties from string. Reason:" + e.getMessage()); e.printStackTrace(); } ImportController.getController().importRepository(db, map, file, encoding, version, onlyLatestVersions, false, contentIdMap, siteNodeIdMap, allContentIds, replaceMap, mergeExistingRepositories); db.commit(); db.close(); Iterator allContentIdsIterator = allContentIds.iterator(); while(allContentIdsIterator.hasNext()) { Integer contentId = (Integer)allContentIdsIterator.next(); try { db = CastorDatabaseService.getDatabase(); db.begin(); Content content = ContentController.getContentController().getContentWithId(contentId, db); ImportController.getController().updateContentVersions(content, contentIdMap, siteNodeIdMap, onlyLatestVersions, new HashMap()); //updateContentVersions(content, contentIdMap, siteNodeIdMap); db.commit(); } catch(Exception e) { try { db.rollback(); } catch(Exception e2) { e2.printStackTrace(); } logger.error("An error occurred when updating content version for content: " + e.getMessage(), e); } finally { db.close(); } } } catch ( Exception e) { try { db.rollback(); db.close(); } catch (Exception e1) { logger.error("An error occurred when importing a repository: " + e.getMessage(), e); throw new SystemException("An error occurred when importing a repository: " + e.getMessage(), e); } logger.error("An error occurred when importing a repository: " + e.getMessage(), e); throw new SystemException("An error occurred when importing a repository: " + e.getMessage(), e); } return "success"; } /** * This handles the actual importing. */ protected String importV3(File file) throws Exception { String exportId = "Import_" + visualFormatter.formatDate(new Date(), "yyyy-MM-dd_HHmm"); ProcessBean processBean = ProcessBean.createProcessBean(ImportRepositoryAction.class.getName(), exportId); OptimizedImportController.importRepositories(file, this.onlyLatestVersions, this.standardReplacement, this.replacements, processBean); return "successRedirectToProcesses"; } /** * This handles copying of a repository. */ public String doCopy() throws Exception { String exportId = "Copy_Repository_" + visualFormatter.formatDate(new Date(), "yyyy-MM-dd_HHmm"); ProcessBean processBean = ProcessBean.createProcessBean(ImportRepositoryAction.class.getName(), exportId); CopyRepositoryController.importRepositories(getRequest().getParameterValues("repositoryId"), this.getInfoGluePrincipal(), this.onlyLatestVersions, this.standardReplacement, this.replacements, processBean); return "successRedirectToProcesses"; /* File file = null; try { Mapping map = new Mapping(); String exportFormat = CmsPropertyHandler.getExportFormat(); String requestExportFormat = ""+getRequest().getParameter("exportFormat"); if(exportFormat.equalsIgnoreCase("3") || this.exportFormat.equals("3") || requestExportFormat.equals("3")) { String[] repositories = getRequest().getParameterValues("repositoryId"); String exportId = "Copy_Import_" + visualFormatter.formatDate(new Date(), "yyyy-MM-dd_HHmm"); ProcessBean processBean = ProcessBean.createProcessBean(ImportRepositoryAction.class.getName(), exportId); OptimizedExportController.copy(repositories, -1, false, null, processBean, onlyLatestVersions, standardReplacement, replacements); return "successRedirectToProcesses"; } logger.info("MappingFile:" + CastorDatabaseService.class.getResource("/xml_mapping_site_2.5.xml").toString()); map.loadMapping(CastorDatabaseService.class.getResource("/xml_mapping_site_2.5.xml").toString()); // All ODMG database access requires a transaction db.begin(); List<SiteNode> siteNodes = new ArrayList<SiteNode>(); List<Content> contents = new ArrayList<Content>(); Hashtable<String,String> allRepositoryProperties = new Hashtable<String,String>(); Hashtable<String,String> allSiteNodeProperties = new Hashtable<String,String>(); Hashtable<String,String> allContentProperties = new Hashtable<String,String>(); List<AccessRight> allAccessRights = new ArrayList<AccessRight>(); //List<AccessRight> allAccessRights = AccessRightController.getController().getAllAccessRightListForExportReadOnly(db); //TEST Map args = new HashMap(); args.put("globalKey", "infoglue"); PropertySet ps = PropertySetManager.getInstance("jdbc", args); //END TEST String names = ""; Repository repository = RepositoryController.getController().getRepositoryWithId(repositoryId, db); SiteNode siteNode = SiteNodeController.getController().getRootSiteNode(repositoryId, db); Content content = ContentController.getContentController().getRootContent(repositoryId, db); InterceptionPointVO interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName("Repository.Read", db); if(interceptionPointVO != null) allAccessRights.addAll(AccessRightController.getController().getAccessRightListOnlyReadOnly(interceptionPointVO.getId(), repository.getId().toString(), db)); interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName("Repository.Write", db); if(interceptionPointVO != null) allAccessRights.addAll(AccessRightController.getController().getAccessRightListOnlyReadOnly(interceptionPointVO.getId(), repository.getId().toString(), db)); interceptionPointVO = InterceptionPointController.getController().getInterceptionPointVOWithName("Repository.ReadForBinding", db); if(interceptionPointVO != null) allAccessRights.addAll(AccessRightController.getController().getAccessRightListOnlyReadOnly(interceptionPointVO.getId(), repository.getId().toString(), db)); ExportRepositoryAction.getContentPropertiesAndAccessRights(ps, allContentProperties, allAccessRights, content, db); ExportRepositoryAction.getSiteNodePropertiesAndAccessRights(ps, allSiteNodeProperties, allAccessRights, siteNode, db); siteNodes.add(siteNode); contents.add(content); names = names + "_" + repository.getName(); allRepositoryProperties.putAll(OptimizedExportController.getRepositoryProperties(ps, repositoryId)); List contentTypeDefinitions = ContentTypeDefinitionController.getController().getContentTypeDefinitionList(db); List categories = CategoryController.getController().getAllActiveCategories(); InfoGlueExportImpl infoGlueExportImpl = new InfoGlueExportImpl(); VisualFormatter visualFormatter = new VisualFormatter(); names = new VisualFormatter().replaceNonAscii(names, '_'); String fileName = "RepositoryCopy_" + names + "_" + visualFormatter.formatDate(new Date(), "yyyy-MM-dd_HHmm") + ".xml"; String filePath = CmsPropertyHandler.getDigitalAssetPath(); String fileSystemName = filePath + File.separator + fileName; String encoding = "UTF-8"; file = new File(fileSystemName); FileOutputStream fos = new FileOutputStream(file); BufferedOutputStream bos = new BufferedOutputStream(fos); OutputStreamWriter osw = new OutputStreamWriter(bos, encoding); Marshaller marshaller = new Marshaller(osw); marshaller.setMapping(map); marshaller.setEncoding(encoding); DigitalAssetBytesHandler.setMaxSize(-1); infoGlueExportImpl.getRootContent().addAll(contents); infoGlueExportImpl.getRootSiteNode().addAll(siteNodes); infoGlueExportImpl.setContentTypeDefinitions(new ArrayList()); infoGlueExportImpl.setCategories(new ArrayList()); infoGlueExportImpl.setRepositoryProperties(allRepositoryProperties); infoGlueExportImpl.setContentProperties(allContentProperties); infoGlueExportImpl.setSiteNodeProperties(allSiteNodeProperties); infoGlueExportImpl.setAccessRights(allAccessRights); marshaller.marshal(infoGlueExportImpl); osw.flush(); osw.close(); db.commit(); db.close(); db = CastorDatabaseService.getDatabase(); db.begin(); Map contentIdMap = new HashMap(); Map siteNodeIdMap = new HashMap(); List allContentIds = new ArrayList(); Map<String,String> replaceMap = new HashMap<String,String>(); Properties properties = new Properties(); try { properties.load(new ByteArrayInputStream(replacements.getBytes("ISO-8859-1"))); Iterator propertySetIterator = properties.keySet().iterator(); while(propertySetIterator.hasNext()) { String key = (String)propertySetIterator.next(); String value = properties.getProperty(key); replaceMap.put(key, value); } } catch(Exception e) { logger.error("Error loading properties from string. Reason:" + e.getMessage()); e.printStackTrace(); } ImportController.getController().importRepository(db, map, file, encoding, 2, onlyLatestVersions, true, contentIdMap, siteNodeIdMap, allContentIds, replaceMap, false); db.commit(); db.close(); Iterator allContentIdsIterator = allContentIds.iterator(); while(allContentIdsIterator.hasNext()) { Integer contentId = (Integer)allContentIdsIterator.next(); try { db = CastorDatabaseService.getDatabase(); db.begin(); Content createdContent = ContentController.getContentController().getContentWithId(contentId, db); ImportController.getController().updateContentVersions(createdContent, contentIdMap, siteNodeIdMap, onlyLatestVersions, replaceMap); db.commit(); } catch(Exception e) { try { db.rollback(); } catch(Exception e2) { e2.printStackTrace(); } logger.error("An error occurred when updating content version for content: " + e.getMessage(), e); } finally { db.close(); } } } catch ( Exception e) { try { db.rollback(); db.close(); } catch (Exception e1) { logger.error("An error occurred when importing a repository: " + e.getMessage(), e); throw new SystemException("An error occurred when importing a repository: " + e.getMessage(), e); } logger.error("An error occurred when importing a repository: " + e.getMessage(), e); throw new SystemException("An error occurred when importing a repository: " + e.getMessage(), e); } finally { if(file != null) file.delete(); } return "success"; */ } public String getOnlyLatestVersions() { return onlyLatestVersions; } public void setOnlyLatestVersions(String onlyLatestVersions) { this.onlyLatestVersions = onlyLatestVersions; } public Integer getRepositoryId() { return repositoryId; } public void setRepositoryId(Integer repositoryId) { this.repositoryId = repositoryId; } public String getStandardReplacement() { return this.standardReplacement; } public void setReplacements(String replacements) { this.replacements = replacements; } public void setMergeExistingRepositories(Boolean mergeExistingRepositories) { this.mergeExistingRepositories = mergeExistingRepositories; } public String getExportFormat() { return exportFormat; } public void setExportFormat(String exportFormat) { this.exportFormat = exportFormat; } public void setProcessId(String processId) { this.processId = processId; } public List<ProcessBean> getProcessBeans() { return ProcessBean.getProcessBeans(ImportRepositoryAction.class.getName()); } public String getStatusAsJSON() { Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC) .setDateFormat("dd MMM HH:mm:ss").create(); JsonObject object = new JsonObject(); try { List<ProcessBean> processes = getProcessBeans(); Type processBeanListType = new TypeToken<List<ProcessBean>>() {}.getType(); JsonElement list = gson.toJsonTree(processes, processBeanListType); object.add("processes", list); object.addProperty("memoryMessage", getMemoryUsageAsText()); } catch (Throwable t) { logger.error("Error when generating repository export status report as JSON.", t); JsonObject error = new JsonObject(); error.addProperty("message", t.getMessage()); error.addProperty("type", t.getClass().getSimpleName()); object.add("error", error); } return gson.toJson(object); } }