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 System.out.println("Adding " + dependencyName + " " + version);
168
169 if (version.equals("latest.integration")) {
170 File dir = new File(ivyDirName + "/cache/" + dependencyName);
171
172 File[] files = dir.listFiles();
173
174 Arrays.sort(files, new FileComparator());
175
176 for (int i = files.length - 1; i >= 0; i--) {
177 File file = files[i];
178
179 if (!file.isFile()) {
180 continue;
181 }
182
183 String fileName = file.getName();
184
185 if (!fileName.endsWith(".xml")) {
186 continue;
187 }
188
189 version = fileName.substring(4, fileName.length() - 4);
190
191 System.out.println(
192 "Substituting " + version + " for latest.integration");
193 }
194 }
195
196 String ivyFileName =
197 ivyDirName + "/cache/" + dependencyName + "/ivy-" + version +
198 ".xml";
199
200 if (_fileUtil.exists(ivyFileName)) {
201 Document document = _saxReader.read(new File(ivyFileName));
202
203 Element rootElement = document.getRootElement();
204
205 Element dependenciesElement = rootElement.element("dependencies");
206
207 if (dependenciesElement != null) {
208 List<Element> dependencyElements = dependenciesElement.elements(
209 "dependency");
210
211 for (Element dependencyElement : dependencyElements) {
212 String conf = GetterUtil.getString(
213 dependencyElement.attributeValue("conf"));
214
215 if (!conf.startsWith("compile")) {
216 continue;
217 }
218
219 String name = GetterUtil.getString(
220 dependencyElement.attributeValue("name"));
221 String org = GetterUtil.getString(
222 dependencyElement.attributeValue("org"));
223 String rev = GetterUtil.getString(
224 dependencyElement.attributeValue("rev"));
225
226 String string = sb.toString();
227
228 if (string.contains(name)) {
229 continue;
230 }
231
232 addIvyCacheJar(sb, ivyDirName, org + "/" + name, rev);
233 }
234 }
235 }
236
237 String dirName = ivyDirName + "/cache/" + dependencyName + "/bundles";
238
239 if (!_fileUtil.exists(dirName)) {
240 dirName = ivyDirName + "/cache/" + dependencyName + "/jars";
241
242 if (!_fileUtil.exists(dirName)) {
243 System.out.println("Unable to find jars in " + dirName);
244
245 return;
246 }
247 }
248
249 File dir = new File(dirName);
250
251 File[] files = dir.listFiles();
252
253 for (File file : files) {
254 if (!file.isFile()) {
255 continue;
256 }
257
258 String fileName = file.getName();
259
260 if (!fileName.endsWith("-" + version + ".jar")) {
261 continue;
262 }
263
264 addClasspathEntry(sb, dirName + "/" + fileName);
265
266 return;
267 }
268
269 System.out.println(
270 "Unable to find jars in " + dirName + " for " + version);
271 }
272
273 protected void addIvyCacheJars(
274 StringBundler sb, String content, String ivyDirName)
275 throws Exception {
276
277 Document document = _saxReader.read(content);
278
279 Element rootElement = document.getRootElement();
280
281 Element dependenciesElement = rootElement.element("dependencies");
282
283 List<Element> dependencyElements = dependenciesElement.elements(
284 "dependency");
285
286 for (Element dependencyElement : dependencyElements) {
287 String conf = GetterUtil.getString(
288 dependencyElement.attributeValue("conf"));
289
290 if (!conf.equals("test->default")) {
291 continue;
292 }
293
294 String name = GetterUtil.getString(
295 dependencyElement.attributeValue("name"));
296 String org = GetterUtil.getString(
297 dependencyElement.attributeValue("org"));
298 String rev = GetterUtil.getString(
299 dependencyElement.attributeValue("rev"));
300
301 addIvyCacheJar(sb, ivyDirName, org + "/" + name, rev);
302 }
303 }
304
305 protected List<String> getCommonJars() {
306 List<String> jars = new ArrayList<String>();
307
308 jars.add("commons-logging.jar");
309 jars.add("log4j.jar");
310 jars.add("util-bridges.jar");
311 jars.add("util-java.jar");
312 jars.add("util-taglib.jar");
313
314 return jars;
315 }
316
317 protected List<String> getImportSharedJars(File projectDir)
318 throws Exception {
319
320 File buildXmlFile = new File(projectDir, "build.xml");
321
322 String content = _fileUtil.read(buildXmlFile);
323
324 int x = content.indexOf("import.shared");
325
326 if (x == -1) {
327 return new ArrayList<String>();
328 }
329
330 x = content.indexOf("value=\"", x);
331 x = content.indexOf("\"", x);
332
333 int y = content.indexOf("\" />", x);
334
335 if ((x == -1) || (y == -1)) {
336 return new ArrayList<String>();
337 }
338
339 String[] importShared = StringUtil.split(content.substring(x + 1, y));
340
341 if (importShared.length == 0) {
342 return new ArrayList<String>();
343 }
344
345 List<String> jars = new ArrayList<String>();
346
347 for (String currentImportShared : importShared) {
348 jars.add(currentImportShared + ".jar");
349
350 File currentImportSharedLibDir = new File(
351 projectDir, "../../shared/" + currentImportShared + "/lib");
352
353 if (!currentImportSharedLibDir.exists()) {
354 continue;
355 }
356
357 for (File file : currentImportSharedLibDir.listFiles()) {
358 jars.add(file.getName());
359 }
360 }
361
362 return jars;
363 }
364
365 protected List<String> getPortalDependencyJars(Properties properties) {
366 String[] dependencyJars = StringUtil.split(
367 properties.getProperty(
368 "portal-dependency-jars",
369 properties.getProperty("portal.dependency.jars")));
370
371 return ListUtil.toList(dependencyJars);
372 }
373
374 protected List<String> getRequiredDeploymentContextsJars(
375 File libDir, Properties properties)
376 throws Exception {
377
378 List<String> jars = new ArrayList<String>();
379
380 String[] requiredDeploymentContexts = StringUtil.split(
381 properties.getProperty("required-deployment-contexts"));
382
383 for (String requiredDeploymentContext : requiredDeploymentContexts) {
384 if (_fileUtil.exists(
385 libDir.getCanonicalPath() + "/" +
386 requiredDeploymentContext + "-service.jar")) {
387
388 jars.add(requiredDeploymentContext + "-service.jar");
389 }
390 }
391
392 return jars;
393 }
394
395 protected void setupJarProject(
396 String dirName, String fileName, List<String> dependencyJars,
397 boolean sharedProject)
398 throws Exception {
399
400 File buildFile = new File(dirName + "/" + fileName);
401
402 File projectDir = new File(buildFile.getParent());
403
404 File libDir = new File(projectDir, "lib");
405
406 writeEclipseFiles(libDir, projectDir, dependencyJars);
407
408 List<String> importSharedJars = getImportSharedJars(projectDir);
409
410 if (sharedProject) {
411 if (!importSharedJars.contains("portal-compat-shared.jar")) {
412 importSharedJars.add("portal-compat-shared.jar");
413 }
414 }
415
416 File gitignoreFile = new File(
417 projectDir.getCanonicalPath() + "/.gitignore");
418
419 String[] gitIgnores = importSharedJars.toArray(
420 new String[importSharedJars.size()]);
421
422 for (int i = 0; i < gitIgnores.length; i++) {
423 String gitIgnore = gitIgnores[i];
424
425 gitIgnore = "/lib/" + gitIgnore;
426
427 gitIgnores[i] = gitIgnore;
428 }
429
430 if (gitIgnores.length > 0) {
431 System.out.println("Updating " + gitignoreFile);
432
433 _fileUtil.write(gitignoreFile, StringUtil.merge(gitIgnores, "\n"));
434 }
435 }
436
437 protected void setupWarProject(String dirName, String fileName)
438 throws Exception {
439
440 File propertiesFile = new File(dirName + "/" + fileName);
441
442 Properties properties = new Properties();
443
444 properties.load(new FileInputStream(propertiesFile));
445
446 Set<String> jars = new TreeSet<String>();
447
448 jars.addAll(getCommonJars());
449
450 List<String> dependencyJars = getPortalDependencyJars(properties);
451
452 jars.addAll(dependencyJars);
453
454 File projectDir = new File(propertiesFile.getParent() + "/../..");
455
456 jars.addAll(getImportSharedJars(projectDir));
457
458 File libDir = new File(propertiesFile.getParent() + "/lib");
459
460 jars.addAll(getRequiredDeploymentContextsJars(libDir, properties));
461
462 writeEclipseFiles(libDir, projectDir, dependencyJars);
463
464 String libDirPath = StringUtil.replace(
465 libDir.getPath(), StringPool.BACK_SLASH, StringPool.SLASH);
466
467 List<String> ignores = ListUtil.fromFile(
468 libDir.getCanonicalPath() + "/../.gitignore");
469
470 if (libDirPath.contains("/ext/") || ignores.contains("/lib")) {
471 return;
472 }
473
474 File gitignoreFile = new File(
475 libDir.getCanonicalPath() + "/.gitignore");
476
477 System.out.println("Updating " + gitignoreFile);
478
479 String[] gitIgnores = jars.toArray(new String[jars.size()]);
480
481 for (int i = 0; i < gitIgnores.length; i++) {
482 String gitIgnore = gitIgnores[i];
483
484 if (Validator.isNotNull(gitIgnore) && !gitIgnore.startsWith("/")) {
485 gitIgnores[i] = "/" + gitIgnore;
486 }
487 }
488
489 _fileUtil.write(gitignoreFile, StringUtil.merge(gitIgnores, "\n"));
490 }
491
492 protected void writeClasspathFile(
493 File libDir, List<String> dependencyJars, String projectDirName,
494 String projectName, boolean javaProject)
495 throws Exception {
496
497 File classpathFile = new File(projectDirName + "/.classpath");
498
499 if (!javaProject) {
500 classpathFile.delete();
501
502 return;
503 }
504
505 Set<String> globalJars = new LinkedHashSet<String>();
506 List<String> portalJars = new ArrayList<String>();
507
508 Set<String> extGlobalJars = new LinkedHashSet<String>();
509 Set<String> extPortalJars = new LinkedHashSet<String>();
510
511 String libDirPath = StringUtil.replace(
512 libDir.getPath(), StringPool.BACK_SLASH, StringPool.SLASH);
513
514 if (libDirPath.contains("/ext/")) {
515 FilenameFilter filenameFilter = new GlobFilenameFilter("*.jar");
516
517 for (String dirName : new String[] {"global", "portal"}) {
518 File file = new File(libDirPath + "/../ext-lib/" + dirName);
519
520 List<String> jars = ListUtil.toList(file.list(filenameFilter));
521
522 if (dirName.equals("global")) {
523 extGlobalJars.addAll(ListUtil.sort(jars));
524
525 File dir = new File(PropsValues.LIFERAY_LIB_GLOBAL_DIR);
526
527 String[] fileNames = dir.list(filenameFilter);
528
529 globalJars.addAll(
530 ListUtil.sort(ListUtil.toList(fileNames)));
531 globalJars.removeAll(extGlobalJars);
532 }
533 else if (dirName.equals("portal")) {
534 extPortalJars.addAll(ListUtil.sort(jars));
535
536 File dir = new File(PropsValues.LIFERAY_LIB_PORTAL_DIR);
537
538 String[] fileNames = dir.list(filenameFilter);
539
540 portalJars.addAll(
541 ListUtil.sort(ListUtil.toList(fileNames)));
542 portalJars.removeAll(extPortalJars);
543 }
544 }
545 }
546 else {
547 globalJars.add("portlet.jar");
548
549 portalJars.addAll(dependencyJars);
550 portalJars.add("commons-logging.jar");
551 portalJars.add("log4j.jar");
552
553 portalJars = new ArrayList<String>(
554 new LinkedHashSet<String>(portalJars));
555
556 Collections.sort(portalJars);
557 }
558
559 String[] customJarsArray = libDir.list(new GlobFilenameFilter("*.jar"));
560
561 List<String> customJars = null;
562
563 if (customJarsArray != null) {
564 customJars = ListUtil.toList(customJarsArray);
565
566 for (String jar : portalJars) {
567 customJars.remove(jar);
568 }
569
570 customJars.remove(projectName + "-service.jar");
571 customJars.remove("util-bridges.jar");
572 customJars.remove("util-java.jar");
573 customJars.remove("util-taglib.jar");
574
575 Collections.sort(customJars);
576 }
577 else {
578 customJars = new ArrayList<String>();
579 }
580
581 StringBundler sb = new StringBundler();
582
583 sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
584 sb.append("<classpath>\n");
585
586 for (String sourceDirName : _SOURCE_DIR_NAMES) {
587 if (_fileUtil.exists(projectDirName + "/" + sourceDirName)) {
588 sb.append("\t<classpathentry excluding=\"**/.svn.svn