View Javadoc
1   /*
2    * (C) Copyright 2006-2014 Nuxeo SA (http://nuxeo.com/) and contributors.
3    *
4    * All rights reserved. This program and the accompanying materials
5    * are made available under the terms of the GNU Lesser General Public License
6    * (LGPL) version 2.1 which accompanies this distribution, and is available at
7    * http://www.gnu.org/licenses/lgpl-2.1.html
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   * Lesser General Public License for more details.
13   *
14   * Contributors:
15   *     bstefanescu, jcarsique
16   */
17  package org.nuxeo.build.ant;
18  
19  import java.io.File;
20  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.io.PrintStream;
24  import java.net.URL;
25  import java.util.List;
26  
27  import org.apache.commons.io.FileCleaningTracker;
28  import org.apache.maven.plugin.logging.Log;
29  import org.apache.tools.ant.BuildException;
30  import org.apache.tools.ant.BuildLogger;
31  import org.apache.tools.ant.DemuxInputStream;
32  import org.apache.tools.ant.DemuxOutputStream;
33  import org.apache.tools.ant.Project;
34  import org.apache.tools.ant.ProjectHelper;
35  import org.apache.tools.ant.input.DefaultInputHandler;
36  import org.apache.tools.ant.input.InputHandler;
37  import org.apache.tools.ant.listener.BigProjectLogger;
38  import org.apache.tools.ant.taskdefs.Typedef;
39  import org.codehaus.plexus.util.IOUtil;
40  
41  /**
42   * TODO NXBT-258
43   */
44  public class AntClient {
45  
46      private static final ThreadLocal<Project> instance = new ThreadLocal<>();
47  
48      public final static String MAVEN_CLIENT_REF = "maven.client.ref";
49  
50      protected ClassLoader loader;
51  
52      protected Project project;
53  
54      protected boolean allowInput = false;
55  
56      protected Log mavenLog;
57  
58      private static final FileCleaningTracker FILE_CLEANING_TRACKER = new FileCleaningTracker();
59  
60      public boolean isAllowInput() {
61          return allowInput;
62      }
63  
64      public void setAllowInput(boolean allowInput) {
65          this.allowInput = allowInput;
66      }
67  
68      public AntClient(Log logger) {
69          this(null, logger);
70      }
71  
72      public AntClient(ClassLoader loader, Log logger) {
73          if (loader == null) {
74              loader = Thread.currentThread().getContextClassLoader();
75              if (loader == null) {
76                  loader = AntClient.class.getClassLoader();
77              }
78          }
79          this.loader = loader;
80          this.mavenLog = logger;
81          project = new Project();
82          project.setCoreLoader(loader);
83          project.setKeepGoingMode(false);
84          project.addBuildListener(createLogger());
85          project.init();
86          initTasks();
87          instance.set(project);
88      }
89  
90      /**
91       * @since 2.0
92       */
93      public static Project getInstance() {
94          return instance.get();
95      }
96  
97      /**
98       * xmlns:nx="urn:nuxeo-build"
99       * xmlns:artifact="urn:nuxeo-artifact"
100      *
101      * @since 2.0
102      */
103     protected void initTasks() {
104         project.log("Initialize Ant Tasks", Project.MSG_DEBUG);
105         Typedef typedef = new Typedef();
106         typedef.setProject(project);
107         typedef.setResource("org/nuxeo/build/antlib.xml");
108         typedef.setURI("urn:nuxeo-build");
109         typedef.execute();
110         typedef = new Typedef();
111         typedef.setProject(project);
112         typedef.setResource("org/nuxeo/build/artifact/antlib.xml");
113         typedef.setURI("urn:nuxeo-artifact");
114         typedef.execute();
115     }
116 
117     public Project getProject() {
118         return project;
119     }
120 
121     public void run(File buildFile) throws BuildException {
122         run(buildFile, (List<String>) null);
123     }
124 
125     public void run(URL buildFile) throws BuildException {
126         run(saveURL(buildFile), null);
127     }
128 
129     public void run(URL buildFile, List<String> targets) throws BuildException {
130         run(saveURL(buildFile), targets);
131     }
132 
133     public void run(File buildFile, List<String> targets) throws BuildException {
134         PrintStream previousErr = System.err;
135         PrintStream previousOut = System.out;
136         InputStream in = System.in;
137         InputStream newIn = null;
138         PrintStream newOut = null;
139         PrintStream newErr = null;
140         try {
141             // Configure IO
142             InputHandler handler = new DefaultInputHandler();
143             project.setInputHandler(handler);
144             if (allowInput) {
145                 project.setDefaultInputStream(System.in);
146             }
147             newIn = new DemuxInputStream(project);
148             System.setIn(newIn);
149             newOut = new PrintStream(new DemuxOutputStream(project, false));
150             System.setOut(newOut);
151             newErr = new PrintStream(new DemuxOutputStream(project, true));
152             System.setErr(newErr);
153 
154             if (!buildFile.isAbsolute()) {
155                 buildFile = new File(project.getBaseDir(), buildFile.getPath());
156             }
157             project.setUserProperty("ant.file", buildFile.getPath());
158             ProjectHelper.configureProject(project, buildFile);
159 
160             project.fireBuildStarted();
161             if (targets != null) {
162                 project.getExecutor().executeTargets(project,
163                         targets.toArray(new String[targets.size()]));
164             } else {
165                 project.getExecutor().executeTargets(project,
166                         new String[] { project.getDefaultTarget() });
167             }
168             project.fireBuildFinished(null);
169         } catch (BuildException e) {
170             project.fireBuildFinished(e);
171             throw e;
172         } finally {
173             System.setOut(previousOut);
174             System.setErr(previousErr);
175             System.setIn(in);
176             IOUtil.close(newIn);
177             IOUtil.close(newOut);
178             IOUtil.close(newErr);
179         }
180     }
181 
182     protected BuildLogger createLogger() {
183         BuildLogger logger = new BigProjectLogger() {
184 
185             @Override
186             protected void printMessage(String message, PrintStream stream,
187                     int priority) {
188                 if (priority > msgOutputLevel) {
189                     return;
190                 }
191                 String prefix;
192                 switch (priority) {
193                 case Project.MSG_ERR:
194                     prefix = "[ERROR] ";
195                     break;
196                 case Project.MSG_WARN:
197                     prefix = "[WARNING] ";
198                     break;
199                 case Project.MSG_INFO:
200                     prefix = "[INFO] ";
201                     break;
202                 case Project.MSG_VERBOSE:
203                     prefix = "[VERBOSE] ";
204                     break;
205                 case Project.MSG_DEBUG:
206                     // Fall through
207                 default:
208                     prefix = "[DEBUG] ";
209                     break;
210                 }
211                 super.printMessage(prefix + message, stream, priority);
212             }
213 
214         };
215         logger.setOutputPrintStream(System.out);
216         logger.setErrorPrintStream(System.err);
217         if (mavenLog == null) {
218             logger.setMessageOutputLevel(Project.MSG_INFO);
219         } else if (mavenLog.isDebugEnabled()) {
220             logger.setMessageOutputLevel(Project.MSG_DEBUG);
221         } else if (mavenLog.isInfoEnabled()) {
222             logger.setMessageOutputLevel(Project.MSG_INFO);
223         } else if (mavenLog.isWarnEnabled()) {
224             logger.setMessageOutputLevel(Project.MSG_WARN);
225         } else if (mavenLog.isErrorEnabled()) {
226             logger.setMessageOutputLevel(Project.MSG_ERR);
227         } else { // TRACE
228             logger.setMessageOutputLevel(Project.MSG_DEBUG);
229         }
230         return logger;
231     }
232 
233     private File saveURL(URL url) {
234         InputStream in = null;
235         FileOutputStream out = null;
236         try {
237             File file = File.createTempFile("ant_client_url_", ".tmp");
238             FILE_CLEANING_TRACKER.track(file, this);
239             in = url.openStream();
240             out = new FileOutputStream(file);
241             IOUtil.copy(in, out);
242             return file;
243         } catch (IOException e) {
244             throw new BuildException(e);
245         } finally {
246             IOUtil.close(in);
247             IOUtil.close(out);
248         }
249     }
250 }