由于处理大量的jar包后,原来的jad就不能再用了,网上找了个JadGen.exe,也很好用,但是没有批量的功能。于是就自己写了个批量生成工具。
实现功能:
1.选择指定jar时,生成jad。
2.选择指定存放jar的文件夹,可批量生成该文件夹下的jar的jad文件。
3.支持生成在线安装jad。
另外,自己发现用exe4j打包生成的exe可以不启动程序,直接将jar或文件夹拖动到程序图标上就可生成jad(但有exe4j的一个宣传splash或Dialog)。但用jsmooth生成的exe却没有这个功能,相当疑惑。
代码如下:
package lab.sodino.jadgen; public class JadGenMain { public static void main(String[] args) { if (args == null || args.length == 0) { JadFrame frame = new JadFrame(); frame.setVisible(true); } else { JadGener.generateJad(args, null, true); } } }
package lab.sodino.jadgen; import java.awt.Container; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.filechooser.FileFilter; public class JadFrame extends JFrame { private static final long serialVersionUID = 1945096113868380635L; private static final int WIDTH_FRAME = 435; private static final int HEIGHT_FRAME = 150; private static final int WIDTH_URL_AREA = 330; private static final int WIDTH_TEXT_LABEL = 55; private JTextField urlTf; private JTextField srcTf; private JarFileFilter jarFileFilter = new JarFileFilter(); private JButton genBtn; public JadFrame() { setTitle(Constant.JADGEN_APP_NAME); setResizable(false); setSizeAndCentralizeMe(WIDTH_FRAME, HEIGHT_FRAME); // 点击窗口右上角的关闭按钮关闭窗口,退出程序 this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setLayout(new GridLayout(3, 1)); addSrcFolderCmp(); addExtraUrlCmp(); addGenerateButton(); } private void addExtraUrlCmp() { int width = 0; int height = 0; Container con = new Container(); con.setLayout(new FlowLayout(FlowLayout.LEFT)); width = WIDTH_TEXT_LABEL; height = 25; JLabel extraUrlLab = new JLabel(Constant.STR_BASE_URL); extraUrlLab.setPreferredSize(new Dimension(width, height)); extraUrlLab.setHorizontalAlignment(JLabel.LEFT); con.add(extraUrlLab); // JTextArea urlTa = new JTextArea(); // urlTa.setLineWrap(false); urlTf = new JTextField(); urlTf.setOpaque(false); height = 25; urlTf.setPreferredSize(new Dimension(WIDTH_URL_AREA, height)); con.add(urlTf); add(con); } private void addSrcFolderCmp() { int width = 0; int height = 0; Container con = new Container(); con.setLayout(new FlowLayout(FlowLayout.LEFT)); // srcFolderLabel JLabel srcFolderLab = new JLabel(Constant.STR_OPERATE_FOLDER); width = WIDTH_TEXT_LABEL; height = 25; srcFolderLab.setPreferredSize(new Dimension(width, height)); con.add(srcFolderLab); // folderTextField srcTf = new JTextField(); width = WIDTH_URL_AREA; height = 25; srcTf.setPreferredSize(new Dimension(width, height)); con.add(srcTf); srcTf.setOpaque(false); // file choose JButton fileChooserBtn = new JButton("..."); fileChooserBtn.setPreferredSize(new Dimension(20, height)); fileChooserBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fileChooserDialog = new JFileChooser( "My Documents"); fileChooserDialog.addChoosableFileFilter(jarFileFilter); fileChooserDialog .setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); int popdownType = fileChooserDialog .showOpenDialog(JadFrame.this); if (popdownType == JFileChooser.APPROVE_OPTION) { File file = fileChooserDialog.getSelectedFile(); srcTf.setText(file.getAbsolutePath()); genBtn.setEnabled(true); } } }); con.add(fileChooserBtn); // add to JFrame add(con); } private void addGenerateButton() { genBtn = new JButton(Constant.STR_GENERATE); genBtn.setEnabled(false); genBtn.setPreferredSize(new Dimension(60, 25)); genBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String extraUrl = urlTf.getText(); if (extraUrl == null) { extraUrl = ""; } if (extraUrl.length() == 0) { File[] runArgs = { new File(srcTf.getText()) }; JadGener.generateJad(runArgs, null, true); JOptionPane.showMessageDialog(JadFrame.this, Constant.STR_OPERATE_DONE); } else if (extraUrl != null && extraUrl.length() > 6) { extraUrl = extraUrl.trim(); String lowStr = extraUrl.toLowerCase(); if (lowStr.startsWith("http://") || lowStr.startsWith("https://")) { if (extraUrl.endsWith("/") == false) { extraUrl += "/"; } File[] runArgs = { new File(srcTf.getText()) }; JadGener.generateJad(runArgs, extraUrl, true); JOptionPane.showMessageDialog(JadFrame.this, Constant.STR_OPERATE_DONE); } else { // invalid JOptionPane.showMessageDialog(JadFrame.this, Constant.STR_HTTP_ERROR, null, JOptionPane.ERROR_MESSAGE); } } else { // invalid JOptionPane.showMessageDialog(JadFrame.this, Constant.STR_HTTP_ERROR, null, JOptionPane.ERROR_MESSAGE); } } }); Container con = new Container(); con.setLayout(new FlowLayout(FlowLayout.CENTER)); con.add(genBtn); add(con); } // 设置程序大小并定位程序在屏幕正中 private void setSizeAndCentralizeMe(int width, int height) { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); this.setSize(width, height); this.setLocation((screenSize.width - width) >> 1, (screenSize.height - height) >> 1); } private static class JarFileFilter extends FileFilter { public String getDescription() { return "Directory and Jar File"; } public boolean accept(File f) { boolean accept = false; if (f.isDirectory()) { accept = true; } else if (f.getName().endsWith(".jar")) { accept = true; } return accept; } } }
package lab.sodino.jadgen; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.Manifest; import lab.sodino.jar.ManifestUtil; public class JadGener { public static void generateJad(String[] args, String extraUrl, boolean subFile) { File[] files = new File[args.length]; for (int i = 0; i < args.length; i++) { files[i] = new File(args[i]); } generateJad(files, extraUrl, subFile); } public static void generateJad(File[] args, String extraUrl, boolean subFile) { if (extraUrl == null) { extraUrl = ""; } for (int i = 0; i < args.length; i++) { File argFile = args[i]; if (argFile.isDirectory() == true) { if (subFile) { File[] files = argFile.listFiles(); if (files == null) { files = new File[0]; } if (files.length == 0) { continue; } else { generateJad(files, extraUrl, false); } } } else { operateFile(argFile, extraUrl); } } } public static void operateFile(File oldJarFile, String extraUrl) { JarFile jarFile = null; // test is j2me jar if (oldJarFile.getName().endsWith(".jar") == false) { return; } else { // is a jar file,and then whether is a j2me jar. // do nothing } String absolutePath = oldJarFile.getAbsolutePath(); String jadPath = absolutePath.substring(0, absolutePath.length() - 1) + "d"; File jadFile = new File(jadPath); OutputStream os = null; try { if (jadFile.exists()) { jadFile.delete(); } jadFile.createNewFile(); os = new FileOutputStream(jadFile); String jarSize = String.valueOf(oldJarFile.length()); String jarUrl = extraUrl + oldJarFile.getName(); jarFile = new JarFile(oldJarFile); Manifest mani = null; try { mani = jarFile.getManifest(); } catch (IOException ie) { ie.printStackTrace(); // 非法的jar或jar已受损坏,直接略过不做提示亦删除jad文件。 jadFile.delete(); return; } if (mani == null) { String tempName = oldJarFile.getAbsolutePath(); jarFile.close(); FileInputStream fis = new FileInputStream(tempName); JarInputStream jis = new JarInputStream(fis); JarEntry entry = null; while ((entry = jis.getNextJarEntry()) != null) { if (entry.getName().equals("META-INF/MANIFEST.MF")) { System.out.println("get meta-inf"); byte[] data = new byte[128]; int read = -1; while ((read = jis.read(data)) != -1) { os.write(data, 0, read); } } } } else { ManifestUtil manifestUtil = new ManifestUtil(mani); byte[] maniData = manifestUtil.getAttributesInfoByte(); os.write(maniData); maniData = null; byte[] extraData = (ManifestUtil.M_MIDLET_JAR_SIZE + ": " + jarSize + "/r/n" + ManifestUtil.M_MIDLET_JAR_URL + ": " + jarUrl + "/r/n").getBytes("UTF-8"); os.write(extraData); extraData = null; } } catch (IOException ie) { ie.printStackTrace(); } finally { try { if (os != null) { os.close(); } if (jarFile != null) { jarFile.close(); } } catch (IOException ie) { ie.printStackTrace(); } } } }
package lab.sodino.jadgen; public class Constant { public static final String JADGEN_APP_NAME = "JADGen--Sodino"; public static final String STR_BASE_URL = "远程地址"; public static final String STR_OPERATE_FOLDER = "操作源"; public static final String STR_GENERATE = "运行"; public static final String STR_HTTP_ERROR = "远程地址错误!"; public static final String STR_OPERATE_DONE = "操作已完成!"; }
package lab.sodino.jar; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; import java.util.jar.Manifest; public class ManifestUtil { public static final String MANIFEST_FULL_NAME = "META-INF/MANIFEST.MF"; /** J2me.jar包中Manifest必须包含的Manifest元素,为1~7项。Jad中必须包含的为1~9项。 */ /** 1.MIDlet-Name */ public static final String M_MIDLET_NAME = "MIDlet-Name"; /** 2.Manifest-Version */ public static final String M_MANIFEST_VERSION = "Manifest-Version"; /** 3.MIDlet-Vendor */ public static final String M_MIDLET_VENDOR = "MIDlet-Vendor"; /** 4.MIDlet-Version */ public static final String M_MIDLET_VERSION = "MIDlet-Version"; /** 5.MicroEdition-Configuration */ public static final String M_MICROEDITION_CONFIGURATION = "MicroEdition-Configuration"; /** 6.MicroEdition-Profile */ public static final String M_MICROEDITION_PROFILE = "MicroEdition-Profile"; /** 7.MIDlet-1。必须得有"MIDlet-1",可以再有"MIDlet-2"或"MIDlet-3"等等。 */ public static final String M_MIDLET_1 = "MIDlet-1"; /** 8.Jar包大小,以byte为单位。 */ public static final String M_MIDLET_JAR_SIZE = "MIDlet-Jar-Size"; /** 9. 引导至jar的url地址,可以是绝对/相对地址。 */ public static final String M_MIDLET_JAR_URL = "MIDlet-Jar-URL"; /** Jar Attributes */ private Attributes attributes; public ManifestUtil(JarFile jarFile) { try { Manifest manifest = jarFile.getManifest(); attributes = manifest.getMainAttributes(); // Set<Object> keySet = attributes.keySet(); // Iterator iterator = keySet.iterator(); // int count = 0; // while (iterator.hasNext()) { // String key = iterator.next().toString(); // String value = attributes.getValue(key); // System.out.println((++count) + " : [key]" + key + " [value]" // + value); // } } catch (IOException ie) { ie.printStackTrace(); } } public boolean reset(String key, String value) { boolean reset = false; Attributes.Name keyName = new Attributes.Name(key); if (attributes.containsKey(keyName)) { attributes.put(keyName, value); reset = true; } return reset; } public void resetMidletName(String newName) { Attributes.Name midlet_1Name = new Attributes.Name(M_MIDLET_1); String str = attributes.getValue(midlet_1Name); int firstIdx = str.indexOf(","); str = newName + str.substring(firstIdx); attributes.put(midlet_1Name, str); } public String getMidletClassName() { String midletClassName = null; String midlet_1_content = attributes.getValue(M_MIDLET_1); int lastIdx = midlet_1_content.lastIndexOf(","); midletClassName = midlet_1_content.substring(lastIdx + 1); return midletClassName; } @SuppressWarnings("unchecked") public byte[] getAttributesInfoByte() { StringBuffer strBuffer = new StringBuffer(); Set keySet = attributes.keySet(); Iterator iterator = keySet.iterator(); while (iterator.hasNext()) { String key = iterator.next().toString(); // System.out.println("[ManifestUtil.getAttributesInfoByte()]key = " // + key); String value = attributes.getValue(key); // System.out.println("[ManifestUtil.getAttributesInfoByte()]value = " // + value); strBuffer.append(key + ": " + value + "/r/n"); } // System.out.println(strBuffer.toString()); byte[] data = null; try { data = strBuffer.toString().getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return data; } }