001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2017 MicroBean.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
014 * implied.  See the License for the specific language governing
015 * permissions and limitations under the License.
016 */
017package org.microbean.helm.maven;
018
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.List;
022import java.util.Objects;
023
024import java.util.concurrent.Callable;
025import java.util.concurrent.Future;
026
027import hapi.services.tiller.Tiller.GetReleaseContentRequest;
028import hapi.services.tiller.Tiller.GetReleaseContentResponse;
029
030import org.apache.maven.plugin.logging.Log;
031
032import org.apache.maven.plugins.annotations.Mojo;
033import org.apache.maven.plugins.annotations.Parameter;
034
035import org.microbean.helm.ReleaseManager;
036
037/**
038 * Retrieves the content of a release.
039 *
040 * @author <a href="https://about.me/lairdnelson"
041 * target="_parent">Laird Nelson</a>
042 */
043@Mojo(name = "content")
044public class GetReleaseContentMojo extends AbstractSingleVersionedReleaseMojo {
045
046
047  /*
048   * Instance fields.
049   */
050  
051  /**
052   * A {@link List} of <a
053   * href="apidocs/org/microbean/helm/maven/ReleaseContentListener.html">{@code
054   * ReleaseContentListener}</a>s that will be notified of a release's
055   * content retrieval.
056   */
057  @Parameter(alias = "releaseContentListenersList")
058  private List<ReleaseContentListener> releaseContentListeners;
059  
060
061  /*
062   * Constructors.
063   */
064  
065
066  /**
067   * Creates a new {@link GetReleaseContentMojo}.
068   */
069  public GetReleaseContentMojo() {
070    super();
071  }
072
073
074  /*
075   * Protected instance methods.
076   */
077  
078
079  /**
080   * {@inheritDoc}
081   *
082   * <p>This implementation retrieves the content of a particular
083   * version of a single release and {@linkplain
084   * ReleaseContentListener#releaseContentRetrieved(ReleaseContentEvent)
085   * notifies registers listeners}.</p>
086   */
087  @Override
088  protected void execute(final Callable<ReleaseManager> releaseManagerCallable) throws Exception {
089    Objects.requireNonNull(releaseManagerCallable);
090    final Log log = this.getLog();
091    assert log != null;
092
093    final Integer version = this.getVersion();
094    if (version == null) {
095      throw new IllegalStateException("version was not specified");
096    }
097    
098    final Collection<? extends ReleaseContentListener> listeners = this.getReleaseContentListenersList();
099    if (listeners == null || listeners.isEmpty()) {
100      if (log.isInfoEnabled()) {
101        log.info("Skipping execution because there are no ReleaseContentListeners specified.");
102      }
103      return;
104    }
105    
106    final GetReleaseContentRequest.Builder requestBuilder = GetReleaseContentRequest.newBuilder();
107    assert requestBuilder != null;
108
109    final String releaseName = this.getReleaseName();
110    if (releaseName != null) {
111      requestBuilder.setName(releaseName);
112    }
113
114    requestBuilder.setVersion(version.intValue());
115
116    final ReleaseManager releaseManager = releaseManagerCallable.call();
117    if (releaseManager == null) {
118      throw new IllegalStateException("releaseManagerCallable.call() == null");
119    }
120
121    if (log.isInfoEnabled()) {
122      log.info("Retrieving content for release " + releaseName);
123    }
124    
125    final Future<GetReleaseContentResponse> getReleaseContentResponseFuture = releaseManager.getContent(requestBuilder.build());
126    assert getReleaseContentResponseFuture != null;
127    final GetReleaseContentResponse getReleaseContentResponse = getReleaseContentResponseFuture.get();
128    assert getReleaseContentResponse != null;
129
130    final ReleaseContentEvent event = new ReleaseContentEvent(this, getReleaseContentResponse);
131    for (final ReleaseContentListener listener : listeners) {
132      if (listener != null) {
133        listener.releaseContentRetrieved(event);
134      }
135    }
136    
137  }
138
139
140  /*
141   * Public instance methods.
142   */
143
144  
145  /**
146   * Adds a {@link ReleaseContentListener} that will be {@linkplain
147   * ReleaseContentListener#releaseContentRetrieved(ReleaseContentEvent)
148   * notified when a release's content is retrieved}.
149   *
150   * @param listener the {@link ReleaseContentListener} to add; may be
151   * {@code null} in which case no action will be taken
152   *
153   * @see #removeReleaseContentListener(ReleaseContentListener)
154   *
155   * @see #getReleaseContentListenersList()
156   */
157  public void addReleaseContentListener(final ReleaseContentListener listener) {
158    if (listener != null) {
159      if (this.releaseContentListeners == null) {
160        this.releaseContentListeners = new ArrayList<>();      
161      }
162      this.releaseContentListeners.add(listener);
163    }
164  }
165
166  /**
167   * Removes a {@link ReleaseContentListener} from this {@link
168   * TestReleaseMojo}.
169   *
170   * @param listener the {@link ReleaseContentListener} to remove; may be
171   * {@code null} in which case no action will be taken
172   *
173   * @see #addReleaseContentListener(ReleaseContentListener)
174   *
175   * @see #getReleaseContentListenersList()
176   */
177  public void removeReleaseContentListener(final ReleaseContentListener listener) {
178    if (listener != null && this.releaseContentListeners != null) {
179      this.releaseContentListeners.remove(listener);
180    }
181  }
182
183  /**
184   * Invokes the {@link #getReleaseContentListenersList()} method and
185   * {@linkplain Collection#toArray(Object[]) converts its return
186   * value to an array}.
187   *
188   * <p>This method never returns {@code null}.</p>
189   *
190   * <p>Overrides of this method must not return {@code null}.</p>
191   *
192   * @return a non-{@code null} array of {@link ReleaseContentListener}s
193   *
194   * @see #getReleaseContentListenersList()
195   */
196  public ReleaseContentListener[] getReleaseContentListeners() {
197    final Collection<ReleaseContentListener> listeners = this.getReleaseContentListenersList();
198    if (listeners == null || listeners.isEmpty()) {
199      return new ReleaseContentListener[0];
200    } else {
201      return listeners.toArray(new ReleaseContentListener[listeners.size()]);
202    }
203  }
204
205  /**
206   * Returns the {@link List} of {@link ReleaseContentListener}s whose
207   * elements will be {@linkplain
208   * ReleaseContentListener#releaseContentRetrieved(ReleaseContentEvent)
209   * notified when the tests complete}.
210   *
211   * <p>This method may return {@code null}.</p>
212   *
213   * <p>Overrides of this method are permitted to return {@code
214   * null}.</p>
215   *
216   * @return a {@link List} of {@link ReleaseContentListener}s, or
217   * {@code null}
218   *
219   * @see #setReleaseContentListenersList(List)
220   *
221   * @see #addReleaseContentListener(ReleaseContentListener)
222   *
223   * @see #removeReleaseContentListener(ReleaseContentListener)
224   */
225  public List<ReleaseContentListener> getReleaseContentListenersList() {
226    return this.releaseContentListeners;
227  }
228
229  /**
230   * Installs the {@link List} of {@link ReleaseContentListener}s
231   * whose elements will be {@linkplain
232   * ReleaseContentListener#releaseContentRetrieved(ReleaseContentEvent)
233   * notified when a release's contents are retrieved}.
234   *
235   * @param releaseContentListeners the {@link List} of {@link
236   * ReleaseContentListener}s whose elements will be {@linkplain
237   * ReleaseContentListener#releaseContentRetrieved(ReleaseContentEvent)
238   * notified when a release's contents are retrieved}; may be {@code
239   * null}
240   *
241   * @see #getReleaseContentListenersList()
242   *
243   * @see #addReleaseContentListener(ReleaseContentListener)
244   *
245   * @see #removeReleaseContentListener(ReleaseContentListener)
246   */
247  public void setReleaseContentListenersList(final List<ReleaseContentListener> releaseContentListeners) {
248    this.releaseContentListeners = releaseContentListeners;
249  }
250
251}