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.session;
020
021import java.util.Collections;
022import java.util.List;
023import java.util.Map;
024import java.util.concurrent.atomic.AtomicBoolean;
025
026import org.eclipse.aether.RepositoryCache;
027import org.eclipse.aether.RepositoryListener;
028import org.eclipse.aether.RepositorySystem;
029import org.eclipse.aether.RepositorySystemSession.CloseableSession;
030import org.eclipse.aether.SessionData;
031import org.eclipse.aether.artifact.ArtifactTypeRegistry;
032import org.eclipse.aether.collection.DependencyGraphTransformer;
033import org.eclipse.aether.collection.DependencyManager;
034import org.eclipse.aether.collection.DependencySelector;
035import org.eclipse.aether.collection.DependencyTraverser;
036import org.eclipse.aether.collection.VersionFilter;
037import org.eclipse.aether.impl.RepositorySystemLifecycle;
038import org.eclipse.aether.repository.AuthenticationSelector;
039import org.eclipse.aether.repository.LocalRepository;
040import org.eclipse.aether.repository.LocalRepositoryManager;
041import org.eclipse.aether.repository.MirrorSelector;
042import org.eclipse.aether.repository.ProxySelector;
043import org.eclipse.aether.repository.WorkspaceReader;
044import org.eclipse.aether.resolution.ArtifactDescriptorPolicy;
045import org.eclipse.aether.resolution.ResolutionErrorPolicy;
046import org.eclipse.aether.transfer.TransferListener;
047import org.eclipse.aether.util.repository.ChainedLocalRepositoryManager;
048
049import static java.util.Objects.requireNonNull;
050import static java.util.stream.Collectors.toList;
051
052/**
053 * A default implementation of repository system session that is immutable and thread-safe.
054 */
055public final class DefaultCloseableSession implements CloseableSession {
056    private final String sessionId;
057
058    private final AtomicBoolean closed;
059
060    private final boolean offline;
061
062    private final boolean ignoreArtifactDescriptorRepositories;
063
064    private final ResolutionErrorPolicy resolutionErrorPolicy;
065
066    private final ArtifactDescriptorPolicy artifactDescriptorPolicy;
067
068    private final String checksumPolicy;
069
070    private final String artifactUpdatePolicy;
071
072    private final String metadataUpdatePolicy;
073
074    private final LocalRepositoryManager localRepositoryManager;
075
076    private final WorkspaceReader workspaceReader;
077
078    private final RepositoryListener repositoryListener;
079
080    private final TransferListener transferListener;
081
082    private final Map<String, String> systemProperties;
083
084    private final Map<String, String> userProperties;
085
086    private final Map<String, Object> configProperties;
087
088    private final MirrorSelector mirrorSelector;
089
090    private final ProxySelector proxySelector;
091
092    private final AuthenticationSelector authenticationSelector;
093
094    private final ArtifactTypeRegistry artifactTypeRegistry;
095
096    private final DependencyTraverser dependencyTraverser;
097
098    private final DependencyManager dependencyManager;
099
100    private final DependencySelector dependencySelector;
101
102    private final VersionFilter versionFilter;
103
104    private final DependencyGraphTransformer dependencyGraphTransformer;
105
106    private final SessionData data;
107
108    private final RepositoryCache cache;
109
110    private final RepositorySystem repositorySystem;
111
112    private final RepositorySystemLifecycle repositorySystemLifecycle;
113
114    @SuppressWarnings("checkstyle:parameternumber")
115    public DefaultCloseableSession(
116            String sessionId,
117            AtomicBoolean closed,
118            boolean offline,
119            boolean ignoreArtifactDescriptorRepositories,
120            ResolutionErrorPolicy resolutionErrorPolicy,
121            ArtifactDescriptorPolicy artifactDescriptorPolicy,
122            String checksumPolicy,
123            String artifactUpdatePolicy,
124            String metadataUpdatePolicy,
125            LocalRepositoryManager localRepositoryManager,
126            List<LocalRepository> localRepositories,
127            WorkspaceReader workspaceReader,
128            RepositoryListener repositoryListener,
129            TransferListener transferListener,
130            Map<String, String> systemProperties,
131            Map<String, String> userProperties,
132            Map<String, Object> configProperties,
133            MirrorSelector mirrorSelector,
134            ProxySelector proxySelector,
135            AuthenticationSelector authenticationSelector,
136            ArtifactTypeRegistry artifactTypeRegistry,
137            DependencyTraverser dependencyTraverser,
138            DependencyManager dependencyManager,
139            DependencySelector dependencySelector,
140            VersionFilter versionFilter,
141            DependencyGraphTransformer dependencyGraphTransformer,
142            SessionData data,
143            RepositoryCache cache,
144            RepositorySystem repositorySystem,
145            RepositorySystemLifecycle repositorySystemLifecycle) {
146        this.sessionId = requireNonNull(sessionId);
147        this.closed = closed == null ? new AtomicBoolean(false) : closed;
148        this.offline = offline;
149        this.ignoreArtifactDescriptorRepositories = ignoreArtifactDescriptorRepositories;
150        this.resolutionErrorPolicy = resolutionErrorPolicy;
151        this.artifactDescriptorPolicy = artifactDescriptorPolicy;
152        this.checksumPolicy = checksumPolicy;
153        this.artifactUpdatePolicy = artifactUpdatePolicy;
154        this.metadataUpdatePolicy = metadataUpdatePolicy;
155        this.workspaceReader = workspaceReader;
156        this.repositoryListener = repositoryListener;
157        this.transferListener = transferListener;
158        this.systemProperties = Collections.unmodifiableMap(systemProperties);
159        this.userProperties = Collections.unmodifiableMap(userProperties);
160        this.configProperties = Collections.unmodifiableMap(configProperties);
161        this.mirrorSelector = requireNonNull(mirrorSelector);
162        this.proxySelector = requireNonNull(proxySelector);
163        this.authenticationSelector = requireNonNull(authenticationSelector);
164        this.artifactTypeRegistry = requireNonNull(artifactTypeRegistry);
165        this.dependencyTraverser = dependencyTraverser;
166        this.dependencyManager = dependencyManager;
167        this.dependencySelector = dependencySelector;
168        this.versionFilter = versionFilter;
169        this.dependencyGraphTransformer = dependencyGraphTransformer;
170        this.data = requireNonNull(data);
171        this.cache = cache;
172
173        this.repositorySystem = requireNonNull(repositorySystem);
174        this.repositorySystemLifecycle = requireNonNull(repositorySystemLifecycle);
175
176        this.localRepositoryManager = getOrCreateLocalRepositoryManager(localRepositoryManager, localRepositories);
177
178        if (closed == null) {
179            repositorySystemLifecycle.sessionStarted(this);
180        }
181    }
182
183    private LocalRepositoryManager getOrCreateLocalRepositoryManager(
184            LocalRepositoryManager localRepositoryManager, List<LocalRepository> localRepositories) {
185        if (localRepositoryManager != null) {
186            return localRepositoryManager;
187        } else if (localRepositories != null) {
188            if (localRepositories.isEmpty()) {
189                throw new IllegalArgumentException("empty localRepositories");
190            } else if (localRepositories.size() == 1) {
191                return repositorySystem.newLocalRepositoryManager(this, localRepositories.get(0));
192            } else {
193                LocalRepositoryManager head =
194                        repositorySystem.newLocalRepositoryManager(this, localRepositories.get(0));
195                List<LocalRepositoryManager> tail = localRepositories.subList(1, localRepositories.size()).stream()
196                        .map(l -> repositorySystem.newLocalRepositoryManager(this, l))
197                        .collect(toList());
198                return new ChainedLocalRepositoryManager(head, tail, this);
199            }
200        } else {
201            throw new IllegalStateException("No local repository manager or local repositories set on session");
202        }
203    }
204
205    @Override
206    public String sessionId() {
207        return sessionId;
208    }
209
210    @Override
211    public SessionBuilder copy() {
212        return new DefaultSessionBuilder(repositorySystem, repositorySystemLifecycle, sessionId, closed)
213                .withRepositorySystemSession(this);
214    }
215
216    @Override
217    public boolean isOffline() {
218        return offline;
219    }
220
221    @Override
222    public boolean isIgnoreArtifactDescriptorRepositories() {
223        return ignoreArtifactDescriptorRepositories;
224    }
225
226    @Override
227    public ResolutionErrorPolicy getResolutionErrorPolicy() {
228        return resolutionErrorPolicy;
229    }
230
231    @Override
232    public ArtifactDescriptorPolicy getArtifactDescriptorPolicy() {
233        return artifactDescriptorPolicy;
234    }
235
236    @Override
237    public String getChecksumPolicy() {
238        return checksumPolicy;
239    }
240
241    @Override
242    public String getUpdatePolicy() {
243        return getArtifactUpdatePolicy();
244    }
245
246    @Override
247    public String getArtifactUpdatePolicy() {
248        return artifactUpdatePolicy;
249    }
250
251    @Override
252    public String getMetadataUpdatePolicy() {
253        return metadataUpdatePolicy;
254    }
255
256    @Override
257    public LocalRepository getLocalRepository() {
258        return getLocalRepositoryManager().getRepository();
259    }
260
261    @Override
262    public LocalRepositoryManager getLocalRepositoryManager() {
263        return localRepositoryManager;
264    }
265
266    @Override
267    public WorkspaceReader getWorkspaceReader() {
268        return workspaceReader;
269    }
270
271    @Override
272    public RepositoryListener getRepositoryListener() {
273        return repositoryListener;
274    }
275
276    @Override
277    public TransferListener getTransferListener() {
278        return transferListener;
279    }
280
281    @Override
282    public Map<String, String> getSystemProperties() {
283        return systemProperties;
284    }
285
286    @Override
287    public Map<String, String> getUserProperties() {
288        return userProperties;
289    }
290
291    @Override
292    public Map<String, Object> getConfigProperties() {
293        return configProperties;
294    }
295
296    @Override
297    public MirrorSelector getMirrorSelector() {
298        return mirrorSelector;
299    }
300
301    @Override
302    public ProxySelector getProxySelector() {
303        return proxySelector;
304    }
305
306    @Override
307    public AuthenticationSelector getAuthenticationSelector() {
308        return authenticationSelector;
309    }
310
311    @Override
312    public ArtifactTypeRegistry getArtifactTypeRegistry() {
313        return artifactTypeRegistry;
314    }
315
316    @Override
317    public DependencyTraverser getDependencyTraverser() {
318        return dependencyTraverser;
319    }
320
321    @Override
322    public DependencyManager getDependencyManager() {
323        return dependencyManager;
324    }
325
326    @Override
327    public DependencySelector getDependencySelector() {
328        return dependencySelector;
329    }
330
331    @Override
332    public VersionFilter getVersionFilter() {
333        return versionFilter;
334    }
335
336    @Override
337    public DependencyGraphTransformer getDependencyGraphTransformer() {
338        return dependencyGraphTransformer;
339    }
340
341    @Override
342    public SessionData getData() {
343        return data;
344    }
345
346    @Override
347    public RepositoryCache getCache() {
348        return cache;
349    }
350
351    @Override
352    public boolean addOnSessionEndedHandler(Runnable handler) {
353        throwIfClosed();
354        repositorySystemLifecycle.addOnSessionEndedHandle(this, handler);
355        return true;
356    }
357
358    @Override
359    public void close() {
360        if (closed.compareAndSet(false, true)) {
361            repositorySystemLifecycle.sessionEnded(this);
362        }
363    }
364
365    private void throwIfClosed() {
366        if (closed.get()) {
367            throw new IllegalStateException("Session " + sessionId + " already closed");
368        }
369    }
370}