001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether.internal.impl;
020
021import javax.inject.Named;
022import javax.inject.Singleton;
023
024import java.util.regex.Pattern;
025
026import org.eclipse.aether.ConfigurationProperties;
027import org.eclipse.aether.RepositorySystemSession;
028import org.eclipse.aether.impl.OfflineController;
029import org.eclipse.aether.repository.RemoteRepository;
030import org.eclipse.aether.transfer.RepositoryOfflineException;
031import org.eclipse.aether.util.ConfigUtils;
032
033import static java.util.Objects.requireNonNull;
034
035/**
036 *
037 */
038@Singleton
039@Named
040public class DefaultOfflineController implements OfflineController {
041    private static final String CONFIG_PROPS_PREFIX = ConfigurationProperties.PREFIX_AETHER + "offline.";
042
043    /**
044     * Comma-separated list of protocols which are supposed to be resolved when session is offline.
045     *
046     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
047     * @configurationType {@link java.lang.String}
048     */
049    public static final String CONFIG_PROP_OFFLINE_PROTOCOLS = CONFIG_PROPS_PREFIX + "protocols";
050
051    /**
052     * Comma-separated list of hosts which are supposed to be resolved when session is offline.
053     *
054     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
055     * @configurationType {@link java.lang.String}
056     */
057    public static final String CONFIG_PROP_OFFLINE_HOSTS = CONFIG_PROPS_PREFIX + "hosts";
058
059    /**
060     * Comma-separated list of repository IDs which are supposed to be resolved when session is offline.
061     *
062     * @configurationSource {@link RepositorySystemSession#getConfigProperties()}
063     * @configurationType {@link java.lang.String}
064     * @since 2.0.8
065     */
066    public static final String CONFIG_PROP_OFFLINE_REPOSITORIES = CONFIG_PROPS_PREFIX + "repositories";
067
068    private static final Pattern SEP = Pattern.compile("\\s*,\\s*");
069
070    @Override
071    public void checkOffline(RepositorySystemSession session, RemoteRepository repository)
072            throws RepositoryOfflineException {
073        requireNonNull(session, "session cannot be null");
074        requireNonNull(repository, "repository cannot be null");
075        if (isOfflineProtocol(session, repository)
076                || isOfflineHost(session, repository)
077                || isOfflineRepository(session, repository)) {
078            return;
079        }
080
081        throw new RepositoryOfflineException(repository);
082    }
083
084    private boolean isOfflineProtocol(RepositorySystemSession session, RemoteRepository repository) {
085        String[] protocols = getConfig(session, CONFIG_PROP_OFFLINE_PROTOCOLS);
086        if (protocols != null) {
087            String protocol = repository.getProtocol();
088            if (!protocol.isEmpty()) {
089                for (String p : protocols) {
090                    if (p.equalsIgnoreCase(protocol)) {
091                        return true;
092                    }
093                }
094            }
095        }
096        return false;
097    }
098
099    private boolean isOfflineHost(RepositorySystemSession session, RemoteRepository repository) {
100        String[] hosts = getConfig(session, CONFIG_PROP_OFFLINE_HOSTS);
101        if (hosts != null) {
102            String host = repository.getHost();
103            if (!host.isEmpty()) {
104                for (String h : hosts) {
105                    if (h.equalsIgnoreCase(host)) {
106                        return true;
107                    }
108                }
109            }
110        }
111        return false;
112    }
113
114    private boolean isOfflineRepository(RepositorySystemSession session, RemoteRepository repository) {
115        String[] repositories = getConfig(session, CONFIG_PROP_OFFLINE_REPOSITORIES);
116        if (repositories != null) {
117            String repositoryId = repository.getId();
118            if (!repositoryId.isEmpty()) {
119                for (String r : repositories) {
120                    if (r.equals(repositoryId)) {
121                        return true;
122                    }
123                }
124            }
125        }
126        return false;
127    }
128
129    private String[] getConfig(RepositorySystemSession session, String key) {
130        String value = ConfigUtils.getString(session, "", key).trim();
131        if (value.isEmpty()) {
132            return null;
133        }
134        return SEP.split(value);
135    }
136}