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