Source Code Cross Referenced for BasicComponentManager.java in  » Content-Management-System » contelligent » de » finix » contelligent » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » contelligent » de.finix.contelligent.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2001-2006 C:1 Financial Services GmbH
0003:         *
0004:         * This software is free software; you can redistribute it and/or
0005:         * modify it under the terms of the GNU Lesser General Public
0006:         * License Version 2.1, as published by the Free Software Foundation.
0007:         *
0008:         * This software is distributed in the hope that it will be useful,
0009:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0010:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0011:         * Lesser General Public License for more details.
0012:         *
0013:         * You should have received a copy of the GNU Lesser General Public
0014:         * License along with this library; if not, write to the Free Software
0015:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
0016:         */
0017:
0018:        package de.finix.contelligent.core;
0019:
0020:        import java.io.IOException;
0021:        import java.io.InputStream;
0022:        import java.io.Writer;
0023:        import java.math.BigDecimal;
0024:        import java.util.ArrayList;
0025:        import java.util.Collection;
0026:        import java.util.Collections;
0027:        import java.util.HashMap;
0028:        import java.util.HashSet;
0029:        import java.util.Iterator;
0030:        import java.util.LinkedList;
0031:        import java.util.List;
0032:        import java.util.ListIterator;
0033:        import java.util.Map;
0034:        import java.util.Set;
0035:
0036:        import javax.transaction.Status;
0037:
0038:        import org.apache.commons.fileupload.FileItem;
0039:
0040:        import de.finix.contelligent.CallData;
0041:        import de.finix.contelligent.Component;
0042:        import de.finix.contelligent.ComponentContext;
0043:        import de.finix.contelligent.ComponentCreationException;
0044:        import de.finix.contelligent.ComponentLink;
0045:        import de.finix.contelligent.ComponentManager;
0046:        import de.finix.contelligent.ComponentNotFoundException;
0047:        import de.finix.contelligent.ComponentPath;
0048:        import de.finix.contelligent.ComponentPathException;
0049:        import de.finix.contelligent.Container;
0050:        import de.finix.contelligent.Contelligent;
0051:        import de.finix.contelligent.CopyMode;
0052:        import de.finix.contelligent.GlobalComponentPath;
0053:        import de.finix.contelligent.ModificationVetoException;
0054:        import de.finix.contelligent.ObservingContainer;
0055:        import de.finix.contelligent.SecureComponent;
0056:        import de.finix.contelligent.Type;
0057:        import de.finix.contelligent.category.Category;
0058:        import de.finix.contelligent.category.CategoryException;
0059:        import de.finix.contelligent.category.CategoryManager;
0060:        import de.finix.contelligent.category.CategorySubset;
0061:        import de.finix.contelligent.components.Folder;
0062:        import de.finix.contelligent.components.SortedFolder;
0063:        import de.finix.contelligent.components.legacy.FileFacade;
0064:        import de.finix.contelligent.content.Metadata;
0065:        import de.finix.contelligent.core.security.AccessControlList;
0066:        import de.finix.contelligent.core.security.AclEntry;
0067:        import de.finix.contelligent.core.security.ComponentAccess;
0068:        import de.finix.contelligent.core.security.ComponentPermission;
0069:        import de.finix.contelligent.core.security.ContelligentPrincipal;
0070:        import de.finix.contelligent.core.security.ContelligentPrincipalFactory;
0071:        import de.finix.contelligent.core.security.ContelligentSecurityManager;
0072:        import de.finix.contelligent.core.security.User;
0073:        import de.finix.contelligent.event.ComponentEvent;
0074:        import de.finix.contelligent.event.ContelligentEvent;
0075:        import de.finix.contelligent.event.EventQueue;
0076:        import de.finix.contelligent.event.TypeEvent;
0077:        import de.finix.contelligent.exception.ComponentAlreadyExistsException;
0078:        import de.finix.contelligent.exception.ComponentAlreadyLockedException;
0079:        import de.finix.contelligent.exception.ComponentLockException;
0080:        import de.finix.contelligent.exception.ComponentMoveException;
0081:        import de.finix.contelligent.exception.ComponentPersistenceException;
0082:        import de.finix.contelligent.exception.ComponentSystemException;
0083:        import de.finix.contelligent.exception.ComponentWriteException;
0084:        import de.finix.contelligent.exception.ContelligentException;
0085:        import de.finix.contelligent.exception.ContelligentExceptionID;
0086:        import de.finix.contelligent.exception.ContelligentRuntimeException;
0087:        import de.finix.contelligent.exception.ContelligentSecurityException;
0088:        import de.finix.contelligent.exception.MissingPermissionException;
0089:        import de.finix.contelligent.exception.NoDeletePermissionException;
0090:        import de.finix.contelligent.exception.NoReadPermissionException;
0091:        import de.finix.contelligent.exception.NoWritePermissionException;
0092:        import de.finix.contelligent.exception.NotLockOwnerException;
0093:        import de.finix.contelligent.exception.NotOwnerException;
0094:        import de.finix.contelligent.exception.RelationExistsException;
0095:        import de.finix.contelligent.exception.RelationsException;
0096:        import de.finix.contelligent.exception.TypeException;
0097:        import de.finix.contelligent.exception.UnknownTypeException;
0098:        import de.finix.contelligent.exception.WouldCreateDeadRelationsException;
0099:        import de.finix.contelligent.logging.LoggingService;
0100:        import de.finix.contelligent.persistence.ComponentDBAdapter;
0101:        import de.finix.contelligent.persistence.ComponentDBPathHolder;
0102:        import de.finix.contelligent.persistence.ComponentPersistenceAdapter;
0103:        import de.finix.contelligent.persistence.LocalFileAdapter;
0104:        import de.finix.contelligent.resource.BinaryResource;
0105:        import de.finix.contelligent.resource.NumberResource;
0106:        import de.finix.contelligent.resource.Resource;
0107:        import de.finix.contelligent.resource.StringResource;
0108:        import de.finix.contelligent.resource.TextResource;
0109:        import de.finix.contelligent.search.system.SystemIndex;
0110:        import de.finix.contelligent.search.system.SystemIndexer;
0111:        import de.finix.contelligent.util.StringHash;
0112:        import de.finix.contelligent.util.ThreadedMem;
0113:        import de.finix.contelligent.xml.elements.ACLElement;
0114:        import de.finix.contelligent.xml.elements.ComponentElement;
0115:        import de.finix.contelligent.xml.elements.ComponentMetainfoElement;
0116:        import de.finix.contelligent.xml.elements.ComponentSecurityElement;
0117:        import de.finix.contelligent.xml.elements.PrincipalElement;
0118:        import de.finix.contelligent.xml.elements.ResourceElement;
0119:        import de.finix.contelligent.xml.elements.SecurityElement;
0120:        import de.finix.contelligent.xml.elements.TypeElement;
0121:
0122:        /**
0123:         * A <code>BasicComponentManager</code> is a {@link ComponentManager} which
0124:         * directly operates on the underlying persistent store.
0125:         * 
0126:         * Since accessing the database for every component access is very slow, a
0127:         * production environment should always use a cacheing subclass of this,
0128:         * although this class can be used directly for development purposes.
0129:         */
0130:        public class BasicComponentManager implements  ComponentManagerInternal {
0131:            final static org.apache.log4j.Logger log = LoggingService
0132:                    .getLogger(BasicComponentManager.class);
0133:
0134:            /**
0135:             * This type is used for all links, for example if a final component should
0136:             * be copied.
0137:             */
0138:            public static final String DEFAULT_LINK_TYPE = "contelligent.core.Link";
0139:
0140:            /** This property must be passed in the map when creating a link. */
0141:            public static final String DEFAULT_LINK_TYPE_PATH_PROPERTY = "targetPath";
0142:
0143:            /**
0144:             * Basic certification level using low-security but less cpu intensive
0145:             * operations only.
0146:             */
0147:            public static final int CERT_BASIC = 1;
0148:
0149:            /**
0150:             * Extended certification level for higher security requirements (reserved;
0151:             * not supported yet)
0152:             */
0153:            public static final int CERT_SIGNED = 2;
0154:
0155:            /**
0156:             * Only certified as safe for execution by user name.
0157:             */
0158:            public static final int CERT_USER = 3;
0159:
0160:            // if true no relations are checked in beforeCompletion():
0161:            final static boolean SKIP_RELATIONS_CHECK = true;
0162:
0163:            final Container rootContainer;
0164:
0165:            final BasicComponentManager parent;
0166:
0167:            final String name;
0168:
0169:            final AccessControlList rootACL;
0170:
0171:            final public String ROOT_TYPENAME = DEFAULT_FOLDER_TYPE;
0172:
0173:            final public String ROOT_TYPEGROUP = "container";
0174:
0175:            final ComponentFactoryImpl componentFactory;
0176:
0177:            final LocalFileAdapter fileAdapter;
0178:
0179:            final ComponentPersistenceAdapter componentAdapter;
0180:
0181:            final User defaultOwner;
0182:
0183:            final Contelligent contelligent;
0184:
0185:            final ComponentLockManager componentLockManager;
0186:
0187:            final RelationsManagerImpl relationsManager;
0188:
0189:            private SystemIndex systemIndex;
0190:
0191:            private SystemIndexer listener;
0192:
0193:            private Set readOnlyPaths = new HashSet(0);
0194:
0195:            /** contains a Map with (ComponentPath, Component) entries */
0196:            final private ThreadLocal cloneMap = new ThreadLocal();
0197:
0198:            /** contains a List with ContelligentEvent instances */
0199:            final private ThreadLocal eventList = new ThreadLocal();
0200:
0201:            /**
0202:             * contains a List of String instances, the names of files to move to parent
0203:             * file-adapter
0204:             */
0205:            final private ThreadLocal filesToMoveList = new ThreadLocal();
0206:
0207:            /**
0208:             * a Boolean flag indicating that this manager was destroyed and
0209:             * file-adapters should be destroyed too
0210:             */
0211:            final private ThreadLocal destroyFileAdapters = new ThreadLocal();
0212:
0213:            /**
0214:             * a boolean flag indicating that this managers parent manager was used in
0215:             * the current transaction
0216:             */
0217:            final private ThreadLocal parentInTransaction = new ThreadLocal();
0218:
0219:            private AccessControlList acl;
0220:
0221:            final private boolean isImportManager;
0222:
0223:            // system property to disable check for dead relations in
0224:            // commitServer/commitSubtree
0225:            static final String PROPERTY_DISABLE_DEADRELATIONSCHECK = "contelligent.unsupported.disable.checkdeadrelations";
0226:
0227:            static final boolean deadRelationsCheckDisabled = Boolean
0228:                    .getBoolean(PROPERTY_DISABLE_DEADRELATIONSCHECK);
0229:
0230:            /**
0231:             * Creates a new <code>BasicComponentManager</code> instance and
0232:             * initializes all adapters.
0233:             * 
0234:             * @exception ContelligentException
0235:             *                if an error occurs
0236:             */
0237:            BasicComponentManager(String fullName,
0238:                    BasicComponentManager parent, Contelligent contelligent,
0239:                    ComponentLockManager componentLockManager,
0240:                    SecurityElement securityConfig,
0241:                    ComponentFactory componentFactory,
0242:                    ComponentPersistenceAdapter componentAdapter,
0243:                    LocalFileAdapter fileAdapter, AccessControlList acl,
0244:                    Map properties) throws ContelligentException {
0245:                this .name = fullName;
0246:                this .parent = parent;
0247:                this .contelligent = contelligent;
0248:                this .componentLockManager = componentLockManager;
0249:                this .componentAdapter = componentAdapter;
0250:                this .isImportManager = (properties == null) ? false : Boolean
0251:                        .valueOf((String) properties.get(PROPERTY_ISIMPORT))
0252:                        .booleanValue();
0253:                this .relationsManager = (RelationsManagerImpl) contelligent
0254:                        .getRelationsManager();
0255:
0256:                try {
0257:                    this .componentFactory = (ComponentFactoryImpl) componentFactory;
0258:                    this .fileAdapter = fileAdapter;
0259:
0260:                    if (securityConfig != null) {
0261:                        PrincipalElement defaultOwnerElement = securityConfig
0262:                                .getDefaultOwnerElement();
0263:                        log.info("'" + this .name
0264:                                + "':<init> - ... set default owner user to '"
0265:                                + defaultOwnerElement.getGroupId() + ':'
0266:                                + defaultOwnerElement.getPrincipalId()
0267:                                + "' ...");
0268:                        if (ContelligentSecurityManager.getInstance()
0269:                                .existsUser(
0270:                                        defaultOwnerElement.getPrincipalId(),
0271:                                        defaultOwnerElement.getGroupId())) {
0272:                            defaultOwner = ContelligentPrincipalFactory
0273:                                    .createUserPrincipal(defaultOwnerElement
0274:                                            .getPrincipalId(),
0275:                                            defaultOwnerElement.getGroupId());
0276:                        } else {
0277:                            log
0278:                                    .warn("'"
0279:                                            + this .name
0280:                                            + "']:<init> - ... could not find default-owner (groupId='"
0281:                                            + defaultOwnerElement.getGroupId()
0282:                                            + "', id='"
0283:                                            + defaultOwnerElement
0284:                                                    .getPrincipalId()
0285:                                            + "') -> using SYSTEM instead.");
0286:                            defaultOwner = getSystemUser();
0287:                        }
0288:                        rootACL = createRootACL(securityConfig.getACLElement());
0289:                        log.info("'" + this .name
0290:                                + "':<init> - ... done with security-config.");
0291:                    } else {
0292:                        if (parent == null) {
0293:                            log
0294:                                    .fatal("'"
0295:                                            + this .name
0296:                                            + "':<init> - need a security-config to configure without a parent!");
0297:                            throw new ContelligentException(
0298:                                    "'"
0299:                                            + this .name
0300:                                            + "':<init> - need a security-config to configure without a parent!");
0301:                        }
0302:                        defaultOwner = parent.defaultOwner;
0303:                        rootACL = (AccessControlList) parent.rootACL.clone();
0304:                    }
0305:                    rootContainer = createRootContainer();
0306:                    this .acl = acl;
0307:
0308:                    if (!isImportManager && contelligent.hasSystemIndex()) {
0309:                        systemIndex = new SystemIndex(this );
0310:                        listener = new SystemIndexer(systemIndex);
0311:                        EventQueue.getInstance().addListener(listener);
0312:                    }
0313:                    log.debug("'" + this .name + "':<init> - done.");
0314:                } catch (ComponentPersistenceException e) {
0315:                    log
0316:                            .error(
0317:                                    "'"
0318:                                            + this .name
0319:                                            + "':<init> - exception during initialization of adapter: ",
0320:                                    e);
0321:                    throw new ContelligentException(
0322:                            this 
0323:                                    + ":<init> - exception during initialization of adapter.",
0324:                            e);
0325:                } catch (Exception e) {
0326:                    log
0327:                            .error(
0328:                                    "'"
0329:                                            + this .name
0330:                                            + "':<init> - Exception during initialization of adapter: ",
0331:                                    e);
0332:                    throw new ContelligentException(
0333:                            this 
0334:                                    + ":<init> - exception during initialization of adapter.",
0335:                            e);
0336:                }
0337:            }
0338:
0339:            /**
0340:             * Answer true whether this is the root manager.
0341:             */
0342:            final public boolean isRoot() {
0343:                return parent == null;
0344:            }
0345:
0346:            /**
0347:             * Answer true whether this is an import manager.
0348:             * 
0349:             * @return
0350:             */
0351:            final public boolean isImport() {
0352:                return isImportManager;
0353:            }
0354:
0355:            final public ComponentManager getParent() {
0356:                return parent;
0357:            }
0358:
0359:            final public ComponentPersistenceAdapter getComponentPersistenceAdapter() {
0360:                return componentAdapter;
0361:            }
0362:
0363:            void destroy(boolean includeFileAdapters)
0364:                    throws ContelligentException {
0365:                if (systemIndex != null) {
0366:                    EventQueue.getInstance().removeListener(listener);
0367:                    listener.stopThread();
0368:                    systemIndex.destroy();
0369:                    systemIndex = null;
0370:                    listener = null;
0371:                }
0372:
0373:                if (isRoot()) {
0374:                    throw new ContelligentException(
0375:                            "Cannot destroy root manager");
0376:                }
0377:                // XXX: maybe check/destroy all sessions related to this manager first.
0378:                // (rs)
0379:                log.debug("'" + name + "':destroy() - begin ...");
0380:                componentAdapter.destroy();
0381:                if (includeFileAdapters) {
0382:                    // thread-local flag: we can't simply destroy the file-adapter here
0383:                    // because that is not transactional!
0384:                    destroyFileAdapters.set(Boolean.TRUE);
0385:                }
0386:                componentLockManager.removeLocksForComponentManager(this );
0387:                relationsManager.removeRelationsOfTree(ComponentPath.ROOT_PATH,
0388:                        this .getId());
0389:                invalidatePath(ComponentPath.ROOT_PATH, true);
0390:                log.debug("'" + name + "':destroy() - ... done.");
0391:            }
0392:
0393:            /**
0394:             * Implementation of
0395:             * {@link de.finix.contelligent.ComponentManager#commitServer}.
0396:             */
0397:            final public void commitServer(CallData callData)
0398:                    throws ContelligentException, ModificationVetoException,
0399:                    RelationsException, ComponentLockException {
0400:                commitPath(ComponentPath.ROOT_PATH, callData);
0401:                parent.checkRelations(callData);
0402:            }
0403:
0404:            /**
0405:             * Implementation of {@link ComponentManager#commitSubtree}.
0406:             */
0407:            final public void commitSubtree(ComponentPath root,
0408:                    CallData callData) throws ContelligentException,
0409:                    ModificationVetoException, RelationsException,
0410:                    ComponentLockException {
0411:                commitPath(root, callData);
0412:                parent.checkRelations(callData);
0413:            }
0414:
0415:            final private void commitPath(ComponentPath rootPath,
0416:                    CallData callData) throws ContelligentException,
0417:                    ModificationVetoException, RelationsException,
0418:                    ComponentLockException {
0419:                boolean debugEnabled = log.isDebugEnabled();
0420:                // FIXME: check if user has permission COMMIT_SUBTREE
0421:                if (isRoot()) {
0422:                    throw new RuntimeException("Operation not supported");
0423:                }
0424:                // Make sure the parent container already exists in the parent manager
0425:                if (!rootPath.isRoot()) {
0426:                    ComponentPath parentPath = rootPath.parentPath();
0427:                    if (!parent.componentExists(parentPath)) {
0428:                        throw new ComponentNotFoundException(
0429:                                ContelligentExceptionID.component_notFoundInParentCM,
0430:                                parentPath);
0431:                    }
0432:                    if (componentExists(parentPath, false)) {
0433:                        Component parentComp = getComponent(parentPath,
0434:                                callData);
0435:                        // If a sorted folder and its subcomponent are modified,
0436:                        // only committing the subcomponent can result in an
0437:                        // inconsistent state on the sorted folder, so we
0438:                        // prevent this.
0439:                        if (parentComp instanceof  SortedFolder) {
0440:                            throw new ComponentPersistenceException(
0441:                                    ContelligentExceptionID.component_commit_without_sorted_parent);
0442:                        }
0443:                    }
0444:                }
0445:                // If a component is deleted and recreated, you cannot just commit
0446:                // one of its subcomponents, since otherwise you could create an
0447:                // inconsistent state that way.
0448:                if (isSubpathOfDeletedOrRecreated(rootPath, callData)) {
0449:                    throw new ComponentPersistenceException(
0450:                            ContelligentExceptionID.component_recreated_parent);
0451:                }
0452:
0453:                // XXX: if one has the permission we must not check locks so the admin
0454:                // may commit changes from various users
0455:                Iterator i = componentAdapter.getLocalComponentNames(rootPath)
0456:                        .iterator();
0457:                while (i.hasNext()) {
0458:                    ComponentDBPathHolder dbPath = (ComponentDBPathHolder) i
0459:                            .next();
0460:                    ComponentPath path = dbPath.getPath();
0461:                    if (dbPath.isRemoved()) {
0462:                        parent.deleteComponentTree(path, callData, true, false,
0463:                                false, true); // fires delete event
0464:                        if (debugEnabled)
0465:                            log.debug("'" + this .name
0466:                                    + "':commitPath() - ... deleted tree '"
0467:                                    + path + "' in parent ...");
0468:                        // removes relations but don't checks for remaining relations!
0469:                    } else {
0470:                        try {
0471:                            Component clonedComponent = cloneForManager(path,
0472:                                    parent, callData);
0473:                            parent.addClone(path, clonedComponent);
0474:                            if (debugEnabled)
0475:                                log.debug("'" + this .name
0476:                                        + "':commitPath() - added clone of '"
0477:                                        + path + "' to parent '" + parent
0478:                                        + "' ...");
0479:                            if (dbPath.isRecreated()) {
0480:                                parent.deleteComponentTree(path, callData,
0481:                                        true, false, false, true); // fires delete event
0482:                                // removes relations but don't checks for remaining relations!
0483:                                parent.addEvent(new ComponentEvent(
0484:                                        ComponentEvent.ADD, clonedComponent,
0485:                                        parent.getName()));
0486:                            } else {
0487:                                if (parent.componentExists(path)) {
0488:                                    parent.getComponentPersistenceAdapter()
0489:                                            .delete(path, false, false);
0490:                                    relationsManager.removeRelations(path,
0491:                                            parent.getId());
0492:                                    parent.addEvent(new ComponentEvent(
0493:                                            ComponentEvent.CHANGE,
0494:                                            clonedComponent, parent.getName()));
0495:                                } else {
0496:                                    parent.addEvent(new ComponentEvent(
0497:                                            ComponentEvent.ADD,
0498:                                            clonedComponent, parent.getName()));
0499:                                }
0500:                            }
0501:                        } catch (Exception e) { // should never occur since we clone an already existing type !!
0502:                            log
0503:                                    .error("'"
0504:                                            + this .name
0505:                                            + "':commitPath() - Exception while cloning '"
0506:                                            + path + "': " + e);
0507:                            throw new ComponentPersistenceException(
0508:                                    new Object[] { path.toPath() }, e);
0509:                        }
0510:                    }
0511:                }
0512:
0513:                checkForFilesToMove(rootPath, callData);
0514:                relationsManager.moveRelationsOfTree(rootPath, this .getId(),
0515:                        parent.getId(), true);
0516:
0517:                if (ComponentPath.ROOT_PATH.equals(rootPath)) {
0518:                    parent.getComponentPersistenceAdapter().mergeAdapter(
0519:                            this .componentAdapter);
0520:                    componentLockManager.removeLocksForComponentManager(this );
0521:                } else {
0522:                    parent.getComponentPersistenceAdapter()
0523:                            .mergeSubtreeOfAdapter(rootPath,
0524:                                    this .componentAdapter);
0525:                    componentLockManager.removeLocksForComponentTree(rootPath);
0526:                }
0527:
0528:                parentInTransaction.set(Boolean.TRUE);
0529:                invalidatePath(rootPath, true);
0530:            }
0531:
0532:            final public void checkRelations(CallData callData)
0533:                    throws ComponentPersistenceException,
0534:                    WouldCreateDeadRelationsException {
0535:                checkRelationsOfComponent(ComponentPath.ROOT_PATH, true,
0536:                        callData);
0537:            }
0538:
0539:            final private void checkRelationsOfComponent(ComponentPath path,
0540:                    boolean recursive, CallData callData)
0541:                    throws ComponentPersistenceException,
0542:                    WouldCreateDeadRelationsException {
0543:                if (!callData.shouldCheckRelations()) {
0544:                    log
0545:                            .debug("'"
0546:                                    + this .name
0547:                                    + "':checkRelations() - check for dead relations disabled in callData!");
0548:                    return;
0549:                }
0550:                if (deadRelationsCheckDisabled) {
0551:                    log
0552:                            .warn("'"
0553:                                    + this .name
0554:                                    + "':checkRelations() - check for dead relations disabled!");
0555:                    return;
0556:                }
0557:                log
0558:                        .debug("'"
0559:                                + this .name
0560:                                + "':checkRelations() - ... now checking for dead relations in subtree '"
0561:                                + path + "' ...");
0562:                Map deadRelations = relationsManager.getDeadRelations(path,
0563:                        this .getIdsUpToRoot(), recursive);
0564:                if (!deadRelations.isEmpty()) {
0565:                    log.debug("'" + name
0566:                            + "':checkRelations() - found dead relations: "
0567:                            + deadRelations + "!");
0568:                    callData.markForRollback();
0569:                    throw new WouldCreateDeadRelationsException(path,
0570:                            deadRelations);
0571:                }
0572:            }
0573:
0574:            /**
0575:             * Force a relation check (to be used by
0576:             * {@link AbstractCallDataImpl#doWithoutRelationsCheck} only).
0577:             * 
0578:             * @throws ComponentPersistenceException
0579:             * @throws WouldCreateDeadRelationsException
0580:             */
0581:            final void checkRelations() throws ComponentPersistenceException,
0582:                    WouldCreateDeadRelationsException {
0583:                Map deadRelations = relationsManager.getDeadRelations(
0584:                        ComponentPath.ROOT_PATH, this .getIdsUpToRoot(), true);
0585:                if (!deadRelations.isEmpty()) {
0586:                    log.debug("'" + name
0587:                            + "':checkRelations() - found dead relations: "
0588:                            + deadRelations + "!");
0589:                    throw new WouldCreateDeadRelationsException(
0590:                            ComponentPath.ROOT_PATH, deadRelations);
0591:                }
0592:            }
0593:
0594:            private Component cloneForManager(ComponentPath componentPath,
0595:                    ComponentManagerInternal manager, CallData callData)
0596:                    throws Exception {
0597:                Component component = this .getComponent(componentPath,
0598:                        callData, false);
0599:                ComponentContextImpl orgCtx = (ComponentContextImpl) component
0600:                        .getComponentContext();
0601:                ComponentContextImpl clonedCtx = orgCtx.clone(parent);
0602:                Type type = orgCtx.getType();
0603:                Component clonedComponent = componentFactory
0604:                        .createRawInstance(type); // throws
0605:                // TypeException
0606:                type.setProperties(clonedComponent, type.getProperties(
0607:                        component, false));
0608:                clonedCtx.setComponent(clonedComponent);
0609:                clonedComponent.postCreate();
0610:                return clonedComponent;
0611:            }
0612:
0613:            /**
0614:             * Searches all components with a path beneath <tt>rootPath</tt> which
0615:             * have a type equal to {@link FileFacade#TYPENAME} or a subtype of this
0616:             * type and adds all corresponding file-names to {@link #filesToMoveList}.
0617:             * These files get then moved into the parent managers adapter in
0618:             * {@link #afterCompletion} if the transaction was successfully commited.
0619:             * 
0620:             * @param rootPath
0621:             *            the path to start searching FileFacade instances, pass null
0622:             *            for root path.
0623:             * @param callData
0624:             *            a <code>CallData</code> value
0625:             * @exception ComponentPersistenceException
0626:             *                if an error occurs
0627:             */
0628:            final private void checkForFilesToMove(ComponentPath rootPath,
0629:                    CallData callData) throws ComponentPersistenceException {
0630:                // we want only files from this manager!
0631:                long[] ids = new long[] { this .getId() };
0632:                Set typeNames = componentFactory
0633:                        .getSubTypeNames(FileFacade.TYPENAME);
0634:                typeNames.add(FileFacade.TYPENAME);
0635:                Set filePaths = componentAdapter
0636:                        .getComponentPathsForTypeInstances(rootPath, typeNames,
0637:                                ids);
0638:                log.debug("'" + name + "':checkFilesToMove() - found "
0639:                        + filePaths.size() + " files to move ...");
0640:                if (filePaths.size() > 0) {
0641:                    List fileNameList = (List) filesToMoveList.get();
0642:                    if (fileNameList == null) {
0643:                        fileNameList = new LinkedList();
0644:                        filesToMoveList.set(fileNameList);
0645:                    }
0646:                    Iterator files = filePaths.iterator();
0647:                    while (files.hasNext()) {
0648:                        ComponentPath path = (ComponentPath) files.next();
0649:                        try {
0650:                            FileFacade fileFacade = (FileFacade) getComponent(
0651:                                    path, callData);
0652:                            String resourceName = fileFacade.getResourceName();
0653:                            fileNameList.add(resourceName);
0654:                        } catch (Exception e) {
0655:                            log
0656:                                    .error("'"
0657:                                            + name
0658:                                            + "':checkFilesToMove() - Exception while fetching resource-name from external file component '"
0659:                                            + path
0660:                                            + "' (ignoring this component): "
0661:                                            + e);
0662:                        }
0663:                    }
0664:                }
0665:            }
0666:
0667:            protected boolean isSubpathOfDeletedOrRecreated(ComponentPath path,
0668:                    CallData callData) throws ComponentPersistenceException {
0669:                ComponentPath parent = path.parentPath();
0670:                if (parent == null) { // Happens if we call parentPath on the root
0671:                    // path
0672:                    return false;
0673:                }
0674:                return (componentAdapter.recreatedHierarchical(parent) || componentAdapter
0675:                        .deletedHierarchical(parent));
0676:            }
0677:
0678:            /**
0679:             * Rollback all changes in the given subtree.
0680:             * 
0681:             * @param root
0682:             * @param callData
0683:             * @throws ComponentPersistenceException
0684:             */
0685:            final public void rollbackChangesInSubtree(ComponentPath root,
0686:                    CallData callData) throws ComponentPersistenceException,
0687:                    NotLockOwnerException {
0688:                boolean wasDeleted = componentAdapter.deleted(root);
0689:                if (isSubpathOfDeletedOrRecreated(root, callData)) {
0690:                    throw new ComponentPersistenceException(
0691:                            ContelligentExceptionID.component_recreated_parent);
0692:                }
0693:                componentLockManager.checkLockPermission(root, callData);
0694:                componentAdapter.removeChanges(root);
0695:                componentLockManager.removeLocksForComponentTree(root);
0696:                // FIXME: add changed components or use 'invalidate-event' !
0697:                EventQueue.getInstance().addEvent(
0698:                        new ComponentEvent(ComponentEvent.CHANGE, root,
0699:                                this .name));
0700:                invalidatePath(root, true);
0701:                if (wasDeleted) {
0702:                    // Make sure a SortedFolder above our tree fixes its sort order
0703:                    try {
0704:                        Component added = getComponent(root, callData);
0705:                        Container parent = parentContainer(added);
0706:                        fireAddEvent(parent, added);
0707:                    } catch (ComponentNotFoundException cne) {
0708:                        throw new ComponentPersistenceException(cne);
0709:                    } catch (ModificationVetoException mve) {
0710:                        throw new ComponentPersistenceException(mve);
0711:                    }
0712:                }
0713:            }
0714:
0715:            final public LocalFileAdapter getFileAdapter() {
0716:                return this .fileAdapter;
0717:            }
0718:
0719:            final public String getName() {
0720:                return name;
0721:            }
0722:
0723:            final public Container getRootComponent() {
0724:                return rootContainer;
0725:            }
0726:
0727:            /**
0728:             * Implementation of {@link ComponentManager#parentContainer}. <BR>
0729:             * If this implementation doesn't find the parent a
0730:             * <code>ContelligentRuntimeException</code> is thrown to indicate this
0731:             * fatal error as every component except the root container must have a
0732:             * parent.
0733:             */
0734:            final public Container parentContainer(Component component) {
0735:                try {
0736:                    ComponentPath path = component.getComponentContext()
0737:                            .getPath();
0738:                    if (isRootPath(path))
0739:                        return null;
0740:                    return (Container) getComponent(path.parentPath(),
0741:                            ThreadedMem.getCallData());
0742:                } catch (ComponentNotFoundException e) {
0743:                    log
0744:                            .fatal("'"
0745:                                    + this .name
0746:                                    + "':parentContainer() - can't find parent of component '"
0747:                                    + component + "': " + e);
0748:                    throw new ContelligentRuntimeException(
0749:                            "'"
0750:                                    + this .name
0751:                                    + "':parentContainer() - can't find parent of component '"
0752:                                    + component + "'!", e);
0753:                }
0754:            }
0755:
0756:            /**
0757:             * Implementation of
0758:             * {@link ComponentManager#getComponent(ComponentPath, CallData)}.
0759:             */
0760:            final public Component getComponent(ComponentPath path,
0761:                    CallData callData) throws ComponentNotFoundException,
0762:                    ComponentCreationException {
0763:                return retrieveComponent(path, null, callData, true);
0764:            }
0765:
0766:            /**
0767:             * Implementation of
0768:             * {@link ComponentManager#getComponent(ComponentPath, CallData, boolean)}.
0769:             */
0770:            final public Component getComponent(ComponentPath path,
0771:                    CallData callData, boolean followLinks)
0772:                    throws ComponentNotFoundException,
0773:                    ComponentCreationException {
0774:                return retrieveComponent(path, null, callData, followLinks);
0775:            }
0776:
0777:            final public Component getSubcomponent(Container parentContainer,
0778:                    String subName, CallData callData)
0779:                    throws ComponentNotFoundException, ComponentPathException,
0780:                    ComponentCreationException {
0781:                return retrieveComponent(new ComponentPath(subName),
0782:                        parentContainer, callData, true);
0783:            }
0784:
0785:            final public Component getSubcomponent(Container parentContainer,
0786:                    String relativePath, CallData callData, boolean followLinks)
0787:                    throws ComponentNotFoundException, ComponentPathException,
0788:                    ComponentCreationException {
0789:                return retrieveComponent(new ComponentPath(relativePath),
0790:                        parentContainer, callData, followLinks);
0791:            }
0792:
0793:            final public Component getSubcomponent(Container parentContainer,
0794:                    ComponentPath relativePath, CallData callData)
0795:                    throws ComponentNotFoundException,
0796:                    ComponentCreationException {
0797:                return retrieveComponent(relativePath, parentContainer,
0798:                        callData, true);
0799:            }
0800:
0801:            final public Component getSubcomponent(Container parentContainer,
0802:                    ComponentPath relativePath, CallData callData,
0803:                    boolean followLinks) throws ComponentNotFoundException,
0804:                    ComponentCreationException {
0805:                return retrieveComponent(relativePath, parentContainer,
0806:                        callData, followLinks);
0807:            }
0808:
0809:            /**
0810:             * Returns the {@link Component} associated with the given
0811:             * {@link ComponentPath path} if it exists in this manager or in any parent
0812:             * manager or otherwise throws a <code>ComponentNotFoundException</code>.
0813:             * The <tt>path</tt> may be {@link ComponentPath#isAbsolute absolute} or
0814:             * {@link ComponentPath#isRelative relative} but in the latter case
0815:             * parameter <tt>parentContainer</tt> must not be null. <BR>
0816:             * If the path {@link CategoryManager#containsCategory contains categories}
0817:             * the category-tokens get replaced using the category map found in the
0818:             * given calldata instance. Note that this may result in a significant
0819:             * performance loss because for every category-token found we have to call
0820:             * {@link #componentExists} maybe multiple times. Hereby the number of calls
0821:             * depends on the number of fallbacks the category defines and which of
0822:             * those values does actually exist. <BR>
0823:             * The lookup of any component should be performed in the following order:
0824:             * <OL>
0825:             * <LI>if the {@link #getClone clone-map} contains an entry for this path
0826:             * return it. Note that any clone gets stored using its absolute path as
0827:             * key.
0828:             * <LI>if the component exists within this manager return it either from
0829:             * cache or {@link #loadRawComponent load} it from the database. If the
0830:             * component gets loaded {@link Component#postCreate} have to be called.
0831:             * <LI>else ask the parent manager to retrieve the component
0832:             * </OL>
0833:             * If the component was loaded or found in a cache and parameter
0834:             * <tt>followLinks</tt> is true and the component is an instance of
0835:             * {@link ComponentLink} the target of the link must be returned instead of
0836:             * the component.
0837:             * 
0838:             * @param path
0839:             *            the path of the component to return, may be relative or
0840:             *            absolute
0841:             * @param parentContainer
0842:             *            the parent container of the component to return, is only
0843:             *            necessary of path is relative.
0844:             * @param callData
0845:             *            CallData instance of this call
0846:             * @param followLinks
0847:             *            if true return target of {@link ComponentLink links} instead
0848:             *            of link itself.
0849:             * @exception ComponentNotFoundException
0850:             *                if the component does not exist in this manager nor in any
0851:             *                parent manager.
0852:             * @exception ComponentCreationException
0853:             *                if anything goes wrong during initialization of the
0854:             *                component, for example if {@link Component#postCreate}
0855:             *                throws an exception.
0856:             * @see LRUMapComponentManager for an implementation using a cache.
0857:             */
0858:            Component retrieveComponent(ComponentPath path,
0859:                    Container parentContainer, CallData callData,
0860:                    boolean followLinks) throws ComponentNotFoundException,
0861:                    ComponentCreationException {
0862:                final boolean debugEnabled = log.isDebugEnabled();
0863:                Component component = null;
0864:
0865:                // First check if there is a clone for the requested component
0866:                if (path.isAbsolute()) {
0867:                    if (isRootPath(path)) {
0868:                        return getRootComponent();
0869:                    }
0870:                    component = getClone(path);
0871:                } else {
0872:                    if (parentContainer == null) {
0873:                        throw new ComponentNotFoundException(
0874:                                ContelligentExceptionID.component_notFound_relativePathWithoutParent,
0875:                                path);
0876:                    }
0877:                    final ComponentContextImpl parentCtx = (ComponentContextImpl) parentContainer
0878:                            .getComponentContext();
0879:                    path = parentCtx.getPath().append(path);
0880:                    component = getClone(path);
0881:                }
0882:
0883:                if (component != null) {
0884:                    // A removed clone means that there is nothing to see here for
0885:                    // this transaction
0886:                    if (component.getComponentContext().isRemoved()) {
0887:                        if (debugEnabled)
0888:                            log
0889:                                    .debug("Clone for "
0890:                                            + component.getComponentContext()
0891:                                                    .getPath()
0892:                                            + " was flagged as removed, throwing an exception.");
0893:                        throw new ComponentNotFoundException(path);
0894:                    }
0895:                    if (debugEnabled)
0896:                        log
0897:                                .debug("'"
0898:                                        + this .name
0899:                                        + "':retrieveComponent() - returning clone for path '"
0900:                                        + path + "'.");
0901:                } else {
0902:                    CategoryManager categoryManager = contelligent
0903:                            .getCategoryManager();
0904:                    if (categoryManager.containsCategory(path)) {
0905:                        Map categoryMap = null;
0906:                        if (callData == null
0907:                                || (categoryMap = callData.getCategoryMap())
0908:                                        .isEmpty()) {
0909:                            throw new ComponentNotFoundException(path);
0910:                        }
0911:                        path = exchangeCategories(path, categoryMap,
0912:                                categoryManager);
0913:                    }
0914:
0915:                    try {
0916:                        component = loadRawComponent(path, callData);
0917:                        initComponent(component, parentContainer);
0918:                    } catch (TypeException e) {
0919:                        throw new ComponentCreationException(
0920:                                ContelligentExceptionID.component_creation_invalidType,
0921:                                path, e);
0922:                    } catch (ComponentPersistenceException e) {
0923:                        throw new ComponentCreationException(
0924:                                ContelligentExceptionID.component_creation_persistence,
0925:                                path, e);
0926:                    } catch (ComponentNotFoundException e) {
0927:                        if (hasParent()) {
0928:                            return parent.retrieveComponent(path,
0929:                                    parentContainer, callData, followLinks);
0930:                        } else {
0931:                            throw e;
0932:                        }
0933:                    }
0934:                    try {
0935:                        component.postCreate();
0936:                    } catch (Exception e) {
0937:                        log
0938:                                .error(
0939:                                        "'"
0940:                                                + this .name
0941:                                                + "':retrieveComponent() - Exception while calling postCreate() on '"
0942:                                                + component + "': ", e);
0943:                        throw new ComponentCreationException(
0944:                                ContelligentExceptionID.component_creation_persistence,
0945:                                path, e);
0946:                    }
0947:                }
0948:                // followLinks states whether or not to return proxies on ComponentLink
0949:                // interfaced components
0950:                if (followLinks && (component instanceof  ComponentLink)) {
0951:                    component = ((ComponentLink) component).getProxyInstance();
0952:                    if (debugEnabled)
0953:                        log
0954:                                .debug("'"
0955:                                        + this .name
0956:                                        + "':retrieveComponent() - detected link at path '"
0957:                                        + path
0958:                                        + "', returning target componen [="
0959:                                        + component + "] instead.");
0960:                }
0961:                if (debugEnabled) {
0962:                    log.debug("'" + this .name
0963:                            + "':retrieveComponent() - end with " + component
0964:                            + "  of class " + component.getClass().getName());
0965:                }
0966:                return component;
0967:            }
0968:
0969:            final Component loadRawComponent(ComponentPath absolutePath,
0970:                    CallData callData) throws TypeException,
0971:                    ComponentPersistenceException, ComponentNotFoundException {
0972:                final boolean debugEnabled = log.isDebugEnabled();
0973:                ComponentContextImpl ctx = new ComponentContextImpl(this ,
0974:                        absolutePath, contelligent);
0975:                componentAdapter.retrieve(ctx);
0976:                if (debugEnabled)
0977:                    log
0978:                            .debug("'"
0979:                                    + this .name
0980:                                    + "':loadRawComponent() - meta-data for component '"
0981:                                    + absolutePath + "' filled ...");
0982:                if (!isRoot() && ctx.isRemoved()) {
0983:                    if (debugEnabled)
0984:                        log.debug("'" + this .name
0985:                                + "':loadRawComponent() - component '"
0986:                                + absolutePath + "' marked as deleted!");
0987:                    throw new ComponentNotFoundException(absolutePath);
0988:                }
0989:                String typeName = ctx.getTypeName();
0990:                Type type = componentFactory.getType(typeName);
0991:                Map propertyMap = ((ComponentPlaceholder) ctx.getComponent())
0992:                        .getProperties();
0993:                Component component = componentFactory.createInstance(type,
0994:                        propertyMap);
0995:                ctx.setType(type);
0996:                ctx.setComponent(component);
0997:                if (debugEnabled)
0998:                    log
0999:                            .debug("'"
1000:                                    + this .name
1001:                                    + "':loadRawComponent() - successfully loaded component '"
1002:                                    + component + "'.");
1003:                return component;
1004:            }
1005:
1006:            /**
1007:             * Exchange all category tokens with valid values of the corresponding
1008:             * category where a component does exist for in this or any parent manager.
1009:             * This means the returned path does always exist either in this or a parent
1010:             * manager. If no component is found for any catagory value (fallback values
1011:             * are considered) a <code>ComponentNotFoundException</code> is thrown.
1012:             * <BR>
1013:             * Note that this method does NOT check whether path contains categories nor
1014:             * whether categoryMap is emtpy!
1015:             */
1016:            final ComponentPath exchangeCategories(ComponentPath path,
1017:                    Map categoryMap, CategoryManager categoryManager)
1018:                    throws ComponentNotFoundException {
1019:                final boolean debugEnabled = log.isDebugEnabled();
1020:                final String[] pathArray = path.getParsedPath();
1021:                ComponentPath actualPath = ComponentPath.ROOT_PATH
1022:                        .append(pathArray[0]);
1023:                for (int a = 1; a < pathArray.length; a++) {
1024:                    if (!CategoryManager.CATEGORY_TOKEN.equals(pathArray[a])) {
1025:                        actualPath = actualPath.append(pathArray[a]);
1026:                    } else {
1027:                        if (debugEnabled) {
1028:                            log
1029:                                    .debug("'"
1030:                                            + this .name
1031:                                            + "':exchangeCategories() - detected category-token in path '"
1032:                                            + path + "' (element no. " + a
1033:                                            + ") ...");
1034:                        }
1035:                        String categoryName = pathArray[a - 1];
1036:                        Category category = categoryManager
1037:                                .getCategory(categoryName);
1038:                        if (category == null) {
1039:                            throw new ComponentNotFoundException(
1040:                                    ContelligentExceptionID.component_notFound_unknownCategory,
1041:                                    new Object[] { category.getName(),
1042:                                            new Integer(a - 1), path.toPath() });
1043:                        }
1044:                        String value = (String) categoryMap.get(categoryName);
1045:                        boolean found = false;
1046:                        while (value != null
1047:                                && !(found = componentExists(actualPath
1048:                                        .append(value), true))) {
1049:                            value = category.getFallbackValue(value);
1050:                        }
1051:                        if (!found) {
1052:                            log
1053:                                    .error("'"
1054:                                            + this .name
1055:                                            + "':exchangeCategories() - no component found for dir '"
1056:                                            + actualPath + "' and value '"
1057:                                            + value + "' of category '"
1058:                                            + category + "', category-map="
1059:                                            + categoryMap);
1060:                            throw new ComponentNotFoundException(path);
1061:                        }
1062:                        actualPath = actualPath.append(value);
1063:                    }
1064:                }
1065:                if (debugEnabled) {
1066:                    log
1067:                            .debug("'"
1068:                                    + this .name
1069:                                    + "':exchangeCategories() - replaced all categories in path '"
1070:                                    + path + "' => path now '" + actualPath
1071:                                    + "'.");
1072:                }
1073:                return actualPath;
1074:            }
1075:
1076:            /**
1077:             * Implementation of {@link ComponentManager#componentExists(ComponentPath)}.
1078:             * Simply calls {@link #componentExists(ComponentPath, boolean)} with 2nd
1079:             * parameter true.
1080:             */
1081:            final public boolean componentExists(ComponentPath path) {
1082:                return componentExists(path, true);
1083:            }
1084:
1085:            /**
1086:             * Implementation of
1087:             * {@link ComponentManager#componentExists(ComponentPath, boolean)}.
1088:             */
1089:            final public boolean componentExists(ComponentPath path,
1090:                    boolean inHierarchy) {
1091:                try {
1092:                    if (isRootPath(path)) // the root container always exists
1093:                        return true;
1094:
1095:                    if (!isRoot()) {
1096:                        if (checkDeleted(path)) {
1097:                            return false;
1098:                        }
1099:                    }
1100:
1101:                    if (componentAdapter.exists(path.getDir(), path.getName()))
1102:                        return true;
1103:
1104:                    if (hasParent() && inHierarchy) {
1105:                        return getParent().componentExists(path, true);
1106:                    }
1107:                } catch (ComponentPersistenceException e) {
1108:                    log
1109:                            .warn("'"
1110:                                    + this .name
1111:                                    + "':componentExists() - ComponentPersistenceException while checking for existence of component '"
1112:                                    + path + "' (return false): " + e);
1113:                }
1114:                return false;
1115:            }
1116:
1117:            final boolean checkDeleted(ComponentPath path)
1118:                    throws ComponentPersistenceException {
1119:                if (path == null || isRootPath(path)) {
1120:                    return false;
1121:                }
1122:                Component cloneComponent = getClone(path);
1123:                if (cloneComponent != null) {
1124:                    if (cloneComponent.getComponentContext().isRemoved()) {
1125:                        return true;
1126:                    }
1127:                }
1128:                if (componentAdapter.deletedHierarchical(path)) {
1129:                    return true;
1130:                } else {
1131:                    if (hasRecreatedParent(path)
1132:                            && !componentAdapter.exists(path.getDir(), path
1133:                                    .getName())) {
1134:                        return true;
1135:                    } else {
1136:                        return false;
1137:                    }
1138:                }
1139:            }
1140:
1141:            final boolean hasRecreatedParent(ComponentPath path)
1142:                    throws ComponentPersistenceException {
1143:                ComponentPath parentPath = path.parentPath();
1144:
1145:                if (parentPath == null) {
1146:                    return false;
1147:                }
1148:                Component cloneComponent = getClone(path);
1149:                if (cloneComponent != null) {
1150:                    if (cloneComponent.getComponentContext().isRecreated()) {
1151:                        return true;
1152:                    }
1153:                }
1154:                if (componentAdapter.recreatedHierarchical(parentPath)) {
1155:                    return true;
1156:                } else {
1157:                    return false;
1158:                }
1159:            }
1160:
1161:            /**
1162:             * Implementation of {@link ComponentManager#updateComponent}.
1163:             */
1164:            final public void updateComponent(Component component,
1165:                    CallData callData) throws ComponentPersistenceException,
1166:                    NoWritePermissionException, ModificationVetoException,
1167:                    ComponentNotFoundException, ComponentLockException,
1168:                    WouldCreateDeadRelationsException {
1169:                if (callData == null) {
1170:                    log
1171:                            .error("'"
1172:                                    + this .name
1173:                                    + "':updateComponent() - cannot write a component without CallData!");
1174:                    throw new ComponentWriteException(
1175:                            "Cannot write a component without CallData - login first please!");
1176:                }
1177:                final ContelligentPrincipal caller = callData
1178:                        .getContelligentSession().getUser();
1179:                if (!callerHasPermission(caller, callData, component,
1180:                        ComponentPermission.WRITE)) {
1181:                    log.warn("'" + this .name + "':updateComponent() - caller '"
1182:                            + caller + "' has no write access for component '"
1183:                            + component + "'!");
1184:                    throw new NoWritePermissionException(caller, component
1185:                            .getComponentContext().getPath());
1186:                }
1187:                ComponentPath path = component.getComponentContext().getPath();
1188:                boolean locked = lockComponent(path, callData);
1189:
1190:                try {
1191:                    ComponentContextImpl context = (ComponentContextImpl) component
1192:                            .getComponentContext();
1193:                    context.setModifiedBy(caller);
1194:                    if (isRoot() || componentExists(path, false)) {
1195:                        updateWrapper(context);
1196:                    } else {
1197:                        context.setPersistenceManager(this );
1198:                        componentAdapter.create(context);
1199:                    }
1200:                    relationsManager
1201:                            .updateRelations(component, callData, false);
1202:                    checkRelationsOfComponent(path, false, callData);
1203:                    fireChangeEvent(component);
1204:                } finally {
1205:                    if (locked) {
1206:                        componentLockManager.unlockComponent(path, this , false,
1207:                                callData);
1208:                    }
1209:                }
1210:                if ((!isRoot()) && componentExists(path, false)) {
1211:                    componentLockManager.lockComponentShared(path, this ,
1212:                            callData);
1213:                }
1214:            }
1215:
1216:            final void checkAvailableLock(CallData callData,
1217:                    ComponentPath component) throws ComponentLockException {
1218:                componentLockManager.checkAvailableLock(component, callData);
1219:            }
1220:
1221:            /**
1222:             * Implementation of {@link ComponentManager#copyComponentTree}.
1223:             */
1224:            final public Component copyComponentTree(CallData callData,
1225:                    ComponentPath sourcePath, ComponentPath targetParentPath,
1226:                    String toName) throws ComponentNotFoundException,
1227:                    ComponentPersistenceException, ComponentPathException,
1228:                    NoReadPermissionException, NoWritePermissionException,
1229:                    ComponentAlreadyExistsException, ModificationVetoException,
1230:                    ComponentLockException {
1231:                return copyComponentTree(callData, sourcePath,
1232:                        targetParentPath, toName, CopyMode.LINK_FINALS, false);
1233:            }
1234:
1235:            /**
1236:             * Implementation of {@link ComponentManager#copyComponentTree}.
1237:             */
1238:            final public Component copyComponentTree(CallData callData,
1239:                    ComponentPath sourcePath, ComponentPath targetParentPath,
1240:                    String toName, CopyMode mode, boolean cloningCopy)
1241:                    throws ComponentNotFoundException,
1242:                    ComponentPersistenceException, ComponentPathException,
1243:                    NoReadPermissionException, NoWritePermissionException,
1244:                    ComponentAlreadyExistsException, ModificationVetoException,
1245:                    ComponentLockException {
1246:                Component sourceComponent = getComponent(sourcePath, callData,
1247:                        false);
1248:                if (toName == null || toName.length() == 0)
1249:                    toName = sourceComponent.getComponentContext().getPath()
1250:                            .getName();
1251:                ComponentPath targetPath = targetParentPath.append(toName);
1252:
1253:                checkReadOnly(targetPath);
1254:
1255:                final User caller = callData.getContelligentSession().getUser();
1256:
1257:                Component targetParent = getComponent(targetParentPath,
1258:                        callData);
1259:                if (!(targetParent instanceof  Container)
1260:                        || (targetParent instanceof  ComponentLink)) {
1261:                    log
1262:                            .warn("'"
1263:                                    + this .name
1264:                                    + "':copyComponentTree() - could not write component to path'"
1265:                                    + targetPath + "' because '"
1266:                                    + targetParentPath
1267:                                    + "' is no container or a link-component!");
1268:                    throw new ComponentWriteException(
1269:                            ContelligentExceptionID.component_noContainer,
1270:                            new Object[] { targetPath.toPath() });
1271:                }
1272:                // check for self-copy:
1273:                if (targetPath.isSubPathOf(sourcePath)
1274:                        || targetPath.equals(sourcePath)
1275:                        || sourcePath.isSubPathOf(targetPath)) {
1276:                    log
1277:                            .warn("'"
1278:                                    + this .name
1279:                                    + "':copyComponentTree() - cannot copy a component '"
1280:                                    + sourceComponent
1281:                                    + "' on itself! Use writeComponent() for this task!");
1282:                    throw new ComponentWriteException(
1283:                            ContelligentExceptionID.component_moveBeneathItself,
1284:                            new Object[] { sourceComponent
1285:                                    .getComponentContext().getPath().toPath() });
1286:                }
1287:                // check write permission for target-path:
1288:                if (!callerHasPermission(caller, callData, targetParent,
1289:                        ComponentPermission.WRITE)) {
1290:                    log.warn("'" + this .name
1291:                            + "':copyComponentTree() - caller '" + caller
1292:                            + "' has no write access for component '"
1293:                            + targetParent + "'!");
1294:                    throw new NoWritePermissionException(caller, targetParent
1295:                            .getComponentContext().getPath());
1296:                }
1297:
1298:                if (componentExists(targetPath)) {
1299:                    log.warn("Could not copy component '" + sourceComponent
1300:                            + "' because target-path '" + targetPath
1301:                            + "' already exists!");
1302:                    throw new ComponentAlreadyExistsException(targetPath);
1303:                }
1304:
1305:                if (!callerHasPermissionForTree(callData, caller,
1306:                        sourceComponent, ComponentPermission.READ)) {
1307:                    log
1308:                            .warn("'"
1309:                                    + this .name
1310:                                    + "':copyComponentTree() - caller has no read access for component-tree '"
1311:                                    + sourcePath + "'!");
1312:                    throw new NoReadPermissionException(caller, sourcePath);
1313:                }
1314:
1315:                boolean locked = lockComponent(targetPath, callData);
1316:                // now (recursivly) copy the whole tree:
1317:                try {
1318:                    Component target = copyComponentTree(
1319:                            (Container) targetParent, caller, callData,
1320:                            sourceComponent, toName, mode);
1321:                    if (target != null) {
1322:                        fireAddEvent((Container) targetParent, target);
1323:                    }
1324:
1325:                    if (cloningCopy) {
1326:
1327:                        // Change internal references within the copied tree to point
1328:                        // to the same relative location within the new copy.
1329:                        // Note that we cant ask the RelationsManager for the relations
1330:                        // of our new copy before the transaction is committed, so we
1331:                        // have to grab the relation sources from the source tree and
1332:                        // calculate their respective positions within the copy.
1333:
1334:                        Set lockedComponents = new HashSet();
1335:
1336:                        List componentsToUpdate = new LinkedList();
1337:
1338:                        RelationsManagerImpl relationsManager = (RelationsManagerImpl) contelligent
1339:                                .getRelationsManager();
1340:                        Set pathsToUpdate = relationsManager
1341:                                .getTreeRelationSources(sourcePath, this 
1342:                                        .getId());
1343:                        Iterator sourcesFromTree = pathsToUpdate.iterator();
1344:                        while (sourcesFromTree.hasNext()) {
1345:                            ComponentPath path = (ComponentPath) sourcesFromTree
1346:                                    .next();
1347:                            if (sourcePath.equals(path)
1348:                                    || path.isSubPathOf(sourcePath)) {
1349:                                if (path.equals(sourcePath)) {
1350:                                    path = targetPath;
1351:                                } else {
1352:                                    path = path.exchangeParent(sourcePath,
1353:                                            targetPath);
1354:                                }
1355:                                Component component = cloneComponent(path,
1356:                                        callData);
1357:                                log.info("'" + this .name
1358:                                        + "':moveComponentTree() - informing '"
1359:                                        + component + "' about move of '"
1360:                                        + sourcePath + "' to '" + targetPath
1361:                                        + "' ... (component was copied)");
1362:                                try {
1363:                                    relationsManager.updateRelationsForMove(
1364:                                            component, sourcePath, targetPath);
1365:                                    updateComponent(component, callData);
1366:                                } catch (ContelligentException ce) {
1367:                                    throw new ComponentPersistenceException(ce);
1368:                                }
1369:                            }
1370:                        }
1371:                    }
1372:
1373:                    return target;
1374:                } finally {
1375:                    if (!isRoot()) {
1376:                        componentLockManager.lockComponentShared(targetPath,
1377:                                this , callData);
1378:                    }
1379:                    if (locked) {
1380:                        unlockComponent(targetPath, callData);
1381:                    }
1382:                }
1383:            }
1384:
1385:            /**
1386:             * Implementation of
1387:             * {@link ComponentManager#cloneComponent(ComponentPath, CallData)}.
1388:             */
1389:            final public Component cloneComponent(ComponentPath path,
1390:                    CallData callData) throws ComponentNotFoundException,
1391:                    ComponentCreationException {
1392:                if (isRootPath(path))
1393:                    return getRootComponent();
1394:
1395:                Component component = getClone(path);
1396:                if (component != null) {
1397:                    if (log.isDebugEnabled()) {
1398:                        log
1399:                                .debug("'"
1400:                                        + this .name
1401:                                        + "':cloneComponent() - returning already cloned component '"
1402:                                        + component + "'.");
1403:                    }
1404:                    return component;
1405:                }
1406:                if (contelligent.getCategoryManager().containsCategory(path)) {
1407:                    throw new ComponentCreationException(
1408:                            ContelligentExceptionID.component_creation_clone,
1409:                            path);
1410:                }
1411:                return cloneComponent(getComponent(path, callData, false)); // don't
1412:                // follow
1413:                // links
1414:            }
1415:
1416:            /**
1417:             * Implementation of {@link ComponentManager#cloneComponent(Component)}.
1418:             */
1419:            final public Component cloneComponent(Component component)
1420:                    throws ComponentCreationException {
1421:                final ComponentContextImpl orgCtx = (ComponentContextImpl) component
1422:                        .getComponentContext();
1423:                final ComponentPath path = orgCtx.getPath();
1424:                if (isRootPath(path))
1425:                    return getRootComponent();
1426:
1427:                Component clonedComponent = getClone(path);
1428:                if (clonedComponent != null) {
1429:                    if (log.isDebugEnabled()) {
1430:                        log
1431:                                .debug("'"
1432:                                        + this .name
1433:                                        + "':cloneComponent() - returning already cloned component '"
1434:                                        + clonedComponent + "'.");
1435:                    }
1436:                    return clonedComponent;
1437:                }
1438:                ComponentContextImpl clonedCtx = (ComponentContextImpl) orgCtx
1439:                        .clone();
1440:                Type type = orgCtx.getType();
1441:                try {
1442:                    clonedComponent = componentFactory.createRawInstance(type); // throws
1443:                    // TypeException
1444:                    type.setProperties(clonedComponent, type.getProperties(
1445:                            component, false));
1446:                    clonedCtx.setComponent(clonedComponent);
1447:                    clonedComponent.postCreate();
1448:                    addClone(path, clonedComponent);
1449:                    if (log.isDebugEnabled()) {
1450:                        log
1451:                                .debug("'"
1452:                                        + this .name
1453:                                        + "':cloneComponent() - ... successfully cloned and initialized component '"
1454:                                        + clonedComponent + "'.");
1455:                    }
1456:                    return clonedComponent;
1457:                } catch (TypeException e) { // should never occur since we clone an already existing type !!
1458:                    log
1459:                            .error("'"
1460:                                    + this .name
1461:                                    + "':cloneComponent() - Exception while creating instance of type '"
1462:                                    + type + "': " + e);
1463:                    throw new ComponentCreationException(
1464:                            ContelligentExceptionID.component_creation_invalidType,
1465:                            path, e);
1466:                } catch (Exception e) {
1467:                    log
1468:                            .error(
1469:                                    "'"
1470:                                            + this .name
1471:                                            + "':cloneComponent() - Exception while calling postCreate() on '"
1472:                                            + clonedComponent + "': ", e);
1473:                    throw new ComponentCreationException(
1474:                            ContelligentExceptionID.component_creation_persistence,
1475:                            path, e);
1476:                }
1477:            }
1478:
1479:            /**
1480:             * Returns a newly created (yet not persistent!) component instance using
1481:             * the specified type, name, acl and property-map. Note that
1482:             * {@link #initComponent} gets called before returning the instance but NOT
1483:             * {@link Component#postCreate} ! The calling method must invoke
1484:             * {@link Component#postCreate} before any client code may access the
1485:             * component! <BR>
1486:             * If parameter <tt>propertyMap</tt> is non-null the instance gets those
1487:             * properties set. A property may be overwritten only if the type does not
1488:             * define that property as final. The map must contain either
1489:             * (String,String) or (String,Double) entries.
1490:             * 
1491:             * @exception TypeException
1492:             *                if the type is unknown
1493:             * @exception ComponentCreationException
1494:             *                if the component could not be created
1495:             * @exception ComponentPathException
1496:             *                if the name contains invalid characters
1497:             * @see Type#setProperties
1498:             */
1499:            final Component newInstanceFromType(Container parent, String name,
1500:                    String typeName, AccessControlList acl, Map propertyMap,
1501:                    ComponentContextImpl orgCtx) throws TypeException,
1502:                    ComponentCreationException, ComponentPathException {
1503:                final ComponentPath path = parent.getComponentContext()
1504:                        .getPath().append(name);
1505:                if (log.isDebugEnabled()) {
1506:                    log.debug("'" + this .name
1507:                            + "':newInstanceFromType() - creating component '"
1508:                            + path + "' with type '" + typeName + "' ...");
1509:                }
1510:                Type type = componentFactory.getType(typeName);
1511:                Component rawInstance = componentFactory.createInstance(type,
1512:                        propertyMap);
1513:
1514:                ComponentContextImpl ctx = (orgCtx == null) ? new ComponentContextImpl(
1515:                        this , path, contelligent)
1516:                        : orgCtx.clone(this , path);
1517:                ctx.setType(type);
1518:                ctx.setTypeName(type.getName());
1519:                ctx.setACL(acl);
1520:                ctx.setComponent(rawInstance);
1521:                ctx.setLastModified(TimeService.getInstance()
1522:                        .currentTimeMillis());
1523:                initComponent(rawInstance, parent);
1524:                return rawInstance;
1525:            }
1526:
1527:            /**
1528:             * Implementation of {@link ComponentManager#createLink}.
1529:             */
1530:            final public ComponentLink createLink(Component linkTarget,
1531:                    Container parent, String name, AccessControlList acl,
1532:                    CallData callData) throws ComponentPersistenceException,
1533:                    ComponentCreationException, ModificationVetoException,
1534:                    ComponentPathException, ComponentLockException,
1535:                    ComponentAlreadyExistsException {
1536:                // XXX: prevent creating a link on a link?
1537:                try {
1538:                    Map propertyMap = new HashMap(2);
1539:                    propertyMap.put(DEFAULT_LINK_TYPE_PATH_PROPERTY, linkTarget
1540:                            .getComponentContext().getPath().toString());
1541:                    return (ComponentLink) createComponent(parent, name,
1542:                            DEFAULT_LINK_TYPE, propertyMap, acl, callData);
1543:                } catch (TypeException e) {
1544:                    // this exception should never occure in a properly configured system:
1545:                    log
1546:                            .fatal("'"
1547:                                    + this .name
1548:                                    + "':createLink() - internal error: TypeException using default link type '"
1549:                                    + DEFAULT_LINK_TYPE + "'!");
1550:                    throw new ComponentCreationException(
1551:                            ContelligentExceptionID.component_creation_invalidType,
1552:                            parent.getComponentContext().getPath().append(name));
1553:                }
1554:            }
1555:
1556:            /**
1557:             * Implementation of {@link ComponentManager#createComponent}.
1558:             */
1559:            final public Component createComponent(Container parent,
1560:                    String name, String typeName, Map propertyMap,
1561:                    AccessControlList acl, CallData callData)
1562:                    throws TypeException, ComponentPersistenceException,
1563:                    ComponentCreationException, ModificationVetoException,
1564:                    ComponentPathException, ComponentLockException,
1565:                    ComponentAlreadyExistsException {
1566:                Type type = componentFactory.getType(typeName); // throws UnknownTypeException
1567:                Map properties = null;
1568:
1569:                if (propertyMap != null && propertyMap.size() > 0) {
1570:                    // given property map contains (String,String) entries only, convert
1571:                    // it into (String,String) or (String,Double) entries depending on
1572:                    // property-type.
1573:                    properties = type.getProperties(propertyMap, false);
1574:                }
1575:                return createComponent(parent, name, type, properties, acl,
1576:                        true, true, callData);
1577:            }
1578:
1579:            // propertyMap expected to contain (String,String) or (String,Double) like
1580:            // Type.getProperties returns!
1581:            final protected Component createComponent(Container parent,
1582:                    String name, Type type, Map propertyMap,
1583:                    AccessControlList acl, boolean postCreate,
1584:                    boolean updateRelations, CallData callData)
1585:                    throws TypeException, ComponentPersistenceException,
1586:                    ComponentCreationException, ModificationVetoException,
1587:                    ComponentPathException, ComponentLockException,
1588:                    ComponentAlreadyExistsException {
1589:                final ComponentPath path = parent.getComponentContext()
1590:                        .getPath().append(name);
1591:                final boolean debugEnabled = log.isDebugEnabled();
1592:
1593:                checkReadOnly(path);
1594:
1595:                boolean locked = lockComponent(path, callData);
1596:                try {
1597:                    // is this a blueprint instantiation (mere copy) or a real creation?
1598:                    if (!isImport() && type.isBlueprint()
1599:                            && !path.equals(type.getBlueprintPath())) {
1600:                        if (debugEnabled) {
1601:                            log.debug("createComponent() - copying blueprint "
1602:                                    + type.getBlueprintPath()
1603:                                    + " for component " + name);
1604:                        }
1605:                        try {
1606:                            Component newInstance = copyComponentTree(callData,
1607:                                    type.getBlueprintPath(), parent
1608:                                            .getComponentContext().getPath(),
1609:                                    name, CopyMode.BLUEPRINT, false);
1610:                            // assert: newInstance is a new clone
1611:                            ComponentContextImpl context = (ComponentContextImpl) newInstance
1612:                                    .getComponentContext();
1613:                            context.setType(type);
1614:                            context.setTypeName(type.getName());
1615:                            context.setModifiedBy(callData
1616:                                    .getContelligentSession().getUser());
1617:                            updateWrapper(context);
1618:                            return newInstance;
1619:                        } catch (ComponentNotFoundException cnfe) {
1620:                            throw new TypeException(
1621:                                    ContelligentExceptionID.type_missingBlueprint,
1622:                                    new Object[] { type.getName() });
1623:                        }
1624:                    } else {
1625:                        User caller = callData.getContelligentSession()
1626:                                .getUser();
1627:                        if (!callerHasPermission(caller, callData, parent,
1628:                                ComponentPermission.WRITE)) {
1629:                            log.warn("'" + this .name
1630:                                    + "':createComponent() - caller '" + caller
1631:                                    + "' has no write access for component '"
1632:                                    + parent + "'!");
1633:                            throw new NoWritePermissionException(caller, parent
1634:                                    .getComponentContext().getPath());
1635:                        }
1636:
1637:                        if (debugEnabled) {
1638:                            log
1639:                                    .debug("'"
1640:                                            + this .name
1641:                                            + "':createComponent() - trying to create component '"
1642:                                            + path + "' with type '"
1643:                                            + type.getName() + "' ...");
1644:                        }
1645:
1646:                        if ((componentExists(path))
1647:                                && (!componentAdapter.deleted(path))) {
1648:                            log
1649:                                    .error("'"
1650:                                            + this .name
1651:                                            + "':createComponent() - component with path '"
1652:                                            + path + "' already exists");
1653:                            throw new ComponentAlreadyExistsException(path);
1654:                        }
1655:
1656:                        if (acl == null) {
1657:                            Set ownerSet = new HashSet(1);
1658:                            ownerSet.add(caller);
1659:                            acl = new AccessControlList(path.toString(),
1660:                                    ownerSet);
1661:                        }
1662:
1663:                        Component newInstance = newInstanceFromType(parent,
1664:                                name, type.getName(), acl, propertyMap, null);
1665:                        ComponentContextImpl context = (ComponentContextImpl) newInstance
1666:                                .getComponentContext();
1667:                        context.setModifiedBy(caller);
1668:                        if (componentAdapter.deleted(context.getPath())) {
1669:                            log
1670:                                    .debug("'"
1671:                                            + this .name
1672:                                            + "':createComponent() - detected creation of deleted component '"
1673:                                            + context.getPath() + "' ...");
1674:                            Component clone = getClone(context.getPath());
1675:                            if (clone != null) { // we must use last-modified of
1676:                                // clone so DB may check for
1677:                                // concurrent modification
1678:                                context.setLastModified(clone
1679:                                        .getComponentContext()
1680:                                        .getLastModified());
1681:                            } else {
1682:                                context.setLastModified(componentAdapter
1683:                                        .getLastModified(context));
1684:                            }
1685:                            updateWrapper(context);
1686:                            // to make queries for subcomponent names work in this
1687:                            // transaction we have to set the state here
1688:                            context
1689:                                    .setStatus(ComponentPersistenceAdapter.RECREATED);
1690:                        } else {
1691:                            componentAdapter.create(context);
1692:                        }
1693:
1694:                        if (updateRelations) {
1695:                            relationsManager.updateRelations(newInstance,
1696:                                    callData, false);
1697:                        }
1698:                        try {
1699:                            if (postCreate) {
1700:                                newInstance.postCreate();
1701:                                fireAddEvent(parent, newInstance);
1702:                            }
1703:                            addClone(path, newInstance);
1704:                        } catch (ComponentLockException e) {
1705:                            throw e;
1706:                        } catch (Exception e) {
1707:                            log
1708:                                    .error(
1709:                                            "'"
1710:                                                    + this .name
1711:                                                    + "':createComponent() - Exception while calling postCreate() on '"
1712:                                                    + newInstance + "': ", e);
1713:                            throw new ComponentCreationException(
1714:                                    ContelligentExceptionID.component_creation_persistence,
1715:                                    path, e);
1716:                        }
1717:
1718:                        return newInstance;
1719:                    }
1720:                } finally {
1721:                    if (!isRoot()) {
1722:                        componentLockManager.lockComponentShared(path, this ,
1723:                                callData);
1724:                    }
1725:                    if (locked) {
1726:                        unlockComponent(path, callData);
1727:                    }
1728:                }
1729:            }
1730:
1731:            /**
1732:             * Implementation of {@link ComponentManager#deleteComponentTree}.
1733:             */
1734:            final public void deleteComponentTree(CallData callData,
1735:                    ComponentPath path) throws ContelligentException,
1736:                    NoDeletePermissionException, ModificationVetoException,
1737:                    RelationExistsException, ComponentLockException {
1738:                deleteComponentTree(path, callData, true, true, true);
1739:            }
1740:
1741:            final void deleteComponentTree(ComponentPath path,
1742:                    CallData callData, boolean removeRelations,
1743:                    boolean checkRelations, boolean checkLinkContext)
1744:                    throws ContelligentException, NoDeletePermissionException,
1745:                    ModificationVetoException, RelationExistsException,
1746:                    ComponentLockException {
1747:                deleteComponentTree(path, callData, removeRelations,
1748:                        checkRelations, checkLinkContext, false);
1749:            }
1750:
1751:            final void deleteComponentTree(ComponentPath path,
1752:                    CallData callData, boolean removeRelations,
1753:                    boolean checkRelations, boolean checkLinkContext,
1754:                    boolean committingDelete) throws ContelligentException,
1755:                    NoDeletePermissionException, ModificationVetoException,
1756:                    RelationExistsException, ComponentLockException {
1757:
1758:                if (isRootPath(path)) {
1759:                    log
1760:                            .warn("'"
1761:                                    + this .name
1762:                                    + "':deleteComponentTree() - the root container cannot be deleted!");
1763:                    return;
1764:                }
1765:                if (!componentExists(path)) {
1766:                    if (log.isDebugEnabled())
1767:                        log.debug("'" + this .name
1768:                                + "':deleteComponentTree() - component '"
1769:                                + path + "' does not exists!");
1770:                    return;
1771:                }
1772:
1773:                checkContainsReadOnly(path);
1774:
1775:                boolean locked = false;
1776:                if (!committingDelete) {
1777:                    // Committing a subtree must be able to bypass these checks, since
1778:                    // in that case (and only in that case) deletes in Production must be
1779:                    // possible despite of shared locks. This is because the matching
1780:                    // shared lock is guaranteed to be in the context we are committing
1781:                    // right now.
1782:                    locked = lockComponentForDelete(path, callData,
1783:                            checkLinkContext);
1784:                }
1785:                try {
1786:                    Component toRemove = getComponent(path, callData, false); // don't follow links;
1787:                    final ContelligentPrincipal caller = callData
1788:                            .getContelligentSession().getUser();
1789:                    if (!callerHasPermissionForTree(callData, caller, toRemove,
1790:                            ComponentPermission.DELETE)) {
1791:                        log
1792:                                .warn("'"
1793:                                        + this .name
1794:                                        + "':deleteComponentTree() - caller has no right to delete component-tree '"
1795:                                        + path + "'!");
1796:                        throw new NoDeletePermissionException(caller, path);
1797:                    }
1798:
1799:                    if (isRoot()) {
1800:                        componentLockManager.removeLocksForComponentTree(path);
1801:                        componentAdapter.delete(path, true, false);
1802:                    } else {
1803:                        if (!getParent().componentExists(path)) {
1804:                            // component was created in this component manager
1805:                            componentLockManager
1806:                                    .removeLocksForComponentTree(path);
1807:                            componentAdapter.delete(path, true, false);
1808:                        } else {
1809:                            ComponentContextImpl ctx = (ComponentContextImpl) toRemove
1810:                                    .getComponentContext();
1811:                            if (ctx.getPersistenceManager().getId() != this 
1812:                                    .getId()) {
1813:                                log
1814:                                        .debug("Component does not originate in this manager, cloning it.");
1815:                                try {
1816:                                    Component clonedComp = cloneForManager(
1817:                                            path, this , callData);
1818:                                    addClone(path, clonedComp);
1819:                                    ctx = (ComponentContextImpl) clonedComp
1820:                                            .getComponentContext();
1821:                                } catch (Exception e) {
1822:                                    log.error("cloneForManager failed.");
1823:                                    throw new ContelligentException(
1824:                                            "cloneForManager failed: ", e);
1825:                                }
1826:                            }
1827:                            ctx.setRemoved();
1828:                            ctx.setModifiedBy(caller);
1829:                            componentAdapter.delete(path, true, true);
1830:                            if (componentAdapter.exists(path.getDir(), path
1831:                                    .getName())) {
1832:                                if (!componentAdapter.deleted(path)) {
1833:                                    updateWrapper(ctx);
1834:                                }
1835:                            } else {
1836:                                componentAdapter.create(ctx);
1837:                            }
1838:                        }
1839:                    }
1840:                    // Make sure any clones in the deleted tree also get properly
1841:                    // flagged as deleted (important for later lookups within this
1842:                    // transaction)
1843:                    Map map = (Map) cloneMap.get();
1844:                    if (map != null) {
1845:                        Iterator it = map.values().iterator();
1846:                        while (it.hasNext()) {
1847:                            ComponentContextImpl currentCtx = (ComponentContextImpl) ((Component) it
1848:                                    .next()).getComponentContext();
1849:                            if (currentCtx.getPath().isSubPathOf(path)
1850:                                    || currentCtx.getPath().equals(path)) {
1851:                                currentCtx.setRemoved();
1852:                            }
1853:                        }
1854:                    }
1855:                    // RELATION
1856:                    if (removeRelations)
1857:                        relationsManager.removeRelationsOfTree(path, this 
1858:                                .getId());
1859:                    if (callData.shouldCheckRelations()) {
1860:                        if (checkRelations && !deadRelationsCheckDisabled) {
1861:                            Map relationsMap = relationsManager
1862:                                    .getGlobalPathsRelatedToTree(path, false,
1863:                                            this .getId());
1864:                            if (!isRoot()) { // we must check if the remaining paths aren't deleted in this manager!
1865:                                long parentId = parent.getId();
1866:                                Iterator entries = relationsMap.entrySet()
1867:                                        .iterator();
1868:                                while (entries.hasNext()) {
1869:                                    Map.Entry entry = (Map.Entry) entries
1870:                                            .next();
1871:                                    String targetPath = (String) entry.getKey();
1872:                                    Set relatedPathSet = (Set) entry.getValue();
1873:                                    Iterator relatedPaths = relatedPathSet
1874:                                            .iterator();
1875:                                    while (relatedPaths.hasNext()) {
1876:                                        GlobalComponentPath relatedPath = (GlobalComponentPath) relatedPaths
1877:                                                .next();
1878:                                        if ((relatedPath
1879:                                                .getPersistenceManagerId() == parentId)
1880:                                                && (componentAdapter
1881:                                                        .deletedHierarchical(relatedPath) || componentAdapter
1882:                                                        .exists(
1883:                                                                relatedPath
1884:                                                                        .getDir(),
1885:                                                                relatedPath
1886:                                                                        .getName()))) {
1887:                                            relatedPaths.remove();
1888:                                        }
1889:                                    }
1890:                                    if (relatedPathSet.isEmpty())
1891:                                        entries.remove();
1892:                                }
1893:                            }
1894:                            if (!relationsMap.isEmpty()) {
1895:                                // we must mark for rollback because the deletion
1896:                                // already happened in the db!
1897:                                callData.markForRollback();
1898:                                throw new WouldCreateDeadRelationsException(
1899:                                        path, relationsMap);
1900:                            }
1901:                        }
1902:                    }
1903:                    Container parent = parentContainer(toRemove);
1904:                    fireDeleteEvent(parent, toRemove, committingDelete);
1905:                } catch (ComponentNotFoundException e) {
1906:                    log
1907:                            .warn("'"
1908:                                    + this .name
1909:                                    + "':deleteComponentTree() - ComponentNotFoundException while fetching component '"
1910:                                    + path
1911:                                    + "' to removeType although componentExists() returned true right before! (ignored): "
1912:                                    + e);
1913:                } finally {
1914:                    if (!isRoot()) {
1915:                        componentLockManager.lockComponentShared(path, this ,
1916:                                callData);
1917:                    }
1918:                    if (locked) {
1919:                        unlockComponent(path, callData);
1920:                    }
1921:                }
1922:            }
1923:
1924:            final public int getSubcomponentCount(Container container) {
1925:                if (isRoot()) {
1926:                    return componentAdapter.getSubcomponentCount(container
1927:                            .getComponentContext().getPath());
1928:                } else {
1929:                    return getSubcomponentNames(container).size();
1930:                }
1931:            }
1932:
1933:            /**
1934:             * Implementation of {@link ComponentManager#getSubcomponentNames}.
1935:             */
1936:            final public Set getSubcomponentNames(Container container) {
1937:                long[] ids;
1938:
1939:                if (container.getComponentContext().isRecreated()) {
1940:                    ids = new long[] { getId() };
1941:                } else {
1942:                    ids = getIdsUpToRoot();
1943:                }
1944:                try {
1945:                    return componentAdapter.getSubComponentNames(container
1946:                            .getComponentContext().getPath(), ids);
1947:                } catch (ComponentPersistenceException e) {
1948:                    log
1949:                            .error(
1950:                                    "'"
1951:                                            + this .name
1952:                                            + "':getSubcomponentNames() - Exception while retrieving subcomponent-names for container '"
1953:                                            + container + "': ", e);
1954:                    return Collections.EMPTY_SET;
1955:                }
1956:            }
1957:
1958:            final public Iterator getSubcomponentNames(Container container,
1959:                    int start, int amount) {
1960:                return getSubcomponentNames(container).iterator();
1961:            }
1962:
1963:            // final public Iterator getSubcomponentNames(Container container, int
1964:            // start, int amount, SortKeyHolder sortKeyHolder) {
1965:            // return getSubcomponentNames(container).iterator();
1966:            // }
1967:
1968:            public String toString() {
1969:                return ("[BasicComponentManager '" + name + "']");
1970:            }
1971:
1972:            final protected boolean hasParent() {
1973:                return getParent() != null;
1974:            }
1975:
1976:            // ==============================================================================
1977:            // non-public methods
1978:            // ==============================================================================
1979:
1980:            /**
1981:             * Creates the root component for the ComponentManager. This is a hardcoded
1982:             * folder component that is not stored in the database.
1983:             */
1984:            final Container createRootContainer() throws Exception {
1985:                Container rootContainer = new Folder();
1986:                ComponentContextImpl ctx = new ComponentContextImpl(this ,
1987:                        ComponentPath.ROOT_PATH, contelligent);
1988:                TypeImpl rootType = new TypeImpl(-1, ROOT_TYPENAME,
1989:                        ROOT_TYPEGROUP, DEFAULT_FOLDER_TYPE, null,
1990:                        Collections.EMPTY_MAP, Collections.EMPTY_MAP,
1991:                        Folder.class.getName(), false, null);
1992:                ctx.setType(rootType);
1993:                ctx.setTypeName(rootType.getName());
1994:                ctx.setInheritSecurity(false);
1995:                ctx.setACL(rootACL);
1996:                ctx.setComponent(rootContainer);
1997:                ctx.setModifiedBy(ContelligentSecurityManager.getSystemUser());
1998:                ctx.setLastModified(TimeService.getInstance()
1999:                        .currentTimeMillis());
2000:                initComponent(rootContainer, null);
2001:                rootContainer.postCreate();
2002:                return rootContainer;
2003:            }
2004:
2005:            final private AccessControlList createRootACL(
2006:                    ACLElement rootACLElement) throws ContelligentException {
2007:                AccessControlList acl = null;
2008:                try {
2009:                    acl = ComponentImport.createACLfromXML("root",
2010:                            rootACLElement, this );
2011:                } catch (ContelligentException e) {
2012:                    log
2013:                            .error("'"
2014:                                    + this .name
2015:                                    + "':createRootACL() - ContelligentException: "
2016:                                    + e);
2017:                    log.info("'" + this .name
2018:                            + "':createRootACL() - ... using default ACL ...");
2019:                    User defaultOwner = getDefaultOwner();
2020:                    AclEntry readAccess = new ComponentAccess(defaultOwner,
2021:                            ComponentPermission.READ, -1, -1, -1, -1);
2022:                    AclEntry writeAccess = new ComponentAccess(defaultOwner,
2023:                            ComponentPermission.WRITE, -1, -1, -1, -1);
2024:                    AclEntry deleteAccess = new ComponentAccess(defaultOwner,
2025:                            ComponentPermission.DELETE, -1, -1, -1, -1);
2026:                    acl = new AccessControlList("ROOT", defaultOwner);
2027:                    acl.addEntry(defaultOwner, readAccess);
2028:                    acl.addEntry(defaultOwner, writeAccess);
2029:                    acl.addEntry(defaultOwner, deleteAccess);
2030:                }
2031:                if (log.isDebugEnabled()) {
2032:                    log.debug("'" + this .name
2033:                            + "':createRootACL() - created acl '" + acl + "'.");
2034:                }
2035:                return acl;
2036:            }
2037:
2038:            final public boolean isRootPath(String path) {
2039:                return (path.length() == 0 || String.valueOf(
2040:                        ComponentPath.SEPARATOR).equals(path));
2041:            }
2042:
2043:            final public boolean isRootPath(ComponentPath path) {
2044:                return (ComponentPath.ROOT_PATH.equals(path));
2045:            }
2046:
2047:            final public ComponentPath getRootPath() {
2048:                return ComponentPath.ROOT_PATH;
2049:            }
2050:
2051:            /**
2052:             * Returns the user principal representing the default owner of this
2053:             * component-manager. This user gets used whenever no caller is available,
2054:             * for example when initially importing components.
2055:             * 
2056:             * @return a <code>User</code> value
2057:             */
2058:            final public User getDefaultOwner() throws ContelligentException {
2059:                return defaultOwner;
2060:            }
2061:
2062:            /**
2063:             * Recursivly copies the component-tree starting with the given
2064:             * {@link Component} to the specified dir without checking any permissions
2065:             * nor asking the target container if its an {@link ObservingContainer}.
2066:             * <BR>
2067:             * Depending on parameter <tt>mode</tt> the copying of
2068:             * {@link de.finix.contelligent.ComponentContext#isFinal} components varies:
2069:             * <UL>
2070:             * <LI> {@link CopyMode#NO_FINALS} - the copy process is interrupted and
2071:             * null returned.
2072:             * <LI> {@link CopyMode#LINK_FINALS} - a link gets created for the final
2073:             * component.
2074:             * <LI> {@link CopyMode#ALL} - everything gets copied.
2075:             * <LI> {@link CopyMode#ALL_ACLS} - everything gets copied and defined ACLs
2076:             * are replicated on the copy.
2077:             * </UL>
2078:             * 
2079:             * @return the root of the copied component tree or null if nothing was
2080:             *         copied.
2081:             */
2082:            final Component copyComponentTree(Container targetParent,
2083:                    User caller, CallData callData, Component source,
2084:                    String toName, CopyMode mode) throws TypeException,
2085:                    ComponentCreationException, ComponentPathException,
2086:                    ComponentPersistenceException, ComponentLockException,
2087:                    ModificationVetoException {
2088:                final boolean debugEnabled = log.isDebugEnabled();
2089:
2090:                if (mode == CopyMode.NO_FINALS
2091:                        && source.getComponentContext().isFinal()) {
2092:                    if (debugEnabled) {
2093:                        log
2094:                                .debug("'"
2095:                                        + this .name
2096:                                        + "':copyComponentTree() - ... copy process interrupted (actual target-parent='"
2097:                                        + targetParent + "', child-name='"
2098:                                        + toName + "') because source '"
2099:                                        + source + "' is final and copy-mode="
2100:                                        + mode);
2101:                    }
2102:                    return null;
2103:                }
2104:
2105:                if (debugEnabled) {
2106:                    log.debug("'" + this .name
2107:                            + "':copyComponentTree() - copying source '"
2108:                            + source + "' beneath target-parent '"
2109:                            + targetParent + "' with name '" + toName
2110:                            + "' (copy-mode=" + mode + ") ...");
2111:                }
2112:
2113:                ComponentContextImpl sourceCtx = (ComponentContextImpl) source
2114:                        .getComponentContext();
2115:                String typeName = sourceCtx.getType().getName();
2116:                AccessControlList newACL;
2117:                if (mode == CopyMode.ALL_ACLS) {
2118:                    newACL = sourceCtx.getACL();
2119:                } else {
2120:                    newACL = new AccessControlList("", caller);
2121:                }
2122:
2123:                boolean goDeeper = true;
2124:                boolean fullCopy = true;
2125:                Map propertyMap = null;
2126:
2127:                if ((mode == CopyMode.LINK_FINALS || mode == CopyMode.BLUEPRINT)
2128:                        && sourceCtx.isFinal()) {
2129:                    if (debugEnabled) {
2130:                        log
2131:                                .debug("'"
2132:                                        + this .name
2133:                                        + "':copyComponentTree() - ... copy process interrupted (actual target-parent='"
2134:                                        + targetParent
2135:                                        + "', child-name='"
2136:                                        + toName
2137:                                        + "') because source component '"
2138:                                        + source
2139:                                        + "' is final and or we should explicitly create a link for it --> creating a link for path '"
2140:                                        + source + "' !");
2141:                    }
2142:                    propertyMap = new HashMap(2);
2143:                    propertyMap.put(DEFAULT_LINK_TYPE_PATH_PROPERTY, sourceCtx
2144:                            .getPath().toString());
2145:                    typeName = DEFAULT_LINK_TYPE;
2146:                    goDeeper = false;
2147:                    fullCopy = false;
2148:                } else {
2149:                    propertyMap = getPropertyMap(source, true);
2150:                }
2151:
2152:                Component copiedInstance = null;
2153:                if (fullCopy) {
2154:                    copiedInstance = newInstanceFromType(targetParent, toName,
2155:                            typeName, newACL, propertyMap, sourceCtx);
2156:                    // if we copy a blueprint to create an instance, we do not copy the
2157:                    // template resources
2158:                    if (definesBlueprint(source) && mode == CopyMode.BLUEPRINT) {
2159:                        ((ComponentContextImpl) copiedInstance
2160:                                .getComponentContext())
2161:                                .setTemplateResources(Collections.EMPTY_MAP);
2162:                    }
2163:                } else {
2164:                    copiedInstance = newInstanceFromType(targetParent, toName,
2165:                            typeName, newACL, propertyMap, null);
2166:                }
2167:
2168:                try {
2169:                    copiedInstance.postCreate();
2170:                } catch (Exception e) {
2171:                    log
2172:                            .error(
2173:                                    "'"
2174:                                            + this .name
2175:                                            + "':copyComponentTree() - Exception while calling postCreate() on '"
2176:                                            + copiedInstance + "': ", e);
2177:                    throw new ComponentCreationException(
2178:                            ContelligentExceptionID.component_creation_persistence,
2179:                            targetParent.getComponentContext().getPath()
2180:                                    .append(toName), e);
2181:                }
2182:
2183:                ComponentContextImpl context = (ComponentContextImpl) copiedInstance
2184:                        .getComponentContext();
2185:                context.setModifiedBy(caller);
2186:                if (!isRoot() && componentAdapter.deleted(context.getPath())) {
2187:                    context.setLastModified(componentAdapter
2188:                            .getLastModified(context));
2189:                    updateWrapper(context);
2190:                } else {
2191:                    componentAdapter.create(context);
2192:                }
2193:                addClone(copiedInstance.getComponentContext().getPath(),
2194:                        copiedInstance);
2195:                // fireAddEvent(targetParent, copiedInstance); // throws
2196:                // ModificationVetoException, ComponentLockException
2197:
2198:                relationsManager.updateRelations(copiedInstance, callData,
2199:                        false);
2200:
2201:                if (goDeeper
2202:                        && (source instanceof  Container)
2203:                        && ((copiedInstance instanceof  Container) && !(copiedInstance instanceof  ComponentLink))) {
2204:                    Container sourceContainer = (Container) source;
2205:                    Iterator subNames = getSubcomponentNames(sourceContainer)
2206:                            .iterator();
2207:                    while (subNames.hasNext()) {
2208:                        String subName = (String) subNames.next();
2209:                        ComponentPath newSourcePath = sourceCtx.getPath()
2210:                                .append(subName);
2211:                        try {
2212:                            Component newSource = getComponent(newSourcePath,
2213:                                    callData, false); // don't
2214:                            // follow
2215:                            // links
2216:                            copyComponentTree((Container) copiedInstance,
2217:                                    caller, callData, newSource, subName, mode);
2218:                        } catch (ComponentNotFoundException e) {
2219:                            log
2220:                                    .error(
2221:                                            "'"
2222:                                                    + this .name
2223:                                                    + "']:copyComponentTree() - error in getSubcomponentNames() algorithm? Got name '"
2224:                                                    + subName
2225:                                                    + "' from source component '"
2226:                                                    + source
2227:                                                    + "' but could not loadType '"
2228:                                                    + newSourcePath + "': ", e);
2229:                        }
2230:                    }
2231:                }
2232:                return copiedInstance;
2233:            }
2234:
2235:            final public boolean callerHasPermission(CallData callData,
2236:                    Component component, ComponentPermission permission) {
2237:                return callerHasPermission(callData, component, permission,
2238:                        false);
2239:            }
2240:
2241:            final public boolean callerHasPermission(CallData callData,
2242:                    Component component, ComponentPermission permission,
2243:                    boolean ignoreAdmin) {
2244:                ContelligentPrincipal caller = callData
2245:                        .getContelligentSession().getUser();
2246:                return callerHasPermission(caller, callData, component,
2247:                        permission, ignoreAdmin);
2248:            }
2249:
2250:            /**
2251:             * @deprecated use the method with calldata. This only provides API
2252:             *             compatibility.
2253:             */
2254:            final public boolean callerHasPermission(
2255:                    ContelligentPrincipal caller, Component component,
2256:                    ComponentPermission permission) {
2257:
2258:                CallData callData = ThreadedMem.getCallData();
2259:                return this .callerHasPermission(caller, callData, component,
2260:                        permission);
2261:            }
2262:
2263:            final public boolean callerHasPermission(
2264:                    ContelligentPrincipal caller, CallData callData,
2265:                    Component component, ComponentPermission permission) {
2266:
2267:                return callerHasPermission(caller, callData, component,
2268:                        permission, false);
2269:            }
2270:
2271:            /**
2272:             * @deprecated use the method with calldata. This only provides API
2273:             *             compatibility.
2274:             */
2275:            final public boolean callerHasPermission(
2276:                    ContelligentPrincipal caller, Component component,
2277:                    ComponentPermission permission, boolean ignoreAdmin) {
2278:
2279:                CallData callData = ThreadedMem.getCallData();
2280:                return this .callerHasPermission(caller, callData, component,
2281:                        permission, ignoreAdmin);
2282:            }
2283:
2284:            final public boolean callerHasPermission(
2285:                    ContelligentPrincipal caller, CallData callData,
2286:                    Component component, ComponentPermission permission,
2287:                    boolean ignoreAdmin) {
2288:
2289:                // The root principal has permission to do everything, but for some
2290:                // things (EXECUTE permission on config components) we still want
2291:                // to check against the actual ACL. For that, the ignoreAdmin
2292:                // flag can be specified.
2293:                if (!ignoreAdmin) {
2294:                    if (ContelligentSecurityManager.getInstance().hasPrivilege(
2295:                            caller,
2296:                            ContelligentSecurityManager.Privilege.IGNORE_ACLS)) {
2297:                        return true;
2298:                    }
2299:                }
2300:
2301:                // The internal index user has READ permission everywhere
2302:                if (permission == ComponentPermission.READ) {
2303:                    if (ContelligentSecurityManager.getInstance().isIndexUser(
2304:                            caller)) {
2305:                        return true;
2306:                    }
2307:                }
2308:
2309:                if (permission == ComponentPermission.EXECUTE) {
2310:                    // do not check execute permission via cm acl
2311:                    if (ignoreAdmin) {
2312:                        return ((ComponentContextImpl) component
2313:                                .getComponentContext()).getEffectiveACL()
2314:                                .checkRealPermission(caller, permission,
2315:                                        callData);
2316:                    } else {
2317:                        return ((ComponentContextImpl) component
2318:                                .getComponentContext()).getEffectiveACL()
2319:                                .checkPermission(caller, permission, callData);
2320:                    }
2321:                }
2322:                if (getACL() == null
2323:                        || (getACL().isEmpty() || getACL().checkPermission(
2324:                                caller, permission, callData))) {
2325:                    if (ignoreAdmin) {
2326:                        return ((ComponentContextImpl) component
2327:                                .getComponentContext()).getEffectiveACL()
2328:                                .checkRealPermission(caller, permission,
2329:                                        callData);
2330:                    } else {
2331:                        return ((ComponentContextImpl) component
2332:                                .getComponentContext()).getEffectiveACL()
2333:                                .checkPermission(caller, permission, callData);
2334:                    }
2335:                } else {
2336:                    return false;
2337:                }
2338:            }
2339:
2340:            final public boolean callerHasPermissionForTree(CallData callData,
2341:                    ContelligentPrincipal caller, Component component,
2342:                    ComponentPermission permission) {
2343:                if ((!getACL().isEmpty())
2344:                        && (!getACL().checkPermission(caller, permission,
2345:                                callData))) {
2346:                    return false;
2347:                }
2348:
2349:                AccessControlList effectiveACL = ((ComponentContextImpl) component
2350:                        .getComponentContext()).getEffectiveACL();
2351:                /*
2352:                 * FIXME: to enable permission inheritance across different managers we
2353:                 * must maybe step down and calculate acl recursivley in realtime ?
2354:                 */
2355:                boolean result = effectiveACL.checkPermission(caller,
2356:                        permission, callData);
2357:                if (result && (component instanceof  Container)
2358:                        && (!(component instanceof  ComponentLink))) {
2359:                    Iterator subNames = getSubcomponentNames(
2360:                            (Container) component).iterator();
2361:                    while (result && subNames.hasNext()) {
2362:                        ComponentPath subName = new ComponentPath(
2363:                                (String) subNames.next());
2364:                        try {
2365:                            Component child = getSubcomponent(
2366:                                    (Container) component, subName, callData,
2367:                                    false);
2368:                            // don't follow links
2369:                            result = callerHasPermissionForTree(callData,
2370:                                    caller, child, permission);
2371:                        } catch (ComponentNotFoundException e) {
2372:                            log
2373:                                    .error(
2374:                                            "'"
2375:                                                    + this .name
2376:                                                    + "']:callerHasPermissionForTree() - error in getSubcomponentNames() algorithm? Got name '"
2377:                                                    + subName
2378:                                                    + "' from container '"
2379:                                                    + component
2380:                                                    + "' but could not loadType it: ",
2381:                                            e);
2382:                        } catch (ComponentCreationException e) {
2383:                            // This is a normal condition on package uninstallation, so
2384:                            // we should not spam the log with stacktraces here.
2385:                            log
2386:                                    .warn("'"
2387:                                            + this .name
2388:                                            + "']:callerHasPermissionForTree() - could not create subcomponent '"
2389:                                            + subName
2390:                                            + "' of component '"
2391:                                            + component
2392:                                            + "' (this component-tree is ignored for permission checking): "
2393:                                            + e.getMessage() + "\n"
2394:                                            + e.getNested().getMessage());
2395:                        }
2396:                    }
2397:                }
2398:                return result;
2399:            }
2400:
2401:            /**
2402:             * Special cleanup routine for sorted folders whose namelist got out of sync
2403:             * with the actual data. This may be caused by direct manipulation of
2404:             * components on the database level, bypassing the Contelligent server.
2405:             * 
2406:             * Due to the possibility of failure and subsequent rollback of the
2407:             * transaction, this should only be called by the xml export class. One
2408:             * reason this might fail is if the user viewing the component does not have
2409:             * write permission to the sorted folder.
2410:             */
2411:            final public void cleanMissingSubcomponent(
2412:                    SortedFolder parentContainer, String subcomponentName)
2413:                    throws ModificationVetoException {
2414:                ComponentPath parentPath = parentContainer
2415:                        .getComponentContext().getPath();
2416:                ComponentPath childPath = parentPath.append(subcomponentName);
2417:                addEvent(new ComponentEvent(ComponentEvent.REMOVE, childPath,
2418:                        this .name));
2419:                CallData callData = ThreadedMem.getCallData();
2420:                try {
2421:                    SortedFolder parentClone = (SortedFolder) cloneComponent(parentContainer);
2422:                    boolean changed = parentClone.subcomponentRemoved(callData,
2423:                            subcomponentName);
2424:                    if (changed) {
2425:                        ComponentContextImpl parentCtx = (ComponentContextImpl) parentClone
2426:                                .getComponentContext();
2427:                        boolean locked = lockComponent(parentPath, callData);
2428:                        parentCtx.setModifiedBy(callData
2429:                                .getContelligentSession().getUser());
2430:                        if (isRoot() || componentExists(parentPath, false)) {
2431:                            updateWrapper(parentCtx);
2432:                        } else {
2433:                            parentCtx.setPersistenceManager(this );
2434:                            componentAdapter.create(parentCtx);
2435:                        }
2436:                        fireChangeEvent(parentClone);
2437:                        if (log.isDebugEnabled())
2438:                            log
2439:                                    .debug("'"
2440:                                            + this .name
2441:                                            + "':cleanMissingSubcomponent() - emitted change-event for container '"
2442:                                            + parentClone + "'.");
2443:                        if (locked) {
2444:                            unlockComponent(parentPath, callData);
2445:                        }
2446:                    }
2447:                } catch (Exception e) {
2448:                    callData.markForRollback();
2449:                    if (e instanceof  ModificationVetoException) {
2450:                        throw (ModificationVetoException) e;
2451:                    } else {
2452:                        log
2453:                                .error(
2454:                                        "'"
2455:                                                + this .name
2456:                                                + "':cleanMissingSubcomponent() - ContelligentException while trying to inform parent '"
2457:                                                + parentContainer
2458:                                                + "' about deletion of child '"
2459:                                                + subcomponentName + "': ", e);
2460:                        throw new ModificationVetoException(e);
2461:                    }
2462:                }
2463:            }
2464:
2465:            final void fireDeleteEvent(Container parentContainer,
2466:                    Component subComponent, boolean committingDelete)
2467:                    throws ModificationVetoException,
2468:                    ComponentPersistenceException, ComponentLockException {
2469:                ComponentContext subCtx = subComponent.getComponentContext();
2470:
2471:                addEvent(new ComponentEvent(ComponentEvent.REMOVE, subCtx
2472:                        .getPath(), this .name));
2473:
2474:                if (!committingDelete) {
2475:                    CallData callData = ThreadedMem.getCallData();
2476:                    if (parentContainer instanceof  ObservingContainer) {
2477:                        try {
2478:                            ObservingContainer parentClone = (ObservingContainer) cloneComponent(parentContainer);
2479:                            boolean changed = parentClone.subcomponentRemoved(
2480:                                    callData, subComponent);
2481:                            if (changed) {
2482:                                ComponentContextImpl parentCtx = (ComponentContextImpl) parentClone
2483:                                        .getComponentContext();
2484:                                ComponentPath parentPath = parentCtx.getPath();
2485:                                boolean locked = lockComponent(parentPath,
2486:                                        ThreadedMem.getCallData());
2487:                                if (!isRoot()) {
2488:                                    componentLockManager.lockComponentShared(
2489:                                            parentPath, this , callData);
2490:                                }
2491:                                parentCtx.setModifiedBy(callData
2492:                                        .getContelligentSession().getUser());
2493:                                if (isRoot()
2494:                                        || componentExists(parentPath, false)) {
2495:                                    updateWrapper(parentCtx);
2496:                                } else {
2497:                                    parentCtx.setPersistenceManager(this );
2498:                                    componentAdapter.create(parentCtx);
2499:                                }
2500:                                fireChangeEvent(parentClone);
2501:                                if (log.isDebugEnabled())
2502:                                    log
2503:                                            .debug("'"
2504:                                                    + this .name
2505:                                                    + "':fireDeleteEvent() - emitted change-event for container '"
2506:                                                    + parentClone + "'.");
2507:                                if (locked) {
2508:                                    unlockComponent(parentPath, ThreadedMem
2509:                                            .getCallData());
2510:                                }
2511:                            }
2512:                        } catch (ContelligentException e) {
2513:                            callData.markForRollback();
2514:                            if (e instanceof  ModificationVetoException) {
2515:                                throw (ModificationVetoException) e;
2516:                            } else {
2517:                                log
2518:                                        .error(
2519:                                                "'"
2520:                                                        + this .name
2521:                                                        + "':fireDeleteEvent() - ContelligentException while trying to inform parent '"
2522:                                                        + parentContainer
2523:                                                        + "' about deletion of child '"
2524:                                                        + subComponent + "': ",
2525:                                                e);
2526:                                throw new ModificationVetoException(e);
2527:                            }
2528:                        }
2529:                    }
2530:                }
2531:            }
2532:
2533:            final void fireAddEvent(Container parentContainer,
2534:                    Component subComponent) throws ModificationVetoException,
2535:                    ComponentPersistenceException, ComponentLockException {
2536:
2537:                addEvent(new ComponentEvent(ComponentEvent.ADD, subComponent,
2538:                        this .name));
2539:
2540:                CallData callData = ThreadedMem.getCallData();
2541:                if (parentContainer instanceof  ObservingContainer) {
2542:                    try {
2543:                        ObservingContainer parentClone = (ObservingContainer) cloneComponent(parentContainer);
2544:                        boolean changed = parentClone.subcomponentAdded(
2545:                                callData, subComponent);
2546:                        if (changed) { // add change-event for parent
2547:                            ComponentContextImpl parentCtx = (ComponentContextImpl) parentClone
2548:                                    .getComponentContext();
2549:                            ComponentPath parentPath = parentCtx.getPath();
2550:                            boolean locked = lockComponent(parentPath,
2551:                                    ThreadedMem.getCallData());
2552:                            if (!isRoot()) {
2553:                                componentLockManager.lockComponentShared(
2554:                                        parentPath, this , callData);
2555:                            }
2556:                            parentCtx.setModifiedBy(callData
2557:                                    .getContelligentSession().getUser());
2558:                            if (isRoot() || componentExists(parentPath, false)) {
2559:                                updateWrapper(parentCtx);
2560:                            } else {
2561:                                parentCtx.setPersistenceManager(this );
2562:                                componentAdapter.create(parentCtx);
2563:                            }
2564:                            fireChangeEvent(parentClone);
2565:                            if (log.isDebugEnabled())
2566:                                log
2567:                                        .debug("'"
2568:                                                + this .name
2569:                                                + "':fireAddEvent() - emitted change-event for container '"
2570:                                                + parentClone + "'.");
2571:                            if (locked) {
2572:                                unlockComponent(parentPath, ThreadedMem
2573:                                        .getCallData());
2574:                            }
2575:                        }
2576:                    } catch (ContelligentException e) {
2577:                        callData.markForRollback();
2578:                        if (e instanceof  ModificationVetoException) {
2579:                            throw (ModificationVetoException) e;
2580:                        } else {
2581:                            log
2582:                                    .error(
2583:                                            "'"
2584:                                                    + this .name
2585:                                                    + "':fireAddEvent() - ContelligentException while trying to inform parent '"
2586:                                                    + parentContainer
2587:                                                    + "' about new child '"
2588:                                                    + subComponent + "': ", e);
2589:                            throw new ModificationVetoException(e);
2590:                        }
2591:                    }
2592:                }
2593:            }
2594:
2595:            final void fireChangeEvent(Component component)
2596:                    throws ComponentNotFoundException,
2597:                    ModificationVetoException, ComponentLockException {
2598:                ComponentContext ctx = component.getComponentContext();
2599:                addEvent(new ComponentEvent(ComponentEvent.CHANGE, component,
2600:                        this .name));
2601:
2602:                CallData callData = ThreadedMem.getCallData();
2603:                Component parentContainer = getComponent(new ComponentPath(ctx
2604:                        .getPath().getDir()), callData);
2605:                if (parentContainer instanceof  ObservingContainer) {
2606:                    try {
2607:                        ObservingContainer parentClone = (ObservingContainer) cloneComponent(parentContainer);
2608:                        boolean changed = parentClone.subcomponentChanged(
2609:                                callData, component);
2610:                        if (changed) {
2611:                            ComponentContextImpl parentCtx = (ComponentContextImpl) parentClone
2612:                                    .getComponentContext();
2613:                            ComponentPath parentPath = parentCtx.getPath();
2614:                            boolean locked = lockComponent(parentPath,
2615:                                    ThreadedMem.getCallData());
2616:                            parentCtx.setModifiedBy(callData
2617:                                    .getContelligentSession().getUser());
2618:                            if (isRoot() || componentExists(parentPath, false)) {
2619:                                updateWrapper(parentCtx);
2620:                            } else {
2621:                                parentCtx.setPersistenceManager(this );
2622:                                componentAdapter.create(parentCtx);
2623:                            }
2624:                            fireChangeEvent(parentClone);
2625:                            if (log.isDebugEnabled())
2626:                                log
2627:                                        .debug("'"
2628:                                                + this .name
2629:                                                + "':fireChangeEvent() - emitted change-event for container '"
2630:                                                + parentClone + "'.");
2631:                            if (locked) {
2632:                                unlockComponent(parentPath, ThreadedMem
2633:                                        .getCallData());
2634:                            }
2635:                        }
2636:                    } catch (ContelligentException e) {
2637:                        callData.markForRollback();
2638:                        if (e instanceof  ModificationVetoException) {
2639:                            throw (ModificationVetoException) e;
2640:                        } else {
2641:                            log
2642:                                    .error(
2643:                                            "'"
2644:                                                    + this .name
2645:                                                    + "':fireChangeEvent() - ContelligentException while trying to inform parent '"
2646:                                                    + parentContainer
2647:                                                    + "' about deletion of child '"
2648:                                                    + component + "': ", e);
2649:                            throw new ModificationVetoException(e);
2650:                        }
2651:                    }
2652:                }
2653:            }
2654:
2655:            final void addClone(ComponentPath path, Component clone) {
2656:                Map map = (Map) cloneMap.get();
2657:                if (map == null) {
2658:                    map = new HashMap();
2659:                    cloneMap.set(map);
2660:                }
2661:                map.put(path, clone);
2662:            }
2663:
2664:            final Component getClone(ComponentPath path) {
2665:                Map map = (Map) cloneMap.get();
2666:                if (map != null)
2667:                    return (Component) map.get(path);
2668:                else
2669:                    return null;
2670:            }
2671:
2672:            /*
2673:             * final Component removeClone(ComponentPath path) { Map map =
2674:             * (Map)cloneMap.get(); if (map!=null && map.containsKey(path)) return
2675:             * (Component)map.removeType(path); else return null; }
2676:             */
2677:
2678:            final void addEvent(ComponentEvent event) {
2679:                List list = (List) eventList.get();
2680:                if (list == null) {
2681:                    list = new LinkedList();
2682:                    eventList.set(list);
2683:                }
2684:                list.add(event);
2685:                EventQueue.getInstance().addEvent(event);
2686:            }
2687:
2688:            final ListIterator getEvents() {
2689:                List list = (List) eventList.get();
2690:                return ((list == null) ? null : Collections.unmodifiableList(
2691:                        list).listIterator());
2692:            }
2693:
2694:            final List getEventList() {
2695:                List list = (List) eventList.get();
2696:                return ((list == null) ? null : Collections
2697:                        .unmodifiableList(list));
2698:            }
2699:
2700:            /**
2701:             * Initialize a raw component instance (set act and attributes inherited
2702:             * from the parent.
2703:             */
2704:            final void initComponent(Component rawInstance,
2705:                    Container parentContainer)
2706:                    throws ComponentCreationException {
2707:                final ComponentContextImpl ctx = (ComponentContextImpl) rawInstance
2708:                        .getComponentContext();
2709:                final ComponentPath path = ctx.getPath();
2710:                final boolean debugEnabled = log.isDebugEnabled();
2711:
2712:                ComponentContextImpl parentCtx = null; // may remain null if
2713:                // ctx.inheritSecurity()==false
2714:                // !!
2715:
2716:                // BUG FIX; IGNORE BULLSHIT PARAMETER
2717:                // (looks like our callers try to save us the time of looking up the
2718:                // component parent here... and then dont really send us the direct
2719:                // parent container but some indirect ancestor, which makes a giant
2720:                // mess of the ACLs)
2721:                parentContainer = null;
2722:
2723:                if (ctx.inheritSecurity()) {
2724:                    if (parentContainer == null)
2725:                        parentContainer = parentContainer(rawInstance);
2726:                    parentCtx = (ComponentContextImpl) parentContainer
2727:                            .getComponentContext();
2728:
2729:                    try {
2730:                        AccessControlList parentACL = parentCtx
2731:                                .getEffectiveACL();
2732:                        AccessControlList childACL = ctx.getACL();
2733:                        if (parentACL == null) {
2734:                            log
2735:                                    .error("'"
2736:                                            + this .name
2737:                                            + "':initComponent() - parent ACL of component '"
2738:                                            + path + "' is null!");
2739:                            // TODO: throw exception !!! (rs)
2740:                            ctx.setEffectiveACL(childACL);
2741:                        } else {
2742:                            AccessControlList effectiveACL = (AccessControlList) childACL
2743:                                    .clone();
2744:                            effectiveACL.addACL(getSystemUser(), parentACL);
2745:                            if (debugEnabled)
2746:                                log
2747:                                        .debug("'"
2748:                                                + this .name
2749:                                                + "':initComponent() - ... successfully merged parent- and own ACL!");
2750:                            ctx.setEffectiveACL(effectiveACL);
2751:                        }
2752:                    } catch (NotOwnerException e) {
2753:                        log
2754:                                .warn("'"
2755:                                        + this .name
2756:                                        + "':initComponent() - NotOwnerException while merging acls: "
2757:                                        + e);
2758:                        // do nothing!
2759:                    }
2760:                } else {
2761:                    ctx.setEffectiveACL(ctx.getACL());
2762:                    if (debugEnabled)
2763:                        log
2764:                                .debug("'"
2765:                                        + this .name
2766:                                        + "':initComponent() - ... inheritSecurity of component '"
2767:                                        + path + "' is false!");
2768:                }
2769:
2770:                // ----- init security mode (https/http)
2771:                if (rawInstance instanceof  SecureComponent
2772:                        || ctx.definesSecureTransfer()
2773:                        || (ctx.inheritSecurity() && parentCtx
2774:                                .requiresSecureTransfer())) {
2775:                    ctx.setRequiresSecureTransfer(true);
2776:                } else {
2777:                    ctx.setRequiresSecureTransfer(false);
2778:                }
2779:            }
2780:
2781:            /**
2782:             * Implementation of {@link ComponentManager#moveComponentTree}. <BR>
2783:             * Algorithm works as follows:
2784:             * <OL>
2785:             * <LI> get paths of those components which have a relation into the moved
2786:             * tree. (including those lying themselves inside the moved tree!)
2787:             * <LI> for each of those components: - clone it - if it lies within the
2788:             * source tree just change any affected paths - else attempt to lock it and
2789:             * then change any affected paths
2790:             * <LI> copy the source tree (using the cloned source components from step
2791:             * 2a with maybe changed paths)
2792:             * <LI> now update the components from step 2b. This can't be done before
2793:             * step 3 or else the system may complain about missing link targets.
2794:             * <LI> delete source tree and all relations originating from it. If this is
2795:             * the root server we may check for any relations still existing to this
2796:             * tree (which would mean our algorithm has a fault). In a child server we
2797:             * can't because we will sure have relations to this tree because our
2798:             * modified components were not yet written to the root server.
2799:             * <LI> at the end we check for any dead-relations in the destination tree.
2800:             * This would also reveal a bug in the algorithm.
2801:             * </OL>
2802:             * <B>Note that currently only one component tree per transaction may be
2803:             * moved!</B>
2804:             */
2805:            final public Set moveComponentTree(ComponentPath source,
2806:                    ComponentPath destination, CallData callData)
2807:                    throws ContelligentException,
2808:                    ComponentPersistenceException, MissingPermissionException,
2809:                    ComponentAlreadyExistsException {
2810:                Set lockedComponents = new HashSet();
2811:
2812:                if (destination.equals(source)
2813:                        || destination.isSubPathOf(source)
2814:                        || source.isSubPathOf(destination)) {
2815:                    throw new ComponentMoveException(
2816:                            ContelligentExceptionID.component_moveBeneathItself,
2817:                            new Object[] { source.toPath() });
2818:                }
2819:                if (componentFactory.containsBlueprintPath(source)) {
2820:                    throw new ComponentMoveException(
2821:                            ContelligentExceptionID.component_moveBlueprint,
2822:                            new Object[] { source.toPath() });
2823:                }
2824:                try {
2825:                    List componentsToUpdate = new LinkedList();
2826:
2827:                    checkContainsReadOnly(source);
2828:
2829:                    RelationsManagerImpl relationsManager = (RelationsManagerImpl) contelligent
2830:                            .getRelationsManager();
2831:                    // Set pathsRelatedToTree =
2832:                    // relationsManager.getPathsRelatedToTree(source, true,
2833:                    // this.getId());
2834:                    // Due to .. references we need to process both references to as
2835:                    // well as all from the tree to be moved
2836:                    Set pathsToUpdate = relationsManager.getPathsRelatedToTree(
2837:                            source, false, this .getId());
2838:                    pathsToUpdate.addAll(relationsManager
2839:                            .getTreeRelationSources(source, this .getId()));
2840:                    Iterator sourcesRelatedToTree = pathsToUpdate.iterator();
2841:                    while (sourcesRelatedToTree.hasNext()) {
2842:                        ComponentPath path = (ComponentPath) sourcesRelatedToTree
2843:                                .next();
2844:                        Component component = cloneComponent(path, callData);
2845:                        if (source.equals(path) || path.isSubPathOf(source)) {
2846:                            log.debug("'" + this .name
2847:                                    + "':moveComponentTree() - informing '"
2848:                                    + component + "' about move of '" + source
2849:                                    + "' to '" + destination
2850:                                    + "' ... (component gets itself moved)");
2851:                            relationsManager.updateRelationsForMove(component,
2852:                                    source, destination);
2853:                        } else {
2854:                            boolean locked = lockComponent(path, callData);
2855:                            log.debug("'" + this .name
2856:                                    + "':moveComponentTree() - informing '"
2857:                                    + component + "' about move of '" + source
2858:                                    + "' to '" + destination + "' ...");
2859:                            relationsManager.updateRelationsForMove(component,
2860:                                    source, destination);
2861:                            componentsToUpdate.add(component);
2862:                            if (locked) {
2863:                                unlockComponent(path, callData);
2864:                            }
2865:                        }
2866:                    }
2867:
2868:                    // all relations changed, now simply copy the source tree: (copy
2869:                    // uses clones)
2870:                    copyComponentTree(callData, source, destination
2871:                            .parentPath(), destination.getName(),
2872:                            CopyMode.ALL_ACLS, false);
2873:
2874:                    // now update those components which got not themselves moved.
2875:                    Iterator it = componentsToUpdate.iterator();
2876:                    while (it.hasNext()) {
2877:                        Component component = (Component) it.next();
2878:                        ComponentPath path = component.getComponentContext()
2879:                                .getPath();
2880:                        log
2881:                                .debug("'"
2882:                                        + this .name
2883:                                        + "':moveComponentTree() - now updating component '"
2884:                                        + component + "' ...");
2885:                        updateComponent(component, callData);
2886:                        unlockComponent(path, callData);
2887:                    }
2888:
2889:                    // delete source tree: (only check for remaining links to this tree
2890:                    // if we are in root server)
2891:                    deleteComponentTree(source, callData, true, isRoot(), true);
2892:
2893:                    // check for dead-relations in destination:
2894:                    checkRelationsOfComponent(destination, true, callData);
2895:
2896:                    return lockedComponents;
2897:                } catch (ContelligentException e) {
2898:                    throw e;
2899:                } catch (ContelligentRuntimeException e) {
2900:                    throw e; // prevent this exception from beeing wrapped in a
2901:                    // ComponentMoveException
2902:                } catch (Exception e) {
2903:                    callData.markForRollback();
2904:                    log
2905:                            .error(
2906:                                    "'"
2907:                                            + this .name
2908:                                            + "':moveComponentTree() - Exception while moving '"
2909:                                            + source + "' to '" + destination
2910:                                            + "': ", e);
2911:                    throw new ComponentMoveException(
2912:                            ContelligentExceptionID.component_generic,
2913:                            new Object[] { source.toPath() }, e);
2914:                }
2915:            }
2916:
2917:            final public Map getPropertyMap(Component component,
2918:                    boolean includeRN) throws TypeException {
2919:                return getPropertyMap(component, includeRN, true);
2920:            }
2921:
2922:            final public Map getPropertyMap(Component component,
2923:                    boolean includeRN, boolean includeW) throws TypeException {
2924:                Type type = component.getComponentContext().getType();
2925:                return type.getProperties(component, includeRN, includeW);
2926:            }
2927:
2928:            /**
2929:             * Implementation of {@link ComponentManager#getInstancesOfType}.
2930:             */
2931:            final public Set getInstancesOfType(ComponentPath treeRoot,
2932:                    String typeName) throws ComponentPersistenceException {
2933:                long[] ids = getIdsUpToRoot();
2934:                Set typeNames = new HashSet(2);
2935:                typeNames.add(typeName);
2936:                return componentAdapter.getComponentPathsForTypeInstances(
2937:                        treeRoot, typeNames, ids);
2938:            }
2939:
2940:            /**
2941:             * Functions like getInstancesOfType, except that it searches across all
2942:             * existing CMs.
2943:             */
2944:            final public Set getGlobalInstancesOfType(ComponentPath treeRoot,
2945:                    String typeName) throws ComponentPersistenceException {
2946:                long[] ids = {};
2947:                Set typeNames = new HashSet(2);
2948:                typeNames.add(typeName);
2949:                return componentAdapter.getComponentPathsForTypeInstances(
2950:                        treeRoot, typeNames, ids);
2951:            }
2952:
2953:            /**
2954:             * Implementation of
2955:             * {@link ComponentManager#getComponentsInSubtreeFilteredByType}.
2956:             */
2957:            final public Set getComponentsInSubtreeFilteredByType(
2958:                    ComponentPath treeRoot, Collection typeNames)
2959:                    throws ComponentPersistenceException {
2960:                Set allTypeNames = new HashSet(typeNames);
2961:                Iterator iterator = typeNames.iterator();
2962:                while (iterator.hasNext()) {
2963:                    String typeName = (String) iterator.next();
2964:                    allTypeNames.addAll(componentFactory
2965:                            .getSubTypeNames(typeName));
2966:                }
2967:                long[] ids = getIdsUpToRoot();
2968:                return componentAdapter.getComponentPathsForTypeInstances(
2969:                        treeRoot, allTypeNames, ids);
2970:            }
2971:
2972:            /**
2973:             * Implementation of {@link ComponentManager#deleteType}.
2974:             */
2975:            final public Set deleteType(CallData callData, String typeName,
2976:                    boolean force, boolean includeBlueprintComponent)
2977:                    throws ContelligentException,
2978:                    ComponentPersistenceException, NoDeletePermissionException,
2979:                    ModificationVetoException, ComponentLockException,
2980:                    RelationExistsException {
2981:                // XXX: as long as we don't have one ComponentFactory per manager we
2982:                // can't allow
2983:                // the deletion of types in a non-root manager! (rs, 2002/11/18)
2984:                if (!isRoot()) {
2985:                    log
2986:                            .error("'"
2987:                                    + this .name
2988:                                    + "':deleteType() - deletion of types not allowed in non-root manager!");
2989:                    throw new TypeException(
2990:                            ContelligentExceptionID.type_noModificationInContext);
2991:                }
2992:
2993:                Set pathsOfTypeInstances = this .getGlobalInstancesOfType(null,
2994:                        typeName);
2995:                if (!force && !pathsOfTypeInstances.isEmpty()) {
2996:                    throw new TypeException(
2997:                            ContelligentExceptionID.type_instancesExist,
2998:                            new Object[] { typeName, pathsOfTypeInstances },
2999:                            pathsOfTypeInstances);
3000:                }
3001:
3002:                ContelligentEvent event = new TypeEvent(TypeEvent.DELETED,
3003:                        this .name, typeName);
3004:                EventQueue.getInstance().addEvent(event);
3005:
3006:                Set lockedComponents = new HashSet();
3007:                if (pathsOfTypeInstances != null) {
3008:                    for (Iterator it = pathsOfTypeInstances.iterator(); it
3009:                            .hasNext();) {
3010:                        ComponentPath path = (ComponentPath) it.next();
3011:                        boolean locked = lockComponent(path, callData);
3012:                        deleteComponentTree(callData, path);
3013:                        if (locked) {
3014:                            unlockComponent(path, callData);
3015:                        } else {
3016:                            lockedComponents.add(path);
3017:                        }
3018:                    }
3019:                }
3020:                if (includeBlueprintComponent) {
3021:                    ComponentPath path = componentFactory.getType(typeName)
3022:                            .getBlueprintPath();
3023:                    if (path != null) {
3024:                        boolean locked = lockComponent(path, callData);
3025:                        deleteComponentTree(callData, path);
3026:                        if (locked) {
3027:                            unlockComponent(path, callData);
3028:                        } else {
3029:                            lockedComponents.add(path);
3030:                        }
3031:                    }
3032:                }
3033:                // throws exception if type has any subtypes or if type does not exist
3034:                componentFactory.deleteType(typeName);
3035:                return lockedComponents;
3036:            }
3037:
3038:            /**
3039:             * Delete the given type without touching instances. Answer true if
3040:             * instances exist. For internal use only and therefore not in the
3041:             * interface.
3042:             * 
3043:             * @param callData
3044:             * @param typeName
3045:             * @return
3046:             * @throws ContelligentException
3047:             * @throws ComponentPersistenceException
3048:             * @throws NoDeletePermissionException
3049:             * @throws ModificationVetoException
3050:             * @throws ComponentLockException
3051:             * @throws RelationExistsException
3052:             */
3053:            final boolean deleteTypeRaw(CallData callData, String typeName)
3054:                    throws ContelligentException,
3055:                    ComponentPersistenceException, NoDeletePermissionException,
3056:                    ModificationVetoException, ComponentLockException,
3057:                    RelationExistsException {
3058:                // XXX: as long as we don't have one ComponentFactory per manager we
3059:                // can't allow
3060:                // the deletion of types in a non-root manager! (rs, 2002/11/18)
3061:                if (!isRoot()) {
3062:                    log
3063:                            .error("'"
3064:                                    + this .name
3065:                                    + "':deleteType() - deletion of types not allowed in non-root manager!");
3066:                    throw new TypeException(
3067:                            ContelligentExceptionID.type_noModificationInContext);
3068:                }
3069:
3070:                Set pathsOfTypeInstances = this .getInstancesOfType(null,
3071:                        typeName);
3072:
3073:                ContelligentEvent event = new TypeEvent(TypeEvent.DELETED,
3074:                        this .name, typeName);
3075:                EventQueue.getInstance().addEvent(event);
3076:
3077:                boolean subtypes = componentFactory.deleteTypeRaw(typeName);
3078:                return (!pathsOfTypeInstances.isEmpty()) || subtypes;
3079:            }
3080:
3081:            final void flagTypeForUpgrade(CallData callData, String typeName)
3082:                    throws ContelligentException,
3083:                    ComponentPersistenceException, NoDeletePermissionException,
3084:                    ModificationVetoException, ComponentLockException,
3085:                    RelationExistsException {
3086:                if (!isRoot()) {
3087:                    log
3088:                            .error("'"
3089:                                    + this .name
3090:                                    + "':flagTypeForUpgrade() - modification of types not allowed in non-root manager!");
3091:                    throw new TypeException(
3092:                            ContelligentExceptionID.type_noModificationInContext);
3093:                }
3094:                componentFactory.flagTypeForUpgrade(typeName);
3095:            }
3096:
3097:            final void checkUpgradedTypes() throws TypeException {
3098:                componentFactory.checkUpgradedTypes();
3099:            }
3100:
3101:            /**
3102:             * Implementation of {@link ComponentManager#renameType}.
3103:             */
3104:            final public Set renameType(CallData callData, String typeName,
3105:                    String newTypeName) throws TypeException,
3106:                    ComponentPersistenceException, ComponentLockException,
3107:                    ModificationVetoException {
3108:                // XXX: as long as we don't have one ComponentFactory per manager we
3109:                // can't allow
3110:                // renaming of types in a non-root manager! (rs, 2002/11/18)
3111:                if (!isRoot()) {
3112:                    log
3113:                            .error("'"
3114:                                    + this .name
3115:                                    + "':renameType() - renaming of types not allowed in non-root manager!");
3116:                    throw new TypeException(
3117:                            ContelligentExceptionID.type_noModificationInContext);
3118:                }
3119:
3120:                Set pathsOfTypeInstances = this .getGlobalInstancesOfType(null,
3121:                        typeName);
3122:                Set changedComponents = new HashSet(); // only used to fire
3123:                // component-events after
3124:                // type-events
3125:                Set lockedComponents = new HashSet();
3126:                if (!pathsOfTypeInstances.isEmpty()) {
3127:                    for (Iterator it = pathsOfTypeInstances.iterator(); it
3128:                            .hasNext();) {
3129:                        ComponentPath path = (ComponentPath) it.next();
3130:                        boolean locked = lockComponent(path, callData);
3131:                        try {
3132:                            Component component = cloneComponent(path, callData);
3133:                            ComponentContextImpl context = (ComponentContextImpl) component
3134:                                    .getComponentContext();
3135:                            context.setTypeName(newTypeName);
3136:                            context.setModifiedBy(callData
3137:                                    .getContelligentSession().getUser());
3138:                            if (isRoot() || componentExists(path, false)) {
3139:                                updateWrapper(context);
3140:                            } else {
3141:                                context.setPersistenceManager(this );
3142:                                componentAdapter
3143:                                        .create((ComponentContextImpl) component
3144:                                                .getComponentContext());
3145:                            }
3146:                            changedComponents.add(component);
3147:                            if (locked) {
3148:                                unlockComponent(path, callData);
3149:                            } else {
3150:                                lockedComponents.add(path);
3151:                            }
3152:                        } catch (ComponentNotFoundException cnfe) {
3153:                            log
3154:                                    .warn("renameType() - can not change type for component '"
3155:                                            + path.toPath()
3156:                                            + "', component does not exist.");
3157:                        }
3158:                    }
3159:                }
3160:
3161:                // throws exception if type has any subtypes or if type does not exist
3162:                componentFactory.renameType(typeName, newTypeName);
3163:
3164:                ContelligentEvent event = new TypeEvent(TypeEvent.DELETED,
3165:                        this .name, typeName);
3166:                EventQueue.getInstance().addEvent(event);
3167:
3168:                Type newType = componentFactory.getType(newTypeName);
3169:                event = new TypeEvent(TypeEvent.CREATION, this .name, newType);
3170:                EventQueue.getInstance().addEvent(event);
3171:
3172:                Iterator chgComponents = changedComponents.iterator();
3173:                while (chgComponents.hasNext()) {
3174:                    Component comp = (Component) chgComponents.next();
3175:                    try {
3176:                        fireChangeEvent(comp);
3177:                    } catch (ComponentNotFoundException e) {
3178:                        log
3179:                                .warn("renameType() - unable to fire change-event for component '"
3180:                                        + comp + "': " + e);
3181:                    }
3182:                }
3183:
3184:                return lockedComponents;
3185:            }
3186:
3187:            /**
3188:             * Implementation of {@link ComponentManager#createType}.
3189:             */
3190:            final public void createType(TypeElement typeDefinition)
3191:                    throws TypeException {
3192:                // XXX: as long as we don't have one ComponentFactory per manager we
3193:                // can't allow
3194:                // the creation of types in a non-root manager! But we need to call this
3195:                // method during import so we allow it for import manager. (rs,
3196:                // 2002/11/18)
3197:                if (isRoot() || isImport()) {
3198:                    boolean update = componentFactory.exists(typeDefinition
3199:                            .getName());
3200:                    if (update && !isImport()) {
3201:                        Type oldType = componentFactory.getType(typeDefinition
3202:                                .getName());
3203:                        String pathOfExistingBlueprint = "";
3204:                        if (oldType.isBlueprint()) {
3205:                            pathOfExistingBlueprint = componentFactory.getType(
3206:                                    typeDefinition.getName())
3207:                                    .getBlueprintPath().toString();
3208:                        }
3209:                        String pathOfAttemptedBlueprint = typeDefinition
3210:                                .getBlueprintPath();
3211:                        // creation is only allowed when you are changing the blueprint.
3212:                        // same type name and different component path means: 
3213:                        // trying to create a blueprint with a name already in use    
3214:                        if (!oldType.isBlueprint()
3215:                                || !pathOfExistingBlueprint
3216:                                        .equals(pathOfAttemptedBlueprint)) {
3217:                            log
3218:                                    .error("'"
3219:                                            + this .name
3220:                                            + "':createType() - failing to create a new type because name '"
3221:                                            + typeDefinition.getName()
3222:                                            + "' is already in use.");
3223:                            throw new TypeException(
3224:                                    ContelligentExceptionID.type_alreadyExist,
3225:                                    new String[] { typeDefinition.getName() });
3226:                        }
3227:                    }
3228:                    Type type = componentFactory.createType(typeDefinition);
3229:                    ContelligentEvent event = new TypeEvent(
3230:                            (update ? TypeEvent.CHANGED : TypeEvent.CREATION),
3231:                            this .name, type);
3232:                    EventQueue.getInstance().addEvent(event);
3233:                } else {
3234:                    log
3235:                            .error("'"
3236:                                    + this .name
3237:                                    + "':createType() - creation of types only allowed in root- or import-manager!");
3238:                    throw new TypeException(
3239:                            ContelligentExceptionID.type_noModificationInContext);
3240:                }
3241:            }
3242:
3243:            final public void exportTypes(Writer writer, boolean omitHeader,
3244:                    String prefix) throws IOException {
3245:                componentFactory.exportTypes(writer, omitHeader, prefix);
3246:            }
3247:
3248:            final public Type getBlueprintType(ComponentPath componentPath) {
3249:                return componentFactory.getBlueprintType(componentPath);
3250:            }
3251:
3252:            final public boolean isBlueprintInstance(Component component) {
3253:                if (component != null) {
3254:                    Type type = component.getComponentContext().getType();
3255:                    return (type.getBlueprintPath() != null);
3256:                }
3257:                return false;
3258:            }
3259:
3260:            final public boolean definesBlueprint(Component component) {
3261:                if (component != null) {
3262:                    return componentFactory.isBlueprintPath(component
3263:                            .getComponentContext().getPath());
3264:                }
3265:                return false;
3266:            }
3267:
3268:            /**
3269:             * Implementation of {@link TxSynchronization#beforeCompletion}.
3270:             */
3271:            public boolean beforeCompletion() {
3272:                Boolean informParent = (Boolean) parentInTransaction.get();
3273:                if (informParent == Boolean.TRUE) {
3274:                    parent.beforeCompletion();
3275:                }
3276:                return true;
3277:            }
3278:
3279:            // FIXME: because we store all the events and clones in thread-locals
3280:            // only one manager per tx is allowed! Can we go with this?
3281:            // The only situation where we need two managers per tx is when one manager
3282:            // gets merged into another. Since the merged one is empty aftwerwards this
3283:            // should be no problem.
3284:            /**
3285:             * Implementation of {@link TxSynchronization#afterCompletion}. <B>If any
3286:             * subclass overwrites this method it must call this method at the end so
3287:             * thread-locals are reseted!</B>
3288:             */
3289:            public void afterCompletion(int status) {
3290:                Boolean informParent = (Boolean) parentInTransaction.get();
3291:
3292:                if (informParent == Boolean.TRUE) {
3293:                    parent.afterCompletion(status);
3294:                }
3295:
3296:                if (!isRoot() && (status == Status.STATUS_COMMITTED)) {
3297:                    List fileNameList = (List) filesToMoveList.get();
3298:                    if (fileNameList != null && fileNameList.size() > 0) {
3299:                        this .fileAdapter.moveFiles(fileNameList, getParent()
3300:                                .getFileAdapter());
3301:                        if (!fileNameList.isEmpty()) {
3302:                            log
3303:                                    .error("'"
3304:                                            + name
3305:                                            + "':afterCompletion() - error while moving external files into parent, remaining files= "
3306:                                            + fileNameList);
3307:                        }
3308:                    }
3309:                }
3310:
3311:                Boolean flag = (Boolean) destroyFileAdapters.get();
3312:                if (flag != null && flag.booleanValue() == true) {
3313:                    fileAdapter.destroy();
3314:                    destroyFileAdapters.set(null);
3315:                }
3316:            }
3317:
3318:            public void clean() {
3319:                parentInTransaction.set(null);
3320:                cloneMap.set(null);
3321:                eventList.set(null);
3322:            }
3323:
3324:            /**
3325:             * Implementation of {@link  ComponentManager#getId}.
3326:             */
3327:            final public long getId() {
3328:                return componentAdapter.getCMId();
3329:            }
3330:
3331:            /**
3332:             * Returns all ids from this manager up to the root manager in order of the
3333:             * hierarchy. First entry is the id of this manager.
3334:             */
3335:            final public long[] getIdsUpToRoot() {
3336:                if (this .isRoot()) {
3337:                    return new long[] { this .getId() };
3338:                } else {
3339:                    int count = 1;
3340:                    ComponentManager manager = this .getParent();
3341:                    while (manager != null) {
3342:                        count++;
3343:                        manager = manager.getParent();
3344:                    }
3345:                    long[] ids = new long[count];
3346:                    count = 0;
3347:                    manager = this ;
3348:                    while (manager != null) {
3349:                        ids[count++] = manager.getId();
3350:                        manager = manager.getParent();
3351:                    }
3352:                    return ids;
3353:                }
3354:            }
3355:
3356:            /**
3357:             * Implementation of {@link ComponentManager#lockComponent}.
3358:             */
3359:            final public boolean lockComponent(ComponentPath componentPath,
3360:                    CallData callData) throws ComponentPersistenceException,
3361:                    ComponentAlreadyLockedException, ComponentLockException,
3362:                    MissingPermissionException {
3363:                return lockComponent(componentPath, callData, true);
3364:            }
3365:
3366:            final protected boolean lockComponent(ComponentPath componentPath,
3367:                    CallData callData, boolean checkLockContext)
3368:                    throws ComponentPersistenceException,
3369:                    ComponentAlreadyLockedException, ComponentLockException,
3370:                    MissingPermissionException {
3371:                if (componentLockManager.isLockedLocally(componentPath)) {
3372:                    if (checkLockContext) {
3373:                        checkAvailableLock(callData, componentPath);
3374:                    }
3375:                    return false;
3376:                }
3377:                componentLockManager.lockComponent(componentPath, this ,
3378:                        callData);
3379:                return true;
3380:            }
3381:
3382:            final protected boolean lockComponentForDelete(
3383:                    ComponentPath componentPath, CallData callData,
3384:                    boolean checkLockContext)
3385:                    throws ComponentPersistenceException,
3386:                    ComponentAlreadyLockedException, ComponentLockException,
3387:                    MissingPermissionException {
3388:                componentLockManager.checkSharedLocksForDelete(componentPath,
3389:                        this , callData);
3390:                if (componentLockManager.isLockedLocally(componentPath)) {
3391:                    if (checkLockContext) {
3392:                        checkAvailableLock(callData, componentPath);
3393:                    }
3394:                    return false;
3395:                }
3396:                componentLockManager.lockComponentForDelete(componentPath,
3397:                        this , callData);
3398:                return true;
3399:            }
3400:
3401:            /**
3402:             * Implementation of {@link ComponentManager#unlockComponent}.
3403:             */
3404:            final public void unlockComponent(ComponentPath componentPath,
3405:                    CallData callData) throws ComponentPersistenceException {
3406:                componentLockManager.unlockComponent(componentPath, this ,
3407:                        false, callData);
3408:            }
3409:
3410:            /**
3411:             * Implementation of {@link ComponentManager#isLocked}.
3412:             */
3413:            final public boolean isLocked(ComponentPath componentPath) {
3414:                return componentLockManager.isLocked(componentPath);
3415:            }
3416:
3417:            final public List createEventsForAllLocks() {
3418:                return componentLockManager.createEventsForAllLocks();
3419:            }
3420:
3421:            /**
3422:             * Implementation of {@link ComponentManager#passLock}.
3423:             */
3424:            final public void passLock(ComponentPath componentPath,
3425:                    String toPrincipal, CallData callData)
3426:                    throws ComponentPersistenceException {
3427:                componentLockManager.passLock(componentPath, toPrincipal,
3428:                        callData);
3429:            }
3430:
3431:            /**
3432:             * Answer the acl of this manager.
3433:             * 
3434:             * @return
3435:             */
3436:            final public AccessControlList getACL() {
3437:                return acl;
3438:            }
3439:
3440:            final public void setACL(CallData callData, AccessControlList acl)
3441:                    throws ComponentPersistenceException {
3442:                if (getACL().isOwner(callData.getUser())
3443:                        || ContelligentSecurityManager
3444:                                .getInstance()
3445:                                .hasPrivilege(
3446:                                        callData.getUser(),
3447:                                        ContelligentSecurityManager.Privilege.IGNORE_OWNERSHIP)) {
3448:                    this .acl = acl;
3449:                    contelligent.getComponentManagerHierarchy().storeACL(
3450:                            getName(), acl);
3451:                } else {
3452:                    throw new NotOwnerException(callData.getUser(), getACL()
3453:                            .getName());
3454:                }
3455:            }
3456:
3457:            final public Component updateComponent(
3458:                    ComponentElement componentElement, CallData callData)
3459:                    throws ContelligentException {
3460:                ComponentPath path = getComponentPath(componentElement);
3461:                boolean locked = lockComponent(path, callData);
3462:
3463:                try {
3464:                    Component component = cloneComponent(
3465:                            getComponentPath(componentElement), callData);
3466:                    final ContelligentPrincipal caller = callData
3467:                            .getContelligentSession().getUser();
3468:                    if (!callerHasPermission(caller, callData, component,
3469:                            ComponentPermission.WRITE)) {
3470:                        log.warn("'" + this .name
3471:                                + "':updateComponent() - caller '" + caller
3472:                                + "' has no write access for component '"
3473:                                + component + "'!");
3474:                        throw new NoWritePermissionException(caller, component
3475:                                .getComponentContext().getPath());
3476:                    }
3477:                    updateComponent(component, componentElement, callData);
3478:                    // also updates relations and checks for dead relations resulting
3479:                    // from update
3480:                    fireChangeEvent(component);
3481:                    return component;
3482:                } finally {
3483:                    if (locked) {
3484:                        unlockComponent(path, callData);
3485:                    }
3486:                    if ((!isRoot()) && componentExists(path, false)
3487:                            && (!componentLockManager.isLockedShared(path))) {
3488:                        componentLockManager.lockComponentShared(path, this ,
3489:                                callData);
3490:                    }
3491:                }
3492:            }
3493:
3494:            /**
3495:             * Updates a contelligent component using the given
3496:             * <code>ComponentElement</code>. Any relations of the component are
3497:             * updated and if this is not an import server a check for dead relations
3498:             * caused by this update is performed too.
3499:             * 
3500:             * @param componentElement
3501:             *            a contelligent component as XML element.
3502:             */
3503:            final private void updateComponent(Component component,
3504:                    ComponentElement componentElement, CallData callData)
3505:                    throws ContelligentException {
3506:                // assert: component is a new component or a clone of an existing
3507:                // component
3508:
3509:                checkReadOnly(component.getComponentContext().getPath());
3510:                CategoryManager categoryManager = contelligent
3511:                        .getCategoryManager();
3512:
3513:                String name = componentElement.getName();
3514:                String typeName = componentElement.getType();
3515:                String directory = componentElement.getDir();
3516:                String pathName = directory + name;
3517:
3518:                ComponentMetainfoElement metainfoElement = componentElement
3519:                        .getMetainfoElement();
3520:                ComponentSecurityElement securityElement = metainfoElement
3521:                        .getSecurityElement();
3522:
3523:                List contentResourceElements = componentElement.getResources();
3524:                List templateResourceElements = componentElement
3525:                        .getTemplateResourceList();
3526:                boolean isFinal = new Boolean(metainfoElement.getIsFinal())
3527:                        .booleanValue();
3528:                String composedBlueprint = metainfoElement
3529:                        .getComposedBlueprint();
3530:                ComponentContextImpl context = (ComponentContextImpl) component
3531:                        .getComponentContext();
3532:
3533:                // change type if it has changed to a subtype of old one:
3534:                if (!typeName.equals(context.getTypeName())) {
3535:                    Type newType = componentFactory.getType(typeName);
3536:                    // XXX: do we allow subtypes which extend the actual type or only
3537:                    // restricted ones?
3538:                    if (componentFactory.isSubType(newType, context
3539:                            .getTypeName())) {
3540:                        context.setType(newType);
3541:                        context.setTypeName(typeName);
3542:                    } else {
3543:                        throw new ContelligentException(
3544:                                "Can not set new type '" + typeName
3545:                                        + "', is no subtype of old type!");
3546:                    }
3547:                }
3548:
3549:                Map properties = ComponentImport
3550:                        .createPropertyMapFromXML(componentElement);
3551:                Metadata metadata = context.getMetadata();
3552:                ComponentImport.loadMetadataFromXML(componentElement, metadata);
3553:
3554:                AccessControlList acl = null;
3555:
3556:                if (securityElement != null) {
3557:                    acl = ComponentImport.createACLfromXML(pathName,
3558:                            securityElement, this );
3559:                    context.setDefinesSecureTransfer(securityElement
3560:                            .definesSecureTransfer());
3561:                }
3562:
3563:                try {
3564:                    Set sensitiveTemplateCategories = ComponentImport
3565:                            .sensitiveCategoriesFromXML(componentElement
3566:                                    .getSensitiveTemplateCategories(),
3567:                                    categoryManager);
3568:                    Set sensitiveContentCategories = ComponentImport
3569:                            .sensitiveCategoriesFromXML(componentElement
3570:                                    .getSensitiveContentCategories(),
3571:                                    categoryManager);
3572:                    context.setIsFinal(isFinal);
3573:                    context.setComposedBlueprintName(composedBlueprint);
3574:                    if (acl != null) {
3575:                        context.setACL(acl);
3576:                    }
3577:                    context.setComponent(component);
3578:
3579:                    context
3580:                            .setSensitiveContentCategories(sensitiveContentCategories);
3581:                    context
3582:                            .setSensitiveTemplateCategories(sensitiveTemplateCategories);
3583:
3584:                    if (component instanceof  FileFacade) {
3585:                        log
3586:                                .debug("'"
3587:                                        + this .name
3588:                                        + "':updateComponent() - ... updating FileFacade '"
3589:                                        + component + "'");
3590:                        Iterator resources = contentResourceElements.iterator();
3591:                        while (resources.hasNext()) {
3592:                            ResourceElement resourceElement = (ResourceElement) resources
3593:                                    .next();
3594:                            if (resourceElement.isBinary()) {
3595:                                resources.remove(); // remove this resource so it is not
3596:                                // streamed into database
3597:                                String extension = resourceElement
3598:                                        .getExtension();
3599:                                properties.put("contentType", resourceElement
3600:                                        .getContentType());
3601:                                properties.put("extension", extension);
3602:                                String source = resourceElement.getSrc();
3603:                                FileItem sourceFile = callData
3604:                                        .getFileItem(source);
3605:                                if (sourceFile == null) {
3606:                                    log
3607:                                            .error("'"
3608:                                                    + this .name
3609:                                                    + "':updateComponent() - can not find file for FileFacade '"
3610:                                                    + component
3611:                                                    + "' and source '" + source
3612:                                                    + "'!");
3613:                                    throw new ContelligentException(
3614:                                            "Can not find file for FileFacade '"
3615:                                                    + component + "' source '"
3616:                                                    + source + "'!");
3617:                                }
3618:                                InputStream in = sourceFile.getInputStream();
3619:                                try {
3620:                                    StringBuffer fileName = new StringBuffer(
3621:                                            context.getPath().toPath());
3622:                                    if (extension != null
3623:                                            && extension.length() > 0) {
3624:                                        fileName.append('.').append(extension);
3625:                                    }
3626:                                    getFileAdapter().storeResourceFromStream(
3627:                                            fileName.toString(), in);
3628:                                } finally {
3629:                                    in.close();
3630:                                    in = null;
3631:                                }
3632:                            }
3633:                        }
3634:                    }
3635:
3636:                    Map changedResources;
3637:                    Iterator iterator = null;
3638:
3639:                    changedResources = createResources(contentResourceElements,
3640:                            sensitiveContentCategories, callData);
3641:
3642:                    iterator = changedResources.entrySet().iterator();
3643:                    while (iterator.hasNext()) {
3644:                        Map.Entry entry = (Map.Entry) iterator.next();
3645:                        if (entry.getValue() instanceof  Resource) {
3646:                            context.setContentResource((String) entry.getKey(),
3647:                                    (Resource) entry.getValue());
3648:                        } else {
3649:                            context.removeContentResource((String) entry
3650:                                    .getKey());
3651:                        }
3652:                    }
3653:
3654:                    changedResources = createResources(
3655:                            templateResourceElements,
3656:                            sensitiveTemplateCategories, callData);
3657:
3658:                    iterator = changedResources.entrySet().iterator();
3659:                    while (iterator.hasNext()) {
3660:                        Map.Entry entry = (Map.Entry) iterator.next();
3661:                        if (entry.getValue() instanceof  Resource) {
3662:                            context.setTemplateResource(
3663:                                    (String) entry.getKey(), (Resource) entry
3664:                                            .getValue());
3665:                        } else {
3666:                            context.removeTemplateResource((String) entry
3667:                                    .getKey());
3668:                        }
3669:                    }
3670:
3671:                    if (!properties.isEmpty()) {
3672:                        context.getType().setProperties(
3673:                                component,
3674:                                context.getType().getProperties(properties,
3675:                                        false));
3676:                    }
3677:
3678:                    ComponentPath path = new ComponentPath(pathName);
3679:
3680:                    context.setModifiedBy(callData.getContelligentSession()
3681:                            .getUser());
3682:
3683:                    if (isRoot() || componentExists(path, false)
3684:                            || componentAdapter.deleted(path)
3685:                            || checkDeleted(path)) {
3686:                        updateWrapper(context);
3687:                    } else {
3688:                        context.setPersistenceManager(this );
3689:                        componentAdapter.create(context);
3690:                    }
3691:                    relationsManager.updateRelations(component, ThreadedMem
3692:                            .getCallData(), false);
3693:                    if (!isImport()) {
3694:                        checkRelationsOfComponent(path, false, callData);
3695:                    }
3696:                } catch (UnknownTypeException ute) {
3697:                    throw new ContelligentException("Type '" + typeName
3698:                            + "' could not be retrieved.", ute);
3699:                } catch (TypeException te) {
3700:                    throw new ContelligentException(
3701:                            ContelligentExceptionID.persistence_propertyNotSet,
3702:                            te);
3703:                } catch (CategoryException ce) {
3704:                    throw new ContelligentException(
3705:                            "Sensitive categories could not be converted.", ce);
3706:                } catch (IOException e) {
3707:                    throw new ContelligentException(
3708:                            "Could not read resource content.", e);
3709:                }
3710:            }
3711:
3712:            final public void createComponent(
3713:                    ComponentElement componentElement, CallData callData)
3714:                    throws ContelligentException {
3715:                ComponentPath componentPath = getComponentPath(componentElement);
3716:
3717:                if (componentExists(componentPath)) {
3718:                    throw new ComponentAlreadyExistsException(componentPath);
3719:                }
3720:
3721:                Component component = getComponent(componentPath.parentPath(),
3722:                        callData);
3723:
3724:                if (!(component instanceof  Container)) {
3725:                    throw new ContelligentException(
3726:                            ContelligentExceptionID.component_noContainer,
3727:                            new Object[] { componentPath.parentPath().toPath() });
3728:                }
3729:                Container parent = (Container) component;
3730:                String typeName = componentElement.getType();
3731:
3732:                ComponentMetainfoElement metainfoElement = componentElement
3733:                        .getMetainfoElement();
3734:                ComponentSecurityElement securityElement = metainfoElement
3735:                        .getSecurityElement();
3736:                AccessControlList acl = null;
3737:                Type type = componentFactory.getType(typeName); // throws
3738:                // UnknownTypeException
3739:                Map properties = ComponentImport
3740:                        .createPropertyMapFromXML(componentElement);
3741:                Metadata metadata = component.getComponentContext()
3742:                        .getMetadata();
3743:                ComponentImport.loadMetadataFromXML(componentElement, metadata);
3744:
3745:                if (securityElement != null) {
3746:                    acl = ComponentImport.createACLfromXML(componentPath
3747:                            .toPath(), securityElement, this );
3748:                }
3749:                // use converted property-map:
3750:                Component answer = createComponent(parent, componentPath
3751:                        .getName(), type,
3752:                        type.getProperties(properties, false), acl, false,
3753:                        false, callData);
3754:                // no postCreate(), no update of relations
3755:                updateComponent(answer, componentElement, callData);
3756:                String name = ComponentImport.loadBasicPublisherFromXML(
3757:                        componentElement, componentPath);
3758:                if (name.length() > 0) {
3759:                    ComponentDBAdapter adapter = (ComponentDBAdapter) getComponentPersistenceAdapter();
3760:                    adapter.certifyComponentBasic(name, componentPath, false);
3761:                }
3762:            }
3763:
3764:            final protected ComponentPath getComponentPath(
3765:                    ComponentElement componentElement) {
3766:                return new ComponentPath(componentElement.getDir()
3767:                        + componentElement.getName());
3768:            }
3769:
3770:            final private Map createResources(Collection resourceElements,
3771:                    Collection sensitiveCategories, CallData callData)
3772:                    throws IOException, ContelligentException {
3773:                Map resources = new HashMap();
3774:                CategoryManager categoryManager = contelligent
3775:                        .getCategoryManager();
3776:                long currentTime = TimeService.getInstance()
3777:                        .currentTimeMillis();
3778:
3779:                for (Iterator i = resourceElements.iterator(); i.hasNext();) {
3780:                    ResourceElement resourceElement = (ResourceElement) i
3781:                            .next();
3782:                    Map supportedCategories = resourceElement
3783:                            .getSupportedCategories();
3784:                    boolean isResourceAccessible = true;
3785:                    for (Iterator j = sensitiveCategories.iterator(); j
3786:                            .hasNext();) {
3787:                        CategorySubset css = (CategorySubset) j.next();
3788:                        if (!supportedCategories.containsKey(css.getName())) {
3789:                            // Found a sensitive category name which is not supported by
3790:                            // this resource
3791:                            isResourceAccessible = false;
3792:                        } else {
3793:                            String[] sensitiveValues = css.getSupportedValues();
3794:                            boolean found = false;
3795:                            String supportedValue = (String) supportedCategories
3796:                                    .get(css.getName());
3797:                            for (int k = 0; k < sensitiveValues.length; k++) {
3798:                                if (supportedValue.equals(sensitiveValues[k])) {
3799:                                    found = true;
3800:                                }
3801:                            }
3802:                            if (!found) {
3803:                                // Found a supported category value which is not a valid
3804:                                // sensitive value (Yes, this is supposed to be checked
3805:                                // the other way around than the category name check
3806:                                // above)
3807:                                isResourceAccessible = false;
3808:                            }
3809:                        }
3810:                    }
3811:                    if (isResourceAccessible) {
3812:                        // Only add the resource if the supported categories on the
3813:                        // resource would result in the resource being accessible from
3814:                        // the sensitive category declared on the component level.
3815:                        String categoryIdentifier = categoryManager
3816:                                .createUniqueCategoryIdentifier(
3817:                                        sensitiveCategories,
3818:                                        supportedCategories);
3819:                        String contentType = resourceElement.getContentType();
3820:                        String extension = resourceElement.getExtension();
3821:                        String source = resourceElement.getSrc();
3822:                        String data = resourceElement.getData();
3823:                        String constraints = resourceElement.getConstraints();
3824:                        Resource resource = null;
3825:
3826:                        if (resourceElement.isBinary()) {
3827:                            InputStream in = null;
3828:                            long length = 0L;
3829:
3830:                            FileItem item = callData.getFileItem(source);
3831:
3832:                            if (item == null) {
3833:                                in = getFileAdapter().getResourceAsStream(
3834:                                        source);
3835:                                length = getFileAdapter()
3836:                                        .getResourceStreamLength(source);
3837:                            } else {
3838:                                in = item.getInputStream();
3839:                                length = item.getSize();
3840:                            }
3841:
3842:                            resource = new BinaryResource(in, contentType,
3843:                                    extension, currentTime, (int) length);
3844:                        } else if (resourceElement.isNumber()) {
3845:                            Number number = new BigDecimal(data);
3846:
3847:                            resource = new NumberResource(number, currentTime);
3848:                        } else if (resourceElement.isText()) {
3849:                            if (source != null) {
3850:                                InputStream in = null;
3851:                                long length = 0L;
3852:
3853:                                FileItem item = callData.getFileItem(source);
3854:
3855:                                if (item == null) {
3856:                                    in = getFileAdapter().getResourceAsStream(
3857:                                            source);
3858:                                } else {
3859:                                    in = item.getInputStream();
3860:                                }
3861:
3862:                                resource = new TextResource(in, currentTime);
3863:                            } else {
3864:                                resource = new TextResource(data, currentTime);
3865:                            }
3866:                        } else if (resourceElement.isString()) {
3867:                            resource = new StringResource(data, currentTime);
3868:                        } else if (resourceElement.isInvalidated()) {
3869:                            resource = null;
3870:                        } else {
3871:                            // The resource type is unknown.
3872:                            throw new ContelligentException(
3873:                                    "Unknown resource type");
3874:                        }
3875:                        if (resource != null) {
3876:                            resource.setConstraints(constraints);
3877:                            resources.put(categoryIdentifier, resource);
3878:                        } else {
3879:                            // Dummy value to force deletion of invalidated resources
3880:                            // from the database.
3881:                            resources.put(categoryIdentifier, "");
3882:                        }
3883:                    } else {
3884:                        // Dummy value to force deletion of invalidated resources
3885:                        // from the database.
3886:                        String categoryIdentifier = categoryManager
3887:                                .createUniqueCategoryIdentifier(
3888:                                        sensitiveCategories,
3889:                                        supportedCategories);
3890:                        resources.put(categoryIdentifier, "");
3891:                    }
3892:                }
3893:                return resources;
3894:            }
3895:
3896:            /**
3897:             * Implementation of {@link ComponentManager#isInstanceOf}.
3898:             */
3899:            final public boolean isInstanceOf(Component component,
3900:                    String typeName) {
3901:                Type type = component.getComponentContext().getType();
3902:                if (type.getName().equals(typeName)) {
3903:                    return true;
3904:                }
3905:                return componentFactory.isSubType(type, typeName);
3906:            }
3907:
3908:            final protected boolean isInstanceOf(ComponentPath path,
3909:                    String typeName) throws ComponentPersistenceException {
3910:                String type = componentAdapter.getTypeOfComponent(path);
3911:                if (type.equals(typeName)) {
3912:                    return true;
3913:                }
3914:
3915:                return componentFactory.isSubType(componentFactory
3916:                        .getType(type), typeName);
3917:            }
3918:
3919:            final private User getSystemUser() {
3920:                return ContelligentSecurityManager.getSystemUser();
3921:            }
3922:
3923:            public final void setComponentFinal(ComponentPath path,
3924:                    boolean finalFlag, CallData callData)
3925:                    throws ComponentNotFoundException,
3926:                    ModificationVetoException, ComponentPersistenceException,
3927:                    ComponentLockException {
3928:                boolean locked = lockComponent(path, callData);
3929:                try {
3930:                    Component component = cloneComponent(path, callData);
3931:                    ComponentContextImpl context = (ComponentContextImpl) component
3932:                            .getComponentContext();
3933:
3934:                    context.setIsFinal(finalFlag);
3935:                    context.setModifiedBy(callData.getContelligentSession()
3936:                            .getUser());
3937:                    updateWrapper(context);
3938:                    fireChangeEvent(component);
3939:                } finally {
3940:                    if (locked) {
3941:                        unlockComponent(path, callData);
3942:                    }
3943:                }
3944:            }
3945:
3946:            public void validateBlueprintTypes() throws TypeException {
3947:                componentFactory.validateBlueprintTypes(this );
3948:            }
3949:
3950:            public Collection getDeletedComponents()
3951:                    throws ComponentPersistenceException {
3952:                if (isRoot()) {
3953:                    return Collections.EMPTY_SET;
3954:                }
3955:                return componentAdapter.getDeletedComponents();
3956:            }
3957:
3958:            public Collection getModifiedComponents(
3959:                    boolean filterBlueprintSubComponents)
3960:                    throws ComponentPersistenceException {
3961:                if (isRoot()) {
3962:                    return Collections.EMPTY_SET;
3963:                }
3964:                Collection answer = componentAdapter.getModifiedComponents();
3965:                if (filterBlueprintSubComponents) {
3966:                    ComponentManager parentCM = getParent();
3967:                    Iterator iterator = componentAdapter
3968:                            .getNewOrModifiedBlueprintInstances().iterator();
3969:
3970:                    while (iterator.hasNext()) {
3971:                        ComponentPath componentPath = (ComponentPath) iterator
3972:                                .next();
3973:
3974:                        if (!parentCM.componentExists(componentPath)) {
3975:                            Iterator subcomponents = componentAdapter
3976:                                    .getLocalComponentNames(componentPath)
3977:                                    .iterator();
3978:                            while (subcomponents.hasNext()) {
3979:                                ComponentDBPathHolder pathHolder = (ComponentDBPathHolder) subcomponents
3980:                                        .next();
3981:                                answer.remove(pathHolder.getPath());
3982:                            }
3983:                            answer.add(componentPath);
3984:                        }
3985:                    }
3986:                }
3987:                return answer;
3988:            }
3989:
3990:            /**
3991:             * Use of this method is permitted for afterCompletion only!!!
3992:             * 
3993:             * @param path
3994:             */
3995:            void invalidatePath(ComponentPath path, boolean includeSubtree) {
3996:
3997:            }
3998:
3999:            public void invalidateCache(ComponentPath path) {
4000:                invalidatePath(path, true);
4001:            }
4002:
4003:            public SystemIndex getSystemIndex() {
4004:                return systemIndex;
4005:            }
4006:
4007:            public void setSkipListener(boolean b) {
4008:                if (listener == null) {
4009:                    return;
4010:                }
4011:                listener.setSkip(b);
4012:            }
4013:
4014:            public void invalidateTypes() {
4015:                componentFactory.invalidateTypes();
4016:            }
4017:
4018:            public void setReadOnlyPaths(Set readOnlyPaths) {
4019:                this .readOnlyPaths = new HashSet(readOnlyPaths);
4020:            }
4021:
4022:            final public void changeTypeOfBlueprintInstance(ComponentPath path,
4023:                    String typeName, CallData callData)
4024:                    throws ContelligentException, ComponentNotFoundException,
4025:                    ModificationVetoException {
4026:                Component component = getComponent(path, callData);
4027:                Type type = component.getComponentContext().getType();
4028:
4029:                if (!type.isBlueprint()) {
4030:                    throw new ContelligentException(
4031:                            ContelligentExceptionID.component_morph_noBlueprint,
4032:                            new Object[] { path.toPath() });
4033:                }
4034:                Type newType = componentFactory.getType(typeName);
4035:                if (!newType.isBlueprint()) {
4036:                    throw new ContelligentException(
4037:                            ContelligentExceptionID.component_morph_noBlueprintType,
4038:                            new Object[] { typeName, path.toPath() });
4039:                }
4040:                if (!getComponent(type.getBlueprintPath(), callData)
4041:                        .getComponentContext().getType().equals(
4042:                                getComponent(newType.getBlueprintPath(),
4043:                                        callData).getComponentContext()
4044:                                        .getType())) {
4045:                    throw new ContelligentException(
4046:                            ContelligentExceptionID.component_morph_incompatibleTypes,
4047:                            new Object[] { typeName, type.getName(),
4048:                                    path.toPath() });
4049:                }
4050:
4051:                boolean locked = lockComponent(path, callData);
4052:                try {
4053:                    Component clone = cloneComponent(component);
4054:                    ComponentContextImpl context = (ComponentContextImpl) clone
4055:                            .getComponentContext();
4056:                    context.setType(newType);
4057:                    context.setModifiedBy(callData.getContelligentSession()
4058:                            .getUser());
4059:
4060:                    if (isRoot() || componentExists(path, false)) {
4061:                        updateWrapper(context);
4062:                    } else {
4063:                        componentAdapter.create(context);
4064:                    }
4065:                    fireChangeEvent(clone);
4066:                } finally {
4067:                    if (locked) {
4068:                        unlockComponent(path, callData);
4069:                    }
4070:                }
4071:            }
4072:
4073:            final public void addToAllBlueprintInstances(ComponentPath path,
4074:                    CallData callData) throws ContelligentException {
4075:                if (componentFactory.isBlueprintPath(path)) {
4076:                    return;
4077:                }
4078:                ComponentPath blueprintRootPath = path;
4079:                while (!componentFactory.isBlueprintPath(blueprintRootPath)) {
4080:                    if (blueprintRootPath.isRoot()) {
4081:                        throw new ContelligentException(
4082:                                ContelligentExceptionID.component_not_in_blueprint,
4083:                                new Object[] { path.toPath() });
4084:                    }
4085:                    blueprintRootPath = blueprintRootPath.parentPath();
4086:                }
4087:                ComponentPath relative = path.toRelativePath(blueprintRootPath);
4088:                String blueprintType = componentFactory.getBlueprintType(
4089:                        blueprintRootPath).getName();
4090:                Collection instances = getInstancesOfType(
4091:                        ComponentPath.ROOT_PATH, blueprintType);
4092:                Iterator iterator = instances.iterator();
4093:
4094:                while (iterator.hasNext()) {
4095:                    ComponentPath instancePath = (ComponentPath) iterator
4096:                            .next();
4097:                    ComponentPath targetPath = instancePath.append(relative);
4098:                    try {
4099:                        copyComponentTree(callData, path, targetPath
4100:                                .parentPath(), targetPath.getName());
4101:                    } catch (ComponentAlreadyExistsException caee) {
4102:                        // Subcomponent already exists here, so we can just skip
4103:                        // over this instance
4104:                    }
4105:                }
4106:            }
4107:
4108:            private ComponentPath getReadOnlyRoot(ComponentPath path) {
4109:                Iterator iterator = readOnlyPaths.iterator();
4110:                while (iterator.hasNext()) {
4111:                    ComponentPath componentPath = (ComponentPath) iterator
4112:                            .next();
4113:
4114:                    if (path.isSubPathOf(componentPath)
4115:                            || path.equals(componentPath)) {
4116:                        return componentPath;
4117:                    }
4118:                }
4119:                return null;
4120:            }
4121:
4122:            protected void checkContainsReadOnly(final ComponentPath path) {
4123:                checkReadOnly(path);
4124:                Iterator iterator = readOnlyPaths.iterator();
4125:                while (iterator.hasNext()) {
4126:                    ComponentPath componentPath = (ComponentPath) iterator
4127:                            .next();
4128:                    if (componentPath.isSubPathOf(path)) {
4129:                        throw new ContelligentSecurityException(
4130:                                ContelligentExceptionID.security_readOnly,
4131:                                new Object[] { componentPath });
4132:                    }
4133:                }
4134:            }
4135:
4136:            public boolean isReadOnly(ComponentPath path) {
4137:                try {
4138:                    checkReadOnly(path);
4139:                } catch (ContelligentSecurityException cse) {
4140:                    return true;
4141:                }
4142:                return false;
4143:            }
4144:
4145:            public boolean containsReadOnly(ComponentPath path) {
4146:                try {
4147:                    checkContainsReadOnly(path);
4148:                } catch (ContelligentSecurityException cse) {
4149:                    return true;
4150:                }
4151:                return false;
4152:            }
4153:
4154:            final public void cleanUpBlueprintInstances(ComponentPath path,
4155:                    CallData callData) throws ContelligentException {
4156:                Collection blueprintInstances;
4157:                Component blueprint;
4158:
4159:                if (componentFactory.isBlueprintPath(path)) {
4160:                    blueprintInstances = getInstancesOfType(
4161:                            ComponentPath.ROOT_PATH, componentFactory
4162:                                    .getBlueprintType(path).getName());
4163:                    blueprint = getComponent(path, callData);
4164:                } else {
4165:                    Component comp = getComponent(path, callData);
4166:                    Type type = comp.getComponentContext().getType();
4167:
4168:                    if (!type.isBlueprint()) {
4169:                        throw new ContelligentException(
4170:                                ContelligentExceptionID.component_no_blueprint_instance,
4171:                                new Object[] { path.toPath() });
4172:                    }
4173:                    blueprint = getComponent(type.getBlueprintPath(), callData);
4174:                    blueprintInstances = new ArrayList(1);
4175:                    blueprintInstances.add(path);
4176:                }
4177:                Set relativeBlueprintSubcomponents = new HashSet();
4178:                ComponentPath blueprintPath = blueprint.getComponentContext()
4179:                        .getPath();
4180:                Iterator iterator = componentAdapter.getAllSubComponentPaths(
4181:                        blueprintPath).iterator();
4182:
4183:                while (iterator.hasNext()) {
4184:                    ComponentPath componentPath = new ComponentPath(
4185:                            (String) iterator.next());
4186:                    relativeBlueprintSubcomponents.add(componentPath
4187:                            .toRelativePath(blueprintPath));
4188:                }
4189:
4190:                Iterator instances = blueprintInstances.iterator();
4191:
4192:                while (instances.hasNext()) {
4193:                    ComponentPath instancePath = (ComponentPath) instances
4194:                            .next();
4195:                    // Only check direct children of the instance
4196:                    Iterator subcomponents = getSubcomponentNames(
4197:                            (Container) getComponent(instancePath, callData))
4198:                            .iterator();
4199:
4200:                    while (subcomponents.hasNext()) {
4201:                        ComponentPath subComponentPath = instancePath
4202:                                .append((String) subcomponents.next());
4203:                        ComponentPath relative = subComponentPath
4204:                                .toRelativePath(instancePath);
4205:                        if (!relativeBlueprintSubcomponents.contains(relative)) {
4206:                            if (componentExists(subComponentPath)) {
4207:                                deleteComponentTree(callData, subComponentPath);
4208:                            }
4209:                        }
4210:                    }
4211:                }
4212:            }
4213:
4214:            protected void checkReadOnly(final ComponentPath path) {
4215:                ComponentPath readOnlyRoot = getReadOnlyRoot(path);
4216:
4217:                if (readOnlyRoot != null) {
4218:                    throw new ContelligentSecurityException(
4219:                            ContelligentExceptionID.security_readOnly,
4220:                            new Object[] { readOnlyRoot });
4221:                }
4222:            }
4223:
4224:            ComponentFactory getComponentFactory() {
4225:                return componentFactory;
4226:            }
4227:
4228:            /*
4229:             * (non-Javadoc)
4230:             * 
4231:             * @see de.finix.contelligent.ComponentManager#getTypesInSubTree(de.finix.contelligent.ComponentPath)
4232:             */
4233:            public Collection getTypesInSubTree(ComponentPath topMostPath)
4234:                    throws ComponentSystemException {
4235:                ComponentPersistenceAdapter adapter = getComponentPersistenceAdapter();
4236:                Set typeSet = new HashSet();
4237:                try {
4238:                    Collection typeNameList = adapter
4239:                            .getTypeNamesInSubTree(topMostPath);
4240:                    Iterator i = typeNameList.iterator();
4241:
4242:                    while (i.hasNext()) {
4243:                        String typeName = (String) i.next();
4244:                        Type type = componentFactory.getType(typeName);
4245:                        typeSet.add(type);
4246:                    }
4247:                } catch (ComponentPersistenceException e) {
4248:                    Object info[] = new Object[] { topMostPath.toPath() };
4249:                    ComponentSystemException e1 = new ComponentSystemException(
4250:                            ContelligentExceptionID.type_fromSubtree, info, e);
4251:                    throw e1;
4252:                }
4253:                return typeSet;
4254:            }
4255:
4256:            public List selectMetaContent(Component root,
4257:                    ComponentPath relative, String key, String value,
4258:                    String comparator) throws ComponentPersistenceException {
4259:                ComponentDBAdapter adapter = (ComponentDBAdapter) getComponentPersistenceAdapter();
4260:                return adapter.selectMetaContent(root, relative, key, value,
4261:                        comparator);
4262:            }
4263:
4264:            public List selectComponentsByName(Component root, String name)
4265:                    throws ComponentPersistenceException {
4266:                ComponentDBAdapter adapter = (ComponentDBAdapter) getComponentPersistenceAdapter();
4267:                return adapter.selectComponentsByName(root, name);
4268:            }
4269:
4270:            public long getSubtreeSize(Component subTree)
4271:                    throws ComponentPersistenceException {
4272:                ComponentDBAdapter adapter = (ComponentDBAdapter) getComponentPersistenceAdapter();
4273:                return adapter.getSubtreeSize((ComponentContextImpl) subTree
4274:                        .getComponentContext());
4275:            }
4276:
4277:            public long getSubtreeComponents(Component subTree)
4278:                    throws ComponentPersistenceException {
4279:                ComponentDBAdapter adapter = (ComponentDBAdapter) getComponentPersistenceAdapter();
4280:                return adapter
4281:                        .getSubtreeComponents((ComponentContextImpl) subTree
4282:                                .getComponentContext());
4283:            }
4284:
4285:            public void certifyComponent(String name, String key, int type,
4286:                    boolean subTree, ComponentPath path, CallData callData)
4287:                    throws NoWritePermissionException,
4288:                    ComponentNotFoundException {
4289:                Component component = getComponent(path, callData);
4290:                final ContelligentPrincipal caller = callData
4291:                        .getContelligentSession().getUser();
4292:                if (!callerHasPermission(caller, callData, component,
4293:                        ComponentPermission.WRITE)) {
4294:                    log.warn("'" + this .name
4295:                            + "':certifyComponent() - caller '" + caller
4296:                            + "' has no write access for component '"
4297:                            + component + "'!");
4298:                    throw new NoWritePermissionException(caller, component
4299:                            .getComponentContext().getPath());
4300:                }
4301:                ComponentDBAdapter adapter = (ComponentDBAdapter) getComponentPersistenceAdapter();
4302:                if (type == CERT_BASIC) {
4303:                    try {
4304:                        String hashText = "[c1contell19]" + name;
4305:                        if (!key.equals(StringHash.getHash(hashText))) {
4306:                            // Invalid key
4307:                            throw new ContelligentRuntimeException(
4308:                                    "Invalid data.");
4309:                        }
4310:                        log.info("Begin cert now...");
4311:                        adapter.certifyComponentBasic(name, path, subTree);
4312:                        invalidateCache(path);
4313:                        addEvent(new ComponentEvent(ComponentEvent.CHANGE,
4314:                                path, getName()));
4315:                        log.info("Cert successful!");
4316:                    } catch (Exception e) {
4317:                        throw new ContelligentRuntimeException(
4318:                                "Certification failed.", e);
4319:                    }
4320:                } else if (type == CERT_USER) {
4321:                    try {
4322:                        adapter.certifyComponentUser(
4323:                                caller.toPrincipalString(), path, subTree);
4324:                        invalidateCache(path);
4325:                        addEvent(new ComponentEvent(ComponentEvent.CHANGE,
4326:                                path, getName()));
4327:                    } catch (Exception e) {
4328:                        throw new ContelligentRuntimeException(
4329:                                "Signing failed.", e);
4330:                    }
4331:                } else {
4332:                    // TODO: Add "signed" cert type
4333:                    throw new ContelligentRuntimeException(
4334:                            "Unsupported certification type.");
4335:                }
4336:            }
4337:
4338:            public int getMaxCacheSize() {
4339:                return 0;
4340:            }
4341:
4342:            public void setMaxCacheSize(int maxSize) {
4343:            }
4344:
4345:            public int getActualCacheSize() {
4346:                return 0;
4347:            }
4348:
4349:            public long getCacheCalls() {
4350:                return 0;
4351:            }
4352:
4353:            public long getCacheMisses() {
4354:                return 0;
4355:            }
4356:
4357:            /**
4358:             * Wraps componentAdapter.update() call so that subclasses can do
4359:             * centralized error handling for this call.
4360:             */
4361:            protected void updateWrapper(ComponentContextImpl ctx)
4362:                    throws ComponentPersistenceException {
4363:                componentAdapter.update(ctx);
4364:            }
4365:
4366:            /**
4367:             * @return
4368:             */
4369:            public SystemIndexer getSystemIndexer() {
4370:                return this.listener;
4371:            }
4372:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.