Back to project page geoar-app.
The source code is released under:
Apache License
If you think the Android project geoar-app listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/** * Copyright 2012 52North Initiative for Geospatial Open Source Software GmbH */* w ww. j a va 2 s . c o m*/ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.n52.geoar.newdata; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.n52.geoar.newdata.Annotations; import org.n52.geoar.newdata.DataSource; import org.n52.geoar.newdata.Filter; import org.n52.geoar.GeoARApplication; import org.n52.geoar.newdata.CheckList.CheckManager; import org.n52.geoar.newdata.PluginLoader.PluginInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Parcel; import dalvik.system.DexClassLoader; import dalvik.system.DexFile; public class InstalledPluginHolder extends PluginHolder { private List<DataSourceHolder> mDataSources = new ArrayList<DataSourceHolder>(); private File pluginFile; private Long version; private String identifier; private boolean loaded = false; private String description; private String name; private Context mPluginContext; private Bitmap pluginIcon; private String publisher; @CheckManager private CheckList<InstalledPluginHolder>.Checker mChecker; private DexClassLoader mPluginDexClassLoader; private boolean iconLoaded; private static final Logger LOG = LoggerFactory .getLogger(InstalledPluginHolder.class); public InstalledPluginHolder(PluginInfo pluginInfo) { this.version = pluginInfo.version; this.identifier = pluginInfo.identifier; this.description = pluginInfo.description; this.name = pluginInfo.name; this.pluginFile = pluginInfo.pluginFile; this.publisher = pluginInfo.publisher; } @Override public String getIdentifier() { return identifier; } @Override public String getName() { return name; } @Override public String getPublisher() { return publisher; } @Override public Long getVersion() { return version; } public String getDescription() { return description; }; /** * Changes to the returned list do not affect loaded data sources * * @return */ public List<DataSourceHolder> getDataSources() { if (!loaded) { try { loadPlugin(); } catch (IOException e) { e.printStackTrace(); } } return mDataSources; } public File getPluginFile() { return pluginFile; } public void setChecked(boolean state) { mChecker.setChecked(state); } public boolean isChecked() { return mChecker.isChecked(); } @SuppressLint("NewApi") private void loadPlugin() throws IOException { mDataSources.clear(); String pluginBaseFileName = getPluginFile().getName().substring(0, getPluginFile().getName().lastIndexOf(".")); // Check if the Plugin exists if (!getPluginFile().exists()) throw new FileNotFoundException("Not found: " + getPluginFile()); File tmpDir = GeoARApplication.applicationContext.getDir( pluginBaseFileName, 0); Enumeration<String> entries = DexFile .loadDex( getPluginFile().getAbsolutePath(), tmpDir.getAbsolutePath() + "/" + pluginBaseFileName + ".dex", 0).entries(); // Path for optimized dex equals path which will be used by // dexClassLoader // create separate ClassLoader for each plugin mPluginDexClassLoader = new DexClassLoader(getPluginFile() .getAbsolutePath(), tmpDir.getAbsolutePath(), null, GeoARApplication.applicationContext.getClassLoader()); try { while (entries.hasMoreElements()) { // Check each classname for annotations String entry = entries.nextElement(); Class<?> entryClass = mPluginDexClassLoader.loadClass(entry); if (entryClass .isAnnotationPresent(Annotations.DataSource.class)) { // Class is a annotated as datasource if (org.n52.geoar.newdata.DataSource.class .isAssignableFrom(entryClass)) { // Class is a datasource @SuppressWarnings("unchecked") DataSourceHolder dataSourceHolder = new DataSourceHolder( (Class<? extends DataSource<? super Filter>>) entryClass, this); mDataSources.add(dataSourceHolder); } else { LOG.error("Datasource " + entryClass.getSimpleName() + " is not implementing DataSource interface"); // TODO handle error, somehow propagate back to user } } } } catch (ClassNotFoundException e) { throw new RuntimeException("Dex changed"); } catch (LinkageError e) { LOG.error("Data source " + getName() + " uses invalid class, " + e.getMessage()); } loaded = true; } /** * Returns a {@link Context} wrapping the * {@link GeoARApplication#applicationContext}, but returning the value of * {@link InstalledPluginHolder#getPluginResources()} as * {@link Context#getResources()} return value. * * @return */ public Context getPluginContext() { if (mPluginContext == null) { mPluginContext = new PluginContext( GeoARApplication.applicationContext, this); } return mPluginContext; } public ClassLoader getPluginClassLoader() { return mPluginDexClassLoader; } @Override public Bitmap getPluginIcon() { if (!iconLoaded) { try { iconLoaded = true; ZipFile zipFile = new ZipFile(pluginFile); ZipEntry pluginIconEntry = zipFile.getEntry("icon.png"); if (pluginIconEntry != null) { pluginIcon = BitmapFactory.decodeStream(zipFile .getInputStream(pluginIconEntry)); } else { LOG.info("Plugin " + getName() + " has no icon"); } } catch (IOException e) { LOG.error("Plugin " + getName() + " has an invalid icon"); } } return pluginIcon; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(getClass().getName()); super.writeToParcel(dest, flags); } public void saveState(ObjectOutputStream objectOutputStream) throws IOException { objectOutputStream.writeBoolean(isChecked()); for (DataSourceHolder dataSource : mDataSources) { dataSource.saveState(objectOutputStream); } } public void restoreState(PluginStateInputStream objectInputStream) throws IOException { setChecked(objectInputStream.readBoolean()); for (DataSourceHolder dataSource : mDataSources) { dataSource.restoreState(objectInputStream); } } /** * Should be called after all state initialization took place, e.g. after * {@link InstalledPluginHolder#restoreState(PluginStateInputStream)} */ public void postConstruct() { for (DataSourceHolder dataSource : mDataSources) { dataSource.postConstruct(); } } }