001 /** 002 * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved. 003 * 004 * This library is free software; you can redistribute it and/or modify it under 005 * the terms of the GNU Lesser General Public License as published by the Free 006 * Software Foundation; either version 2.1 of the License, or (at your option) 007 * any later version. 008 * 009 * This library is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 011 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 012 * details. 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 FileUtil.write(classpathFile, sb.toString()); 261 } 262 263 // SVN 264 265 if (_svn) { 266 String projectFileName = "\"" + projectFile + "\""; 267 268 try { 269 _exec(_SVN_INFO + projectFileName); 270 } 271 catch (Exception e) { 272 _exec(_SVN_ADD + projectFileName); 273 } 274 275 if (javaProject) { 276 String classpathFileName = "\"" + classpathFile + "\""; 277 278 try { 279 _exec(_SVN_INFO + classpathFileName); 280 } 281 catch (Exception e) { 282 _exec(_SVN_ADD + classpathFileName); 283 } 284 } 285 286 File tempFile = File.createTempFile("svn-ignores-", null, null); 287 288 try { 289 FileUtil.write(tempFile, "bin\ntmp"); 290 291 _exec( 292 _SVN_SET_IGNORES + "-F \"" + tempFile.getCanonicalPath() + 293 "\" \"" + projectDirName + "\""); 294 } 295 finally { 296 FileUtil.delete(tempFile); 297 } 298 } 299 } 300 301 public void updateLibIgnores(File libDir, String[] jars) throws Exception { 302 if (!_isSVNDir(libDir)) { 303 return; 304 } 305 306 File tempFile = null; 307 308 try { 309 String libDirName = "\"" + libDir.getCanonicalPath() + "\""; 310 311 String[] oldIgnores = _exec(_SVN_GET_IGNORES + libDirName); 312 313 Arrays.sort(oldIgnores); 314 315 if (Arrays.equals(oldIgnores, jars)) { 316 return; 317 } 318 319 tempFile = File.createTempFile("svn-ignores-", null, null); 320 321 _exec(_SVN_DEL_IGNORES + libDirName); 322 323 if (jars.length == 0) { 324 FileUtil.write(tempFile, StringPool.BLANK); 325 } 326 else { 327 StringBundler sb = new StringBundler(jars.length * 2); 328 329 for (String jar : jars) { 330 sb.append(jar); 331 sb.append("\n"); 332 } 333 334 FileUtil.write(tempFile, sb.toString()); 335 } 336 337 _exec( 338 _SVN_SET_IGNORES + "-F \"" + tempFile.getCanonicalPath() + 339 "\" \"" + libDirName + "\""); 340 341 String[] newIgnores = _exec( 342 _SVN_GET_IGNORES + "\"" + libDirName + "\""); 343 344 if (newIgnores.length > 0) { 345 Arrays.sort(newIgnores); 346 } 347 } 348 finally { 349 if (tempFile != null) { 350 FileUtil.delete(tempFile); 351 } 352 } 353 } 354 355 private void _addClasspathEntry(StringBundler sb, String jar) 356 throws Exception { 357 358 sb.append("\t<classpathentry kind=\"lib\" path=\""); 359 sb.append(jar); 360 sb.append("\" />\n"); 361 } 362 363 private String[] _exec(String cmd) throws Exception { 364 Process process = Runtime.getRuntime().exec(cmd); 365 366 String[] stdout = _getExecOutput(process.getInputStream()); 367 String[] stderr = _getExecOutput(process.getErrorStream()); 368 369 if (stderr.length > 0) { 370 StringBundler sb = new StringBundler(stderr.length * 3 + 3); 371 372 sb.append("Received errors in executing '"); 373 sb.append(cmd); 374 sb.append("'\n"); 375 376 for (String err : stderr) { 377 sb.append("\t"); 378 sb.append(err); 379 sb.append("\n"); 380 } 381 382 throw new Exception(sb.toString()); 383 } 384 385 return stdout; 386 } 387 388 private String[] _getExecOutput(InputStream is) throws IOException { 389 List<String> list = new ArrayList<String>(); 390 391 UnsyncBufferedReader unsyncBufferedReader = null; 392 393 try { 394 unsyncBufferedReader = new UnsyncBufferedReader( 395 new InputStreamReader(is)); 396 397 String line = unsyncBufferedReader.readLine(); 398 399 while (line != null) { 400 line = line.trim(); 401 402 if (Validator.isNotNull(line)) { 403 list.add(line); 404 } 405 406 line = unsyncBufferedReader.readLine(); 407 } 408 } 409 finally { 410 if (unsyncBufferedReader != null) { 411 try { 412 unsyncBufferedReader.close(); 413 } 414 catch (Exception e) { 415 } 416 } 417 } 418 419 return list.toArray(new String[] {}); 420 } 421 422 private boolean _isSVNDir(File libDir) { 423 if (!libDir.exists()) { 424 return false; 425 } 426 427 try { 428 _exec(_SVN_INFO + "\"" + libDir + "\""); 429 } 430 catch (Exception e) { 431 return false; 432 } 433 434 return true; 435 } 436 437 private static final String _SVN_ADD = "svn add "; 438 439 private static final String _SVN_DEL_IGNORES = "svn propdel svn:ignore "; 440 441 private static final String _SVN_GET_IGNORES = "svn propget svn:ignore "; 442 443 private static final String _SVN_INFO = "svn info "; 444 445 private static final String _SVN_SET_IGNORES = "svn propset svn:ignore "; 446 447 private boolean _svn; 448 449 }