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