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

📄 packager.java

📁 配置文件
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * Copyright (c) 2003-2005 Craig Setera
 * All Rights Reserved.
 * Licensed under the Eclipse Public License - v 1.0
 * For more information see http://www.eclipse.org/legal/epl-v10.html
 */
package eclipseme.core.internal.packaging;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;

import eclipseme.core.IEclipseMECoreConstants;
import eclipseme.core.internal.EclipseMECorePlugin;
import eclipseme.core.internal.PreferenceAccessor;
import eclipseme.core.internal.preverifier.PreverificationUtils;
import eclipseme.core.internal.signing.SignatureUtils;
import eclipseme.core.internal.utils.ColonDelimitedProperties;
import eclipseme.core.internal.utils.EntryTrackingJarOutputStream;
import eclipseme.core.internal.utils.FilteringClasspathEntryVisitor;
import eclipseme.core.internal.utils.Utils;
import eclipseme.core.model.IJADConstants;
import eclipseme.core.model.IJadSignature;
import eclipseme.core.model.IMidletSuiteProject;
import eclipseme.core.model.IResourceFilter;
import eclipseme.core.model.Version;
import eclipseme.preverifier.results.PreverificationError;

/**
 * Helper class for creating deployed Midlet JAR files.
 * <p>
 * <b>Note:</b> This class/interface is part of an interim API that is still under development and expected to
 * change before reaching stability. It is being made available at this early stage to solicit feedback
 * from pioneering adopters on the understanding that any code that uses this API will almost 
 * certainly be broken as the API evolves.
 * </p>
 * Copyright (c) 2003-2005 Craig Setera<br>
 * All Rights Reserved.<br>
 * Licensed under the Eclipse Public License - v 1.0<p/>
 * <br>
 * $Revision: 1.5 $
 * <br>
 * $Date: 2006/11/17 01:09:32 $
 * <br>
 * @author Craig Setera
 */
public class Packager {
	
	/**
	 * Resource filter that always includes everything.
	 */
	private class IncludeAllResourceFilter implements IResourceFilter {
		/**
		 * @see eclipseme.core.model.impl.Packager.IResourceFilter#shouldTraverseContainer(org.eclipse.core.resources.IContainer)
		 */
		public boolean shouldTraverseContainer(IContainer container) {
			return true;
		}

		/**
		 * @see eclipseme.core.model.impl.Packager.IResourceFilter#shouldBeIncluded(org.eclipse.core.resources.IFile)
		 */
		public boolean shouldBeIncluded(IFile file) {
			return true;
		}
	}

	/**
	 * IClasspathEntryVisitor that does the work necessary to
	 * package up the information based on the classpath.
	 */
	private class PackagerClasspathEntryVisitor extends FilteringClasspathEntryVisitor {
		private EntryTrackingJarOutputStream jarStream;
		private boolean visitedSource;
		
		/** Constructor */
		private PackagerClasspathEntryVisitor(EntryTrackingJarOutputStream jarStream) {
			this.jarStream = jarStream;
			visitedSource = false;
		}
		
		/**
		 * @see eclipseme.core.internal.utils.IClasspathEntryVisitor#visitLibraryEntry(org.eclipse.jdt.core.IClasspathEntry, org.eclipse.jdt.core.IJavaProject, org.eclipse.core.runtime.IProgressMonitor)
		 */
		public void visitLibraryEntry(
			IClasspathEntry entry,
			IJavaProject javaProject, 
			IProgressMonitor monitor)
				throws CoreException 
		{
			File entryFile = Utils.getResolvedClasspathEntryFile(entry);
			if ((entryFile != null) && entryFile.isFile()) {
				IFolder libFolder = 
					midletSuite.getVerifiedLibrariesOutputFolder(monitor);
				IFile lib = libFolder.getFile(entry.getPath().lastSegment());
				if (lib.exists()) {
					try {
						copyLibContentsToJar(jarStream, lib, monitor);
					} catch (IOException e) {
						EclipseMECorePlugin.throwCoreException(IStatus.ERROR, -999, e);
					}
				}
			}
		}
		
		/**
		 * @see eclipseme.core.internal.utils.IClasspathEntryVisitor#visitSourceEntry(org.eclipse.jdt.core.IClasspathEntry, org.eclipse.jdt.core.IJavaProject, org.eclipse.core.runtime.IProgressMonitor)
		 */
		public void visitSourceEntry(
			IClasspathEntry entry,
			IJavaProject javaProject, 
			IProgressMonitor monitor)
				throws CoreException 
		{
			if (!visitedSource) {
				visitedSource = true;
				
				IFolder verifiedClasses = 
					midletSuite.getVerifiedClassesOutputFolder(monitor);
				try {
					addFilteredResourcesToJar(
						jarStream, 
						new IncludeAllResourceFilter(), 
						verifiedClasses.getFullPath(), 
						verifiedClasses,
						monitor);
				} catch (IOException e) {
					EclipseMECorePlugin.throwCoreException(IStatus.ERROR, -999, e);
				}
			}
		}

