1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.tools.deploy;
16  
17  import com.liferay.portal.deploy.DeployUtil;
18  import com.liferay.portal.kernel.deploy.Deployer;
19  import com.liferay.portal.kernel.deploy.auto.AutoDeployException;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.plugin.License;
23  import com.liferay.portal.kernel.plugin.PluginPackage;
24  import com.liferay.portal.kernel.util.FileUtil;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.HttpUtil;
27  import com.liferay.portal.kernel.util.PropertiesUtil;
28  import com.liferay.portal.kernel.util.PropsKeys;
29  import com.liferay.portal.kernel.util.ServerDetector;
30  import com.liferay.portal.kernel.util.StringBundler;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Time;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.kernel.xml.Document;
36  import com.liferay.portal.kernel.xml.Element;
37  import com.liferay.portal.kernel.xml.SAXReaderUtil;
38  import com.liferay.portal.plugin.PluginPackageUtil;
39  import com.liferay.portal.tools.WebXMLBuilder;
40  import com.liferay.portal.util.ExtRegistry;
41  import com.liferay.portal.util.InitUtil;
42  import com.liferay.portal.util.PortalUtil;
43  import com.liferay.portal.util.PrefsPropsUtil;
44  import com.liferay.portal.util.PropsUtil;
45  import com.liferay.portal.util.PropsValues;
46  import com.liferay.util.SystemProperties;
47  import com.liferay.util.ant.CopyTask;
48  import com.liferay.util.ant.DeleteTask;
49  import com.liferay.util.ant.ExpandTask;
50  import com.liferay.util.ant.UpToDateTask;
51  import com.liferay.util.ant.WarTask;
52  import com.liferay.util.xml.XMLFormatter;
53  
54  import java.io.File;
55  import java.io.FileInputStream;
56  import java.io.IOException;
57  import java.io.InputStream;
58  
59  import java.util.ArrayList;
60  import java.util.List;
61  import java.util.Map;
62  import java.util.Properties;
63  import java.util.Set;
64  import java.util.zip.ZipEntry;
65  import java.util.zip.ZipFile;
66  
67  import org.apache.oro.io.GlobFilenameFilter;
68  
69  /**
70   * <a href="BaseDeployer.java.html"><b><i>View Source</i></b></a>
71   *
72   * @author Brian Wing Shun Chan
73   * @author Sandeep Soni
74   */
75  public class BaseDeployer implements Deployer {
76  
77      public static final String DEPLOY_TO_PREFIX = "DEPLOY_TO__";
78  
79      public static void main(String[] args) {
80          InitUtil.initWithSpring();
81  
82          List<String> wars = new ArrayList<String>();
83          List<String> jars = new ArrayList<String>();
84  
85          for (String arg : args) {
86              String fileName = arg.toLowerCase();
87  
88              if (fileName.endsWith(".war")) {
89                  wars.add(arg);
90              }
91              else if (fileName.endsWith(".jar")) {
92                  jars.add(arg);
93              }
94          }
95  
96          new BaseDeployer(wars, jars);
97      }
98  
99      public BaseDeployer() {
100     }
101 
102     public BaseDeployer(List<String> wars, List<String> jars) {
103         baseDir = System.getProperty("deployer.base.dir");
104         destDir = System.getProperty("deployer.dest.dir");
105         appServerType = System.getProperty("deployer.app.server.type");
106         portletTaglibDTD = System.getProperty("deployer.portlet.taglib.dtd");
107         portletExtTaglibDTD = System.getProperty(
108             "deployer.portlet.ext.taglib.dtd");
109         securityTaglibDTD = System.getProperty("deployer.security.taglib.dtd");
110         themeTaglibDTD = System.getProperty("deployer.theme.taglib.dtd");
111         uiTaglibDTD = System.getProperty("deployer.ui.taglib.dtd");
112         utilTaglibDTD = System.getProperty("deployer.util.taglib.dtd");
113         unpackWar = GetterUtil.getBoolean(
114             System.getProperty("deployer.unpack.war"), true);
115         filePattern = System.getProperty("deployer.file.pattern");
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     public void addExtJar(List<String> jars, String resource)
133         throws Exception {
134 
135         Set<String> servletContextNames = ExtRegistry.getServletContextNames();
136 
137         for (String servletContextName : servletContextNames) {
138             String extResource =
139                 "ext-" + servletContextName + resource.substring(3);
140 
141             String path = DeployUtil.getResourcePath(extResource);
142 
143             if (_log.isDebugEnabled()) {
144                 if (path == null) {
145                     _log.debug("Resource " + extResource + " is not available");
146                 }
147                 else {
148                     _log.debug(
149                         "Resource " + extResource + " is available at " + path);
150                 }
151             }
152 
153             if (path != null) {
154                 jars.add(path);
155             }
156         }
157     }
158 
159     public void addRequiredJar(List<String> jars, String resource)
160         throws Exception {
161 
162         String path = DeployUtil.getResourcePath(resource);
163 
164         if (path == null) {
165             throw new RuntimeException(
166                 "Resource " + resource + " does not exist");
167         }
168 
169         if (_log.isDebugEnabled()) {
170             _log.debug("Resource " + resource + " is available at " + path);
171         }
172 
173         jars.add(path);
174     }
175 
176     public void checkArguments() {
177         if (Validator.isNull(baseDir)) {
178             throw new IllegalArgumentException(
179                 "The system property deployer.base.dir is not set");
180         }
181 
182         if (Validator.isNull(destDir)) {
183             throw new IllegalArgumentException(
184                 "The system property deployer.dest.dir is not set");
185         }
186 
187         if (Validator.isNull(appServerType)) {
188             throw new IllegalArgumentException(
189                 "The system property deployer.app.server.type is not set");
190         }
191 
192         if (!appServerType.startsWith(ServerDetector.GERONIMO_ID) &&
193             !appServerType.startsWith(ServerDetector.GLASSFISH_ID) &&
194             !appServerType.startsWith(ServerDetector.JBOSS_ID) &&
195             !appServerType.startsWith(ServerDetector.JONAS_ID) &&
196             !appServerType.equals(ServerDetector.JETTY_ID) &&
197             !appServerType.equals(ServerDetector.OC4J_ID) &&
198             !appServerType.equals(ServerDetector.RESIN_ID) &&
199             !appServerType.equals(ServerDetector.TOMCAT_ID) &&
200             !appServerType.equals(ServerDetector.WEBLOGIC_ID) &&
201             !appServerType.equals(ServerDetector.WEBSPHERE_ID)) {
202 
203             throw new IllegalArgumentException(
204                 appServerType + " is not a valid application server type");
205         }
206 
207         if (appServerType.startsWith(ServerDetector.GLASSFISH_ID) ||
208             appServerType.equals(ServerDetector.WEBLOGIC_ID)) {
209 
210             unpackWar = false;
211         }
212 
213         if (Validator.isNotNull(jbossPrefix) &&
214             !Validator.isNumber(jbossPrefix)) {
215 
216             jbossPrefix = "1";
217         }
218     }
219 
220     public void copyDependencyXml(String fileName, String targetDir)
221         throws Exception {
222 
223         copyDependencyXml(fileName, targetDir, null);
224     }
225 
226     public void copyDependencyXml(
227             String fileName, String targetDir, Map<String, String> filterMap)
228         throws Exception {
229 
230         copyDependencyXml(fileName, targetDir, filterMap, false);
231     }
232 
233     public void copyDependencyXml(
234             String fileName, String targetDir, Map<String, String> filterMap,
235             boolean overwrite)
236         throws Exception {
237 
238         File file = new File(DeployUtil.getResourcePath(fileName));
239         File targetFile = new File(targetDir + "/" + fileName);
240 
241         if (!targetFile.exists()) {
242             CopyTask.copyFile(
243                 file, new File(targetDir), filterMap, overwrite, true);
244         }
245     }
246 
247     public void copyJars(File srcFile, PluginPackage pluginPackage)
248         throws Exception {
249 
250         for (int i = 0; i < jars.size(); i++) {
251             String jarFullName = jars.get(i);
252 
253             String jarName = jarFullName.substring(
254                 jarFullName.lastIndexOf("/") + 1, jarFullName.length());
255 
256             if ((!appServerType.equals(ServerDetector.TOMCAT_ID)) ||
257                 (appServerType.equals(ServerDetector.TOMCAT_ID) &&
258                     !jarFullName.equals("util-java.jar"))) {
259 
260                 FileUtil.copyFile(
261                     jarFullName, srcFile + "/WEB-INF/lib/" + jarName, true);
262             }
263         }
264 
265         FileUtil.delete(srcFile + "/WEB-INF/lib/util-jsf.jar");
266     }
267 
268     public void copyPortalDependencies(File srcFile) throws Exception {
269         Properties properties = getPluginPackageProperties(srcFile);
270 
271         if (properties == null) {
272             return;
273         }
274 
275         // jars
276 
277         String[] portalJars = StringUtil.split(
278             properties.getProperty(
279                 "portal-dependency-jars",
280                 properties.getProperty("portal.dependency.jars")));
281 
282         for (int i = 0; i < portalJars.length; i++) {
283             String portalJar = portalJars[i].trim();
284 
285             if (_log.isDebugEnabled()) {
286                 _log.debug("Copy portal JAR " + portalJar);
287             }
288 
289             try {
290                 String portalJarPath = PortalUtil.getPortalLibDir() + portalJar;
291 
292                 FileUtil.copyFile(
293                     portalJarPath, srcFile + "/WEB-INF/lib/" + portalJar, true);
294             }
295             catch (Exception e) {
296                 _log.error("Unable to copy portal JAR " + portalJar, e);
297             }
298         }
299 
300         // tlds
301 
302         String[] portalTlds = StringUtil.split(
303             properties.getProperty(
304                 "portal-dependency-tlds",
305                 properties.getProperty("portal.dependency.tlds")));
306 
307         for (int i = 0; i < portalTlds.length; i++) {
308             String portalTld = portalTlds[i].trim();
309 
310             if (_log.isDebugEnabled()) {
311                 _log.debug("Copy portal TLD " + portalTld);
312             }
313 
314             try {
315                 String portalTldPath = DeployUtil.getResourcePath(portalTld);
316 
317                 FileUtil.copyFile(
318                     portalTldPath, srcFile + "/WEB-INF/tld/" + portalTld, true);
319             }
320             catch (Exception e) {
321                 _log.error("Unable to copy portal TLD " + portalTld, e);
322             }
323         }
324 
325         // commons-logging*.jar
326 
327         File pluginLibDir = new File(srcFile + "/WEB-INF/lib/");
328 
329         String[] commonsLoggingJars = pluginLibDir.list(
330             new GlobFilenameFilter("commons-logging*.jar"));
331 
332         if ((commonsLoggingJars == null) || (commonsLoggingJars.length == 0)) {
333             String portalJarPath =
334                 PortalUtil.getPortalLibDir() + "commons-logging.jar";
335 
336             FileUtil.copyFile(
337                 portalJarPath, srcFile + "/WEB-INF/lib/commons-logging.jar",
338                 true);
339         }
340 
341         // log4j*.jar
342 
343         String[] log4jJars = pluginLibDir.list(
344             new GlobFilenameFilter("log4j*.jar"));
345 
346         if ((log4jJars == null) || (log4jJars.length == 0)) {
347             String portalJarPath = PortalUtil.getPortalLibDir() + "log4j.jar";
348 
349             FileUtil.copyFile(
350                 portalJarPath, srcFile + "/WEB-INF/lib/log4j.jar", true);
351         }
352     }
353 
354     public void copyProperties(File srcFile, PluginPackage pluginPackage)
355         throws Exception {
356 
357         copyDependencyXml("log4j.properties", srcFile + "/WEB-INF/classes");
358         copyDependencyXml("logging.properties", srcFile + "/WEB-INF/classes");
359     }
360 
361     public void copyTlds(File srcFile, PluginPackage pluginPackage)
362         throws Exception {
363 
364         if (Validator.isNotNull(portletTaglibDTD)) {
365             FileUtil.copyFile(
366                 portletTaglibDTD, srcFile + "/WEB-INF/tld/liferay-portlet.tld",
367                 true);
368         }
369 
370         if (Validator.isNotNull(portletExtTaglibDTD)) {
371             FileUtil.copyFile(
372                 portletExtTaglibDTD,
373                 srcFile + "/WEB-INF/tld/liferay-portlet-ext.tld", true);
374         }
375 
376         if (Validator.isNotNull(securityTaglibDTD)) {
377             FileUtil.copyFile(
378                 securityTaglibDTD,
379                 srcFile + "/WEB-INF/tld/liferay-security.tld", true);
380         }
381 
382         if (Validator.isNotNull(themeTaglibDTD)) {
383             FileUtil.copyFile(
384                 themeTaglibDTD, srcFile + "/WEB-INF/tld/liferay-theme.tld",
385                 true);
386         }
387 
388         if (Validator.isNotNull(uiTaglibDTD)) {
389             FileUtil.copyFile(
390                 uiTaglibDTD, srcFile + "/WEB-INF/tld/liferay-ui.tld", true);
391         }
392 
393         if (Validator.isNotNull(utilTaglibDTD)) {
394             FileUtil.copyFile(
395                 utilTaglibDTD, srcFile + "/WEB-INF/tld/liferay-util.tld", true);
396         }
397     }
398 
399     public void copyXmls(
400             File srcFile, String displayName, PluginPackage pluginPackage)
401         throws Exception {
402 
403         if (appServerType.startsWith(ServerDetector.GERONIMO_ID)) {
404             copyDependencyXml("geronimo-web.xml", srcFile + "/WEB-INF");
405         }
406         else if (appServerType.equals(ServerDetector.WEBLOGIC_ID)) {
407             copyDependencyXml("weblogic.xml", srcFile + "/WEB-INF");
408         }
409         else if (appServerType.equals(ServerDetector.WEBSPHERE_ID)) {
410             copyDependencyXml("ibm-web-ext.xmi", srcFile + "/WEB-INF");
411         }
412 
413         copyDependencyXml("web.xml", srcFile + "/WEB-INF");
414     }
415 
416     public void deploy() throws Exception {
417         try {
418             File baseDirFile = new File(baseDir);
419 
420             File[] files = baseDirFile.listFiles();
421 
422             if (files == null) {
423                 return;
424             }
425 
426             files = FileUtil.sortFiles(files);
427 
428             for (int i = 0; i < files.length; i++) {
429                 File srcFile = files[i];
430 
431                 String fileName = srcFile.getName().toLowerCase();
432 
433                 boolean deploy = false;
434 
435                 if (fileName.endsWith(".war") || fileName.endsWith(".zip")) {
436                     deploy = true;
437 
438                     if (wars.size() > 0) {
439                         if (!wars.contains(srcFile.getName())) {
440                             deploy = false;
441                         }
442                     }
443                     else if (Validator.isNotNull(filePattern)) {
444                         if (!StringUtil.matches(fileName, filePattern)) {
445                             deploy = false;
446                         }
447                     }
448                 }
449 
450                 if (deploy) {
451                     deployFile(srcFile);
452                 }
453             }
454         }
455         catch (Exception e) {
456             e.printStackTrace();
457         }
458     }
459 
460     public void deployDirectory(
461             File srcFile, String displayName, boolean override,
462             PluginPackage pluginPackage)
463         throws Exception {
464 
465         deployDirectory(
466             srcFile, null, null, displayName, override, pluginPackage);
467     }
468 
469     public void deployDirectory(
470             File srcFile, File mergeDir, File deployDir, String displayName,
471             boolean overwrite, PluginPackage pluginPackage)
472         throws Exception {
473 
474         rewriteFiles(srcFile);
475 
476         mergeDirectory(mergeDir, srcFile);
477 
478         processPluginPackageProperties(srcFile, displayName, pluginPackage);
479 
480         copyJars(srcFile, pluginPackage);
481         copyProperties(srcFile, pluginPackage);
482         copyTlds(srcFile, pluginPackage);
483         copyXmls(srcFile, displayName, pluginPackage);
484         copyPortalDependencies(srcFile);
485 
486         updateGeronimoWebXml(srcFile, displayName, pluginPackage);
487 
488         File webXml = new File(srcFile + "/WEB-INF/web.xml");
489 
490         updateWebXml(webXml, srcFile, displayName, pluginPackage);
491 
492         File extLibGlobalDir = new File(
493             srcFile.getAbsolutePath() + "/WEB-INF/ext-lib/global");
494 
495         if (extLibGlobalDir.exists()) {
496             File globalLibDir = new File(PortalUtil.getGlobalLibDir());
497 
498             CopyTask.copyDirectory(
499                 extLibGlobalDir, globalLibDir, "*.jar", StringPool.BLANK,
500                 overwrite, true);
501         }
502 
503         File extLibPortalDir = new File(
504             srcFile.getAbsolutePath() + "/WEB-INF/ext-lib/portal");
505 
506         if (extLibPortalDir.exists()) {
507             File portalLibDir = new File(PortalUtil.getPortalLibDir());
508 
509             CopyTask.copyDirectory(
510                 extLibPortalDir, portalLibDir, "*.jar", StringPool.BLANK,
511                 overwrite, true);
512         }
513 
514         if ((deployDir == null) || baseDir.equals(destDir)) {
515             return;
516         }
517 
518         updateDeployDirectory(srcFile);
519 
520         String excludes = StringPool.BLANK;
521 
522         if (appServerType.startsWith("jboss")) {
523             excludes += "**/WEB-INF/lib/log4j.jar,";
524         }
525         else if (appServerType.equals(ServerDetector.TOMCAT_ID)) {
526             String[] libs = FileUtil.listFiles(tomcatLibDir);
527 
528             for (int i = 0; i < libs.length; i++) {
529                 excludes += "**/WEB-INF/lib/" + libs[i] + ",";
530             }
531 
532             File contextXml = new File(srcFile + "/META-INF/context.xml");
533 
534             if (contextXml.exists()) {
535                 String content = FileUtil.read(contextXml);
536 
537                 if (content.indexOf(_PORTAL_CLASS_LOADER) != -1) {
538                     excludes += "**/WEB-INF/lib/util-bridges.jar,";
539                     excludes += "**/WEB-INF/lib/util-java.jar,";
540                     excludes += "**/WEB-INF/lib/util-taglib.jar,";
541                 }
542             }
543 
544             try {
545 
546                 // LEP-2990
547 
548                 Class.forName("javax.el.ELContext");
549 
550                 excludes += "**/WEB-INF/lib/el-api.jar,";
551             }
552             catch (ClassNotFoundException cnfe) {
553             }
554         }
555 
556         if (!unpackWar || appServerType.equals(ServerDetector.WEBSPHERE_ID)) {
557             File tempDir = new File(
558                 SystemProperties.get(SystemProperties.TMP_DIR) +
559                     File.separator + Time.getTimestamp());
560 
561             WarTask.war(srcFile, tempDir, "WEB-INF/web.xml", webXml);
562 
563             if (isJEEDeploymentEnabled()) {
564                 File tempWarDir = new File(
565                     tempDir.getParent(), deployDir.getName());
566 
567                 if (tempWarDir.exists()) {
568                     tempWarDir.delete();
569                 }
570 
571                 if (!tempDir.renameTo(tempWarDir)) {
572                     tempWarDir = tempDir;
573                 }
574 
575                 DeploymentHandler deploymentHandler = getDeploymentHandler();
576 
577                 deploymentHandler.deploy(tempWarDir, displayName);
578 
579                 deploymentHandler.releaseDeploymentManager();
580 
581                 DeleteTask.deleteDirectory(tempWarDir);
582             }
583             else {
584                 if (!tempDir.renameTo(deployDir)) {
585                     WarTask.war(srcFile, deployDir, "WEB-INF/web.xml", webXml);
586                 }
587 
588                 DeleteTask.deleteDirectory(tempDir);
589             }
590         }
591         else {
592 
593             // The deployer might only copy files that have been modified.
594             // However, the deployer always copies and overwrites web.xml after
595             // the other files have been copied because application servers
596             // usually detect that a WAR has been modified based on the web.xml
597             // timestamp.
598 
599             excludes += "**/WEB-INF/web.xml";
600 
601             CopyTask.copyDirectory(
602                 srcFile, deployDir, StringPool.BLANK, excludes, overwrite,
603                 true);
604 
605             CopyTask.copyDirectory(
606                 srcFile, deployDir, "**/WEB-INF/web.xml", StringPool.BLANK,
607                 true, false);
608 
609             if (appServerType.equals(ServerDetector.TOMCAT_ID)) {
610 
611                 // See org.apache.catalina.startup.HostConfig to see how Tomcat
612                 // checks to make sure that web.xml was modified 5 seconds after
613                 // WEB-INF
614 
615                 File deployWebXml = new File(deployDir + "/WEB-INF/web.xml");
616 
617                 deployWebXml.setLastModified(
618                     System.currentTimeMillis() + (Time.SECOND * 6));
619             }
620         }
621     }
622 
623     public void deployFile(File srcFile) throws Exception {
624         PluginPackage pluginPackage = readPluginPackage(srcFile);
625 
626         if (_log.isInfoEnabled()) {
627             _log.info("Deploying " + srcFile.getName());
628         }
629 
630         String deployDir = null;
631         String displayName = null;
632         boolean overwrite = false;
633         String preliminaryContext = null;
634 
635         // File names starting with DEPLOY_TO_PREFIX should use the filename
636         // after the prefix as the deployment context
637 
638         if (srcFile.getName().startsWith(DEPLOY_TO_PREFIX)) {
639             displayName = srcFile.getName().substring(
640                 DEPLOY_TO_PREFIX.length(), srcFile.getName().length() - 4);
641 
642             overwrite = true;
643             preliminaryContext = displayName;
644         }
645 
646         if (preliminaryContext == null) {
647             preliminaryContext = getDisplayName(srcFile);
648         }
649 
650         if (pluginPackage != null) {
651             if (!PluginPackageUtil.isCurrentVersionSupported(
652                     pluginPackage.getLiferayVersions())) {
653 
654                 throw new AutoDeployException(
655                     srcFile.getName() +
656                         " does not support this version of Liferay");
657             }
658 
659             if (displayName == null) {
660                 displayName = pluginPackage.getRecommendedDeploymentContext();
661             }
662 
663             if (Validator.isNull(displayName)) {
664                 displayName = getDisplayName(srcFile);
665             }
666 
667             pluginPackage.setContext(displayName);
668 
669             PluginPackageUtil.updateInstallingPluginPackage(
670                 preliminaryContext, pluginPackage);
671         }
672 
673         if (Validator.isNotNull(displayName)) {
674             deployDir = displayName + ".war";
675         }
676         else {
677             deployDir = srcFile.getName();
678             displayName = getDisplayName(srcFile);
679         }
680 
681         if (appServerType.startsWith(ServerDetector.JBOSS_ID)) {
682             deployDir = jbossPrefix + deployDir;
683         }
684         else if (appServerType.equals(ServerDetector.JETTY_ID) ||
685                  appServerType.equals(ServerDetector.OC4J_ID) ||
686                  appServerType.equals(ServerDetector.RESIN_ID) ||
687                  appServerType.equals(ServerDetector.TOMCAT_ID)) {
688 
689             if (unpackWar) {
690                 deployDir = deployDir.substring(0, deployDir.length() - 4);
691             }
692         }
693 
694         deployDir = destDir + "/" + deployDir;
695 
696         File deployDirFile = new File(deployDir);
697 
698         try {
699             PluginPackage previousPluginPackage =
700                 readPluginPackage(deployDirFile);
701 
702             if ((pluginPackage != null) && (previousPluginPackage != null)) {
703                 if (_log.isInfoEnabled()) {
704                     String name = pluginPackage.getName();
705                     String previousVersion = previousPluginPackage.getVersion();
706                     String version = pluginPackage.getVersion();
707 
708                     _log.info(
709                         "Updating " + name + " from version " +
710                             previousVersion + " to version " + version);
711                 }
712 
713                 if (pluginPackage.isLaterVersionThan(
714                     previousPluginPackage)) {
715 
716                     overwrite = true;
717                 }
718             }
719 
720             File mergeDirFile = new File(
721                 srcFile.getParent() + "/merge/" + srcFile.getName());
722 
723             if (srcFile.isDirectory()) {
724                 deployDirectory(
725                     srcFile, mergeDirFile, deployDirFile, displayName,
726                     overwrite, pluginPackage);
727             }
728             else {
729                 boolean deployed = deployFile(
730                     srcFile, mergeDirFile, deployDirFile, displayName,
731                     overwrite, pluginPackage);
732 
733                 if (!deployed) {
734                     String context = preliminaryContext;
735 
736                     if (pluginPackage != null) {
737                         context = pluginPackage.getContext();
738                     }
739 
740                     PluginPackageUtil.endPluginPackageInstallation(context);
741                 }
742             }
743         }
744         catch (Exception e) {
745             if (pluginPackage != null) {
746                 PluginPackageUtil.endPluginPackageInstallation(
747                     pluginPackage.getContext());
748             }
749 
750             throw e;
751         }
752     }
753 
754     public boolean deployFile(
755             File srcFile, File mergeDir, File deployDir, String displayName,
756             boolean overwrite, PluginPackage pluginPackage)
757         throws Exception {
758 
759         boolean undeployOnRedeploy = false;
760 
761         try {
762             undeployOnRedeploy = PrefsPropsUtil.getBoolean(
763                 PropsKeys.HOT_UNDEPLOY_ON_REDEPLOY,
764                 PropsValues.HOT_UNDEPLOY_ON_REDEPLOY);
765         }
766         catch (Exception e) {
767 
768             // This will only happen when running the deploy tool in Ant in the
769             // classical way where the WAR file is actually massaged and
770             // packaged.
771 
772         }
773 
774         if (undeployOnRedeploy) {
775             DeployUtil.undeploy(appServerType, deployDir);
776         }
777 
778         if (!overwrite && UpToDateTask.isUpToDate(srcFile, deployDir)) {
779             if (_log.isInfoEnabled()) {
780                 _log.info(deployDir + " is already up to date");
781             }
782 
783             return false;
784         }
785 
786         File tempDir = new File(
787             SystemProperties.get(SystemProperties.TMP_DIR) + File.separator +
788                 Time.getTimestamp());
789 
790         ExpandTask.expand(srcFile, tempDir);
791 
792         deployDirectory(
793             tempDir, mergeDir, deployDir, displayName, overwrite,
794             pluginPackage);
795 
796         DeleteTask.deleteDirectory(tempDir);
797 
798         return true;
799     }
800 
801     public String downloadJar(String jar) throws Exception {
802         String tmpDir = SystemProperties.get(SystemProperties.TMP_DIR);
803 
804         File file = new File(
805             tmpDir + "/liferay/com/liferay/portal/deploy/dependencies/" +
806                 jar);
807 
808         if (!file.exists()) {
809             synchronized (this) {
810                 String url = PropsUtil.get(
811                     PropsKeys.LIBRARY_DOWNLOAD_URL + jar);
812 
813                 if (_log.isInfoEnabled()) {
814                     _log.info("Downloading library from " + url);
815                 }
816 
817                 byte[] bytes = HttpUtil.URLtoByteArray(url);
818 
819                 FileUtil.write(file, bytes);
820             }
821         }
822 
823         return FileUtil.getAbsolutePath(file);
824     }
825 
826     public String getDisplayName(File srcFile) {
827         String displayName = srcFile.getName();
828 
829         if (StringUtil.endsWith(displayName, ".war") ||
830             StringUtil.endsWith(displayName, ".xml")) {
831 
832             displayName = displayName.substring(0, displayName.length() - 4);
833         }
834 
835         if (appServerType.startsWith("jboss") &&
836             Validator.isNotNull(jbossPrefix) &&
837             displayName.startsWith(jbossPrefix)) {
838 
839             displayName = displayName.substring(1, displayName.length());
840         }
841 
842         return displayName;
843     }
844 
845     public DeploymentHandler getDeploymentHandler() {
846         String prefix = "auto.deploy." + ServerDetector.getServerId() + ".jee.";
847 
848         String dmId = PropsUtil.get(prefix + "dm.id");
849         String dmUser =  PropsUtil.get(prefix + "dm.user");
850         String dmPassword =  PropsUtil.get(prefix + "dm.passwd");
851         String dfClassName = PropsUtil.get(prefix + "df.classname");
852 
853         return new DeploymentHandler(dmId, dmUser, dmPassword, dfClassName);
854     }
855 
856     public String getExtraContent(
857             double webXmlVersion, File srcFile, String displayName)
858         throws Exception {
859 
860         StringBundler sb = new StringBundler();
861 
862         sb.append("<display-name>");
863         sb.append(displayName);
864         sb.append("</display-name>");
865 
866         sb.append("<listener>");
867         sb.append("<listener-class>");
868         sb.append("com.liferay.portal.kernel.servlet.");
869         sb.append("SerializableSessionAttributeListener");
870         sb.append("</listener-class>");
871         sb.append("</listener>");
872 
873         File serviceXml = new File(srcFile + "/WEB-INF/service.xml");
874 
875         if (serviceXml.exists()) {
876             sb.append("<listener>");
877             sb.append("<listener-class>");
878             sb.append("com.liferay.portal.kernel.spring.context.");
879             sb.append("PortletContextLoaderListener");
880             sb.append("</listener-class>");
881             sb.append("</listener>");
882         }
883 
884         File serverConfigWsdd = new File(
885             srcFile + "/WEB-INF/server-config.wsdd");
886 
887         if (serverConfigWsdd.exists()) {
888             File webXml = new File(srcFile + "/WEB-INF/web.xml");
889 
890             String content = FileUtil.read(webXml);
891 
892             if (!content.contains("axis.servicesPath")) {
893                 String remotingContent = FileUtil.read(
894                     DeployUtil.getResourcePath("remoting-web.xml"));
895 
896                 sb.append(remotingContent);
897             }
898         }
899 
900         boolean hasTaglib = false;
901 
902         if (Validator.isNotNull(portletTaglibDTD) ||
903             Validator.isNotNull(portletExtTaglibDTD) ||
904             Validator.isNotNull(securityTaglibDTD) ||
905             Validator.isNotNull(themeTaglibDTD) ||
906             Validator.isNotNull(uiTaglibDTD) ||
907             Validator.isNotNull(utilTaglibDTD)) {
908 
909             hasTaglib = true;
910         }
911 
912         if (hasTaglib && (webXmlVersion > 2.3)) {
913             sb.append("<jsp-config>");
914         }
915 
916         if (Validator.isNotNull(portletTaglibDTD)) {
917             sb.append("<taglib>");
918             sb.append(
919                 "<taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>");
920             sb.append("<taglib-location>");
921             sb.append("/WEB-INF/tld/liferay-portlet.tld");
922             sb.append("</taglib-location>");
923             sb.append("</taglib>");
924         }
925 
926         if (Validator.isNotNull(portletExtTaglibDTD)) {
927             sb.append("<taglib>");
928             sb.append("<taglib-uri>");
929             sb.append("http://liferay.com/tld/portlet");
930             sb.append("</taglib-uri>");
931             sb.append("<taglib-location>");
932             sb.append("/WEB-INF/tld/liferay-portlet-ext.tld");
933             sb.append("</taglib-location>");
934             sb.append("</taglib>");
935         }
936 
937         if (Validator.isNotNull(securityTaglibDTD)) {
938             sb.append("<taglib>");
939             sb.append("<taglib-uri>");
940             sb.append("http://liferay.com/tld/security");
941             sb.append("</taglib-uri>");
942             sb.append("<taglib-location>");
943             sb.append("/WEB-INF/tld/liferay-security.tld");
944             sb.append("</taglib-location>");
945             sb.append("</taglib>");
946         }
947 
948         if (Validator.isNotNull(themeTaglibDTD)) {
949             sb.append("<taglib>");
950             sb.append("<taglib-uri>http://liferay.com/tld/theme</taglib-uri>");
951             sb.append("<taglib-location>");
952             sb.append("/WEB-INF/tld/liferay-theme.tld");
953             sb.append("</taglib-location>");
954             sb.append("</taglib>");
955         }
956 
957         if (Validator.isNotNull(uiTaglibDTD)) {
958             sb.append("<taglib>");
959             sb.append("<taglib-uri>http://liferay.com/tld/ui</taglib-uri>");
960             sb.append("<taglib-location>");
961             sb.append("/WEB-INF/tld/liferay-ui.tld");
962             sb.append("</taglib-location>");
963             sb.append("</taglib>");
964         }
965 
966         if (Validator.isNotNull(utilTaglibDTD)) {
967             sb.append("<taglib>");
968             sb.append("<taglib-uri>http://liferay.com/tld/util</taglib-uri>");
969             sb.append("<taglib-location>");
970             sb.append("/WEB-INF/tld/liferay-util.tld");
971             sb.append("</taglib-location>");
972             sb.append("</taglib>");
973         }
974 
975         if (hasTaglib && (webXmlVersion > 2.3)) {
976             sb.append("</jsp-config>");
977         }
978 
979         return sb.toString();
980     }
981 
982     public String getIgnoreFiltersContent(File srcFile) throws Exception {
983         boolean ignoreFiltersEnabled = true;
984 
985         Properties properties = getPluginPackageProperties(srcFile);
986 
987         if (properties != null) {
988             ignoreFiltersEnabled = GetterUtil.getBoolean(
989                 properties.getProperty("ignore-filters-enabled"), true);
990         }
991 
992         if (ignoreFiltersEnabled) {
993             String ignoreFiltersContent = FileUtil.read(
994                 DeployUtil.getResourcePath("ignore-filters-web.xml"));
995 
996             return ignoreFiltersContent;
997         }
998         else {
999             return StringPool.BLANK;
1000        }
1001    }
1002
1003    public String getPluginPackageLicensesXml(List<License> licenses) {
1004        if (licenses.isEmpty()) {
1005            return StringPool.BLANK;
1006        }
1007
1008        StringBundler sb = new StringBundler(5 * licenses.size() + 2);
1009
1010        for (int i = 0; i < licenses.size(); i++) {
1011            License license = licenses.get(i);
1012
1013            if (i == 0) {
1014                sb.append("\r\n");
1015            }
1016
1017            sb.append("\t\t<license osi-approved=\"");
1018            sb.append(license.isOsiApproved());
1019            sb.append("\">");
1020            sb.append(license.getName());
1021            sb.append("</license>\r\n");
1022
1023            if ((i + 1) == licenses.size()) {
1024                sb.append("\t");
1025            }
1026        }
1027
1028        return sb.toString();
1029    }
1030
1031    public String getPluginPackageLiferayVersionsXml(
1032        List<String> liferayVersions) {
1033
1034        if (liferayVersions.isEmpty()) {
1035            return StringPool.BLANK;
1036        }
1037
1038        StringBundler sb = new StringBundler(liferayVersions.size() * 3 + 2);
1039
1040        for (int i = 0; i < liferayVersions.size(); i++) {
1041            String liferayVersion = liferayVersions.get(i);
1042
1043            if (i == 0) {
1044                sb.append("\r\n");
1045            }
1046
1047            sb.append("\t\t<liferay-version>");
1048            sb.append(liferayVersion);
1049            sb.append("</liferay-version>\r\n");
1050
1051            if ((i + 1) == liferayVersions.size()) {
1052                sb.append("\t");
1053            }
1054        }
1055
1056        return sb.toString();
1057    }
1058
1059    public Properties getPluginPackageProperties(File srcFile)
1060        throws Exception {
1061
1062        File propertiesFile = new File(
1063            srcFile + "/WEB-INF/liferay-plugin-package.properties");
1064
1065        if (!propertiesFile.exists()) {
1066            return null;
1067        }
1068
1069        String propertiesString = FileUtil.read(propertiesFile);
1070
1071        return PropertiesUtil.load(propertiesString);
1072    }
1073
1074    public String getPluginPackageTagsXml(List<String> tags) {
1075        if (tags.isEmpty()) {
1076            return StringPool.BLANK;
1077        }
1078
1079        StringBundler sb = new StringBundler(tags.size() * 3 + 2);
1080
1081        for (int i = 0; i < tags.size(); i++) {
1082            String tag = tags.get(i);
1083
1084            if (i == 0) {
1085                sb.append("\r\n");
1086            }
1087
1088            sb.append("\t\t<tag>");
1089            sb.append(tag);
1090            sb.append("</tag>\r\n");
1091
1092            if ((i + 1) == tags.size()) {
1093                sb.append("\t");
1094            }
1095        }
1096
1097        return sb.toString();
1098    }
1099
1100    public String getSpeedFiltersContent(File srcFile) throws Exception {
1101        boolean speedFiltersEnabled = true;
1102
1103        Properties properties = getPluginPackageProperties(srcFile);
1104
1105        if (properties != null) {
1106            speedFiltersEnabled = GetterUtil.getBoolean(
1107                properties.getProperty("speed-filters-enabled"), true);
1108        }
1109
1110        if (speedFiltersEnabled) {
1111            String speedFiltersContent = FileUtil.read(
1112                DeployUtil.getResourcePath("speed-filters-web.xml"));
1113
1114            return speedFiltersContent;
1115        }
1116        else {
1117            return StringPool.BLANK;
1118        }
1119    }
1120
1121    public boolean isJEEDeploymentEnabled() {
1122        return GetterUtil.getBoolean(PropsUtil.get(
1123            "auto.deploy." + ServerDetector.getServerId() +
1124                ".jee.deployment.enabled"));
1125    }
1126
1127    public void mergeDirectory(File mergeDir, File targetDir) {
1128        if ((mergeDir == null) || (!mergeDir.exists())) {
1129            return;
1130        }
1131
1132        CopyTask.copyDirectory(mergeDir, targetDir, null, null, true, false);
1133    }
1134
1135    public void processPluginPackageProperties(
1136            File srcFile, String displayName, PluginPackage pluginPackage)
1137        throws Exception {
1138    }
1139
1140    public PluginPackage readPluginPackage(File file) {
1141        if (!file.exists()) {
1142            return null;
1143        }
1144
1145        InputStream is = null;
1146        ZipFile zipFile = null;
1147
1148        try {
1149            boolean parseProps = false;
1150
1151            if (file.isDirectory()) {
1152                String path = file.getPath();
1153
1154                File pluginPackageXmlFile = new File(
1155                    file.getParent() + "/merge/" + file.getName() +
1156                        "/WEB-INF/liferay-plugin-package.xml");
1157
1158                if (pluginPackageXmlFile.exists()) {
1159                    is = new FileInputStream(pluginPackageXmlFile);
1160                }
1161                else {
1162                    pluginPackageXmlFile = new File(
1163                        path + "/WEB-INF/liferay-plugin-package.xml");
1164
1165                    if (pluginPackageXmlFile.exists()) {
1166                        is = new FileInputStream(pluginPackageXmlFile);
1167                    }
1168                }
1169
1170                File pluginPackagePropsFile = new File(
1171                    file.getParent() + "/merge/" + file.getName() +
1172                        "/WEB-INF/liferay-plugin-package.properties");
1173
1174                if ((is == null) && pluginPackagePropsFile.exists()) {
1175                    is = new FileInputStream(pluginPackagePropsFile);
1176
1177                    parseProps = true;
1178                }
1179                else {
1180                    pluginPackagePropsFile = new File(
1181                        path + "/WEB-INF/liferay-plugin-package.properties");
1182
1183                    if ((is == null) && pluginPackagePropsFile.exists()) {
1184                        is = new FileInputStream(pluginPackagePropsFile);
1185
1186                        parseProps = true;
1187                    }
1188                }
1189            }
1190            else {
1191                zipFile = new ZipFile(file);
1192
1193                File pluginPackageXmlFile = new File(
1194                    file.getParent() + "/merge/" + file.getName() +
1195                        "/WEB-INF/liferay-plugin-package.xml");
1196
1197                if (pluginPackageXmlFile.exists()) {
1198                    is = new FileInputStream(pluginPackageXmlFile);
1199                }
1200                else {
1201                    ZipEntry zipEntry = zipFile.getEntry(
1202                        "WEB-INF/liferay-plugin-package.xml");
1203
1204                    if (zipEntry != null) {
1205                        is = zipFile.getInputStream(zipEntry);
1206                    }
1207                }
1208
1209                File pluginPackagePropsFile = new File(
1210                    file.getParent() + "/merge/" + file.getName() +
1211                        "/WEB-INF/liferay-plugin-package.properties");
1212
1213                if ((is == null) && pluginPackagePropsFile.exists()) {
1214                    is = new FileInputStream(pluginPackagePropsFile);
1215
1216                    parseProps = true;
1217                }
1218                else {
1219                    ZipEntry zipEntry = zipFile.getEntry(
1220                        "WEB-INF/liferay-plugin-package.properties");
1221
1222                    if ((is == null) && (zipEntry != null)) {
1223                        is = zipFile.getInputStream(zipEntry);
1224
1225                        parseProps = true;
1226                    }
1227                }
1228            }
1229
1230            if (is == null) {
1231                if (_log.isInfoEnabled()) {
1232                    _log.info(
1233                        file.getPath() + " does not have a " +
1234                            "WEB-INF/liferay-plugin-package.xml or " +
1235                                "WEB-INF/liferay-plugin-package.properties");
1236                }
1237
1238                return null;
1239            }
1240
1241            if (parseProps) {
1242                String displayName = getDisplayName(file);
1243
1244                String propertiesString = StringUtil.read(is);
1245
1246                Properties properties = PropertiesUtil.load(propertiesString);
1247
1248                return PluginPackageUtil.readPluginPackageProperties(
1249                    displayName, properties);
1250            }
1251            else {
1252                String xml = StringUtil.read(is);
1253
1254                xml = XMLFormatter.fixProlog(xml);
1255
1256                return PluginPackageUtil.readPluginPackageXml(xml);
1257            }
1258        }
1259        catch (Exception e) {
1260            _log.error(file.getPath() + ": " + e.toString());
1261        }
1262        finally {
1263            if (is != null) {
1264                try {
1265                    is.close();
1266                }
1267                catch (IOException ioe) {
1268                }
1269            }
1270
1271            if (zipFile != null) {
1272                try {
1273                    zipFile.close();
1274                }
1275                catch (IOException ioe) {
1276                }
1277            }
1278        }
1279
1280        return null;
1281    }
1282
1283    public void rewriteFiles(File srcDir) throws Exception {
1284        String[] files = FileUtil.listFiles(srcDir + "/WEB-INF/");
1285
1286        for (int i = 0; i < files.length; i++) {
1287            String fileName = GetterUtil.getString(
1288                FileUtil.getShortFileName(files[i]));
1289
1290            // LEP-6415
1291
1292            if (fileName.equalsIgnoreCase("mule-config.xml")) {
1293                continue;
1294            }
1295
1296            String ext = GetterUtil.getString(FileUtil.getExtension(files[i]));
1297
1298            if (!ext.equalsIgnoreCase("xml")) {
1299                continue;
1300            }
1301
1302            // Make sure to rewrite any XML files to include external entities
1303            // into same file. See LEP-3142.
1304
1305            File file = new File(srcDir + "/WEB-INF/" + files[i]);
1306
1307            try {
1308                Document doc = SAXReaderUtil.read(file);
1309
1310                String content = doc.formattedString(StringPool.TAB, true);
1311
1312                FileUtil.write(file, content);
1313            }
1314            catch (Exception e) {
1315                if (_log.isWarnEnabled()) {
1316                    _log.warn(
1317                        "Unable to format " + file + ": " + e.getMessage());
1318                }
1319            }
1320        }
1321    }
1322
1323    public void updateDeployDirectory(File srcFile) throws Exception {
1324    }
1325
1326    public void updateGeronimoWebXml(
1327            File srcFile, String displayName, PluginPackage pluginPackage)
1328        throws Exception {
1329
1330        if (!appServerType.startsWith(ServerDetector.GERONIMO_ID)) {
1331            return;
1332        }
1333
1334        File geronimoWebXml = new File(srcFile + "/WEB-INF/geronimo-web.xml");
1335
1336        Document doc = SAXReaderUtil.read(geronimoWebXml);
1337
1338        Element root = doc.getRootElement();
1339
1340        Element environmentEl = root.element("environment");
1341
1342        Element moduleIdEl = environmentEl.element("moduleId");
1343
1344        Element artifactIdEl = moduleIdEl.element("artifactId");
1345
1346        String artifactIdText = GetterUtil.getString(artifactIdEl.getText());
1347
1348        if (!artifactIdText.equals(displayName)) {
1349            artifactIdEl.setText(displayName);
1350
1351            String content = doc.formattedString();
1352
1353            FileUtil.write(geronimoWebXml, content);
1354
1355            if (_log.isInfoEnabled()) {
1356                _log.info("Modifying Geronimo " + geronimoWebXml);
1357            }
1358        }
1359    }
1360
1361    public void updateWebXml(
1362            File webXml, File srcFile, String displayName,
1363            PluginPackage pluginPackage)
1364        throws Exception {
1365
1366        String content = FileUtil.read(webXml);
1367
1368        int x = content.indexOf("<display-name>");
1369
1370        if (x != -1) {
1371            int y = content.indexOf("</display-name>", x);
1372
1373            y = content.indexOf(">", y) + 1;
1374
1375            content = content.substring(0, x) + content.substring(y);
1376        }
1377
1378        double webXmlVersion = 2.3;
1379
1380        Document webXmlDoc = SAXReaderUtil.read(content);
1381
1382        Element webXmlRoot = webXmlDoc.getRootElement();
1383
1384        webXmlVersion = GetterUtil.getDouble(
1385            webXmlRoot.attributeValue("version"), webXmlVersion);
1386
1387        // Merge extra content
1388
1389        String extraContent = getExtraContent(
1390            webXmlVersion, srcFile, displayName);
1391
1392        if (webXmlVersion > 2.3) {
1393            while (true) {
1394                int pos = extraContent.indexOf(
1395                    "<param-name>servlet-2.4-dispatcher</param-name>");
1396
1397                if (pos == -1) {
1398                    break;
1399                }
1400
1401                x = extraContent.lastIndexOf("<init-param>", pos);
1402                int y = extraContent.indexOf("</init-param>", pos);
1403
1404                extraContent =
1405                    extraContent.substring(0, x) +
1406                        extraContent.substring(y + 13);
1407            }
1408        }
1409
1410        int pos = content.indexOf("</web-app>");
1411
1412        String newContent =
1413            content.substring(0, pos) + extraContent +
1414                content.substring(pos, content.length());
1415
1416        // Replace old package names
1417
1418        newContent = StringUtil.replace(
1419            newContent, "com.liferay.portal.shared.",
1420            "com.liferay.portal.kernel.");
1421
1422        newContent = WebXMLBuilder.organizeWebXML(newContent);
1423
1424        FileUtil.write(webXml, newContent, true);
1425
1426        if (_log.isInfoEnabled()) {
1427            _log.info("Modifying Servlet " + webXmlVersion + " " + webXml);
1428        }
1429    }
1430
1431    protected String baseDir;
1432    protected String destDir;
1433    protected String appServerType;
1434    protected String portletTaglibDTD;
1435    protected String portletExtTaglibDTD;
1436    protected String securityTaglibDTD;
1437    protected String themeTaglibDTD;
1438    protected String uiTaglibDTD;
1439    protected String utilTaglibDTD;
1440    protected boolean unpackWar;
1441    protected String filePattern;
1442    protected String jbossPrefix;
1443    protected String tomcatLibDir;
1444    protected List<String> wars;
1445    protected List<String> jars;
1446
1447    private static final String _PORTAL_CLASS_LOADER =
1448        "com.liferay.support.tomcat.loader.PortalClassLoader";
1449
1450    private static Log _log = LogFactoryUtil.getLog(BaseDeployer.class);
1451
1452}