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