1 package org.springframework.roo.addon.maven;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.util.logging.Logger;
9
10 import org.apache.felix.scr.annotations.Component;
11 import org.apache.felix.scr.annotations.Reference;
12 import org.apache.felix.scr.annotations.Service;
13 import org.osgi.service.component.ComponentContext;
14 import org.springframework.roo.model.JavaPackage;
15 import org.springframework.roo.model.JavaSymbolName;
16 import org.springframework.roo.shell.CliAvailabilityIndicator;
17 import org.springframework.roo.shell.CliCommand;
18 import org.springframework.roo.shell.CliOption;
19 import org.springframework.roo.shell.CommandMarker;
20 import org.springframework.roo.shell.converters.StaticFieldConverter;
21 import org.springframework.roo.support.logging.HandlerUtils;
22 import org.springframework.roo.support.util.Assert;
23
24 @Component
25 @Service
26 public class MavenCommands implements CommandMarker {
27
28 @Reference private MavenOperations mavenOperations;
29 @Reference private StaticFieldConverter staticFieldConverter;
30 protected final Logger logger = HandlerUtils.getLogger(getClass());
31
32 protected void activate(ComponentContext context) {
33 staticFieldConverter.add(Template.class);
34 }
35
36 protected void deactivate(ComponentContext context) {
37 staticFieldConverter.remove(Template.class);
38 }
39
40 @CliAvailabilityIndicator("project")
41 public boolean isCreateProjectAvailable() {
42 return mavenOperations.isCreateProjectAvailable();
43 }
44
45 @CliCommand(value="project", help="Creates a new project")
46 public void createProject(
47 @CliOption(key={"", "topLevelPackage"}, mandatory=true, help="The uppermost package name (this becomes the <groupId> in Maven and also the '~' value when using Roo's shell)") JavaPackage topLevelPackage,
48 @CliOption(key="projectName", mandatory=false, help="The name of the project (last segment of package name used as default)") String projectName,
49 @CliOption(key="java", mandatory=false, help="Forces a particular major version of Java to be used (will be auto-detected if unspecified; specify 5 or 6 or 7 only)") Integer majorJavaVersion,
50 @CliOption(key="template", mandatory=false, specifiedDefaultValue="STANDARD_PROJECT", unspecifiedDefaultValue="STANDARD_PROJECT", help="The type of project to create (defaults to STANDARD_PROJECT)") Template template) {
51 mavenOperations.createProject(template, topLevelPackage, projectName, majorJavaVersion);
52 }
53
54 @CliAvailabilityIndicator({"dependency add", "dependency remove"})
55 public boolean isDependencyModificationAllowed() {
56 return mavenOperations.isDependencyModificationAllowed();
57 }
58
59 @CliCommand(value="dependency add", help="Adds a new dependency to the Maven project object model (POM)")
60 public void addDependency(@CliOption(key="groupId", mandatory=true, help="The group ID of the dependency") JavaPackage groupId,
61 @CliOption(key="artifactId", mandatory=true, help="The artifact ID of the dependency") JavaSymbolName artifactId,
62 @CliOption(key="version", mandatory=true, help="The version of the dependency") String version) {
63 mavenOperations.addDependency(groupId, artifactId, version);
64 }
65
66 @CliCommand(value="dependency remove", help="Removes an existing dependency from the Maven project object model (POM)")
67 public void removeDependency(@CliOption(key="groupId", mandatory=true, help="The group ID of the dependency") JavaPackage groupId,
68 @CliOption(key="artifactId", mandatory=true, help="The artifact ID of the dependency") JavaSymbolName artifactId,
69 @CliOption(key="version", mandatory=true, help="The version of the dependency") String version) {
70 mavenOperations.removeDependency(groupId, artifactId, version);
71 }
72
73 @CliAvailabilityIndicator({"perform package", "perform eclipse", "perform tests", "perform clean", "perform assembly", "perform command"})
74 public boolean isPerformCommandAllowed() {
75 return mavenOperations.isPerformCommandAllowed();
76 }
77
78 @CliCommand(value={"perform package"}, help="Packages the application using Maven, but does not execute any tests")
79 public void runPackage() throws IOException {
80 mvn("-Dmaven.test.skip=true package");
81 }
82
83 @CliCommand(value={"perform eclipse"}, help="Sets up Eclipse configuration via Maven (only necessary if you have not installed the m2eclipse plugin in Eclipse)")
84 public void runEclipse() throws IOException {
85 mvn("eclipse:clean eclipse:eclipse");
86 }
87
88 @CliCommand(value={"perform tests"}, help="Executes the tests via Maven")
89 public void runTest() throws IOException {
90 mvn("test");
91 }
92
93 @CliCommand(value={"perform assembly"}, help="Executes the assembly goal via Maven")
94 public void runAssembly() throws IOException {
95 mvn("assembly:assembly");
96 }
97
98 @CliCommand(value={"perform clean"}, help="Executes a full clean (including Eclipse files) via Maven")
99 public void runClean() throws IOException {
100 mvn("clean");
101 }
102
103 @CliCommand(value={"perform command"}, help="Executes a user-specified Maven command")
104 public void mvn(@CliOption(key="mavenCommand", mandatory=true, help="User-specified Maven command (eg test:test)") String extra) throws IOException {
105 File root = new File(mavenOperations.getProjectRoot());
106 Assert.isTrue(root.isDirectory() && root.exists(), "Project root does not currently exist as a directory ('" + root.getCanonicalPath() + "')");
107
108 String cmd = null;
109 if (File.separatorChar == '\\') {
110 cmd = "mvn.bat " + extra;
111 } else {
112 cmd = "mvn " + extra;
113 }
114 Process p = Runtime.getRuntime().exec(cmd, null, root);
115
116
117 LoggingInputStream input = new LoggingInputStream(p.getInputStream());
118 LoggingInputStream errors = new LoggingInputStream(p.getErrorStream());
119
120 input.start();
121 errors.start();
122
123 try {
124 p.waitFor();
125 } catch (InterruptedException e) {
126 throw new IllegalStateException(e);
127 }
128
129 }
130
131 private class LoggingInputStream extends Thread {
132
133 private BufferedReader inputStream;
134
135 public LoggingInputStream(InputStream inputStream) {
136 this.inputStream = new BufferedReader(new InputStreamReader(inputStream));
137 }
138
139 @Override
140 public void run() {
141 String line;
142 try {
143 while ((line = inputStream.readLine()) != null) {
144 if (line.startsWith("[ERROR]")) {
145 logger.severe(line);
146 } else if (line.startsWith("[WARNING]")) {
147 logger.warning(line);
148 } else {
149 logger.info(line);
150 }
151 }
152 } catch (IOException ioe) {
153 if (ioe.getMessage().contains("No such file or directory") ||
154 ioe.getMessage().contains("CreateProcess error=2"))
155 {
156 logger.severe("Could not locate Maven executable; please ensure mvn command is in your path");
157 }
158 } finally {
159 if (inputStream != null) {
160 try {
161 inputStream.close();
162 } catch (IOException ignore) {}
163 }
164 }
165
166 }
167
168 }
169
170 }