001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.ejb.beans;
034:
035: import com.flexive.core.Database;
036: import com.flexive.core.LifeCycleInfoImpl;
037: import com.flexive.core.storage.ContentStorage;
038: import com.flexive.core.storage.StorageManager;
039: import com.flexive.shared.*;
040: import com.flexive.shared.configuration.SystemParameters;
041: import com.flexive.shared.content.*;
042: import com.flexive.shared.exceptions.*;
043: import com.flexive.shared.interfaces.*;
044: import com.flexive.shared.scripting.FxScriptBinding;
045: import com.flexive.shared.scripting.FxScriptEvent;
046: import com.flexive.shared.security.ACL;
047: import com.flexive.shared.security.UserTicket;
048: import com.flexive.shared.structure.FxAssignment;
049: import com.flexive.shared.structure.FxEnvironment;
050: import com.flexive.shared.structure.FxType;
051: import com.flexive.shared.structure.TypeStorageMode;
052: import com.flexive.shared.value.BinaryDescriptor;
053: import com.flexive.shared.value.FxBinary;
054: import com.flexive.shared.workflow.Step;
055: import org.apache.commons.logging.Log;
056: import org.apache.commons.logging.LogFactory;
057:
058: import javax.annotation.Resource;
059: import javax.ejb.*;
060: import java.sql.Connection;
061: import java.sql.PreparedStatement;
062: import java.sql.SQLException;
063: import java.util.List;
064:
065: /**
066: * Content Engine implementation
067: *
068: * @author Markus Plesser (markus.plesser@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
069: */
070: @Stateless(name="ContentEngine")
071: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
072: @TransactionManagement(TransactionManagementType.CONTAINER)
073: public class ContentEngineBean implements ContentEngine,
074: ContentEngineLocal {
075:
076: private static transient Log LOG = LogFactory
077: .getLog(ContentEngineBean.class);
078: @Resource
079: javax.ejb.SessionContext ctx;
080:
081: @EJB
082: LanguageEngine language;
083:
084: @EJB
085: SequencerEngineLocal seq;
086:
087: @EJB
088: ScriptingEngineLocal scripting;
089:
090: /**
091: * {@inheritDoc}
092: */
093: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
094: public FxContent initialize(long typeId, long mandatorId,
095: long prefACL, long prefStep, long prefLang)
096: throws FxApplicationException {
097: UserTicket ticket = FxContext.get().getTicket();
098: FxEnvironment environment;
099: environment = CacheAdmin.getEnvironment();
100: FxPermissionUtils.checkMandatorExistance(mandatorId);
101: FxPermissionUtils.checkTypeAvailable(typeId, false);
102: FxType type = environment.getType(typeId);
103: //security check start
104: if (type.useTypePermissions()
105: && !ticket.mayCreateACL(type.getACL().getId(), ticket
106: .getUserId()))
107: throw new FxNoAccessException("ex.acl.noAccess.create",
108: type.getACL().getName());
109: //security check end
110: long acl = prefACL;
111: try {
112: environment.getACL(acl);
113: } catch (Exception e) {
114: if (ticket.isGlobalSupervisor()) {
115: acl = ACL.Category.INSTANCE.getDefaultId();
116: } else {
117: //get best fit if possible
118: Long[] acls = ticket.getACLsId(ticket.getUserId(),
119: ACL.Category.INSTANCE, ACL.Permission.CREATE,
120: ACL.Permission.EDIT, ACL.Permission.READ);
121: if (acls.length > 0)
122: acl = acls[0];
123: else {
124: if (type.useInstancePermissions())
125: throw new FxNoAccessException(
126: "ex.content.noSuitableACL", type
127: .getName());
128: else
129: acl = ACL.Category.INSTANCE.getDefaultId();
130: }
131: }
132: }
133: long step = prefStep;
134: if (!type.getWorkflow().isStepValid(step))
135: try {
136: step = type.getWorkflow().getSteps().get(0).getId();
137: } catch (Exception e) {
138: throw new FxInvalidParameterException("STEP",
139: "ex.workflow.noStepDefined", type.getWorkflow()
140: .getName());
141: }
142: long lang = prefLang;
143: try {
144: language.load(lang);
145: } catch (FxInvalidLanguageException e) {
146: lang = ticket.getLanguage().getId();
147: }
148: FxPK sourcePK = null, destinationPK = null;
149: int sourcePos = 0, destinationPos = 0;
150: if (type.isRelation()) {
151: sourcePK = FxPK.createNewPK();
152: destinationPK = FxPK.createNewPK();
153: sourcePos = destinationPos = 0;
154: }
155: FxContent content = new FxContent(FxPK.createNewPK(), type
156: .getId(), type.isRelation(), mandatorId, acl, step, 1,
157: environment.getStep(step).isLiveStep() ? 1 : 0, true,
158: lang, sourcePK, destinationPK, sourcePos,
159: destinationPos, LifeCycleInfoImpl.createNew(ticket),
160: type.createEmptyData(type.buildXPathPrefix(FxPK
161: .createNewPK())), BinaryDescriptor.SYS_UNKNOWN,
162: 1).initSystemProperties();
163: //scripting after start
164: FxScriptBinding binding = null;
165: long[] scripts = type
166: .getScriptMapping(FxScriptEvent.AfterContentInitialize);
167: if (scripts != null)
168: for (long script : scripts) {
169: if (binding == null)
170: binding = new FxScriptBinding();
171: binding.setVariable("content", content);
172: scripting.runScript(script, binding);
173: }
174: //scripting after end
175: return content;
176: }
177:
178: /**
179: * {@inheritDoc}
180: */
181: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
182: public FxContent initialize(long typeId)
183: throws FxApplicationException {
184: FxType type = CacheAdmin.getEnvironment().getType(typeId);
185: UserTicket ticket = FxContext.get().getTicket();
186: return initialize(
187: type.getId(),
188: ticket.getMandatorId(),
189: -1 /*invalid ACL will cause a lookup for best-fit ACL*/,
190: type.getWorkflow().getSteps().get(0).getId(), ticket
191: .getLanguage().getId());
192: }
193:
194: /**
195: * {@inheritDoc}
196: */
197: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
198: public FxContent initialize(String typeName)
199: throws FxApplicationException {
200: return initialize(CacheAdmin.getEnvironment().getType(typeName)
201: .getId());
202: }
203:
204: /**
205: * {@inheritDoc}
206: */
207: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
208: public FxContent load(FxPK pk) throws FxApplicationException {
209: // long time = System.currentTimeMillis();
210: // System.out.println("=> Cache check for " + pk);
211: FxCachedContent cachedContent = CacheAdmin.getCachedContent(pk);
212: FxEnvironment env = CacheAdmin.getEnvironment();
213: Connection con = null;
214: PreparedStatement ps = null;
215: try {
216: if (cachedContent == null) {
217: // System.out.println("=> Cache miss for " + pk);
218: ContentStorage storage = StorageManager
219: .getContentStorage(pk.getStorageMode());
220: StringBuilder sql = new StringBuilder(2000);
221: con = Database.getDbConnection();
222: FxContent rawContent = storage.contentLoad(con, pk,
223: env, sql).copy();
224: cachedContent = new FxCachedContent(rawContent, storage
225: .getContentSecurityInfo(con, pk));
226: CacheAdmin.cacheContent(cachedContent);
227: // System.out.println("=> Cached " + pk);
228: } else {
229: // System.out.println("=> Cache hit for " + pk);
230: }
231: FxContent content = cachedContent.getContent().copy();
232:
233: //security check start
234: UserTicket ticket = FxContext.get().getTicket();
235: FxType type = env.getType(cachedContent.getContent()
236: .getTypeId());
237: FxPermissionUtils.checkPermission(ticket, content
238: .getLifeCycleInfo().getCreatorId(),
239: ACL.Permission.READ, type, cachedContent
240: .getSecurityInfo().getStepACL(),
241: cachedContent.getSecurityInfo().getContentACL(),
242: true);
243: FxPermissionUtils.checkMandatorExistance(content
244: .getMandatorId());
245: FxPermissionUtils.checkTypeAvailable(type.getId(), true);
246: if (type.usePropertyPermissions()
247: && !ticket.isGlobalSupervisor()) {
248: //wrap with FxNoAccess or set to readonly when appropriate
249: FxPermissionUtils.wrapNoAccessValues(ticket,
250: cachedContent.getSecurityInfo(), content, type,
251: env);
252: }
253: //security check end
254: //scripting after start
255: FxScriptBinding binding = null;
256: long[] scripts = env.getType(content.getTypeId())
257: .getScriptMapping(FxScriptEvent.AfterContentLoad);
258: if (scripts != null)
259: for (long script : scripts) {
260: if (binding == null)
261: binding = new FxScriptBinding();
262: binding.setVariable("content", content);
263: scripting.runScript(script, binding);
264: }
265: //scripting after end
266: content.getRootGroup().removeEmptyEntries();
267: content.getRootGroup().compactPositions(true);
268: return content;
269: } catch (SQLException e) {
270: throw new FxLoadException(LOG, e, "ex.db.sqlError", e
271: .getMessage());
272: } finally {
273: Database.closeObjects(ContentEngineBean.class, con, ps);
274: // System.out.println("=> Load time: " + (System.currentTimeMillis() - time));
275: }
276: }
277:
278: /**
279: * {@inheritDoc}
280: */
281: @TransactionAttribute(TransactionAttributeType.REQUIRED)
282: public FxPK save(FxContent content) throws FxApplicationException {
283: Connection con = null;
284: PreparedStatement ps = null;
285: FxPK pk;
286: FxScriptEvent beforeAssignmentScript, afterAssignmentScript;
287: try {
288: FxEnvironment env = CacheAdmin.getEnvironment();
289: FxPermissionUtils.checkMandatorExistance(content
290: .getMandatorId());
291: FxPermissionUtils.checkTypeAvailable(content.getTypeId(),
292: false);
293: ContentStorage storage = StorageManager
294: .getContentStorage(content.getPk().getStorageMode());
295: con = Database.getDbConnection();
296:
297: //security check start
298: FxType type = env.getType(content.getTypeId());
299: Step step = env.getStep(content.getStepId());
300: UserTicket ticket = FxContext.get().getTicket();
301: if (content.getPk().isNew()) {
302: FxPermissionUtils.checkPermission(ticket, ticket
303: .getUserId(), ACL.Permission.CREATE, type, step
304: .getAclId(), content.getAclId(), true);
305: beforeAssignmentScript = FxScriptEvent.BeforeAssignmentDataCreate;
306: afterAssignmentScript = FxScriptEvent.AfterAssignmentDataCreate;
307: } else {
308: FxPermissionUtils.checkPermission(ticket, content
309: .getLifeCycleInfo().getCreatorId(),
310: ACL.Permission.EDIT, type, step.getAclId(),
311: content.getAclId(), true);
312: beforeAssignmentScript = FxScriptEvent.BeforeAssignmentDataSave;
313: afterAssignmentScript = FxScriptEvent.AfterAssignmentDataSave;
314: }
315: if (type.usePropertyPermissions()
316: && !ticket.isGlobalSupervisor())
317: FxPermissionUtils.checkPropertyPermissions(content,
318: content.getPk().isNew() ? ACL.Permission.CREATE
319: : ACL.Permission.EDIT);
320: //security check end
321:
322: storage.prepareSave(con, content);
323:
324: FxScriptBinding binding = null;
325: long[] typeScripts;
326: //scripting before start
327: //type scripting
328: typeScripts = type
329: .getScriptMapping(content.getPk().isNew() ? FxScriptEvent.BeforeContentCreate
330: : FxScriptEvent.BeforeContentSave);
331: if (typeScripts != null)
332: for (long script : typeScripts) {
333: if (binding == null)
334: binding = new FxScriptBinding();
335: binding.setVariable("content", content);
336: Object result = scripting
337: .runScript(script, binding).getResult();
338: if (result != null && result instanceof FxContent) {
339: content = (FxContent) result;
340: }
341: }
342: //assignment scripting
343: if (type.hasScriptedAssignments()) {
344: binding = null;
345: for (FxAssignment as : type
346: .getScriptedAssignments(beforeAssignmentScript)) {
347: if (binding == null)
348: binding = new FxScriptBinding();
349: binding.setVariable("assignment", as);
350: for (long script : as
351: .getScriptMapping(beforeAssignmentScript)) {
352: binding.setVariable("content", content);
353: Object result = scripting.runScript(script,
354: binding).getResult();
355: if (result != null
356: && result instanceof FxContent) {
357: content = (FxContent) result;
358: }
359: }
360: }
361: }
362: //scripting before end
363: //unwrap all no access values so they can be saved
364: if (type.usePropertyPermissions()
365: && !ticket.isGlobalSupervisor()) {
366: FxContext.get().runAsSystem();
367: FxPermissionUtils.unwrapNoAccessValues(content);
368: FxContext.get().stopRunAsSystem();
369: }
370: if (content.getPk().isNew()) {
371: pk = storage
372: .contentCreate(con, env, null, seq
373: .getId(SequencerEngine.System.CONTENT),
374: content);
375: if (LOG.isDebugEnabled())
376: LOG.debug("creating new content for type "
377: + CacheAdmin.getEnvironment().getType(
378: content.getTypeId()).getName());
379: } else {
380: pk = storage.contentSave(con, env, null, content,
381: EJBLookup.getConfigurationEngine().get(
382: SystemParameters.TREE_FQN_PROPERTY));
383: }
384: //scripting after start
385: //assignment scripting
386: if (type.hasScriptedAssignments()) {
387: binding = new FxScriptBinding();
388: binding.setVariable("pk", pk);
389: for (FxAssignment as : type
390: .getScriptedAssignments(afterAssignmentScript)) {
391: binding.setVariable("assignment", as);
392: for (long script : as
393: .getScriptMapping(afterAssignmentScript)) {
394: scripting.runScript(script, binding);
395: }
396: }
397: }
398: //type scripting
399: typeScripts = env
400: .getType(content.getTypeId())
401: .getScriptMapping(
402: content.getPk().isNew() ? FxScriptEvent.AfterContentCreate
403: : FxScriptEvent.AfterContentSave);
404: if (typeScripts != null)
405: for (long script : typeScripts) {
406: if (binding == null)
407: binding = new FxScriptBinding();
408: binding.setVariable("pk", pk);
409: scripting.runScript(script, binding);
410: }
411: //scripting after end
412: return pk;
413: } catch (FxNotFoundException e) {
414: ctx.setRollbackOnly();
415: throw new FxCreateException(e);
416: } catch (SQLException e) {
417: ctx.setRollbackOnly();
418: // if (Database.isUniqueConstraintViolation(e))
419: // throw new FxEntryExistsException("ex.structure.property.exists", property.getName(), (parentXPath.length() == 0 ? "/" : parentXPath));
420: throw new FxCreateException(LOG, e, "ex.db.sqlError", e
421: .getMessage());
422: } catch (FxInvalidParameterException e) {
423: ctx.setRollbackOnly();
424: throw new FxCreateException(e);
425: } catch (Throwable t) {
426: ctx.setRollbackOnly();
427: throw new FxCreateException(LOG, t);
428: } finally {
429: Database.closeObjects(ContentEngineBean.class, con, ps);
430: if (!ctx.getRollbackOnly())
431: CacheAdmin.expireCachedContent(content.getId());
432: }
433: }
434:
435: /**
436: * {@inheritDoc}
437: */
438: @TransactionAttribute(TransactionAttributeType.REQUIRED)
439: public FxPK createNewVersion(FxContent content)
440: throws FxApplicationException {
441: Connection con = null;
442: PreparedStatement ps = null;
443: try {
444: //security check start
445: FxEnvironment env = CacheAdmin.getEnvironment();
446: FxType type = env.getType(content.getTypeId());
447: Step step = env.getStep(content.getStepId());
448: UserTicket ticket = FxContext.get().getTicket();
449: FxPermissionUtils.checkMandatorExistance(content
450: .getMandatorId());
451: FxPermissionUtils.checkTypeAvailable(type.getId(), false);
452: FxPermissionUtils.checkPermission(ticket, ticket
453: .getUserId(), ACL.Permission.CREATE, type, step
454: .getAclId(), content.getAclId(), true);
455: //security check end
456: ContentStorage storage = StorageManager
457: .getContentStorage(content.getPk().getStorageMode());
458: con = Database.getDbConnection();
459: return storage.contentCreateVersion(con, CacheAdmin
460: .getEnvironment(), null, content);
461: } catch (SQLException e) {
462: ctx.setRollbackOnly();
463: throw new FxCreateException(LOG, e, "ex.db.sqlError", e
464: .getMessage());
465: } catch (FxNotFoundException e) {
466: ctx.setRollbackOnly();
467: throw e;
468: } catch (FxApplicationException e) {
469: ctx.setRollbackOnly();
470: throw new FxCreateException(e);
471: } finally {
472: Database.closeObjects(ContentEngineBean.class, con, ps);
473: if (!ctx.getRollbackOnly())
474: CacheAdmin.expireCachedContent(content.getId());
475: }
476: }
477:
478: /**
479: * {@inheritDoc}
480: */
481: @TransactionAttribute(TransactionAttributeType.REQUIRED)
482: public FxContent prepareSave(FxContent content)
483: throws FxApplicationException {
484: Connection con = null;
485: PreparedStatement ps = null;
486: try {
487: ContentStorage storage = StorageManager
488: .getContentStorage(content.getPk().getStorageMode());
489: con = Database.getDbConnection();
490: storage.prepareSave(con, content);
491: FxScriptBinding binding = null;
492: long[] scripts;
493: //scripting before start
494: scripts = CacheAdmin
495: .getEnvironment()
496: .getType(content.getTypeId())
497: .getScriptMapping(
498: content.getPk().isNew() ? FxScriptEvent.PrepareContentCreate
499: : FxScriptEvent.PrepareContentSave);
500: if (scripts != null)
501: for (long script : scripts) {
502: if (binding == null)
503: binding = new FxScriptBinding();
504: binding.setVariable("content", content);
505: Object result = scripting
506: .runScript(script, binding).getResult();
507: if (result != null && result instanceof FxContent) {
508: // System.out.println("setting result");
509: content = (FxContent) result;
510: }
511: }
512: //scripting before end
513: return content;
514: } catch (FxNotFoundException e) {
515: ctx.setRollbackOnly();
516: throw new FxCreateException(e);
517: } catch (SQLException e) {
518: ctx.setRollbackOnly();
519: throw new FxCreateException(LOG, e, "ex.db.sqlError", e
520: .getMessage());
521: } catch (FxInvalidParameterException e) {
522: ctx.setRollbackOnly();
523: throw new FxCreateException(e);
524: } finally {
525: Database.closeObjects(ContentEngineBean.class, con, ps);
526: }
527: }
528:
529: /**
530: * {@inheritDoc}
531: */
532: @TransactionAttribute(TransactionAttributeType.REQUIRED)
533: public void remove(FxPK pk) throws FxApplicationException {
534: Connection con = null;
535: PreparedStatement ps = null;
536: try {
537: ContentStorage storage = StorageManager
538: .getContentStorage(pk.getStorageMode());
539: con = Database.getDbConnection();
540: final FxEnvironment env = CacheAdmin.getEnvironment();
541: //security check start
542: if (!(FxContext.get().getRunAsSystem() || FxContext.get()
543: .getTicket().isGlobalSupervisor())) {
544: FxContentVersionInfo cvi = storage
545: .getContentVersionInfo(con, pk.getId());
546: FxPK currPK;
547: for (int currVer : cvi.getVersions()) {
548: currPK = new FxPK(pk.getId(), currVer);
549: FxContentSecurityInfo si = storage
550: .getContentSecurityInfo(con, currPK);
551: FxPermissionUtils.checkPermission(FxContext.get()
552: .getTicket(), ACL.Permission.DELETE, si,
553: true);
554: }
555: }
556: //security check end
557: FxScriptBinding binding = null;
558: long[] scripts;
559: FxContentSecurityInfo securityInfo = storage
560: .getContentSecurityInfo(con, pk);
561: try {
562: FxPermissionUtils.checkMandatorExistance(securityInfo
563: .getMandatorId());
564: FxPermissionUtils.checkTypeAvailable(securityInfo
565: .getTypeId(), false);
566: } catch (FxNotFoundException e) {
567: throw new FxRemoveException(e);
568: }
569: long typeId = securityInfo.getTypeId();
570: FxType type = env.getType(typeId);
571:
572: //scripting before start
573: //type scripting
574: scripts = env.getType(typeId).getScriptMapping(
575: FxScriptEvent.BeforeContentRemove);
576: if (scripts != null)
577: for (long script : scripts) {
578: if (binding == null)
579: binding = new FxScriptBinding();
580: binding.setVariable("pk", pk);
581: if (!binding.getProperties().containsKey(
582: "securityInfo"))
583: binding.setVariable("securityInfo",
584: securityInfo);
585: scripting.runScript(script, binding);
586: }
587: //assignment scripting
588: if (type.hasScriptedAssignments()) {
589: binding = new FxScriptBinding();
590: binding.setVariable("pk", pk);
591: for (FxAssignment as : type
592: .getScriptedAssignments(FxScriptEvent.BeforeAssignmentDataDelete)) {
593: binding.setVariable("assignment", as);
594: for (long script : as
595: .getScriptMapping(FxScriptEvent.BeforeAssignmentDataDelete)) {
596: scripting.runScript(script, binding);
597: }
598: }
599: }
600: //scripting before end
601: storage.contentRemove(con, pk);
602: //scripting after start
603: //assignment scripting
604: if (type.hasScriptedAssignments()) {
605: binding = new FxScriptBinding();
606: binding.setVariable("pk", pk);
607: for (FxAssignment as : type
608: .getScriptedAssignments(FxScriptEvent.AfterAssignmentDataDelete)) {
609: binding.setVariable("assignment", as);
610: for (long script : as
611: .getScriptMapping(FxScriptEvent.AfterAssignmentDataDelete)) {
612: scripting.runScript(script, binding);
613: }
614: }
615: }
616: //type scripting
617: scripts = env.getType(typeId).getScriptMapping(
618: FxScriptEvent.AfterContentRemove);
619: if (scripts != null)
620: for (long script : scripts) {
621: if (binding == null)
622: binding = new FxScriptBinding();
623: binding.setVariable("pk", pk);
624: if (!binding.getProperties().containsKey(
625: "securityInfo"))
626: binding.setVariable("securityInfo",
627: securityInfo);
628: scripting.runScript(script, binding);
629: }
630: //scripting after end
631: } catch (FxRemoveException e) {
632: ctx.setRollbackOnly();
633: throw e;
634: } catch (FxNotFoundException e) {
635: //not found is ok for removed instances
636: } catch (SQLException e) {
637: ctx.setRollbackOnly();
638: throw new FxRemoveException(LOG, e, "ex.db.sqlError", e
639: .getMessage());
640: } finally {
641: Database.closeObjects(ContentEngineBean.class, con, ps);
642: if (!ctx.getRollbackOnly())
643: CacheAdmin.expireCachedContent(pk.getId());
644: }
645: }
646:
647: /**
648: * {@inheritDoc}
649: */
650: @TransactionAttribute(TransactionAttributeType.REQUIRED)
651: public void removeVersion(FxPK pk) throws FxApplicationException {
652: Connection con = null;
653: PreparedStatement ps = null;
654: try {
655: ContentStorage storage = StorageManager
656: .getContentStorage(pk.getStorageMode());
657: con = Database.getDbConnection();
658: //security check start
659: FxContentSecurityInfo si = StorageManager
660: .getContentStorage(pk.getStorageMode())
661: .getContentSecurityInfo(con, pk);
662: FxPermissionUtils
663: .checkMandatorExistance(si.getMandatorId());
664: FxPermissionUtils.checkTypeAvailable(si.getTypeId(), false);
665: FxPermissionUtils.checkPermission(FxContext.get()
666: .getTicket(), ACL.Permission.DELETE, si, true);
667: //security check end
668:
669: storage.contentRemoveVersion(con, pk);
670: } catch (FxNotFoundException e) {
671: ctx.setRollbackOnly();
672: throw e;
673: } catch (SQLException e) {
674: ctx.setRollbackOnly();
675: throw new FxRemoveException(LOG, e, "ex.db.sqlError", e
676: .getMessage());
677: } finally {
678: Database.closeObjects(ContentEngineBean.class, con, ps);
679: if (!ctx.getRollbackOnly())
680: CacheAdmin.expireCachedContent(pk.getId());
681: }
682: }
683:
684: /**
685: * {@inheritDoc}
686: */
687: @TransactionAttribute(TransactionAttributeType.REQUIRED)
688: public int removeForType(long typeId) throws FxApplicationException {
689: Connection con = null;
690: try {
691: FxType type = CacheAdmin.getEnvironment().getType(typeId);
692: FxPermissionUtils.checkTypeAvailable(typeId, false);
693: ContentStorage storage = StorageManager
694: .getContentStorage(type.getStorageMode());
695: con = Database.getDbConnection();
696: long[] scriptsBefore = null;
697: long[] scriptsAfter = null;
698:
699: FxScriptBinding binding = null;
700: UserTicket ticket = FxContext.get().getTicket();
701: if (CacheAdmin
702: .getEnvironment()
703: .getType(typeId)
704: .getScriptMapping(FxScriptEvent.BeforeContentRemove) != null)
705: scriptsBefore = CacheAdmin.getEnvironment().getType(
706: typeId).getScriptMapping(
707: FxScriptEvent.BeforeContentRemove);
708: if (CacheAdmin.getEnvironment().getType(typeId)
709: .getScriptMapping(FxScriptEvent.AfterContentRemove) != null)
710: scriptsAfter = CacheAdmin.getEnvironment().getType(
711: typeId).getScriptMapping(
712: FxScriptEvent.AfterContentRemove);
713: List<FxPK> pks = null;
714: if (scriptsBefore != null || scriptsAfter != null
715: || !ticket.isGlobalSupervisor()) {
716: binding = new FxScriptBinding();
717: if (!ticket.isGlobalSupervisor()
718: || scriptsBefore != null) {
719: pks = storage.getPKsForType(con, type, false);
720: for (FxPK pk : pks) {
721: //security check start
722: FxContentSecurityInfo si = storage
723: .getContentSecurityInfo(con, pk);
724: if (!ticket.isGlobalSupervisor())
725: FxPermissionUtils.checkPermission(FxContext
726: .get().getTicket(),
727: ACL.Permission.DELETE, si, true);
728: //note: instances of deactivated mandators are silently ignored and erased on purposed!
729: //security check end
730: //scripting before start
731: //type scripting
732: if (scriptsBefore != null) {
733: binding.setVariable("pk", pk);
734: binding.setVariable("securityInfo", si);
735: for (long script : scriptsBefore)
736: scripting.runScript(script, binding);
737: }
738: //assignment scripting
739: if (type.hasScriptedAssignments()) {
740: binding = new FxScriptBinding();
741: binding.setVariable("pk", pk);
742: for (FxAssignment as : type
743: .getScriptedAssignments(FxScriptEvent.BeforeAssignmentDataDelete)) {
744: binding.setVariable("assignment", as);
745: for (long script : as
746: .getScriptMapping(FxScriptEvent.BeforeAssignmentDataDelete)) {
747: scripting
748: .runScript(script, binding);
749: }
750: }
751: }
752: //scripting before end
753: }
754: }
755: }
756: int removed = storage.contentRemoveForType(con, type);
757: if (scriptsAfter != null) {
758: if (pks == null)
759: pks = storage.getPKsForType(con, type, false);
760: for (FxPK pk : pks) {
761: binding.getProperties().remove("securityInfo");
762: //scripting after start
763: //assignment scripting
764: if (type.hasScriptedAssignments()) {
765: binding = new FxScriptBinding();
766: binding.setVariable("pk", pk);
767: for (FxAssignment as : type
768: .getScriptedAssignments(FxScriptEvent.AfterAssignmentDataDelete)) {
769: binding.setVariable("assignment", as);
770: for (long script : as
771: .getScriptMapping(FxScriptEvent.AfterAssignmentDataDelete)) {
772: scripting.runScript(script, binding);
773: }
774: }
775: }
776: //type scripting
777: if (scriptsBefore != null) {
778: binding.setVariable("pk", pk);
779: for (long script : scriptsAfter)
780: scripting.runScript(script, binding);
781: }
782: //scripting after end
783: }
784: }
785: return removed;
786: } catch (FxNotFoundException e) {
787: ctx.setRollbackOnly();
788: throw new FxRemoveException(e);
789: } catch (SQLException e) {
790: ctx.setRollbackOnly();
791: throw new FxRemoveException(LOG, e, "ex.db.sqlError", e
792: .getMessage());
793: } finally {
794: Database.closeObjects(ContentEngineBean.class, con, null);
795: if (!ctx.getRollbackOnly())
796: CacheAdmin.expireCachedContents();
797: }
798: }
799:
800: /**
801: * {@inheritDoc}
802: */
803: @TransactionAttribute(TransactionAttributeType.REQUIRED)
804: public FxContentSecurityInfo getContentSecurityInfo(FxPK pk)
805: throws FxApplicationException {
806: FxSharedUtils.checkParameterNull(pk, "pk");
807: Connection con = null;
808: try {
809: ContentStorage storage = StorageManager
810: .getContentStorage(pk.getStorageMode());
811: con = Database.getDbConnection();
812: return storage.getContentSecurityInfo(con, pk);
813: } catch (FxNotFoundException e) {
814: throw new FxLoadException(e);
815: } catch (SQLException e) {
816: throw new FxLoadException(LOG, e, "ex.db.sqlError", e
817: .getMessage());
818: } finally {
819: Database.closeObjects(ContentEngineBean.class, con, null);
820: }
821: }
822:
823: /**
824: * {@inheritDoc}
825: */
826: @TransactionAttribute(TransactionAttributeType.REQUIRED)
827: public FxContentVersionInfo getContentVersionInfo(FxPK pk)
828: throws FxApplicationException {
829: FxSharedUtils.checkParameterNull(pk, "pk");
830: Connection con = null;
831: try {
832: ContentStorage storage = StorageManager
833: .getContentStorage(pk.getStorageMode());
834: con = Database.getDbConnection();
835: return storage.getContentVersionInfo(con, pk.getId());
836: } catch (FxNotFoundException e) {
837: throw new FxLoadException(e);
838: } catch (SQLException e) {
839: throw new FxLoadException(LOG, e, "ex.db.sqlError", e
840: .getMessage());
841: } finally {
842: Database.closeObjects(ContentEngineBean.class, con, null);
843: }
844: }
845:
846: /**
847: * {@inheritDoc}
848: */
849: @TransactionAttribute(TransactionAttributeType.REQUIRED)
850: public int getReferencedContentCount(FxPK pk)
851: throws FxApplicationException {
852: FxSharedUtils.checkParameterNull(pk, "pk");
853: Connection con = null;
854: try {
855: ContentStorage storage = StorageManager
856: .getContentStorage(pk.getStorageMode());
857: con = Database.getDbConnection();
858: return storage.getReferencedContentCount(con, pk.getId());
859: } catch (FxNotFoundException e) {
860: throw new FxLoadException(e);
861: } catch (SQLException e) {
862: throw new FxLoadException(LOG, e, "ex.db.sqlError", e
863: .getMessage());
864: } finally {
865: Database.closeObjects(ContentEngineBean.class, con, null);
866: }
867: }
868:
869: /**
870: * {@inheritDoc}
871: */
872: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
873: public List<FxPK> getPKsForType(long typeId,
874: boolean onePkPerInstance) throws FxApplicationException {
875: if (!FxContext.get().getTicket().isGlobalSupervisor()) {
876: throw new FxNoAccessException(
877: "ex.content.type.getAll.noPermission");
878: }
879: Connection con = null;
880: try {
881: con = Database.getDbConnection();
882: return StorageManager.getContentStorage(
883: TypeStorageMode.Hierarchical).getPKsForType(con,
884: CacheAdmin.getEnvironment().getType(typeId),
885: onePkPerInstance);
886: } catch (Exception e) {
887: throw new FxLoadException(LOG, e, "ex.db.sqlError", e
888: .getMessage());
889: } finally {
890: Database.closeObjects(ContentEngineBean.class, con, null);
891: }
892: }
893:
894: /**
895: * {@inheritDoc}
896: */
897: @TransactionAttribute(TransactionAttributeType.SUPPORTS)
898: public long getBinaryId(FxPK pk, String xpath, FxLanguage language)
899: throws FxApplicationException {
900: FxSharedUtils.checkParameterNull(pk, "pk");
901: FxSharedUtils.checkParameterNull(xpath, "xpath");
902: Connection con = null;
903: try {
904: ContentStorage storage = StorageManager
905: .getContentStorage(pk.getStorageMode());
906: con = Database.getDbConnection();
907: FxContent co = load(pk);
908: UserTicket ticket = FxContext.get().getTicket();
909: if (xpath.equals("/")) {
910: if (!ticket.isGlobalSupervisor()) {
911: FxType type = CacheAdmin.getEnvironment().getType(
912: co.getTypeId());
913: if (type.usePermissions()) {
914: FxContentSecurityInfo si = storage
915: .getContentSecurityInfo(con, pk);
916: FxPermissionUtils.checkPermission(ticket,
917: ACL.Permission.READ, si, true);
918: }
919: }
920: return co.getBinaryPreviewId();
921: }
922: FxPropertyData pd = co.getPropertyData(xpath);
923: if (!pd.getValue().isEmpty()
924: && pd.getValue() instanceof FxBinary)
925: return ((FxBinary) pd.getValue()).getBestTranslation(
926: language != null ? language : ticket
927: .getLanguage()).getId();
928: throw new FxInvalidParameterException("XPATH",
929: "ex.content.binary.xpath.invalid", xpath);
930: } catch (FxNotFoundException e) {
931: throw new FxLoadException(e);
932: } catch (SQLException e) {
933: throw new FxLoadException(LOG, e, "ex.db.sqlError", e
934: .getMessage());
935: } finally {
936: Database.closeObjects(ContentEngineBean.class, con, null);
937: }
938: }
939: }
|