1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.tools;
24  
25  import com.liferay.portal.kernel.util.FileUtil;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.ListUtil;
28  import com.liferay.portal.kernel.util.StringUtil;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.util.InitUtil;
31  
32  import java.io.BufferedReader;
33  import java.io.File;
34  import java.io.FileInputStream;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.InputStreamReader;
38  
39  import java.util.ArrayList;
40  import java.util.Arrays;
41  import java.util.List;
42  import java.util.Properties;
43  
44  import org.apache.oro.io.GlobFilenameFilter;
45  import org.apache.tools.ant.DirectoryScanner;
46  
47  /**
48   * <a href="PluginsEnvironmentBuilder.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Alexander Chow
51   * @author Brian Wing Shun Chan
52   */
53  public class PluginsEnvironmentBuilder {
54  
55      public static void main(String[] args) throws Exception {
56          InitUtil.initWithSpring();
57  
58          File dir = new File(System.getProperty("plugins.env.dir"));
59          boolean svn = GetterUtil.getBoolean(
60              System.getProperty("plugins.env.svn"));
61          boolean eclipse = GetterUtil.getBoolean(
62              System.getProperty("plugins.env.eclipse"));
63  
64          new PluginsEnvironmentBuilder(dir, svn, eclipse);
65      }
66  
67      public PluginsEnvironmentBuilder(File dir, boolean svn, boolean eclipse) {
68          try {
69              _svn = svn;
70  
71              DirectoryScanner ds = new DirectoryScanner();
72  
73              ds.setBasedir(dir);
74              ds.setIncludes(
75                  new String[] {
76                      "**\\liferay-plugin-package.properties",
77                  });
78  
79              ds.scan();
80  
81              String dirName = dir.getCanonicalPath();
82  
83              String[] fileNames = ds.getIncludedFiles();
84  
85              for (String fileName : fileNames) {
86                  File propertiesFile = new File(dirName + "/" + fileName);
87                  File libDir = new File(propertiesFile.getParent() + "/lib");
88                  File projectDir = new File(
89                      propertiesFile.getParent() + "/../..");
90  
91                  Properties properties = new Properties();
92  
93                  properties.load(new FileInputStream(propertiesFile));
94  
95                  List<String> dependencyJars = ListUtil.toList(StringUtil.split(
96                      properties.getProperty(
97                          "portal-dependency-jars",
98                          properties.getProperty("portal.dependency.jars"))));
99  
100                 if (svn) {
101                     List<String> jars = new ArrayList<String>(dependencyJars);
102 
103                     jars.add("commons-logging.jar");
104                     jars.add("log4j.jar");
105                     jars.add("util-bridges.jar");
106                     jars.add("util-java.jar");
107                     jars.add("util-taglib.jar");
108 
109                     jars = ListUtil.sort(jars);
110 
111                     updateLibIgnores(
112                         libDir, jars.toArray(new String[jars.size()]));
113                 }
114 
115                 if (eclipse) {
116                     updateEclipseFiles(libDir, projectDir, dependencyJars);
117                 }
118             }
119         }
120         catch (Exception e) {
121             e.printStackTrace();
122         }
123     }
124 
125     public void updateEclipseFiles(
126             File libDir, File projectDir, List<String> dependencyJars)
127         throws Exception {
128 
129         String projectDirName = projectDir.getCanonicalPath();
130         String projectName = StringUtil.extractLast(
131             projectDirName, File.separator);
132 
133         // .project
134 
135         StringBuilder sb = new StringBuilder();
136 
137         sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
138         sb.append("<projectDescription>\n");
139         sb.append("\t<name>" + projectName + "</name>\n");
140         sb.append("\t<comment></comment>\n");
141         sb.append("\t<projects></projects>\n");
142         sb.append("\t<buildSpec>\n");
143         sb.append("\t\t<buildCommand>\n");
144         sb.append("\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n");
145         sb.append("\t\t\t<arguments></arguments>\n");
146         sb.append("\t\t</buildCommand>\n");
147         sb.append("\t</buildSpec>\n");
148         sb.append("\t<natures>\n");
149         sb.append("\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n");
150         sb.append("\t</natures>\n");
151         sb.append("</projectDescription>");
152 
153         File projectFile = new File(projectDirName + "/.project");
154 
155         System.out.println("Updating " + projectFile);
156 
157         FileUtil.write(projectFile, sb.toString());
158 
159         // .classpath
160 
161         List<String> portalJars = new ArrayList<String>(dependencyJars);
162 
163         portalJars.add("commons-logging.jar");
164         portalJars.add("log4j.jar");
165 
166         portalJars = ListUtil.sort(portalJars);
167 
168         String[] customJarsArray = libDir.list(new GlobFilenameFilter("*.jar"));
169 
170         List<String> customJars = null;
171 
172         if (customJarsArray != null) {
173             customJars = ListUtil.toList(customJarsArray);
174 
175             customJars = ListUtil.sort(customJars);
176 
177             for (String jar : portalJars) {
178                 customJars.remove(jar);
179             }
180 
181             customJars.remove(projectName + "-service.jar");
182             customJars.remove("util-bridges.jar");
183             customJars.remove("util-java.jar");
184             customJars.remove("util-taglib.jar");
185         }
186         else {
187             customJars = new ArrayList<String>();
188         }
189 
190         sb = new StringBuilder();
191 
192         sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
193         sb.append("<classpath>\n");
194 
195         if (FileUtil.exists(projectDirName + "/docroot/WEB-INF/service")) {
196             sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" ");
197             sb.append("kind=\"src\" path=\"docroot/WEB-INF/service\" />\n");
198         }
199 
200         sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" ");
201         sb.append("kind=\"src\" path=\"docroot/WEB-INF/src\" />\n");
202         sb.append("\t<classpathentry kind=\"src\" path=\"/portal\" />\n");
203         sb.append("\t<classpathentry kind=\"con\" ");
204         sb.append("path=\"org.eclipse.jdt.launching.JRE_CONTAINER\" />\n");
205 
206         if (FileUtil.exists(projectDirName + "/docroot/WEB-INF/test")) {
207             sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" ");
208             sb.append("kind=\"src\" path=\"docroot/WEB-INF/test\" />\n");
209         }
210 
211         _addClasspathEntry(sb, "/portal/lib/development/activation.jar");
212         _addClasspathEntry(sb, "/portal/lib/development/jsp-api.jar");
213         _addClasspathEntry(sb, "/portal/lib/development/mail.jar");
214         _addClasspathEntry(sb, "/portal/lib/development/servlet-api.jar");
215         _addClasspathEntry(sb, "/portal/lib/global/annotations.jar");
216         _addClasspathEntry(sb, "/portal/lib/global/portlet.jar");
217 
218         for (String jar : portalJars) {
219             _addClasspathEntry(sb, "/portal/lib/portal/" + jar);
220         }
221 
222         _addClasspathEntry(sb, "/portal/portal-kernel/portal-kernel.jar");
223         _addClasspathEntry(sb, "/portal/portal-service/portal-service.jar");
224         _addClasspathEntry(sb, "/portal/util-bridges/util-bridges.jar");
225         _addClasspathEntry(sb, "/portal/util-java/util-java.jar");
226         _addClasspathEntry(sb, "/portal/util-taglib/util-taglib.jar");
227 
228         for (String jar : customJars) {
229             _addClasspathEntry(sb, "docroot/WEB-INF/lib/" + jar);
230         }
231 
232         sb.append("\t<classpathentry kind=\"output\" path=\"bin\" />\n");
233         sb.append("</classpath>");
234 
235         File classpathFile = new File(projectDirName + "/.classpath");
236 
237         System.out.println("Updating " + classpathFile);
238 
239         FileUtil.write(classpathFile, sb.toString());
240 
241         // SVN
242 
243         if (_svn) {
244             String projectFileName = "\"" + projectFile + "\"";
245 
246             try {
247                 _exec(_SVN_INFO + projectFileName);
248             }
249             catch (Exception e) {
250                 _exec(_SVN_ADD + projectFileName);
251             }
252 
253             String classpathFileName = "\"" + classpathFile + "\"";
254 
255             try {
256                 _exec(_SVN_INFO + classpathFileName);
257             }
258             catch (Exception e) {
259                 _exec(_SVN_ADD + classpathFileName);
260             }
261 
262             File tempFile = File.createTempFile("svn-ignores-", null, null);
263 
264             try {
265                 FileUtil.write(tempFile, "bin\ntmp");
266 
267                 _exec(
268                     _SVN_SET_IGNORES + "-F \"" + tempFile.getCanonicalPath() +
269                         "\" \"" + projectDirName + "\"");
270             }
271             finally {
272                 FileUtil.delete(tempFile);
273             }
274         }
275     }
276 
277     public void updateLibIgnores(File libDir, String[] jars) throws Exception {
278         if (!_isSVNDir(libDir)) {
279             return;
280         }
281 
282         File tempFile = null;
283 
284         try {
285             String libDirName = "\"" + libDir.getCanonicalPath() + "\"";
286 
287             String[] oldIgnores = _exec(_SVN_GET_IGNORES + libDirName);
288 
289             Arrays.sort(oldIgnores);
290 
291             if (Arrays.equals(oldIgnores, jars)) {
292                 return;
293             }
294 
295             tempFile = File.createTempFile("svn-ignores-", null, null);
296 
297             _exec(_SVN_DEL_IGNORES + libDirName);
298 
299             StringBuilder sb = new StringBuilder();
300 
301             for (String jar : jars) {
302                 sb.append(jar + "\n");
303             }
304 
305             FileUtil.write(tempFile, sb.toString());
306 
307             _exec(
308                 _SVN_SET_IGNORES + "-F \"" + tempFile.getCanonicalPath() +
309                     "\" \"" + libDirName + "\"");
310 
311             String[] newIgnores = _exec(
312                 _SVN_GET_IGNORES + "\"" + libDirName + "\"");
313 
314             if (newIgnores.length > 0) {
315                 Arrays.sort(newIgnores);
316             }
317         }
318         finally {
319             if (tempFile != null) {
320                 FileUtil.delete(tempFile);
321             }
322         }
323     }
324 
325     private void _addClasspathEntry(StringBuilder sb, String jar)
326         throws Exception {
327 
328         sb.append("\t<classpathentry kind=\"lib\" path=\"");
329         sb.append(jar);
330         sb.append("\" />\n");
331     }
332 
333     private String[] _exec(String cmd) throws Exception {
334         Process process = Runtime.getRuntime().exec(cmd);
335 
336         String[] stdout = _getExecOutput(process.getInputStream());
337         String[] stderr = _getExecOutput(process.getErrorStream());
338 
339         if (stderr.length > 0) {
340             StringBuilder sb = new StringBuilder();
341 
342             sb.append("Received errors in executing '" + cmd + "'\n");
343 
344             for (String err : stderr) {
345                 sb.append("\t" + err + "\n");
346             }
347 
348             throw new Exception(sb.toString());
349         }
350 
351         return stdout;
352     }
353 
354     private String[] _getExecOutput(InputStream is) throws IOException {
355         List<String> list = new ArrayList<String>();
356 
357         BufferedReader br = null;
358 
359         try {
360             br = new BufferedReader(new InputStreamReader(is));
361 
362             String line = br.readLine();
363 
364             while (line != null) {
365                 line = line.trim();
366 
367                 if (Validator.isNotNull(line)) {
368                     list.add(line);
369                 }
370 
371                 line = br.readLine();
372             }
373         }
374         finally {
375             if (br != null) {
376                 try {
377                     br.close();
378                 }
379                 catch (Exception e) {
380                 }
381             }
382         }
383 
384         return list.toArray(new String[] {});
385     }
386 
387     private boolean _isSVNDir(File libDir) {
388         if (!libDir.exists()) {
389             return false;
390         }
391 
392         try {
393             _exec(_SVN_INFO + "\"" + libDir + "\"");
394         }
395         catch (Exception e) {
396             return false;
397         }
398 
399         return true;
400     }
401 
402     private static final String _SVN_ADD = "svn add ";
403 
404     private static final String _SVN_DEL_IGNORES = "svn propdel svn:ignore ";
405 
406     private static final String _SVN_GET_IGNORES = "svn propget svn:ignore ";
407 
408     private static final String _SVN_INFO = "svn info ";
409 
410     private static final String _SVN_SET_IGNORES = "svn propset svn:ignore ";
411 
412     private boolean _svn;
413 
414 }