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;