protected Resource deepGetOrCreateResource()

in src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCreateOperation.java [517:602]


    protected Resource deepGetOrCreateResource(
            final ResourceResolver resolver,
            final String path,
            final Map<String, RequestProperty> reqProperties,
            final List<Modification> changes,
            final VersioningConfiguration versioningConfiguration)
            throws PersistenceException {
        if (log.isDebugEnabled()) {
            log.debug("Deep-creating resource '{}'", path);
        }
        if (path == null || !path.startsWith("/")) {
            throw new IllegalArgumentException("path must be an absolute path.");
        }
        // get the starting resource
        String startingResourcePath = path;
        Resource startingResource = null;
        while (startingResource == null) {
            if (startingResourcePath.equals("/")) {
                startingResource = resolver.getResource("/");
                if (startingResource == null) {
                    throw new PersistenceException(
                            "Access denied for root resource, resource can't be created: " + path);
                }
            } else {
                final Resource r = resolver.getResource(startingResourcePath);
                if (r != null && !ResourceUtil.isSyntheticResource(r)) {
                    startingResource = resolver.getResource(startingResourcePath);
                    updateNodeType(resolver, startingResourcePath, reqProperties, changes, versioningConfiguration);
                    updateMixins(resolver, startingResourcePath, reqProperties, changes, versioningConfiguration);
                } else {
                    int pos = startingResourcePath.lastIndexOf('/');
                    if (pos > 0) {
                        startingResourcePath = startingResourcePath.substring(0, pos);
                    } else {
                        startingResourcePath = "/";
                    }
                }
            }
        }
        // is the searched resource already existing?
        if (startingResourcePath.length() == path.length()) {
            return startingResource;
        }
        // create nodes
        int from = (startingResourcePath.length() == 1 ? 1 : startingResourcePath.length() + 1);
        Resource resource = startingResource;
        while (from > 0) {
            final int to = path.indexOf('/', from);
            final String name = to < 0 ? path.substring(from) : path.substring(from, to);
            // although the resource should not exist (according to the first test
            // above)
            // we do a sanety check.
            final Resource child = resource.getChild(name);
            if (child != null && !ResourceUtil.isSyntheticResource(child)) {
                resource = child;
                updateNodeType(resolver, resource.getPath(), reqProperties, changes, versioningConfiguration);
                updateMixins(resolver, resource.getPath(), reqProperties, changes, versioningConfiguration);
            } else {
                final String tmpPath = to < 0 ? path : path.substring(0, to);
                // check for node type
                final String nodeType = getPrimaryType(reqProperties, tmpPath);

                this.jcrSupport.checkoutIfNecessary(resource, changes, versioningConfiguration);

                try {
                    final Map<String, Object> props = new HashMap<>();
                    if (nodeType != null) {
                        props.put("jcr:primaryType", nodeType);
                    }
                    // check for mixin types
                    final String[] mixinTypes = getMixinTypes(reqProperties, tmpPath);
                    if (mixinTypes != null) {
                        props.put("jcr:mixinTypes", mixinTypes);
                    }

                    resource = resolver.create(resource, name, props);
                } catch (final PersistenceException e) {
                    log.error("Unable to create resource named " + name + " in " + resource.getPath());
                    throw e;
                }
                changes.add(Modification.onCreated(resource.getPath()));
            }
            from = to + 1;
        }
        return resource;
    }