View Javadoc

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 		// Ensure separate threads are used for logging, as per ROO-652
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") || // for *nix/Mac
154 		    		ioe.getMessage().contains("CreateProcess error=2"))       // for Windows
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 }