Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/opencms/defaults/master/genericsql/CmsDbAccess.java


1   /*
2   * File   : $Source: /usr/local/cvs/opencms/src/com/opencms/defaults/master/genericsql/CmsDbAccess.java,v $
3   * Date   : $Date: 2003/04/23 08:40:01 $
4   * Version: $Revision: 1.31 $
5   *
6   * This library is part of OpenCms -
7   * the Open Source Content Mananagement System
8   *
9   * Copyright (C) 2001  The OpenCms Group
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about OpenCms, please see the
22  * OpenCms Website: http://www.opencms.org
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  */
28  
29  package com.opencms.defaults.master.genericsql;
30  
31  import com.opencms.boot.CmsBase;
32  import com.opencms.boot.I_CmsLogChannels;
33  import com.opencms.core.CmsException;
34  import com.opencms.core.I_CmsConstants;
35  import com.opencms.dbpool.CmsIdGenerator;
36  import com.opencms.defaults.master.CmsMasterContent;
37  import com.opencms.defaults.master.CmsMasterDataSet;
38  import com.opencms.defaults.master.CmsMasterMedia;
39  import com.opencms.file.CmsGroup;
40  import com.opencms.file.CmsObject;
41  import com.opencms.file.CmsResource;
42  import com.opencms.file.CmsUser;
43  import com.opencms.util.Utils;
44  
45  import java.io.ByteArrayInputStream;
46  import java.lang.reflect.Constructor;
47  import java.sql.Connection;
48  import java.sql.DriverManager;
49  import java.sql.PreparedStatement;
50  import java.sql.ResultSet;
51  import java.sql.SQLException;
52  import java.sql.Statement;
53  import java.sql.Timestamp;
54  import java.sql.Types;
55  import java.util.Enumeration;
56  import java.util.HashMap;
57  import java.util.Iterator;
58  import java.util.Properties;
59  import java.util.Vector;
60  
61  /**
62   * This class provides methods to access the database in a generic way.
63   */
64  public class CmsDbAccess {
65  
66      public static final String C_COS_PREFIX = "/" + I_CmsConstants.C_ROOTNAME_COS;
67  
68      /** The pool to access offline ressources */
69      protected String m_poolName;
70  
71      /** The pool to access the online ressources */
72      protected String m_onlinePoolName;
73  
74      /** The pool to access the backup ressources */
75      protected String m_backupPoolName;
76  
77      /** The query properties for this accessmodule */
78      protected Properties m_queries;
79  
80      /** The root channel of the module */
81      protected String m_rootChannel = "/";
82  
83      /**
84       * Public empty constructor, call "init()" on this class afterwards.
85       * This allows more flexible custom module development.
86       * FLEX: Made the constructor public!
87       */
88      public CmsDbAccess() {
89      }
90  
91      /**
92       * Constructs a new DbAccessObject.
93       * @param poolName the pool to access offline ressources.
94       * @param onlinePoolName the pool to access the online ressources.
95       * @param backupPoolName the pool to access the backup ressources.
96       */
97      public CmsDbAccess(String poolName, String onlinePoolName, String backupPoolName) {
98          init(poolName, onlinePoolName, backupPoolName);
99      }
100     
101     /**
102      * Initializes the DBAccessObject.
103      */
104     public void init(String offline, String online, String backup) {
105         m_poolName = online;
106         m_onlinePoolName = offline;
107         m_backupPoolName = backup;
108         m_queries = new Properties();
109         // collect all query.properties in all packages of superclasses
110         loadQueries(getClass());
111         combineQueries();        
112     }
113 
114     /**
115      * Set the root channel
116      * @param newRootChannel the new value for the rootChannel
117      */
118     public void setRootChannel(String newRootChannel) {
119         m_rootChannel = newRootChannel;
120     }
121 
122     /**
123      * Get the root channel
124      */
125     public String getRootChannel() {
126         return m_rootChannel;
127     }
128 
129     /**
130      * Inserts a new row in the database with the dataset.
131      * @param cms the CmsObject to get access to cms-ressources.
132      * @param content the CmsMasterContent to write to the database.
133      * @param dataset the set of data for this contentdefinition.
134      * @param mediaToAdd a Vector of media to add.
135      */
136     public void insert(CmsObject cms, CmsMasterContent content,
137                        CmsMasterDataSet dataset)
138         throws CmsException {
139         if(isOnlineProject(cms)) {
140             // this is the onlineproject - don't write into this project directly
141             throw new CmsException("Can't write to the online project", CmsException.C_NO_ACCESS);
142         }
143         int newMasterId = CmsIdGenerator.nextId(m_poolName, "CMS_MODULE_MASTER");
144         int projectId = cms.getRequestContext().currentProject().getId();
145         int currentUserId = cms.getRequestContext().currentUser().getId();
146         long currentTime = new java.util.Date().getTime();
147         // filling some default-values for new dataset's
148         dataset.m_masterId = newMasterId;
149         dataset.m_userId = currentUserId;
150         dataset.m_groupId = cms.getRequestContext().currentGroup().getId();
151         dataset.m_projectId = projectId;
152         dataset.m_lockedInProject = projectId;
153         dataset.m_state = I_CmsConstants.C_STATE_NEW;
154         dataset.m_lockedBy = currentUserId;
155         dataset.m_lastModifiedBy = currentUserId;
156         dataset.m_dateCreated = currentTime;
157         dataset.m_dateLastModified = currentTime;
158 
159         PreparedStatement stmnt = null;
160         Connection con = null;
161         try {
162             con = DriverManager.getConnection(m_poolName);
163             stmnt = sqlPrepare(con, "insert_offline");
164             sqlFillValues(stmnt, content.getSubId(), dataset);
165             stmnt.executeUpdate();
166             // after inserting the row, we have to update media and channel tables
167             updateMedia(dataset.m_masterId, dataset.m_mediaToAdd, new Vector(), new Vector());
168             updateChannels(cms, dataset.m_masterId, dataset.m_channelToAdd, dataset.m_channelToDelete);
169         } catch(SQLException exc) {
170             throw new CmsException(CmsException.C_SQL_ERROR, exc);
171         } finally {
172             sqlClose(con, stmnt, null);
173         }
174     }
175 
176     /**
177      * Inserts a new row in the database with the copied dataset.
178      * @param cms the CmsObject to get access to cms-ressources.
179      * @param content the CmsMasterContent to write to the database.
180      * @param dataset the set of data for this contentdefinition.
181      * @param mediaToAdd a Vector of media to add.
182      * @param channelToAdd a Vector of channels to add.
183      * @return int The id of the new content definition
184      */
185     public int copy(CmsObject cms, CmsMasterContent content,
186                        CmsMasterDataSet dataset, Vector mediaToAdd, Vector channelToAdd)
187         throws CmsException {
188         if(isOnlineProject(cms)) {
189             // this is the onlineproject - don't write into this project directly
190             throw new CmsException("Can't write to the online project", CmsException.C_NO_ACCESS);
191         }
192         if(dataset.m_versionId != I_CmsConstants.C_UNKNOWN_ID) {
193             // this is not the online row - it was read from history
194             // don't write it!
195             throw new CmsException("Can't update a cd with a backup cd ", CmsException.C_NO_ACCESS);
196         }
197         if(!content.isWriteable()) {
198             // no write access
199             throw new CmsException("Not writeable", CmsException.C_NO_ACCESS);
200         }
201         int newMasterId = CmsIdGenerator.nextId(m_poolName, "CMS_MODULE_MASTER");
202         int projectId = cms.getRequestContext().currentProject().getId();
203         int currentUserId = cms.getRequestContext().currentUser().getId();
204         long currentTime = new java.util.Date().getTime();
205         // filling some default-values for new dataset's
206         dataset.m_masterId = newMasterId;
207         dataset.m_projectId = projectId;
208         dataset.m_lockedInProject = projectId;
209         dataset.m_state = I_CmsConstants.C_STATE_NEW;
210         dataset.m_lockedBy = currentUserId;
211         dataset.m_lastModifiedBy = currentUserId;
212         dataset.m_dateCreated = currentTime;
213         dataset.m_dateLastModified = currentTime;
214 
215         PreparedStatement stmnt = null;
216         Connection con = null;
217         try {
218             con = DriverManager.getConnection(m_poolName);
219             stmnt = sqlPrepare(con, "insert_offline");
220             sqlFillValues(stmnt, content.getSubId(), dataset);
221             stmnt.executeUpdate();
222             // after inserting the row, we have to update media and channel tables
223             updateMedia(dataset.m_masterId, mediaToAdd, new Vector(), new Vector());
224             updateChannels(cms, dataset.m_masterId, channelToAdd, new Vector());
225         } catch(SQLException exc) {
226             throw new CmsException(CmsException.C_SQL_ERROR, exc);
227         } finally {
228             sqlClose(con, stmnt, null);
229         }
230         return newMasterId;
231     }
232 
233     /**
234      * Updates the lockstate in the database.
235      * @param cms the CmsObject to get access to cms-ressources.
236      * @param content the CmsMasterContent to write to the database.
237      * @param dataset the set of data for this contentdefinition.
238      */
239     public void writeLockstate(CmsObject cms, CmsMasterContent content, CmsMasterDataSet dataset)
240         throws CmsException {
241         if(isOnlineProject(cms)) {
242             // this is the onlineproject - don't write into this project directly
243             throw new CmsException("Can't lock in the online project", CmsException.C_NO_ACCESS);
244         }
245         if(!content.isWriteable()) {
246             // no write access
247             throw new CmsException("Not writeable", CmsException.C_NO_ACCESS);
248         }
249         if(dataset.m_lockedBy <= -1) {
250             // unlock the cd
251             dataset.m_lockedBy = -1;
252         } else {
253             // lock the ressource into the current project
254             dataset.m_lockedInProject = cms.getRequestContext().currentProject().getId();
255         }
256 
257         PreparedStatement stmnt = null;
258         Connection con = null;
259         try {
260             con = DriverManager.getConnection(m_poolName);
261             stmnt = sqlPrepare(con, "update_lockstate_offline");
262             stmnt.setInt(1, dataset.m_lockedBy);
263             stmnt.setInt(2, dataset.m_lockedInProject);
264             stmnt.setInt(3, dataset.m_masterId);
265             stmnt.setInt(4, content.getSubId());
266             stmnt.executeUpdate();
267         } catch(SQLException exc) {
268             throw new CmsException(CmsException.C_SQL_ERROR, exc);
269         } finally {
270             sqlClose(con, stmnt, null);
271         }
272     }
273 
274     /**
275      * @param cms the CmsObject to get access to cms-ressources.
276      * @param content the CmsMasterContent to write to the database.
277      * @param dataset the set of data for this contentdefinition.
278      */
279     public void write(CmsObject cms, CmsMasterContent content, CmsMasterDataSet dataset)
280         throws CmsException {
281         if(isOnlineProject(cms)) {
282             // this is the onlineproject - don't write into this project directly
283             throw new CmsException("Can't write to the online project", CmsException.C_NO_ACCESS);
284         }
285         if(dataset.m_versionId != I_CmsConstants.C_UNKNOWN_ID) {
286             // this is not the online row - it was read from history
287             // don't write it!
288             throw new CmsException("Can't update a cd with a backup cd ", CmsException.C_NO_ACCESS);
289         }
290         // read the lockstate
291         readLockstate(dataset, content.getSubId());
292         if((dataset.m_lockedBy != cms.getRequestContext().currentUser().getId())) {
293             // is not locked by this user
294             throw new CmsException("Not locked by this user", CmsException.C_NO_ACCESS);
295         }
296         if(dataset.m_lockedInProject != dataset.m_projectId) {
297             // not locked in this project
298             throw new CmsException("Not locked in this project", CmsException.C_NO_ACCESS);
299         }
300         if(!content.isWriteable()) {
301             // no write access
302             throw new CmsException("Not writeable", CmsException.C_NO_ACCESS);
303         }
304 
305         long currentTime = new java.util.Date().getTime();
306         int currentUserId = cms.getRequestContext().currentUser().getId();
307         // updateing some values for updated dataset
308         if(dataset.m_state != I_CmsConstants.C_STATE_NEW) {
309             // if the state is not new then set the state to changed
310             dataset.m_state = I_CmsConstants.C_STATE_CHANGED;
311         }
312         dataset.m_lastModifiedBy = currentUserId;
313         dataset.m_dateLastModified = currentTime;
314 
315         PreparedStatement stmnt = null;
316         Connection con = null;
317         try {
318             con = DriverManager.getConnection(m_poolName);
319             stmnt = sqlPrepare(con, "update_offline");
320             int rowcounter = sqlFillValues(stmnt, content.getSubId(), dataset);
321             stmnt.setInt(rowcounter++, dataset.m_masterId);
322             stmnt.setInt(rowcounter++, content.getSubId());
323             stmnt.executeUpdate();
324             // after inserting the row, we have to update media and channel tables
325             updateMedia(dataset.m_masterId, dataset.m_mediaToAdd, dataset.m_mediaToUpdate, dataset.m_mediaToDelete);
326             updateChannels(cms, dataset.m_masterId, dataset.m_channelToAdd, dataset.m_channelToDelete);
327         } catch(SQLException exc) {
328             throw new CmsException(CmsException.C_SQL_ERROR, exc);
329         } finally {
330             sqlClose(con, stmnt, null);
331         }
332     }
333 
334     /**
335      * @param cms the CmsObject to get access to cms-ressources.
336      * @param content the CmsMasterContent to write to the database.
337      * @param dataset the set of data for this contentdefinition.
338      */
339     public void read(CmsObject cms, CmsMasterContent content, CmsMasterDataSet dataset, int masterId)
340         throws CmsException {
341         if(!content.isReadable()) {
342             // no read access
343             throw new CmsException("Not readable", CmsException.C_NO_ACCESS);
344         }
345         String statement_key = "read_offline";
346         String poolToUse = m_poolName;
347         if(isOnlineProject(cms)) {
348             statement_key = "read_online";
349             poolToUse = m_onlinePoolName;
350         }
351 
352         PreparedStatement stmnt = null;
353         ResultSet res = null;
354         Connection con = null;
355         try {
356             con = DriverManager.getConnection(poolToUse);
357             stmnt = sqlPrepare(con, statement_key);
358             stmnt.setInt(1, masterId);
359             stmnt.setInt(2, content.getSubId());
360             res = stmnt.executeQuery();
361             if(res.next()) {
362                 sqlFillValues(res, cms, dataset);
363             } else {
364                 throw new CmsException( "[" + this.getClass().getName() + ".read] no content found for CID:" + masterId + ", SID: " + content.getSubId() + ", statement: " + statement_key, CmsException.C_NOT_FOUND);
365             }
366             if(!checkAccess(content, false)) {
367                 throw new CmsException("Not readable", CmsException.C_NO_ACCESS);
368             }
369         } catch(SQLException exc) {
370             throw new CmsException(CmsException.C_SQL_ERROR, exc);
371         } finally {
372             sqlClose(con, stmnt, res);
373         }
374     }
375 
376     /**
377      * Read the lockstate from the database.
378      * We nned this, because of someone has maybe stolen the lock.
379      * @param dataset the dataset to read the lockstate into.
380      * @param subId the subId of this cd
381      */
382     protected void readLockstate(CmsMasterDataSet dataset, int subId) throws CmsException {
383         PreparedStatement stmnt = null;
384         ResultSet res = null;
385         Connection con = null;
386         try {
387             con = DriverManager.getConnection(m_poolName);
388             stmnt = sqlPrepare(con, "read_lockstate_offline");
389             stmnt.setInt(1, dataset.m_masterId);
390             stmnt.setInt(2, subId);
391             res = stmnt.executeQuery();
392             if(res.next()) {
393                 // update the values
394                 dataset.m_lockedInProject = res.getInt(1);
395                 dataset.m_lockedBy = res.getInt(2);
396             } else {
397                 // no values found - this is a new row
398             }
399         } catch(SQLException exc) {
400             throw new CmsException(CmsException.C_SQL_ERROR, exc);
401         } finally {
402             sqlClose(con, stmnt, res);
403         }
404     }
405 
406     /**
407      * Reads all media from the database.
408      * @param cms the CmsObject to get access to cms-ressources.
409      * @param content the CmsMasterContent to write to the database.
410      * @return a Vector of media objects.
411      */
412     public Vector readMedia(CmsObject cms, CmsMasterContent content)
413         throws CmsException {
414         if(!content.isReadable()) {
415             // no read access
416             throw new CmsException("Not readable", CmsException.C_NO_ACCESS);
417         }
418         Vector retValue = new Vector();
419         String statement_key = "read_media_offline";
420         String poolToUse = m_poolName;
421         if(isOnlineProject(cms)) {
422             statement_key = "read_media_online";
423             poolToUse = m_onlinePoolName;
424         }
425 
426         PreparedStatement stmnt = null;
427         ResultSet res = null;
428         Connection con = null;
429         try {
430             con = DriverManager.getConnection(poolToUse);
431             stmnt = sqlPrepare(con, statement_key);
432             stmnt.setInt(1, content.getId());
433             res = stmnt.executeQuery();
434             while(res.next()) {
435                 int i = 1;
436                 retValue.add(new CmsMasterMedia (
437                     res.getInt(i++),
438                     res.getInt(i++),
439                     res.getInt(i++),
440                     res.getInt(i++),
441                     res.getInt(i++),
442                     res.getInt(i++),
443                     res.getString(i++),
444                     res.getInt(i++),
445                     res.getString(i++),
446                     res.getString(i++),
447                     res.getString(i++),
448                     res.getBytes(i++)
449                 ));
450             }
451         } catch(SQLException exc) {
452             throw new CmsException(CmsException.C_SQL_ERROR, exc);
453         } finally {
454             sqlClose(con, stmnt, res);
455         }
456         return retValue;
457     }
458 
459     /**
460      * Reads all channels from the database.
461      * @param cms the CmsObject to get access to cms-ressources.
462      * @param content the CmsMasterContent to write to the database.
463      * @return a Vector of channel names.
464      */
465     public Vector readChannels(CmsObject cms, CmsMasterContent content)
466         throws CmsException {
467         if(!content.isReadable()) {
468             // no read access
469             throw new CmsException("Not readable", CmsException.C_NO_ACCESS);
470         }
471         Vector retValue = new Vector();
472         String statement_key = "read_channel_offline";
473         String poolToUse = m_poolName;
474         if(isOnlineProject(cms)) {
475             statement_key = "read_channel_online";
476             poolToUse = m_onlinePoolName;
477         }
478 
479         PreparedStatement stmnt = null;
480         ResultSet res = null;
481         Connection con = null;
482         try {
483             con = DriverManager.getConnection(poolToUse);
484             stmnt = sqlPrepare(con, statement_key);
485             stmnt.setInt(1, content.getId());
486             res = stmnt.executeQuery();
487             while(res.next()) {
488                 // get the channel id
489                 int channeldId = res.getInt(1);
490                 // read the resource by property "channelid"
491                 cms.setContextToCos();
492                 Vector resources = new Vector();
493                 try {
494                     resources = cms.getResourcesWithProperty(I_CmsConstants.C_PROPERTY_CHANNELID, channeldId+"", I_CmsConstants.C_TYPE_FOLDER);
495                 } catch(CmsException exc) {
496                     // ignore the exception - switch to next channel
497                 }
498                 cms.setContextToVfs();
499                 if(resources.size() >= 1) {
500                     // add the name of the channel to the ret-value
501                     CmsResource resource = (CmsResource)resources.get(0);
502                     if (resource.getState() != CmsResource.C_STATE_DELETED) {
503                         retValue.add(resource.getAbsolutePath());
504                     }
505                 }
506             }
507         } catch(SQLException exc) {
508             throw new CmsException(CmsException.C_SQL_ERROR, exc);
509         } finally {
510             sqlClose(con, stmnt, res);
511         }
512         return retValue;
513     }
514 
515     /**
516      * Reads all content definitions of a given channel
517      * @param cms the CmsObject to get access to cms-ressources.
518      * @param channelId the id of the channel.
519      * @return Vector The datasets of the contentdefinitions in the channel
520      */
521     public Vector readAllByChannel(CmsObject cms, int channelId, int subId)
522         throws CmsException {
523         Vector theDataSets = new Vector();
524         String statement_key = "readallbychannel_offline";
525         String poolToUse = m_poolName;
526         if(isOnlineProject(cms)) {
527             statement_key = "readallbychannel_online";
528             poolToUse = m_onlinePoolName;
529         }
530 
531         PreparedStatement stmnt = null;
532         ResultSet res = null;
533         Connection con = null;
534         try {
535             con = DriverManager.getConnection(poolToUse);
536             stmnt = sqlPrepare(con, statement_key);
537             stmnt.setInt(1, subId);
538             stmnt.setInt(2, channelId);
539             res = stmnt.executeQuery();
540             while(res.next()) {
541                 CmsMasterDataSet dataset = new CmsMasterDataSet();
542                 sqlFillValues(res, cms, dataset);
543                 theDataSets.add(dataset);
544             }
545         } catch(SQLException exc) {
546             throw new CmsException(CmsException.C_SQL_ERROR, exc);
547         } finally {
548             sqlClose(con, stmnt, res);
549         }
550         return theDataSets;
551     }
552 
553     /**
554      * @param cms the CmsObject to get access to cms-ressources.
555      * @param content the CmsMasterContent to write to the database.
556      * @param dataset the set of data for this contentdefinition.
557      */
558     public void delete(CmsObject cms, CmsMasterContent content, CmsMasterDataSet dataset)
559         throws CmsException {
560         if(isOnlineProject(cms)) {
561             // this is the onlineproject - don't write into this project directly
562             throw new CmsException("Can't delete from the online project", CmsException.C_NO_ACCESS);
563         }
564         if(dataset.m_versionId != I_CmsConstants.C_UNKNOWN_ID) {
565             // this is not the online row - it was read from history
566             // don't delete it!
567             throw new CmsException("Can't delete a backup cd ", CmsException.C_NO_ACCESS);
568         }
569         // read the lockstate
570         readLockstate(dataset, content.getSubId());
571         if((dataset.m_lockedBy != cms.getRequestContext().currentUser().getId())) {
572             // is not locked by this user
573             throw new CmsException("Not locked by this user", CmsException.C_NO_ACCESS);
574         }
575         if(dataset.m_lockedInProject != dataset.m_projectId) {
576             // not locked in this project
577             throw new CmsException("Not locked in this project", CmsException.C_NO_ACCESS);
578         }
579         if(!content.isWriteable()) {
580             // no write access
581             throw new CmsException("Not writeable", CmsException.C_NO_ACCESS);
582         }
583 
584         if(dataset.m_state == I_CmsConstants.C_STATE_NEW) {
585             // this is a new line in this project and can be deleted
586             String statement_key = "delete_offline";
587             PreparedStatement stmnt = null;
588             Connection con = null;
589             try {
590                 con = DriverManager.getConnection(m_poolName);
591                 stmnt = sqlPrepare(con, statement_key);
592                 stmnt.setInt(1, dataset.m_masterId);
593                 stmnt.setInt(2, content.getSubId());
594                 if(stmnt.executeUpdate() != 1) {
595                     // no line deleted - row wasn't found
596                     throw new CmsException("Row not found: " + dataset.m_masterId + " " + content.getSubId(), CmsException.C_NOT_FOUND);
597                 }
598                 // after deleting the row, we have to delete media and channel rows
599                 deleteAllMedia(dataset.m_masterId);
600                 deleteAllChannels(dataset.m_masterId);
601             } catch(SQLException exc) {
602                 throw new CmsException(CmsException.C_SQL_ERROR, exc);
603             } finally {
604                 sqlClose(con, stmnt, null);
605             }
606         } else {
607             // set state to deleted and update the line
608             dataset.m_state = I_CmsConstants.C_STATE_DELETED;
609             dataset.m_lockedBy = I_CmsConstants.C_UNKNOWN_ID;
610             PreparedStatement stmnt = null;
611             Connection con = null;
612             try {
613                 con = DriverManager.getConnection(m_poolName);
614                 stmnt = sqlPrepare(con, "update_offline");
615                 int rowcounter = sqlFillValues(stmnt, content.getSubId(), dataset);
616                 stmnt.setInt(rowcounter++, dataset.m_masterId);
617                 stmnt.setInt(rowcounter++, content.getSubId());
618                 stmnt.executeUpdate();
619             } catch(SQLException exc) {
620                 throw new CmsException(CmsException.C_SQL_ERROR, exc);
621             } finally {
622                 sqlClose(con, stmnt, null);
623             }
624         }
625     }
626 
627     /**
628      * @param cms the CmsObject to get access to cms-ressources.
629      * @param content the CmsMasterContent to write to the database.
630      * @param dataset the set of data for this contentdefinition.
631      */
632     public void undelete(CmsObject cms, CmsMasterContent content, CmsMasterDataSet dataset)
633         throws CmsException {
634         if(isOnlineProject(cms)) {
635             // this is the onlineproject - don't write into this project directly
636             throw new CmsException("Can't undelete from the online project", CmsException.C_NO_ACCESS);
637         }
638         if(dataset.m_versionId != I_CmsConstants.C_UNKNOWN_ID) {
639             // this is not the online row - it was read from history
640             // don't delete it!
641             throw new CmsException("Can't undelete a backup cd ", CmsException.C_NO_ACCESS);
642         }
643         if(!content.isWriteable()) {
644             // no write access
645             throw new CmsException("Not writeable", CmsException.C_NO_ACCESS);
646         }
647         // set state to deleted and update the line
648         dataset.m_state = I_CmsConstants.C_STATE_CHANGED;
649         dataset.m_lockedBy = cms.getRequestContext().currentUser().getId();
650         dataset.m_lockedInProject = cms.getRequestContext().currentProject().getId();
651         PreparedStatement stmnt = null;
652         Connection con = null;
653         try {
654             con = DriverManager.getConnection(m_poolName);
655             stmnt = sqlPrepare(con, "update_offline");
656             int rowcounter = sqlFillValues(stmnt, content.getSubId(), dataset);
657             stmnt.setInt(rowcounter++, dataset.m_masterId);
658             stmnt.setInt(rowcounter++, content.getSubId());
659             stmnt.executeUpdate();
660         } catch(SQLException exc) {
661             throw new CmsException(CmsException.C_SQL_ERROR, exc);
662         } finally {
663             sqlClose(con, stmnt, null);
664         }
665     }
666 
667     /**
668      * Changes the perrmissions of the Master
669      *
670      * @param cms the CmsObject to get access to cms-ressources.
671      * @param content the CmsMasterContent to write to the database.
672      * @param dataset the set of data for this contentdefinition.
673      */
674     public void changePermissions(CmsObject cms, CmsMasterContent content, CmsMasterDataSet dataset) throws CmsException {
675         if(isOnlineProject(cms)) {
676             // this is the onlineproject - don't write into this project directly
677             throw new CmsException("Can't change permissions in online project", CmsException.C_NO_ACCESS);
678         }
679         if(dataset.m_versionId != I_CmsConstants.C_UNKNOWN_ID) {
680             // this is not the online row - it was read from history
681             // don't delete it!
682             throw new CmsException("Can't change permissions of a backup cd ", CmsException.C_NO_ACCESS);
683         }
684         // read the lockstate
685         readLockstate(dataset, content.getSubId());
686         if((dataset.m_lockedBy != cms.getRequestContext().currentUser().getId())) {
687             // is not locked by this user
688             throw new CmsException("Not locked by this user", CmsException.C_NO_ACCESS);
689         }
690         if(dataset.m_lockedInProject != dataset.m_projectId) {
691             // not locked in this project
692             throw new CmsException("Not locked in this project", CmsException.C_NO_ACCESS);
693         }
694         if(!content.isWriteable()) {
695             // no write access
696             throw new CmsException("Not writeable", CmsException.C_NO_ACCESS);
697         }
698         if (dataset.m_state != I_CmsConstants.C_STATE_NEW){
699             dataset.m_state = I_CmsConstants.C_STATE_CHANGED;
700         }
701         dataset.m_dateLastModified = System.currentTimeMillis();
702         dataset.m_lastModifiedBy = cms.getRequestContext().currentUser().getId();
703         // update the line
704         PreparedStatement stmnt = null;
705         Connection con = null;
706         try {
707             con = DriverManager.getConnection(m_poolName);
708             stmnt = sqlPrepare(con, "update_permissions_offline");
709             stmnt.setInt(1, dataset.m_userId);
710             stmnt.setInt(2, dataset.m_groupId);
711             stmnt.setInt(3, dataset.m_accessFlags);
712             stmnt.setInt(4, dataset.m_state);
713             stmnt.setInt(5, dataset.m_lastModifiedBy);
714             stmnt.setTimestamp(6, new Timestamp(dataset.m_dateLastModified));
715             stmnt.setInt(7, dataset.m_masterId);
716             stmnt.setInt(8, content.getSubId());
717             stmnt.executeUpdate();
718         } catch(SQLException exc) {
719             throw new CmsException(CmsException.C_SQL_ERROR, exc);
720         } finally {
721             sqlClose(con, stmnt, null);
722         }
723     }
724 
725     /**
726      * Returns a string representation of this instance.
727      * This can be used for debugging.
728      * @return the string representation of this instance.
729      */
730     public String toString() {
731         StringBuffer returnValue = new StringBuffer();
732         returnValue.append(this.getClass().getName() + "{");
733         returnValue.append("m_poolName="+m_poolName+";");
734         returnValue.append("m_backupPoolName="+m_backupPoolName+";");
735         returnValue.append("m_onlinePoolName="+m_onlinePoolName+";");
736         returnValue.append("m_queries="+m_queries + "}");
737         return returnValue.toString();
738     }
739 
740     /**
741      * Loads recursively all query.properties from all packages of the
742      * superclasses. This method calls recuresively itself with the superclass
743      * (if exists) as parameter.
744      *
745      * @param the currentClass of the dbaccess module.
746      */
747     private void loadQueries(Class currentClass) {
748         // creates the queryFilenam from the packagename and
749         // filename query.properties
750         String className = currentClass.getName();
751         String queryFilename = className.substring(0, className.lastIndexOf('.'));
752         queryFilename = queryFilename.replace('.','/') + "/query.properties";
753         // gets the superclass and calls this method recursively
754         Class superClass = currentClass.getSuperclass();
755         if(superClass != java.lang.Object.class) {
756             loadQueries(superClass);
757         }
758         try {
759             // load the queries. Entries of the most recent class will overwrite
760             // entries of superclasses.
761             m_queries.load(getClass().getClassLoader().getResourceAsStream(queryFilename));
762         } catch(Exception exc) {
763             // no query.properties found - write to logstream.
764             if(CmsBase.isLogging()) {
765                 CmsBase.log(CmsBase.C_MODULE_DEBUG, "[CmsDbAccess] Couldn't load " + queryFilename + " errormessage: " + exc.getMessage());
766             }
767         }
768     }
769 
770     /**
771      * Combines the queries in the properties to complete quereis. Therefor a
772      * replacement is needed: The follwing Strings will be replaces
773      * automatically by the corresponding property-entrys:
774      * ${property_key}
775      */
776     private void combineQueries() {
777         Enumeration keys = m_queries.keys();
778         while(keys.hasMoreElements()) {
779             String key = (String)keys.nextElement();
780             // replace while there has benn repacements performaend
781             while(replace(key));
782         }
783     }
784 
785     /**
786      * Computes one run of the replacement for one query.
787      * Stores the new value into m_queries.
788      * @param key the key for the query to compute.
789      * @return if in this run replacements are done.
790      */
791     private boolean replace(String key) {
792         boolean retValue = false;
793         String value = m_queries.getProperty(key);
794         String newValue = new String();
795         int index = 0;
796         int lastIndex = 0;
797         // run as long as there are "${" strings found
798         while(index != -1) {
799             index = value.indexOf("${", lastIndex);
800             if(index != -1) {
801                 retValue = true;
802                 int nextIndex = value.indexOf('}', index);
803                 if(nextIndex != -1) {
804                     // get the replacer key
805                     String replacer = value.substring(index+2, nextIndex);
806                     // copy the first part of the query
807                     newValue += value.substring(lastIndex, index);
808                     // copy the replcement-value
809                     newValue += m_queries.getProperty(replacer, "");
810                     // set up lastindex
811                     lastIndex = nextIndex+1;
812                 } else {
813                     // no key found, just copy the query-part
814                     newValue += value.substring(lastIndex, index+2);
815                     // set up lastindex
816                     lastIndex = index+2;
817                 }
818             } else {
819                 // end of the string, copy the tail into new value
820                 newValue += value.substring(lastIndex);
821             }
822         }
823         // put back the new query to the queries
824         m_queries.put(key, newValue);
825         // returns true, if replacements were made in this run
826         return retValue;
827     }
828 
829     /**
830      * Creates a new connection and prepares a stement.
831      * @param con the Connection to use.
832      * @param queryKey the key for the query to use. The query will be get
833      * by m_queries.getParameter(key)
834      */
835     protected PreparedStatement sqlPrepare(Connection con, String queryKey) throws SQLException {
836         return con.prepareStatement(m_queries.getProperty(queryKey, ""));
837     }
838 
839     /**
840      * Creates a new connection and prepares a stement.
841      * @param cms the CmsObject to get access to cms-ressources.
842      * @param con the Connection to use.
843      * @param queryKey the key for the query to use. The query will be get
844      * by m_queries.getParameter(key)
845      */
846     protected PreparedStatement sqlPrepare(CmsObject cms, Connection con, String queryKey) throws SQLException {
847         return this.sqlPrepare(cms, con, queryKey, null);
848     }
849     
850     /**
851      * Replaces in a SQL statement $XXX tokens by strings and returns a prepared statement.
852      * 
853      * @param cms the current user's CmsObject instance
854      * @param con the JDBC connection
855      * @param queryKey the name of the SQL statement (in query.properties)
856      * @param optionalSqlTokens a HashMap with optional SQL tokens to be replaced in the SQL statement
857      * @return a new PreparedStatement
858      * @throws SQLException
859      */
860     protected PreparedStatement sqlPrepare(CmsObject cms, Connection con, String queryKey, HashMap optionalSqlTokens) throws SQLException {
861         String statement = null;
862         String moduleMaster = null;
863         String channelRel = null;
864         String media = null;
865 
866         // get the string of the SQL statement
867         statement = m_queries.getProperty(queryKey, "");
868 
869         // choose the right tables depending on the online/offline project
870         if (isOnlineProject(cms)) {
871             moduleMaster = "CMS_MODULE_ONLINE_MASTER";
872             channelRel = "CMS_MODULE_ONLINE_CHANNEL_REL";
873             media = "CMS_MODULE_ONLINE_MEDIA";
874         } else {
875             moduleMaster = "CMS_MODULE_MASTER";
876             channelRel = "CMS_MODULE_CHANNEL_REL";
877             media = "CMS_MODULE_MEDIA";
878         }
879 
880         // replace in the SQL statement the table names
881         statement = Utils.replace(statement, "$CMS_MODULE_MASTER", moduleMaster);
882         statement = Utils.replace(statement, "$CMS_MODULE_CHANNEL_REL", channelRel);
883         statement = Utils.replace(statement, "$CMS_MODULE_MEDIA", media);
884 
885         // replace in the SQL statement further optional SQL tokens
886         if (optionalSqlTokens != null) {
887             Iterator optionalSqlKeys = optionalSqlTokens.keySet().iterator();
888             while (optionalSqlKeys.hasNext()) {
889                 String currentKey = (String) optionalSqlKeys.next();
890                 String currentValue = (String) optionalSqlTokens.get(currentKey);
891                 statement = Utils.replace(statement, currentKey, currentValue);
892             }
893         }
894 
895         //System.err.println(statement);
896 
897         return con.prepareStatement(statement);
898     }
899 
900     /**
901      * Closes all sql ressources.
902      * @param con the Connection to close.
903      * @param stmnt the SqlStatement to close.
904      * @param resr the ResultSet to close.
905      */
906     protected void sqlClose(Connection con, Statement stmnt, ResultSet res) {
907         try {
908             res.close();
909         } catch (Exception e) {
910             // ignore the exception
911         } finally {
912             res = null;
913         }
914 
915         try {
916             stmnt.close();
917         } catch (Exception e) {
918             // ignore the exception
919         } finally {
920             stmnt = null;
921         }
922 
923         try {
924             con.close();
925         } catch (Exception e) {
926             // ignore the exception
927         } finally {
928             con = null;
929         }
930     }
931 
932     /**
933      * Inserts all values to the statement for insert and update.
934      * @param stmnt the Statement to fill the values to.
935      * @param cms the CmsObject to get access to cms-ressources.
936      * @param subId the subid of this module.
937      * @param dataset the set of data for this contentdefinition.
938      * @return the actual rowcounter.
939      */
940     protected int sqlFillValues(PreparedStatement stmnt, int subId, CmsMasterDataSet dataset)
941         throws SQLException {
942         // columncounter
943         int i = 1;
944         //// COREDATA ////
945         stmnt.setInt(i++,dataset.m_masterId);
946         stmnt.setInt(i++,subId);
947         stmnt.setInt(i++,dataset.m_userId);
948         stmnt.setInt(i++,dataset.m_groupId);
949         stmnt.setInt(i++,dataset.m_lockedInProject);
950         stmnt.setInt(i++,dataset.m_accessFlags);
951         stmnt.setInt(i++,dataset.m_state);
952         stmnt.setInt(i++,dataset.m_lockedBy);
953         stmnt.setInt(i++,dataset.m_lastModifiedBy);
954         stmnt.setTimestamp(i++,new Timestamp(dataset.m_dateCreated));
955         stmnt.setTimestamp(i++,new Timestamp(dataset.m_dateLastModified));
956         //// USERDATA ////
957         stmnt.setTimestamp(i++,new Timestamp(dataset.m_publicationDate));
958         stmnt.setTimestamp(i++,new Timestamp(dataset.m_purgeDate));
959         stmnt.setInt(i++,dataset.m_flags);
960         stmnt.setInt(i++,dataset.m_feedId);
961         stmnt.setInt(i++,dataset.m_feedReference);
962         if(dataset.m_feedFilename == null){
963             stmnt.setNull(i++,Types.VARCHAR);
964         } else {
965             stmnt.setString(i++,dataset.m_feedFilename);
966         }
967         if(dataset.m_title == null){
968             stmnt.setNull(i++,Types.VARCHAR);
969         } else {
970             stmnt.setString(i++,dataset.m_title);
971         }
972         //// GENERIC DATA ////
973         i = sqlSetTextArray(stmnt, dataset.m_dataBig, i);
974         i = sqlSetTextArray(stmnt, dataset.m_dataMedium, i);
975         i = sqlSetTextArray(stmnt, dataset.m_dataSmall, i);
976         i = sqlSetIntArray(stmnt, dataset.m_dataInt, i);
977         i = sqlSetIntArray(stmnt, dataset.m_dataReference, i);
978         i = sqlSetDateArray(stmnt, dataset.m_dataDate, i);
979         return i;
980     }
981 
982     /**
983      * Inserts all values to the statement for insert and update.
984      * @param res the Resultset read the values from.
985      * @param cms the CmsObject to get access to cms-ressources.
986      * @param content the CmsMasterContent to write to the database.
987      * @param dataset the set of data for this contentdefinition.
988      * @return the actual rowcounter.
989      */
990     protected int sqlFillValues(ResultSet res, CmsObject cms, CmsMasterDataSet dataset)
991         throws SQLException {
992         // columncounter
993         int i = 1;
994         //// COREDATA ////
995         dataset.m_masterId = res.getInt(i++);
996         res.getInt(i++); // we don't have to store the sub-id
997         dataset.m_userId = res.getInt(i++);
998         dataset.m_groupId = res.getInt(i++);
999         dataset.m_lockedInProject = res.getInt(i++);
1000        // compute project based on the current project and the channels
1001        dataset.m_projectId = computeProjectId(cms, dataset);
1002        dataset.m_accessFlags = res.getInt(i++);
1003        dataset.m_state = res.getInt(i++);
1004        dataset.m_lockedBy =res.getInt(i++);
1005        dataset.m_lastModifiedBy = res.getInt(i++);
1006        dataset.m_dateCreated = res.getTimestamp(i++).getTime();
1007        dataset.m_dateLastModified = res.getTimestamp(i++).getTime();
1008        //// USERDATA ////
1009        dataset.m_publicationDate = res.getTimestamp(i++).getTime();
1010        dataset.m_purgeDate = res.getTimestamp(i++).getTime();
1011        dataset.m_flags = res.getInt(i++);
1012        dataset.m_feedId = res.getInt(i++);
1013        dataset.m_feedReference = res.getInt(i++);
1014        dataset.m_feedFilename = res.getString(i++);
1015        dataset.m_title = res.getString(i++);;
1016        //// GENERIC DATA ////
1017        i = sqlSetTextArray(res, dataset.m_dataBig, i);
1018        i = sqlSetTextArray(res, dataset.m_dataMedium, i);
1019        i = sqlSetTextArray(res, dataset.m_dataSmall, i);
1020        i = sqlSetIntArray(res, dataset.m_dataInt, i);
1021        i = sqlSetIntArray(res, dataset.m_dataReference, i);
1022        i = sqlSetDateArray(res, dataset.m_dataDate, i);
1023        return i;
1024    }
1025
1026    /**
1027     * Computes the correct project id based on the channels.
1028     */
1029    protected int computeProjectId(CmsObject cms, CmsMasterDataSet dataset) throws SQLException  {
1030        int onlineProjectId = I_CmsConstants.C_UNKNOWN_ID;
1031        int offlineProjectId = I_CmsConstants.C_UNKNOWN_ID;
1032
1033        try {
1034            offlineProjectId = cms.getRequestContext().currentProject().getId();
1035            onlineProjectId = cms.onlineProject().getId();
1036        } catch(CmsException exc) {
1037            // ignore the exception
1038        }
1039
1040        if(!isOnlineProject(cms)) {
1041            // this is a offline project -> compute if we have to return the
1042            // online project id or the offline project id
1043
1044            // the owner and the administrtor has always access
1045            try {
1046                if( (cms.getRequestContext().currentUser().getId() == dataset.m_userId) ||
1047                     cms.isAdmin()) {
1048                     return offlineProjectId;
1049                }
1050            } catch(CmsException exc) {
1051                // ignore the exception -> we are not admin
1052            }
1053
1054            String statement_key = "read_channel_offline";
1055            String poolToUse = m_poolName;
1056
1057            PreparedStatement stmnt = null;
1058            ResultSet res = null;
1059            Connection con = null;
1060            try {
1061                cms.setContextToCos();
1062                con = DriverManager.getConnection(poolToUse);
1063                stmnt = sqlPrepare(con, statement_key);
1064                stmnt.setInt(1, dataset.m_masterId);
1065                res = stmnt.executeQuery();
1066                while(res.next()) {
1067                    // get the channel id
1068                    int channeldId = res.getInt(1);
1069                    // read the resource by property "channelid"
1070                    Vector resources = new Vector();
1071                    try {
1072                        resources = cms.getResourcesWithProperty(I_CmsConstants.C_PROPERTY_CHANNELID, channeldId+"", I_CmsConstants.C_TYPE_FOLDER);
1073                    } catch(CmsException exc) {
1074                        // ignore the exception - read the next one
1075                    }
1076                    if(resources.size() >= 1) {
1077                        int resProjectId = ((CmsResource)resources.get(0)).getProjectId();
1078                        if(resProjectId == offlineProjectId) {
1079                            // yes - we have found a chanel that belongs to
1080                            // the current offlineproject -> we can return the
1081                            // offline project id as computed project id
1082                            return offlineProjectId;
1083                        }
1084                    }
1085                }
1086            } finally {
1087                cms.setContextToVfs();
1088                sqlClose(con, stmnt, res);
1089            }
1090        }
1091        // no channel found, that belongs to the offlineproject ->
1092        // return the online project id.
1093        return onlineProjectId;
1094    }
1095
1096    /**
1097     * Sets an array of strings into the stmnt.
1098     * @param stmnt the PreparedStatement to set the values into.
1099     * @param array the array of strings to set.
1100     * @param the columnscounter for the stmnt.
1101     * @return the increased columnscounter;
1102     */
1103    protected int sqlSetTextArray(PreparedStatement stmnt, String[] array, int columnscounter)
1104        throws SQLException {
1105        for(int j = 0; j < array.length; j++) {
1106            if(array[j] == null) {
1107                stmnt.setNull(columnscounter++,Types.LONGVARCHAR);
1108            } else {
1109                stmnt.setString(columnscounter++,array[j]);
1110            }
1111        }
1112        return columnscounter;
1113    }
1114
1115    /**
1116     * Sets an array of strings from the resultset.
1117     * @param res the ResultSet to get the values from.
1118     * @param array the array of strings to set.
1119     * @param the columnscounter for the res.
1120     * @return the increased columnscounter;
1121     */
1122    protected int sqlSetTextArray(ResultSet res, String[] array, int columnscounter)
1123        throws SQLException {
1124        for(int j = 0; j < array.length; j++) {
1125            array[j] = res.getString(columnscounter++);
1126        }
1127        return columnscounter;
1128    }
1129
1130    /**
1131     * Sets an array of ints into the stmnt.
1132     * @param stmnt the PreparedStatement to set the values into.
1133     * @param array the array of ints to set.
1134     * @param the columnscounter for the stmnt.
1135     * @return the increased columnscounter;
1136     */
1137    protected int sqlSetIntArray(PreparedStatement stmnt, int[] array, int columnscounter)
1138        throws SQLException {
1139        for(int j = 0; j < array.length; j++) {
1140            stmnt.setInt(columnscounter++,array[j]);
1141        }
1142        return columnscounter;
1143    }
1144
1145    /**
1146     * Sets an array of ints from the resultset.
1147     * @param res the ResultSet to get the values from.
1148     * @param array the array of ints to set.
1149     * @param the columnscounter for the res.
1150     * @return the increased columnscounter;
1151     */
1152    protected int sqlSetIntArray(ResultSet res, int[] array, int columnscounter)
1153        throws SQLException {
1154        for(int j = 0; j < array.length; j++) {
1155            array[j] = res.getInt(columnscounter++);
1156        }
1157        return columnscounter;
1158    }
1159
1160    /**
1161     * Sets an array of ints into the stmnt.
1162     * @param stmnt the PreparedStatement to set the values into.
1163     * @param array the array of longs to set.
1164     * @param the columnscounter for the stmnt.
1165     * @return the increased columnscounter;
1166     */
1167    protected int sqlSetDateArray(PreparedStatement stmnt, long[] array, int columnscounter)
1168        throws SQLException {
1169        for(int j = 0; j < array.length; j++) {
1170            stmnt.setTimestamp(columnscounter++,new Timestamp(array[j]));
1171        }
1172        return columnscounter;
1173    }
1174
1175    /**
1176     * Sets an array of ints from the resultset.
1177     * @param res the ResultSet to get the values from.
1178     * @param array the array of longs to set.
1179     * @param the columnscounter for the res.
1180     * @return the increased columnscounter;
1181     */
1182    protected int sqlSetDateArray(ResultSet res, long[] array, int columnscounter)
1183        throws SQLException {
1184        for(int j = 0; j < array.length; j++) {
1185            array[j] = res.getTimestamp(columnscounter++).getTime();
1186        }
1187        return columnscounter;
1188    }
1189
1190    /**
1191     * Returns a vector of contentdefinitions based on the sql resultset.
1192     * Never mind about the visible flag.
1193     * @param res - the ResultSet to get data-lines from.
1194     * @param contentDefinitionClass - the class of the cd to create new instances.
1195     * @param cms - the CmsObject to get access to cms-ressources.
1196     * @throws SqlException if nothing could be read from the resultset.
1197     */
1198    protected Vector createVectorOfCd(ResultSet res, Class contentDefinitionClass, CmsObject cms)
1199        throws SQLException {
1200        return createVectorOfCd(res, contentDefinitionClass, cms, false);
1201    }
1202
1203    /**
1204     * Returns a vector of contentdefinitions based on the sql resultset.
1205     * @param res - the ResultSet to get data-lines from.
1206     * @param contentDefinitionClass - the class of the cd to create new instances.
1207     * @param cms - the CmsObject to get access to cms-ressources.
1208     * @param viewonly - decides, if only the ones that are visible should be returned
1209     * @throws SqlException if nothing could be read from the resultset.
1210     */
1211    protected Vector createVectorOfCd(ResultSet res, Class contentDefinitionClass, CmsObject cms, boolean viewonly)
1212        throws SQLException {
1213        Constructor constructor;
1214        Vector retValue = new Vector();
1215        try { // to get the constructor to create an empty contentDefinition
1216            constructor = contentDefinitionClass.getConstructor(new Class[]{CmsObject.class, CmsMasterDataSet.class});
1217        } catch(NoSuchMethodException exc) {
1218            if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && CmsBase.isLogging()) {
1219                CmsBase.log(I_CmsLogChannels.C_MODULE_DEBUG, "[CmsDbAccess] Cannot locate constructor: " + exc.getMessage());
1220            }
1221            // canno't fill the vector - missing constructor
1222            return retValue;
1223        }
1224        while(res.next()) { // while there is data in the resultset
1225            CmsMasterDataSet dataset = new CmsMasterDataSet();
1226            try { // to invoce the constructor to get a new empty instance
1227                CmsMasterContent content = (CmsMasterContent)constructor.newInstance(new Object[]{cms, dataset});
1228                sqlFillValues(res, cms, dataset);
1229                // add the cd only if read (and visible) permissions are granted.
1230                // the visible-permissens will be checked, if viewonly is set to true
1231                // viewonly=true is needed for the backoffice
1232                if(checkAccess(content, viewonly)) {
1233                    retValue.add(content);
1234                }
1235            } catch(Exception exc) {
1236                if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && CmsBase.isLogging()) {
1237                    CmsBase.log(I_CmsLogChannels.C_MODULE_DEBUG, "[CmsDbAccess] Cannot invoce constructor: " + exc.getMessage());
1238                }
1239            }
1240        }
1241        return retValue;
1242    }
1243
1244    /**
1245     * Returns a vector of contentdefinitions based on the sql resultset.
1246     * @param datasets - the vector with the datasets.
1247     * @param contentDefinitionClass - the class of the cd to create new instances.
1248     * @param cms - the CmsObject to get access to cms-ressources.
1249     * @throws SqlException if nothing could be read from the resultset.
1250     */
1251    protected Vector createVectorOfCd(Vector datasets, Class contentDefinitionClass, CmsObject cms)
1252        throws SQLException {
1253        Constructor constructor;
1254        Vector retValue = new Vector();
1255        try { // to get the constructor to create an empty contentDefinition
1256            constructor = contentDefinitionClass.getConstructor(new Class[]{CmsObject.class, CmsMasterDataSet.class});
1257        } catch(NoSuchMethodException exc) {
1258            if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && CmsBase.isLogging()) {
1259                CmsBase.log(I_CmsLogChannels.C_MODULE_DEBUG, "[CmsDbAccess] Cannot locate constructor: " + exc.getMessage());
1260            }
1261            // canno't fill the vector - missing constructor
1262            return retValue;
1263        }
1264        // create content definition for each dataset
1265        for(int i=0; i < datasets.size(); i++) {
1266            CmsMasterDataSet dataset = (CmsMasterDataSet)datasets.elementAt(i);
1267            try { // to invoce the constructor to get a new empty instance
1268                CmsMasterContent content = (CmsMasterContent)constructor.newInstance(new Object[]{cms, dataset});
1269                retValue.add(content);
1270            } catch(Exception exc) {
1271                if(I_CmsLogChannels.C_PREPROCESSOR_IS_LOGGING && CmsBase.isLogging()) {
1272                    CmsBase.log(I_CmsLogChannels.C_MODULE_DEBUG, "[CmsDbAccess] Cannot invoce constructor: " + exc.getMessage());
1273                }
1274            }
1275        }
1276        return retValue;
1277    }
1278
1279    /**
1280     * Checks if read (and visible) permissions are granted.
1281     * the visible-permissens will be checked, if viewonly is set to true
1282     * viewonly=true is needed for the backoffice
1283     * @param cms - the CmsObject to get access to cms-ressources.
1284     * @param content - the cd to check.
1285     * @param viewonly - if set to true the v-Flag will be checked, too
1286     */
1287    protected boolean checkAccess(CmsMasterContent content, boolean viewonly) {
1288        if(!content.isReadable()) {
1289            // was not readable
1290            return false;