📄 packager.java
字号:
/**
* 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 + -