1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.tools;
24  
25  import com.liferay.portal.deploy.DeployUtil;
26  import com.liferay.portal.kernel.deploy.auto.AutoDeployException;
27  import com.liferay.portal.kernel.plugin.PluginPackage;
28  import com.liferay.portal.kernel.util.GetterUtil;
29  import com.liferay.portal.kernel.util.HttpUtil;
30  import com.liferay.portal.kernel.util.PropertiesUtil;
31  import com.liferay.portal.kernel.util.ServerDetector;
32  import com.liferay.portal.kernel.util.StringMaker;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.StringUtil;
35  import com.liferay.portal.kernel.util.Validator;
36  import com.liferay.portal.plugin.PluginPackageUtil;
37  import com.liferay.portal.util.DocumentUtil;
38  import com.liferay.portal.util.PortalUtil;
39  import com.liferay.portal.util.PrefsPropsUtil;
40  import com.liferay.portal.util.PropsUtil;
41  import com.liferay.portal.util.PropsValues;
42  import com.liferay.util.FileUtil;
43  import com.liferay.util.License;
44  import com.liferay.util.SystemProperties;
45  import com.liferay.util.Time;
46  import com.liferay.util.ant.CopyTask;
47  import com.liferay.util.ant.DeleteTask;
48  import com.liferay.util.ant.ExpandTask;
49  import com.liferay.util.ant.UpToDateTask;
50  import com.liferay.util.ant.WarTask;
51  import com.liferay.util.xml.XMLFormatter;
52  
53  import java.io.File;
54  import java.io.FileInputStream;
55  import java.io.IOException;
56  import java.io.InputStream;
57  
58  import java.util.ArrayList;
59  import java.util.List;
60  import java.util.Map;
61  import java.util.Properties;
62  import java.util.zip.ZipEntry;
63  import java.util.zip.ZipFile;
64  
65  import org.apache.commons.logging.Log;
66  import org.apache.commons.logging.LogFactory;
67  import org.apache.oro.io.GlobFilenameFilter;
68  
69  import org.dom4j.Document;
70  import org.dom4j.Element;
71  
72  /**
73   * <a href="BaseDeployer.java.html"><b><i>View Source</i></b></a>
74   *
75   * @author Brian Wing Shun Chan
76   *
77   */
78  public class BaseDeployer {
79  
80      public static final String DEPLOY_TO_PREFIX = "DEPLOY_TO__";
81  
82      public static void main(String[] args) {
83          List<String> wars = new ArrayList<String>();
84          List<String> jars = new ArrayList<String>();
85  
86          for (String arg : args) {
87              String fileName = arg.toLowerCase();
88  
89              if (fileName.endsWith(".war")) {
90                  wars.add(arg);
91              }
92              else if (fileName.endsWith(".jar")) {
93                  jars.add(arg);
94              }
95          }
96  
97          new BaseDeployer(wars, jars);
98      }
99  
100     protected BaseDeployer() {
101     }
102 
103     protected BaseDeployer(List<String> wars, List<String> jars) {
104         baseDir = System.getProperty("deployer.base.dir");
105         destDir = System.getProperty("deployer.dest.dir");
106         appServerType = System.getProperty("deployer.app.server.type");
107         portletTaglibDTD = System.getProperty("deployer.portlet.taglib.dtd");
108         portletExtTaglibDTD = System.getProperty(
109             "deployer.portlet.ext.taglib.dtd");
110         securityTaglibDTD = System.getProperty("deployer.security.taglib.dtd");
111         themeTaglibDTD = System.getProperty("deployer.theme.taglib.dtd");
112         uiTaglibDTD = System.getProperty("deployer.ui.taglib.dtd");
113         utilTaglibDTD = System.getProperty("deployer.util.taglib.dtd");
114         unpackWar = GetterUtil.getBoolean(
115             System.getProperty("deployer.unpack.war"), true);
116         jbossPrefix = GetterUtil.getString(
117             System.getProperty("deployer.jboss.prefix"));
118         tomcatLibDir = System.getProperty("deployer.tomcat.lib.dir");
119         this.wars = wars;
120         this.jars = jars;
121 
122         checkArguments();
123 
124         try {
125             deploy();
126         }
127         catch (Exception e) {
128             e.printStackTrace();
129         }
130     }
131 
132     protected void checkArguments() {
133         if (Validator.isNull(baseDir)) {
134             throw new IllegalArgumentException(
135                 "The system property deployer.base.dir is not set");
136         }
137 
138         if (Validator.isNull(destDir)) {
139             throw new IllegalArgumentException(
140                 "The system property deployer.dest.dir is not set");
141         }
142 
143         if (Validator.isNull(appServerType)) {
144             throw new IllegalArgumentException(
145                 "The system property deployer.app.server.type is not set");
146         }
147 
148         if (!appServerType.startsWith(ServerDetector.GERONIMO_ID) &&
149             !appServerType.startsWith(ServerDetector.GLASSFISH_ID) &&
150             !appServerType.startsWith(ServerDetector.JBOSS_ID) &&
151             !appServerType.startsWith(ServerDetector.JONAS_ID) &&
152             !appServerType.equals(ServerDetector.JETTY_ID) &&
153             !appServerType.equals(ServerDetector.OC4J_ID) &&
154             !appServerType.equals(ServerDetector.ORION_ID) &&
155             !appServerType.equals(ServerDetector.PRAMATI_ID) &&
156             !appServerType.equals(ServerDetector.RESIN_ID) &&
157             !appServerType.equals(ServerDetector.TOMCAT_ID) &&
158             !appServerType.equals(ServerDetector.WEBLOGIC_ID) &&
159             !appServerType.equals(ServerDetector.WEBSPHERE_ID)) {
160 
161             throw new IllegalArgumentException(
162                 appServerType + " is not a valid application server type");
163         }
164 
165         if (appServerType.startsWith(ServerDetector.GLASSFISH_ID) ||
166             appServerType.equals(ServerDetector.PRAMATI_ID) ||
167             appServerType.equals(ServerDetector.WEBLOGIC_ID)) {
168 
169             unpackWar = false;
170         }
171 
172         if (Validator.isNotNull(jbossPrefix) &&
173             !Validator.isNumber(jbossPrefix)) {
174 
175             jbossPrefix = "1";
176         }
177     }
178 
179     protected void copyDependencyXml(String fileName, String targetDir)
180         throws Exception {
181 
182         copyDependencyXml(fileName, targetDir, null);
183     }
184 
185     protected void copyDependencyXml(
186             String fileName, String targetDir, Map<String, String> filterMap)
187         throws Exception {
188 
189         copyDependencyXml(fileName, targetDir, filterMap, false);
190     }
191 
192     protected void copyDependencyXml(
193             String fileName, String targetDir, Map<String, String> filterMap,
194             boolean overwrite)
195         throws Exception {
196 
197         File file = new File(DeployUtil.getResourcePath(fileName));
198         File targetFile = new File(targetDir + "/" + fileName);
199 
200         if (!targetFile.exists()) {
201             CopyTask.copyFile(
202                 file, new File(targetDir), filterMap, overwrite, true);
203         }
204     }
205 
206     protected void copyJars(File srcFile, PluginPackage pluginPackage)
207         throws Exception {
208 
209         for (int i = 0; i < jars.size(); i++) {
210             String jarFullName = jars.get(i);
211             String jarName = jarFullName.substring(
212                 jarFullName.lastIndexOf("/") + 1, jarFullName.length());
213 
214             if ((!appServerType.equals(ServerDetector.TOMCAT_ID)) ||
215                 (appServerType.equals(ServerDetector.TOMCAT_ID) &&
216                     !jarFullName.equals("util-java.jar"))) {
217 
218                 FileUtil.copyFile(
219                     jarFullName, srcFile + "/WEB-INF/lib/" + jarName, true);
220             }
221         }
222 
223         FileUtil.delete(srcFile + "/WEB-INF/lib/util-jsf.jar");
224     }
225 
226     protected void copyPortalDependencies(File srcFile) throws Exception {
227         Properties props = getPluginPackageProperties(srcFile);
228 
229         if (props == null) {
230             return;
231         }
232 
233         // jars
234 
235         String[] portalJars = StringUtil.split(
236             props.getProperty("portal.dependency.jars"));
237 
238         for (int i = 0; i < portalJars.length; i++) {
239             String portalJar = portalJars[i].trim();
240 
241             if (_log.isDebugEnabled()) {
242                 _log.debug("Copy portal JAR " + portalJar);
243             }
244 
245             try {
246                 String portalJarPath = PortalUtil.getPortalLibDir() + portalJar;
247 
248                 FileUtil.copyFile(
249                     portalJarPath, srcFile + "/WEB-INF/lib/" + portalJar, true);
250             }
251             catch (Exception e) {
252                 _log.error("Unable to copy portal JAR " + portalJar, e);
253             }
254         }
255 
256         // tlds
257 
258         String[] portalTlds = StringUtil.split(
259             props.getProperty("portal.dependency.tlds"));
260 
261         for (int i = 0; i < portalTlds.length; i++) {
262             String portalTld = portalTlds[i].trim();
263 
264             if (_log.isDebugEnabled()) {
265                 _log.debug("Copy portal TLD " + portalTld);
266             }
267 
268             try {
269                 String portalTldPath = DeployUtil.getResourcePath(portalTld);
270 
271                 FileUtil.copyFile(
272                     portalTldPath, srcFile + "/WEB-INF/tld/" + portalTld, true);
273             }
274             catch (Exception e) {
275                 _log.error("Unable to copy portal TLD " + portalTld, e);
276             }
277         }
278 
279         // commons-logging*.jar
280 
281         File pluginLibDir = new File(srcFile + "/WEB-INF/lib/");
282 
283         String[] commonsLoggingJars = pluginLibDir.list(
284             new GlobFilenameFilter("commons-logging*.jar"));
285 
286         if ((commonsLoggingJars == null) || (commonsLoggingJars.length == 0)) {
287             String portalJarPath =
288                 PortalUtil.getPortalLibDir() + "commons-logging.jar";
289 
290             FileUtil.copyFile(
291                 portalJarPath, srcFile + "/WEB-INF/lib/commons-logging.jar",
292                 true);
293         }
294 
295         // log4j*.jar
296 
297         String[] log4jJars = pluginLibDir.list(
298             new GlobFilenameFilter("log4j*.jar"));
299 
300         if ((log4jJars == null) || (log4jJars.length == 0)) {
301             String portalJarPath = PortalUtil.getPortalLibDir() + "log4j.jar";
302 
303             FileUtil.copyFile(
304                 portalJarPath, srcFile + "/WEB-INF/lib/log4j.jar", true);
305         }
306     }
307 
308     protected void copyTlds(File srcFile, PluginPackage pluginPackage)
309         throws Exception {
310 
311         if (Validator.isNotNull(portletTaglibDTD)) {
312             FileUtil.copyFile(
313                 portletTaglibDTD, srcFile + "/WEB-INF/tld/liferay-portlet.tld",
314                 true);
315         }
316 
317         if (Validator.isNotNull(themeTaglibDTD)) {
318             FileUtil.copyFile(
319                 themeTaglibDTD, srcFile + "/WEB-INF/tld/liferay-theme.tld",
320                 true);
321         }
322 
323         if (Validator.isNotNull(utilTaglibDTD)) {
324             FileUtil.copyFile(
325                 utilTaglibDTD, srcFile + "/WEB-INF/tld/liferay-util.tld", true);
326         }
327     }
328 
329     protected void copyXmls(
330             File srcFile, String displayName, PluginPackage pluginPackage)
331         throws Exception {
332 
333         if (appServerType.startsWith(ServerDetector.GERONIMO_ID)) {
334             copyDependencyXml("geronimo-web.xml", srcFile + "/WEB-INF");
335         }
336 
337         copyDependencyXml("web.xml", srcFile + "/WEB-INF");
338     }
339 
340     protected void deploy() throws Exception  {
341         try {
342             File baseDirFile = new File(baseDir);
343 
344             File[] files = baseDirFile.listFiles();
345 
346             if (files == null) {
347                 return;
348             }
349 
350             files = FileUtil.sortFiles(files);
351 
352             for (int i = 0; i < files.length; i++) {
353                 File srcFile = files[i];
354 
355                 String fileName = srcFile.getName().toLowerCase();
356 
357                 boolean deploy = false;
358 
359                 if (fileName.endsWith(".war") || fileName.endsWith(".zip")) {
360                     deploy = true;
361 
362                     if ((wars.size() > 0) &&
363                         (!wars.contains(srcFile.getName()))) {
364 
365                         deploy = false;
366                     }
367                 }
368 
369                 if (deploy) {
370                     deployFile(srcFile);
371                 }
372             }
373         }
374         catch (Exception e) {
375             e.printStackTrace();
376         }
377     }
378 
379     protected void deployDirectory(
380             File srcFile, String displayName, boolean override,
381             PluginPackage pluginPackage)
382         throws Exception {
383 
384         deployDirectory(
385             srcFile, null, null, displayName, override, pluginPackage);
386     }
387 
388     protected void deployDirectory(
389             File srcFile, File mergeDir, File deployDir, String displayName,
390             boolean overwrite, PluginPackage pluginPackage)
391         throws Exception {
392 
393         rewriteFiles(srcFile);
394 
395         mergeDirectory(mergeDir, srcFile);
396 
397         processPluginPackageProperties(srcFile, displayName, pluginPackage);
398 
399         copyJars(srcFile, pluginPackage);
400         copyTlds(srcFile, pluginPackage);
401         copyXmls(srcFile, displayName, pluginPackage);
402         copyPortalDependencies(srcFile);
403 
404         updateGeronimoWebXml(srcFile, displayName, pluginPackage);
405 
406         File webXml = new File(srcFile + "/WEB-INF/web.xml");
407 
408         updateWebXml(webXml, srcFile, displayName, pluginPackage);
409 
410         if ((deployDir != null) && !baseDir.equals(destDir)) {
411             updateDeployDirectory(srcFile);
412 
413             String excludes = StringPool.BLANK;
414 
415             if (appServerType.startsWith("jboss")) {
416                 excludes += "**/WEB-INF/lib/log4j.jar,";
417             }
418             else if (appServerType.equals(ServerDetector.TOMCAT_ID)) {
419                 String[] libs = FileUtil.listFiles(tomcatLibDir);
420 
421                 for (int i = 0; i < libs.length; i++) {
422                     excludes += "**/WEB-INF/lib/" + libs[i] + ",";
423                 }
424 
425                 File contextXml = new File(srcFile + "/META-INF/context.xml");
426 
427                 if (contextXml.exists()) {
428                     String content = FileUtil.read(contextXml);
429 
430                     if (content.indexOf(_PORTAL_CLASS_LOADER) != -1) {
431                         excludes += "**/WEB-INF/lib/util-bridges.jar,";
432                         excludes += "**/WEB-INF/lib/util-java.jar,";
433                         excludes += "**/WEB-INF/lib/util-taglib.jar,";
434                     }
435                 }
436 
437                 try {
438 
439                     // LEP-2990
440 
441                     Class.forName("javax.el.ELContext");
442 
443                     excludes += "**/WEB-INF/lib/el-api.jar,";
444                 }
445                 catch (ClassNotFoundException cnfe) {
446                 }
447             }
448 
449             if (!unpackWar || appServerType.equals("websphere")) {
450                 File tempDir = new File(
451                     SystemProperties.get(SystemProperties.TMP_DIR) +
452                         File.separator + Time.getTimestamp());
453 
454                 WarTask.war(srcFile, tempDir, "WEB-INF/web.xml", webXml);
455 
456                 if (!tempDir.renameTo(deployDir)) {
457                     WarTask.war(srcFile, deployDir, "WEB-INF/web.xml", webXml);
458                 }
459 
460                 DeleteTask.deleteDirectory(tempDir);
461             }
462             else {
463 
464                 // The deployer might only copy files that have been modified.
465                 // However, the deployer always copies and overwrites web.xml
466                 // after the other files have been copied because application
467                 // servers usually detect that a WAR has been modified based on
468                 // the web.xml time stamp.
469 
470                 excludes += "**/WEB-INF/web.xml";
471 
472                 CopyTask.copyDirectory(
473                     srcFile, deployDir, StringPool.BLANK, excludes, overwrite,
474                     true);
475 
476                 CopyTask.copyDirectory(
477                     srcFile, deployDir, "**/WEB-INF/web.xml", StringPool.BLANK,
478                     true, false);
479 
480                 if (appServerType.equals(ServerDetector.TOMCAT_ID)) {
481 
482                     // See org.apache.catalina.startup.HostConfig to see how
483                     // Tomcat checks to make sure that web.xml was modified 5
484                     // seconds after WEB-INF
485 
486                     File deployWebXml = new File(
487                         deployDir + "/WEB-INF/web.xml");
488 
489                     deployWebXml.setLastModified(
490                         System.currentTimeMillis() + (Time.SECOND * 6));
491                 }
492             }
493         }
494     }
495 
496     protected void deployFile(File srcFile) throws Exception {
497         PluginPackage pluginPackage = readPluginPackage(srcFile);
498 
499         if (_log.isInfoEnabled()) {
500             _log.info("Deploying " + srcFile.getName());
501         }
502 
503         String deployDir = null;
504         String displayName = null;
505         boolean overwrite = false;
506         String preliminaryContext = null;
507 
508         // File names starting with DEPLOY_TO_PREFIX should use the filename
509         // after the prefix as the deployment context
510 
511         if (srcFile.getName().startsWith(DEPLOY_TO_PREFIX)) {
512             displayName = srcFile.getName().substring(
513                 DEPLOY_TO_PREFIX.length(), srcFile.getName().length() - 4);
514 
515             overwrite = true;
516             preliminaryContext = displayName;
517         }
518 
519         if (preliminaryContext == null) {
520             preliminaryContext = getDisplayName(srcFile);
521         }
522 
523         if (pluginPackage != null) {
524             if (!PluginPackageUtil.isCurrentVersionSupported(
525                     pluginPackage.getLiferayVersions())) {
526 
527                 throw new AutoDeployException(
528                     srcFile.getName() +
529                         " does not support this version of Liferay");
530             }
531 
532             if (displayName == null) {
533                 displayName = pluginPackage.getRecommendedDeploymentContext();
534             }
535 
536             if (Validator.isNull(displayName)) {
537                 displayName = getDisplayName(srcFile);
538             }
539 
540             pluginPackage.setContext(displayName);
541 
542             PluginPackageUtil.updateInstallingPluginPackage(
543                 preliminaryContext, pluginPackage);
544         }
545 
546         if (Validator.isNotNull(displayName)) {
547             deployDir = displayName + ".war";
548         }
549         else {
550             deployDir = srcFile.getName();
551             displayName = getDisplayName(srcFile);
552         }
553 
554         if (appServerType.startsWith(ServerDetector.JBOSS_ID)) {
555             deployDir = jbossPrefix + deployDir;
556         }
557         else if (appServerType.equals(ServerDetector.JETTY_ID) ||
558                  appServerType.equals(ServerDetector.OC4J_ID) ||
559                  appServerType.equals(ServerDetector.ORION_ID) ||
560                  appServerType.equals(ServerDetector.RESIN_ID) ||
561                  appServerType.equals(ServerDetector.TOMCAT_ID)) {
562 
563             if (unpackWar) {
564                 deployDir = deployDir.substring(0, deployDir.length() - 4);
565             }
566         }
567 
568         deployDir = destDir + "/" + deployDir;
569 
570         File deployDirFile = new File(deployDir);
571 
572         try {
573             PluginPackage previousPluginPackage =
574                 readPluginPackage(deployDirFile);
575 
576             if ((pluginPackage != null) && (previousPluginPackage != null)) {
577                 if (_log.isInfoEnabled()) {
578                     String name = pluginPackage.getName();
579                     String previousVersion = previousPluginPackage.getVersion();
580                     String version = pluginPackage.getVersion();
581 
582                     _log.info(
583                         "Updating " + name + " from version " +
584                             previousVersion + " to version " + version);
585                 }
586 
587                 if (pluginPackage.isLaterVersionThan(
588                     previousPluginPackage)) {
589 
590                     overwrite = true;
591                 }
592             }
593 
594             File mergeDirFile = new File(
595                 srcFile.getParent() + "/merge/" + srcFile.getName());
596 
597             if (srcFile.isDirectory()) {
598                 deployDirectory(
599                     srcFile, mergeDirFile, deployDirFile, displayName,
600                     overwrite, pluginPackage);
601             }
602             else {
603                 boolean deployed = deployFile(
604                     srcFile, mergeDirFile, deployDirFile, displayName,
605                     overwrite, pluginPackage);
606 
607                 if (!deployed) {
608                     String context = preliminaryContext;
609 
610                     if (pluginPackage != null) {
611                         context = pluginPackage.getContext();
612                     }
613 
614                     PluginPackageUtil.endPluginPackageInstallation(context);
615                 }
616             }
617         }
618         catch (Exception e) {
619             if (pluginPackage != null) {
620                 PluginPackageUtil.endPluginPackageInstallation(
621                     pluginPackage.getContext());
622             }
623 
624             throw e;
625         }
626     }
627 
628     protected boolean deployFile(
629             File srcFile, File mergeDir, File deployDir, String displayName,
630             boolean overwrite, PluginPackage pluginPackage)
631         throws Exception {
632 
633         boolean undeployOnRedeploy = false;
634 
635         try {
636             undeployOnRedeploy = PrefsPropsUtil.getBoolean(
637                 PropsUtil.HOT_UNDEPLOY_ON_REDEPLOY,
638                 PropsValues.HOT_UNDEPLOY_ON_REDEPLOY);
639         }
640         catch (Exception e) {
641 
642             // This will only happen when running the deploy tool in Ant in the
643             // classical way where the WAR file is actually massaged and
644             // packaged.
645 
646         }
647 
648         if (undeployOnRedeploy) {
649             DeployUtil.undeploy(appServerType, deployDir);
650         }
651 
652         if (!overwrite && UpToDateTask.isUpToDate(srcFile, deployDir)) {
653             if (_log.isInfoEnabled()) {
654                 _log.info(deployDir + " is already up to date");
655             }
656 
657             return false;
658         }
659 
660         File tempDir = new File(
661             SystemProperties.get(SystemProperties.TMP_DIR) + File.separator +
662                 Time.getTimestamp());
663 
664         ExpandTask.expand(srcFile, tempDir);
665 
666         deployDirectory(
667             tempDir, mergeDir, deployDir, displayName, overwrite,
668             pluginPackage);
669 
670         DeleteTask.deleteDirectory(tempDir);
671 
672         return true;
673     }
674 
675     protected String downloadJar(String jar) throws Exception {
676         String tmpDir = SystemProperties.get(SystemProperties.TMP_DIR);
677 
678         File file = new File(
679             tmpDir + "/liferay/com/liferay/portal/deploy/dependencies/" +
680                 jar);
681 
682         if (!file.exists()) {
683             synchronized(this) {
684                 String url = PropsUtil.get(
685                     PropsUtil.LIBRARY_DOWNLOAD_URL + jar);
686 
687                 if (_log.isInfoEnabled()) {
688                     _log.info("Downloading library from " + url);
689                 }
690 
691                 byte[] bytes = HttpUtil.URLtoByteArray(url);
692 
693                 FileUtil.write(file, bytes);
694             }
695         }
696 
697         return FileUtil.getAbsolutePath(file);
698     }
699 
700     protected String getDisplayName(File srcFile) {
701         String displayName = srcFile.getName();
702 
703         displayName = displayName.substring(0, displayName.length() - 4);
704 
705         if (appServerType.startsWith("jboss") &&
706             Validator.isNotNull(jbossPrefix) &&
707             displayName.startsWith(jbossPrefix)) {
708 
709             displayName = displayName.substring(1, displayName.length());
710         }
711 
712         return displayName;
713     }
714 
715     protected String getExtraContent(
716             double webXmlVersion, File srcFile, String displayName)
717         throws Exception {
718 
719         StringMaker sm = new StringMaker();
720 
721         sm.append("<display-name>");
722         sm.append(displayName);
723         sm.append("</display-name>");
724 
725         boolean hasTaglib = false;
726 
727         if (Validator.isNotNull(portletTaglibDTD) ||
728             Validator.isNotNull(portletExtTaglibDTD) ||
729             Validator.isNotNull(securityTaglibDTD) ||
730             Validator.isNotNull(themeTaglibDTD) ||
731             Validator.isNotNull(uiTaglibDTD) ||
732             Validator.isNotNull(utilTaglibDTD)) {
733 
734             hasTaglib = true;
735         }
736 
737         if (hasTaglib && (webXmlVersion > 2.3)) {
738             sm.append("<jsp-config>");
739         }
740 
741         if (Validator.isNotNull(portletTaglibDTD)) {
742             sm.append("<taglib>");
743             sm.append(
744                 "<taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>");
745             sm.append("<taglib-location>");
746             sm.append("/WEB-INF/tld/liferay-portlet.tld");
747             sm.append("</taglib-location>");
748             sm.append("</taglib>");
749         }
750 
751         if (Validator.isNotNull(portletExtTaglibDTD)) {
752             sm.append("<taglib>");
753             sm.append("<taglib-uri>");
754             sm.append("http://liferay.com/tld/portlet");
755             sm.append("</taglib-uri>");
756             sm.append("<taglib-location>");
757             sm.append("/WEB-INF/tld/liferay-portlet-ext.tld");
758             sm.append("</taglib-location>");
759             sm.append("</taglib>");
760         }
761 
762         if (Validator.isNotNull(securityTaglibDTD)) {
763             sm.append("<taglib>");
764             sm.append("<taglib-uri>");
765             sm.append("http://liferay.com/tld/security");
766             sm.append("</taglib-uri>");
767             sm.append("<taglib-location>");
768             sm.append("/WEB-INF/tld/liferay-security.tld");
769             sm.append("</taglib-location>");
770             sm.append("</taglib>");
771         }
772 
773         if (Validator.isNotNull(themeTaglibDTD)) {
774             sm.append("<taglib>");
775             sm.append("<taglib-uri>http://liferay.com/tld/theme</taglib-uri>");
776             sm.append("<taglib-location>");
777             sm.append("/WEB-INF/tld/liferay-theme.tld");
778             sm.append("</taglib-location>");
779             sm.append("</taglib>");
780         }
781 
782         if (Validator.isNotNull(uiTaglibDTD)) {
783             sm.append("<taglib>");
784             sm.append("<taglib-uri>http://liferay.com/tld/ui</taglib-uri>");
785             sm.append("<taglib-location>");
786             sm.append("/WEB-INF/tld/liferay-ui.tld");
787             sm.append("</taglib-location>");
788             sm.append("</taglib>");
789         }
790 
791         if (Validator.isNotNull(utilTaglibDTD)) {
792             sm.append("<taglib>");
793             sm.append("<taglib-uri>http://liferay.com/tld/util</taglib-uri>");
794             sm.append("<taglib-location>");
795             sm.append("/WEB-INF/tld/liferay-util.tld");
796             sm.append("</taglib-location>");
797             sm.append("</taglib>");
798         }
799 
800         if (hasTaglib && (webXmlVersion > 2.3)) {
801             sm.append("</jsp-config>");
802         }
803 
804         return sm.toString();
805     }
806 
807     protected String getPluginPackageLicensesXml(List<License> licenses) {
808         StringMaker sm = new StringMaker();
809 
810         for (int i = 0; i < licenses.size(); i++) {
811             License license = licenses.get(i);
812 
813             if (i == 0) {
814                 sm.append("\r\n");
815             }
816 
817             sm.append("\t\t<license osi-approved=\"");
818             sm.append(license.isOsiApproved());
819             sm.append("\">");
820             sm.append(license.getName());
821             sm.append("</license>\r\n");
822 
823             if ((i + 1) == licenses.size()) {
824                 sm.append("\t");
825             }
826         }
827 
828         return sm.toString();
829     }
830 
831     protected String getPluginPackageLiferayVersionsXml(
832         List<String> liferayVersions) {
833 
834         StringMaker sm = new StringMaker();
835 
836         for (int i = 0; i < liferayVersions.size(); i++) {
837             String liferayVersion = liferayVersions.get(i);
838 
839             if (i == 0) {
840                 sm.append("\r\n");
841             }
842 
843             sm.append("\t\t<liferay-version>");
844             sm.append(liferayVersion);
845             sm.append("</liferay-version>\r\n");
846 
847             if ((i + 1) == liferayVersions.size()) {
848                 sm.append("\t");
849             }
850         }
851 
852         return sm.toString();
853     }
854 
855     protected Properties getPluginPackageProperties(File srcFile)
856         throws Exception {
857 
858         File propsFile = new File(
859             srcFile + "/WEB-INF/liferay-plugin-package.properties");
860 
861         if (!propsFile.exists()) {
862             return null;
863         }
864 
865         String propsString = FileUtil.read(propsFile);
866 
867         return PropertiesUtil.load(propsString);
868     }
869 
870     protected String getPluginPackageTagsXml(List<String> tags) {
871         StringMaker sm = new StringMaker();
872 
873         for (int i = 0; i < tags.size(); i++) {
874             String tag = tags.get(i);
875 
876             if (i == 0) {
877                 sm.append("\r\n");
878             }
879 
880             sm.append("\t\t<tag>");
881             sm.append(tag);
882             sm.append("</tag>\r\n");
883 
884             if ((i + 1) == tags.size()) {
885                 sm.append("\t");
886             }
887         }
888 
889         return sm.toString();
890     }
891 
892     protected void mergeDirectory(File mergeDir, File targetDir) {
893         if ((mergeDir == null) || (!mergeDir.exists())) {
894             return;
895         }
896 
897         CopyTask.copyDirectory(mergeDir, targetDir, null, null, true, false);
898     }
899 
900     protected void processPluginPackageProperties(
901             File srcFile, String displayName, PluginPackage pluginPackage)
902         throws Exception {
903     }
904 
905     protected PluginPackage readPluginPackage(File file) {
906         if (!file.exists()) {
907             return null;
908         }
909 
910         InputStream is = null;
911         ZipFile zipFile = null;
912 
913         try {
914             boolean parseProps = false;
915 
916             if (file.isDirectory()) {
917                 String path = file.getPath();
918 
919                 File pluginPackageXmlFile = new File(
920                     file.getParent() + "/merge/" + file.getName() +
921                         "/WEB-INF/liferay-plugin-package.xml");
922 
923                 if (pluginPackageXmlFile.exists()) {
924                     is = new FileInputStream(pluginPackageXmlFile);
925                 }
926                 else {
927                     pluginPackageXmlFile = new File(
928                         path + "/WEB-INF/liferay-plugin-package.xml");
929 
930                     if (pluginPackageXmlFile.exists()) {
931                         is = new FileInputStream(pluginPackageXmlFile);
932                     }
933                 }
934 
935                 File pluginPackagePropsFile = new File(
936                     file.getParent() + "/merge/" + file.getName() +
937                         "/WEB-INF/liferay-plugin-package.properties");
938 
939                 if (pluginPackagePropsFile.exists()) {
940                     is = new FileInputStream(pluginPackagePropsFile);
941 
942                     parseProps = true;
943                 }
944                 else {
945                     pluginPackagePropsFile = new File(
946                         path + "/WEB-INF/liferay-plugin-package.properties");
947 
948                     if (pluginPackagePropsFile.exists()) {
949                         is = new FileInputStream(pluginPackagePropsFile);
950 
951                         parseProps = true;
952                     }
953                 }
954             }
955             else {
956                 zipFile = new ZipFile(file);
957 
958                 File pluginPackageXmlFile = new File(
959                     file.getParent() + "/merge/" + file.getName() +
960                         "/WEB-INF/liferay-plugin-package.xml");
961 
962                 if (pluginPackageXmlFile.exists()) {
963                     is = new FileInputStream(pluginPackageXmlFile);
964                 }
965                 else {
966                     ZipEntry zipEntry = zipFile.getEntry(
967                         "WEB-INF/liferay-plugin-package.xml");
968 
969                     if (zipEntry != null) {
970                         is = zipFile.getInputStream(zipEntry);
971                     }
972                 }
973 
974                 File pluginPackagePropsFile = new File(
975                     file.getParent() + "/merge/" + file.getName() +
976                         "/WEB-INF/liferay-plugin-package.properties");
977 
978                 if (pluginPackagePropsFile.exists()) {
979                     is = new FileInputStream(pluginPackagePropsFile);
980 
981                     parseProps = true;
982                 }
983                 else {
984                     ZipEntry zipEntry = zipFile.getEntry(
985                         "WEB-INF/liferay-plugin-package.properties");
986 
987                     if (zipEntry != null) {
988                         is = zipFile.getInputStream(zipEntry);
989 
990                         parseProps = true;
991                     }
992                 }
993             }
994 
995             if (is == null) {
996                 if (_log.isInfoEnabled()) {
997                     _log.info(
998                         file.getPath() + " does not have a " +
999                             "WEB-INF/liferay-plugin-package.xml or " +
1000                                "WEB-INF/liferay-plugin-package.properties");
1001                }
1002
1003                return null;
1004            }
1005
1006            if (parseProps) {
1007                String displayName = getDisplayName(file);
1008
1009                String propsString = StringUtil.read(is);
1010
1011                Properties props = PropertiesUtil.load(propsString);
1012
1013                return PluginPackageUtil.readPluginPackageProps(
1014                    displayName, props);
1015            }
1016            else {
1017                String xml = StringUtil.read(is);
1018
1019                xml = XMLFormatter.fixProlog(xml);
1020
1021                return PluginPackageUtil.readPluginPackageXml(xml);
1022            }
1023        }
1024        catch (Exception e) {
1025            _log.error(file.getPath() + ": " + e.toString());
1026        }
1027        finally {
1028            if (is != null) {
1029                try {
1030                    is.close();
1031                }
1032                catch (IOException ioe) {
1033                }
1034            }
1035
1036            if (zipFile != null) {
1037                try {
1038                    zipFile.close();
1039                }
1040                catch (IOException ioe) {
1041                }
1042            }
1043        }
1044
1045        return null;
1046    }
1047
1048    protected void rewriteFiles(File srcDir) throws Exception {
1049        String[] files = FileUtil.listFiles(srcDir + "/WEB-INF/");
1050
1051        for (int i = 0; i < files.length; i++) {
1052            String ext = FileUtil.getExtension(files[i]);
1053
1054            if (ext.equalsIgnoreCase("xml")) {
1055
1056                // Make sure to rewrite any XML files to include external
1057                // entities into same file. See LEP-3142.
1058
1059                File file = new File(srcDir + "/WEB-INF/" + files[i]);
1060
1061                try {
1062                    Document doc = DocumentUtil.readDocumentFromFile(file);
1063
1064                    String content = XMLFormatter.toString(
1065                        doc, XMLFormatter.INDENT, true);
1066
1067                    FileUtil.write(file, content);
1068                }
1069                catch (Exception e) {
1070                    if (_log.isWarnEnabled()) {
1071                        _log.warn(
1072                            "Unable to format " + file + ": " + e.getMessage());
1073                    }
1074                }
1075            }
1076        }
1077    }
1078
1079    protected void updateDeployDirectory(File srcFile) throws Exception {
1080    }
1081
1082    protected void updateGeronimoWebXml(
1083            File srcFile, String displayName, PluginPackage pluginPackage)
1084        throws Exception {
1085
1086        if (!appServerType.startsWith(ServerDetector.GERONIMO_ID)) {
1087            return;
1088        }
1089
1090        File geronimoWebXml = new File(srcFile + "/WEB-INF/geronimo-web.xml");
1091
1092        Document doc = DocumentUtil.readDocumentFromFile(geronimoWebXml);
1093
1094        Element root = doc.getRootElement();
1095
1096        Element environmentEl = root.element("environment");
1097
1098        Element moduleIdEl = environmentEl.element("moduleId");
1099
1100        Element artifactIdEl = moduleIdEl.element("artifactId");
1101
1102        String artifactIdText = GetterUtil.getString(artifactIdEl.getText());
1103
1104        if (!artifactIdText.equals(displayName)) {
1105            artifactIdEl.setText(displayName);
1106
1107            String content = XMLFormatter.toString(doc);
1108
1109            FileUtil.write(geronimoWebXml, content);
1110
1111            if (_log.isInfoEnabled()) {
1112                _log.info("Modifying Geronimo " + geronimoWebXml);
1113            }
1114        }
1115    }
1116
1117    protected void updateWebXml(
1118            File webXml, File srcFile, String displayName,
1119            PluginPackage pluginPackage)
1120        throws Exception {
1121
1122        String content = FileUtil.read(webXml);
1123
1124        int x = content.indexOf("<display-name>");
1125
1126        if (x != -1) {
1127            int y = content.indexOf("</display-name>", x);
1128
1129            y = content.indexOf(">", y);
1130
1131            content = content.substring(0, x) + content.substring(y);
1132        }
1133
1134        double webXmlVersion = 2.3;
1135
1136        Document webXmlDoc = DocumentUtil.readDocumentFromXML(content);
1137
1138        Element webXmlRoot = webXmlDoc.getRootElement();
1139
1140        webXmlVersion = GetterUtil.getDouble(
1141            webXmlRoot.attributeValue("version"), webXmlVersion);
1142
1143        // Merge extra content
1144
1145        String extraContent = getExtraContent(
1146            webXmlVersion, srcFile, displayName);
1147
1148        int pos = content.indexOf("</web-app>");
1149
1150        String newContent =
1151            content.substring(0, pos) + extraContent +
1152            content.substring(pos, content.length());
1153
1154        // Replace old package names
1155
1156        newContent = StringUtil.replace(
1157            newContent, "com.liferay.portal.shared.",
1158            "com.liferay.portal.kernel.");
1159
1160        newContent = WebXMLBuilder.organizeWebXML(newContent);
1161
1162        FileUtil.write(webXml, newContent, true);
1163
1164        if (_log.isInfoEnabled()) {
1165            _log.info("Modifying Servlet " + webXmlVersion + " " + webXml);
1166        }
1167    }
1168
1169    protected String baseDir;
1170    protected String destDir;
1171    protected String appServerType;
1172    protected String portletTaglibDTD;
1173    protected String portletExtTaglibDTD;
1174    protected String securityTaglibDTD;
1175    protected String themeTaglibDTD;
1176    protected String uiTaglibDTD;
1177    protected String utilTaglibDTD;
1178    protected boolean unpackWar;
1179    protected String jbossPrefix;
1180    protected String tomcatLibDir;
1181    protected List<String> wars;
1182    protected List<String> jars;
1183
1184    private static final String _PORTAL_CLASS_LOADER =
1185        "com.liferay.support.tomcat.loader.PortalClassLoader";
1186
1187    private static Log _log = LogFactory.getLog(BaseDeployer.class);
1188
1189}