		/**
		 * Copy the contents of a library file to the jar output.
		 * 
		 * @param jarOutputStream
		 * @param lib
		 * @param monitor
		 * @throws CoreException 
		 */
		private void copyLibContentsToJar(
			EntryTrackingJarOutputStream jarOutputStream, 
			IFile lib, 
			IProgressMonitor monitor) 
				throws IOException, CoreException
		{
			File libFile = lib.getLocation().toFile();
			ZipInputStream zis = new ZipInputStream(new FileInputStream(libFile));
			
			ZipEntry zipEntry = null;
			do {
				zipEntry = zis.getNextEntry();
				if (zipEntry != null) {
					createJarEntry(jarOutputStream, zipEntry, zis);
				}
			} while (zipEntry != null);

			zis.close();
		}
	}

	/**
	 * 
	 * @uml.property name="midletSuite"
	 * @uml.associationEnd 
	 * @uml.property name="midletSuite" multiplicity="(1 1)"
	 */
	// The midlet suite being packaged
	private IMidletSuiteProject midletSuite;

	
	// Track whether to do obfuscation
	private boolean obfuscate;
	private boolean logObfuscation;
	
	/**
	 * Construct a new packager instance.
	 * 
	 * @param midletSuite
	 * @param obfuscate
	 */	
	public Packager(IMidletSuiteProject midletSuite, boolean obfuscate) {
		super();
		this.midletSuite = midletSuite;
		this.obfuscate = obfuscate;
		if (obfuscate) {
			String logObfuscationProperty =
				System.getProperty(IEclipseMECoreConstants.PROP_LOG_OBFUSCATION_STDOUT, "false");
			logObfuscation = logObfuscationProperty.equals("true");
		}
	}

	/**
	 * Build the deployed midlet suite package.
	 * 
	 * @param monitor
	 * @throws CoreException
	 * @throws IOException
	 */
	public void buildPackage(IProgressMonitor monitor) 
		throws CoreException, IOException 
	{
		// TODO Do we need to force a build first?
		// Delete the target jar file if it already exists...
		IFolder deploymentFolder = getDeploymentFolder(monitor);
		IFile finalJarFile = getJarFile(deploymentFolder, false);
		if (finalJarFile.exists()) finalJarFile.delete(true, monitor);

		// If the user wants auto versioning to occur, do it now
		boolean autoVersion = 
			PreferenceAccessor.instance.getAutoversionPackage(midletSuite.getProject());
		if (autoVersion) {
			updateJADVersion(monitor);
		}
		
		// Do the actual build
		File deployedJar = createDeployedJarFile(deploymentFolder, monitor);
		copyAndUpdateJadFile(deploymentFolder, deployedJar, monitor);
		
		// Mark the deployed project as up to date
		midletSuite.setDeployedJarFileUpToDate(true);
		
		// Let Eclipse know about changes and mark
		// everything as derived.
		deploymentFolder.refreshLocal(IResource.DEPTH_ONE, monitor);
		EclipseMECorePlugin.setResourcesAsDerived(deploymentFolder);
	}

	/**
	 * Add the contents of the verified classpath to the jar.
	 * 
	 * @param jarOutputStream
	 * @param monitor
	 */
	private void addVerifiedClasspathContentsToJar(
		EntryTrackingJarOutputStream jarOutputStream, 
		IProgressMonitor monitor) 
			throws CoreException, IOException
	{
		IJavaProject javaProject = midletSuite.getJavaProject();
		PackagerClasspathEntryVisitor visitor =
			new PackagerClasspathEntryVisitor(jarOutputStream);
		visitor.getRunner().run(javaProject, visitor, monitor);
	}

	/**
	 * Add the specified file contents to the jar file.
	 * 
	 * @param jarOutputStream
	 * @param string
	 * @param file
	 * @throws IOException
	 */
	private void addFileToJar(
		EntryTrackingJarOutputStream jarOutputStream, 
		String entryName, 
		File file) 
			throws IOException
	{
		// Create the ZipEntry to represent the file
		ZipEntry entry = new ZipEntry(entryName);
		entry.setSize(file.length());
		entry.setTime(file.lastModified());
		createJarEntry(jarOutputStream, entry, new FileInputStream(file));
	}

	/**
	 * 
	 * Add the specified resources to the JAR file.
	 * 
	 * @param jarOutputStream
	 * @param rootPath
	 * @param resource
	 * @param monitor
	 * @throws IOException
	 * @throws CoreException 
	 */
	private void addResourceToJar(
		EntryTrackingJarOutputStream jarOutputStream, 
		IPath rootPath, 
		IResource resource,
		IProgressMonitor monitor) 
			throws IOException, CoreException
	{
		// Figure the path of the JAR file entry
		IPath resourcePath = resource.getFullPath();
		int commonSegments = resourcePath.matchingFirstSegments(rootPath);
		IPath entryPath = resourcePath.removeFirstSegments(commonSegments);
		
		// Add the new entry
		File file = resource.getLocation().toFile(); 
		addFileToJar(jarOutputStream, entryPath.toString(), file);
	}

	/**
	 * Add the resources to the output jar stream after filtering based on the
	 * specified resource filter.
	 * 
	 * @param jarOutputStream
	 * @param resourceFilter
	 * @param rootPath
	 * @param container
	 * @throws CoreException
	 * @throws IOException
	 */
	private void addFilteredResourcesToJar(
		EntryTrackingJarOutputStream jarOutputStream,
		IResourceFilter resourceFilter,
		IPath rootPath,
		IContainer container,
		IProgressMonitor monitor)
			throws CoreException, IOException
	{
		IResource[] members = container.members();
		for (int i = 0; i < members.length; i++) {
			IResource resource = members[i];
			if (resource instanceof IContainer) {
				IContainer cont = (IContainer) resource;
				if (resourceFilter.shouldTraverseContainer(cont)) {
					addFilteredResourcesToJar(jarOutputStream, resourceFilter, rootPath, cont, monitor);
				}
			} else if (resource.getType() == IResource.FILE) {
				if (resourceFilter.shouldBeIncluded((IFile) resource)) {
					addResourceToJar(jarOutputStream, rootPath, resource, monitor);
				}
			}
		}
	}
		
	/**
	 * Copy the source jad file and update the contents.
	 * 
	 * @param deploymentFolder
	 * @param deployedJarFile
	 * @throws IOException
	 * @throws CoreException
	 */
	private void copyAndUpdateJadFile(
		IFolder deploymentFolder, 
		File deployedJarFile,
		IProgressMonitor monitor) 
			throws IOException, CoreException 
	{
		// Read the source jad file and update the jar file
		// length property.
		ColonDelimitedProperties jadProperties = getSourceJADProperties();
		
		// Update the size of the jar file
		jadProperties.setProperty(
			IJADConstants.JAD_MIDLET_JAR_SIZE,
			(new Long(deployedJarFile.length())).toString());
		
		// write the JAD file in case signing blows up - at least we'll have
		// something non-bogus.
		
		writeJad(deploymentFolder, jadProperties, monitor);
		
		// Retrieve the signature object for this project.  This will be null
		// if we're not supposed to sign this project.
		
		IJadSignature signatureObject = SignatureUtils.getSignatureObject(midletSuite);
		if (signatureObject != null)
		{
			signJad(signatureObject, deployedJarFile, jadProperties);
			writeJad(deploymentFolder, jadProperties, monitor);
		}
	}
	
	/**
	 * Sign the JAR file associated with the project and add the signature
	 * properties to the JAD file.
	 * 
	 * @param signatureObject	IJadSignature object that will do the actual signing
	 * @param deployedJarFile	File referencing the JAR file to be signed
	 * @param jadProperties		Contents of the JAD file to be added to
	 * 
	 * @throws CoreException
	 */
	private void signJad(IJadSignature signatureObject, File deployedJarFile, ColonDelimitedProperties jadProperties)
		throws CoreException
	{
		signatureObject.computeSignature(deployedJarFile);
		
		jadProperties.setProperty(IJADConstants.JAD_MIDLET_JAR_RSA_SHA1,
									signatureObject.getJarSignatureString());
		
		String[] certificates = signatureObject.getCertificateStrings();
		for (int i = 1; i <= certificates.length; i++)
		{
			jadProperties.setProperty(IJADConstants.JAD_MIDLET_CERTIFICATE + i,
					certificates[i-1]);
		}
	}

	/**
	 * Create the deployed JAR file.
	 * @param deployedJarFile
	 * 
	 * @throws IOException
	 */
	private File createDeployedJarFile(
		IFolder deploymentFolder, 
		IProgressMonitor monitor)
			throws CoreException, IOException 
	{
		// The jar file
		IFile jarIFile = getJarFile(deploymentFolder, obfuscate);
		File jarFile = resourceToFile(jarIFile, monitor);

		// Get the JAR file manifest ready to go.
		Properties manifestProperties = getJadSourceManifest();
		filterManifestAttributes(manifestProperties);

		Manifest jarManifest = new Manifest();
		Attributes mainAttributes = jarManifest.getMainAttributes();
		mainAttributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
		
		Iterator iterator = manifestProperties.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry entry = (Map.Entry) iterator.next();
			try {
				mainAttributes.putValue(
						(String) entry.getKey(), 
						(String) entry.getValue());
			} catch (IllegalArgumentException e) {

⌨️ 快捷键说明

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