/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.tools.internal.jarutils;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.eclipse.jubula.tools.internal.constants.StringConstants;
/**
* Tool-class for searching jar file's main class
* Simply call getMainClass(File file) to get a List
* of Main Classes in jar file.
*
* @author BREDEX GmbH
*
*/
public class MainClassLocator {
/** to prevent instantiation */
private MainClassLocator() {
// do nothing
}
/**
* External called static method to get MainClass
*
* @param file
* a jarfile
* @return List
* @throws IOException
* error
*/
public static List<String> getMainClass(File file) throws IOException {
MainClassLocator t = new MainClassLocator();
return t.getMainClassName(file);
}
/**
* tries to get mainclass from manifest file
*
* @param url a jar file
* @return List
* @throws IOException error
*/
private List<String> getMainClassName(File url) throws IOException {
URL u = new URL("jar", //$NON-NLS-1$
StringConstants.EMPTY, url.toURL()
+ "!/"); //$NON-NLS-1$
JarURLConnection uc = (JarURLConnection) u.openConnection();
Attributes attr = uc.getMainAttributes();
List<String> returnValue = new Vector<String>();
try {
if ((attr != null)
&& (attr.getValue(Attributes.Name.MAIN_CLASS) != null)) {
returnValue.add(attr.getValue(Attributes.Name.MAIN_CLASS));
return returnValue;
}
if (returnValue.isEmpty()) {
return getMainClassNameParse(url.toURL());
}
return returnValue;
} finally {
uc.getJarFile().close();
}
}
/**
* tries to locate main class in a jar file
*
* @param url a jar file
* @return List
* @throws IOException error
*/
private List<String> getMainClassNameParse(URL url) throws IOException {
MyClassLoader cl = new MyClassLoader(url);
List<String> main = cl.getMainMethod();
cl.close();
return main;
}
/**
* inserted class
* @author BREDEX GmbH
*
*/
private static class MyClassLoader extends ClassLoader {
/**
* JarResources
*/
private JarResources m_res;
/**
* a jar file
*/
private JarFile m_jar;
/**
* constructor of class
* @param fileName filename as string
* @throws IOException error
*/
MyClassLoader(URL fileName) throws IOException {
m_res = new JarResources(fileName.getFile());
m_jar = new JarFile(new File(fileName.getFile()));
}
/**
* finalizes the classloader
*
*/
public void close() {
try {
m_jar.close();
m_res = null;
m_jar = null;
} catch (Throwable e) { // NOPMD by al on 3/21/07 11:02 AM
// just cleanup
// since it's not clear where this class may be used (i.e.
// in a server context, no logging is done to avoid
// class loader problems
}
}
/**
* returns the Main Method of a class
* @return List
*/
public List<String> getMainMethod() {
List<String> returnValue = new Vector<String>();
Enumeration entries = m_jar.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
if ((!entry.isDirectory())
&& (entry.getName().endsWith(".class"))) { //$NON-NLS-1$
if (checkClass(entry.getName()) != null) { // NOPMD by al on 3/19/07 2:06 PM
returnValue.add(entry.
getName().replace('/',
'.')
.substring(
0,
entry.getName().
replace('/',
'.')
.lastIndexOf(
".class"))); //$NON-NLS-1$
}
}
}
return returnValue;
}
/**
* checks if a class is a main-class
* @param cNRaw classname
* @return String
* @throws ClassFormatError error
*/
private String checkClass(String cNRaw) throws ClassFormatError {
String cN = cNRaw;
cN = cN.replace('/', '.');
byte[] classBytes = m_res.getResource(cNRaw);
try {
Class c;
try {
c = findClass(cN);
} catch (ClassNotFoundException e) {
c = defineClass(
cN.substring(0,
cN.lastIndexOf(".class")), //$NON-NLS-1$
classBytes,
0, classBytes.length);
}
for (int i = 0; i < (c.getDeclaredMethods().length); i++) {
if (c.getDeclaredMethods()[i].
getName().equals("main")) { //$NON-NLS-1$
return cN;
}
}
} catch (NoClassDefFoundError e) { // NOPMD by al on 3/19/07 2:07 PM
//nothing
}
return null;
}
}
}