/** * This file Copyright (c) 2003-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.importexport; import info.magnolia.cms.core.Content; import info.magnolia.cms.core.HierarchyManager; import info.magnolia.cms.util.SiblingsHelper; import info.magnolia.cms.util.StringLengthComparator; import info.magnolia.context.MgnlContext; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import javax.jcr.RepositoryException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utilities to bootstrap set of files and/or to export content into a specified directory. * @version $Revision$ ($Author$) */ public class BootstrapUtil { private static final Logger log = LoggerFactory.getLogger(BootstrapUtil.class); public static void bootstrap(String[] resourceNames, int importUUIDBehavior) throws IOException, RepositoryException { // sort by length --> import parent node first List<String> list = new ArrayList<String>(Arrays.asList(resourceNames)); Collections.sort(list, new StringLengthComparator()); for (Iterator<String> iter = list.iterator(); iter.hasNext();) { String resourceName = iter.next(); String name = getFilenameFromResource(resourceName, ".xml"); String repository = getWorkspaceNameFromResource(resourceName); String pathName = getPathnameFromResource(resourceName); String fullPath = getFullpathFromResource(resourceName); String nodeName = StringUtils.substringAfterLast(fullPath, "/"); log.debug("Will bootstrap {}", resourceName); final InputStream stream = BootstrapUtil.class.getResourceAsStream(resourceName); if (stream == null) { throw new IOException("Can't find resource to bootstrap at " + resourceName); } // if the node already exists we will keep the order String nameOfNodeAfterTheImportedNode = null; final HierarchyManager hm = MgnlContext.getHierarchyManager(repository); // if the path already exists --> delete it try { // HM can be null if module is not properly registered and the repository has not been created if (hm != null && hm.isExist(fullPath)) { // but keep the order Content node = hm.getContent(fullPath); SiblingsHelper siblings = SiblingsHelper.of(node); if(!siblings.isLast()){ nameOfNodeAfterTheImportedNode = siblings.next().getName(); } hm.delete(fullPath); log.warn("Deleted already existing node for bootstrapping: {}", fullPath); } } catch (RepositoryException e) { throw new RepositoryException("Can't check existence of node for bootstrap file: [" + name + "]", e); } DataTransporter.importXmlStream(stream, repository, pathName, name, false, importUUIDBehavior, false, true); if(nameOfNodeAfterTheImportedNode != null){ Content newNode = hm.getContent(fullPath); newNode.getParent().orderBefore(nodeName, nameOfNodeAfterTheImportedNode); } } } public static void export(Content content, File directory) throws IOException, RepositoryException{ String fileName = content.getWorkspace().getName() + DataTransporter.createExportPath(content.getHandle()) + ".xml"; File file = new File(directory, fileName); FileOutputStream out = new FileOutputStream(file); try{ DataTransporter.executeExport(out,false, true, content.getWorkspace().getSession(), content.getHandle(), content.getWorkspace().getName(), DataTransporter.XML); } finally{ IOUtils.closeQuietly(out); } } /** * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> it will return <code>config</code>. */ public static String getWorkspaceNameFromResource(final String resourcePath) { String resourceName = StringUtils.replace(resourcePath, "\\", "/"); String name = getFilenameFromResource(resourceName, ".xml"); String fullPath = DataTransporter.revertExportPath(name); return StringUtils.substringBefore(fullPath, "/"); } /** * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> it will return <code>/server/i18n</code>. */ public static String getFullpathFromResource(final String resourcePath) { String resourceName = StringUtils.replace(resourcePath, "\\", "/"); String name = getFilenameFromResource(resourceName, ".xml"); String fullPath = DataTransporter.revertExportPath(name); String repository = StringUtils.substringBefore(fullPath, "/"); return StringUtils.removeStart(fullPath, repository); } /** * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> it will return <code>/server</code>. */ public static String getPathnameFromResource(final String resourcePath) { String resourceName = StringUtils.replace(resourcePath, "\\", "/"); String name = getFilenameFromResource(resourceName, ".xml"); String fullPath = DataTransporter.revertExportPath(name); String pathName = StringUtils.substringAfter(StringUtils.substringBeforeLast(fullPath, "/"), "/"); if(!pathName.startsWith("/")) { pathName = "/" + pathName; } return pathName; } /** * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> and <code>.xml</code> extension it will return <code>config.server.i18n</code> (no trailing dot). * If extension is <code>null</code>, it defaults to <code>.xml</code>. */ public static String getFilenameFromResource(final String resourcePath, final String extension) { String ext = StringUtils.defaultIfEmpty(extension, ".xml"); String tmpResourcePath = resourcePath; if(resourcePath.contains("/")) { tmpResourcePath = StringUtils.substringAfterLast(resourcePath, "/"); } return StringUtils.removeEnd(tmpResourcePath, ext.startsWith(".") ? ext : "." + ext); } }