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