/**
* OpenAtlasForAndroid Project
* The MIT License (MIT) Copyright (OpenAtlasForAndroid) 2015 Bunny Blue,achellies
* <p>
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
* <p>
* The above copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
* <p>
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @author BunnyBlue
**/
package com.openatlas.framework;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Process;
import com.openatlas.framework.bundlestorage.BundleArchive;
import com.openatlas.log.Logger;
import com.openatlas.log.LoggerFactory;
import com.openatlas.log.OpenAtlasMonitor;
import com.openatlas.runtime.ClassNotFoundInterceptorCallback;
import com.openatlas.runtime.RuntimeVariables;
import com.openatlas.util.BundleLock;
import com.openatlas.util.FileUtils;
import com.openatlas.util.OpenAtlasFileLock;
import com.openatlas.util.OpenAtlasUtils;
import com.openatlas.util.StringUtils;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.service.startlevel.StartLevel;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
//import org.osgi.framework.ServiceReference;
public final class Framework {
private static final AdminPermission ADMIN_PERMISSION = new AdminPermission();
private static String BASEDIR = null;
private static String BUNDLE_LOCATION = null;
static int CLASSLOADER_BUFFER_SIZE = 0;
static boolean DEBUG_BUNDLES = true;
static boolean DEBUG_CLASSLOADING = true;
static boolean DEBUG_PACKAGES = true;
static boolean DEBUG_SERVICES = true;
static final String FRAMEWORK_VERSION = "1.0.0";
private static final String DOWN_GRADE_FILE = "down_grade_list";
static int LOG_LEVEL;
static String STORAGE_LOCATION;
@SuppressWarnings("unused")
private static boolean STRICT_STARTUP;
static List<BundleListener> bundleListeners = new ArrayList<BundleListener>();
static Map<String, Bundle> bundles = new ConcurrentHashMap<String, Bundle>();
private static ClassNotFoundInterceptorCallback classNotFoundCallback;
static List<FrameworkListener> frameworkListeners = new ArrayList<FrameworkListener>();
static boolean frameworkStartupShutdown = false;
static int initStartlevel = 1;
static final Logger log = LoggerFactory.getInstance("Framework");
static Properties properties;
static boolean restart = false;
static int startlevel = 0;
static List<BundleListener> syncBundleListeners = new ArrayList<BundleListener>();
static SystemBundle systemBundle;
static ClassLoader systemClassLoader;
static List<String> writeAheads = new ArrayList<String>();
private static final class SystemBundle implements Bundle, StartLevel {
private final Dictionary<String, String> props;
int state;
class ShutdownThread extends Thread {
final boolean restart;
ShutdownThread(boolean restart) {
this.restart = restart;
}
@Override
public void run() {
Framework.shutdown(this.restart);
}
}
class UpdateLevelThread extends Thread {
final int targetLevel;
UpdateLevelThread(int i) {
this.targetLevel = i;
}
@Override
public void run() {
List bundles = Framework.getBundles();
SystemBundle.this.setLevel((Bundle[]) bundles.toArray(new Bundle[bundles.size()]), this.targetLevel, false);
Framework.notifyFrameworkListeners(BundleEvent.UPDATED, Framework.systemBundle, null);
Framework.storeMetadata();
}
}
class RefreshBundlesThread extends Thread {
final Bundle[] bundleArray;
RefreshBundlesThread(Bundle[] bundleArr) {
this.bundleArray = bundleArr;
}
@Override
public void run() {
}
}
SystemBundle() {
this.props = new Hashtable<String, String>();
this.props.put(Constants.BUNDLE_NAME, Constants.SYSTEM_BUNDLE_LOCATION);
this.props.put(Constants.BUNDLE_VERSION, Framework.FRAMEWORK_VERSION);
this.props.put(Constants.BUNDLE_VENDOR, "OpenAtlas");
}
@Override
public long getBundleId() {
return 0;
}
@Override
public Dictionary<String, String> getHeaders() {
return this.props;
}
@Override
public String getLocation() {
return Constants.SYSTEM_BUNDLE_LOCATION;
}
// @Override
// public ServiceReference[] getRegisteredServices() {
// return null;
// }
@Override
public URL getResource(String name) {
return getClass().getResource(name);
}
// @Override
// public ServiceReference[] getServicesInUse() {
// return null;
// }
@Override
public int getState() {
return this.state;
}
@Override
public boolean hasPermission(Object permission) {
return true;
}
@Override
public void start() throws BundleException {
}
@Override
public void stop() throws BundleException {
shutdownThread(false);
}
@Override
public void uninstall() throws BundleException {
throw new BundleException("Cannot uninstall the System Bundle");
}
@Override
public void update() throws BundleException {
shutdownThread(true);
}
private void shutdownThread(boolean z) {
new ShutdownThread(z).start();
}
@Override
public void update(InputStream inputStream) throws BundleException {
shutdownThread(true);
}
@Override
public void update(File file) throws BundleException {
shutdownThread(true);
}
@Override
public int getBundleStartLevel(Bundle bundle) {
if (bundle == this) {
return 0;
}
BundleImpl bundleImpl = (BundleImpl) bundle;
if (bundleImpl.state != BundleEvent.INSTALLED) {
return bundleImpl.currentStartlevel;
}
throw new IllegalArgumentException("Bundle " + bundle + " has been uninstalled");
}
@Override
public int getInitialBundleStartLevel() {
return Framework.initStartlevel;
}
@Override
public int getStartLevel() {
return Framework.startlevel;
}
@Override
public boolean isBundlePersistentlyStarted(Bundle bundle) {
if (bundle == this) {
return true;
}
BundleImpl bundleImpl = (BundleImpl) bundle;
if (bundleImpl.state != BundleEvent.INSTALLED) {
return bundleImpl.persistently;
}
throw new IllegalArgumentException("Bundle " + bundle + " has been uninstalled");
}
@Override
public void setBundleStartLevel(Bundle bundle, int level) {
if (bundle == this) {
throw new IllegalArgumentException("Cannot set the start level for the system bundle.");
}
BundleImpl bundleImpl = (BundleImpl) bundle;
if (bundleImpl.state == BundleEvent.INSTALLED) {
throw new IllegalArgumentException("Bundle " + bundle + " has been uninstalled");
} else if (level <= 0) {
throw new IllegalArgumentException("Start level " + level + " is not Component valid level");
} else {
bundleImpl.currentStartlevel = level;
bundleImpl.updateMetadata();
if (level <= Framework.startlevel && bundle.getState() != BundleEvent.RESOLVED && bundleImpl.persistently) {
try {
bundleImpl.startBundle();
} catch (Throwable e) {
e.printStackTrace();
Framework.notifyFrameworkListeners(BundleEvent.STARTED, bundle, e);
}
} else if (level <= Framework.startlevel) {
} else {
if (bundle.getState() != BundleEvent.STOPPED || bundle.getState() != BundleEvent.STARTED) {
try {
bundleImpl.stopBundle();
} catch (Throwable e2) {
Framework.notifyFrameworkListeners(BundleEvent.STARTED, bundle, e2);
}
}
}
}
}
@Override
public void setInitialBundleStartLevel(int level) {
if (level <= 0) {
throw new IllegalArgumentException("Start level " + level + " is not Component valid level");
}
Framework.initStartlevel = level;
}
@Override
public void setStartLevel(int i) {
if (i <= 0) {
throw new IllegalArgumentException("Start level " + i + " is not Component valid level");
}
new UpdateLevelThread(i).start();
}
@SuppressLint({"UseSparseArrays"})
private void setLevel(Bundle[] bundles, int startlevel, boolean z) {
if (Framework.startlevel != startlevel) {
int iStartlevelHigh = startlevel > Framework.startlevel ? 1 : 0;
int levelDiff = iStartlevelHigh != 0 ? startlevel - Framework.startlevel : Framework.startlevel - startlevel;
Map hashMap = new HashMap(0);
for (Bundle mBundle:bundles){
if (mBundle != Framework.systemBundle && (z || ((BundleImpl)mBundle).persistently)) {
int mLevelDiff;
BundleImpl bundleImpl = (BundleImpl) mBundle;
if (iStartlevelHigh != 0) {
mLevelDiff = (bundleImpl.currentStartlevel - Framework.startlevel) - 1;
} else {
mLevelDiff = Framework.startlevel - bundleImpl.currentStartlevel;
}
if (mLevelDiff >= 0 && mLevelDiff < levelDiff) {
Framework.addValue(hashMap, Integer.valueOf(mLevelDiff), bundleImpl);
}
}
}
for (int j = 0; j < levelDiff; j++) {
if (iStartlevelHigh != 0) {
Framework.startlevel++;
} else {
Framework.startlevel--;
}
List list = (List) hashMap.get(Integer.valueOf(j));
if (list != null) {
BundleImpl[] bundleImplArr = (BundleImpl[]) list.toArray(new BundleImpl[list.size()]);
for (int i = 0; i < bundleImplArr.length; i++) {
if (iStartlevelHigh != 0) {
try {
System.out.println("STARTING " + bundleImplArr[i].location);
bundleImplArr[i].startBundle();
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace();
Framework.notifyFrameworkListeners(FrameworkEvent.ERROR, Framework.systemBundle, e);
}
} else if (bundleImplArr[i].getState() != 1) {
System.out.println("STOPPING " + bundleImplArr[i].location);
try {
bundleImplArr[(bundleImplArr.length - i) - 1].stopBundle();
} catch (BundleException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
Framework.startlevel = startlevel;
}
}
//@Override
public void refreshPackages(Bundle[] bundleArr) {
new RefreshBundlesThread(bundleArr).start();
}
@Override
public String toString() {
return "SystemBundle";
}
}
static BundleImpl installNewBundle(String location, File apkFile) throws BundleException {
BundleImpl bundleImpl;
File mBundleArchiveFile = null;
try {
BundleLock.WriteLock(location);
bundleImpl = (BundleImpl) Framework.getBundle(location);
if (bundleImpl != null) {
BundleLock.WriteUnLock(location);
} else {
mBundleArchiveFile = new File(STORAGE_LOCATION, location);
OpenAtlasFileLock.getInstance().LockExclusive(mBundleArchiveFile);
if (mBundleArchiveFile.exists()) {
bundleImpl = restoreFromExistedBundle(location, mBundleArchiveFile);
if (bundleImpl != null) {
BundleLock.WriteUnLock(location);
if (mBundleArchiveFile != null) {
OpenAtlasFileLock.getInstance().unLock(mBundleArchiveFile);
}
}
}
bundleImpl = new BundleImpl(mBundleArchiveFile, location, null, apkFile, true);
storeMetadata();
BundleLock.WriteUnLock(location);
if (mBundleArchiveFile != null) {
OpenAtlasFileLock.getInstance().unLock(mBundleArchiveFile);
}
}
} catch (Throwable e) {
e.printStackTrace();
BundleLock.WriteUnLock(location);
throw new BundleException(e.getMessage());
}
return bundleImpl;
}
static boolean restoreBundle(String[] packageNames) {
try {
for (String pkgName : packageNames) {
File archiveFile = new File(STORAGE_LOCATION, pkgName);
if (!archiveFile.exists() || !BundleArchive.downgradeRevision(archiveFile)) {
return false;
}
}
return true;
} catch (Exception e) {
return false;
}
}
static BundleImpl installNewBundle(String location, InputStream archiveInputStream) throws BundleException {
BundleImpl bundleImpl = null;
File mBundleArchiveFile = null;
try {
BundleLock.WriteLock(location);
bundleImpl = (BundleImpl) getBundle(location);
if (bundleImpl != null) {
BundleLock.WriteUnLock(location);
} else {
mBundleArchiveFile = new File(STORAGE_LOCATION, location);
OpenAtlasFileLock.getInstance().LockExclusive(mBundleArchiveFile);
if (mBundleArchiveFile.exists()) {
bundleImpl = restoreFromExistedBundle(location, mBundleArchiveFile);
if (bundleImpl != null) {
BundleLock.WriteUnLock(location);
if (location != null) {
OpenAtlasFileLock.getInstance().unLock(mBundleArchiveFile);
}
}
}
bundleImpl = new BundleImpl(mBundleArchiveFile, location, archiveInputStream, null, true);
storeMetadata();
BundleLock.WriteUnLock(location);
if (mBundleArchiveFile != null) {
OpenAtlasFileLock.getInstance().unLock(mBundleArchiveFile);
}
}
} catch (Throwable v0) {
BundleLock.WriteUnLock(location);
}
return bundleImpl;
}
private Framework() {
}
static void startup(Properties properties) throws BundleException {
if (properties == null) {
properties = new Properties();
}
Framework.properties = properties;
startup();
}
private static void startup() throws BundleException {
int startlevel;
frameworkStartupShutdown = true;
System.out.println("---------------------------------------------------------");
System.out.println(" OpenAtlas OSGi 1.0.0 Pre-Release on " + Build.MODEL + "/" + Build.CPU_ABI + "/"
+ VERSION.RELEASE +" SDK version "+Build.VERSION.SDK_INT+ " starting ...");
System.out.println("---------------------------------------------------------");
long currentTimeMillis = System.currentTimeMillis();
initialize();
Framework.launch();
boolean init = getProperty("osgi.init", false);
if (init) {
startlevel = -1;
} else {
startlevel = restoreProfile();
restart = true;
}
if (startlevel == -1) {
restart = false;
File file = new File(STORAGE_LOCATION);
if (init && file.exists()) {
System.out.println("Purging storage ...");
try {
deleteDirectory(file);
} catch (Throwable e) {
throw new RuntimeException("deleteDirectory failed", e);
}
}
try {
file.mkdirs();
Integer.getInteger("osgi.maxLevel", Integer.valueOf(1)).intValue();
initStartlevel = getProperty("osgi.startlevel.bundle", 1);
startlevel = getProperty("osgi.startlevel.framework", 1);
} catch (Throwable e) {
throw new RuntimeException("mkdirs failed", e);
}
}
notifyFrameworkListeners(FrameworkEvent.STARTING, systemBundle, null);
systemBundle.setLevel(getBundles().toArray(new Bundle[bundles.size()]), startlevel, false);
frameworkStartupShutdown = false;
if (!restart) {
try {
storeProfile();
} catch (Throwable e) {
throw new RuntimeException("storeProfile failed", e);
}
}
long currentTimeMillis2 = System.currentTimeMillis() - currentTimeMillis;
System.out.println("---------------------------------------------------------");
System.out.println(" Framework " + (restart ? "restarted" : "started") + " in " + currentTimeMillis2 + " milliseconds.");
System.out.println("---------------------------------------------------------");
System.out.flush();
systemBundle.state = BundleEvent.RESOLVED;
try {
notifyFrameworkListeners(FrameworkEvent.STARTED, systemBundle, null);
} catch (Throwable e) {
throw new RuntimeException("notifyFrameworkListeners failed", e);
}
}
public static ClassLoader getSystemClassLoader() {
return systemClassLoader;
}
public static List<Bundle> getBundles() {
List<Bundle> arrayList = new ArrayList<Bundle>(bundles.size());
synchronized (bundles) {
arrayList.addAll(bundles.values());
}
return arrayList;
}
public static Bundle getBundle(String location) {
return bundles.get(location);
}
public static Bundle getBundle(long j) {
return null;
}
static void shutdown(boolean restart) {
System.out.println("---------------------------------------------------------");
System.out.println(" OpenAtlas OSGi shutting down ...");
System.out.println(" Bye !");
System.out.println("---------------------------------------------------------");
systemBundle.state = BundleEvent.UNINSTALLED;
systemBundle.setLevel(getBundles().toArray(new Bundle[bundles.size()]), 0, true);
bundles.clear();
systemBundle.state = BundleEvent.INSTALLED;
if (restart) {
try {
startup();
} catch (Throwable th) {
th.printStackTrace();
}
}
}
public static void initialize() {
File filesDir = RuntimeVariables.androidApplication.getFilesDir();
if (filesDir == null || !filesDir.exists()) {
filesDir = RuntimeVariables.androidApplication.getFilesDir();
}
BASEDIR = properties.getProperty(OpenAtlasInternalConstant.OPENATLAS_BASEDIR, filesDir.getAbsolutePath());
BUNDLE_LOCATION = properties.getProperty(OpenAtlasInternalConstant.OPENATLAS_BUNDLE_LOCATION, "file:" + BASEDIR);
CLASSLOADER_BUFFER_SIZE = getProperty(OpenAtlasInternalConstant.OPENATLAS_CLASSLOADER_BUFFER_SIZE, 1024 * 10);
LOG_LEVEL = getProperty(OpenAtlasInternalConstant.OPENATLAS_LOG_LEVEL, 6);
DEBUG_BUNDLES = getProperty(OpenAtlasInternalConstant.OPENATLAS_DEBUG_BUNDLES, false);
DEBUG_PACKAGES = getProperty(OpenAtlasInternalConstant.OPENATLAS_DEBUG_PACKAGES, false);
DEBUG_SERVICES = getProperty(OpenAtlasInternalConstant.OPENATLAS_DEBUG_SERVICES, false);
DEBUG_CLASSLOADING = getProperty(OpenAtlasInternalConstant.OPENATLAS_DEBUG_CLASSLOADING, false);
if (getProperty(OpenAtlasInternalConstant.OPENATLAS_DEBUG, false)) {
System.out.println("SETTING ALL DEBUG FLAGS");
LOG_LEVEL = 3;
DEBUG_BUNDLES = true;
DEBUG_PACKAGES = true;
DEBUG_SERVICES = true;
DEBUG_CLASSLOADING = true;
}
STRICT_STARTUP = getProperty(OpenAtlasInternalConstant.OPENATLAS_STRICT_STARTUP, false);
String property = properties.getProperty("org.osgi.framework.system.packages");
if (property != null) {
StringTokenizer stringTokenizer = new StringTokenizer(property, ",");
int countTokens = stringTokenizer.countTokens();
for (int i = 0; i < countTokens; i++) {
BundleClassLoader.FRAMEWORK_PACKAGES.add(stringTokenizer.nextToken().trim());
}
}
properties.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, System.getProperty("java.specification.name") + "/" + System.getProperty("java.specification.version"));
String key = Constants.FRAMEWORK_OS_NAME;
property = System.getProperty("os.name");
if (property == null) {
property = "undefined";
}
properties.put(key, property);
key = Constants.FRAMEWORK_OS_VERSION;
property = System.getProperty("os.version");
if (property == null) {
property = "undefined";
}
properties.put(key, property);
key = Constants.FRAMEWORK_PROCESSOR;
property = System.getProperty("os.arch");
if (property == null) {
property = "undefined";
}
properties.put(key, property);
properties.put(Constants.FRAMEWORK_VERSION, FRAMEWORK_VERSION);
properties.put(Constants.FRAMEWORK_VENDOR, "OpenAtlas");
property = Locale.getDefault().getLanguage();
key = Constants.FRAMEWORK_LANGUAGE;
if (property == null) {
property = "en";
}
properties.put(key,property);
}
private static void launch() {
STORAGE_LOCATION = properties.getProperty(OpenAtlasInternalConstant.INSTALL_LOACTION, properties.getProperty("org.osgi.framework.dir", BASEDIR + File.separatorChar + "storage"))
+ File.separatorChar;
systemBundle = new SystemBundle();
systemBundle.state = BundleEvent.UPDATED;
}
public static boolean getProperty(String key, boolean defaultValue) {
if (properties == null) {
return defaultValue;
}
String value = (String) properties.get(key);
return value != null ? Boolean.valueOf(value).booleanValue() : defaultValue;
}
public static int getProperty(String key, int defaultValue) {
if (properties == null) {
return defaultValue;
}
String value = (String) properties.get(key);
return value != null ? Integer.parseInt(value) : defaultValue;
}
public static String getProperty(String key) {
if (properties == null) {
return null;
}
return (String) properties.get(key);
}
public static String getProperty(String key, String defaultValue) {
return properties == null ? defaultValue : (String) properties.get(key);
}
protected static void warning(String message) throws RuntimeException {
if (getProperty(OpenAtlasInternalConstant.OPENATLAS_STRICT_STARTUP, false)) {
throw new RuntimeException(message);
}
System.err.println("WARNING: " + message);
}
private static void storeProfile() {
BundleImpl[] bundleImplArr = getBundles().toArray(new BundleImpl[bundles.size()]);
for (BundleImpl updateMetadata : bundleImplArr) {
updateMetadata.updateMetadata();
}
storeMetadata();
}
static void storeMetadata() {
try {
File metaFile = new File(STORAGE_LOCATION, "meta");
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(metaFile));
dataOutputStream.writeInt(startlevel);
String join = StringUtils.join(writeAheads.toArray(), ",");
if (join == null) {
join = "";
}
dataOutputStream.writeUTF(join);
dataOutputStream.flush();
dataOutputStream.close();
} catch (IOException e) {
OpenAtlasMonitor.getInstance().trace(Integer.valueOf(OpenAtlasMonitor.WRITE_META_FAIL), "", "", "storeMetadata failed ", e);
log.error("Could not save meta data.", e);
}
}
private static int restoreProfile() {
try {
System.out.println("Restoring profile");
File meta = new File(STORAGE_LOCATION, "meta");
if (meta.exists()) {
DataInputStream dataInputStream = new DataInputStream(new FileInputStream(meta));
int readInt = dataInputStream.readInt();
String[] split = StringUtils.split(dataInputStream.readUTF(), ",");
if (split != null) {
writeAheads.addAll(Arrays.asList(split));
}
dataInputStream.close();
if (!getProperty(OpenAtlasInternalConstant.OPENATLAS_AUTO_LOAD, true)) {
return readInt;
}
File storageLocation = new File(STORAGE_LOCATION);
mergeWalsDir(new File(STORAGE_LOCATION, "wal"), storageLocation);
MergeWirteAheads(storageLocation);
File[] listFiles = storageLocation.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String str) {
return !str.matches("^[0-9]*");
}
});
int i = 0;
while (i < listFiles.length) {
if (listFiles[i].isDirectory() && new File(listFiles[i], "meta").exists()) {
try {
System.out.println("RESTORED BUNDLE " + new BundleImpl(listFiles[i]).location);
} catch (Exception e) {
log.error(e.getMessage(), e.getCause());
}
}
i++;
}
return readInt;
}
System.out.println("Profile not found, performing clean start ...");
return -1;
} catch (Exception e2) {
e2.printStackTrace();
return 0;
}
}
private static void mergeWalsDir(File walFile, File storageLocation) {
if (writeAheads != null && writeAheads.size() > 0) {
for (int i = 0; i < writeAheads.size(); i++) {
if (writeAheads.get(i) != null) {
File mHeadDir = new File(walFile, writeAheads.get(i));
if (mHeadDir != null) {
try {
if (mHeadDir.exists()) {
File[] mHeadFiles = mHeadDir.listFiles();
if (mHeadFiles != null) {
for (File mHeadFile : mHeadFiles) {
if (mHeadFile.isDirectory()) {
File targetFile = new File(storageLocation, mHeadFile.getName());
if (targetFile.exists()) {
File[] reversionList = mHeadFile.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String str) {
return str.startsWith(BundleArchive.REVISION_DIRECTORY);
}
});
if (reversionList != null) {
for (File mFile : reversionList) {
if (new File(mFile, "meta").exists()) {
mFile.renameTo(new File(targetFile, mFile.getName()));
}
}
}
} else {
mHeadFile.renameTo(targetFile);
}
}
}
}
}
} catch (Throwable e) {
log.error("Error while merge wal dir", e);
}
}
writeAheads.set(i, null);
}
}
}
if (walFile.exists()) {
walFile.delete();
}
}
public static void deleteDirectory(File mDirectory) {
File[] listFiles = mDirectory.listFiles();
for (int i = 0; i < listFiles.length; i++) {
if (listFiles[i].isDirectory()) {
deleteDirectory(listFiles[i]);
} else {
listFiles[i].delete();
}
}
mDirectory.delete();
}
static BundleImpl installNewBundle(String bundleName) throws BundleException {
try {
String location = bundleName.indexOf(":") > -1 ? bundleName : BUNDLE_LOCATION + File.separatorChar + bundleName;
return installNewBundle(location, new URL(location).openConnection().getInputStream());
} catch (Throwable e) {
throw new BundleException("Cannot retrieve bundle from " + bundleName, e);
}
}
private static BundleImpl restoreFromExistedBundle(String location, File file) {
try {
return new BundleImpl(file);
} catch (Throwable e) {
OpenAtlasMonitor.getInstance().trace(Integer.valueOf(-1), "", "", "restore bundle failed " + location + e);
log.error("restore bundle failed" + location, e);
return null;
}
}
static void installOrUpdate(String[] locations, File[] archiveFiles) throws BundleException {
if (locations == null || archiveFiles == null || locations.length != archiveFiles.length) {
throw new IllegalArgumentException("locations and files must not be null and must be same length");
}
String valueOf = String.valueOf(System.currentTimeMillis());
File file = new File(new File(STORAGE_LOCATION, "wal"), valueOf);
file.mkdirs();
int i = 0;
while (i < locations.length) {
if (!(locations[i] == null || archiveFiles[i] == null)) {
try {
BundleLock.WriteLock(locations[i]);
Bundle bundle = getBundle(locations[i]);
if (bundle != null) {
bundle.update(archiveFiles[i]);
} else {
BundleImpl bundleImpl = new BundleImpl(new File(file, locations[i]), locations[i], null, archiveFiles[i], false);
}
BundleLock.WriteUnLock(locations[i]);
} catch (Throwable th) {
BundleLock.WriteUnLock(locations[i]);
}
}
i++;
}
writeAheads.add(valueOf);
storeMetadata();
}
static void notifyBundleListeners(int event, Bundle bundle) {
if (!syncBundleListeners.isEmpty() || !bundleListeners.isEmpty()) {
BundleEvent bundleEvent = new BundleEvent(event, bundle);
BundleListener[] bundleListenerArr = syncBundleListeners.toArray(new BundleListener[syncBundleListeners.size()]);
for (BundleListener bundleChanged : bundleListenerArr) {
bundleChanged.bundleChanged(bundleEvent);
}
if (!bundleListeners.isEmpty()) {
bundleListenerArr = bundleListeners.toArray(new BundleListener[bundleListeners.size()]);
for (BundleListener bundleListener : bundleListenerArr) {
bundleListener.bundleChanged(bundleEvent);
}
}
}
}
static void addFrameworkListener(FrameworkListener frameworkListener) {
frameworkListeners.add(frameworkListener);
}
static void removeFrameworkListener(FrameworkListener frameworkListener) {
frameworkListeners.remove(frameworkListener);
}
private static void restoreBundles() throws IOException {
File file = new File(STORAGE_LOCATION, DOWN_GRADE_FILE);
for (String pkg : FileUtils.getStrings(file)) {
File locationFolder = new File(STORAGE_LOCATION, pkg);
if (locationFolder.exists()) {
String[] list = locationFolder.list();
String version = null;
if (list != null) {
for (String string : list) {
if (string.startsWith("version")
|| Long.parseLong(StringUtils.substringAfter(string, ".")) <= 0) {
version = string;
}
}
}
if (version == null) {
FileUtils.deleteFile(locationFolder.getAbsolutePath());
} else {
File tmp = new File(locationFolder, version);
if (tmp.exists()) {
FileUtils.deleteFile(tmp.getAbsolutePath());
}
}
}
}
if (file.exists()) {
FileUtils.deleteFile(file.getAbsolutePath());
}
}
private static void MergeWirteAheads(File storageLocation) {
try {
File wal = new File(STORAGE_LOCATION, "wal");
String curProcessName = OpenAtlasUtils.getProcessNameByPID(Process.myPid());
log.debug("restoreProfile in process " + curProcessName);
String packageName = RuntimeVariables.androidApplication.getPackageName();
if (curProcessName != null && packageName != null && curProcessName.equals(packageName)) {
mergeWalsDir(wal, storageLocation);
}
} catch (Throwable th) {
if (Build.MODEL == null || !Build.MODEL.equals("HTC 802w")) {
log.error(th.getMessage(), th.getCause());
return;
}
}
}
static void addBundleListener(BundleListener bundleListener) {
bundleListeners.add(bundleListener);
}
static void removeBundleListener(BundleListener bundleListener) {
bundleListeners.remove(bundleListener);
}
static void notifyFrameworkListeners(int event, Bundle bundle, Throwable th) {
if (!frameworkListeners.isEmpty()) {
FrameworkEvent frameworkEvent = new FrameworkEvent(event, bundle, th);
FrameworkListener[] frameworkListenerArr = frameworkListeners.toArray(new FrameworkListener[frameworkListeners.size()]);
for (FrameworkListener frameworkListener : frameworkListenerArr) {
frameworkListener.frameworkEvent(frameworkEvent);
}
}
}
static void clearBundleTrace(BundleImpl bundleImpl) {
if (bundleImpl.registeredFrameworkListeners != null) {
frameworkListeners.removeAll(bundleImpl.registeredFrameworkListeners);
bundleImpl.registeredFrameworkListeners = null;
}
if (bundleImpl.registeredBundleListeners != null) {
bundleListeners.removeAll(bundleImpl.registeredBundleListeners);
syncBundleListeners.removeAll(bundleImpl.registeredBundleListeners);
bundleImpl.registeredBundleListeners = null;
}
}
static void addValue(Map map, Object key, Object value) {
List list = (List) map.get(key);
if (list == null) {
list = new ArrayList();
}
list.add(value);
map.put(key, list);
}
static void removeValue(Map map, Object[] objArr, Object obj) {
for (int i = 0; i < objArr.length; i++) {
List list = (List) map.get(objArr[i]);
if (list != null) {
list.remove(obj);
if (list.isEmpty()) {
map.remove(objArr[i]);
} else {
map.put(objArr[i], list);
}
}
}
}
public static boolean isFrameworkStartupShutdown() {
return frameworkStartupShutdown;
}
public static ClassNotFoundInterceptorCallback getClassNotFoundCallback() {
return classNotFoundCallback;
}
public static void setClassNotFoundCallback(ClassNotFoundInterceptorCallback classNotFoundInterceptorCallback) {
classNotFoundCallback = classNotFoundInterceptorCallback;
}
}