1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.importexport;
35
36 import info.magnolia.cms.util.StringLengthComparator;
37 import info.magnolia.context.MgnlContext;
38 import info.magnolia.importexport.command.JcrExportCommand;
39 import info.magnolia.importexport.command.JcrImportCommand;
40 import info.magnolia.jcr.util.NodeNameHelper;
41 import info.magnolia.jcr.util.NodeTypes;
42 import info.magnolia.jcr.util.NodeUtil;
43 import info.magnolia.objectfactory.Components;
44 import info.magnolia.repository.DefaultRepositoryManager;
45 import info.magnolia.repository.RepositoryManager;
46
47 import java.io.File;
48 import java.io.FileOutputStream;
49 import java.io.IOException;
50 import java.io.InputStream;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.Iterator;
55 import java.util.List;
56
57 import javax.jcr.Node;
58 import javax.jcr.RepositoryException;
59 import javax.jcr.Session;
60
61 import org.apache.commons.io.FilenameUtils;
62 import org.apache.commons.io.IOUtils;
63 import org.apache.commons.lang3.StringUtils;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67
68
69
70 public class BootstrapUtil {
71 private static final Logger log = LoggerFactory.getLogger(BootstrapUtil.class);
72
73 public static void bootstrap(String[] resourceNames, int importUUIDBehavior) throws IOException, RepositoryException {
74
75 List<String> list = new ArrayList<>(Arrays.asList(resourceNames));
76 if (list.contains(null)) {
77 throw new IllegalArgumentException("Resource names contain a <null> entry that cannot be processed.");
78 }
79
80 Collections.sort(list, new StringLengthComparator());
81
82 for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
83 bootstrap(iter.next(), null, importUUIDBehavior);
84 }
85 }
86
87 public static void bootstrap(String resourceName, String subPath, int importUUIDBehavior) throws IOException, RepositoryException {
88 String name = getFilenameFromResource(resourceName, null);
89 String workspace = getWorkspaceNameFromResource(resourceName);
90 String fullPath = getFullpathFromResource(resourceName);
91 if (subPath != null) {
92 fullPath += "/" + StringUtils.substringAfter(StringUtils.removeStart(StringUtils.removeEnd(subPath, "/"), "/"), "/");
93 }
94 String parentPath = StringUtils.substringBeforeLast(fullPath, "/");
95 if (StringUtils.isEmpty(parentPath)) {
96 parentPath = "/";
97 }
98
99 log.debug("Will bootstrap {}", resourceName);
100
101 final InputStream stream = BootstrapUtil.class.getResourceAsStream(resourceName);
102 if (stream == null) {
103 throw new IOException("Can't find resource to bootstrap at " + resourceName);
104 }
105
106
107 String nameOfNodeAfterTheImportedNode = null;
108
109
110 RepositoryManager repoManager = Components.getComponent(RepositoryManager.class);
111 if (repoManager instanceof DefaultRepositoryManager) {
112 boolean isClusteredWorkspace = ((DefaultRepositoryManager) repoManager).isClusteredWorkspace(workspace);
113 boolean isMasterCluster = ((DefaultRepositoryManager) repoManager).isClusterMaster();
114
115 if (isClusteredWorkspace && !isMasterCluster) {
116 log.info("Skipping bootstrapping of resource '{}' because workspace '{}' is clustered and node is not cluster master ", resourceName, workspace);
117 return;
118 }
119 }
120
121 final Session session = MgnlContext.getJCRSession(workspace);
122
123 try {
124
125 if (StringUtils.isNotEmpty(fullPath) && session.nodeExists(fullPath)) {
126
127 Node node = session.getNode(fullPath);
128 if (!NodeUtil.isLastSibling(node)) {
129 nameOfNodeAfterTheImportedNode = NodeUtil.getSiblingAfter(node).getName();
130 }
131 if (node.getDepth() == 1) {
132 Node parent = node.getParent();
133 Node tmp = NodeUtil.createPath(parent, Components.getComponent(NodeNameHelper.class).getUniqueName(parent, "tmp"), NodeTypes.Content.NAME);
134 NodeUtil.moveNode(node, tmp);
135 tmp.remove();
136 } else {
137 node.remove();
138 }
139 log.warn("Deleted already existing node for bootstrapping: {}", fullPath);
140 }
141 NodeUtil.createPath(session.getRootNode(), parentPath, NodeTypes.Content.NAME);
142
143 final JcrImportCommand command = new JcrImportCommand();
144 command.setStream(stream);
145 command.setFileName(resourceName);
146 command.setRepository(workspace);
147 command.setPath(parentPath);
148 command.setImportPath(subPath);
149 command.setIdentifierBehavior(importUUIDBehavior);
150 command.setSaveAfterImport(false);
151 command.execute(MgnlContext.getInstance());
152
153 } catch (RepositoryException e) {
154 IOUtils.closeQuietly(stream);
155 throw new RepositoryException("Can't check existence of node for bootstrap file: [" + name + "]", e);
156 } catch (Exception e) {
157 throw new RuntimeException(e);
158 }
159 if (nameOfNodeAfterTheImportedNode != null) {
160 Node newNode = session.getNode(fullPath);
161 NodeUtil.orderBefore(newNode, nameOfNodeAfterTheImportedNode);
162 }
163 }
164
165 public static void export(Node content, File directory) throws IOException, RepositoryException {
166
167 Session session = content.getSession();
168 String workspace = session.getWorkspace().getName();
169 String path = content.getPath();
170 String fileName = workspace + DataTransporter.createExportPath(path) + ".xml";
171 File file = new File(directory, fileName);
172 FileOutputStream out = new FileOutputStream(file);
173 try {
174 DataTransporter.executeExport(out, false, true, session, path, workspace, DataTransporter.XML);
175 } finally {
176 IOUtils.closeQuietly(out);
177 }
178 }
179
180
181
182
183 public static String getWorkspaceNameFromResource(final String resourcePath) {
184 String resourceName = StringUtils.replace(resourcePath, "\\", "/");
185
186 String name = getFilenameFromResource(resourceName, null);
187 String fullPath = DataTransporter.revertExportPath(name);
188 return StringUtils.substringBefore(fullPath, "/");
189 }
190
191
192
193
194 public static String getFullpathFromResource(final String resourcePath) {
195 String resourceName = StringUtils.replace(resourcePath, "\\", "/");
196
197 String name = getFilenameFromResource(resourceName, null);
198 String fullPath = DataTransporter.revertExportPath(name);
199 String repository = StringUtils.substringBefore(fullPath, "/");
200
201 return StringUtils.removeStart(fullPath, repository);
202 }
203
204
205
206
207 public static String getPathnameFromResource(final String resourcePath) {
208 String resourceName = StringUtils.replace(resourcePath, "\\", "/");
209
210 String name = getFilenameFromResource(resourceName, null);
211 String fullPath = DataTransporter.revertExportPath(name);
212 String pathName = StringUtils.substringAfter(StringUtils.substringBeforeLast(fullPath, "/"), "/");
213
214 if (!pathName.startsWith("/")) {
215 pathName = "/" + pathName;
216 }
217 return pathName;
218 }
219
220
221
222
223
224 public static String getFilenameFromResource(final String resourcePath, final String extension) {
225 String resolvedExtension = extension;
226
227 if (StringUtils.isEmpty(extension)) {
228 resolvedExtension = FilenameUtils.getExtension(resourcePath);
229 if (!JcrExportCommand.Format.isSupportedExtension(resolvedExtension)) {
230 resolvedExtension = StringUtils.EMPTY;
231 }
232 }
233 String tmpResourcePath = resourcePath;
234 if (resourcePath.contains("/")) {
235 tmpResourcePath = StringUtils.substringAfterLast(resourcePath, "/");
236 }
237 return StringUtils.removeEnd(tmpResourcePath, resolvedExtension.startsWith(".") ? resolvedExtension : "." + resolvedExtension);
238 }
239
240 }