Updating files inside an existing WAR file

南楼画角 提交于 2019-12-18 12:55:32

问题


I am trying to update files inside an existing WAR file using the ANT WAR task. I need to replace a set of xml files in a folder in WAR with new ones from my HDD.

<war destfile="myApp.war" update="true" >
    <zipfileset dir="<PathToStubsFolderOnHDD>" includes="**/*.xml" prefix="<PathToStubsFolderInWAR>"/>
</war>

This works fine if the original WAR does not have xmls with same name. However if the original WAR contains xmls with same name; WAR task does not update them with files from HDD.

The ANT WAR task documentation reads:

update | indicates whether to update or overwrite the destination file if it already exists. Default is "false".
duplicate | behavior when a duplicate file is found. Valid values are "add", "preserve", and "fail". The default value is "add".

if i use update="false"; all other files in the original WAR are deleted and only the new xmls stored.

using duplicate="add" didnot have any effect either.

Any suggestions on how this can be achieved??


回答1:


Seems that with update=true option, the war file is newer than the files that you want to update. Someone suggest to apply the touch task with '0' to workaround the problem.

The zip task checks only if the source files you whish to add to an existing zip are more recent than the zip. A workaround would be to <touch millis="0" /> the zip file before adding.

Or you could do the reverse stuff:

Performing a touch before the war task on XML file(s) makes it work.




回答2:


Thanks Aito!

Here is the complete ANT script:

<target name = "UpdateWARWithStubs"
    description="Updates WAR file with files from Stub folder">

    <!-- Use touch to set modification time of all stubs to current time. This will force war task to update stub files inside the war -->
    <tstamp> <format property="touch.time" pattern="MM/dd/yyyy hh:mm aa"/>  </tstamp>
    <touch datetime="${touch.time}">
        <fileset dir="${path.to.stubs.on.hdd}" />
    </touch>

    <war destfile="myApp.war" update="true">
        <zipfileset dir="${path.to.stubs.on.hdd}"  prefix="${path.to.stubs.in.war}"/>
    </war>
</target>



回答3:


This is my solution to replace existing files in zip(.war) file. Initial state is I have build.xml to compile and package mywebapp.war for Tomcat6 server. Minor configuration changes within war file are required for Tomcat7 server.

  • project subfolders web and webT7 are CVS controlled folders, I don't want to touch timestamps for no reason. The following trick does the job.
  • compile and create web/WEB-INF/lib/mywebapp.jar file as usual
  • target "war" creates tomcat6 archive from web folder
  • have few specific files in webT7 subfolder such as META-INF/context.xml and WEB-INF/web.xml ones I have to modify a bit for each tomcat version.
  • create a copy of mywebapp.war.zip file
  • copy files from webT7 subfolder to a new build temp folder, do not use preservelastmodified attribute !!! This gives a new timestamp for each files, so its touches without separate touch command.
  • failsafe touch new zip to put past timestamp, this makes sure zip update works properly.
  • use zip task to update mywebapp.war_T7.zip content, it should replace existing files because we copied them without preserving original timestamps.

Reason I copy webT7 content to a temp build folder is content management systems. I don't want to change timestamps of the original repository files for no reason. Everything else compile,jar,war targets are always same no matter what Tomcat target I use.

Zip update="true" attribute as was said earlier do not replace files, it updates only if zip had older file than the one we give. This may introduce problems if I have web/config.jsp(2013-01-21 14:01:01) and webT7/config.jsp(2012-12-21 15:02:03) files. File was not replaced.

Snippet from build.xml file

<target name="war" depends="compile,jar" description="Create a .war file">
    <delete file="${name}.war.zip" />
    <zip destfile="${name}.war.zip"
        basedir="./web/"
        excludes="
            **/CVS*
            "
    />
</target>

<target name="warT7" depends="war" description="Create a .war file for Tomcat7">
    <delete dir="${build}" />
    <mkdir dir="${build}" />

    <delete file="${name}.war_T7.zip" />
    <copy file="${name}.war.zip" 
      tofile="${name}.war_T7.zip" overwrite="true" preservelastmodified="true"
    />      

    <copy todir="${build}" overwrite="true">
      <fileset dir="./webT7" />
    </copy>

    <touch datetime="01/31/1981 01:00:00 AM" file="${name}.war_T7.zip" />
    <zip destfile="${name}.war_T7.zip" update="true">
      <zipfileset dir="${build}"  prefix="" />
    </zip>
    <delete dir="${build}" />
</target>



回答4:


Perhaps the easiest way is to explode the war to a temporary directory, make your changes and then rebuild the war. Not nice, admittedly.




回答5:


Neither touch option worked for me. The original war file being created by a maven artifact from within the ant script might have something to do with this. Ended up repackaging the war file into a temp file and overwriting the original war file like this:

<target name="update-properties">
    <war destfile="target/${war.name}temp" needxmlfile='false'>
        <zipfileset src="target/${war.name}" includes="**/*" 
                      excludes="${path.to.properties.in.war}" />
        <zipfileset file="${path.to.new.properties}"  
                      fullpath="${path.to.properties.in.war}" />
    </war>
    <move file="target/${local.war.name}temp" tofile="target/${local.war.name}"/>
    <delete file="target/${local.war.name}temp"/>
</target>

where ${path.to.properties.in.war} can be something like "WEB-INF/classes/META-INF/spring/database.properties"



来源:https://stackoverflow.com/questions/2210041/updating-files-inside-an-existing-war-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!