private void internalResourceAddedOrUpdated()

in src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java [1144:1313]


    private void internalResourceAddedOrUpdated(final String resourceType,
            final String entityId,
            final ResourceData data,
            final Dictionary<String, Object> dict,
            final Map<String, Object> attributes) {
        final String key = resourceType + ':' + entityId;
        final boolean persistChange = attributes != null
                ? Converters.standardConverter().convert(attributes.get(ResourceChangeListener.RESOURCE_PERSIST))
                        .defaultValue(Boolean.TRUE).to(Boolean.class)
                : true;
        try {
            boolean compactAndSave = false;
            boolean done = false;

            synchronized ( this.resourcesLock ) {
                final EntityResourceList erl = this.persistentList.getEntityResourceList(key);
                logger.debug("Added or updated {} : {}", key, erl);

                // we first check for update
                if ( erl != null && erl.getFirstResource() != null ) {
                    // check digest for dictionaries
                    final TaskResource tr = erl.getFirstResource();
                    if ( dict != null ) {
                        final String digest = FileDataStore.computeDigest(dict);
                        if ( tr.getDigest().equals(digest) ) {
                            if ( tr.getState() == ResourceState.INSTALLED  ) {
                                logger.debug("Resource did not change {}", key);
                            } else if ( tr.getState() == ResourceState.INSTALL
                                || tr.getState() == ResourceState.IGNORED ) {
                                erl.setForceFinishState(ResourceState.INSTALLED, null);
                                compactAndSave = true;
                            }
                            done = true;
                        }
                    }

                    final UpdateHandler handler;
                    if ( !done && persistChange ) {
                        handler = this.findHandler(tr.getScheme());
                        if ( handler == null ) {
                            logger.debug("No handler found to handle update of resource with scheme {}", tr.getScheme());
                        }
                    } else {
                        handler = null;
                    }

                    if ( !done && handler == null ) {
                        compactAndSave = this.handleExternalUpdateWithoutWriteBack(erl);
                        done = true;
                    }

                    if ( !done ) {
                        final InputStream localIS = data.getInputStream();
                        try {
                            final UpdateResult result = (localIS == null ? handler.handleUpdate(resourceType, entityId, tr.getURL(), data.getDictionary(), attributes)
                                    : handler.handleUpdate(resourceType, entityId, tr.getURL(), localIS, attributes));
                            if ( result != null ) {
                                if ( !result.getURL().equals(tr.getURL()) && !result.getResourceIsMoved() ) {
                                    // resource has been added!
                                    final InternalResource internalResource = new InternalResource(result.getScheme(),
                                            result.getResourceId(),
                                            null,
                                            data.getDictionary(),
                                            (data.getDictionary() != null ? InstallableResource.TYPE_PROPERTIES : InstallableResource.TYPE_FILE),
                                            data.getDigest(result.getURL(), result.getDigest()),
                                            result.getPriority(),
                                            data.getDataFile(),
                                            null);
                                    final RegisteredResource rr = this.persistentList.addOrUpdate(internalResource);
                                    final TransformationResult transRes = new TransformationResult();
                                    // use the old entity id
                                    final int pos = erl.getResourceId().indexOf(':');
                                    transRes.setId(erl.getResourceId().substring(pos + 1));
                                    transRes.setResourceType(resourceType);
                                    if ( attributes != null ) {
                                        transRes.setAttributes(attributes);
                                    }
                                    this.persistentList.transform(rr, new TransformationResult[] {
                                            transRes
                                    });
                                    final EntityResourceList newGroup = this.persistentList.getEntityResourceList(key);
                                    newGroup.setFinishState(ResourceState.INSTALLED, null);
                                    newGroup.compact();
                                } else {
                                    // resource has been updated or moved
                                    ((RegisteredResourceImpl)tr).update(
                                            data.getDataFile(), data.getDictionary(),
                                            data.getDigest(result.getURL(), result.getDigest()),
                                            result.getPriority(),
                                            result.getURL());
                                    erl.setForceFinishState(ResourceState.INSTALLED, null);
                                }
                                compactAndSave = true;
                            } else {
                                // handler does not persist
                                compactAndSave = this.handleExternalUpdateWithoutWriteBack(erl);
                            }
                        } finally {
                            if ( localIS != null ) {
                                // always close the input stream!
                                try {  localIS.close(); } catch (final IOException ignore) {
                                    // ignore
                                }
                            }
                        }
                        done = true;
                    }
                }

                if ( !done && persistChange) {
                    // create
                    final List<UpdateHandler> handlerList = this.updateHandlerTracker.getSortedServices();
                    for(final UpdateHandler handler : handlerList) {
                        final InputStream localIS = data.getInputStream();
                        try {
                            final UpdateResult result = (localIS == null ? handler.handleUpdate(resourceType, entityId, null, data.getDictionary(), attributes)
                                    : handler.handleUpdate(resourceType, entityId, null, localIS, attributes));
                            if ( result != null ) {
                                final InternalResource internalResource = new InternalResource(result.getScheme(),
                                        result.getResourceId(),
                                        null,
                                        data.getDictionary(),
                                        (data.getDictionary() != null ? InstallableResource.TYPE_PROPERTIES : InstallableResource.TYPE_FILE),
                                        data.getDigest(result.getURL(), result.getDigest()),
                                        result.getPriority(),
                                        data.getDataFile(),
                                        null);
                                final RegisteredResource rr = this.persistentList.addOrUpdate(internalResource);
                                final TransformationResult transRes = new TransformationResult();
                                transRes.setId(entityId);
                                transRes.setResourceType(resourceType);
                                if ( attributes != null ) {
                                    transRes.setAttributes(attributes);
                                }
                                this.persistentList.transform(rr, new TransformationResult[] {
                                        transRes
                                });
                                final EntityResourceList newGroup = this.persistentList.getEntityResourceList(key);
                                newGroup.setFinishState(ResourceState.INSTALLED);
                                newGroup.compact();
                                compactAndSave = true;
                                done = true;
                                break;
                            }
                        } finally {
                            if ( localIS != null ) {
                                // always close the input stream!
                                try {
                                    localIS.close();
                                } catch (final IOException ignore) {
                                    // ignore
                                }
                            }
                        }
                    }
                    if ( !done ) {
                        logger.debug("No handler found to handle creation of resource {}", key);
                    }
                }
                if ( compactAndSave ) {
                    if ( erl != null ) {
                        erl.compact();
                    }
                    this.persistentList.save();
                }
            }
        } catch (final IOException ioe) {
            logger.error("Unable to handle resource add or update of " + key, ioe);
        }
    }