Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/***************************************************************************/
/* */
/* ADOBE CONFIDENTIAL */
/* _ _ _ _ _ _ _ _ _ _ */
/* */
/* Copyright 2011, Adobe Systems Incorporated */
/* All Rights Reserved. */
/* */
/* NOTICE: All information contained herein is, and remains the property */
/* of Adobe Systems Incorporated and its suppliers, if any. The */
/* intellectual and technical concepts contained herein are proprietary */
/* to Adobe Systems Incorporated and its suppliers and may be covered by */
/* U.S. and Foreign Patents, patents in process, and are protected by */
/* trade secret or copyright law. Dissemination of this information or */
/* reproduction of this material is strictly forbidden unless prior */
/* written permission is obtained from Adobe Systems Incorporated. */
/* */
/***************************************************************************/
package com.adobe.octopus.extract;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.Version;
import org.osgi.service.packageadmin.PackageAdmin;
/**
* @author tnaroska
* @version $Revision$
* @since 1.0
*/
public final class BundleExtractor
{
// --------------------------------------------------------------------------- Private Constants
/** Root folder used for extracted resources in the bundle data store */
private static final String ROOT = ".octopus";
/** file that stores version information about this extractor's bundle and any of its
* attached fragments */
private static final String VERSION_FILE = ROOT + "/nativeCommExtractedVersions";
// --------------------------------------------------------------------------- Private Variables
/** Target bundle to operate on */
private final Bundle bundle;
/** Target bundle context to operate on */
private final File baseDir;
// -------------------------------------------------------------------------- Public Constructor
/**
* Creates a BundleExtractor instance for the specified bundle.
*
* @param bundle - target bundle of this instance
*/
public BundleExtractor(Bundle bundle)
{
if (bundle == null)
{
throw new IllegalArgumentException("bundle == null");
}
this.bundle = bundle;
BundleContext context = getBundleContext();
baseDir = context.getDataFile(ROOT);
if (baseDir == null)
{
throw new IllegalArgumentException("the OSGi platform has no file system support");
}
baseDir.mkdir();
// Needed to retrieve fragment information
PackageAdmin packageAdmin = (PackageAdmin)context.getService(context.getServiceReference(PackageAdmin.class.getName()));
// Check if the versions have changed
try
{
if( resourcesNeedUpdate(packageAdmin) )
{
//If they have, delete any content of the working directory
deleteDirectory( baseDir );
baseDir.mkdir();
//Create a new version file
updateVersionFile(packageAdmin);
}
}
catch (IOException e)
{
throw new IllegalStateException( e );
}
}
/**
* Creates a BundleExtractor instance for the parent bundle of the specified class.
*
* @param clazz - a class object of the target bundle
*/
public BundleExtractor(Class clazz)
{
this(FrameworkUtil.getBundle(clazz));
}
// ------------------------------------------------------------------------------ Public Methods
/**
* Extracts a resource from the target bundle to the file system. If path denotes a folder
* all contents of the folder is extracted recursively.
*
* @param path - path to the bundle resource (always relative to the bundle root)
* @return file object pointing to the extracted file/folder
* @throws IOException - if path cannot be found in the bundle or extraction fails
*/
public File extractResource(String path) throws IOException
{
File resolvedFile = getEntry(path);
return resolvedFile;
}
/**
* Extract the specified file from this bundle and mark it as executable (Linux only).
*
* @param path - path to the executable bundle resource (always relative to the bundle root)
* @return file object pointing to the extracted executable file
* @throws IOException - if path cannot be found in the bundle or extraction fails
*/
public File extractExecutable(String path) throws IOException
{
File resolvedFile = getEntry(path);
// chmod +x on unix-like systems
if (File.separatorChar == '/')
{
markExecutable(path, resolvedFile);
}
return resolvedFile;
}
// ----------------------------------------------------------------------------- Private Methods
/**
* Recursively delete a directory
* @param path directory to delete
* @return see File.delete()
*/
private boolean deleteDirectory(File path)
{
File[] files = path.listFiles();
for(int i=0; i 1 )
{
resourcesNeedUpdate = true;
}
}
finally
{
is.close();
}
} // If the version file does not exist, it means an update is needed
return resourcesNeedUpdate;
}
/**
* Updates/creates the version file with the ID and version info from the
* extractor's bundle and any attached fragment bundles.
* It will create the file if it does not exist
* @throws IOException
*/
private void updateVersionFile(PackageAdmin packageAdmin) throws IOException
{
Properties prop = new Properties();
// store host bundle id and version
prop.setProperty( String.valueOf( bundle.getBundleId() ), bundle.getVersion().toString() );
// store fragments info, if any
if( packageAdmin != null )
{
Bundle[] fragments = packageAdmin.getFragments( bundle );
if(fragments != null)
{
for( Bundle fragment : fragments )
{
prop.setProperty( String.valueOf( fragment.getBundleId() ), fragment.getVersion().toString() );
}
}
}
BundleContext context = getBundleContext();
File versionFile = context.getDataFile( VERSION_FILE );
OutputStream os = new FileOutputStream( versionFile );
try
{
prop.store(os, null);
}
finally
{
os.close();
}
}
/**
* Get the current BundleContext
* @return the bundle's current context
*/
private BundleContext getBundleContext()
{
BundleContext context = bundle.getBundleContext();
if (context == null)
{
startBundle();
context = bundle.getBundleContext();
if (context == null)
{
throw new IllegalArgumentException("bundle '" + bundle +"' has no BundleContext." +
"Either it is not active or a fragment bundle.");
}
}
return context;
}
/**
* Find the specified path in the target bundle and resolve it to a java.io.File, unpacking
* bundle contents if necessary.
*
* @param path - bundle resource path (always relative to the bundle root)
* @return File object pointing to the extracted file.
* @throws IOException - if resource not found or cannot be resolved
*/
private File getEntry(String path) throws IOException
{
// first try recursive extraction
Enumeration entries = bundle.findEntries(path, null, true);
if (entries != null)
{
while (entries.hasMoreElements())
{
URL url = (URL) entries.nextElement();
String entryPath = url.getPath();
File target = new File(baseDir, entryPath);
if (!entryPath.endsWith("/"))
{
copyOut(url, target);
}
else
{
target.mkdirs();
}
}
File result = new File(baseDir, path);
return result;
}
else
{
// fall back to single file extraction
URL rootUrl = bundle.getResource(path);
if (rootUrl == null)
{
throw new FileNotFoundException("'" + path + "' not found in Bundle " + bundle);
}
String rootPath = rootUrl.getPath();
File result = new File(baseDir, rootPath);
copyOut(rootUrl, result);
return result;
}
}
/**
* Copy out a bundle resource to the specified target location.
* If the resource already exists at the location it is not copied again.
* @param url - bundler resource URL
* @param target - target file location
* @throws IOException on error
*/
private void copyOut(final URL url, File target) throws IOException
{
if( ! target.exists() )
{
target.getParentFile().mkdirs();
InputStream in = url.openStream();
OutputStream out = new FileOutputStream(target);
copy(in, out);
}
}
/**
* Copy inputstream to outputstream.
* @param is - source
* @param os - destination
* @return bytes copied
* @throws IOException on error
*/
private static long copy(InputStream is, OutputStream os) throws IOException
{
long total = 0;
try
{
int read = 0;
byte[] bytes = new byte[64 * 1024];
while ((read = is.read(bytes)) != -1)
{
os.write(bytes, 0, read);
total += read;
}
}
finally
{
safeClose(is);
safeClose(os);
}
return total;
}
/**
* Mark the specified file as executable using Java File class.
* @param path - bundle resource path
* @param resolvedFile - actual file to modify
*/
private void markExecutable(String path, File resolvedFile) throws IOException
{
try
{
if (!resolvedFile.setExecutable(true, true))
{
throw new IOException("Failed to mark '" + path + "' of Bundle '" + bundle +
"' as executable. (" + resolvedFile.getAbsolutePath() + ")");
}
}
catch (NoSuchMethodError e)
{
// fallback to java 1.5 implementation
markExecutable15(path, resolvedFile);
}
}
/**
* Mark the specified file as executable spawning a chmod process.
* @param path - bundle resource path
* @param resolvedFile - actual file to modify
*/
private void markExecutable15(String path, File resolvedFile) throws IOException
{
try
{
Process p = Runtime.getRuntime().exec(new String[] {
"chmod",
"+x",
resolvedFile.getAbsolutePath()
});
int pe = p.waitFor();
if (pe != 0)
{
throw new IOException(String.format("chmod +x \"%s\" returned %i",
resolvedFile.getAbsolutePath(), pe));
}
}
catch (Exception ioe)
{
throw new IOException("Failed to mark '" + path + "' of Bundle '" + bundle +
"' as executable. (" + resolvedFile.getAbsolutePath() + ")", ioe);
}
}
private static void safeClose(Closeable c)
{
try
{
c.close();
}
catch (IOException e)
{
;
}
}
/**
* Try to start the target bundle if it is not already active.
*/
private void startBundle()
{
try
{
if (bundle.getState() != Bundle.ACTIVE)
{
bundle.start(Bundle.START_TRANSIENT);
}
}
catch (BundleException be)
{
throw new IllegalArgumentException("failed to start bundle '" + bundle +"'", be);
}
}
}