All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sling.installer.api.InstallableResource Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.sling.installer.api;

import java.io.InputStream;
import java.util.Dictionary;


/**
 * A piece of data that can be installed by the {@link OsgiInstaller}
 * Currently the OSGi installer supports bundles and configurations,
 * but it can be extended by additional task factories supporting
 * other formats.
 *
 * The installable resource contains as much information as the client
 * can provide. An input stream or dictionary is mandatory everything
 * else is optional. All optional values will be tried to be evaluated
 * by the OSGi installer. If such evaluation fails the resource will
 * be ignore during installation.
 *
 * If the client provides a configuration it should use the
 * resource type {@link #TYPE_PROPERTIES}. Otherwise the resource
 * type {@link #TYPE_FILE} should be used. These two generic types
 * are transformed by resource transformer services to the appropriate
 * resource type like bundle or configuration etc. This frees the
 * client from having any knowledge about the provided data.
 * However, if the client has the knowledge about the data it can
 * provided a specific resource type.
 *
 * The provider should provide a digest for files (input streams).
 * The installer will calculate a digest for dictionaries, regardless
 * if the provider provided a dictionary.
 */
public class InstallableResource {

    /**
     * The type for properties - in this case {@link #getDictionary()}
     * should contain a dictionary or the {@link #getInputStream()}
     * should point to a property or configuration file.
     * @since 3.1 */
    public static final String TYPE_PROPERTIES = "properties";

    /**
     * The type for all other provided data like a bundle etc.
     * In this case {@link #getInputStream()} must return an input
     * stream to the data. {@link #getDictionary()} might return
     * additional information.
     * @since 3.1 */
    public static final String TYPE_FILE = "file";

    /**
     * The type for a bundle - in this case {@link #getInputStream} must
     * return an input stream to the bundle. {@link #getDictionary()} might
     * return additional information.
     * This type should only be used if the client really knows that the
     * provided data is a bundle.
     */
    public static final String TYPE_BUNDLE = "bundle";

    /**
     * The type for a configuration - in this case {@link #getDictionary()}
     * must return a dictionary with the configuration.
     * This type should only be used if the client really knows that the
     * provided data is an OSGi configuration.
     */
    public static final String TYPE_CONFIG = "config";

    /**
     * Optional parameter in the dictionary if a bundle is installed. If this
     * is set with a valid start level, the bundle is installed in that start level.
     */
    public static final String BUNDLE_START_LEVEL = "bundle.startlevel";

    /**
     * Optional parameter in the dictionary if a resource (not a dict) is installed.
     * This parameter might be used by the installation task for any purpose like
     * bundle start level etc.
     * @since 3.1
     */
    public static final String INSTALLATION_HINT = "installation.hint";

    /**
     * Optional parameter in the dictionary if a resource (not a dict) is installed.
     * If this parameter is specified, the installer uses the URI to get the input
     * stream of the resource! Usually the installer copies the resource into the
     * file system and uses this copy. To optimize this, if the URI of the resource
     * is always available (like a file URI), this property can be used to avoid
     * copying the resource.
     * It is only evaluated if the resource type is either unknown (null) or
     * {@link #TYPE_FILE} and a digest for the resource is delivered.
     * The value of this property is a string.
     * This property might also be set for an {@link UpdateHandler} in order
     * to give a hint for the (file) name the resource or dictionary should
     * have.
     * @since 3.1.2
     */
    public static final String RESOURCE_URI_HINT = "resource.uri.hint";

    /**
     * Optional parameter to be passed in the dictionary.
     * If this property is set (the value is ignored), this artifact acts like a template:
     * If the artifact is changed into a new artifact and later this new artifact is deleted,
     * the installer will not revert to the template. Without this property, the installer
     * would install the original artifact again.
     * For example: if a configuration is installed and then changed through configuration
     * admin, a new artifact for the new configuration is created and managed.
     * If now this configuration is deleted through configuration admin and the original
     * configuration is not marked as a template, the original configuration is applied:
     * the delete through config admin is not a remove of the configuration but a revert
     * to the initial version.
     * If the initial configuration is marked as template with this property, the removal
     * of the changed configuration results in a real removal.
     *
     * @since 3.2.0
     */
    public static final String RESOURCE_IS_TEMPLATE = "org.apache.sling.installer.api.template";

    /** Default resource priority */
    public static final int DEFAULT_PRIORITY = 100;

    private final String id;
    private final String digest;
    private final InputStream inputStream;
    private final Dictionary dictionary;
    private final int priority;
    private final String resourceType;

    /**
     * Create a data object - this is a simple constructor just using the
     * values as they are provided.
     * @param id Unique id for the resource, For auto detection of the resource
     *           type, the id should contain an extension like .jar, .cfg etc.
     * @param is The input stream to the data or
     * @param dict A dictionary with data
     * @param digest A digest of the data - providers should make sure to set
     *               a digest. Calculating a digest by the installer can be very
     *               expensive for input streams
     * @param type The resource type if known, otherwise {@link #TYPE_PROPERTIES}
     *             or {@link #TYPE_FILE}
     * @param priority Optional priority - if not specified {@link #DEFAULT_PRIORITY}
     *                 is used
     * @throws IllegalArgumentException if something is wrong
     */
    public InstallableResource(final String id,
            final InputStream is,
            final Dictionary dict,
            final String digest,
            final String type,
            final Integer priority) {
        if ( id == null ) {
            throw new IllegalArgumentException("id must not be null.");
        }
        if ( is == null ) {
            // if input stream is null, config through dictionary is expected!
            if ( dict == null ) {
                throw new IllegalArgumentException("dictionary must not be null (or input stream must not be null).");
            }
        }

        this.id = id;
        this.inputStream = is;
        this.dictionary = dict;
        this.digest = digest;
        this.priority = (priority != null ? priority : DEFAULT_PRIORITY);
        this.resourceType = type;
    }

    /**
     * Return this data's id. It is opaque for the {@link OsgiInstaller}
     * but should uniquely identify the resource within the namespace of
     * the used installation mechanism.
     * @return The id.
     */
    public String getId() {
        return this.id;
    }

    /**
     * Return the type of this resource.
     * @return The resource type or null if the type is unknown for the client.
     */
    public String getType() {
        return this.resourceType;
    }

    /**
     * Return an input stream with the data of this resource.
     * Null if resource contains a configuration instead. Caller is responsible for
     * closing the stream.
     * If this resource is of type CONFIG it must not return an input stream and
     * if this resource is of type BUNDLE it must return an input stream!
     * @return The input stream or null.
     */
    public InputStream getInputStream() {
        return this.inputStream;
    }

    /**
     * Return this resource's dictionary.
     * Null if resource contains an InputStream instead. If this resource is of
     * type CONFIG it must return a dictionary and if this resource is of type BUNDLE
     * it might return a dictionary!
     * @return The resource's dictionary or null.
     */
    public Dictionary getDictionary() {
        return this.dictionary;
    }

    /**
     * Return this resource's digest. Not necessarily an actual md5 or other digest of the
     * data, can be any string that changes if the data changes.
     * @return The digest or null
     */
    public String getDigest() {
        return this.digest;
    }

    /**
     * Return the priority of this resource. Priorities are used to decide which
     * resource to install when several are registered for the same OSGi entity
     * (bundle, config, etc.)
     * @return The priority.
     */
    public int getPriority() {
        return this.priority;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ", priority=" + priority + ", id=" + id;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy