⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classversionlimiter.java

📁 Java写的ERP系统
💻 JAVA
字号:
package org.compiere.tools;

import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.util.jar.*;

/**
 *  <b>JDK 1.4 Beta 2 won't work with JBuilder</b>
 *  <p>
 *  When compiling a ".java"-file the compiler puts format version info in the
 *  first bytes of the resulting class file. In Merlin (JDK 1.4)
 *  Beta2 Sun has changed the version info of many of the JDK's class files
 *  to '48.0' while previous JDKs used versions up to '46.0'.
 *  I do not know if there actually are any differences in the class file format.
 *  There are almost certainly some minor changes. Unfortunately the JDK 1.4 release
 *  notes fail to adress this incompatibility. If anyone knows some details please e-mail me.
 *  The JDK tools provided with the Beta release can all deal with version '48.0' class files.
 *  But if you use other tools (like the Borland compiler), they will probably refuse to load the JDK's class files.
 *  <p>
 *  <b>Patch the JDK 1.4 Beta 2 release</b>
 *  <p>
 *  To be able to play around with Merlin Beta 2 using JBuilder5, I wrote a little hack,
 *  that patches all jar files in the JDK to a version of max. '46.0'.
 *  I got my current project running without noticing any problems.
 *  <p>
 *  THIS IS A HACK. IT WILL ALMOST CERTAINLY BREAK SOME CODE. USE AT YOUR OWN RISK.
 *  If in any part of your application you get some strange errors,
 *  especially related to class loading, this patch may well be the reason.
 *  Please E-Mail me with details about where the problems occur.
 *  <p>
 *  If your JDK's root directory isn't "D:\jdk1.4b2"
 *  then edit the path in the code (one of the very first lines).
 *  Be sure to have write access to the JDK sub-directories.
 *  <p>
 *  Run the resulting class. It will patch all class files in all jar files
 *  in your JDK to have a version info of '46.0' at max.
 *  The original jar-files will get copied to .BAK-files.
 *  <p>
 *  java -cp %COMPIERE_HOME%/lib/CServer.jar org.compiere.tools.ClassVersionLimiter
 *
 *  @author Stephen Kelvin - with minor changes by Jorg Janke
 *  @see http://www.StephenKelvin.de/MerlinPatch/
 *  @version  $Id: ClassVersionLimiter.java,v 1.3 2001/11/14 02:49:29 jjanke Exp $
 */
public class ClassVersionLimiter
{
	/**
	 *  Run it
	 */
	public static void main(String[] args)
	{
		ClassVersionLimiter classVersionLimiter = new ClassVersionLimiter("D:/j2sdk1.4b3p", 46, 0);
	}   //  main

	/** Version Key             */
	private long _maxAllowedVersion;

	/** Log file                */
	private PrintWriter	m_out = null;


	/**
	 *  Constructor
	 */
	public ClassVersionLimiter(String rootDirectory, int mainVersion, int minorVersion)
	{
		_maxAllowedVersion = mainVersion * 65536 + minorVersion;

		//  Create Log file
		try
		{
			File logFile = new File(rootDirectory + File.separator + "patchJar.log");
			m_out = new PrintWriter(new FileOutputStream(logFile), true);	//	autoFlush
			System.out.println("Log=" + logFile.getAbsolutePath());
		}
		catch (Exception e)
		{
			System.err.println("Cannot write log");
			e.printStackTrace(System.err);
			System.exit(1);
		}

		//  Change jars
		File root = new File(rootDirectory);
		search(root);
	}   //  ClassVersionLimiter

	/**
	 *  Search all for all jars in a directory and recursively go through sub-directories
	 */
	private void search(File dir)
	{
		dir.listFiles (new FileFilter()
		{
			public boolean accept(File pathname)
			{
				if (pathname.getName().endsWith(".jar"))
					checkJar(pathname);
				if (pathname.isDirectory())
					search(pathname);
				return false;
			}
		});
	}   //  search

	/**
	 *  Check the Jar
	 */
	private void checkJar(File file)
	{
		byte[]   header         = new byte[8];
		long     maxVersion     = 0;
		boolean  foundClassFiles = false;
		try
		{
			JarFile jarFile = new JarFile(file);
			Enumeration entries = jarFile.entries();
			while (entries.hasMoreElements())
			{
				JarEntry entry = (JarEntry) entries.nextElement();
				if (entry.getName().endsWith(".class"))
				{
					foundClassFiles = true;
					InputStream stream = jarFile.getInputStream(entry);
					stream.read(header);
					int mainVersion = header[6] * 256 + header[7];
					int minorVersion = header[4] * 256 + header[5];
					long version = mainVersion * 65536 + minorVersion;
					if (version > maxVersion)
						maxVersion = version;
				}
			}
			jarFile.close();
			if (foundClassFiles && maxVersion > _maxAllowedVersion)
			{
				patchJar(file);
			}
		}
		catch (Exception e)
		{
			log ("checkJar", e);
		}
	}   //  checkJar

	/**
	 *  Patch the Jar
	 */
	private void patchJar(File file)
	{
		log ("Patching " + file, null);
		try
		{
			final int MAX_ENTRY_SIZE = 1024 * 1024;     //  1 MB
			byte[] classBytes = new byte[MAX_ENTRY_SIZE];
			File newFile = new File(file.getAbsolutePath() + ".NEW");

			CRC32             crc32          = new CRC32();
			JarFile           oldJarFile     = new JarFile(file);
			Manifest          manifest       = oldJarFile.getManifest();
			FileOutputStream  outputStream   = new FileOutputStream(newFile);
			JarOutputStream   jarOutput      = new JarOutputStream(outputStream, manifest);
			Enumeration       entries        = oldJarFile.entries();

			while (entries.hasMoreElements())
			{
				JarEntry oldEntry = (JarEntry) entries.nextElement();
				JarEntry newEntry = (JarEntry) oldEntry.clone();
				System.out.print(".");      //  indicate progress, don't log
				if (oldEntry.getName().equals("META-INF/MANIFEST.MF"))
					continue;

				//  copy into classBytes
				InputStream    in             = oldJarFile.getInputStream(oldEntry);
				int            totalLen       = 0;
				int            readLen        = 0;
				do
				{
					totalLen += readLen;
					readLen = in.read(classBytes, totalLen, MAX_ENTRY_SIZE - totalLen);
				} while(readLen > 0);
				if (totalLen == MAX_ENTRY_SIZE)
				{
					log ("ERROR= patchJAR: MAX_ENTRY_SIZE too small - " + MAX_ENTRY_SIZE, null);
					return;
				}

				if (totalLen > 0 && oldEntry.getName().endsWith(".class"))
				{
					int         mainVersion    = classBytes[6] * 256 + classBytes[7];
					int         minorVersion   = classBytes[4] * 256 + classBytes[5];
					long        version        = mainVersion * 65536 + minorVersion;
					//  we need to patch this class file
					if (version > _maxAllowedVersion)
					{
						log (" - " + oldEntry.getName(), null);
						mainVersion    = (int) _maxAllowedVersion / 65536;
						minorVersion   = (int) _maxAllowedVersion % 65536;
						classBytes[4]  = (byte) (minorVersion / 256);
						classBytes[5]  = (byte) (minorVersion % 256);
						classBytes[6]  = (byte) (mainVersion / 256);
						classBytes[7]  = (byte) (mainVersion % 256);

						crc32.reset();
						crc32.update(classBytes, 0, totalLen);
						newEntry.setCrc(crc32.getValue());
						// The compressed size can differ if the uncompressed data is changed. -1 means unknown.
						newEntry.setCompressedSize(-1);
					}
				}
				jarOutput.putNextEntry(newEntry);
				if (totalLen > 0)
					jarOutput.write(classBytes, 0, totalLen);
				jarOutput.closeEntry();
			}
			jarOutput.close();
			outputStream.close();
			oldJarFile.close();
			//  done with entries
			log ("", null);

			//
			File bakFile = new File(file.getAbsolutePath() + ".BAK");
			if (!file.renameTo(bakFile))
			{
				log ("ERROR= Cannot rename " + file + " to " + bakFile + ". EXITING.", null);
				System.exit(99);
			}
			if(!newFile.renameTo(file))
			{
				log ("ERROR= Cannot rename " + newFile + " to " + file + ". EXITING.", null);
				System.exit(99);
			}
		}
		catch (Exception e)
		{
			log ("patchJar", e);
		}
	}   // patchJar

	/**
	 *  Log entries in file
	 */
	private void log (String message, Exception e)
	{
		if (e == null)
		{
			System.out.println(message);
			m_out.println(message);
		}
		else
		{
			System.err.print("ERROR= ");
			System.err.println(message);
			e.printStackTrace(System.err);
			//
			m_out.print("ERROR= ");
			m_out.println(message);
			e.printStackTrace(m_out);
		}
	}   //  log

}   //  ClassVersionLimiter

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -