org.commonjava.aprox.autoprox.data.AutoProxDataManagerDecorator.java Source code

Java tutorial

Introduction

Here is the source code for org.commonjava.aprox.autoprox.data.AutoProxDataManagerDecorator.java

Source

/**
 * Copyright (C) 2011 Red Hat, Inc. (jdcasey@commonjava.org)
 *
 * Licensed 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.commonjava.aprox.autoprox.data;

import static org.commonjava.maven.galley.util.PathUtils.normalize;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.enterprise.inject.Any;
import javax.inject.Inject;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpHead;
import org.commonjava.aprox.audit.ChangeSummary;
import org.commonjava.aprox.data.AproxDataException;
import org.commonjava.aprox.data.StoreDataManager;
import org.commonjava.aprox.mem.data.MemoryStoreDataManager;
import org.commonjava.aprox.model.core.ArtifactStore;
import org.commonjava.aprox.model.core.Group;
import org.commonjava.aprox.model.core.HostedRepository;
import org.commonjava.aprox.model.core.RemoteRepository;
import org.commonjava.aprox.model.core.StoreKey;
import org.commonjava.aprox.model.core.StoreType;
import org.commonjava.aprox.subsys.http.AproxHttpProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Decorator
public abstract class AutoProxDataManagerDecorator implements StoreDataManager {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Delegate
    @Any
    @Inject
    private StoreDataManager dataManager;

    @Inject
    private AutoProxCatalogManager catalog;

    @Inject
    private AproxHttpProvider http;

    protected AutoProxDataManagerDecorator() {
    }

    public AutoProxDataManagerDecorator(final MemoryStoreDataManager dataManager,
            final AutoProxCatalogManager catalog, final AproxHttpProvider http) {
        this.dataManager = dataManager;
        this.catalog = catalog;
        this.http = http;
    }

    protected final StoreDataManager getDelegate() {
        return dataManager;
    }

    @Override
    public Group getGroup(final String name) throws AproxDataException {
        logger.debug("DECORATED (getGroup: {})", name);
        Group g = dataManager.getGroup(name);

        if (!catalog.isEnabled()) {
            logger.debug("AutoProx decorator disabled; returning: {}", g);
            return g;
        }

        logger.debug("AutoProx decorator active");
        if (g == null) {
            logger.debug("AutoProx: creating repository for: {}", name);
            try {
                g = catalog.createGroup(name);
            } catch (final AutoProxRuleException e) {
                throw new AproxDataException(
                        "[AUTOPROX] Failed to create new group from factory matching: '%s'. Reason: %s", e, name,
                        e.getMessage());
            }

            if (g != null) {
                if (!checkValidity(name)) {
                    return null;
                }

                for (final StoreKey key : new ArrayList<StoreKey>(g.getConstituents())) {
                    final ArtifactStore store = getArtifactStore(key);
                    if (store == null) {
                        g.removeConstituent(key);
                    }
                }

                if (g.getConstituents().isEmpty()) {
                    return null;
                }

                final Group group = g;
                dataManager.storeArtifactStore(group, new ChangeSummary(ChangeSummary.SYSTEM_USER,
                        "AUTOPROX: Creating group for: '" + name + "'"));
            }
        }

        return g;
    }

    /**
     * Validates the remote connection, produced from rule-set for given name, 
     * for a remote repo or group containing a remote. If:
     * 
     * <ul>
     *   <li>rule.isValidationEnabled() == false, return true</li>
     *   <li>rule.getValidationRemote() == null, return true</li>
     *   <li>
     *     rule.getRemoteValidationPath() != null, validate remote.getUrl() + validationPath
     *     <ul>
     *       <li>if response code is 200 OK, then return true</li>
     *       <li>otherwise, return false</li>
     *     </ul>
     *   </li>
     * </ul>
     * @throws AproxDataException if the selected rule encounters an error while creating the new group/repository instance(s).
     */
    private boolean checkValidity(final String name) throws AproxDataException {
        if (catalog.isValidationEnabled(name)) {
            try {
                final RemoteRepository validationRepo = catalog.createValidationRemote(name);
                if (validationRepo == null) {
                    return true;
                }

                String url = catalog.getRemoteValidationUrl(name);
                if (url == null) {
                    url = validationRepo.getUrl();
                } else {
                    url = normalize(validationRepo.getUrl(), url);
                }

                logger.debug("\n\n\n\n\n[AutoProx] Checking URL: {}", url);
                final HttpHead head = new HttpHead(url);

                http.bindRepositoryCredentialsTo(validationRepo, head);

                boolean result = false;
                try {
                    final HttpResponse response = http.getClient().execute(head);
                    final StatusLine statusLine = response.getStatusLine();
                    final int status = statusLine.getStatusCode();
                    logger.debug("[AutoProx] HTTP Status: {}", statusLine);
                    result = status == HttpStatus.SC_OK;

                    if (!result) {
                        logger.warn("Invalid repository URL: {}", validationRepo.getUrl());
                    }
                } catch (final ClientProtocolException e) {
                    logger.warn("[AutoProx] Cannot connect to target repository: '{}'.", url);
                } catch (final IOException e) {
                    logger.warn("[AutoProx] Cannot connect to target repository: '{}'.", url);
                } finally {
                    head.reset();

                    http.clearRepositoryCredentials();
                    http.closeConnection();
                }

                return result;
            } catch (final AutoProxRuleException e) {
                throw new AproxDataException(
                        "[AUTOPROX] Failed to create new group from factory matching: '%s'. Reason: %s", e, name,
                        e.getMessage());
            }
        }

        return true;
    }

    @Override
    public RemoteRepository getRemoteRepository(final String name) throws AproxDataException {
        logger.debug("DECORATED (getRemoteRepository: {})", name);
        RemoteRepository repo = dataManager.getRemoteRepository(name);
        if (!catalog.isEnabled()) {
            logger.debug("AutoProx decorator disabled; returning: {}", repo);
            return repo;
        }

        logger.debug("AutoProx decorator active");
        if (repo == null) {
            logger.info("AutoProx: creating repository for: {}", name);

            try {
                repo = catalog.createRemoteRepository(name);
                if (repo != null) {
                    if (!checkValidity(name)) {
                        return null;
                    }

                    final RemoteRepository remote = repo;
                    dataManager.storeRemoteRepository(remote, new ChangeSummary(ChangeSummary.SYSTEM_USER,
                            "AUTOPROX: Creating remote repository for: '" + name + "'"));
                }
            } catch (final AutoProxRuleException e) {
                throw new AproxDataException(
                        "[AUTOPROX] Failed to create new remote repository from factory matching: '%s'. Reason: %s",
                        e, name, e.getMessage());
            }
        }

        return repo;
    }

    @Override
    public HostedRepository getHostedRepository(final String name) throws AproxDataException {
        logger.debug("DECORATED (getHostedRepository: {})", name);
        HostedRepository repo = dataManager.getHostedRepository(name);
        if (!catalog.isEnabled()) {
            logger.debug("AutoProx decorator disabled; returning: {}", repo);
            return repo;
        }

        logger.debug("AutoProx decorator active");
        if (repo == null) {
            logger.info("AutoProx: creating repository for: {}", name);

            try {
                repo = catalog.createHostedRepository(name);
            } catch (final AutoProxRuleException e) {
                throw new AproxDataException(
                        "[AUTOPROX] Failed to create new hosted repository from factory matching: '%s'. Reason: %s",
                        e, name, e.getMessage());
            }

            if (repo != null) {
                final HostedRepository hosted = repo;
                dataManager.storeHostedRepository(hosted, new ChangeSummary(ChangeSummary.SYSTEM_USER,
                        "AUTOPROX: Creating remote repository for: '" + name + "'"));
            }
        }

        return repo;
    }

    @Override
    public ArtifactStore getArtifactStore(final StoreKey key) throws AproxDataException {
        if (key == null) {
            return null;
        }

        if (key.getType() == StoreType.group) {
            return getGroup(key.getName());
        } else if (key.getType() == StoreType.remote) {
            return getRemoteRepository(key.getName());
        } else {
            return getHostedRepository(key.getName());
        }
    }

    @Override
    public List<ArtifactStore> getOrderedConcreteStoresInGroup(final String groupName) throws AproxDataException {
        getGroup(groupName);
        return dataManager.getOrderedConcreteStoresInGroup(groupName);
    }

    @Override
    public List<ArtifactStore> getOrderedStoresInGroup(final String groupName) throws AproxDataException {
        getGroup(groupName);
        return dataManager.getOrderedStoresInGroup(groupName);
    }

    @Override
    public boolean hasRemoteRepository(final String name) {
        try {
            return getRemoteRepository(name) != null;
        } catch (final AproxDataException e) {
            logger.error(String.format("Failed to retrieve/create remote: %s. Reason: %s", name, e.getMessage()),
                    e);
        }

        return false;
    }

    @Override
    public boolean hasHostedRepository(final String name) {
        try {
            return getHostedRepository(name) != null;
        } catch (final AproxDataException e) {
            logger.error(String.format("Failed to retrieve/create hosted: %s. Reason: %s", name, e.getMessage()),
                    e);
        }

        return false;
    }

    @Override
    public boolean hasGroup(final String name) {
        try {
            return getGroup(name) != null;
        } catch (final AproxDataException e) {
            logger.error(String.format("Failed to retrieve/create group: %s. Reason: %s", name, e.getMessage()), e);
        }

        return false;
    }

    @Override
    public boolean hasArtifactStore(final StoreKey key) {
        try {
            return getArtifactStore(key) != null;
        } catch (final AproxDataException e) {
            logger.error(String.format("Failed to retrieve/create: %s. Reason: %s", key, e.getMessage()), e);
        }

        return false;
    }

}