package android.taobao.atlas.framework;

import android.taobao.atlas.framework.bundlestorage.Archive;
import android.taobao.atlas.framework.bundlestorage.BundleArchive;
import android.taobao.atlas.log.Logger;
import android.taobao.atlas.log.LoggerFactory;
import android.taobao.atlas.util.AtlasFileLock;
import android.taobao.atlas.util.StringUtils;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;

public final class BundleImpl implements Bundle {
    static final Logger log;
    Archive archive;
    final File bundleDir;
    BundleClassLoader classloader;
    private final BundleContextImpl context;
    int currentStartlevel;
    ProtectionDomain domain;
    Hashtable<String, String> headers;
    final String location;
    boolean persistently;
    List<BundleListener> registeredBundleListeners;
    List<FrameworkListener> registeredFrameworkListeners;
    List<ServiceListener> registeredServiceListeners;
    List<ServiceReference> registeredServices;
    Package[] staleExportedPackages;
    int state;

    static {
        log = LoggerFactory.getInstance("BundleImpl");
    }

    BundleImpl(File file, String str, BundleContextImpl bundleContextImpl, InputStream inputStream, File file2, boolean z) throws BundleException {
        this.persistently = false;
        this.domain = null;
        this.registeredServices = null;
        this.registeredFrameworkListeners = null;
        this.registeredBundleListeners = null;
        this.registeredServiceListeners = null;
        this.staleExportedPackages = null;
        long currentTimeMillis = System.currentTimeMillis();
        this.location = str;
        bundleContextImpl.bundle = this;
        this.context = bundleContextImpl;
        this.currentStartlevel = Framework.initStartlevel;
        this.bundleDir = file;
        if (inputStream != null) {
            try {
                this.archive = new BundleArchive(str, file, inputStream);
            } catch (Throwable e) {
                Framework.deleteDirectory(file);
                throw new BundleException("Could not install bundle " + str, e);
            }
        } else if (file2 != null) {
            this.archive = new BundleArchive(str, file, file2);
        }
        this.state = 2;
        Framework.notifyBundleListeners(1, this);
        updateMetadata();
        if (z) {
            Framework.bundles.put(str, this);
            resolveBundle(false);
        }
        if (Framework.DEBUG_BUNDLES && log.isInfoEnabled()) {
            log.info("Framework: Bundle " + toString() + " created. " + (System.currentTimeMillis() - currentTimeMillis) + " ms");
        }
    }

