View Javadoc
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.cms.ui.workbench.internal.jcr.commands;
17  
18  import java.io.File;
19  import java.io.FileOutputStream;
20  import java.io.IOException;
21  import java.nio.file.Files;
22  import java.nio.file.Path;
23  import java.text.DateFormat;
24  import java.text.SimpleDateFormat;
25  import java.util.ArrayList;
26  import java.util.GregorianCalendar;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  import javax.jcr.Node;
31  import javax.jcr.NodeIterator;
32  import javax.jcr.RepositoryException;
33  
34  import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem;
35  import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
36  import org.argeo.eclipse.ui.EclipseUiException;
37  import org.argeo.eclipse.ui.EclipseUiUtils;
38  import org.argeo.jcr.JcrUtils;
39  import org.eclipse.core.commands.AbstractHandler;
40  import org.eclipse.core.commands.ExecutionEvent;
41  import org.eclipse.core.commands.ExecutionException;
42  import org.eclipse.jface.viewers.ISelection;
43  import org.eclipse.jface.viewers.IStructuredSelection;
44  import org.eclipse.jface.window.Window;
45  import org.eclipse.jface.wizard.Wizard;
46  import org.eclipse.jface.wizard.WizardDialog;
47  import org.eclipse.jface.wizard.WizardPage;
48  import org.eclipse.swt.SWT;
49  import org.eclipse.swt.events.ModifyEvent;
50  import org.eclipse.swt.events.ModifyListener;
51  import org.eclipse.swt.layout.GridData;
52  import org.eclipse.swt.layout.GridLayout;
53  import org.eclipse.swt.widgets.Button;
54  import org.eclipse.swt.widgets.Composite;
55  import org.eclipse.swt.widgets.Label;
56  import org.eclipse.swt.widgets.Shell;
57  import org.eclipse.swt.widgets.Text;
58  import org.eclipse.ui.handlers.HandlerUtil;
59  
60  /**
61   * First draft of a wizard that enable configurable recursive dump of the
62   * current selected Node (Only one at a time). Enable among other to export
63   * children Nodes and to choose to export binaries or not. It is useful to
64   * retrieve business data from live systems to prepare migration or test locally
65   */
66  public class ConfigurableNodeDump extends AbstractHandler {
67  	public final static String ID = WorkbenchUiPlugin.PLUGIN_ID
68  			+ ".nodeConfigurableDump";
69  
70  	private final static DateFormat df = new SimpleDateFormat(
71  			"yyyy-MM-dd_HH-mm");
72  
73  	public final static int EXPORT_NODE = 0;
74  	public final static int EXPORT_CHILDREN = 1;
75  	public final static int EXPORT_GRAND_CHILDREN = 2;
76  
77  	public Object execute(ExecutionEvent event) throws ExecutionException {
78  		ISelection selection = HandlerUtil.getActiveWorkbenchWindow(event)
79  				.getActivePage().getSelection();
80  		if (selection == null || !(selection instanceof IStructuredSelection))
81  			return null;
82  
83  		Iterator<?> lst = ((IStructuredSelection) selection).iterator();
84  		if (lst.hasNext()) {
85  			Object element = lst.next();
86  			if (element instanceof SingleJcrNodeElem) {
87  				SingleJcrNodeElem sjn = (SingleJcrNodeElem) element;
88  				Node node = sjn.getNode();
89  
90  				ConfigureDumpWizard wizard = new ConfigureDumpWizard(
91  						HandlerUtil.getActiveShell(event),
92  						"Import Resource CSV");
93  				WizardDialog dialog = new WizardDialog(
94  						HandlerUtil.getActiveShell(event), wizard);
95  				int result = dialog.open();
96  
97  				if (result == Window.OK) {
98  
99  					String dateVal = df.format(new GregorianCalendar()
100 							.getTime());
101 					try {
102 
103 						Path tmpDirPath = Files.createTempDirectory(dateVal
104 								+ "-NodeDump-");
105 						List<Node> toExport = retrieveToExportNodes(node,
106 								wizard.currExportType);
107 
108 						for (Node currNode : toExport) {
109 							FileOutputStream fos;
110 							String fileName = wizard.prefix
111 									+ JcrUtils.replaceInvalidChars(currNode
112 											.getName()) + "_" + dateVal
113 									+ ".xml";
114 							File currFile = new File(tmpDirPath.toString()
115 									+ "/" + fileName);
116 							currFile.createNewFile();
117 							fos = new FileOutputStream(currFile);
118 							node.getSession().exportSystemView(
119 									currNode.getPath(), fos,
120 									!wizard.includeBinaries, false);
121 							fos.flush();
122 							fos.close();
123 						}
124 					} catch (RepositoryException e) {
125 						throw new EclipseUiException(
126 								"Unable to perform SystemExport on " + node, e);
127 					} catch (IOException e) {
128 						throw new EclipseUiException("Unable to SystemExport "
129 								+ node, e);
130 					}
131 				}
132 			}
133 		}
134 		return null;
135 	}
136 
137 	private List<Node> retrieveToExportNodes(Node node, int currExportType)
138 			throws RepositoryException {
139 		List<Node> nodes = new ArrayList<Node>();
140 		switch (currExportType) {
141 		case EXPORT_NODE:
142 			nodes.add(node);
143 			return nodes;
144 		case EXPORT_CHILDREN:
145 			return JcrUtils.nodeIteratorToList(node.getNodes());
146 		case EXPORT_GRAND_CHILDREN:
147 			NodeIterator nit = node.getNodes();
148 			while (nit.hasNext())
149 				nodes.addAll(JcrUtils.nodeIteratorToList(nit.nextNode()
150 						.getNodes()));
151 			return nodes;
152 
153 		default:
154 			return nodes;
155 		}
156 	}
157 
158 	// private synchronized void openGeneratedFile(String path, String fileName)
159 	// {
160 	// Map<String, String> params = new HashMap<String, String>();
161 	// params.put(OpenFile.PARAM_FILE_NAME, fileName);
162 	// params.put(OpenFile.PARAM_FILE_URI, "file://" + path);
163 	// CommandUtils.callCommand("org.argeo.security.ui.specific.openFile",
164 	// params);
165 	// }
166 
167 	private class ConfigureDumpWizard extends Wizard {
168 
169 		// parameters
170 		protected String prefix;
171 		protected int currExportType = EXPORT_NODE;
172 		protected boolean includeBinaries = false;
173 
174 		// UI Objects
175 		private BasicPage page;
176 		private Text prefixTxt;
177 		private Button includeBinaryBtn;
178 		private Button b1, b2, b3;
179 
180 		public ConfigureDumpWizard(Shell parentShell, String title) {
181 			setWindowTitle(title);
182 		}
183 
184 		@Override
185 		public void addPages() {
186 			try {
187 				page = new BasicPage("Main page");
188 				addPage(page);
189 			} catch (Exception e) {
190 				throw new EclipseUiException("Cannot add page to wizard", e);
191 			}
192 		}
193 
194 		@Override
195 		public boolean performFinish() {
196 			prefix = prefixTxt.getText();
197 			if (b1.getSelection())
198 				currExportType = EXPORT_NODE;
199 			else if (b2.getSelection())
200 				currExportType = EXPORT_CHILDREN;
201 			else if (b3.getSelection())
202 				currExportType = EXPORT_GRAND_CHILDREN;
203 			includeBinaries = includeBinaryBtn.getSelection();
204 			return true;
205 		}
206 
207 		@Override
208 		public boolean performCancel() {
209 			return true;
210 		}
211 
212 		@Override
213 		public boolean canFinish() {
214 			String errorMsg = "No prefix defined.";
215 			if ("".equals(prefixTxt.getText().trim())) {
216 				page.setErrorMessage(errorMsg);
217 				return false;
218 			} else {
219 				page.setErrorMessage(null);
220 				return true;
221 			}
222 		}
223 
224 		protected class BasicPage extends WizardPage {
225 			private static final long serialVersionUID = 1L;
226 
227 			public BasicPage(String pageName) {
228 				super(pageName);
229 				setTitle("Configure dump before launching");
230 				setMessage("Define the parameters of the dump to launch");
231 			}
232 
233 			public void createControl(Composite parent) {
234 				parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
235 
236 				// Main Layout
237 				Composite mainCmp = new Composite(parent, SWT.NONE);
238 				mainCmp.setLayout(new GridLayout(2, false));
239 				mainCmp.setLayoutData(EclipseUiUtils.fillAll());
240 
241 				// The path
242 				createBoldLabel(mainCmp, "Prefix");
243 				prefixTxt = new Text(mainCmp, SWT.SINGLE | SWT.BORDER);
244 				prefixTxt.setLayoutData(EclipseUiUtils.fillAll());
245 				prefixTxt.addModifyListener(new ModifyListener() {
246 					private static final long serialVersionUID = 1L;
247 
248 					@Override
249 					public void modifyText(ModifyEvent event) {
250 						if (prefixTxt.getText() != null)
251 							getWizard().getContainer().updateButtons();
252 					}
253 				});
254 
255 				new Label(mainCmp, SWT.SEPARATOR | SWT.HORIZONTAL)
256 						.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
257 								false, 2, 1));
258 
259 				// Which node to export
260 				Label typeLbl = new Label(mainCmp, SWT.RIGHT);
261 				typeLbl.setText(" Type");
262 				typeLbl.setFont(EclipseUiUtils.getBoldFont(mainCmp));
263 				typeLbl.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false,
264 						false, 1, 3));
265 
266 				b1 = new Button(mainCmp, SWT.RADIO);
267 				b1.setText("Export this node");
268 				b1.setSelection(true);
269 				b2 = new Button(mainCmp, SWT.RADIO);
270 				b2.setText("Export children nodes");
271 				b3 = new Button(mainCmp, SWT.RADIO);
272 				b3.setText("Export grand-children nodes");
273 
274 				new Label(mainCmp, SWT.SEPARATOR | SWT.HORIZONTAL)
275 						.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
276 								false, 2, 1));
277 
278 				createBoldLabel(mainCmp, "Files and images");
279 				includeBinaryBtn = new Button(mainCmp, SWT.CHECK);
280 				includeBinaryBtn.setText("Include binaries");
281 
282 				prefixTxt.setFocus();
283 				setControl(mainCmp);
284 			}
285 		}
286 	}
287 
288 	private Label createBoldLabel(Composite parent, String value) {
289 		Label label = new Label(parent, SWT.RIGHT);
290 		label.setText(" " + value);
291 		label.setFont(EclipseUiUtils.getBoldFont(parent));
292 		label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
293 		return label;
294 	}
295 }