/**********************************************************************
* Copyright (c) 2005-2009 ant4eclipse project team.
*
* 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:
* Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich
**********************************************************************/
package org.ant4eclipse.lib.core.osgi;
import org.ant4eclipse.lib.core.Assure;
import org.ant4eclipse.lib.core.CoreExceptionCode;
import org.ant4eclipse.lib.core.exception.Ant4EclipseException;
import org.ant4eclipse.lib.core.logging.A4ELogging;
import org.ant4eclipse.lib.core.util.ManifestHelper;
import org.ant4eclipse.lib.core.util.ManifestHelper.ManifestHeaderElement;
import org.ant4eclipse.lib.core.util.Utilities;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
/**
* <p>
* Implements a {@link BundleLayoutResolver} for jared bundles.
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public class JaredBundleLayoutResolver implements BundleLayoutResolver {
/** the location */
private File _location;
/** the expansion directory */
private File _expansionDirectory;
/** the jar file */
private JarFile _jarFile;
/** the manifest */
private Manifest _manifest;
/**
* <p>
* Creates a new instance of type {@link JaredBundleLayoutResolver}.
* </p>
*
* @param location
* the location of the jar file
* @param expansionDirectory
* the expansion directory
*/
public JaredBundleLayoutResolver(File location, File expansionDirectory) {
Assure.isFile("location", location);
Assure.notNull("expansionDirectory", expansionDirectory);
this._location = location;
this._expansionDirectory = expansionDirectory;
try {
this._jarFile = new JarFile(this._location);
this._manifest = this._jarFile.getManifest();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* {@inheritDoc}
*/
public byte getType() {
return LIBRARY;
}
/**
* {@inheritDoc}
*/
public File getLocation() {
return this._location;
}
/**
* {@inheritDoc}
*/
public Manifest getManifest() {
return this._manifest;
}
/**
* {@inheritDoc}
*/
public File[] resolveBundleClasspathEntries() {
// expand if necessary
if (needExpansion()) {
return expand();
}
// return 'self'
return new File[] { this._location };
}
/**
* <p>
* Returns if the contained jar file has to be unwrapped or not.
* </p>
*
* @return <code>true</code> if the contained jar file has to be unwrapped, <code>false</code> otherwise.
*/
private boolean needExpansion() {
// get the bundle class path
String[] bundleClasspath = ManifestHelper.getBundleClasspath(this._manifest);
// check entries
for (int i = 0; i < bundleClasspath.length; i++) {
// avoid expanding for erroneous BundleClasspath-Entries
if (!".".equals(bundleClasspath[i]) && (this._jarFile.getEntry(bundleClasspath[i]) != null)) {
return true;
}
}
// no additional entries found -> no need for expansion
return false;
}
/**
* <p>
* Expands the jared bundle to the expansion directory and returns all files that belongs to the bundle class path.
* </p>
*
* @return all files that belongs to the bundle class path.
*/
private File[] expand() {
// compute destination
ManifestHeaderElement[] elements = ManifestHelper.getManifestHeaderElements(this._manifest,
ManifestHelper.BUNDLE_SYMBOLICNAME);
if (elements == null || elements.length == 0 || elements[0].getValues() == null
|| elements[0].getValues().length == 0) {
// TODO: NLS
throw new RuntimeException("Invalid header '" + ManifestHelper.BUNDLE_SYMBOLICNAME + "' in bundle '"
+ this._location + "'.");
}
String version = ManifestHelper.getManifestHeader(this._manifest, ManifestHelper.BUNDLE_VERSION);
File destination = new File(this._expansionDirectory, elements[0].getValues()[0] + "_" + version);
// unwrap jar file
try {
Utilities.expandJarFile(this._jarFile, destination);
} catch (Ant4EclipseException ex) {
if (ex.getExceptionCode() == CoreExceptionCode.IO_FAILURE) {
// log error
A4ELogging.error("Could not expand jar file '%s'. Reason: '%s'", this._location, ex.getMessage());
// return 'self'
return new File[] { this._location };
} else {
throw ex;
}
}
// prepare results
List<File> result = new LinkedList<File>();
// get bundle class path
String[] bundleClasspathEntries = ManifestHelper.getBundleClasspath(this._manifest);
// add class path entries to the result
for (String bundleClasspathEntrie : bundleClasspathEntries) {
// add 'self'
if (".".equals(bundleClasspathEntrie)) {
result.add(destination);
}
// add entry
else {
File classpathEntry = new File(destination, bundleClasspathEntrie);
if (classpathEntry.exists()) {
result.add(classpathEntry);
}
}
}
// return result
return result.toArray(new File[0]);
}
}