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;
020
021import java.io.File;
022import java.nio.file.Path;
023import java.util.Collections;
024import java.util.List;
025
026import org.eclipse.aether.artifact.Artifact;
027import org.eclipse.aether.metadata.Metadata;
028import org.eclipse.aether.repository.ArtifactRepository;
029
030import static java.util.Objects.requireNonNull;
031
032/**
033 * An event describing an action performed by the repository system. Note that events which indicate the end of an
034 * action like {@link EventType#ARTIFACT_RESOLVED} are generally fired in both the success and the failure case. Use
035 * {@link #getException()} to check whether an event denotes success or failure.
036 *
037 * @see RepositoryListener
038 * @see RepositoryEvent.Builder
039 */
040public final class RepositoryEvent {
041
042    /**
043     * The type of the repository event.
044     */
045    public enum EventType {
046
047        /**
048         * @see RepositoryListener#artifactDescriptorInvalid(RepositoryEvent)
049         */
050        ARTIFACT_DESCRIPTOR_INVALID,
051
052        /**
053         * @see RepositoryListener#artifactDescriptorMissing(RepositoryEvent)
054         */
055        ARTIFACT_DESCRIPTOR_MISSING,
056
057        /**
058         * @see RepositoryListener#metadataInvalid(RepositoryEvent)
059         */
060        METADATA_INVALID,
061
062        /**
063         * @see RepositoryListener#artifactResolving(RepositoryEvent)
064         */
065        ARTIFACT_RESOLVING,
066
067        /**
068         * @see RepositoryListener#artifactResolved(RepositoryEvent)
069         */
070        ARTIFACT_RESOLVED,
071
072        /**
073         * @see RepositoryListener#metadataResolving(RepositoryEvent)
074         */
075        METADATA_RESOLVING,
076
077        /**
078         * @see RepositoryListener#metadataResolved(RepositoryEvent)
079         */
080        METADATA_RESOLVED,
081
082        /**
083         * @see RepositoryListener#artifactDownloading(RepositoryEvent)
084         */
085        ARTIFACT_DOWNLOADING,
086
087        /**
088         * @see RepositoryListener#artifactDownloaded(RepositoryEvent)
089         */
090        ARTIFACT_DOWNLOADED,
091
092        /**
093         * @see RepositoryListener#metadataDownloading(RepositoryEvent)
094         */
095        METADATA_DOWNLOADING,
096
097        /**
098         * @see RepositoryListener#metadataDownloaded(RepositoryEvent)
099         */
100        METADATA_DOWNLOADED,
101
102        /**
103         * @see RepositoryListener#artifactInstalling(RepositoryEvent)
104         */
105        ARTIFACT_INSTALLING,
106
107        /**
108         * @see RepositoryListener#artifactInstalled(RepositoryEvent)
109         */
110        ARTIFACT_INSTALLED,
111
112        /**
113         * @see RepositoryListener#metadataInstalling(RepositoryEvent)
114         */
115        METADATA_INSTALLING,
116
117        /**
118         * @see RepositoryListener#metadataInstalled(RepositoryEvent)
119         */
120        METADATA_INSTALLED,
121
122        /**
123         * @see RepositoryListener#artifactDeploying(RepositoryEvent)
124         */
125        ARTIFACT_DEPLOYING,
126
127        /**
128         * @see RepositoryListener#artifactDeployed(RepositoryEvent)
129         */
130        ARTIFACT_DEPLOYED,
131
132        /**
133         * @see RepositoryListener#metadataDeploying(RepositoryEvent)
134         */
135        METADATA_DEPLOYING,
136
137        /**
138         * @see RepositoryListener#metadataDeployed(RepositoryEvent)
139         */
140        METADATA_DEPLOYED
141    }
142
143    private final EventType type;
144
145    private final RepositorySystemSession session;
146
147    private final Artifact artifact;
148
149    private final Metadata metadata;
150
151    private final ArtifactRepository repository;
152
153    private final Path path;
154
155    private final List<Exception> exceptions;
156
157    private final RequestTrace trace;
158
159    RepositoryEvent(Builder builder) {
160        type = builder.type;
161        session = builder.session;
162        artifact = builder.artifact;
163        metadata = builder.metadata;
164        repository = builder.repository;
165        path = builder.path;
166        exceptions = builder.exceptions;
167        trace = builder.trace;
168    }
169
170    /**
171     * Gets the type of the event.
172     *
173     * @return The type of the event, never {@code null}.
174     */
175    public EventType getType() {
176        return type;
177    }
178
179    /**
180     * Gets the repository system session during which the event occurred.
181     *
182     * @return The repository system session during which the event occurred, never {@code null}.
183     */
184    public RepositorySystemSession getSession() {
185        return session;
186    }
187
188    /**
189     * Gets the artifact involved in the event (if any).
190     *
191     * @return The involved artifact or {@code null} if none.
192     */
193    public Artifact getArtifact() {
194        return artifact;
195    }
196
197    /**
198     * Gets the metadata involved in the event (if any).
199     *
200     * @return The involved metadata or {@code null} if none.
201     */
202    public Metadata getMetadata() {
203        return metadata;
204    }
205
206    /**
207     * Gets the file involved in the event (if any).
208     *
209     * @return The involved file or {@code null} if none.
210     * @deprecated Use {@link #getPath()} instead.
211     */
212    @Deprecated
213    public File getFile() {
214        return path != null ? path.toFile() : null;
215    }
216
217    /**
218     * Gets the file involved in the event (if any).
219     *
220     * @return The involved file or {@code null} if none.
221     * @since 2.0.0
222     */
223    public Path getPath() {
224        return path;
225    }
226
227    /**
228     * Gets the repository involved in the event (if any).
229     *
230     * @return The involved repository or {@code null} if none.
231     */
232    public ArtifactRepository getRepository() {
233        return repository;
234    }
235
236    /**
237     * Gets the exception that caused the event (if any). As a rule of thumb, an event accompanied by an exception
238     * indicates a failure of the corresponding action. If multiple exceptions occurred, this method returns the first
239     * exception.
240     *
241     * @return The exception or {@code null} if none.
242     */
243    public Exception getException() {
244        return exceptions.isEmpty() ? null : exceptions.get(0);
245    }
246
247    /**
248     * Gets the exceptions that caused the event (if any). As a rule of thumb, an event accompanied by exceptions
249     * indicates a failure of the corresponding action.
250     *
251     * @return The exceptions, never {@code null}.
252     */
253    public List<Exception> getExceptions() {
254        return exceptions;
255    }
256
257    /**
258     * Gets the trace information about the request during which the event occurred.
259     *
260     * @return The trace information or {@code null} if none.
261     */
262    public RequestTrace getTrace() {
263        return trace;
264    }
265
266    @Override
267    public String toString() {
268        StringBuilder buffer = new StringBuilder(256);
269        buffer.append(getType());
270        if (getArtifact() != null) {
271            buffer.append(" ").append(getArtifact());
272        }
273        if (getMetadata() != null) {
274            buffer.append(" ").append(getMetadata());
275        }
276        if (getPath() != null) {
277            buffer.append(" (").append(getPath()).append(")");
278        }
279        if (getRepository() != null) {
280            buffer.append(" @ ").append(getRepository());
281        }
282        return buffer.toString();
283    }
284
285    /**
286     * A builder to create events.
287     */
288    public static final class Builder {
289
290        final EventType type;
291
292        final RepositorySystemSession session;
293
294        Artifact artifact;
295
296        Metadata metadata;
297
298        ArtifactRepository repository;
299
300        Path path;
301
302        List<Exception> exceptions = Collections.emptyList();
303
304        RequestTrace trace;
305
306        /**
307         * Creates a new event builder for the specified session and event type.
308         *
309         * @param session The repository system session, must not be {@code null}.
310         * @param type The type of the event, must not be {@code null}.
311         */
312        public Builder(RepositorySystemSession session, EventType type) {
313            this.session = requireNonNull(session, "session cannot be null");
314            this.type = requireNonNull(type, "event type cannot be null");
315        }
316
317        /**
318         * Sets the artifact involved in the event.
319         *
320         * @param artifact The involved artifact, may be {@code null}.
321         * @return This event builder for chaining, never {@code null}.
322         */
323        public Builder setArtifact(Artifact artifact) {
324            this.artifact = artifact;
325            return this;
326        }
327
328        /**
329         * Sets the metadata involved in the event.
330         *
331         * @param metadata The involved metadata, may be {@code null}.
332         * @return This event builder for chaining, never {@code null}.
333         */
334        public Builder setMetadata(Metadata metadata) {
335            this.metadata = metadata;
336            return this;
337        }
338
339        /**
340         * Sets the repository involved in the event.
341         *
342         * @param repository The involved repository, may be {@code null}.
343         * @return This event builder for chaining, never {@code null}.
344         */
345        public Builder setRepository(ArtifactRepository repository) {
346            this.repository = repository;
347            return this;
348        }
349
350        /**
351         * Sets the file involved in the event.
352         *
353         * @param file The involved file, may be {@code null}.
354         * @return This event builder for chaining, never {@code null}.
355         * @deprecated Use {@link #setPath(Path)} instead.
356         */
357        @Deprecated
358        public Builder setFile(File file) {
359            return setPath(file != null ? file.toPath() : null);
360        }
361
362        /**
363         * Sets the file involved in the event.
364         *
365         * @param path The involved file, may be {@code null}.
366         * @return This event builder for chaining, never {@code null}.
367         * @since 2.0.0
368         */
369        public Builder setPath(Path path) {
370            this.path = path;
371            return this;
372        }
373
374        /**
375         * Sets the exception causing the event.
376         *
377         * @param exception The exception causing the event, may be {@code null}.
378         * @return This event builder for chaining, never {@code null}.
379         */
380        public Builder setException(Exception exception) {
381            if (exception != null) {
382                this.exceptions = Collections.singletonList(exception);
383            } else {
384                this.exceptions = Collections.emptyList();
385            }
386            return this;
387        }
388
389        /**
390         * Sets the exceptions causing the event.
391         *
392         * @param exceptions The exceptions causing the event, may be {@code null}.
393         * @return This event builder for chaining, never {@code null}.
394         */
395        public Builder setExceptions(List<Exception> exceptions) {
396            if (exceptions != null) {
397                this.exceptions = exceptions;
398            } else {
399                this.exceptions = Collections.emptyList();
400            }
401            return this;
402        }
403
404        /**
405         * Sets the trace information about the request during which the event occurred.
406         *
407         * @param trace The trace information, may be {@code null}.
408         * @return This event builder for chaining, never {@code null}.
409         */
410        public Builder setTrace(RequestTrace trace) {
411            this.trace = trace;
412            return this;
413        }
414
415        /**
416         * Builds a new event from the current values of this builder. The state of the builder itself remains
417         * unchanged.
418         *
419         * @return The event, never {@code null}.
420         */
421        public RepositoryEvent build() {
422            return new RepositoryEvent(this);
423        }
424    }
425}