    BundleImpl(File file, BundleContextImpl bundleContextImpl) throws Exception {
        this.persistently = false;
        this.domain = null;
        this.registeredServices = null;
        this.registeredFrameworkListeners = null;
        this.registeredBundleListeners = null;
        this.registeredServiceListeners = null;
        this.staleExportedPackages = null;
        long currentTimeMillis = System.currentTimeMillis();
        File file2 = new File(file, "meta");
        if (AtlasFileLock.getInstance().LockExclusive(file2)) {
            DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file2));
            this.location = dataInputStream.readUTF();
            this.currentStartlevel = dataInputStream.readInt();
            this.state = 2;
            this.persistently = dataInputStream.readBoolean();
            dataInputStream.close();
            AtlasFileLock.getInstance().unLock(file2);
            bundleContextImpl.bundle = this;
            this.context = bundleContextImpl;
            this.bundleDir = file;
            try {
                this.archive = new BundleArchive(this.location, file);
                Framework.bundles.put(this.location, this);
                resolveBundle(false);
                if (Framework.DEBUG_BUNDLES && log.isInfoEnabled()) {
                    log.info("Framework: Bundle " + toString() + " loaded. " + (System.currentTimeMillis() - currentTimeMillis) + " ms");
                    return;
                }
                return;
            } catch (Exception e) {
                throw new BundleException("Could not load bundle " + this.location, e.getCause());
            }
        }
        throw new BundleException("FileLock failed " + file2.getAbsolutePath());
    }

    private synchronized void resolveBundle(boolean z) throws BundleException {
        if (this.state != 4) {
            if (this.classloader == null) {
                this.classloader = new BundleClassLoader(this);
            }
            if (z) {
                this.classloader.resolveBundle(true, new HashSet(0));
                this.state = 4;
            } else if (this.classloader.resolveBundle(false, null)) {
                this.state = 4;
            }
            Framework.notifyBundleListeners(0, this);
        }
    }

    public long getBundleId() {
        return 0;
    }

    public Dictionary<String, String> getHeaders() {
        return this.headers;
    }

    public String getLocation() {
        return this.location;
    }

    public Archive getArchive() {
        return this.archive;
    }

    public ClassLoader getClassLoader() {
        return this.classloader;
    }

    public ServiceReference[] getRegisteredServices() {
        if (this.state == 1) {
            throw new IllegalStateException("Bundle " + toString() + "has been unregistered.");
        } else if (this.registeredServices == null) {
            return null;
        } else {
            return (ServiceReference[]) this.registeredServices.toArray(new ServiceReference[this.registeredServices.size()]);
        }
    }

    public URL getResource(String str) {
        if (this.state != 1) {
            return this.classloader.getResource(str);
        }
        throw new IllegalStateException("Bundle " + toString() + " has been uninstalled");
    }

    public ServiceReference[] getServicesInUse() {
        if (this.state == 1) {
            throw new IllegalStateException("Bundle " + toString() + "has been unregistered.");
        }
        ArrayList arrayList = new ArrayList();
        ServiceReferenceImpl[] serviceReferenceImplArr = (ServiceReferenceImpl[]) Framework.services.toArray(new ServiceReferenceImpl[Framework.services.size()]);
        int i = 0;
        while (i < serviceReferenceImplArr.length) {
            synchronized (serviceReferenceImplArr[i].useCounters) {
                if (serviceReferenceImplArr[i].useCounters.get(this) != null) {
                    arrayList.add(serviceReferenceImplArr[i]);
                }
            }
            i++;
        }
        return (ServiceReference[]) arrayList.toArray(new ServiceReference[arrayList.size()]);
    }

    public int getState() {
        return this.state;
    }

    public boolean hasPermission(Object obj) {
        if (this.state != 1) {
            return true;
        }
        throw new IllegalStateException("Bundle " + toString() + "has been unregistered.");
    }

    public synchronized void start() throws BundleException {
        this.persistently = true;
        updateMetadata();
        if (this.currentStartlevel <= Framework.startlevel) {
            startBundle();
        }
    }

    public synchronized void startBundle() throws BundleException {
        if (this.state == 1) {
            throw new IllegalStateException("Cannot start uninstalled bundle " + toString());
        } else if (this.state != 32) {
            if (this.state == 2) {
                resolveBundle(true);
            }
            this.state = 8;
            try {
                this.context.isValid = true;
                if (!(this.classloader.activatorClassName == null || StringUtils.isBlank(this.classloader.activatorClassName))) {
                    Class loadClass = this.classloader.loadClass(this.classloader.activatorClassName);
                    if (loadClass == null) {
                        throw new ClassNotFoundException(this.classloader.activatorClassName);
                    }
                    this.classloader.activator = (BundleActivator) loadClass.newInstance();
                    this.classloader.activator.start(this.context);
                }
                this.state = 32;
                Framework.notifyBundleListeners(2, this);
                if (Framework.DEBUG_BUNDLES && log.isInfoEnabled()) {
                    log.info("Framework: Bundle " + toString() + " started.");
                }
            } catch (Throwable th) {
                Throwable th2 = th;
                Framework.clearBundleTrace(this);
                this.state = 4;
                String str = "Error starting bundle " + toString();
                if (th2.getCause() != null) {
                    th2 = th2.getCause();
                }
                BundleException bundleException = new BundleException(str, th2);
            }
        }
    }

    public synchronized void stop() throws BundleException {
        this.persistently = false;
        updateMetadata();
        stopBundle();
    }

    public synchronized void stopBundle() throws BundleException {
        if (this.state == 1) {
            throw new IllegalStateException("Cannot stop uninstalled bundle " + toString());
        } else if (this.state == 32) {
            this.state = 16;
            try {
                if (this.classloader.activator != null) {
                    this.classloader.activator.stop(this.context);
                }
                if (Framework.DEBUG_BUNDLES && log.isInfoEnabled()) {
                    log.info("Framework: Bundle " + toString() + " stopped.");
                }
                this.classloader.activator = null;
                Framework.clearBundleTrace(this);
                this.state = 4;
                Framework.notifyBundleListeners(4, this);
                this.context.isValid = false;
            } catch (Throwable th) {
                this.classloader.activator = null;
                Framework.clearBundleTrace(this);
                this.state = 4;
                Framework.notifyBundleListeners(4, this);
                this.context.isValid = false;
            }
        }
    }

    public synchronized void uninstall() throws BundleException {
        if (this.state == 1) {
            throw new IllegalStateException("Bundle " + toString() + " is already uninstalled.");
        }
        if (this.state == 32) {
            try {
                stopBundle();
            } catch (Throwable th) {
                Framework.notifyFrameworkListeners(2, this, th);
            }
        }
        this.state = 1;
        File file = new File(this.bundleDir, "meta");
        if (AtlasFileLock.getInstance().LockExclusive(file)) {
            file.delete();
            AtlasFileLock.getInstance().unLock(file);
            if (this.classloader.originalExporter != null) {
                this.classloader.originalExporter.cleanup(true);
                this.classloader.originalExporter = null;
            }
            this.classloader.cleanup(true);
            this.classloader = null;
            Framework.bundles.remove(this);
            Framework.notifyBundleListeners(16, this);
            this.context.isValid = false;
            this.context.bundle = null;
        } else {
            throw new BundleException("FileLock failed " + file.getAbsolutePath());
        }
    }

    public synchronized void update() throws BundleException {
        String str = (String) this.headers.get(Constants.BUNDLE_UPDATELOCATION);
        try {
            String str2;
            if (str == null) {
                str2 = this.location;
            } else {
                str2 = str;
            }
            update(new URL(str2).openConnection().getInputStream());
        } catch (Throwable e) {
            throw new BundleException("Could not update " + toString() + " from " + str, e);
        }
    }

    public synchronized void update(InputStream inputStream) throws BundleException {
        if (this.state == 1) {
            throw new IllegalStateException("Cannot update uninstalled bundle " + toString());
        }
        try {
            this.archive.newRevision(this.location, this.bundleDir, inputStream);
        } catch (Throwable e) {
            throw new BundleException("Could not update bundle " + toString(), e);
        }
    }

    public synchronized void update(File file) throws BundleException {
        if (this.state == 1) {
            throw new IllegalStateException("Cannot update uninstalled bundle " + toString());
        }
        try {
            this.archive.newRevision(this.location, this.bundleDir, file);
        } catch (Throwable e) {
            throw new BundleException("Could not update bundle " + toString(), e);
        }
    }

    public synchronized void refresh() throws BundleException {
        if (this.state == 1) {
            throw new IllegalStateException("Cannot refresh uninstalled bundle " + toString());
        }
        Object obj;
        if (this.state == 32) {
            stopBundle();
            obj = 1;
        } else {
            obj = null;
        }
        try {
            this.archive = new BundleArchive(this.location, this.bundleDir);
            BundleClassLoader bundleClassLoader = new BundleClassLoader(this);
            String[] strArr = this.classloader.exports;
            if (strArr.length > 0) {
                int i = 0;
                Object obj2 = null;
                while (i < strArr.length) {
                    Object obj3;
                    Package packageR = (Package) Framework.exportedPackages.get(new Package(strArr[i], null, false));
                    if (packageR.importingBundles == null || packageR.classloader != this.classloader) {
                        obj3 = obj2;
                    } else {
                        packageR.removalPending = true;
                        obj3 = 1;
                    }
                    i++;
                    obj2 = obj3;
                }
                if (obj2 != null) {
                    if (this.classloader.originalExporter != null) {
                        bundleClassLoader.originalExporter = this.classloader.originalExporter;
                    } else {
                        bundleClassLoader.originalExporter = this.classloader;
                    }
                }
            }
            this.classloader.cleanup(true);
            this.classloader = bundleClassLoader;
            if (this.classloader.resolveBundle(false, null)) {
                this.state = 4;
            } else {
                this.state = 2;
            }
            Framework.notifyBundleListeners(8, this);
            if (obj != null) {
                startBundle();
            }
        } catch (BundleException e) {
            throw e;
        } catch (Throwable e2) {
            throw new BundleException("Could not refresh bundle " + toString(), e2);
        }
    }

    public synchronized void optDexFile() {
        getArchive().optDexFile();
    }

    public synchronized void purge() throws BundleException {
        try {
            getArchive().purge();
        } catch (Throwable e) {
            throw new BundleException("Could not purge bundle " + toString(), e);
        }
    }

    void updateMetadata() {
        Throwable e;
        File file = new File(this.bundleDir, "meta");
        DataOutputStream dataOutputStream = null;
        try {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            if (AtlasFileLock.getInstance().LockExclusive(file)) {
                OutputStream fileOutputStream = new FileOutputStream(file);
                DataOutputStream dataOutputStream2 = new DataOutputStream(fileOutputStream);
                try {
                    dataOutputStream2.writeUTF(this.location);
                    dataOutputStream2.writeInt(this.currentStartlevel);
                    dataOutputStream2.writeBoolean(this.persistently);
                    dataOutputStream2.flush();
                    fileOutputStream.getFD().sync();
                    AtlasFileLock.getInstance().unLock(file);
                    if (dataOutputStream2 != null) {
                        try {
                            dataOutputStream2.close();
                            return;
                        } catch (IOException e2) {
                            e2.printStackTrace();
                            return;
                        }
                    }
                    return;
                } catch (IOException e3) {
                    e = e3;
                    dataOutputStream = dataOutputStream2;
                    try {
                        log.error("Could not save meta data " + file.getAbsolutePath(), e);
                        AtlasFileLock.getInstance().unLock(file);
                        if (dataOutputStream != null) {
                            try {
                                dataOutputStream.close();
                            } catch (IOException e22) {
                                e22.printStackTrace();
                                return;
                            }
                        }
                    } catch (Throwable th) {
                        e = th;
                        AtlasFileLock.getInstance().unLock(file);
                        if (dataOutputStream != null) {
                            try {
                                dataOutputStream.close();
                            } catch (IOException e4) {
                                e4.printStackTrace();
                            }
                        }
                        throw e;
                    }
                } catch (Throwable th2) {
                    e = th2;
                    dataOutputStream = dataOutputStream2;
                    AtlasFileLock.getInstance().unLock(file);
                    if (dataOutputStream != null) {
                        dataOutputStream.close();
                    }
                    throw e;
                }
            }
            log.error("Failed to get file lock for " + file.getAbsolutePath());
            AtlasFileLock.getInstance().unLock(file);
            if (dataOutputStream != null) {
                try {
                    dataOutputStream.close();
                } catch (IOException e222) {
                    e222.printStackTrace();
                }
            }
        } catch (IOException e5) {
            e = e5;
            log.error("Could not save meta data " + file.getAbsolutePath(), e);
            AtlasFileLock.getInstance().unLock(file);
            if (dataOutputStream != null) {
                dataOutputStream.close();
            }
        }
    }

    public String toString() {
        return this.location;
    }
}