/** * 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.beans.config.ContentRepository; import info.magnolia.cms.core.Path; import info.magnolia.cms.core.SystemProperty; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.FileFilterUtils; import org.apache.commons.io.filefilter.IOFileFilter; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Bootstrapper: loads content from xml when a magnolia is started with an uninitialized repository. * * @author Fabrizio Giustina * @version $Revision$ ($Author$) */ public final class Bootstrapper { private static final Logger log = LoggerFactory.getLogger(Bootstrapper.class); /** * Filter used to provide an additional filtering for the bootstrap files. * * @author philipp */ public interface BootstrapFilter { boolean accept(String filename); } private Bootstrapper() { // unused } /** * Repositories appears to be empty and the <code>"magnolia.bootstrap.dir</code> directory is configured in * web.xml. Loops over all the repositories and try to load any xml file found in a subdirectory with the same name * of the repository. For example the <code>config</code> repository will be initialized using all the * <code>*.xml</code> files found in <code>"magnolia.bootstrap.dir</code><strong>/config</strong> directory. * * @param bootdirs bootstrap dir */ public static void bootstrapRepositories(String[] bootdirs, BootstrapFilter filter) { log.info("Trying to initialize repositories from: \n {}", StringUtils.join(bootdirs, "\n ")); Iterator repositoryNames = ContentRepository.getAllRepositoryNames(); while (repositoryNames.hasNext()) { String repositoryName = (String) repositoryNames.next(); if (!bootstrapRepository(bootdirs, repositoryName, filter)) { // exeption was already logged break; } log.info("Repository [{}] has been initialized.", repositoryName); } } /** * Bootstrap a specific repository. */ public static boolean bootstrapRepository(String[] bootdirs, String repositoryName, BootstrapFilter filter) { Set<File> xmlfileset = getBootstrapFiles(bootdirs, repositoryName, filter); if (xmlfileset.isEmpty()) { log.debug("No bootstrap files found for repository [{}], skipping...", repositoryName); return true; } log.info("Trying to import content from {} files into repository [{}]", Integer.toString(xmlfileset.size()), repositoryName); final File[] files = xmlfileset.toArray(new File[xmlfileset.size()]); return bootstrapFiles(repositoryName, files); } /** * Bootstrap the array of files. */ private static boolean bootstrapFiles(String repositoryName, File[] files) { try { for (int k = 0; k < files.length; k++) { File xmlFile = files[k]; log.debug("Importing {}", xmlFile); DataTransporter.executeBootstrapImport(xmlFile, repositoryName); } } catch (IOException ioe) { log.error(ioe.getMessage(), ioe); } catch (OutOfMemoryError e) { int maxMem = (int) (Runtime.getRuntime().maxMemory() / 1024 / 1024); int needed = Math.max(256, maxMem + 128); log.error("Unable to complete bootstrapping: out of memory.\n" + "{} MB were not enough, try to increase the amount of memory available by adding the -Xmx{}m parameter to the server startup script.\n" + "You will need to completely remove the Magnolia webapp before trying again", Integer.toString(maxMem), Integer.toString(needed)); return false; } return true; } /** * Get the files to bootstrap. The method garantees that only one file is imported if it occures twice in the * bootstrap dir. The set is returned sorted, so that the execution fo the import will import the upper most nodes * first. This is done using the filelength. * * @return the sorted set */ private static SortedSet<File> getBootstrapFiles(String[] bootdirs, final String repositoryName, final BootstrapFilter filter) { SortedSet<File> xmlfileset = new TreeSet<File>(new BootstrapFilesComparator()); for (int j = 0; j < bootdirs.length; j++) { String bootdir = bootdirs[j]; File xmldir = new File(bootdir); if (!xmldir.exists() || !xmldir.isDirectory()) { continue; } @SuppressWarnings("unchecked") Collection<File> files = FileUtils.listFiles(xmldir, new IOFileFilter() { @Override public boolean accept(File file) { return accept(file.getParentFile(), file.getName()); } @Override public boolean accept(File dir, String name) { return name.startsWith(repositoryName + ".") && filter.accept(name) && (name.endsWith(DataTransporter.XML) || name.endsWith(DataTransporter.ZIP) || name .endsWith(DataTransporter.GZ) || name.endsWith(DataTransporter.PROPERTIES)); } }, FileFilterUtils.trueFileFilter()); xmlfileset.addAll(files); } return xmlfileset; } /** * Return the standard bootstrap dirs defined in the <code>magnolia.properties</code> file. * @return Array of directory names */ public static String[] getBootstrapDirs() { String bootdirProperty = SystemProperty.getProperty(SystemProperty.MAGNOLIA_BOOTSTRAP_ROOTDIR); if (StringUtils.isEmpty(bootdirProperty)) { return new String[0]; } String[] bootDirs = StringUtils.split(bootdirProperty); // converts to absolute paths for (int j = 0; j < bootDirs.length; j++) { bootDirs[j] = Path.getAbsoluteFileSystemPath(bootDirs[j]); } return bootDirs; } }