]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/plugins/org.argeo.jcr.ui.explorer/src/main/java/org/argeo/jcr/ui/explorer/wizards/ImportFileSystemWizard.java
6653a80aa1e71fc1a673203773e2586ba61263bc
[lgpl/argeo-commons.git] / server / plugins / org.argeo.jcr.ui.explorer / src / main / java / org / argeo / jcr / ui / explorer / wizards / ImportFileSystemWizard.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.jcr.ui.explorer.wizards;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20
21 import javax.jcr.Binary;
22 import javax.jcr.Node;
23 import javax.jcr.Property;
24 import javax.jcr.nodetype.NodeType;
25
26 import org.apache.commons.io.FileUtils;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.argeo.ArgeoException;
31 import org.argeo.eclipse.ui.ErrorFeedback;
32 import org.argeo.eclipse.ui.specific.ImportToServerWizardPage;
33 import org.eclipse.core.runtime.IProgressMonitor;
34 import org.eclipse.jface.dialogs.MessageDialog;
35 import org.eclipse.jface.operation.IRunnableWithProgress;
36 import org.eclipse.jface.wizard.Wizard;
37
38 public class ImportFileSystemWizard extends Wizard {
39 private final static Log log = LogFactory
40 .getLog(ImportFileSystemWizard.class);
41
42 private ImportToServerWizardPage importPage;
43 private final Node folder;
44
45 public ImportFileSystemWizard(Node folder) {
46 this.folder = folder;
47 setWindowTitle("Import from file system");
48 }
49
50 @Override
51 public void addPages() {
52 importPage = new ImportToServerWizardPage();
53 addPage(importPage);
54 setNeedsProgressMonitor(importPage.getNeedsProgressMonitor());
55 }
56
57 /**
58 * Called when the user click on 'Finish' in the wizard. The real upload to
59 * the JCR repository is done here.
60 */
61 @Override
62 public boolean performFinish() {
63
64 // Initialization
65 final String objectType = importPage.getObjectType();
66 final String objectPath = importPage.getObjectPath();
67
68 // We do not display a progress bar for one file only
69 if (ImportToServerWizardPage.FILE_ITEM_TYPE.equals(objectType)) {
70 // In Rap we must force the "real" upload of the file
71 importPage.performFinish();
72 try {
73 Node fileNode = folder.addNode(importPage.getObjectName(),
74 NodeType.NT_FILE);
75 Node resNode = fileNode.addNode(Property.JCR_CONTENT,
76 NodeType.NT_RESOURCE);
77 Binary binary = null;
78 try {
79 binary = folder.getSession().getValueFactory()
80 .createBinary(importPage.getFileInputStream());
81 resNode.setProperty(Property.JCR_DATA, binary);
82 } finally {
83 if (binary != null)
84 binary.dispose();
85 IOUtils.closeQuietly(importPage.getFileInputStream());
86 }
87 folder.getSession().save();
88 } catch (Exception e) {
89 e.printStackTrace();
90 return false;
91 }
92 return true;
93 } else if (ImportToServerWizardPage.FOLDER_ITEM_TYPE.equals(objectType)) {
94 if (objectPath == null || !new File(objectPath).exists()) {
95 ErrorFeedback.show("Directory " + objectPath + " does not exist");
96 return false;
97 }
98
99 Boolean failed = false;
100 final File dir = new File(objectPath).getAbsoluteFile();
101 final Long sizeB = directorySize(dir, 0l);
102 final Stats stats = new Stats();
103 Long begin = System.currentTimeMillis();
104 try {
105 getContainer().run(true, true, new IRunnableWithProgress() {
106 public void run(IProgressMonitor monitor) {
107 try {
108 Integer sizeKB = (int) (sizeB / FileUtils.ONE_KB);
109 monitor.beginTask("", sizeKB);
110 importDirectory(folder, dir, monitor, stats);
111 monitor.done();
112 } catch (Exception e) {
113 if (e instanceof RuntimeException)
114 throw (RuntimeException) e;
115 else
116 throw new ArgeoException("Cannot import "
117 + objectPath, e);
118 }
119 }
120 });
121 } catch (Exception e) {
122 ErrorFeedback.show("Cannot import " + objectPath, e);
123 failed = true;
124 }
125
126 Long duration = System.currentTimeMillis() - begin;
127 Long durationS = duration / 1000l;
128 String durationStr = (durationS / 60) + " min " + (durationS % 60)
129 + " s";
130 StringBuffer message = new StringBuffer("Imported\n");
131 message.append(stats.fileCount).append(" files\n");
132 message.append(stats.dirCount).append(" directories\n");
133 message.append(FileUtils.byteCountToDisplaySize(stats.sizeB));
134 if (failed)
135 message.append(" of planned ").append(
136 FileUtils.byteCountToDisplaySize(sizeB));
137 message.append("\n");
138 message.append("in ").append(durationStr).append("\n");
139 if (failed)
140 MessageDialog.openError(getShell(), "Import failed",
141 message.toString());
142 else
143 MessageDialog.openInformation(getShell(), "Import successful",
144 message.toString());
145
146 return true;
147 }
148 return false;
149
150 }
151
152 /** Recursively computes the size of the directory in bytes. */
153 protected Long directorySize(File dir, Long currentSize) {
154 Long size = currentSize;
155 File[] files = dir.listFiles();
156 for (File file : files) {
157 if (file.isDirectory()) {
158 size = directorySize(file, size);
159 } else {
160 size = size + file.length();
161 }
162 }
163 return size;
164 }
165
166 /**
167 * Import recursively a directory and its content to the repository.
168 */
169 protected void importDirectory(Node folder, File dir,
170 IProgressMonitor monitor, Stats stats) {
171 try {
172 File[] files = dir.listFiles();
173 for (File file : files) {
174 if (file.isDirectory()) {
175 Node childFolder = folder.addNode(file.getName(),
176 NodeType.NT_FOLDER);
177 importDirectory(childFolder, file, monitor, stats);
178 folder.getSession().save();
179 stats.dirCount++;
180 } else {
181 Long fileSize = file.length();
182
183 // we skip tempory files that are created by apps when a
184 // file is being edited.
185 // TODO : make this configurable.
186 if (file.getName().lastIndexOf('~') != file.getName()
187 .length() - 1) {
188
189 monitor.subTask(file.getName() + " ("
190 + FileUtils.byteCountToDisplaySize(fileSize)
191 + ") " + file.getCanonicalPath());
192 try {
193 Node fileNode = folder.addNode(file.getName(),
194 NodeType.NT_FILE);
195 Node resNode = fileNode.addNode(
196 Property.JCR_CONTENT, NodeType.NT_RESOURCE);
197 Binary binary = null;
198 try {
199 binary = folder
200 .getSession()
201 .getValueFactory()
202 .createBinary(new FileInputStream(file));
203 resNode.setProperty(Property.JCR_DATA, binary);
204 } finally {
205 if (binary != null)
206 binary.dispose();
207 }
208 folder.getSession().save();
209 stats.fileCount++;
210 stats.sizeB = stats.sizeB + fileSize;
211 } catch (Exception e) {
212 log.warn("Import of "
213 + file
214 + " ("
215 + FileUtils
216 .byteCountToDisplaySize(fileSize)
217 + ") failed: " + e);
218 folder.getSession().refresh(false);
219 }
220 monitor.worked((int) (fileSize / FileUtils.ONE_KB));
221 }
222 }
223 }
224 } catch (Exception e) {
225 throw new ArgeoException("Cannot import " + dir + " to " + folder,
226 e);
227 }
228 }
229
230 static class Stats {
231 public Long fileCount = 0l;
232 public Long dirCount = 0l;
233 public Long sizeB = 0l;
234 }
235 }