001 /** 002 * Copyright (c) 2000-2012 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.util.ListUtil; 018 import com.liferay.portal.kernel.util.StringBundler; 019 import com.liferay.portal.kernel.util.StringPool; 020 import com.liferay.portal.kernel.util.StringUtil; 021 import com.liferay.portal.kernel.util.UniqueList; 022 import com.liferay.portal.kernel.util.Validator; 023 import com.liferay.portal.util.FileImpl; 024 import com.liferay.portal.util.PropsValues; 025 026 import java.io.File; 027 import java.io.FileInputStream; 028 import java.io.FilenameFilter; 029 030 import java.util.ArrayList; 031 import java.util.Collections; 032 import java.util.HashMap; 033 import java.util.Iterator; 034 import java.util.List; 035 import java.util.Map; 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 try { 049 File dir = new File(System.getProperty("plugins.env.dir")); 050 051 new PluginsEnvironmentBuilder(dir); 052 } 053 catch (Exception e) { 054 e.printStackTrace(); 055 } 056 } 057 058 public PluginsEnvironmentBuilder(File dir) throws Exception { 059 DirectoryScanner ds = new DirectoryScanner(); 060 061 ds.setBasedir(dir); 062 ds.setIncludes(new String[] {"**\\liferay-plugin-package.properties"}); 063 064 ds.scan(); 065 066 String dirName = dir.getCanonicalPath(); 067 068 String[] fileNames = ds.getIncludedFiles(); 069 070 for (String fileName : fileNames) { 071 setupProject(dirName, fileName); 072 } 073 } 074 075 protected void addClasspathEntry(StringBundler sb, String jar) { 076 addClasspathEntry(sb, jar, null); 077 } 078 079 protected void addClasspathEntry( 080 StringBundler sb, String jar, Map<String, String> attributes) { 081 082 sb.append("\t<classpathentry kind=\"lib\" path=\""); 083 sb.append(jar); 084 085 if ((attributes == null) || attributes.isEmpty()) { 086 sb.append("\" />\n"); 087 088 return; 089 } 090 091 sb.append("\">\n\t\t<attributes>\n"); 092 093 Iterator<Map.Entry<String, String>> itr = 094 attributes.entrySet().iterator(); 095 096 while (itr.hasNext()) { 097 Map.Entry<String, String> entry = itr.next(); 098 099 sb.append("\t\t\t<attribute name=\""); 100 sb.append(entry.getKey()); 101 sb.append("\" value=\""); 102 sb.append(entry.getValue()); 103 sb.append("\" />\n"); 104 } 105 106 sb.append("\t\t</attributes>\n\t</classpathentry>\n"); 107 } 108 109 protected void setupProject(String dirName, String fileName) 110 throws Exception { 111 112 File propertiesFile = new File(dirName + "/" + fileName); 113 114 File libDir = new File(propertiesFile.getParent() + "/lib"); 115 116 File projectDir = new File(propertiesFile.getParent() + "/../.."); 117 118 Properties properties = new Properties(); 119 120 properties.load(new FileInputStream(propertiesFile)); 121 122 String[] dependencyJars = StringUtil.split( 123 properties.getProperty( 124 "portal-dependency-jars", 125 properties.getProperty("portal.dependency.jars"))); 126 127 List<String> jars = ListUtil.toList(dependencyJars); 128 129 jars.add("commons-logging.jar"); 130 jars.add("log4j.jar"); 131 jars.add("util-bridges.jar"); 132 jars.add("util-java.jar"); 133 jars.add("util-taglib.jar"); 134 135 Collections.sort(jars); 136 137 writeEclipseFiles(libDir, projectDir, dependencyJars); 138 139 String libDirPath = StringUtil.replace( 140 libDir.getPath(), StringPool.BACK_SLASH, StringPool.SLASH); 141 142 List<String> ignores = ListUtil.fromFile( 143 libDir.getCanonicalPath() + "/../.gitignore"); 144 145 if (!libDirPath.contains("/ext/") && !ignores.contains("/lib")) { 146 File gitignoreFile = new File( 147 libDir.getCanonicalPath() + "/.gitignore"); 148 149 System.out.println("Updating " + gitignoreFile); 150 151 String[] gitIgnores = jars.toArray(new String[jars.size()]); 152 153 for (int i = 0; i < gitIgnores.length; i++) { 154 String gitIgnore = gitIgnores[i]; 155 156 if (Validator.isNotNull(gitIgnore) && 157 !gitIgnore.startsWith("/")) { 158 159 gitIgnores[i] = "/" + gitIgnore; 160 } 161 } 162 163 _fileUtil.write(gitignoreFile, StringUtil.merge(gitIgnores, "\n")); 164 } 165 } 166 167 protected void writeClasspathFile( 168 File libDir, String[] dependencyJars, String projectDirName, 169 String projectName, boolean javaProject) 170 throws Exception { 171 172 File classpathFile = new File(projectDirName + "/.classpath"); 173 174 if (!javaProject) { 175 classpathFile.delete(); 176 177 return; 178 } 179 180 List<String> globalJars = new UniqueList<String>(); 181 List<String> portalJars = new UniqueList<String>(); 182 183 List<String> extGlobalJars = new UniqueList<String>(); 184 List<String> extPortalJars = new UniqueList<String>(); 185 186 String libDirPath = StringUtil.replace( 187 libDir.getPath(), StringPool.BACK_SLASH, StringPool.SLASH); 188 189 if (libDirPath.contains("/ext/")) { 190 FilenameFilter filenameFilter = new GlobFilenameFilter("*.jar"); 191 192 for (String dirName : new String[] {"global", "portal"}) { 193 File file = new File(libDirPath + "/../ext-lib/" + dirName); 194 195 List<String> jars = ListUtil.toList(file.list(filenameFilter)); 196 197 if (dirName.equals("global")) { 198 extGlobalJars.addAll(ListUtil.sort(jars)); 199 200 File dir = new File(PropsValues.LIFERAY_LIB_GLOBAL_DIR); 201 202 String[] fileNames = dir.list(filenameFilter); 203 204 globalJars.addAll( 205 ListUtil.sort(ListUtil.toList(fileNames))); 206 globalJars.removeAll(extGlobalJars); 207 } 208 else if (dirName.equals("portal")) { 209 extPortalJars.addAll(ListUtil.sort(jars)); 210 211 File dir = new File(PropsValues.LIFERAY_LIB_PORTAL_DIR); 212 213 String[] fileNames = dir.list(filenameFilter); 214 215 portalJars.addAll( 216 ListUtil.sort(ListUtil.toList(fileNames))); 217 portalJars.removeAll(extPortalJars); 218 } 219 } 220 } 221 else { 222 globalJars.add("portlet.jar"); 223 224 portalJars.addAll(ListUtil.toList(dependencyJars)); 225 portalJars.add("commons-logging.jar"); 226 portalJars.add("log4j.jar"); 227 228 Collections.sort(portalJars); 229 } 230 231 String[] customJarsArray = libDir.list(new GlobFilenameFilter("*.jar")); 232 233 List<String> customJars = null; 234 235 if (customJarsArray != null) { 236 customJars = ListUtil.toList(customJarsArray); 237 238 for (String jar : portalJars) { 239 customJars.remove(jar); 240 } 241 242 customJars.remove(projectName + "-service.jar"); 243 customJars.remove("util-bridges.jar"); 244 customJars.remove("util-java.jar"); 245 customJars.remove("util-taglib.jar"); 246 247 Collections.sort(customJars); 248 } 249 else { 250 customJars = new ArrayList<String>(); 251 } 252 253 StringBundler sb = new StringBundler(); 254 255 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"); 256 sb.append("<classpath>\n"); 257 258 for (String sourceDirName : _SOURCE_DIR_NAMES) { 259 if (_fileUtil.exists(projectDirName + "/" + sourceDirName)) { 260 sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" "); 261 sb.append("kind=\"src\" path=\"" + sourceDirName + "\" />\n"); 262 } 263 } 264 265 sb.append("\t<classpathentry kind=\"src\" path=\"/portal\" />\n"); 266 sb.append("\t<classpathentry kind=\"con\" "); 267 sb.append("path=\"org.eclipse.jdt.launching.JRE_CONTAINER\" />\n"); 268 269 boolean addJunitJars = false; 270 271 for (String testType :_TEST_TYPES) { 272 String testFolder = "test/" + testType; 273 274 if (_fileUtil.exists(projectDirName + "/" + testFolder)) { 275 addJunitJars = true; 276 277 sb.append("\t<classpathentry excluding=\"**/.svn/**|.svn/\" "); 278 sb.append("kind=\"src\" path=\""+ testFolder + "\" />\n"); 279 } 280 } 281 282 if (addJunitJars) { 283 addClasspathEntry(sb, "/portal/lib/development/junit.jar"); 284 addClasspathEntry(sb, "/portal/lib/portal/commons-io.jar"); 285 } 286 287 addClasspathEntry(sb, "/portal/lib/development/activation.jar"); 288 addClasspathEntry(sb, "/portal/lib/development/annotations.jar"); 289 addClasspathEntry(sb, "/portal/lib/development/jsp-api.jar"); 290 addClasspathEntry(sb, "/portal/lib/development/mail.jar"); 291 addClasspathEntry(sb, "/portal/lib/development/servlet-api.jar"); 292 293 Map<String, String> attributes = new HashMap<String, String>(); 294 295 if (libDirPath.contains("/ext/")) { 296 attributes.put("optional", "true"); 297 } 298 299 for (String jar : globalJars) { 300 addClasspathEntry(sb, "/portal/lib/global/" + jar, attributes); 301 } 302 303 for (String jar : portalJars) { 304 addClasspathEntry(sb, "/portal/lib/portal/" + jar, attributes); 305 } 306 307 addClasspathEntry(sb, "/portal/portal-service/portal-service.jar"); 308 addClasspathEntry(sb, "/portal/util-bridges/util-bridges.jar"); 309 addClasspathEntry(sb, "/portal/util-java/util-java.jar"); 310 addClasspathEntry(sb, "/portal/util-taglib/util-taglib.jar"); 311 312 for (String jar : extGlobalJars) { 313 addClasspathEntry(sb, "docroot/WEB-INF/ext-lib/global/" + jar); 314 } 315 316 for (String jar : extPortalJars) { 317 addClasspathEntry(sb, "docroot/WEB-INF/ext-lib/portal/" + jar); 318 } 319 320 for (String jar : customJars) { 321 if (libDirPath.contains("/tmp/WEB-INF/lib")) { 322 addClasspathEntry(sb, "tmp/WEB-INF/lib/" + jar); 323 } 324 else { 325 addClasspathEntry(sb, "docroot/WEB-INF/lib/" + jar); 326 } 327 } 328 329 sb.append("\t<classpathentry kind=\"output\" path=\"bin\" />\n"); 330 sb.append("</classpath>"); 331 332 System.out.println("Updating " + classpathFile); 333 334 String content = StringUtil.replace( 335 sb.toString(), "\"/portal", "\"/portal-" + _BRANCH); 336 337 _fileUtil.write(classpathFile, content); 338 } 339 340 protected void writeEclipseFiles( 341 File libDir, File projectDir, String[] dependencyJars) 342 throws Exception { 343 344 String projectDirName = projectDir.getCanonicalPath(); 345 346 String projectName = StringUtil.extractLast( 347 projectDirName, File.separatorChar); 348 349 boolean javaProject = false; 350 351 for (String sourceDirName : _SOURCE_DIR_NAMES) { 352 if (_fileUtil.exists(projectDirName + "/" + sourceDirName)) { 353 javaProject = true; 354 355 break; 356 } 357 } 358 359 if (!javaProject) { 360 System.out.println( 361 "Eclipse Java project will not be used because a source " + 362 "folder does not exist"); 363 } 364 365 writeProjectFile(projectDirName, projectName, javaProject); 366 367 writeClasspathFile( 368 libDir, dependencyJars, projectDirName, projectName, javaProject); 369 370 for (String sourceDirName : _SOURCE_DIR_NAMES) { 371 if (_fileUtil.exists(projectDirName + "/" + sourceDirName)) { 372 List<String> gitIgnores = new ArrayList<String>(); 373 374 if (sourceDirName.endsWith("ext-impl/src")) { 375 gitIgnores.add("/classes"); 376 gitIgnores.add("/ext-impl.jar"); 377 } 378 else if (sourceDirName.endsWith("ext-service/src")) { 379 gitIgnores.add("/classes"); 380 gitIgnores.add("/ext-service.jar"); 381 } 382 else if (sourceDirName.endsWith("ext-util-bridges/src")) { 383 gitIgnores.add("/classes"); 384 gitIgnores.add("/ext-util-bridges.jar"); 385 } 386 else if (sourceDirName.endsWith("ext-util-java/src")) { 387 gitIgnores.add("/classes"); 388 gitIgnores.add("/ext-util-java.jar"); 389 } 390 else if (sourceDirName.endsWith("ext-util-taglib/src")) { 391 gitIgnores.add("/classes"); 392 gitIgnores.add("/ext-util-taglib.jar"); 393 } 394 else { 395 continue; 396 } 397 398 String dirName = projectDirName + "/" + sourceDirName + "/../"; 399 400 if (gitIgnores.isEmpty()) { 401 _fileUtil.delete(dirName + ".gitignore"); 402 } 403 else { 404 String gitIgnoresString = StringUtil.merge( 405 gitIgnores, "\n"); 406 407 _fileUtil.write(dirName + ".gitignore", gitIgnoresString); 408 } 409 } 410 } 411 412 if (_fileUtil.exists(projectDirName + "/test")) { 413 _fileUtil.write( 414 projectDirName + "/.gitignore", "/test-classes\n/test-results"); 415 } 416 else { 417 _fileUtil.delete(projectDirName + "/.gitignore"); 418 } 419 } 420 421 protected void writeProjectFile( 422 String projectDirName, String projectName, boolean javaProject) 423 throws Exception { 424 425 StringBundler sb = new StringBundler(17); 426 427 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"); 428 sb.append("<projectDescription>\n"); 429 sb.append("\t<name>"); 430 sb.append(projectName); 431 sb.append("-"); 432 sb.append(_BRANCH); 433 sb.append("</name>\n"); 434 sb.append("\t<comment></comment>\n"); 435 sb.append("\t<projects></projects>\n"); 436 sb.append("\t<buildSpec>\n"); 437 438 if (javaProject) { 439 sb.append("\t\t<buildCommand>\n"); 440 sb.append("\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n"); 441 sb.append("\t\t\t<arguments></arguments>\n"); 442 sb.append("\t\t</buildCommand>\n"); 443 } 444 445 sb.append("\t</buildSpec>\n"); 446 sb.append("\t<natures>\n"); 447 448 if (javaProject) { 449 sb.append("\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n"); 450 } 451 452 sb.append("\t</natures>\n"); 453 sb.append("</projectDescription>"); 454 455 File projectFile = new File(projectDirName + "/.project"); 456 457 System.out.println("Updating " + projectFile); 458 459 _fileUtil.write(projectFile, sb.toString()); 460 } 461 462 private static final String _BRANCH = "6.1.x"; 463 464 private static final String[] _SOURCE_DIR_NAMES = new String[] { 465 "docroot/WEB-INF/ext-impl/src", "docroot/WEB-INF/ext-service/src", 466 "docroot/WEB-INF/ext-util-bridges/src", 467 "docroot/WEB-INF/ext-util-java/src", 468 "docroot/WEB-INF/ext-util-taglib/src", "docroot/WEB-INF/service", 469 "docroot/WEB-INF/src" 470 }; 471 472 private static final String[] _TEST_TYPES = {"integration", "unit"}; 473 474 private static FileImpl _fileUtil = FileImpl.getInstance(); 475 476 }