001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.core;
019:
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.HashSet;
025: import java.util.Iterator;
026: import java.util.Map;
027: import java.util.Set;
028:
029: import de.finix.contelligent.Component;
030: import de.finix.contelligent.ComponentContext;
031: import de.finix.contelligent.ComponentManager;
032: import de.finix.contelligent.ComponentPath;
033: import de.finix.contelligent.Contelligent;
034: import de.finix.contelligent.ModificationVetoException;
035: import de.finix.contelligent.SecureComponent;
036: import de.finix.contelligent.Type;
037: import de.finix.contelligent.category.Category;
038: import de.finix.contelligent.category.CategoryManager;
039: import de.finix.contelligent.content.Metadata;
040: import de.finix.contelligent.core.security.AccessControlList;
041: import de.finix.contelligent.core.security.ContelligentPrincipal;
042: import de.finix.contelligent.exception.ComponentPersistenceException;
043: import de.finix.contelligent.exception.ContelligentExceptionID;
044: import de.finix.contelligent.logging.LoggingService;
045: import de.finix.contelligent.persistence.ComponentPersistenceAdapter;
046: import de.finix.contelligent.resource.Resource;
047: import de.finix.contelligent.resource.ResourceReference;
048: import de.finix.contelligent.search.Metainfo;
049: import de.finix.contelligent.util.ThreadedMem;
050:
051: public class ComponentContextImpl implements ComponentContext,
052: Cloneable {
053:
054: final static org.apache.log4j.Logger log = LoggingService
055: .getLogger(ComponentContextImpl.class);
056:
057: private ComponentManager persistenceManager;
058:
059: private Component component;
060:
061: final private ComponentPath path;
062:
063: final private Contelligent system;
064:
065: private long typeId;
066:
067: private String typeName;
068:
069: private Type type;
070:
071: private boolean isFinal = false;
072:
073: private boolean definesSecureTransfer = false;
074:
075: private boolean requiresSecureTransfer = false;
076:
077: private boolean inheritSecurity = true;
078:
079: private NamedNode node;
080:
081: /** this ACL is the cumulative acl of all parents + myAcl */
082: private AccessControlList effectiveACL = null;
083:
084: private AccessControlList acl = null;
085:
086: private long lastModified = -1;
087:
088: private int status = ComponentPersistenceAdapter.REGULAR;
089:
090: private String composedBlueprintName;
091:
092: private Set sensitiveContentCategories;
093:
094: private Set sensitiveTemplateCategories;
095:
096: private Map contentResources;
097:
098: private Map templateResources;
099:
100: private Set removedResources = new HashSet();
101:
102: private ContelligentPrincipal modifiedBy;
103:
104: private Metadata meta = null;
105:
106: private String publisherName = "";
107:
108: private String publisherType = "";
109:
110: ComponentContextImpl(ComponentManager persistenceManager,
111: ComponentPath path, Contelligent system) {
112: this .persistenceManager = persistenceManager;
113: this .path = path;
114: this .system = system;
115: }
116:
117: /**
118: * Implementation of {@link ComponentContext#getPersistenceManager}.
119: */
120: public ComponentManager getPersistenceManager() {
121: return persistenceManager;
122: }
123:
124: void setPersistenceManager(ComponentManager persistenceManager) {
125: this .persistenceManager = persistenceManager;
126: }
127:
128: /**
129: * Implementation of {@link ComponentContext#getCallManager}.
130: */
131: public ComponentManager getCallManager() {
132: ComponentManager callManager = ThreadedMem.getActualManager();
133: return ((callManager != null) ? callManager
134: : persistenceManager);
135: }
136:
137: public Contelligent getSystem() {
138: return system;
139: }
140:
141: public ComponentPath getPath() {
142: return path;
143: }
144:
145: public Type getType() {
146: return type;
147: }
148:
149: void setType(Type type) {
150: this .type = type;
151: typeName = type.getName();
152: typeId = ((TypeImpl) type).getId();
153: }
154:
155: public boolean isFinal() {
156: return isFinal;
157: }
158:
159: public AccessControlList getEffectiveACL() {
160: return effectiveACL;
161: }
162:
163: public AccessControlList getACL() {
164: return acl;
165: }
166:
167: public long getLastModified() {
168: if (log.isDebugEnabled())
169: log.debug("LastModified (AbstractComponent): "
170: + lastModified);
171: return lastModified;
172: }
173:
174: public ContelligentPrincipal getModifiedBy() {
175: return modifiedBy;
176: }
177:
178: public int getStatus() {
179: return status;
180: }
181:
182: public String getComposedBlueprintName() {
183: return composedBlueprintName;
184: }
185:
186: public void setComposedBlueprintName(String composedBlueprintName) {
187: this .composedBlueprintName = composedBlueprintName;
188: }
189:
190: /**
191: * If true, needsSecureTransfer is set in this context, otherwise it is
192: * inherited from the parent or defined because the component implements
193: * {@link SecureComponent}.
194: *
195: * @return
196: */
197: public boolean definesSecureTransfer() {
198: return definesSecureTransfer;
199: }
200:
201: public void setDefinesSecureTransfer(boolean definesSecureTransfer) {
202: this .definesSecureTransfer = definesSecureTransfer;
203: }
204:
205: public boolean requiresSecureTransfer() {
206: return requiresSecureTransfer;
207: }
208:
209: public void setRequiresSecureTransfer(boolean requiresSecureTransfer) {
210: this .requiresSecureTransfer = requiresSecureTransfer;
211: }
212:
213: public Object clone() {
214: ComponentContextImpl clone = new ComponentContextImpl(
215: persistenceManager, path, this .system);
216: setPropertiesOnClone(clone);
217: return clone;
218: }
219:
220: public ComponentContextImpl clone(
221: ComponentManager persistenceManager) {
222: ComponentContextImpl clone = new ComponentContextImpl(
223: persistenceManager, path, this .system);
224: setPropertiesOnClone(clone);
225: return clone;
226: }
227:
228: public ComponentContextImpl clone(
229: ComponentManager persistenceManager, ComponentPath path) {
230: ComponentContextImpl clone = new ComponentContextImpl(
231: persistenceManager, path, this .system);
232: setPropertiesOnClone(clone);
233: return clone;
234: }
235:
236: private void setPropertiesOnClone(ComponentContextImpl clone) {
237: clone.type = this .type;
238: clone.typeId = this .typeId;
239: clone.typeName = this .typeName;
240: clone.isFinal = this .isFinal;
241: clone.definesSecureTransfer = this .definesSecureTransfer;
242: clone.requiresSecureTransfer = this .requiresSecureTransfer;
243: clone.inheritSecurity = this .inheritSecurity;
244: if (this .node != null) { // nodes are used by EditManager only!
245: clone.node = (NamedNode) this .node.clone();
246: }
247: clone.acl = (AccessControlList) this .acl.clone();
248: clone.effectiveACL = (AccessControlList) this .effectiveACL
249: .clone();
250: clone.lastModified = this .lastModified;
251: clone.status = this .status;
252: clone.composedBlueprintName = this .composedBlueprintName;
253: clone.sensitiveContentCategories = this .sensitiveContentCategories;
254: clone.sensitiveTemplateCategories = this .sensitiveTemplateCategories;
255: clone.contentResources = cloneResources(contentResources);
256: clone.templateResources = cloneResources(templateResources);
257: clone.meta = (Metadata) meta.clone();
258: clone.meta.setModified(true);
259: clone.publisherName = "";
260: clone.publisherType = "";
261: }
262:
263: public Map cloneResources(Map resources) {
264: if (resources == null) {
265: return null;
266: }
267: HashMap map = new HashMap();
268: Iterator iterator = resources.entrySet().iterator();
269:
270: while (iterator.hasNext()) {
271: Map.Entry entry = (Map.Entry) iterator.next();
272: try {
273: map.put(entry.getKey(), ((ResourceReference) entry
274: .getValue()).clone());
275: } catch (CloneNotSupportedException e) {
276: // will never happen as ResourceReference is Cloneable
277: }
278: }
279: return map;
280: }
281:
282: public void setIsFinal(boolean flag) {
283: isFinal = flag;
284: }
285:
286: public void setLastModified(long time) {
287: this .lastModified = time;
288: }
289:
290: public void setModifiedBy(ContelligentPrincipal principal) {
291: this .modifiedBy = principal;
292: }
293:
294: void setEffectiveACL(AccessControlList effectiveACL) {
295: this .effectiveACL = effectiveACL;
296: }
297:
298: public void setACL(AccessControlList acl) {
299: this .acl = acl;
300: }
301:
302: public void setStatus(int status) {
303: this .status = status;
304: }
305:
306: void setNode(final NamedNode node) {
307: this .node = node;
308: }
309:
310: NamedNode getNode() {
311: return node;
312: }
313:
314: void setInheritSecurity(boolean value) {
315: this .inheritSecurity = value;
316: }
317:
318: boolean inheritSecurity() {
319: return inheritSecurity;
320: }
321:
322: // these methods are public but NOT in the ComponentContext interface
323: // only needed to communicate the type-name between
324: // ComponentPersistenceAdapter
325: // and ComponentManager implementation
326: public long getTypeId() {
327: return typeId;
328: }
329:
330: public void setTypeId(long typeId) {
331: this .typeId = typeId;
332: }
333:
334: public String getTypeName() {
335: return typeName;
336: }
337:
338: public void setTypeName(String typeName) {
339: this .typeName = typeName;
340: }
341:
342: public boolean isRemoved() {
343: return status == ComponentPersistenceAdapter.DELETED;
344: }
345:
346: public boolean isRecreated() {
347: return status == ComponentPersistenceAdapter.RECREATED;
348: }
349:
350: public Component getComponent() {
351: return component;
352: }
353:
354: public void setComponent(Component component) {
355: if (component.getComponentContext() != null
356: && component.getComponentContext() != this ) {
357: throw new IllegalArgumentException(
358: "Component is already assigned to another context");
359: }
360: this .component = component;
361: component.setComponentContext(this );
362: }
363:
364: public Set getSensitiveContentCategories() {
365: if (sensitiveContentCategories == null) {
366: return Collections.EMPTY_SET;
367: }
368: return sensitiveContentCategories;
369: }
370:
371: public void setSensitiveContentCategories(
372: Set sensitiveContentCategories) {
373: if (contentResources != null) {
374: try {
375: Map newMap = rehashResources(getContentResources(),
376: getSensitiveContentCategories(),
377: sensitiveContentCategories);
378: removedResources.addAll(findRemovedResources(
379: getContentResources(), newMap));
380: setContentResources(newMap, false);
381: } catch (ModificationVetoException e) {
382: // ignore, will never happen
383: }
384: }
385: this .sensitiveContentCategories = Collections
386: .unmodifiableSet(new HashSet(sensitiveContentCategories));
387: }
388:
389: public Set getSensitiveTemplateCategories() {
390: if (sensitiveTemplateCategories == null) {
391: return Collections.EMPTY_SET;
392: }
393: return sensitiveTemplateCategories;
394: }
395:
396: public void setSensitiveTemplateCategories(
397: Set sensitiveTemplateCategories) {
398: if (templateResources != null) {
399: Map newMap = rehashResources(getTemplateResources(),
400: getSensitiveTemplateCategories(),
401: sensitiveTemplateCategories);
402: removedResources.addAll(findRemovedResources(
403: getTemplateResources(), newMap));
404: setTemplateResources(newMap);
405: }
406: this .sensitiveTemplateCategories = Collections
407: .unmodifiableSet(new HashSet(
408: sensitiveTemplateCategories));
409: }
410:
411: private Collection findRemovedResources(Map templateResources,
412: Map newMap) {
413: HashSet set = new HashSet();
414:
415: Iterator iterator = templateResources.values().iterator();
416: while (iterator.hasNext()) {
417: ResourceReference reference = (ResourceReference) iterator
418: .next();
419: if (reference.isPersistent()) {
420: set.add(new Long(reference.getResourceId()));
421: }
422: }
423:
424: iterator = newMap.values().iterator();
425: while (iterator.hasNext()) {
426: ResourceReference reference = (ResourceReference) iterator
427: .next();
428: if (reference.isPersistent()) {
429: set.remove(new Long(reference.getResourceId()));
430: }
431: }
432: return set;
433: }
434:
435: public Resource getTemplateResource(String identifier)
436: throws ComponentPersistenceException {
437: ResourceReference proxy = (ResourceReference) getTemplateResources()
438: .get(identifier.trim());
439:
440: if (proxy == null) {
441: return null;
442: }
443: return proxy.getResource();
444: }
445:
446: public void setTemplateResource(String identifier, Resource resource) {
447: String key = identifier.trim();
448: if (templateResources == null) {
449: templateResources = new HashMap();
450: } else {
451: ResourceReference proxy = (ResourceReference) templateResources
452: .get(key);
453:
454: if (proxy != null && proxy.isPersistent()) {
455: removedResources.add(new Long(proxy.getResourceId()));
456: }
457: }
458: templateResources.put(key, new ResourceReference(resource));
459: }
460:
461: public void removeTemplateResource(String identifier) {
462: if (templateResources == null) {
463: return;
464: }
465: ResourceReference proxy = (ResourceReference) getTemplateResources()
466: .get(identifier.trim());
467: if (proxy != null && proxy.isPersistent()) {
468: removedResources.add(new Long(proxy.getResourceId()));
469: }
470: templateResources.remove(identifier.trim());
471: }
472:
473: public Resource getContentResource(String identifier)
474: throws ComponentPersistenceException {
475: ResourceReference proxy = (ResourceReference) getContentResources()
476: .get(identifier.trim());
477:
478: if (proxy == null) {
479: return null;
480: }
481: return proxy.getResource();
482: }
483:
484: public void setContentResource(String identifier, Resource resource) {
485: String key = identifier.trim();
486: if (contentResources == null) {
487: contentResources = new HashMap();
488: } else {
489: ResourceReference proxy = (ResourceReference) contentResources
490: .get(key);
491:
492: if (proxy != null && proxy.isPersistent()) {
493: removedResources.add(new Long(proxy.getResourceId()));
494: }
495: }
496: contentResources.put(key, new ResourceReference(resource));
497: }
498:
499: public void removeContentResource(String identifier) {
500: if (contentResources == null) {
501: return;
502: }
503: ResourceReference proxy = (ResourceReference) getContentResources()
504: .get(identifier.trim());
505: if (proxy != null && proxy.isPersistent()) {
506: removedResources.add(new Long(proxy.getResourceId()));
507: }
508: contentResources.remove(identifier.trim());
509: }
510:
511: public Map getContentResources() {
512: if (contentResources == null) {
513: return Collections.EMPTY_MAP;
514: }
515: return Collections.unmodifiableMap(contentResources);
516: }
517:
518: public void setContentResources(Map contentResources)
519: throws ModificationVetoException {
520: setContentResources(contentResources, true);
521: }
522:
523: public void setContentResources(Map contentResources, boolean check)
524: throws ModificationVetoException {
525: if (check && !component.mayChangeContent()) {
526: throw new ModificationVetoException(
527: ContelligentExceptionID.modificationVeto_content_readOnly,
528: new Object[] { getPath() });
529: } else {
530: this .contentResources = insertProxies(contentResources);
531: }
532: }
533:
534: public Map getTemplateResources() {
535: if (templateResources == null) {
536: return Collections.EMPTY_MAP;
537: }
538: return Collections.unmodifiableMap(templateResources);
539: }
540:
541: public void setTemplateResources(Map templateResources) {
542: this .templateResources = insertProxies(templateResources);
543: }
544:
545: public Set getContentResourceIdentifiers() {
546: return Collections.unmodifiableSet(getContentResources()
547: .keySet());
548: }
549:
550: public Set getTemplateResourceIdentifiers() {
551: return Collections.unmodifiableSet(getTemplateResources()
552: .keySet());
553: }
554:
555: public void putMetainfo(Metainfo metainfo) {
556: metainfo.addKeyword("type", getTypeName());
557: metainfo.addKeyword("secureTransfer", String
558: .valueOf(definesSecureTransfer()));
559: metainfo.addDate("lastModified", getLastModified());
560: metainfo.addKeyword("cm", persistenceManager.getName());
561: }
562:
563: public Set getRemovedResources() {
564: return Collections.unmodifiableSet(removedResources);
565: }
566:
567: public void resetRemovedResources() {
568: removedResources = new HashSet();
569: }
570:
571: private Map rehashResources(Map resources,
572: Collection oldCategories, Collection newCategories) {
573: Map newResourceMap = new HashMap();
574: Collection ignoreIdentifiers = new ArrayList();
575:
576: Collection addedCategories = new ArrayList(newCategories);
577: Collection removedCategories = new ArrayList(oldCategories);
578: addedCategories.removeAll(oldCategories);
579: removedCategories.removeAll(newCategories);
580: // now we have added and status categories in separated collections
581: CategoryManager categoryManager = system.getCategoryManager();
582:
583: Iterator iterator = resources.keySet().iterator();
584: while (iterator.hasNext()) {
585: String identifier = (String) iterator.next();
586: Map categoryMap = categoryManager
587: .createCategoryMapForUniqueCategoryIdentifier(
588: oldCategories, identifier);
589: update(categoryMap, addedCategories, removedCategories);
590: String newIdentifier = categoryManager
591: .createUniqueCategoryIdentifier(newCategories,
592: categoryMap);
593:
594: if (!ignoreIdentifiers.contains(newIdentifier)) {
595: if (newResourceMap.containsKey(newIdentifier)) {
596: newResourceMap.remove(newIdentifier);
597: ignoreIdentifiers.add(newIdentifier);
598: } else {
599: newResourceMap.put(newIdentifier, resources
600: .get(identifier));
601: }
602: }
603: }
604: return newResourceMap;
605: }
606:
607: /**
608: * Modify the given category map by adding the default value for added
609: * categories and removing the value for status categories.
610: *
611: * @param categoryMap
612: * @param addedCategories
613: * @param removedCategories
614: */
615: private void update(Map categoryMap, Collection addedCategories,
616: Collection removedCategories) {
617: Iterator iterator;
618:
619: iterator = addedCategories.iterator();
620: while (iterator.hasNext()) {
621: Category category = (Category) iterator.next();
622: categoryMap.put(category.getName(), category
623: .getDefaultValue());
624: }
625: iterator = removedCategories.iterator();
626: while (iterator.hasNext()) {
627: Category category = (Category) iterator.next();
628: categoryMap.remove(category.getName());
629: }
630: }
631:
632: private Map insertProxies(Map templateResources) {
633: HashMap map = new HashMap();
634: Iterator iterator = templateResources.entrySet().iterator();
635: while (iterator.hasNext()) {
636: Map.Entry entry = (Map.Entry) iterator.next();
637: if (entry.getValue() instanceof ResourceReference) {
638: map.put(entry.getKey(), entry.getValue());
639: } else {
640: map.put(entry.getKey(), new ResourceReference(
641: (Resource) entry.getValue()));
642: }
643: }
644: return map;
645: }
646:
647: public void setRemoved() {
648: setStatus(ComponentPersistenceAdapter.DELETED);
649: }
650:
651: public boolean isDynamic() {
652: return false;
653: }
654:
655: public void setMetadata(Metadata meta) {
656: this .meta = meta;
657: }
658:
659: public Metadata getMetadata() {
660: if (meta == null) {
661: meta = new Metadata();
662: }
663: return meta;
664: }
665:
666: public void setPublisher(String publisherName, String publisherType) {
667: this .publisherName = publisherName;
668: this .publisherType = publisherType;
669: }
670:
671: public String getPublisherName() {
672: return publisherName;
673: }
674:
675: public String getPublisherType() {
676: return publisherType;
677: }
678:
679: }
|