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}