1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.serializer;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.sql.Date;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.StringTokenizer;
28
29 import javolution.xml.XMLBinding;
30 import javolution.xml.XMLObjectReader;
31 import javolution.xml.XMLObjectWriter;
32
33 import org.apache.commons.configuration.Configuration;
34 import org.apache.commons.configuration.PropertiesConfiguration;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.jetspeed.components.ComponentManager;
38 import org.apache.jetspeed.components.SpringComponentManager;
39 import org.apache.jetspeed.engine.JetspeedEngineConstants;
40 import org.apache.jetspeed.serializer.objects.JSSnapshot;
41
42 public abstract class JetspeedSerializerBase
43 {
44
45 /*** Logger */
46 protected static final Log log = LogFactory.getLog(JetspeedSerializer.class);
47
48 private ComponentManager cm = null;
49
50
51 int refCouter = 0;
52
53 /*** the main wrapper class for an XML file */
54 private JSSnapshot snapshot;
55
56 /*** processing flags */
57 /*** export/import instructions */
58
59 private HashMap processSettings = new HashMap();
60
61 private boolean initialized = false;
62
63 /*** current indent for XML files - defaults to tab */
64 private String currentIndent = null;
65
66 private static String ENCODING_STRING = "JETSPEED 2.1 - 2006";
67 private static String JETSPEED = "JETSPEED";
68
69
70 protected final ComponentManager getCM()
71 {
72 return cm;
73 }
74
75 public JetspeedSerializerBase()
76 {
77 }
78
79
80
81 /***
82 * hand over existing component manager
83 *
84 * @param cm
85 */
86 public JetspeedSerializerBase(ComponentManager cm)
87 {
88 this.setComponentManager(cm);
89 this.initialized = true;
90 }
91
92 /***
93 * This constructor takes the application root, the search path for the boot
94 * component configuration files and the search path for the application
95 * component configuration files.
96 * <p>
97 * For example: new JetspeedSerializerSecondaryImpl("./", "assembly/boot/*.xml",
98 * "assembly/*.xml") will establish the current directory as the root,
99 * process all xml files in the assembly/boot directory before processing
100 * all xml files in the assembly directory itself.
101 *
102 * @param appRoot
103 * working directory
104 * @param bootConfig
105 * boot (primary) file or files (wildcards are allowed)
106 * @param appConfig
107 * application (secondary) file or files (wildcards are allowed)
108 */
109 public JetspeedSerializerBase(String appRoot, String[] bootConfig,
110 String[] appConfig) throws SerializerException
111 {
112 this.initializeComponentManager(appRoot, bootConfig, appConfig);
113 this.initialized = true;
114 }
115
116
117
118
119
120
121 public final void initializeComponentManager(String appRoot, String[] bootConfig,
122 String[] appConfig) throws SerializerException
123 {
124
125
126
127 if (this.initialized)
128 throw new SerializerException(
129 SerializerException.COMPONENT_MANAGER_EXISTS.create(""));
130 SpringComponentManager cm = new SpringComponentManager(bootConfig,
131 appConfig, appRoot);
132 cm.start();
133 Configuration properties = new PropertiesConfiguration();
134 properties.setProperty(JetspeedEngineConstants.APPLICATION_ROOT_KEY,
135 appRoot);
136 this.setComponentManager(cm);
137 }
138
139
140
141
142
143
144 public final void setComponentManager(ComponentManager cm)
145 {
146 this.cm = cm;
147 }
148
149
150
151
152
153
154 public final void closeUp()
155 {
156 if (cm != null) cm.stop();
157 cm = null;
158 }
159
160
161
162
163
164
165 public final void setDefaultIndent(String indent)
166 {
167 this.currentIndent = indent;
168 }
169
170
171
172
173
174
175 public final String getDefaultIndent()
176 {
177 return this.currentIndent;
178 }
179
180
181
182
183
184
185
186 public final void importData(String importFileName, Map settings)
187 throws SerializerException
188 {
189 /*** pre-processing homework... */
190 XMLBinding binding = new XMLBinding();
191 setupAliases(binding);
192 checkSettings(settings);
193
194
195 setSnapshot(readFile(importFileName, binding));
196
197 if (getSnapshot() == null)
198 throw new SerializerException(
199 SerializerException.FILE_PROCESSING_ERROR
200 .create(new String[]
201 { importFileName, "Snapshot is NULL"}));
202
203 if (!(getSnapshot().checkVersion()))
204 throw new SerializerException(
205 SerializerException.INCOMPETIBLE_VERSION
206 .create(new String[]
207 {
208 importFileName,
209 String.valueOf(getSnapshot()
210 .getSoftwareVersion()),
211 String.valueOf(getSnapshot()
212 .getSavedSubversion())}));
213
214 /*** ok, now we have a valid snapshot and can start processing it */
215
216 /*** ensure we can work undisturbed */
217 synchronized (cm)
218 {
219 logMe("*********Reading data*********");
220 this.processImport();
221 }
222 return;
223 }
224
225
226
227
228
229
230
231 public final void exportData(String name, String exportFileName, Map settings)
232 throws SerializerException
233 {
234 /*** pre-processing homework... */
235 XMLBinding binding = new XMLBinding();
236 setupAliases(binding);
237 checkSettings(settings);
238
239 /*** ensure we can work undisturbed */
240 synchronized (cm)
241 {
242 /*** get the snapshot construct */
243 this.processExport(name, binding);
244 XMLObjectWriter writer = openWriter(exportFileName);
245 writer.setBinding(binding);
246
247 if (this.getDefaultIndent() != null)
248 writer.setIndentation(this.getDefaultIndent());
249
250 try
251 {
252 logMe("*********Writing data*********");
253 writer.write(getSnapshot(), getSerializerDataTag(),
254 getSerializerDataClass());
255
256 } catch (Exception e)
257 {
258 throw new SerializerException(
259 SerializerException.FILE_PROCESSING_ERROR
260 .create(new String[]
261 { exportFileName, e.getMessage()}));
262 } finally
263 {
264 /*** ensure the writer is closed */
265 try
266 {
267 logMe("*********closing up********");
268 writer.close();
269 } catch (Exception e)
270 {
271 logMe("Error in closing writer " + e.getMessage());
272 /***
273 * don't do anything with this exception - never let the
274 * bubble out of the finally block
275 */
276 }
277 }
278 }
279 return;
280 }
281
282 /***
283 * create a backup of the current environment in case the import fails
284 *
285 */
286 protected final void doBackupOfCurrent(String importFileName, Map currentSettings)
287 {
288
289 }
290
291 /***
292 * read a snapshot and return the reconstructed class tree
293 *
294 * @param importFileName
295 * @throws SerializerException
296 */
297
298 /***
299 * read a snapshot and return the reconstructed class tree
300 *
301 * @param importFileName
302 * @throws SerializerException
303 */
304
305 protected final JSSnapshot readFile(String importFileName, XMLBinding binding)
306 throws SerializerException
307 {
308 XMLObjectReader reader = null;
309 JSSnapshot snap = null;
310 try
311 {
312 reader = XMLObjectReader.newInstance(new FileInputStream(
313 importFileName));
314 } catch (Exception e)
315 {
316 throw new SerializerException(SerializerException.FILE_READER_ERROR
317 .create(new String[]
318 { importFileName, e.getMessage()}));
319 }
320 try
321 {
322 if (binding != null) reader.setBinding(binding);
323 snap = (JSSnapshot) reader.read(this.getSerializerDataTag(),
324 getSerializerDataClass());
325
326 } catch (Exception e)
327 {
328 e.printStackTrace();
329 new SerializerException(SerializerException.FILE_PROCESSING_ERROR
330 .create(new String[]
331 { importFileName, e.getMessage()}));
332 } finally
333 {
334 /*** ensure the reader is closed */
335 try
336 {
337 logMe("*********closing up reader ********");
338 reader.close();
339 } catch (Exception e1)
340 {
341 logMe("Error in closing reader " + e1.getMessage());
342 /***
343 * don't do anything with this exception - never let the bubble
344 * out of the finally block
345 */
346 return null;
347 }
348 }
349 return snap;
350 }
351 /***
352 * create or open a given file for writing
353 */
354 protected final XMLObjectWriter openWriter(String filename)
355 throws SerializerException
356 {
357 File f;
358
359 try
360 {
361 f = new File(filename);
362 } catch (Exception e)
363 {
364 throw new SerializerException(
365 SerializerException.FILE_PROCESSING_ERROR
366 .create(new String[]
367 { filename, e.getMessage()}));
368 }
369 boolean exists = f.exists();
370
371 if (exists)
372 {
373 if (!(this.getSetting(JetspeedSerializer.KEY_OVERWRITE_EXISTING)))
374 throw new SerializerException(
375 SerializerException.FILE_ALREADY_EXISTS
376 .create(filename));
377 if (this.getSetting(JetspeedSerializer.KEY_BACKUP_BEFORE_PROCESS))
378 {
379 String backName = createUniqueBackupFilename(f.getName());
380 if (backName == null)
381 throw new SerializerException(
382 SerializerException.FILE_BACKUP_FAILED
383 .create(filename));
384 File ftemp = new File(backName);
385 f.renameTo(ftemp);
386 }
387 }
388 try
389 {
390 XMLObjectWriter writer = XMLObjectWriter
391 .newInstance(new FileOutputStream(filename));
392 return writer;
393 } catch (Exception e)
394 {
395 throw new SerializerException(SerializerException.FILE_WRITER_ERROR
396 .create(new String[]
397 { filename, e.getMessage()}));
398 }
399 }
400
401 /***
402 * returns the key for a particular process setting. False if the key
403 * doesn't exist.
404 *
405 * @param key
406 * @return
407 */
408 public final boolean getSetting(String key)
409 {
410 Object o = processSettings.get(key);
411 if ((o == null) || (!(o instanceof Boolean))) return false;
412 return ((Boolean) o).booleanValue();
413 }
414
415 /***
416 * set a process setting for a given key
417 *
418 * @param key
419 * instruction to set
420 * @param value
421 * true or false
422 */
423 protected final void setSetting(String key, boolean value)
424 {
425 processSettings.put(key, (value ? Boolean.TRUE : Boolean.FALSE));
426 }
427
428
429 /***
430 * set instruction flags to new settings
431 *
432 * @param settings
433 */
434 protected final void checkSettings(Map settings)
435 {
436 /*** ensure we don't have settings from a previous run */
437 resetSettings();
438 /*** process the new isntructionSet */
439 if ((settings == null) || (settings.size() == 0)) return;
440 Iterator _it = settings.keySet().iterator();
441 while (_it.hasNext())
442 {
443 try
444 {
445 String key = (String) _it.next();
446 Object o = settings.get(key);
447 if ((o != null) && (o instanceof Boolean))
448 setSetting(key, ((Boolean) o).booleanValue());
449 } catch (Exception e)
450 {
451 log.error("checkSettings", e);
452 }
453 }
454 }
455
456 /***
457 * On import, get the basic SnapShot data
458 *
459 */
460 protected void getSnapshotData()
461 {
462 logMe("date created : " + getSnapshot().getDateCreated());
463 logMe("software Version : " + getSnapshot().getSavedVersion());
464 logMe("software SUbVersion : " + getSnapshot().getSavedSubversion());
465 }
466
467 /***
468 * On export, set the basic SnapShot data
469 *
470 */
471 protected void setSnapshotData()
472 {
473 java.util.Date d1 = new java.util.Date();
474 Date d = new Date(d1.getTime());
475 getSnapshot().setDateCreated(d.toString());
476 getSnapshot().setSavedVersion(getSnapshot().getSoftwareVersion());
477 getSnapshot().setSavedSubversion(getSnapshot().getSoftwareSubVersion());
478 }
479
480
481
482
483 /***
484 * simple lookup for object from a map
485 * @param map
486 * @param _fullPath
487 * @return
488 */
489 protected final Object getObjectBehindPath(Map map, String _fullPath)
490 {
491 return map.get(_fullPath);
492 }
493
494
495 /***
496 * ++++++++++++++++++++++++++++++HELPERS
497 * +++++++++++++++++++++++++++++++++++++++++++++
498 */
499
500 /***
501 * remove a given sequence from the beginning of a string
502 */
503 protected final String removeFromString(String base, String excess)
504 {
505 return base.replaceFirst(excess, "").trim();
506 }
507
508 /***
509 *
510 * just a Simple helper to make code more readable
511 *
512 * @param text
513 */
514 protected final void logMe(String text)
515 {
516 if (log.isDebugEnabled())
517 log.debug(text);
518 }
519
520 /***
521 * Helper routine to create a unique filename for a backup of an existing
522 * filename....not intended to be rocket science...
523 *
524 * @param name
525 * @return
526 */
527 protected final String createUniqueBackupFilename(String name)
528 {
529 String newName = name + ".bak";
530
531 File f = new File(newName);
532 int counter = 0;
533 if (!(f.exists())) return newName;
534 while (counter < 100)
535 {
536 String newName1 = newName + counter;
537 if (!(new File(newName1).exists())) return newName1;
538 counter++;
539 }
540 return null;
541 }
542
543 /***
544 * convert a list of elements in a string, seperated by ',' into an arraylist of strings
545 * @param _line Strinbg containing one or more elements seperated by ','
546 * @return list of elements of null
547 */
548 protected final ArrayList getTokens(String _line)
549 {
550 if ((_line == null) || (_line.length() == 0)) return null;
551
552 StringTokenizer st = new StringTokenizer(_line, ",");
553 ArrayList list = new ArrayList();
554
555 while (st.hasMoreTokens())
556 list.add(st.nextToken());
557 return list;
558 }
559
560
561 protected final String recreatePassword(char[] savedPassword)
562 {
563 if (savedPassword == null)
564 return null;
565 return new String(savedPassword);
566 }
567
568
569 /***
570 * reset instruction flags to default settings (all true)
571 *
572 */
573 protected abstract void resetSettings();
574
575
576 /***
577 * The workhorse for exporting data
578 *
579 * @param binding
580 * established XML binding
581 * @return
582 * @throws SerializerException
583 */
584 protected abstract void processExport(String name, XMLBinding binding)
585 throws SerializerException;
586
587 /***
588 * The workhorse for importing data
589 *
590 * @param binding
591 * established XML binding
592 * @return
593 * @throws SerializerException
594 */
595 protected abstract void processImport() throws SerializerException;
596
597 /***
598 * Setup the binding for the different classes, mapping each extracted class
599 * to a unique tag name in the XML
600 *
601 * @param binding
602 */
603 protected abstract void setupAliases(XMLBinding binding);
604
605
606 /***
607 * return the class for the serializer data , for example JSSeedData.class)
608 *
609 * @return
610 */
611 protected abstract Class getSerializerDataClass();
612
613
614 /***
615 * return the XML tag for the serializer data , for example "JSSnapShot")
616 *
617 * @return
618 */
619 protected abstract String getSerializerDataTag();
620
621 public JSSnapshot getSnapshot()
622 {
623 return snapshot;
624 }
625
626
627
628 public void setSnapshot(JSSnapshot snapshot)
629 {
630 this.snapshot = snapshot;
631 }
632
633 }