1 /*
2 * Copyright (c) 2012-2023, jcabi.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met: 1) Redistributions of source code must retain the above
8 * copyright notice, this list of conditions and the following
9 * disclaimer. 2) Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution. 3) Neither the name of the jcabi.com nor
13 * the names of its contributors may be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package com.jcabi.mysql.maven.plugin;
31
32 import com.jcabi.aspects.Cacheable;
33 import com.jcabi.log.Logger;
34 import java.io.File;
35 import java.util.Collections;
36 import java.util.List;
37 import lombok.EqualsAndHashCode;
38 import lombok.ToString;
39 import org.apache.maven.plugin.AbstractMojo;
40 import org.apache.maven.plugin.MojoFailureException;
41 import org.apache.maven.plugins.annotations.Parameter;
42 import org.apache.maven.project.MavenProject;
43 import org.slf4j.impl.StaticLoggerBinder;
44
45 /**
46 * Abstract MOJO.
47 * @since 0.1
48 */
49 @ToString
50 @EqualsAndHashCode(callSuper = false)
51 abstract class AbstractMysqlMojo extends AbstractMojo {
52
53 /**
54 * Property that will be exported by the plugin indicating if an existing
55 * database could be reused.
56 */
57 private static final String PROPERTY_REUSED = "jcabi.reused.database";
58
59 /**
60 * The Maven project.
61 */
62 @Parameter(
63 defaultValue = "${project}",
64 readonly = true
65 )
66 private transient MavenProject project;
67
68 /**
69 * Shall we skip execution?
70 */
71 @Parameter(
72 defaultValue = "false",
73 required = false
74 )
75 private transient boolean skip;
76
77 /**
78 * Port to use.
79 */
80 @Parameter(
81 defaultValue = "3306",
82 required = false
83 )
84 private transient int port;
85
86 /**
87 * Location of MySQL distribution.
88 */
89 @Parameter(
90 defaultValue = "${project.build.directory}/mysql-dist",
91 required = true
92 )
93 private transient File dist;
94
95 /**
96 * Username to use.
97 */
98 @Parameter(
99 defaultValue = "root",
100 required = false
101 )
102 private transient String user;
103
104 /**
105 * Password to use.
106 */
107 @Parameter(
108 defaultValue = "root",
109 required = false
110 )
111 private transient String password;
112
113 /**
114 * Database name to use.
115 */
116 @Parameter(
117 defaultValue = "root",
118 required = false
119 )
120 private transient String dbname;
121
122 /**
123 * Location of MySQL data.
124 */
125 @Parameter(
126 defaultValue = "${project.build.directory}/mysql-data",
127 required = true
128 )
129 private transient File data;
130
131 /**
132 * Override location of MySQL socket file. Defaults to
133 * (data dir)/mysql.socket.
134 */
135 @Parameter(required = false)
136 private transient File socket;
137
138 /**
139 * Shall we always delete an existing database or reuse it?
140 */
141 @Parameter(
142 defaultValue = "true",
143 required = false
144 )
145 private transient boolean erase;
146
147 /**
148 * Configuration options.
149 */
150 @Parameter(
151 required = false
152 )
153 private transient List<String> options;
154
155 /**
156 * Set skip option.
157 * @param skp Shall we skip execution?
158 */
159 public void setSkip(final boolean skp) {
160 this.skip = skp;
161 }
162
163 @Override
164 public void execute() throws MojoFailureException {
165 StaticLoggerBinder.getSingleton().setMavenLog(this.getLog());
166 if (this.skip) {
167 Logger.info(this, "execution skipped because of 'skip' option");
168 return;
169 }
170 this.run(AbstractMysqlMojo.instances());
171 if (this.project == null) {
172 Logger.warn(
173 this,
174 "MavenProject not initialized, unable to set property %s",
175 AbstractMysqlMojo.PROPERTY_REUSED
176 );
177 } else {
178 Logger.info(
179 this,
180 "set Maven property %s = %s ",
181 AbstractMysqlMojo.PROPERTY_REUSED,
182 AbstractMysqlMojo.instances().reusedExistingDatabase()
183 );
184 this.project.getProperties().setProperty(
185 AbstractMysqlMojo.PROPERTY_REUSED,
186 Boolean.toString(
187 AbstractMysqlMojo.instances().reusedExistingDatabase()
188 )
189 );
190 }
191 }
192
193 /**
194 * Get directory with MySQL dist.
195 * @return Directory
196 * @throws MojoFailureException If fails
197 */
198 public File distDir() throws MojoFailureException {
199 if (!this.dist.exists()) {
200 throw new MojoFailureException(
201 String.format(
202 "MySQL distribution directory doesn't exist: %s", this.dist
203 )
204 );
205 }
206 return this.dist;
207 }
208
209 /**
210 * Get directory with MySQL data.
211 * @return Directory
212 */
213 public File dataDir() {
214 return this.data;
215 }
216
217 /**
218 * Get MySQL socket location.
219 * @return Overridden socket location (null for default)
220 */
221 public File socketFile() {
222 return this.socket;
223 }
224
225 /**
226 * If true, always delete existing database files and create a new instance
227 * from scratch. If false, try to reuse existing files.
228 * @return If existing database files should be deleted.
229 */
230 public boolean clear() {
231 return this.erase;
232 }
233
234 /**
235 * Get configuration.
236 * @return Configuration
237 */
238 public Config config() {
239 if (this.options == null) {
240 this.options = Collections.emptyList();
241 }
242 return new Config(
243 this.port, this.user, this.password, this.dbname,
244 Collections.unmodifiableList(this.options)
245 );
246 }
247
248 /**
249 * Run custom functionality.
250 * @param instances Instances to work with
251 * @throws MojoFailureException If fails
252 */
253 protected abstract void run(Instances instances) throws MojoFailureException;
254
255 /**
256 * Get instances.
257 * @return Instances
258 */
259 @Cacheable(forever = true)
260 private static Instances instances() {
261 return new Instances();
262 }
263
264 }