KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > synchronize > CmsSynchronize


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/synchronize/CmsSynchronize.java,v $
3  * Date : $Date: 2006/07/20 11:03:27 $
4  * Version: $Revision: 1.64 $
5  * Date : $Date: 2006/07/20 11:03:27 $
6  * Version: $Revision: 1.64 $
7  *
8  * This library is part of OpenCms -
9  * the Open Source Content Mananagement System
10  *
11  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public
15  * License as published by the Free Software Foundation; either
16  * version 2.1 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * Lesser General Public License for more details.
22  *
23  * For further information about Alkacon Software GmbH, please see the
24  * company website: http://www.alkacon.com
25  *
26  * For further information about OpenCms, please see the
27  * project website: http://www.opencms.org
28  *
29  * You should have received a copy of the GNU Lesser General Public
30  * License along with this library; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32  */

33
34 package org.opencms.synchronize;
35
36 import org.opencms.db.CmsDbIoException;
37 import org.opencms.file.CmsFile;
38 import org.opencms.file.CmsObject;
39 import org.opencms.file.CmsResource;
40 import org.opencms.file.CmsResourceFilter;
41 import org.opencms.file.types.CmsResourceTypeFolder;
42 import org.opencms.main.CmsException;
43 import org.opencms.main.CmsLog;
44 import org.opencms.main.OpenCms;
45 import org.opencms.report.I_CmsReport;
46 import org.opencms.util.CmsFileUtil;
47
48 import java.io.DataOutputStream JavaDoc;
49 import java.io.File JavaDoc;
50 import java.io.FileOutputStream JavaDoc;
51 import java.io.FileReader JavaDoc;
52 import java.io.IOException JavaDoc;
53 import java.io.LineNumberReader JavaDoc;
54 import java.io.PrintWriter JavaDoc;
55 import java.util.ArrayList JavaDoc;
56 import java.util.HashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59 import java.util.StringTokenizer JavaDoc;
60
61 import org.apache.commons.logging.Log;
62
63 /**
64  * Contains all methods to synchronize the VFS with the "real" FS.<p>
65  *
66  * @author Michael Emmerich
67  *
68  * @version $Revision: 1.64 $
69  *
70  * @since 6.0.0
71  */

