To update a jar file adding one class I can use it:
jar -uvf
But I need to update a jar file inside a ear file, I tried the command below but it did not work:
jar -uvf NameOfEarfile.ear:FolderName/NameOfJar.jar path/NameOfClass.class
Could someone help me on it?
Better way to do is using 7zip software.
Below is the code to update the ear/war/zip/jar file. Before the execute of below code first convert the file into unix format.
Copy the below code in TestUpdate.sh file and copy to unix server. Then use below commands. Make sure the TestUpdate.sh, class files (which you want to copy inside the EAR/WAR/ZIP/jar) and the EAR/WAR/ZIP/jar file all are in same directory.
dos2unix TestUpdate.sh
. ./TestUpdate.sh FileNameWhichYouWantToUpdate # EAR/WAR/JAR/ZIP filename
#!/bin/bash
#LearName='TEST.ear'
LearName=$1
jar xf $LearName
for clas in *.class
do
echo "Checking for $clas ..."
for f in *.jar
do
result=$(jar tf $f | grep -w $clas)
if [ -n "$result" ]; then
echo "$f contains $result"
Lp="${#clas}";
Lr="${#result}";
count=$((Lr-Lp));
#echo $count
dirC=${result:0:$count};
echo "Directory $dirC"
echo $dirC
mkdir -p $dirC;
echo "Copying $clas $dirC"
cp $clas $dirC;
echo "updating $f ..."
jar ufv $f $result;
file_write "updating $f ..."
echo "Updating $LearName ..."
jar ufv $LearName $f;
echo "-----------------------------------------------"
break
fi
done
done
rm -f *.jar ---- comment this line if your input file is .jar. If your input file is EAR/WAR/ZIP file then NO need to comment this line
rm -r *.war
rm -r META-INF
rm -f *.tmp
rm -r com
I currently have a directory that contains numerous .java files, all with different names. ie. name.java, name2.java, name3.java
I am trying to write a script that loops through all of the files in the directory and changes their class names (inside the file) to match the file name itself.
Currently, all of the .java files contain the class name MyCritter. I want to change all instances of MyCritter in each of the files to the name of the particular java file itself. I wrote a script to try and replace all of the MyCritter terms, however I am getting no change in output. The code is getting frozen after printing the echo line for the first name of the file:
#!/bin/bash
dir1="/Users/path to folder"
subs=`ls $dir1`
for a in $subs;
do
echo a
[ -f "$a" ]
grep -lr "MyCritter" * | xargs sed “s/MyCritter/$a/g”
done
output to terminal: name.java --> then infinite loop/gets stuck
The above code prints the name of the first file in the directory once, but then gets stuck. When I change my second line to this: [ -f "$a" ] || continue it runs through the whole code, but fails to update the files.
I've tried other variations of grep including:
grep -lr -e "MyCritter" * | xargs sed -i “s/MyCritter/$a/g”
grep -lr -e "MyCritter" . | xargs sed -i “s/MyCritter/$a/g”
grep -lr -e "MyCritter" . | xargs sed “s/MyCritter/$a/g”
I was primarily using this site to guide me: http://isaacsukin.com/news/2013/06/command-line-tip-replace-word-all-files-directory
Any push in the right direction would be much appreciated!
If you don't need to have a solution is script form, in a terminal, just cd to the directory containing the *.java files and use the following command:
for f in *.java; do sed -i "s/MyCritter/"${f%.*}"/g" "$f"; done
The "${f%.*}" portion of the sed command returns the filename without the extension and uses it to replace MyCritter.
As others mentioned, there are syntax errors in your code and shellcheck can easily detect those.
One of the alternate ways this can be done is:
#!/bin/bash
dir1="Absolute_path_for_dir"
for f in $dir1/*.java;do
# Extract name from /path/name.java
filename=$(basename "$f" .java)
# Replace ALL occurrences of MyCritter with filename in file $f
sed -i "s/MyCritter/$filename/g" "$f"
done
With GNU awk for inplace editing:
awk -i inplace '{gsub(/MyCritter/,FILENAME)} 1' *.java
or if you want to strip off the ".java":
awk -i inplace 'FNR==1{f=FILENAME; sub(/\.java$/,"",f)} {gsub(/MyCritter/,f)} 1' *.java
I have the following script which does close to what I need; that is, to search the whole system for jar files that contain a specific java class file. My only issue with this script is getting it to acknowledge when it has found a class file in the jar based on the class name I pass in. The script at the moment only gives me back the class package inside the jar, not the jar it is in, which means its kind of useless. I'm trying to use $? to check if the search command was successful and if so echo the directory it was in into a file. It's always returning success(0) though, so every jar location it finds it is appending to the file. I'll stop talking now, can someone run this script and see what it is doing vs what I am trying to do?
if [ $# -ne 1 ]
then
echo "Need to provide class name as argument"
exit 1
fi
> findClassResults.txt
for i in $(locate "*.jar");
do
if [ -d $i ]
then
continue
fi
if jar -tvf $i | grep -Hsi $1.class 1>/dev/null
then
potentialMatches=`jar -tvf $i | grep -Hsi $1.class`
exactMatch=`echo $potentialMatches | grep -o \/$1.class`
if [ ! -z $exactMatch ]
then
echo "matches found: " $potentialMatches >> findClassResults.txt
echo ".....in jar #: " $i >> findClassResults.txt
echo -e "\n" >> findClassResults.txt
fi
fi
done
Edit: the above is now the working script. It will find any .class file and the location of its jar on the system by passing in the name of the class e.g. ./findClass.sh MyClass
Redirect the output of the loop as a whole to your results file, not each command individually (and use a while loop to iterate over the results, not a for loop):
< <(locate "*.jar") while read -r i
do
if [ -d "$i" ] #mvn repos have dirs named as .jar, so skip...
then
continue
fi
if jar -tvf "$i" | grep -q -Hsi "$1.class"
then
echo "jar location: $i"
fi
done | tee -a findClassResutls.txt
the $? you're using there is on the tee command, which I bet pretty well always succeeds. You probably want Pipe output and capture exit status in Bash
I am trying to create a bash script where I would run jalopy (Java Code Formatter) on the files that are about to be committed to make sure that Code Formatting is done properly and otherwise reject the commit.
I have researched and have tried the following so far:
#!/bin/bash
AllVariables="$#"
checkingAnyArgs='/tmp/checkingAnyArgs'
echo >> ${checkingAnyArgs} ; echo >> ${checkingAnyArgs}
echo "\$AllVariables: ${AllVariables}" >> ${checkingAnyArgs}
echo "I see the commit now." >> ${checkingAnyArgs}
while read oldrev newrev ref
do
echo "STARTING [$oldrev $newrev $ref]" >> ${checkingAnyArgs}
echo "git diff-tree --full-index -a -r \$oldrev..\$newrev -- $(git diff-tree --full-index -a -r $oldrev..$newrev) " >> ${checkingAnyArgs}
for FILE in `git diff-tree -r $oldrev..$newrev | awk '{print $6}'`
do
echo "pwd: $(pwd)" >> ${checkingAnyArgs}
echo "git update-ref refs/blametree/$ref/$FILE $newrev $oldrev" >> ${checkingAnyArgs}
echo "ls -l $FILE: $(ls -l $FILE)" >> ${checkingAnyArgs}
if [[ $(grep 'changed' $FILE) ]] ; then
echo "$FILE ' contains changed!'" >> ${checkingAnyArgs}
exit 1
fi
#echo "git diff-tree --name-status -rz $ref $newrev : $(git diff-tree --name-status -rz $ref..$newrev)" >> ${checkingAnyArgs}
echo "jalopy.sh --convention http://svn1.cvs.ula.comcast.net/svn/cvs-common/trunk/tools/jalopy/jalopy-1.9.4.xml --profile default -r ${FILE} -d /root/test-jalopy1" >> ${checkingAnyArgs}
/opt/jalopy/bin/jalopy.sh --convention http://svn1.cvs.ula.comcast.net/svn/cvs-common/trunk/tools/jalopy/jalopy-1.9.4.xml --profile default ${FILE} -d /root/test-jalopy1 >> ${checkingAnyArgs} 2>&1
#git update-ref refs/blametree/$ref/$path $newrev >> ${checkingAnyArgs}
done
done
${checkingAnyArgs} output
$AllVariables:
I see the commit now.
STARTING [2f4ccbcc830ee5c464aeb34f0468dcda4782c507 6392fa90586a0b262fb6abde643a8d955e00d32b refs/heads/master]
git diff-tree --full-index -a -r $oldrev..$newrev -- :100644 100644 ee3198f98544cda7b2075ff25f92dab63a7afc0f e5695b1a44a821041016cae7fe3063effde7b977 M Test.java
pwd: /usr/local/stash/data/repositories/1
git update-ref refs/blametree/refs/heads/master/Test.java 6392fa90586a0b262fb6abde643a8d955e00d32b 2f4ccbcc830ee5c464aeb34f0468dcda4782c507
ls -l Test.java:
jalopy.sh --convention URL/jalopy-1.9.4.xml --profile default -r Test.java -d /root/test-jalopy1
Jalopy Source Code Formatter 1.9.4_79
Multi-User License (120 Users) Owner: TVWorks, Mill Valley, USA
Copyright (c) 2003-2010 TRIEMAX Software. All rights reserved.
[INFO] Detecting code convention format
[INFO] Jalopy code convention detected
[INFO] Importing settings into profile "default"
[INFO] Imported 742 keys into profile "default"
No files found for path or filter expression "Test.java"
So my question is why cant it find the 'Test.java' file? Any help here is appreciated. Or, how can i work with this file.
Thanks,
Murtaza
I'm new to Scala and don't know Java. I want to create a jar file out of a simple Scala file. So I have my HelloWorld.scala, generate a HelloWorld.jar.
Manifest.mf:
Main-Class: HelloWorld
In the console I run:
fsc HelloWorld.scala
jar -cvfm HelloWorld.jar Manifest.mf HelloWorld\$.class HelloWorld.class
java -jar HelloWorld.jar
=> "Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld/jar"
java -cp HelloWorld.jar HelloWorld
=> Exception in thread "main" java.lang.NoClassDefFoundError: scala/ScalaObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
at hoppity.main(HelloWorld.scala)
Sample directory structure:
X:\scala\bin
X:\scala\build.bat
X:\scala\MANIFEST.MF
X:\scala\src
X:\scala\src\foo
X:\scala\src\foo\HelloWorld.scala
HelloWorld.scala:
//file: foo/HelloWorld.scala
package foo {
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
}
MANIFEST.MF:
Main-Class: foo.HelloWorld
Class-Path: scala-library.jar
build.bat:
#ECHO OFF
IF EXIST hellow.jar DEL hellow.jar
IF NOT EXIST scala-library.jar COPY %SCALA_HOME%\lib\scala-library.jar .
CALL scalac -sourcepath src -d bin src\foo\HelloWorld.scala
CD bin
jar -cfm ..\hellow.jar ..\MANIFEST.MF *.*
CD ..
java -jar hellow.jar
In order to successfully use the -jar switch, you need two entries in the META-INF/MANIFEST.MF file: the main class; relative URLs to any dependencies. The documentation notes:
-jar
Execute a program encapsulated in a
JAR file. The first argument is the
name of a JAR file instead of a
startup class name. In order for this
option to work, the manifest of the
JAR file must contain a line of the
form Main-Class: classname. Here,
classname identifies the class having
the public static void main(String[]
args) method that serves as your
application's starting point. See the
Jar tool reference page and the Jar
trail of the Java Tutorial for
information about working with Jar
files and Jar-file manifests.
When you use this option, the JAR file
is the source of all user classes,
and other user class path settings are ignored.
java command line usage
manifest spec
(Notes: JAR files can be inspected with most ZIP applications; I probably neglect handling spaces in directory names in the batch script; Scala code runner version 2.7.4.final .)
For completeness, an equivalent bash script:
#!/bin/bash
if [ ! $SCALA_HOME ]
then
echo ERROR: set a SCALA_HOME environment variable
exit
fi
if [ ! -f scala-library.jar ]
then
cp $SCALA_HOME/lib/scala-library.jar .
fi
scalac -sourcepath src -d bin src/foo/HelloWorld.scala
cd bin
jar -cfm ../hellow.jar ../MANIFEST.MF *
cd ..
java -jar hellow.jar
Because Scala scripts require the Scala libraries to be installed, you will have to include the Scala runtime along with your JAR.
There are many strategies for doing this, such as jar jar, but ultimately the issue you're seeing is that the Java process you've started can't find the Scala JARs.
For a simple stand-alone script, I'd recommend using jar jar, otherwise you should start looking at a dependency management tool, or require users to install Scala in the JDK.
I ended up using sbt assembly, it is really simple to use. I added a file called assembly.sbt into the project/ directory at the root of the project with a one liner (Note your version might need to be changed).
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
Then just run the assembly task in sbt:
> assembly
Or just 'sbt assembly' in project root directory
$ sbt assembly
It will first run your tests and then it will generate the new jar into the target/ directory (given that my build.sbt already lists all my dependencies).
In my case, I just make that .jar file executable, rename to remove the extension and it is ready to ship!
Also, if you are doing a command line tool, don't forget to add a man page (I hate scripts without proper manpages or with multi-page plain text documentation that is not even piped into a pager for you).
You can also use maven and the maven-scala-plugin. Once you set up maven, you can just do mvn package and it will create your jar for you.
I tried to reproduce MyDowell's method. Finally I could make it work. However I find that the answer though correct a bit too complicated for a novice ( in particular the directory structure is unnecessarily complicated ).
I can reproduce this result with very simplistic means. To start with there is only one directory which contains three files:
helloworld.scala
MANIFEST.MF
scala-library.jar
helloworld.scala
object HelloWorld
{
def main(args: Array[String])
{
println("Hello, world!")
}
}
MANIFEST.MF:
Main-Class: HelloWorld
Class-Path: scala-library.jar
first compile helloworld.scala:
scalac helloworld.scala
then create the jar:
\progra~1\java\jdk18~1.0_4\bin\jar -cfm helloworld.jar MANIFEST.MF .
now you can run it with:
java -jar helloworld.jar
I found this simple solution because the original one did not work. Later I found out that not because it is wrong, but because of a trivial error: if I don't close the second line in MANIFEST.MF with a newline, then this line will be ignored. This took me an hour to find out and I tried all other things before, in the process finding this very simple solution.
I don't want to write why's and how's rather just show the solution which worked in my case (via Linux Ubuntu command line):
1)
mkdir scala-jar-example
cd scala-jar-example
2)
nano Hello.scala
object Hello extends App { println("Hello, world") }
3)
nano build.sbt
import AssemblyKeys._
assemblySettings
name := "MyProject"
version := "1.0"
scalaVersion := "2.11.0"
3)
mkdir project
cd project
nano plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.9.1")
4)
cd ../
sbt assembly
5)
java -jar target/target/scala-2.11/MyProject-assembly-1.0.jar
>> Hello, world
I modified the bash script adding some intelligence including auto-manifest generation.
This script assumes that the main object is named the same as the file it is in (case sensitive). Also, either the current directory name must equal to the main object name or the main object name should be provided as a command line parameter. Launch this script from the root directory of your project. Modify the variables at the top as required.
Be aware that the script will generate the bin and dist folders and will ERASE any existing contents in bin.
#!/bin/bash
SC_DIST_PATH=dist
SC_SRC_PATH=src
SC_BIN_PATH=bin
SC_INCLUDE_LIB_JAR=scala-library.jar
SC_MANIFEST_PATH=MANIFEST.MF
SC_STARTING_PATH=$(pwd)
if [[ ! $SCALA_HOME ]] ; then
echo "ERROR: set a SCALA_HOME environment variable"
exit 1
fi
if [[ ! -f $SCALA_HOME/lib/$SC_INCLUDE_LIB_JAR ]] ; then
echo "ERROR: Cannot find Scala Libraries!"
exit 1
fi
if [[ -z "$1" ]] ; then
SC_APP=$(basename $SC_STARTING_PATH)
else
SC_APP=$1
fi
[[ ! -d $SC_DIST_PATH ]] && mkdir $SC_DIST_PATH
if [[ ! -d $SC_BIN_PATH ]] ; then
mkdir "$SC_BIN_PATH"
else
rm -r "$SC_BIN_PATH"
if [[ -d $SC_BIN_PATH ]] ; then
echo "ERROR: Cannot remove temp compile directory: $SC_BIN_PATH"
exit 1
fi
mkdir "$SC_BIN_PATH"
fi
if [[ ! -d $SC_SRC_PATH ]] || [[ ! -d $SC_DIST_PATH ]] || [[ ! -d $SC_BIN_PATH ]] ; then
echo "ERROR: Directory not found!: $SC_SRC_PATH or $SC_DIST_PATH or $SC_BIN_PATH"
exit 1
fi
if [[ ! -f $SC_DIST_PATH/$SC_INCLUDE_LIB_JAR ]] ; then
cp "$SCALA_HOME/lib/$SC_INCLUDE_LIB_JAR" "$SC_DIST_PATH"
fi
SCALA_MAIN=$(find ./$SC_SRC_PATH -name "$SC_APP.scala")
COMPILE_STATUS=$?
SCALA_MAIN_COUNT=$(echo "$SCALA_MAIN" | wc -l)
if [[ $SCALA_MAIN_COUNT != "1" ]] || [[ ! $COMPILE_STATUS == 0 ]] ; then
echo "Main source file not found or too many exist!: $SC_APP.scala"
exit 1
fi
if [[ -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
rm "$SC_DIST_PATH/$SC_APP.jar"
if [[ -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
echo "Unable to remove existing distribution!: $SC_DIST_PATH/$SC_APP.jar"
exit 1
fi
fi
if [[ ! -f $SC_MANIFEST_PATH ]] ; then
LEN_BASE=$(echo $(( $(echo "./$SC_SRC_PATH" |wc -c) - 0 )))
SC_MAIN_CLASS=$(echo $SCALA_MAIN |cut --complement -c1-$LEN_BASE)
SC_MAIN_CLASS=${SC_MAIN_CLASS%%.*}
SC_MAIN_CLASS=$(echo $SC_MAIN_CLASS |awk '{gsub( "/", "'"."'"); print}')
echo $(echo "Main-Class: "$SC_MAIN_CLASS) > $SC_MANIFEST_PATH
echo $(echo "Class-Path: "$SC_INCLUDE_LIB_JAR) >> $SC_MANIFEST_PATH
fi
scalac -sourcepath $SC_SRC_PATH -d $SC_BIN_PATH $SCALA_MAIN
COMPILE_STATUS=$?
if [[ $COMPILE_STATUS != "0" ]] ; then
echo "Compile Failed!"
exit 1
fi
cd "$SC_BIN_PATH"
jar -cfm ../$SC_DIST_PATH/$SC_APP.jar ../$SC_MANIFEST_PATH *
COMPILE_STATUS=$?
cd "$SC_STARTING_PATH"
if [[ $COMPILE_STATUS != "0" ]] || [[ ! -f $SC_DIST_PATH/$SC_APP.jar ]] ; then
echo "JAR Build Failed!"
exit 1
fi
echo " "
echo "BUILD COMPLETE!... TO LAUNCH: java -jar $SC_DIST_PATH/$SC_APP.jar"
echo " "
One thing which may cause a similar problem (although it's not the problem in the initial question above) is that the Java vm seems to demand that the main method returns void. In Scala we can write something like (observe the =-sign in the definition of main):
object MainProgram {
def main(args: Array[String]) = {
new GUI(args)
}
}
where main actually returns a GUI-object (i.e. it's not void), but the program will run nicely when we start it using the scala command.
If we package this code into a jar-file, with MainProgram as the Main-Class, the Java vm will complain that there's no main function, since the return type of our main is not void (I find this complaint somewhat strange, since the return type is not part of the signature).
We would have no problems if we left out the =-sign in the header of main, or if we explicitly declared it as Unit.
If you do not wish to use sbt facilities I recommend the use of a makefile.
Here is an example where foo package is replaced by foo.bar.myApp for completeness.
makefile
NAME=HelloWorld
JARNAME=helloworld
PACKAGE=foo.bar.myApp
PATHPACK=$(subst .,/,$(PACKAGE))
.DUMMY: default
default: $(NAME)
.DUMMY: help
help:
#echo "make [$(NAME)]"
#echo "make [jar|runJar]"
#echo "make [clean|distClean|cleanAllJars|cleanScalaJar|cleanAppJar]"
.PRECIOUS: bin/$(PATHPACK)/%.class
bin/$(PATHPACK)/%.class: src/$(PATHPACK)/%.scala
scalac -sourcepath src -d bin $<
scala-library.jar:
cp $(SCALA_HOME)/lib/scala-library.jar .
.DUMMY: runjar
runJar: jar
java -jar $(JARNAME).jar
.DUMMY: jar
jar: $(JARNAME).jar
MANIFEST.MF:
#echo "Main-Class: $(PACKAGE).$(NAME)" > $#
#echo "Class-Path: scala-library.jar" >> $#
$(JARNAME).jar: scala-library.jar bin/$(PATHPACK)/$(NAME).class \
MANIFEST.MF
(cd bin && jar -cfm ../$(JARNAME).jar ../MANIFEST.MF *)
%: bin/$(PATHPACK)/%.class
scala -cp bin $(PACKAGE).$#
.DUMMY: clean
clean:
rm -R -f bin/* MANIFEST.MF
cleanAppJar:
rm -f $(JARNAME).jar
cleanScalaJar:
rm -f scala-library.jar
cleanAllJars: cleanAppJar cleanScalaJar
distClean cleanDist: clean cleanAllJars