001
014
015 package com.liferay.portal.tools;
016
017 import com.liferay.portal.kernel.util.FileComparator;
018 import com.liferay.portal.kernel.util.GetterUtil;
019 import com.liferay.portal.kernel.util.ListUtil;
020 import com.liferay.portal.kernel.util.StringBundler;
021 import com.liferay.portal.kernel.util.StringPool;
022 import com.liferay.portal.kernel.util.StringUtil;
023 import com.liferay.portal.kernel.util.Validator;
024 import com.liferay.portal.kernel.xml.Document;
025 import com.liferay.portal.kernel.xml.Element;
026 import com.liferay.portal.kernel.xml.SAXReader;
027 import com.liferay.portal.util.FileImpl;
028 import com.liferay.portal.util.PropsValues;
029 import com.liferay.portal.xml.SAXReaderImpl;
030
031 import java.io.File;
032 import java.io.FileInputStream;
033 import java.io.FilenameFilter;
034
035 import java.util.ArrayList;
036 import java.util.Arrays;
037 import java.util.Collections;
038 import java.util.HashMap;
039 import java.util.LinkedHashSet;
040 import java.util.List;
041 import java.util.Map;
042 import java.util.Properties;
043 import java.util.Set;
044 import java.util.TreeSet;
045
046 import org.apache.oro.io.GlobFilenameFilter;
047 import org.apache.tools.ant.DirectoryScanner;
048
049
053 public class PluginsEnvironmentBuilder {
054
055 public static void main(String[] args) throws Exception {
056 try {
057 File dir = new File(System.getProperty("plugins.env.dir"));
058
059 new PluginsEnvironmentBuilder(dir);
060 }
061 catch (Exception e) {
062 e.printStackTrace();
063 }
064 }
065
066 public PluginsEnvironmentBuilder(File dir) throws Exception {
067 DirectoryScanner directoryScanner = new DirectoryScanner();
068
069 directoryScanner.setBasedir(dir);
070 directoryScanner.setIncludes(
071 new String[] {"**\\liferay-plugin-package.properties"});
072
073 directoryScanner.scan();
074
075 String dirName = dir.getCanonicalPath();
076
077 for (String fileName : directoryScanner.getIncludedFiles()) {
078 setupWarProject(dirName, fileName);
079 }
080
081 directoryScanner = new DirectoryScanner();
082
083 directoryScanner.setBasedir(dir);
084 directoryScanner.setIncludes(new String[] {"**\\build.xml"});
085
086 directoryScanner.scan();
087
088 for (String fileName : directoryScanner.getIncludedFiles()) {
089 String content = _fileUtil.read(dirName + "/" + fileName);
090
091 boolean osgiProject = false;
092
093 if (content.contains("../build-common-osgi-plugin.xml\" />") ||
094 content.contains(
095 "../tools/sdk/build-common-osgi-plugin.xml\" />")) {
096
097 osgiProject = true;
098 }
099
100 boolean sharedProject = false;
101
102 if (content.contains(
103 "<import file=\"../build-common-shared.xml\" />") ||
104 content.contains(
105 "../tools/sdk/build-common-shared.xml\" />")) {
106
107 sharedProject = true;
108 }
109
110 List<String> dependencyJars = Collections.emptyList();
111
112 if (osgiProject) {
113 int x = content.indexOf("osgi.ide.dependencies");
114
115 if (x != -1) {
116 x = content.indexOf("value=\"", x);
117 x = content.indexOf("\"", x);
118
119 int y = content.indexOf("\"", x + 1);
120
121 dependencyJars = Arrays.asList(
122 StringUtil.split(content.substring(x + 1, y)));
123 }
124 }
125
126 if (osgiProject || sharedProject) {
127 setupJarProject(
128 dirName, fileName, dependencyJars, sharedProject);
129 }
130 }
131 }
132
133 protected void addClasspathEntry(StringBundler sb, String jar) {
134 addClasspathEntry(sb, jar, null);
135 }
136
137 protected void addClasspathEntry(
138 StringBundler sb, String jar, Map<String, String> attributes) {
139
140 sb.append("\t<classpathentry kind=\"lib\" path=\"");
141 sb.append(jar);
142
143 if ((attributes == null) || attributes.isEmpty()) {
144 sb.append("\" />\n");
145
146 return;
147 }
148
149 sb.append("\">\n\t\t<attributes>\n");
150
151 for (Map.Entry<String, String> entry : attributes.entrySet()) {
152 sb.append("\t\t\t<attribute name=\"");
153 sb.append(entry.getKey());
154 sb.append("\" value=\"");
155 sb.append(entry.getValue());
156 sb.append("\" />\n");
157 }
158
159 sb.append("\t\t</attributes>\n\t</classpathentry>\n");
160 }
161
162 protected void addIvyCacheJar(
163 StringBundler sb, String ivyDirName, String dependencyName,
164 String version)
165 throws Exception {
166
167 String string = sb.toString();
168
169 if (string.contains(dependencyName)) {
170 System.out.println(
171 "Skipping duplicate " + dependencyName + " " + version);
172
173 return;
174 }
175
176 System.out.println("Adding " + dependencyName + " " + version);
177
178 if (version.equals("latest.integration")) {
179 File dir = new File(ivyDirName + "/cache/" + dependencyName);
180
181 File[] files = dir.listFiles();
182
183 Arrays.sort(files, new FileComparator());
184
185 for (int i = files.length - 1; i >= 0; i--) {
186 File file = files[i];
187
188 if (!file.isFile()) {
189 continue;
190 }
191
192 String fileName = file.getName();
193
194 if (!fileName.endsWith(".xml")) {
195 continue;
196 }
197
198 version = fileName.substring(4, fileName.length() - 4);
199
200 System.out.println(
201 "Substituting " + version + " for latest.integration");
202 }
203 }
204
205 String ivyFileName =
206 ivyDirName + "/cache/" + dependencyName + "/ivy-" + version +
207 ".xml";
208
209 if (_fileUtil.exists(ivyFileName)) {
210 Document document = _saxReader.read(new File(ivyFileName));
211
212 Element rootElement = document.getRootElement();
213
214 Element dependenciesElement = rootElement.element("dependencies");
215
216 if (dependenciesElement != null) {
217 List<Element> dependencyElements = dependenciesElement.elements(
218 "dependency");
219
220 for (Element dependencyElement : dependencyElements) {
221 String conf = GetterUtil.getString(
222 dependencyElement.attributeValue("conf"));
223
224 if (!conf.startsWith("compile")) {
225 continue;
226 }
227
228 String name = GetterUtil.getString(
229 dependencyElement.attributeValue("name"));
230 String org = GetterUtil.getString(
231 dependencyElement.attributeValue("org"));
232 String rev = GetterUtil.getString(
233 dependencyElement.attributeValue("rev"));
234
235 string = sb.toString();
236
237 if (string.contains(name)) {
238 continue;
239 }
240
241 addIvyCacheJar(sb, ivyDirName, org + "/" + name, rev);
242 }
243 }
244 }
245
246 String dirName = ivyDirName + "/cache/" + dependencyName + "/bundles";
247
248 if (!_fileUtil.exists(dirName)) {
249 dirName = ivyDirName + "/cache/" + dependencyName + "/jars";
250
251 if (!_fileUtil.exists(dirName)) {
252 System.out.println("Unable to find jars in " + dirName);
253
254 return;
255 }
256 }
257
258 File dir = new File(dirName);
259
260 File[] files = dir.listFiles();
261
262 for (File file : files) {
263 if (!file.isFile()) {
264 continue;
265 }
266
267 String fileName = file.getName();
268
269 if (!fileName.endsWith("-" + version + ".jar")) {
270 continue;
271 }
272
273 int index = dirName.indexOf("/.ivy");
274
275 String eclipseRelativeDirName =
276 "/portal" + dirName.substring(index);
277
278 addClasspathEntry(sb, eclipseRelativeDirName + "/" + fileName);
279
280 return;
281 }
282
283 System.out.println(
284 "Unable to find jars in " + dirName + " for " + version);
285 }
286
287 protected void addIvyCacheJars(
288 StringBundler sb, String content, String ivyDirName)
289 throws Exception {
290
291 Document document = _saxReader.read(content);
292
293 Element rootElement = document.getRootElement();
294
295 Element dependenciesElement = rootElement.element("dependencies");
296
297 List<Element> dependencyElements = dependenciesElement.elements(
298 "dependency");
299
300 for (Element dependencyElement : dependencyElements) {
301 String conf = GetterUtil.getString(
302 dependencyElement.attributeValue("conf"));
303
304 if (!conf.equals("test->default")) {
305 continue;
306 }
307
308 String name = GetterUtil.getString(
309 dependencyElement.attributeValue("name"));
310 String org = GetterUtil.getString(
311 dependencyElement.attributeValue("org"));
312 String rev = GetterUtil.getString(
313 dependencyElement.attributeValue("rev"));
314
315 addIvyCacheJar(sb, ivyDirName, org + "/" + name, rev);
316 }
317 }
318
319 protected List<String> getCommonJars() {
320 List<String> jars = new ArrayList<>();
321
322 jars.add("commons-logging.jar");
323 jars.add("log4j.jar");
324 jars.add("util-bridges.jar");
325 jars.add("util-java.jar");
326 jars.add("util-taglib.jar");
327
328 return jars;
329 }
330
331 protected List<String> getImportSharedJars(File projectDir)
332 throws Exception {
333
334 File buildXmlFile = new File(projectDir, "build.xml");
335
336 String content = _fileUtil.read(buildXmlFile);
337
338 int x = content.indexOf("import.shared");
339
340 if (x == -1) {
341 return new ArrayList<>();
342 }
343
344 x = content.indexOf("value=\"", x);
345 x = content.indexOf("\"", x);
346
347 int y = content.indexOf("\" />", x);
348
349 if ((x == -1) || (y == -1)) {
350 return new ArrayList<>();
351 }
352
353 String[] importShared = StringUtil.split(content.substring(x + 1, y));
354
355 if (importShared.length == 0) {
356 return new ArrayList<>();
357 }
358
359 List<String> jars = new ArrayList<>();
360
361 for (String currentImportShared : importShared) {
362 jars.add(currentImportShared + ".jar");
363
364 File currentImportSharedLibDir = new File(
365 projectDir, "../../shared/" + currentImportShared + "/lib");
366
367 if (!currentImportSharedLibDir.exists()) {
368 continue;
369 }
370
371 for (File file : currentImportSharedLibDir.listFiles()) {
372 jars.add(file.getName());
373 }
374 }
375
376 return jars;
377 }
378
379 protected List<String> getPortalDependencyJars(Properties properties) {
380 String[] dependencyJars = StringUtil.split(
381 properties.getProperty(
382 "portal-dependency-jars",
383 properties.getProperty("portal.dependency.jars")));
384
385 return ListUtil.toList(dependencyJars);
386 }
387
388 protected List<String> getRequiredDeploymentContextsJars(
389 File libDir, Properties properties)
390 throws Exception {
391
392 List<String> jars = new ArrayList<>();
393
394 String[] requiredDeploymentContexts = StringUtil.split(
395 properties.getProperty("required-deployment-contexts"));
396
397 for (String requiredDeploymentContext : requiredDeploymentContexts) {
398 if (_fileUtil.exists(
399 libDir.getCanonicalPath() + "/" +
400 requiredDeploymentContext + "-service.jar")) {
401
402 jars.add(requiredDeploymentContext + "-service.jar");
403 }
404 }
405
406 return jars;
407 }
408
409 protected boolean hasModulesGitIgnore(String dirName) {
410 int index = dirName.indexOf("/modules/");
411
412 if (index == -1) {
413 return false;
414 }
415
416 return _fileUtil.exists(
417 dirName.substring(0, index) + "/modules/.gitignore");
418 }
419
420 protected void setupJarProject(
421 String dirName, String fileName, List<String> dependencyJars,
422 boolean sharedProject)
423 throws Exception {
424
425 File buildFile = new File(dirName + "/" + fileName);
426
427 File projectDir = new File(buildFile.getParent());
428
429 File libDir = new File(projectDir, "lib");
430
431 if (!libDir.exists()) {
432 libDir = new File(projectDir, "docroot/WEB-INF/lib");
433 }
434
435 writeEclipseFiles(libDir, projectDir, dependencyJars);
436
437 List<String> importSharedJars = getImportSharedJars(projectDir);
438
439 if (sharedProject) {
440 if (!importSharedJars.contains("portal-compat-shared.jar")) {
441 importSharedJars.add("portal-compat-shared.jar");
442 }
443 }
444
445 File gitignoreFile = new File(
446 projectDir.getCanonicalPath() + "/.gitignore");
447
448 if (hasModulesGitIgnore(dirName)) {
449 gitignoreFile.delete();
450
451 return;
452 }
453
454 String[] gitIgnores = importSharedJars.toArray(
455 new String[importSharedJars.size()]);
456
457 for (int i = 0; i < gitIgnores.length; i++) {
458 String gitIgnore = gitIgnores[i];
459
460 gitIgnore = "/lib/" + gitIgnore;
461
462 gitIgnores[i] = gitIgnore;
463 }
464
465 if (gitIgnores.length > 0) {
466 System.out.println("Updating " + gitignoreFile);
467
468 _fileUtil.write(gitignoreFile, StringUtil.merge(gitIgnores, "\n"));
469 }
470 }
471
472 protected void setupWarProject(String dirName, String fileName)
473 throws Exception {
474
475 File propertiesFile = new File(dirName + "/" + fileName);
476
477 Properties properties = new Properties();
478
479 properties.load(new FileInputStream(propertiesFile));
480
481 Set<String> jars = new TreeSet<>();
482
483 jars.addAll(getCommonJars());
484
485 List<String> dependencyJars = getPortalDependencyJars(properties);
486
487 jars.addAll(dependencyJars);
488
489 File projectDir = new File(propertiesFile.getParent() + "/../..");
490
491 jars.addAll(getImportSharedJars(projectDir));
492
493 File libDir = new File(propertiesFile.getParent() + "/lib");
494
495 jars.addAll(getRequiredDeploymentContextsJars(libDir, properties));
496
497 writeEclipseFiles(libDir, projectDir, dependencyJars);
498
499 String libDirPath = StringUtil.replace(
500 libDir.getPath(), StringPool.BACK_SLASH, StringPool.SLASH);
501
502 List<String> ignores = ListUtil.fromFile(
503 libDir.getCanonicalPath() + "/../.gitignore");
504
505 if (libDirPath.contains("/ext/") || ignores.contains("/lib")) {
506 return;
507 }
508
509 File gitignoreFile = new File(
510 libDir.getCanonicalPath() + "/.gitignore");
511
512 System.out.println("Updating " + gitignoreFile);
513
514 String[] gitIgnores = jars.toArray(new String[jars.size()]);
515
516 for (int i = 0; i < gitIgnores.length; i++) {
517 String gitIgnore = gitIgnores[i];
518
519 if (Validator.isNotNull(gitIgnore) && !gitIgnore.startsWith("/")) {
520 gitIgnores[i] = "/" + gitIgnore;
521 }
522 }
523
524 _fileUtil.write(gitignoreFile, StringUtil.merge(gitIgnores, "\n"));
525 }
526
527 protected void writeClasspathFile(
528 File libDir, List<String> dependencyJars, String projectDirName,
529 String projectName, boolean javaProject)
530 throws Exception {
531
532 File classpathFile = new File(projectDirName + "/.classpath");
533
534 if (!javaProject) {
535 classpathFile.delete();
536
537 return;
538 }
539
540 Set<String> globalJars = new LinkedHashSet<>();
541 List<String> portalJars = new ArrayList<>();
542
543 Set<String> extGlobalJars = new LinkedHashSet<>();
544 Set<String> extPortalJars = new LinkedHashSet<>();
545
546 String libDirPath = StringUtil.replace(
547 libDir.getPath(), StringPool.BACK_SLASH, StringPool.SLASH);
548
549 if (libDirPath.contains("/ext/")) {
550 FilenameFilter filenameFilter = new GlobFilenameFilter("*.jar");
551
552 for (String dirName : new String[] {"global", "portal"}) {
553 File file = new File(libDirPath + "/../ext-lib/" + dirName);
554
555 List<String> jars = ListUtil.toList(file.list(filenameFilter));
556
557 if (dirName.equals("global")) {
558 extGlobalJars.addAll(ListUtil.sort(jars));
559
560 File dir = new File(PropsValues.LIFERAY_LIB_GLOBAL_DIR);
561
562 String[] fileNames = dir.list(filenameFilter);
563
564 globalJars.addAll(
565 ListUtil.sort(ListUtil.toList(fileNames)));
566 globalJars.removeAll(extGlobalJars);
567 }
568 else if (dirName.equals("portal")) {
569 extPortalJars.addAll(ListUtil.sort(jars));
570
571 File dir = new File(PropsValues.LIFERAY_LIB_PORTAL_DIR);
572
573 String[] fileNames = dir.list(filenameFilter);
574
575 portalJars.addAll(
576 ListUtil.sort(ListUtil.toList(fileNames)));
577 portalJars.removeAll(extPortalJars);
578 }
579 }
580 }
581 else {
582 globalJars.add("portlet.jar");
583
584 portalJars.addAll(dependencyJars);
585 portalJars.add("bnd.jar");
586 portalJars.add("commons-logging.jar");
587 portalJars.add("log4j.jar");
588
589 portalJars = ListUtil.unique(portalJars);
590
591 Collections.sort(portalJars);
592 }
593
594 String[] customJarsArray = libDir.list(new GlobFilenameFilter("*.jar"));
595
596 List<String> customJars = null;
597
598 if (customJarsArray != null) {
599 customJars = ListUtil.toList(customJarsArray);
600
601 for (String jar : portalJars) {
602 customJars.remove(jar);
603 }
604
605 customJars.remove(projectName + "-service.jar");
606 customJars.remove("util-bridges.jar");
607 customJars.remove("util-java.jar");
608 customJars.remove("util-taglib.jar");
609
610 Collections.sort(customJars);
611 }
612 else {
613 customJars = new ArrayList<>();
614 }
615
616 StringBundler sb = new StringBundler();
617
618 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
619 sb.append("<classpath>\n");
620
621 for (String sourceDirName : _SOURCE_DIR_NAMES) {
622 if (_fileUtil.exists(projectDirName + "/" + sourceDirName)) {
623 sb.append("\t<classpathentry excluding=\"**/.svn.svn