72 public class CmsSynchronize {
73
74     /** Flag to import a deleted resource in the VFS. */
75     static final int DELETE_VFS = 3;
76
77     /** Flag to export a resource from the VFS to the FS. */
78     static final int EXPORT_VFS = 1;
79
80     /** Filname of the synclist file on the server FS. */
81     static final String JavaDoc SYNCLIST_FILENAME = "#synclist.txt";
82
83     /** Flag to import a resource from the FS to the VFS. */
84     static final int UPDATE_VFS = 2;
85
86     /** The log object for this class. */
87     private static final Log LOG = CmsLog.getLog(CmsSynchronize.class);
88
89     /** List to store all file modification interface implementations. */
90     private static List JavaDoc m_synchronizeModifications = new ArrayList JavaDoc();
91
92     /** The CmsObject. */
93     private CmsObject m_cms;
94
95     /** Counter for logging. */
96     private int m_count;
97
98     /** The path in the "real" file system where the resources have to be synchronized to. */
99     private String JavaDoc m_destinationPathInRfs;
100
101     /** Hashmap for the new synchronisation list of the current sync process. */
102     private HashMap JavaDoc m_newSyncList;
103
104     /** The report to write the output to. */
105     private I_CmsReport m_report;
106
107     /** Hashmap for the synchronisation list of the last sync process. */
108     private HashMap JavaDoc m_syncList;
109
110     /**
111      * Creates a new CmsSynchronize object which automatically start the
112      * synchronisation process.<p>
113      *
114      * @param cms the current CmsObject
115      * @param settings the synchonization settings to use
116      * @param report the report to write the output to
117      *
118      * @throws CmsException if something goes wrong
119      * @throws CmsSynchronizeException if the synchronization process cannot be started
120      */

121     public CmsSynchronize(CmsObject cms, CmsSynchronizeSettings settings, I_CmsReport report)
122     throws CmsSynchronizeException, CmsException {
123
124         // TODO: initialize the list of file modifiaction interface implementations
125

126         // do the synchronization only if the synchonization folders in the VFS
127
// and the FS are valid
128
if ((settings != null) && (settings.isSyncEnabled())) {
129
130             // create an independent copy of the provided user context
131
m_cms = OpenCms.initCmsObject(cms);
132             // set site to root site
133
m_cms.getRequestContext().setSiteRoot("/");
134
135             m_report = report;
136             m_count = 1;
137             
138             // get the destination folder
139
m_destinationPathInRfs = settings.getDestinationPathInRfs();
140
141             // check if target folder exists and is writeable
142
File destinationFolder = new File(m_destinationPathInRfs);
143             if (!destinationFolder.exists() || !destinationFolder.isDirectory()) {
144                 // destination folder does not exist
145
throw new CmsSynchronizeException(Messages.get().container(
146                     Messages.ERR_RFS_DESTINATION_NOT_THERE_1,
147                     m_destinationPathInRfs));
148             }
149             if (!destinationFolder.canWrite()) {
150                 // destination folder can't be written to
151
throw new CmsSynchronizeException(Messages.get().container(
152                     Messages.ERR_RFS_DESTINATION_NO_WRITE_1,
153                     m_destinationPathInRfs));
154             }
155
156             // create the sync list for this run
157
m_syncList = readSyncList();
158             m_newSyncList = new HashMap JavaDoc();
159
160             Iterator JavaDoc i = settings.getSourceListInVfs().iterator();
161             while (i.hasNext()) {
162                 // iterate all source folders
163
String JavaDoc sourcePathInVfs = (String JavaDoc)i.next();
164                 String JavaDoc destPath = m_destinationPathInRfs + sourcePathInVfs.replace('/', File.separatorChar);
165
166                 report.println(org.opencms.workplace.threads.Messages.get().container(
167                     org.opencms.workplace.threads.Messages.RPT_SYNCHRONIZE_FOLDERS_2,
168                     sourcePathInVfs,
169                     destPath), I_CmsReport.FORMAT_HEADLINE);
170                 // synchronice the VFS and the RFS
171
syncVfsToRfs(sourcePathInVfs);
172             }
173
174             // remove files from the RFS
175
removeFromRfs(m_destinationPathInRfs);
176             i = settings.getSourceListInVfs().iterator();
177
178             while (i.hasNext()) {
179                 // add new files from the RFS
180
copyFromRfs((String JavaDoc)i.next());
181             }
182
183             // write the sync list
184
writeSyncList();
185
186             // free mem
187
m_syncList = null;
188             m_newSyncList = null;
189             m_cms = null;
190         } else {
191             throw new CmsSynchronizeException(Messages.get().container(Messages.ERR_INIT_SYNC_0));
192         }
193     }
194
195     /**
196      * Copys all resources from the FS which are not existing in the VFS yet. <p>
197      *
198      * @param folder the folder in the VFS to be synchronized with the FS
199      * @throws CmsException if something goes wrong
200      */

201     private void copyFromRfs(String JavaDoc folder) throws CmsException {
202
203         // get the corresponding folder in the FS
204
File[] res;
205         File fsFile = getFileInRfs(folder);
206         // first of all, test if this folder existis in the VFS. If not, create it
207
try {
208             m_cms.readFolder(translate(folder), CmsResourceFilter.IGNORE_EXPIRATION);
209         } catch (CmsException e) {
210             // the folder could not be read, so create it
211
String JavaDoc foldername = translate(folder);
212             m_report.print(org.opencms.report.Messages.get().container(
213                 org.opencms.report.Messages.RPT_SUCCESSION_1,
214                 String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
215             m_report.print(Messages.get().container(Messages.RPT_IMPORT_FOLDER_0), I_CmsReport.FORMAT_NOTE);
216             m_report.print(org.opencms.report.Messages.get().container(
217                 org.opencms.report.Messages.RPT_ARGUMENT_1,
218                 fsFile.getAbsolutePath().replace('\\', '/')));
219             m_report.print(Messages.get().container(Messages.RPT_FROM_FS_TO_0), I_CmsReport.FORMAT_NOTE);
220             m_report.print(org.opencms.report.Messages.get().container(
221                 org.opencms.report.Messages.RPT_ARGUMENT_1,
222                 foldername));
223             m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
224
225             CmsResource newFolder = m_cms.createResource(foldername, CmsResourceTypeFolder.RESOURCE_TYPE_ID);
226             // now check if there is some external method to be called which
227
// should modify the imported resource in the VFS
228
Iterator JavaDoc i = m_synchronizeModifications.iterator();
229             while (i.hasNext()) {
230                 try {
231                     ((I_CmsSynchronizeModification)i.next()).modifyVfs(m_cms, newFolder, fsFile);
232                 } catch (CmsSynchronizeException e1) {
233                     break;
234                 }
235             }
236             // we have to read the new resource again, to get the correct timestamp
237
newFolder = m_cms.readFolder(foldername, CmsResourceFilter.IGNORE_EXPIRATION);
238             String JavaDoc resourcename = m_cms.getSitePath(newFolder);
239             // add the folder to the sync list
240
CmsSynchronizeList sync = new CmsSynchronizeList(
241                 folder,
242                 resourcename,
243                 newFolder.getDateLastModified(),
244                 fsFile.lastModified());
245             m_newSyncList.put(resourcename, sync);
246
247             m_report.println(
248                 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
249                 I_CmsReport.FORMAT_OK);
250         }
251         // since the check has been done on folder basis, this must be a folder
252
if (fsFile.isDirectory()) {
253             // get all resources in this folder
254
res = fsFile.listFiles();
255
256             // now loop through all resources
257
for (int i = 0; i < res.length; i++) {
258                 // get the relative filename
259
String JavaDoc resname = res[i].getAbsolutePath();
260                 resname = resname.substring(m_destinationPathInRfs.length());
261                 // translate the folder seperator if nescessary
262
resname = resname.replace(File.separatorChar, '/');
263                 // now check if this resource was already processed, by looking
264
// up the new sync list
265
if (res[i].isFile()) {
266                     if (!m_newSyncList.containsKey(translate(resname))) {
267                         // this file does not exist in the VFS, so import it
268
importToVfs(res[i], resname, folder);
269                     }
270                 } else {
271                     // do a recursion if the current resource is a folder
272
copyFromRfs(resname + "/");
273                 }
274             }
275         }
276         // free mem
277
res = null;
278     }
279
280     /**
281      * Creates a new file on the server FS.<p>
282      *
283      * @param newFile the file that has to be created
284      * @throws CmsException if something goes wrong
285      */

286     private void createNewLocalFile(File newFile) throws CmsException {
287
288         if (newFile.exists()) {
289             throw new CmsSynchronizeException(Messages.get().container(Messages.ERR_EXISTENT_FILE_1, newFile.getPath()));
290         }
291         FileOutputStream JavaDoc fOut = null;
292         try {
293             File parentFolder = new File(newFile.getPath().replace('/', File.separatorChar).substring(
294                 0,
295                 newFile.getPath().lastIndexOf(File.separator)));
296             parentFolder.mkdirs();
297             if (parentFolder.exists()) {
298                 fOut = new FileOutputStream JavaDoc(newFile);
299             } else {
300                 throw new CmsSynchronizeException(
301                     Messages.get().container(Messages.ERR_CREATE_DIR_1, newFile.getPath()));
302             }
303         } catch (IOException JavaDoc e) {
304             throw new CmsSynchronizeException(Messages.get().container(
305                 Messages.ERR_CREATE_FILE_1,
306                 this.getClass().getName(),
307                 newFile.getPath()), e);
308         } finally {
309             if (fOut != null) {
310                 try {
311                     fOut.close();
312                 } catch (IOException JavaDoc e) {
313                     // ignore
314
}
315             }
316         }
317     }
318
319     /**
320      * Deletes a resource in the VFS and updates the synchronisation lists.<p>
321      *
322      * @param res The resource to be deleted
323      *
324      * @throws CmsException if something goes wrong
325      */

326     private void deleteFromVfs(CmsResource res) throws CmsException {
327
328         String JavaDoc resourcename = m_cms.getSitePath(res);
329
330         m_report.print(org.opencms.report.Messages.get().container(
331             org.opencms.report.Messages.RPT_SUCCESSION_1,
332             String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
333         if (res.isFile()) {
334             m_report.print(Messages.get().container(Messages.RPT_DEL_FILE_0), I_CmsReport.FORMAT_NOTE);
335         } else {
336             m_report.print(Messages.get().container(Messages.RPT_DEL_FOLDER_0), I_CmsReport.FORMAT_NOTE);
337         }
338         m_report.print(org.opencms.report.Messages.get().container(
339             org.opencms.report.Messages.RPT_ARGUMENT_1,
340             resourcename));
341         m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
342
343         // lock the file in the VFS, so that it can be updated
344
m_cms.lockResource(resourcename);
345         m_cms.deleteResource(resourcename, CmsResource.DELETE_PRESERVE_SIBLINGS);
346         // Remove it from the sync list
347
m_syncList.remove(translate(resourcename));
348
349         m_report.println(
350             org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
351             I_CmsReport.FORMAT_OK);
352     }
353
354     /**
355      * Exports a resource from the VFS to the FS and updates the
356      * synchronisation lists.<p>
357      *
358      * @param res the resource to be exported
359      * @throws CmsException if something goes wrong
360      */

361     private void exportToRfs(CmsResource res) throws CmsException {
362
363         CmsFile vfsFile;
364         File fsFile;
365         String JavaDoc resourcename;
366         // to get the name of the file in the FS, we must look it up in the
367
// sync list. This is nescessary, since the VFS could use a tranlated
368
// filename.
369
CmsSynchronizeList sync = (CmsSynchronizeList)m_syncList.get(translate(m_cms.getSitePath(res)));
370         // if no entry in the sync list was found, its a new resource and we
371
// can use the name of the VFS resource.
372
if (sync != null) {
373             resourcename = sync.getResName();
374         } else {
375             // otherwise use the original non-translated name
376
resourcename = m_cms.getSitePath(res);
377
378             // the parent folder could contain a translated names as well, so
379
// make a lookup in the sync list ot get its original
380
// non-translated name
381
String JavaDoc parent = CmsResource.getParentFolder(resourcename);
382             CmsSynchronizeList parentSync = (CmsSynchronizeList)m_newSyncList.get(parent);
383             // use the non-translated pathname
384
if (parentSync != null) {
385                 resourcename = parentSync.getResName() + res.getName();
386             }
387         }
388         if ((res.isFolder()) && (!resourcename.endsWith("/"))) {
389             resourcename += "/";
390         }
391         fsFile = getFileInRfs(resourcename);
392
393         try {
394             // if the resource is marked for deletion, do not export it!
395
if (res.getState() != CmsResource.STATE_DELETED) {
396                 // if its a file, create export the file to the FS
397
m_report.print(org.opencms.report.Messages.get().container(
398                     org.opencms.report.Messages.RPT_SUCCESSION_1,
399                     String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
400                 if (res.isFile()) {
401
402                     m_report.print(Messages.get().container(Messages.RPT_EXPORT_FILE_0), I_CmsReport.FORMAT_NOTE);
403                     m_report.print(org.opencms.report.Messages.get().container(
404                         org.opencms.report.Messages.RPT_ARGUMENT_1,
405                         m_cms.getSitePath(res)));
406                     m_report.print(Messages.get().container(Messages.RPT_TO_FS_AS_0), I_CmsReport.FORMAT_NOTE);
407                     m_report.print(org.opencms.report.Messages.get().container(
408                         org.opencms.report.Messages.RPT_ARGUMENT_1,
409                         fsFile.getAbsolutePath().replace('\\', '/')));
410                     m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
411
412                     // create the resource if nescessary
413
if (!fsFile.exists()) {
414                         createNewLocalFile(fsFile);
415                     }
416                     // write the file content to the FS
417
vfsFile = m_cms.readFile(m_cms.getSitePath(res), CmsResourceFilter.IGNORE_EXPIRATION);
418                     try {
419                         writeFileByte(vfsFile.getContents(), fsFile);
420                     } catch (IOException JavaDoc e) {
421                         throw new CmsSynchronizeException(Messages.get().container(Messages.ERR_WRITE_FILE_0));
422                     }
423                     // now check if there is some external method to be called
424
// which should modify the exported resource in the FS
425
Iterator JavaDoc i = m_synchronizeModifications.iterator();
426                     while (i.hasNext()) {
427                         try {
428                             ((I_CmsSynchronizeModification)i.next()).modifyFs(m_cms, vfsFile, fsFile);
429                         } catch (CmsSynchronizeException e) {
430                             if (LOG.isWarnEnabled()) {
431                                 LOG.warn(Messages.get().getBundle().key(
432                                     Messages.LOG_SYNCHRONIZE_EXPORT_FAILED_1,
433                                     res.getRootPath()), e);
434                             }
435                             break;
436                         }
437                     }
438                     fsFile.setLastModified(res.getDateLastModified());
439                 } else {
440
441                     m_report.print(Messages.get().container(Messages.RPT_EXPORT_FOLDER_0), I_CmsReport.FORMAT_NOTE);
442                     m_report.print(org.opencms.report.Messages.get().container(
443                         org.opencms.report.Messages.RPT_ARGUMENT_1,
444                         m_cms.getSitePath(res)));
445                     m_report.print(Messages.get().container(Messages.RPT_TO_FS_AS_0), I_CmsReport.FORMAT_NOTE);
446                     m_report.print(org.opencms.report.Messages.get().container(
447                         org.opencms.report.Messages.RPT_ARGUMENT_1,
448                         fsFile.getAbsolutePath().replace('\\', '/')));
449                     m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
450
451                     // its a folder, so create a folder in the FS
452
fsFile.mkdir();
453                 }
454                 // add resource to synchronisation list
455
CmsSynchronizeList syncList = new CmsSynchronizeList(
456                     resourcename,
457                     translate(resourcename),
458                     res.getDateLastModified(),
459                     fsFile.lastModified());
460                 m_newSyncList.put(translate(resourcename), syncList);
461                 // and remove it fomr the old one
462
m_syncList.remove(translate(resourcename));
463                 m_report.println(
464                     org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
465                     I_CmsReport.FORMAT_OK);
466             }
467             // free mem
468
vfsFile = null;
469
470         } catch (CmsException e) {
471             throw new CmsSynchronizeException(e.getMessageContainer(), e);
472         }
473     }
474
475     /**
476      * Gets the corresponding file to a resource in the VFS. <p>
477      *
478      * @param res path to the resource inside the VFS
479      * @return the corresponding file in the FS
480      */

481     private File getFileInRfs(String JavaDoc res) {
482
483         String JavaDoc path = m_destinationPathInRfs + res.substring(0, res.lastIndexOf("/"));
484         String JavaDoc fileName = res.substring(res.lastIndexOf("/") + 1);
485         return new File(path, fileName);
486     }
487
488     /**
489      * Gets the corresponding filename of the VFS to a resource in the FS. <p>
490      *
491      * @param res the resource in the FS
492      * @return the corresponding filename in the VFS
493      */

494     private String JavaDoc getFilenameInVfs(File res) {
495
496         String JavaDoc resname = res.getAbsolutePath();
497         if (res.isDirectory()) {
498             resname += "/";
499         }
500         // translate the folder seperator if nescessary
501
resname = resname.replace(File.separatorChar, '/');
502         return resname.substring(m_destinationPathInRfs.length());
503     }
504
505     /**
506      * Imports a new resource from the FS into the VFS and updates the
507      * synchronisation lists.<p>
508      *
509      * @param fsFile the file in the FS
510      * @param resName the name of the resource in the VFS
511      * @param folder the folder to import the file into
512      * @throws CmsException if something goes wrong
513      */

514     private void importToVfs(File fsFile, String JavaDoc resName, String JavaDoc folder) throws CmsException {
515
516         try {
517             // get the content of the FS file
518
byte[] content = CmsFileUtil.readFile(fsFile);
519
520             // create the file
521
String JavaDoc filename = translate(fsFile.getName());
522
523             m_report.print(org.opencms.report.Messages.get().container(
524                 org.opencms.report.Messages.RPT_SUCCESSION_1,
525                 String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
526             if (fsFile.isFile()) {
527                 m_report.print(Messages.get().container(Messages.RPT_IMPORT_FILE_0), I_CmsReport.FORMAT_NOTE);
528             } else {
529                 m_report.print(Messages.get().container(Messages.RPT_IMPORT_FOLDER_0), I_CmsReport.FORMAT_NOTE);
530             }
531
532             m_report.print(org.opencms.report.Messages.get().container(
533                 org.opencms.report.Messages.RPT_ARGUMENT_1,
534                 fsFile.getAbsolutePath().replace('\\', '/')));
535             m_report.print(Messages.get().container(Messages.RPT_FROM_FS_TO_0), I_CmsReport.FORMAT_NOTE);
536
537             // get the file type of the FS file
538
int resType = OpenCms.getResourceManager().getDefaultTypeForName(resName).getTypeId();
539             CmsResource newFile = m_cms.createResource(translate(folder) + filename, resType, content, new ArrayList JavaDoc());
540
541             m_report.print(org.opencms.report.Messages.get().container(
542                 org.opencms.report.Messages.RPT_ARGUMENT_1,
543                 m_cms.getSitePath(newFile)));
544             m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
545
546             // now check if there is some external method to be called which
547
// should modify the imported resource in the VFS
548
Iterator JavaDoc i = m_synchronizeModifications.iterator();
549             while (i.hasNext()) {
550                 try {
551                     ((I_CmsSynchronizeModification)i.next()).modifyVfs(m_cms, newFile, fsFile);
552                 } catch (CmsSynchronizeException e) {
553                     break;
554                 }
555             }
556             // we have to read the new resource again, to get the correct timestamp
557
m_cms.setDateLastModified(m_cms.getSitePath(newFile), fsFile.lastModified(), false);
558             CmsResource newRes = m_cms.readResource(m_cms.getSitePath(newFile));
559             // add resource to synchronisation list
560
CmsSynchronizeList syncList = new CmsSynchronizeList(
561                 resName,
562                 translate(resName),
563                 newRes.getDateLastModified(),
564                 fsFile.lastModified());
565             m_newSyncList.put(translate(resName), syncList);
566             // free mem
567
newFile = null;
568             content = null;
569
570             m_report.println(
571                 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
572                 I_CmsReport.FORMAT_OK);
573         } catch (IOException JavaDoc e) {
574             throw new CmsSynchronizeException(
575                 Messages.get().container(Messages.ERR_READING_FILE_1, fsFile.getName()),
576                 e);
577         }
578     }
579
580     /**
581      * Reads the synchronisation list from the last sync process form the file
582      * system and stores the information in a HashMap. <p>
583      *
584      * Filenames are stored as keys, CmsSynchronizeList objects as values.
585      * @return HashMap with synchronisation infomration of the last sync process
586      * @throws CmsException if something goes wrong
587      */

588     private HashMap JavaDoc readSyncList() throws CmsException {
589
590         HashMap JavaDoc syncList = new HashMap JavaDoc();
591
592         // the sync list file in the server fs
593
File syncListFile;
594         syncListFile = new File(m_destinationPathInRfs, SYNCLIST_FILENAME);
595         // try to read the sync list file if it is there
596
if (syncListFile.exists()) {
597             // prepare the streams to write the data
598
FileReader JavaDoc fIn = null;
599             LineNumberReader JavaDoc lIn = null;
600             try {
601                 fIn = new FileReader JavaDoc(syncListFile);
602                 lIn = new LineNumberReader JavaDoc(fIn);
603                 // read one line from the file
604
String JavaDoc line = lIn.readLine();
605                 while (line != null) {
606                     line = lIn.readLine();
607                     // extract the data and create a CmsSychroizedList object
608
// from it
609
if (line != null) {
610                         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(line, ":");
611                         if (tok != null) {
612                             String JavaDoc resName = tok.nextToken();
613                             String JavaDoc tranResName = tok.nextToken();
614                             long modifiedVfs = new Long JavaDoc(tok.nextToken()).longValue();
615                             long modifiedFs = new Long JavaDoc(tok.nextToken()).longValue();
616                             CmsSynchronizeList sync = new CmsSynchronizeList(
617                                 resName,
618                                 tranResName,
619                                 modifiedVfs,
620                                 modifiedFs);
621                             syncList.put(translate(resName), sync);
622                         }
623                     }
624                 }
625             } catch (IOException JavaDoc e) {
626                 throw new CmsSynchronizeException(Messages.get().container(Messages.ERR_READ_SYNC_LIST_0), e);
627             } finally {
628                 // close all streams that were used
629
try {
630                     if (lIn != null) {
631                         lIn.close();
632                     }
633                     if (fIn != null) {
634                         fIn.close();
635                     }
636                 } catch (IOException JavaDoc e) {
637                     // ignore
638
}
639             }
640         }
641
642         return syncList;
643     }
644
645     /**
646      * Removes all resources in the RFS which are deleted in the VFS.<p>
647      *
648      * @param folder the folder in the FS to check
649      * @throws CmsException if something goes wrong
650      */

651     private void removeFromRfs(String JavaDoc folder) throws CmsException {
652
653         // get the corresponding folder in the FS
654
File[] res;
655         File rfsFile = new File(folder);
656         // get all resources in this folder
657
res = rfsFile.listFiles();
658         // now loop through all resources
659
for (int i = 0; i < res.length; i++) {
660             // get the corrsponding name in the VFS
661
String JavaDoc vfsFile = getFilenameInVfs(res[i]);
662             // recurse if it is an directory, we must go depth first to delete
663
// files
664
if (res[i].isDirectory()) {
665                 removeFromRfs(res[i].getAbsolutePath());
666             }
667             // now check if this resource is still in the old sync list.
668
// if so, then it does not exist in the FS anymore andm ust be
669
// deleted
670
CmsSynchronizeList sync = (CmsSynchronizeList)m_syncList.get(translate(vfsFile));
671
672             // there is an entry, so delete the resource
673
if (sync != null) {
674
675                 m_report.print(org.opencms.report.Messages.get().container(
676                     org.opencms.report.Messages.RPT_SUCCESSION_1,
677                     String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
678                 if (res[i].isFile()) {
679                     m_report.print(Messages.get().container(Messages.RPT_DEL_FS_FILE_0), I_CmsReport.FORMAT_NOTE);
680                 } else {
681                     m_report.print(Messages.get().container(Messages.RPT_DEL_FS_FOLDER_0), I_CmsReport.FORMAT_NOTE);
682                 }
683                 m_report.print(org.opencms.report.Messages.get().container(
684                     org.opencms.report.Messages.RPT_ARGUMENT_1,
685                     res[i].getAbsolutePath().replace('\\', '/')));
686                 m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
687
688                 res[i].delete();
689                 m_syncList.remove(translate(vfsFile));
690
691                 m_report.println(
692                     org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
693                     I_CmsReport.FORMAT_OK);
694             }
695         }
696         // free mem
697
res = null;
698         rfsFile = null;
699     }
700
701     /**
702      * Updates the synchroinisation lists if a resource is not used during the
703      * synchronisation process.<p>
704      *
705      * @param res the resource whose entry must be updated
706      */

707     private void skipResource(CmsResource res) {
708
709         // add the file to the new sync list...
710
String JavaDoc resname = m_cms.getSitePath(res);
711         CmsSynchronizeList syncList = (CmsSynchronizeList)m_syncList.get(translate(resname));
712         m_newSyncList.put(translate(resname), syncList);
713         // .. and remove it from the old one
714
m_syncList.remove(translate(resname));
715         // update the report
716
m_report.print(org.opencms.report.Messages.get().container(
717             org.opencms.report.Messages.RPT_SUCCESSION_1,
718             String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
719         m_report.print(Messages.get().container(Messages.RPT_SKIPPING_0), I_CmsReport.FORMAT_NOTE);
720         m_report.println(org.opencms.report.Messages.get().container(
721             org.opencms.report.Messages.RPT_ARGUMENT_1,
722             resname));
723     }
724
725     /**
726      * Synchronizes resources from the VFS to the RFS. <p>
727      *
728      * During the synchronization process, the following actions will be done:<p>
729      *
730      * <ul>
731      * <li>Export modified resources from the VFS to the FS</li>
732      * <li>Update resources in the VFS if the corresponding resource in the FS
733      * has changed</li>
734      * <li>Delete resources in the VFS if the corresponding resource in the FS
735      * has been deleted</li>
736      * </ul>
737      *
738      * @param folder The folder in the VFS to be synchronized with the FS
739      * @throws CmsException if something goes wrong
740      */

741     private void syncVfsToRfs(String JavaDoc folder) throws CmsException {
742
743         int action = 0;
744         //get all resources in the given folder
745
List JavaDoc resources = m_cms.getResourcesInFolder(folder, CmsResourceFilter.IGNORE_EXPIRATION);
746         // now look through all resources in the folder
747
for (int i = 0; i < resources.size(); i++) {
748             CmsResource res = (CmsResource)resources.get(i);
749             // test if the resource is marked as deleted. if so,
750
// do nothing, the corrsponding file in the FS will be removed later
751
if (res.getState() != CmsResource.STATE_DELETED) {
752                 // do a recursion if the current resource is a folder
753
if (res.isFolder()) {
754                     // first check if this folder must be synchronised
755
action = testSyncVfs(res);
756                     // do the correct action according to the test result
757
if (action == EXPORT_VFS) {
758                         exportToRfs(res);
759                     } else if (action != DELETE_VFS) {
760                         skipResource(res);
761                     }
762                     // recurse into the subfolders. This must be done before
763
// the folder might be deleted!
764
syncVfsToRfs(m_cms.getSitePath(res));
765                     if (action == DELETE_VFS) {
766                         deleteFromVfs(res);
767                     }
768                 } else {
769                     // if the current resource is a file, check if it has to
770
// be synchronized
771
action = testSyncVfs(res);
772                     // do the correct action according to the test result
773
switch (action) {
774                         case EXPORT_VFS:
775                             exportToRfs(res);
776                             break;
777
778                         case UPDATE_VFS:
779                             updateFromRfs(res);
780                             break;
781
782                         case DELETE_VFS:
783                             deleteFromVfs(res);
784                             break;
785
786                         default:
787                             skipResource(res);
788
789                     }
790                 }
791                 // free mem
792
res = null;
793             }
794         }
795         // free mem
796
resources = null;
797     }
798
799     /**
800      * Determines the synchronisation status of a VFS resource. <p>
801      *
802      * @param res the VFS resource to check
803      * @return integer value for the action to be done for this VFS resource
804      */

805     private int testSyncVfs(CmsResource res) {
806
807         int action = 0;
808         File fsFile;
809         //data from sync list
810
String JavaDoc resourcename = m_cms.getSitePath(res);
811
812         if (m_syncList.containsKey(translate(resourcename))) {
813             // this resource was already used in a previous syncprocess
814
CmsSynchronizeList sync = (CmsSynchronizeList)m_syncList.get(translate(resourcename));
815             // get the corresponding resource from the FS
816
fsFile = getFileInRfs(sync.getResName());
817             // now check what to do with this resource.
818
// if the modification date is newer than the logged modification
819
// date in the sync list, this resource must be exported too
820
if (res.getDateLastModified() > sync.getModifiedVfs()) {
821                 // now check if the resource in the FS is newer, then the
822
// resource from the FS must be imported
823

824                 // check if it has been modified since the last sync process
825
// and its newer than the resource in the VFS, only then this
826
// resource must be imported form the FS
827
if ((fsFile.lastModified() > sync.getModifiedFs())
828                     && (fsFile.lastModified() > res.getDateLastModified())) {
829                     action = UPDATE_VFS;
830                 } else {
831
832                     action = EXPORT_VFS;
833                 }
834             } else {
835                 // test if the resource in the FS does not exist anymore.
836
// if so, remove the resource in the VFS
837
if (!fsFile.exists()) {
838                     action = DELETE_VFS;
839                 } else {
840                     // now check if the resource in the FS might have changed
841
if (fsFile.lastModified() > sync.getModifiedFs()) {
842                         action = UPDATE_VFS;
843                     }
844                 }
845             }
846         } else {
847             // the resource name was not found in the sync list
848
// this is a new resource
849
action = EXPORT_VFS;
850         }
851         //free mem
852
fsFile = null;
853         return action;
854     }
855
856     /**
857      * Translates the resource name. <p>
858      *
859      * This is nescessary since the server RFS does allow different naming
860      * conventions than the VFS.
861      *
862      * @param name the resource name to be translated
863      * @return the translated resource name
864      */

865     private String JavaDoc translate(String JavaDoc name) {
866
867         String JavaDoc translation = null;
868         // test if an external translation should be used
869
Iterator JavaDoc i = m_synchronizeModifications.iterator();
870         while (i.hasNext()) {
871             try {
872                 translation = ((I_CmsSynchronizeModification)i.next()).translate(m_cms, name);
873             } catch (CmsSynchronizeException e) {
874                 if (LOG.isInfoEnabled()) {
875                     LOG.info(Messages.get().getBundle().key(Messages.LOG_EXTERNAL_TRANSLATION_1, name), e);
876                 }
877                 break;
878             }
879         }
880         // if there was no external method called, do the default OpenCms
881
// RFS-VFS translation
882
if (translation == null) {
883             translation = m_cms.getRequestContext().getFileTranslator().translateResource(name);
884         }
885         return translation;
886     }
887
888     /**
889      * Imports a resource from the FS to the VFS and updates the
890      * synchronisation lists.<p>
891      *
892      * @param res the resource to be exported
893      *
894      * @throws CmsSynchronizeException if the resource could not be synchronized
895      * @throws CmsException if something goes wrong
896      */

897     private void updateFromRfs(CmsResource res) throws CmsSynchronizeException, CmsException {
898
899         CmsFile vfsFile;
900         // to get the name of the file in the FS, we must look it up in the
901
// sync list. This is nescessary, since the VFS could use a tranlated
902
// filename.
903
String JavaDoc resourcename = m_cms.getSitePath(res);
904         CmsSynchronizeList sync = (CmsSynchronizeList)m_syncList.get(translate(resourcename));
905         File fsFile = getFileInRfs(sync.getResName());
906
907         m_report.print(org.opencms.report.Messages.get().container(
908             org.opencms.report.Messages.RPT_SUCCESSION_1,
909             String.valueOf(m_count++)), I_CmsReport.FORMAT_NOTE);
910         m_report.print(Messages.get().container(Messages.RPT_UPDATE_FILE_0), I_CmsReport.FORMAT_NOTE);
911         m_report.print(org.opencms.report.Messages.get().container(
912             org.opencms.report.Messages.RPT_ARGUMENT_1,
913             resourcename));
914         m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0));
915
916         // lock the file in the VFS, so that it can be updated
917
m_cms.lockResource(resourcename);
918         // read the file in the VFS
919
vfsFile = m_cms.readFile(resourcename, CmsResourceFilter.IGNORE_EXPIRATION);
920         // import the content from the FS
921
try {
922             vfsFile.setContents(CmsFileUtil.readFile(fsFile));
923         } catch (IOException JavaDoc e) {
924             throw new CmsSynchronizeException(Messages.get().container(Messages.ERR_IMPORT_1, fsFile.getName()));
925         }
926         m_cms.writeFile(vfsFile);
927         // now check if there is some external method to be called which
928
// should modify
929
// the updated resource in the VFS
930
Iterator JavaDoc i = m_synchronizeModifications.iterator();
931         while (i.hasNext()) {
932             try {
933                 ((I_CmsSynchronizeModification)i.next()).modifyVfs(m_cms, vfsFile, fsFile);
934             } catch (CmsSynchronizeException e) {
935                 if (LOG.isInfoEnabled()) {
936                     LOG.info(
937                         Messages.get().getBundle().key(Messages.LOG_SYNCHRONIZE_UPDATE_FAILED_1, res.getRootPath()),
938                         e);
939                 }
940                 break;
941             }
942         }
943         // everything is done now, so unlock the resource
944
// read the resource again, nescessary to get the actual timestamps
945
m_cms.setDateLastModified(resourcename, fsFile.lastModified(), false);
946         res = m_cms.readResource(resourcename);
947
948         //add resource to synchronisation list
949
CmsSynchronizeList syncList = new CmsSynchronizeList(
950             sync.getResName(),
951             translate(resourcename),
952             res.getDateLastModified(),
953             fsFile.lastModified());
954         m_newSyncList.put(translate(resourcename), syncList);
955         // and remove it from the old one
956
m_syncList.remove(translate(resourcename));
957         vfsFile = null;
958
959         m_report.println(
960             org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0),
961             I_CmsReport.FORMAT_OK);
962     }
963
964     /**
965      * This writes the byte content of a resource to the file on the server
966      * filesystem.<p>
967      *
968      * @param content the content of the file in the VFS
969      * @param file the file in SFS that has to be updated with content
970      *
971      * @throws IOException if something goes wrong
972      */

973     private void writeFileByte(byte[] content, File file) throws IOException JavaDoc {
974
975         FileOutputStream JavaDoc fOut = null;
976         DataOutputStream JavaDoc dOut = null;
977         try {
978             // write the content to the file in server filesystem
979
fOut = new FileOutputStream JavaDoc(file);
980             dOut = new DataOutputStream JavaDoc(fOut);
981             dOut.write(content);
982             dOut.flush();
983         } catch (IOException JavaDoc e) {
984             throw e;
985         } finally {
986             try {
987                 if (fOut != null) {
988                     fOut.close();
989                 }
990             } catch (IOException JavaDoc e) {
991                 // ignore
992
}
993         }
994     }
995
996     /**
997      * Writes the synchronisation list of the current sync process to the
998      * server file system. <p>
999      *
1000     * The file can be found in the synchronization folder
1001     * @throws CmsException if something goes wrong
1002     */

1003    private void writeSyncList() throws CmsException {
1004
1005        // the sync list file in the server fs
1006
File syncListFile;
1007        syncListFile = new File(m_destinationPathInRfs, SYNCLIST_FILENAME);
1008
1009        // prepare the streams to write the data
1010
FileOutputStream JavaDoc fOut = null;
1011        PrintWriter JavaDoc pOut = null;
1012        try {
1013            fOut = new FileOutputStream JavaDoc(syncListFile);
1014            pOut = new PrintWriter JavaDoc(fOut);
1015            pOut.println(CmsSynchronizeList.getFormatDescription());
1016
1017            // get all keys from the hashmap and make an iterator on it
1018
Iterator JavaDoc values = m_newSyncList.values().iterator();
1019            // loop throush all values and write them to the sync list file in
1020
// a human readable format
1021
while (values.hasNext()) {
1022                CmsSynchronizeList sync = (CmsSynchronizeList)values.next();
1023                //fOut.write(sync.toString().getBytes());
1024
pOut.println(sync.toString());
1025            }
1026        } catch (IOException JavaDoc e) {
1027            throw new CmsDbIoException(Messages.get().container(Messages.ERR_IO_WRITE_SYNCLIST_0), e);
1028        } finally {
1029            // close all streams that were used
1030
try {
1031                pOut.flush();
1032                fOut.flush();
1033                if (pOut != null) {
1034                    pOut.close();
1035                }
1036                if (fOut != null) {
1037                    fOut.close();
1038                }
1039            } catch (IOException JavaDoc e) {
1040                // ignore
1041
}
1042        }
1043    }
1044}
Popular Tags