001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.tools;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
018    import com.liferay.portal.kernel.util.FileUtil;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.ListUtil;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.util.InitUtil;
026    
027    import java.io.File;
028    import java.io.FileInputStream;
029    import java.io.IOException;
030    import java.io.InputStream;
031    import java.io.InputStreamReader;
032    
033    import java.util.ArrayList;
034    import java.util.Arrays;
035    import java.util.List;
036    import java.util.Properties;
037    
038    import org.apache.oro.io.GlobFilenameFilter;
039    import org.apache.tools.ant.DirectoryScanner;
040    
041    /**
042     * @author Alexander Chow
043     * @author Brian Wing Shun Chan
044     */
045    public class PluginsEnvironmentBuilder {
046    
047            public static void main(String[] args) throws Exception {
048                    InitUtil.initWithSpring();
049    
050                    File dir = new File(System.getProperty("plugins.env.dir"));
051                    boolean svn = GetterUtil.getBoolean(
052                            System.getProperty("plugins.env.svn"));
053                    boolean eclipse = GetterUtil.getBoolean(
054                            System.getProperty("plugins.env.eclipse"));
055    
056                    new PluginsEnvironmentBuilder(dir, svn, eclipse);
057            }
058    
059            public PluginsEnvironmentBuilder(File dir, boolean svn, boolean eclipse) {
060                    try {
061                            _svn = svn;
062    
063                            DirectoryScanner ds = new DirectoryScanner();
064    
065                            ds.setBasedir(dir);
066                            ds.setIncludes(
067                                    new String[] {
068                                            "**\\liferay-plugin-package.properties",
069                                    });
070    
071                            ds.scan();
072    
073                            String dirName = dir.getCanonicalPath();
074    
075                            String[] fileNames = ds.getIncludedFiles();
076    
077                            for (String fileName : fileNames) {
078                                    File propertiesFile = new File(dirName + "/" + fileName);
079                                    File libDir = new File(propertiesFile.getParent() + "/lib");
080                                    File projectDir = new File(
081                                            propertiesFile.getParent() + "/../..");
082    
083                                    Properties properties = new Properties();
084    
085                                    properties.load(new FileInputStream(propertiesFile));
086    
087                                    String[] dependencyJars = StringUtil.split(
088                                            properties.getProperty(
089                                                    "portal-dependency-jars",
090                                                    properties.getProperty("portal.dependency.jars")));
091    
092                                    if (svn) {
093                                            List<String> jars = ListUtil.toList(dependencyJars);
094    
095                                            jars.add("commons-logging.jar");
096                                            jars.add("log4j.jar");
097                                            jars.add("util-bridges.jar");
098                                            jars.add("util-java.jar");
099                                            jars.add("util-taglib.jar");
100    
101                                            jars = ListUtil.sort(jars);
102    
103                                            updateLibIgnores(
104                                                    libDir, jars.toArray(new String[jars.size()]));
105                                    }
106    
107                                    if (eclipse) {
108                                            updateEclipseFiles(libDir, projectDir, dependencyJars);
109                                    }
110                            }
111                    }
112                    catch (Exception e) {
113                            e.printStackTrace();
114                    }
115            }
116    
117            public void updateEclipseFiles(
118                            File libDir, File projectDir, String[] dependencyJars)
119                    throws Exception {
120    
121                    String libDirPath = libDir.getPath();
122    
123                    libDirPath = StringUtil.replace(
124                            libDirPath, StringPool.BACK_SLASH, StringPool.SLASH);
125    
126                    String projectDirName = projectDir.getCanonicalPath();
127                    String projectName = StringUtil.extractLast(
128                            projectDirName, File.separator);
129    
130                    boolean javaProject = false;
131    
132                    if (FileUtil.exists(projectDirName + "/docroot/WEB-INF/src")) {
133                            javaProject = true;
134                    }
135    
136                    // .project
137    
138                    StringBundler sb = new StringBundler(17);
139    
140                    sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
141                    sb.append("<projectDescription>\n");
142                    sb.append("\t<name>");
143                    sb.append(projectName);
144                    sb.append("</name>\n");
145                    sb.append("\t<comment></comment>\n");
146                    sb.append("\t<projects></projects>\n");
147                    sb.append("\t<buildSpec>\n");
148    
149                    if (javaProject) {
150                            sb.append("\t\t<buildCommand>\n");
151                            sb.append("\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n");
152                            sb.append("\t\t\t<arguments></arguments>\n");
153                            sb.append("\t\t</buildCommand>\n");
154                    }
155    
156                    sb.append("\t</buildSpec>\n");
157                    sb.append("\t<natures>\n");
158    
159                    if (javaProject) {
160                            sb.append("\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n");
161                    }
162    
163                    sb.append("\t</natures>\n");
164                    sb.append("</projectDescription>");
165    
166                    File projectFile = new File(projectDirName + "/.project");
167    
168                    System.out.println("Updating " + projectFile);
169    
170                    FileUtil.write(projectFile, sb.toString());
171    
172                    // .classpath
173    
174                    File classpathFile = null;
175    
176                    if (javaProject) {
177                            List<String> portalJars = ListUtil.toList(dependencyJars);
178    
179                            portalJars.add("commons-logging.jar");
180                            portalJars.add("log4j.jar");
181    
182                            portalJars = ListUtil.sort(portalJars);
183    
184                            String[] customJarsArray = libDir.list(
185                                    new GlobFilenameFilter("*.jar"));
186    
187                            List<String> customJars = null;
188    
189                            if (customJarsArray != null) {
190                                    customJars = ListUtil.toList(customJarsArray);
191    
192                                    customJars = ListUtil.sort(customJars);
193    
194                                    for (String jar : portalJars) {
195                                            customJars.remove(jar);
196                                    }
197    
198                                    customJars.remove(projectName + "-service.jar");
199                                    customJars.remove("util-bridges.jar");
200                                    customJars.remove("util-java.jar");
201                                    customJars.remove("util-taglib.jar");
202                            }
203                            else {
204                                    customJars = new ArrayList<String>();
205                            }
206    
207                            sb = new StringBundler();
208    
209                            sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
210                            sb.append("<classpath>\n");
211    
212                            if (FileUtil.exists(projectDirName + "/docroot/WEB-INF/service")) {
213                                    sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" ");
214                                    sb.append("kind=\"src\" path=\"docroot/WEB-INF/service\" />\n");
215                            }
216    
217                            sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" ");
218                            sb.append("kind=\"src\" path=\"docroot/WEB-INF/src\" />\n");
219                            sb.append("\t<classpathentry kind=\"src\" path=\"/portal\" />\n");
220                            sb.append("\t<classpathentry kind=\"con\" ");
221                            sb.append("path=\"org.eclipse.jdt.launching.JRE_CONTAINER\" />\n");
222    
223                            if (FileUtil.exists(projectDirName + "/docroot/WEB-INF/test")) {
224                                    sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" ");
225                                    sb.append("kind=\"src\" path=\"docroot/WEB-INF/test\" />\n");
226                            }
227    
228                            _addClasspathEntry(sb, "/portal/lib/development/activation.jar");
229                            _addClasspathEntry(sb, "/portal/lib/development/annotations.jar");
230                            _addClasspathEntry(sb, "/portal/lib/development/jsp-api.jar");
231                            _addClasspathEntry(sb, "/portal/lib/development/mail.jar");
232                            _addClasspathEntry(sb, "/portal/lib/development/servlet-api.jar");
233                            _addClasspathEntry(sb, "/portal/lib/global/portlet.jar");
234    
235                            for (String jar : portalJars) {
236                                    _addClasspathEntry(sb, "/portal/lib/portal/" + jar);
237                            }
238    
239                            _addClasspathEntry(sb, "/portal/portal-service/portal-service.jar");
240                            _addClasspathEntry(sb, "/portal/util-bridges/util-bridges.jar");
241                            _addClasspathEntry(sb, "/portal/util-java/util-java.jar");
242                            _addClasspathEntry(sb, "/portal/util-taglib/util-taglib.jar");
243    
244                            for (String jar : customJars) {
245                                    if (libDirPath.contains("/tmp/WEB-INF/lib")) {
246                                            _addClasspathEntry(sb, "tmp/WEB-INF/lib/" + jar);
247                                    }
248                                    else {
249                                            _addClasspathEntry(sb, "docroot/WEB-INF/lib/" + jar);
250                                    }
251                            }
252    
253                            sb.append("\t<classpathentry kind=\"output\" path=\"bin\" />\n");
254                            sb.append("</classpath>");
255    
256                            classpathFile = new File(projectDirName + "/.classpath");
257    
258                            System.out.println("Updating " + classpathFile);
259    
260                            String content = sb.toString();
261    
262                            content = StringUtil.replace(
263                                    content, "\"/portal", "\"/portal-trunk");
264    
265                            FileUtil.write(classpathFile, content);
266                    }
267    
268                    // SVN
269    
270                    if (_svn) {
271                            String projectFileName = "\"" + projectFile + "\"";
272    
273                            try {
274                                    _exec(_SVN_INFO + projectFileName);
275                            }
276                            catch (Exception e) {
277                                    _exec(_SVN_ADD + projectFileName);
278                            }
279    
280                            if (javaProject) {
281                                    String classpathFileName = "\"" + classpathFile + "\"";
282    
283                                    try {
284                                            _exec(_SVN_INFO + classpathFileName);
285                                    }
286                                    catch (Exception e) {
287                                            _exec(_SVN_ADD + classpathFileName);
288                                    }
289                            }
290    
291                            File tempFile = File.createTempFile("svn-ignores-", null, null);
292    
293                            try {
294                                    FileUtil.write(tempFile, "bin\ntmp");
295    
296                                    _exec(
297                                            _SVN_SET_IGNORES + "-F \"" + tempFile.getCanonicalPath() +
298                                                    "\" \"" + projectDirName + "\"");
299                            }
300                            finally {
301                                    FileUtil.delete(tempFile);
302                            }
303                    }
304            }
305    
306            public void updateLibIgnores(File libDir, String[] jars) throws Exception {
307                    if (!_isSVNDir(libDir)) {
308                            return;
309                    }
310    
311                    File tempFile = null;
312    
313                    try {
314                            String libDirName = "\"" + libDir.getCanonicalPath() + "\"";
315    
316                            String[] oldIgnores = _exec(_SVN_GET_IGNORES + libDirName);
317    
318                            Arrays.sort(oldIgnores);
319    
320                            if (Arrays.equals(oldIgnores, jars)) {
321                                    return;
322                            }
323    
324                            tempFile = File.createTempFile("svn-ignores-", null, null);
325    
326                            _exec(_SVN_DEL_IGNORES + libDirName);
327    
328                            if (jars.length == 0) {
329                                    FileUtil.write(tempFile, StringPool.BLANK);
330                            }
331                            else {
332                                    StringBundler sb = new StringBundler(jars.length * 2);
333    
334                                    for (String jar : jars) {
335                                            sb.append(jar);
336                                            sb.append("\n");
337                                    }
338    
339                                    FileUtil.write(tempFile, sb.toString());
340                            }
341    
342                            _exec(
343                                    _SVN_SET_IGNORES + "-F \"" + tempFile.getCanonicalPath() +
344                                            "\" \"" + libDirName + "\"");
345    
346                            String[] newIgnores = _exec(
347                                    _SVN_GET_IGNORES + "\"" + libDirName + "\"");
348    
349                            if (newIgnores.length > 0) {
350                                    Arrays.sort(newIgnores);
351                            }
352                    }
353                    finally {
354                            if (tempFile != null) {
355                                    FileUtil.delete(tempFile);
356                            }
357                    }
358            }
359    
360            private void _addClasspathEntry(StringBundler sb, String jar)
361                    throws Exception {
362    
363                    sb.append("\t<classpathentry kind=\"lib\" path=\"");
364                    sb.append(jar);
365                    sb.append("\" />\n");
366            }
367    
368            private String[] _exec(String cmd) throws Exception {
369                    Process process = Runtime.getRuntime().exec(cmd);
370    
371                    String[] stdout = _getExecOutput(process.getInputStream());
372                    String[] stderr = _getExecOutput(process.getErrorStream());
373    
374                    if (stderr.length > 0) {
375                            StringBundler sb = new StringBundler(stderr.length * 3 + 3);
376    
377                            sb.append("Received errors in executing '");
378                            sb.append(cmd);
379                            sb.append("'\n");
380    
381                            for (String err : stderr) {
382                                    sb.append("\t");
383                                    sb.append(err);
384                                    sb.append("\n");
385                            }
386    
387                            throw new Exception(sb.toString());
388                    }
389    
390                    return stdout;
391            }
392    
393            private String[] _getExecOutput(InputStream is) throws IOException {
394                    List<String> list = new ArrayList<String>();
395    
396                    UnsyncBufferedReader unsyncBufferedReader = null;
397    
398                    try {
399                            unsyncBufferedReader = new UnsyncBufferedReader(
400                                    new InputStreamReader(is));
401    
402                            String line = unsyncBufferedReader.readLine();
403    
404                            while (line != null) {
405                                    line = line.trim();
406    
407                                    if (Validator.isNotNull(line)) {
408                                            list.add(line);
409                                    }
410    
411                                    line = unsyncBufferedReader.readLine();
412                            }
413                    }
414                    finally {
415                            if (unsyncBufferedReader != null) {
416                                    try {
417                                            unsyncBufferedReader.close();
418                                    }
419                                    catch (Exception e) {
420                                    }
421                            }
422                    }
423    
424                    return list.toArray(new String[] {});
425            }
426    
427            private boolean _isSVNDir(File libDir) {
428                    if (!libDir.exists()) {
429                            return false;
430                    }
431    
432                    try {
433                            _exec(_SVN_INFO + "\"" + libDir + "\"");
434                    }
435                    catch (Exception e) {
436                            return false;
437                    }
438    
439                    return true;
440            }
441    
442            private static final String _SVN_ADD = "svn add ";
443    
444            private static final String _SVN_DEL_IGNORES = "svn propdel svn:ignore ";
445    
446            private static final String _SVN_GET_IGNORES = "svn propget svn:ignore ";
447    
448            private static final String _SVN_INFO = "svn info ";
449    
450            private static final String _SVN_SET_IGNORES = "svn propset svn:ignore ";
451    
452            private boolean _svn;
453    
454    }