View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.importexport;
35  
36  import info.magnolia.cms.core.Content;
37  import info.magnolia.cms.core.HierarchyManager;
38  import info.magnolia.cms.util.SiblingsHelper;
39  import info.magnolia.cms.util.StringLengthComparator;
40  import info.magnolia.context.MgnlContext;
41  
42  import java.io.File;
43  import java.io.FileOutputStream;
44  import java.io.IOException;
45  import java.io.InputStream;
46  import java.util.ArrayList;
47  import java.util.Arrays;
48  import java.util.Collections;
49  import java.util.Iterator;
50  import java.util.List;
51  
52  import javax.jcr.RepositoryException;
53  
54  import org.apache.commons.io.IOUtils;
55  import org.apache.commons.lang.StringUtils;
56  import org.slf4j.Logger;
57  import org.slf4j.LoggerFactory;
58  
59  
60  /**
61   * Utilities to bootstrap set of files and/or to export content into a specified directory.
62   * @version $Revision$ ($Author$)
63   */
64  public class BootstrapUtil {
65      private static final Logger log = LoggerFactory.getLogger(BootstrapUtil.class);
66  
67      public static void bootstrap(String[] resourceNames, int importUUIDBehavior) throws IOException, RepositoryException {
68          // sort by length --> import parent node first
69          List<String> list = new ArrayList<String>(Arrays.asList(resourceNames));
70  
71          Collections.sort(list, new StringLengthComparator());
72  
73          for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
74              String resourceName = iter.next();
75  
76              String name = getFilenameFromResource(resourceName, ".xml");
77              String repository = getWorkspaceNameFromResource(resourceName);
78              String pathName = getPathnameFromResource(resourceName);
79              String fullPath = getFullpathFromResource(resourceName);
80              String nodeName = StringUtils.substringAfterLast(fullPath, "/");
81  
82              log.debug("Will bootstrap {}", resourceName);
83  
84              final InputStream stream = BootstrapUtil.class.getResourceAsStream(resourceName);
85              if (stream == null) {
86                  throw new IOException("Can't find resource to bootstrap at " + resourceName);
87              }
88  
89              // if the node already exists we will keep the order
90              String nameOfNodeAfterTheImportedNode = null;
91  
92              final HierarchyManager hm = MgnlContext.getHierarchyManager(repository);
93  
94              // if the path already exists --> delete it
95              try {
96  
97                  // HM can be null if module is not properly registered and the repository has not been created
98                  if (hm != null && hm.isExist(fullPath)) {
99                      // but keep the order
100                     Content node = hm.getContent(fullPath);
101                     SiblingsHelper siblings = SiblingsHelper.of(node);
102                     if(!siblings.isLast()){
103                         nameOfNodeAfterTheImportedNode = siblings.next().getName();
104                     }
105 
106                     hm.delete(fullPath);
107                     log.warn("Deleted already existing node for bootstrapping: {}", fullPath);
108                 }
109             } catch (RepositoryException e) {
110                 throw new RepositoryException("Can't check existence of node for bootstrap file: [" + name + "]", e);
111             }
112 
113             DataTransporter.importXmlStream(stream, repository, pathName, name, false, importUUIDBehavior, false, true);
114 
115             if(nameOfNodeAfterTheImportedNode != null){
116                 Content newNode = hm.getContent(fullPath);
117                 newNode.getParent().orderBefore(nodeName, nameOfNodeAfterTheImportedNode);
118             }
119 
120         }
121     }
122 
123     public static void export(Content content, File directory) throws IOException, RepositoryException{
124         String fileName = content.getWorkspace().getName() + DataTransporter.createExportPath(content.getHandle()) + ".xml";
125         File file = new File(directory, fileName);
126         FileOutputStream out = new FileOutputStream(file);
127         try{
128             DataTransporter.executeExport(out,false, true, content.getWorkspace().getSession(), content.getHandle(), content.getWorkspace().getName(), DataTransporter.XML);
129         }
130         finally{
131             IOUtils.closeQuietly(out);
132         }
133     }
134 
135     /**
136      * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> it will return <code>config</code>.
137      */
138     public static String getWorkspaceNameFromResource(final String resourcePath) {
139         String resourceName = StringUtils.replace(resourcePath, "\\", "/");
140 
141         String name = getFilenameFromResource(resourceName, ".xml");
142         String fullPath = DataTransporter.revertExportPath(name);
143         return StringUtils.substringBefore(fullPath, "/");
144     }
145 
146     /**
147      * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> it will return <code>/server/i18n</code>.
148      */
149     public static String getFullpathFromResource(final String resourcePath) {
150         String resourceName = StringUtils.replace(resourcePath, "\\", "/");
151 
152         String name = getFilenameFromResource(resourceName, ".xml");
153         String fullPath = DataTransporter.revertExportPath(name);
154         String repository = StringUtils.substringBefore(fullPath, "/");
155 
156         return StringUtils.removeStart(fullPath, repository);
157     }
158 
159     /**
160      * I.e. given a resource path like <code>/mgnl-bootstrap/foo/config.server.i18n.xml</code> it will return <code>/server</code>.
161      */
162     public static String getPathnameFromResource(final String resourcePath) {
163         String resourceName = StringUtils.replace(resourcePath, "\\", "/");
164 
165         String name = getFilenameFromResource(resourceName, ".xml");
166         String fullPath = DataTransporter.revertExportPath(name);
167         String pathName = StringUtils.substringAfter(StringUtils.substringBeforeLast(fullPath, "/"), "/");
168 
169         if(!pathName.startsWith("/")) {
170             pathName = "/" + pathName;
171         }
172         return pathName;
173     }
174 
175     /**
176      * 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).
177      * If extension is <code>null</code>, it defaults to <code>.xml</code>.
178      */
179     public static String getFilenameFromResource(final String resourcePath, final String extension) {
180         String ext = StringUtils.defaultIfEmpty(extension, ".xml");
181         String tmpResourcePath = resourcePath;
182         if(resourcePath.contains("/")) {
183             tmpResourcePath = StringUtils.substringAfterLast(resourcePath, "/");
184         }
185         return StringUtils.removeEnd(tmpResourcePath, ext.startsWith(".") ? ext : "." + ext);
186     }
187 
188 }
189