<commit_before>/**
 * Licensed to jclouds, Inc. (jclouds) under one or more
 * contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  jclouds 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.jclouds.karaf.core;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.scriptbuilder.domain.Statement;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;

/**
 * A proxy implementations of the {@link ComputeService} which delegates calls to the underlying impl and notifies
 * {@link NodeListener}s about node creation/destruction events.
 */
public class ComputeServiceEventProxy implements ComputeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ComputeServiceEventProxy.class);

    private BundleContext bundleContext;
    private ComputeService computeService;

    private ServiceTracker listenerTracker;

    /**
     * Constructor
     *
     * @param bundleContext
     * @param computeService
     */
    public ComputeServiceEventProxy(BundleContext bundleContext, ComputeService computeService) {
        this.bundleContext = bundleContext;
        this.computeService = computeService;
        this.listenerTracker = new ServiceTracker(bundleContext, NodeListener.class.getName(), null);
        this.listenerTracker.open();
    }

    private List<? extends NodeListener> getNodeListeners() {
        List<NodeListener> listeners = new LinkedList<NodeListener>();
        try {
            listeners.addAll(Arrays.asList((NodeListener[]) listenerTracker.getServices()));
        } catch (Exception ex) {
            LOGGER.warn("Could not lookup node listeners. Listeners will not receive the last event.");
        }
        return listeners;
    }

    /**
     * @return a reference to the context that created this ComputeService.
     */
    @Override
    public ComputeServiceContext getContext() {
        return computeService.getContext();
    }

    /**
     * Makes a new template builder for this service
     */
    @Override
    public TemplateBuilder templateBuilder() {
        return computeService.templateBuilder();
    }

    /**
     * Makes a new set of options for running nodes
     */
    @Override
    public TemplateOptions templateOptions() {
        return computeService.templateOptions();
    }

    /**
     * The list hardware profiles command shows you the options including virtual cpu count, memory,
     * and disks. cpu count is not a portable quantity across clouds, as they are measured
     * differently. However, it is a good indicator of relative speed within a cloud. memory is
     * measured in megabytes and disks in gigabytes.
     *
     * @return a map of hardware profiles by ID, conceding that in some clouds the "id" is not used.
     */
    @Override
    public Set<? extends Hardware> listHardwareProfiles() {
        return computeService.listHardwareProfiles();
    }

    /**
     * Images define the operating system and metadata related to a node. In some clouds, Images are
     * bound to a specific region, and their identifiers are different across these regions. For this
     * reason, you should consider matching image requirements like operating system family with
     * TemplateBuilder as opposed to choosing an image explicitly. The getImages() command returns a
     * map of images by id.
     */
    @Override
    public Set<? extends Image> listImages() {
        return computeService.listImages();
    }

    /**
     * all nodes available to the current user by id. If possible, the returned set will include
     * {@link org.jclouds.compute.domain.NodeMetadata} objects.
     */
    @Override
    public Set<? extends ComputeMetadata> listNodes() {
        return computeService.listNodes();
    }

    /**
     * The list locations command returns all the valid locations for nodes. A location has a scope,
     * which is typically region or zone. A region is a general area, like eu-west, where a zone is
     * similar to a datacenter. If a location has a parent, that implies it is within that location.
     * For example a location can be a rack, whose parent is likely to be a zone.
     */
    @Override
    public Set<? extends Location> listAssignableLocations() {
        return computeService.listAssignableLocations();
    }

    /**
     * The compute api treats nodes as a group based on the name you specify. Using this group, you
     * can choose to operate one or many nodes as a logical unit without regard to the implementation<commit_msg>Added missing method from the ComputeService interface<commit_after>/**
 * Licensed to jclouds, Inc. (jclouds) under one or more
 * contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  jclouds 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.jclouds.karaf.core;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Location;
import org.jclouds.scriptbuilder.domain.Statement;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;

/**
 * A proxy implementations of the {@link ComputeService} which delegates calls to the underlying impl and notifies
 * {@link NodeListener}s about node creation/destruction events.
 */
public class ComputeServiceEventProxy implements ComputeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ComputeServiceEventProxy.class);

    private BundleContext bundleContext;
    private ComputeService computeService;

    private ServiceTracker listenerTracker;

    /**
     * Constructor
     *
     * @param bundleContext
     * @param computeService
     */
    public ComputeServiceEventProxy(BundleContext bundleContext, ComputeService computeService) {
        this.bundleContext = bundleContext;
        this.computeService = computeService;
        this.listenerTracker = new ServiceTracker(bundleContext, NodeListener.class.getName(), null);
        this.listenerTracker.open();
    }

    private List<? extends NodeListener> getNodeListeners() {
        List<NodeListener> listeners = new LinkedList<NodeListener>();
        try {
            listeners.addAll(Arrays.asList((NodeListener[]) listenerTracker.getServices()));
        } catch (Exception ex) {
            LOGGER.warn("Could not lookup node listeners. Listeners will not receive the last event.");
        }
        return listeners;
    }

    /**
     * @return a reference to the context that created this ComputeService.
     */
    @Override
    public ComputeServiceContext getContext() {
        return computeService.getContext();
    }

    /**
     * Makes a new template builder for this service
     */
    @Override
    public TemplateBuilder templateBuilder() {
        return computeService.templateBuilder();
    }

    /**
     * Makes a new set of options for running nodes
     */
    @Override
    public TemplateOptions templateOptions() {
        return computeService.templateOptions();
    }

    /**
     * The list hardware profiles command shows you the options including virtual cpu count, memory,
     * and disks. cpu count is not a portable quantity across clouds, as they are measured
     * differently. However, it is a good indicator of relative speed within a cloud. memory is
     * measured in megabytes and disks in gigabytes.
     *
     * @return a map of hardware profiles by ID, conceding that in some clouds the "id" is not used.
     */
    @Override
    public Set<? extends Hardware> listHardwareProfiles() {
        return computeService.listHardwareProfiles();
    }

    /**
     * Images define the operating system and metadata related to a node. In some clouds, Images are
     * bound to a specific region, and their identifiers are different across these regions. For this
     * reason, you should consider matching image requirements like operating system family with
     * TemplateBuilder as opposed to choosing an image explicitly. The getImages() command returns a
     * map of images by id.
     */
    @Override
    public Set<? extends Image> listImages() {
        return computeService.listImages();
    }

    /**
     * all nodes available to the current user by id. If possible, the returned set will include
     * {@link org.jclouds.compute.domain.NodeMetadata} objects.
     */
    @Override
    public Set<? extends ComputeMetadata> listNodes() {
        return computeService.listNodes();
    }

    /**
     * all nodes available to the current user that have the given id. If possible, the returned set will include
     * {@link org.jclouds.compute.domain.NodeMetadata} objects.
     */
    @Override
    public Set<? extends NodeMetadata> listNodesByIds(Iterable<String> ids) {
       return computeService.listNodesByIds(ids);
    }

    /**
     * The list locations command returns all the valid locations for nodes. A location has a scope,
     * which is typically region or zone. A region is a general area, like eu-west, where a zone is
     * similar to a datacenter. If a location has a parent, that implies it is within that location.
     * For example a location can be a rack, whose parent is likely to be a zone.
     */
    @Override
    public Set<? extends Location> listAssignableLocations() {
        return computeService.listAssignableLocations();
    }

    /**
     * The compute api treats nodes as a group based on the name you specify. Using this group, you
     * can choose to operate one or many nodes as a logical unit without regard to the implementation
{'fraction_non_alphanumeric': 0.07654340332184269, 'fraction_numerical': 0.000940144155437167, 'mean_word_length': 3.4726699369306235, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3634824', 'n_tokens_mistral': 3252, 'n_tokens_neox': 3209, 'n_words': 1214}